@@ -490,3 +490,49 @@ func DetectSnapshotFormat(path string) SnapshotFormat {
490490
491491 return FormatCustom
492492}
493+
494+ func computeSchemaHash (schemaPath string ) (string , error ) {
495+ format := DetectSnapshotFormat (schemaPath )
496+ return computeFileHash (schemaPath , format )
497+ }
498+
499+ func ValidateSchemaHash (root string ) error {
500+ snapshotsDir := GetSnapshotsDir (root )
501+
502+ metadata , err := ReadSnapshotMetadata (snapshotsDir )
503+ if err != nil {
504+ fmt .Fprintf (os .Stderr , "Warning: no snapshot metadata found. Consider using 'regresql snapshot build' for reproducible tests.\n " )
505+ return nil
506+ }
507+
508+ if metadata .Current == nil || metadata .Current .SchemaPath == "" {
509+ return nil
510+ }
511+
512+ // Check if schema file still exists
513+ if _ , err := os .Stat (metadata .Current .SchemaPath ); os .IsNotExist (err ) {
514+ // Schema file referenced in metadata doesn't exist - stale metadata
515+ return nil
516+ }
517+
518+ currentHash , err := computeSchemaHash (metadata .Current .SchemaPath )
519+ if err != nil {
520+ return fmt .Errorf ("failed to hash schema %s: %w" , metadata .Current .SchemaPath , err )
521+ }
522+
523+ if currentHash != metadata .Current .SchemaHash {
524+ return fmt .Errorf (`schema has changed since last snapshot build
525+
526+ Schema file: %s
527+ Expected: %s
528+ Current: %s
529+
530+ Run 'regresql snapshot build --schema=%s' to rebuild the snapshot` ,
531+ metadata .Current .SchemaPath ,
532+ metadata .Current .SchemaHash [:20 ]+ "..." ,
533+ currentHash [:20 ]+ "..." ,
534+ metadata .Current .SchemaPath )
535+ }
536+
537+ return nil
538+ }
0 commit comments