11import type {
22 SchemaSnapshot , TableDescriptor , ColumnDescriptor , IndexDescriptor , FkDescriptor ,
33 ViewDescriptor ,
4- Change , ChangeStatus , DiffResult , AllowOptions , AmbiguousCallback ,
4+ Change , ChangeStatus , DiffResult , AllowOptions , AmbiguousCallback , Dialect ,
55} from "../types.js" ;
66import type { SqlType } from "../sql-type.js" ;
77import { sqlTypeEquals } from "../sql-type.js" ;
88import { applyStatus } from "./status.js" ;
99import { detectColumnRenames , detectTableRenames } from "./rename-heuristic.js" ;
1010import { viewSqlEquals } from "../view-sql-compare.js" ;
11+ import { checkExprEquals } from "../check-expr-compare.js" ;
1112import { DEFAULT_DB_SCHEMA_POSTGRES } from "@metaobjectsdev/metadata" ;
1213
1314export interface DiffArgs {
@@ -26,6 +27,8 @@ export interface DiffArgs {
2627 * the default. Pass additional patterns to extend.
2728 */
2829 ignoreTables ?: string [ ] ;
30+ /** Dialect; CHECK-constraint evolution on existing tables is emitted for postgres only. */
31+ dialect ?: Dialect ;
2932}
3033
3134const ALLOWED : ChangeStatus = { state : "allowed" } ;
@@ -156,10 +159,10 @@ export async function diff(
156159 diffTableColumns ( expectedTable , actualTable , changes ) ;
157160 diffTableIndexes ( expectedTable , actualTable , changes ) ;
158161 diffTableForeignKeys ( expectedTable , actualTable , changes ) ;
159- // CHECK constraints on existing tables are intentionally NOT diffed:
160- // checks are a create-time-only concern (inlined in CREATE TABLE). Evolving
161- // an enum's values on a live table (which would alter its CHECK) is deferred
162- // until check introspection lands. No add-check / drop-check is produced here.
162+ // CHECK constraints on existing tables are evolved for postgres only (SQLite
163+ // evolves checks via table recreate, not ALTER). Gated on `actual.checks`
164+ // being populated — by the snapshot offline, or pg_constraint introspection.
165+ if ( args . dialect === "postgres" ) diffTableChecks ( expectedTable , actualTable , changes ) ;
163166 }
164167
165168 // Pass 2b: views. Identity is (schema, name). A name present on both sides
@@ -293,6 +296,26 @@ function diffTableForeignKeys(
293296 }
294297}
295298
299+ function diffTableChecks ( expected : TableDescriptor , actual : TableDescriptor , changes : Change [ ] ) : void {
300+ const sx = schemaSpread ( expected . schema ) ;
301+ const expectedChk = new Map ( expected . checks . map ( ( c ) => [ c . name , c ] ) ) ;
302+ const actualChk = new Map ( actual . checks . map ( ( c ) => [ c . name , c ] ) ) ;
303+ for ( const [ name , ec ] of expectedChk ) {
304+ const ac = actualChk . get ( name ) ;
305+ if ( ! ac ) {
306+ changes . push ( { kind : "add-check" , table : expected . name , ...sx , check : ec , status : ALLOWED } ) ;
307+ } else if ( ! checkExprEquals ( ec . expression , ac . expression ) ) {
308+ changes . push ( { kind : "drop-check" , table : expected . name , ...sx , check : name , restore : ac , status : ALLOWED } ) ;
309+ changes . push ( { kind : "add-check" , table : expected . name , ...sx , check : ec , status : ALLOWED } ) ;
310+ }
311+ }
312+ for ( const [ name , ac ] of actualChk ) {
313+ if ( ! expectedChk . has ( name ) ) {
314+ changes . push ( { kind : "drop-check" , table : expected . name , ...sx , check : name , restore : ac , status : ALLOWED } ) ;
315+ }
316+ }
317+ }
318+
296319function viewIdentity ( v : { name : string ; schema ?: string } ) : string {
297320 return ( v . schema ?? DEFAULT_DB_SCHEMA_POSTGRES ) + "." + v . name ;
298321}
0 commit comments