@smartive/graphql-magic 23.7.0-next.4 → 23.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -198,7 +198,6 @@ __export(index_exports, {
198
198
  updateEntity: () => updateEntity,
199
199
  updateFunctions: () => updateFunctions,
200
200
  validateCheckConstraint: () => validateCheckConstraint,
201
- validateExcludeConstraint: () => validateExcludeConstraint,
202
201
  value: () => value
203
202
  });
204
203
  module.exports = __toCommonJS(index_exports);
@@ -655,8 +654,6 @@ var EntityModel = class extends Model {
655
654
  for (const constraint of this.constraints) {
656
655
  if (constraint.kind === "check") {
657
656
  validateCheckConstraint(this, constraint);
658
- } else if (constraint.kind === "exclude") {
659
- validateExcludeConstraint(this, constraint);
660
657
  }
661
658
  }
662
659
  }
@@ -955,19 +952,6 @@ var validateCheckConstraint = (model, constraint) => {
955
952
  }
956
953
  }
957
954
  };
958
- var validateExcludeConstraint = (model, constraint) => {
959
- const validColumnNames = new Set(model.fields.map((f) => getColumnName(f)));
960
- for (const el of constraint.elements) {
961
- if ("column" in el) {
962
- if (!validColumnNames.has(el.column)) {
963
- const validList = [...validColumnNames].sort().join(", ");
964
- throw new Error(
965
- `Exclude constraint "${constraint.name}" references column "${el.column}" which does not exist on model ${model.name}. Valid columns: ${validList}`
966
- );
967
- }
968
- }
969
- }
970
- };
971
955
 
972
956
  // src/client/queries.ts
973
957
  var fieldIsSearchable = (model, fieldName) => {
@@ -1182,7 +1166,6 @@ var generateFunctionsFromDatabase = async (knex) => {
1182
1166
  JOIN pg_namespace n ON p.pronamespace = n.oid
1183
1167
  WHERE n.nspname = 'public'
1184
1168
  AND NOT EXISTS (SELECT 1 FROM pg_aggregate a WHERE a.aggfnoid = p.oid)
1185
- AND NOT EXISTS (SELECT 1 FROM pg_depend d WHERE d.objid = p.oid AND d.deptype = 'e')
1186
1169
  ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
1187
1170
  `);
1188
1171
  const aggregateFunctions = await knex.raw(`
@@ -1197,7 +1180,6 @@ var generateFunctionsFromDatabase = async (knex) => {
1197
1180
  JOIN pg_aggregate a ON p.oid = a.aggfnoid
1198
1181
  JOIN pg_namespace n ON p.pronamespace = n.oid
1199
1182
  WHERE n.nspname = 'public'
1200
- AND NOT EXISTS (SELECT 1 FROM pg_depend d WHERE d.objid = p.oid AND d.deptype = 'e')
1201
1183
  ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
1202
1184
  `);
1203
1185
  const functions = [];
@@ -2942,7 +2924,6 @@ var getDatabaseFunctions = async (knex) => {
2942
2924
  JOIN pg_namespace n ON p.pronamespace = n.oid
2943
2925
  WHERE n.nspname = 'public'
2944
2926
  AND NOT EXISTS (SELECT 1 FROM pg_aggregate a WHERE a.aggfnoid = p.oid)
2945
- AND NOT EXISTS (SELECT 1 FROM pg_depend d WHERE d.objid = p.oid AND d.deptype = 'e')
2946
2927
  ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
2947
2928
  `);
2948
2929
  const aggregateFunctions = await knex.raw(`
@@ -2958,7 +2939,6 @@ var getDatabaseFunctions = async (knex) => {
2958
2939
  JOIN pg_aggregate a ON p.oid = a.aggfnoid
2959
2940
  JOIN pg_namespace n ON p.pronamespace = n.oid
2960
2941
  WHERE n.nspname = 'public'
2961
- AND NOT EXISTS (SELECT 1 FROM pg_depend d WHERE d.objid = p.oid AND d.deptype = 'e')
2962
2942
  ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
2963
2943
  `);
2964
2944
  const result = [];
@@ -3102,7 +3082,7 @@ Summary: ${updatedCount} updated, ${skippedCount} skipped`);
3102
3082
  };
3103
3083
 
3104
3084
  // src/migrations/generate.ts
3105
- var MigrationGenerator = class _MigrationGenerator {
3085
+ var MigrationGenerator = class {
3106
3086
  constructor(knex, models, parsedFunctions) {
3107
3087
  this.models = models;
3108
3088
  this.parsedFunctions = parsedFunctions;
@@ -3118,10 +3098,6 @@ var MigrationGenerator = class _MigrationGenerator {
3118
3098
  columns = {};
3119
3099
  /** table name -> constraint name -> check clause expression */
3120
3100
  existingCheckConstraints = {};
3121
- /** table name -> constraint name -> exclude definition (normalized) */
3122
- existingExcludeConstraints = {};
3123
- /** table name -> constraint name -> trigger definition (normalized) */
3124
- existingConstraintTriggers = {};
3125
3101
  uuidUsed;
3126
3102
  nowUsed;
3127
3103
  needsMigration = false;
@@ -3149,50 +3125,8 @@ var MigrationGenerator = class _MigrationGenerator {
3149
3125
  }
3150
3126
  this.existingCheckConstraints[tableName].set(row.constraint_name, row.check_clause);
3151
3127
  }
3152
- const excludeResult = await schema.knex.raw(
3153
- `SELECT c.conrelid::regclass::text as table_name, c.conname as constraint_name, pg_get_constraintdef(c.oid) as constraint_def
3154
- FROM pg_constraint c
3155
- JOIN pg_namespace n ON c.connamespace = n.oid
3156
- WHERE n.nspname = 'public' AND c.contype = 'x'`
3157
- );
3158
- const excludeRows = "rows" in excludeResult && Array.isArray(excludeResult.rows) ? excludeResult.rows : [];
3159
- for (const row of excludeRows) {
3160
- const tableName = row.table_name.split(".").pop()?.replace(/^"|"$/g, "") ?? row.table_name;
3161
- if (!this.existingExcludeConstraints[tableName]) {
3162
- this.existingExcludeConstraints[tableName] = /* @__PURE__ */ new Map();
3163
- }
3164
- this.existingExcludeConstraints[tableName].set(row.constraint_name, this.normalizeExcludeDef(row.constraint_def));
3165
- }
3166
- const triggerResult = await schema.knex.raw(
3167
- `SELECT c.conrelid::regclass::text as table_name, c.conname as constraint_name, pg_get_triggerdef(t.oid) as trigger_def
3168
- FROM pg_constraint c
3169
- JOIN pg_trigger t ON t.tgconstraint = c.oid
3170
- JOIN pg_namespace n ON c.connamespace = n.oid
3171
- WHERE n.nspname = 'public' AND c.contype = 't'`
3172
- );
3173
- const triggerRows = "rows" in triggerResult && Array.isArray(triggerResult.rows) ? triggerResult.rows : [];
3174
- for (const row of triggerRows) {
3175
- const tableName = row.table_name.split(".").pop()?.replace(/^"|"$/g, "") ?? row.table_name;
3176
- if (!this.existingConstraintTriggers[tableName]) {
3177
- this.existingConstraintTriggers[tableName] = /* @__PURE__ */ new Map();
3178
- }
3179
- this.existingConstraintTriggers[tableName].set(row.constraint_name, this.normalizeTriggerDef(row.trigger_def));
3180
- }
3181
3128
  const up = [];
3182
3129
  const down = [];
3183
- const wantsBtreeGist = models.entities.some(
3184
- (model) => model.constraints?.some((c) => c.kind === "exclude" && c.elements.some((el) => "column" in el && el.operator === "="))
3185
- );
3186
- if (wantsBtreeGist) {
3187
- const extResult = await schema.knex("pg_extension").where("extname", "btree_gist").select("oid").first();
3188
- const btreeGistInstalled = !!extResult;
3189
- if (!btreeGistInstalled) {
3190
- up.unshift(() => {
3191
- this.writer.writeLine(`await knex.raw('CREATE EXTENSION IF NOT EXISTS btree_gist');`);
3192
- this.writer.blankLine();
3193
- });
3194
- }
3195
- }
3196
3130
  this.createEnums(
3197
3131
  this.models.enums.filter((enm2) => !enums.includes((0, import_lowerFirst.default)(enm2.name))),
3198
3132
  up,
@@ -3271,22 +3205,10 @@ var MigrationGenerator = class _MigrationGenerator {
3271
3205
  if (entry.kind === "check") {
3272
3206
  validateCheckConstraint(model, entry);
3273
3207
  const table = model.name;
3274
- const constraintName = this.getConstraintName(model, entry, i);
3275
- up.push(() => {
3276
- this.addCheckConstraint(table, constraintName, entry.expression, entry.deferrable);
3277
- });
3278
- } else if (entry.kind === "exclude") {
3279
- validateExcludeConstraint(model, entry);
3280
- const table = model.name;
3281
- const constraintName = this.getConstraintName(model, entry, i);
3208
+ const constraintName = this.getCheckConstraintName(model, entry, i);
3209
+ const expression = entry.expression;
3282
3210
  up.push(() => {
3283
- this.addExcludeConstraint(table, constraintName, entry);
3284
- });
3285
- } else if (entry.kind === "constraint_trigger") {
3286
- const table = model.name;
3287
- const constraintName = this.getConstraintName(model, entry, i);
3288
- up.push(() => {
3289
- this.addConstraintTrigger(table, constraintName, entry);
3211
+ this.addCheckConstraint(table, constraintName, expression);
3290
3212
  });
3291
3213
  }
3292
3214
  }
@@ -3326,81 +3248,36 @@ var MigrationGenerator = class _MigrationGenerator {
3326
3248
  );
3327
3249
  this.updateFields(model, existingFields, up, down);
3328
3250
  if (model.constraints?.length) {
3329
- const existingCheckMap = this.existingCheckConstraints[model.name];
3330
- const existingExcludeMap = this.existingExcludeConstraints[model.name];
3331
- const existingTriggerMap = this.existingConstraintTriggers[model.name];
3332
3251
  for (let i = 0; i < model.constraints.length; i++) {
3333
3252
  const entry = model.constraints[i];
3253
+ if (entry.kind !== "check") {
3254
+ continue;
3255
+ }
3256
+ validateCheckConstraint(model, entry);
3334
3257
  const table = model.name;
3335
- const constraintName = this.getConstraintName(model, entry, i);
3336
- if (entry.kind === "check") {
3337
- validateCheckConstraint(model, entry);
3338
- const newExpression = entry.expression;
3339
- const existingExpression = existingCheckMap?.get(constraintName);
3340
- if (existingExpression === void 0) {
3341
- up.push(() => {
3342
- this.addCheckConstraint(table, constraintName, newExpression, entry.deferrable);
3343
- });
3344
- down.push(() => {
3345
- this.dropCheckConstraint(table, constraintName);
3346
- });
3347
- } else if (this.normalizeCheckExpression(existingExpression) !== this.normalizeCheckExpression(newExpression)) {
3348
- up.push(() => {
3349
- this.dropCheckConstraint(table, constraintName);
3350
- this.addCheckConstraint(table, constraintName, newExpression, entry.deferrable);
3351
- });
3352
- down.push(() => {
3353
- this.dropCheckConstraint(table, constraintName);
3354
- this.addCheckConstraint(table, constraintName, existingExpression);
3355
- });
3356
- }
3357
- } else if (entry.kind === "exclude") {
3358
- validateExcludeConstraint(model, entry);
3359
- const newDef = this.normalizeExcludeDef(this.buildExcludeDef(entry));
3360
- const existingDef = existingExcludeMap?.get(constraintName);
3361
- if (existingDef === void 0) {
3362
- up.push(() => {
3363
- this.addExcludeConstraint(table, constraintName, entry);
3364
- });
3365
- down.push(() => {
3366
- this.dropExcludeConstraint(table, constraintName);
3367
- });
3368
- } else if (existingDef !== newDef) {
3369
- up.push(() => {
3370
- this.dropExcludeConstraint(table, constraintName);
3371
- this.addExcludeConstraint(table, constraintName, entry);
3372
- });
3373
- down.push(() => {
3374
- this.dropExcludeConstraint(table, constraintName);
3375
- const escaped = this.escapeExpressionForRaw(existingDef);
3376
- this.writer.writeLine(
3377
- `await knex.raw(\`ALTER TABLE "${table}" ADD CONSTRAINT "${constraintName}" ${escaped}\`);`
3378
- );
3379
- this.writer.blankLine();
3380
- });
3381
- }
3382
- } else if (entry.kind === "constraint_trigger") {
3383
- const newDef = this.normalizeTriggerDef(this.buildConstraintTriggerDef(table, constraintName, entry));
3384
- const existingDef = existingTriggerMap?.get(constraintName);
3385
- if (existingDef === void 0) {
3386
- up.push(() => {
3387
- this.addConstraintTrigger(table, constraintName, entry);
3388
- });
3389
- down.push(() => {
3390
- this.dropConstraintTrigger(table, constraintName);
3391
- });
3392
- } else if (existingDef !== newDef) {
3393
- up.push(() => {
3394
- this.dropConstraintTrigger(table, constraintName);
3395
- this.addConstraintTrigger(table, constraintName, entry);
3396
- });
3397
- down.push(() => {
3398
- this.dropConstraintTrigger(table, constraintName);
3399
- const escaped = existingDef.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$");
3400
- this.writer.writeLine(`await knex.raw(\`${escaped}\`);`);
3401
- this.writer.blankLine();
3402
- });
3403
- }
3258
+ const constraintName = this.getCheckConstraintName(model, entry, i);
3259
+ const existingConstraint = this.findExistingConstraint(table, entry, constraintName);
3260
+ if (!existingConstraint) {
3261
+ up.push(() => {
3262
+ this.addCheckConstraint(table, constraintName, entry.expression);
3263
+ });
3264
+ down.push(() => {
3265
+ this.dropCheckConstraint(table, constraintName);
3266
+ });
3267
+ } else if (!await this.equalExpressions(
3268
+ table,
3269
+ existingConstraint.constraintName,
3270
+ existingConstraint.expression,
3271
+ entry.expression
3272
+ )) {
3273
+ up.push(() => {
3274
+ this.dropCheckConstraint(table, existingConstraint.constraintName);
3275
+ this.addCheckConstraint(table, constraintName, entry.expression);
3276
+ });
3277
+ down.push(() => {
3278
+ this.dropCheckConstraint(table, constraintName);
3279
+ this.addCheckConstraint(table, existingConstraint.constraintName, existingConstraint.expression);
3280
+ });
3404
3281
  }
3405
3282
  }
3406
3283
  }
@@ -3775,90 +3652,148 @@ var MigrationGenerator = class _MigrationGenerator {
3775
3652
  renameColumn(from, to) {
3776
3653
  this.writer.writeLine(`table.renameColumn('${from}', '${to}');`);
3777
3654
  }
3778
- getConstraintName(model, entry, index) {
3655
+ getCheckConstraintName(model, entry, index) {
3779
3656
  return `${model.name}_${entry.name}_${entry.kind}_${index}`;
3780
3657
  }
3781
- static SQL_KEYWORDS = /* @__PURE__ */ new Set([
3782
- "and",
3783
- "or",
3784
- "not",
3785
- "in",
3786
- "is",
3787
- "null",
3788
- "true",
3789
- "false",
3790
- "between",
3791
- "like",
3792
- "exists",
3793
- "all",
3794
- "any",
3795
- "asc",
3796
- "desc",
3797
- "with",
3798
- "using",
3799
- "as",
3800
- "on",
3801
- "infinity",
3802
- "extract",
3803
- "current_date",
3804
- "current_timestamp"
3805
- ]);
3806
- normalizeSqlIdentifiers(s) {
3807
- const literals = [];
3808
- let result = s.replace(/'([^']|'')*'/g, (lit) => {
3809
- literals.push(lit);
3810
- return `\0L${literals.length - 1}\0`;
3811
- });
3812
- result = result.replace(/"([^"]*)"/g, (_, ident) => `"${ident.toLowerCase()}"`);
3813
- result = result.replace(
3814
- /\b([a-zA-Z_][a-zA-Z0-9_]*)\b(?!\s*\()/g,
3815
- (match) => _MigrationGenerator.SQL_KEYWORDS.has(match.toLowerCase()) ? match : `"${match.toLowerCase()}"`
3816
- );
3817
- for (let i = 0; i < literals.length; i++) {
3818
- result = result.replace(new RegExp(`\0L${i}\0`, "g"), literals[i]);
3658
+ normalizeCheckExpression(expr) {
3659
+ let normalized = expr.replace(/\s+/g, " ").trim();
3660
+ while (this.isWrappedByOuterParentheses(normalized)) {
3661
+ normalized = normalized.slice(1, -1).trim();
3819
3662
  }
3820
- return result;
3663
+ return normalized;
3821
3664
  }
3822
- normalizeCheckExpression(expr) {
3823
- let s = expr.replace(/\s+/g, " ").trim();
3824
- while (s.length >= 2 && s.startsWith("(") && s.endsWith(")")) {
3825
- let depth = 0;
3826
- let match = true;
3827
- for (let i = 0; i < s.length; i++) {
3828
- if (s[i] === "(") {
3829
- depth++;
3830
- } else if (s[i] === ")") {
3831
- depth--;
3665
+ isWrappedByOuterParentheses(expr) {
3666
+ if (!expr.startsWith("(") || !expr.endsWith(")")) {
3667
+ return false;
3668
+ }
3669
+ let depth = 0;
3670
+ let inSingleQuote = false;
3671
+ for (let i = 0; i < expr.length; i++) {
3672
+ const char = expr[i];
3673
+ const next = expr[i + 1];
3674
+ if (char === "'") {
3675
+ if (inSingleQuote && next === "'") {
3676
+ i++;
3677
+ continue;
3832
3678
  }
3833
- if (depth === 0 && i < s.length - 1) {
3834
- match = false;
3835
- break;
3679
+ inSingleQuote = !inSingleQuote;
3680
+ continue;
3681
+ }
3682
+ if (inSingleQuote) {
3683
+ continue;
3684
+ }
3685
+ if (char === "(") {
3686
+ depth++;
3687
+ } else if (char === ")") {
3688
+ depth--;
3689
+ if (depth === 0 && i !== expr.length - 1) {
3690
+ return false;
3691
+ }
3692
+ if (depth < 0) {
3693
+ return false;
3836
3694
  }
3837
3695
  }
3838
- if (!match || depth !== 0) {
3839
- break;
3696
+ }
3697
+ return depth === 0;
3698
+ }
3699
+ findExistingConstraint(table, entry, preferredConstraintName) {
3700
+ const existingMap = this.existingCheckConstraints[table];
3701
+ if (!existingMap) {
3702
+ return null;
3703
+ }
3704
+ const preferredExpression = existingMap.get(preferredConstraintName);
3705
+ if (preferredExpression !== void 0) {
3706
+ return {
3707
+ constraintName: preferredConstraintName,
3708
+ expression: preferredExpression
3709
+ };
3710
+ }
3711
+ const normalizedNewExpression = this.normalizeCheckExpression(entry.expression);
3712
+ const constraintPrefix = `${table}_${entry.name}_${entry.kind}_`;
3713
+ for (const [constraintName, expression] of existingMap.entries()) {
3714
+ if (!constraintName.startsWith(constraintPrefix)) {
3715
+ continue;
3716
+ }
3717
+ if (this.normalizeCheckExpression(expression) !== normalizedNewExpression) {
3718
+ continue;
3840
3719
  }
3841
- s = s.slice(1, -1).trim();
3720
+ return { constraintName, expression };
3842
3721
  }
3843
- s = s.replace(/\s*\(\s*/g, "(").replace(/\s*\)\s*/g, ")").replace(/\s+AND\s+/gi, " AND ").replace(/\s+OR\s+/gi, " OR ").trim();
3844
- return this.normalizeSqlIdentifiers(s);
3722
+ return null;
3845
3723
  }
3846
- normalizeExcludeDef(def) {
3847
- const s = def.replace(/\s+/g, " ").replace(/\s*\(\s*/g, "(").replace(/\s*\)\s*/g, ")").trim();
3848
- return this.normalizeSqlIdentifiers(s);
3724
+ async equalExpressions(table, constraintName, existingExpression, newExpression) {
3725
+ try {
3726
+ const [canonicalExisting, canonicalNew] = await Promise.all([
3727
+ this.canonicalizeCheckExpressionWithPostgres(table, existingExpression),
3728
+ this.canonicalizeCheckExpressionWithPostgres(table, newExpression)
3729
+ ]);
3730
+ return canonicalExisting === canonicalNew;
3731
+ } catch (error) {
3732
+ console.warn(
3733
+ `Failed to canonicalize check constraint "${constraintName}" on table "${table}". Treating it as changed.`,
3734
+ error
3735
+ );
3736
+ return false;
3737
+ }
3738
+ }
3739
+ async canonicalizeCheckExpressionWithPostgres(table, expression) {
3740
+ const sourceTableIdentifier = table.split(".").map((part) => this.quoteIdentifier(part)).join(".");
3741
+ const uniqueSuffix = `${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
3742
+ const tableSlug = table.toLowerCase().replace(/[^a-z0-9_]/g, "_");
3743
+ const tempTableName = `gqm_tmp_check_${tableSlug}_${uniqueSuffix}`;
3744
+ const tempTableIdentifier = this.quoteIdentifier(tempTableName);
3745
+ const constraintName = `gqm_tmp_check_${uniqueSuffix}`;
3746
+ const constraintIdentifier = this.quoteIdentifier(constraintName);
3747
+ const trx = await this.knex.transaction();
3748
+ try {
3749
+ await trx.raw(`CREATE TEMP TABLE ${tempTableIdentifier} (LIKE ${sourceTableIdentifier}) ON COMMIT DROP`);
3750
+ await trx.raw(`ALTER TABLE ${tempTableIdentifier} ADD CONSTRAINT ${constraintIdentifier} CHECK (${expression})`);
3751
+ const result = await trx.raw(
3752
+ `SELECT pg_get_constraintdef(c.oid, true) AS constraint_definition
3753
+ FROM pg_constraint c
3754
+ JOIN pg_class t
3755
+ ON t.oid = c.conrelid
3756
+ WHERE t.relname = ?
3757
+ AND c.conname = ?
3758
+ ORDER BY c.oid DESC
3759
+ LIMIT 1`,
3760
+ [tempTableName, constraintName]
3761
+ );
3762
+ const rows = "rows" in result && Array.isArray(result.rows) ? result.rows : [];
3763
+ const definition = rows[0]?.constraint_definition;
3764
+ if (!definition) {
3765
+ throw new Error(`Could not read canonical check definition for expression: ${expression}`);
3766
+ }
3767
+ return this.normalizeCheckExpression(this.extractCheckExpressionFromDefinition(definition));
3768
+ } finally {
3769
+ try {
3770
+ await trx.rollback();
3771
+ } catch {
3772
+ }
3773
+ }
3774
+ }
3775
+ extractCheckExpressionFromDefinition(definition) {
3776
+ const trimmed = definition.trim();
3777
+ const match = trimmed.match(/^CHECK\s*\(([\s\S]*)\)$/i);
3778
+ if (!match) {
3779
+ return trimmed;
3780
+ }
3781
+ return match[1];
3782
+ }
3783
+ quoteIdentifier(identifier) {
3784
+ return `"${identifier.replace(/"/g, '""')}"`;
3849
3785
  }
3850
- normalizeTriggerDef(def) {
3851
- return def.replace(/\s+/g, " ").replace(/\s*\(\s*/g, "(").replace(/\s*\)\s*/g, ")").trim();
3786
+ quoteQualifiedIdentifier(identifier) {
3787
+ return identifier.split(".").map((part) => this.quoteIdentifier(part)).join(".");
3852
3788
  }
3853
3789
  /** Escape expression for embedding inside a template literal in generated code */
3854
3790
  escapeExpressionForRaw(expr) {
3855
3791
  return expr.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$");
3856
3792
  }
3857
- addCheckConstraint(table, constraintName, expression, deferrable) {
3793
+ addCheckConstraint(table, constraintName, expression) {
3858
3794
  const escaped = this.escapeExpressionForRaw(expression);
3859
- const deferrableClause = deferrable ? ` DEFERRABLE ${deferrable}` : "";
3860
3795
  this.writer.writeLine(
3861
- `await knex.raw(\`ALTER TABLE "${table}" ADD CONSTRAINT "${constraintName}" CHECK (${escaped})${deferrableClause}\`);`
3796
+ `await knex.raw(\`ALTER TABLE "${table}" ADD CONSTRAINT "${constraintName}" CHECK (${escaped})\`);`
3862
3797
  );
3863
3798
  this.writer.blankLine();
3864
3799
  }
@@ -3866,43 +3801,6 @@ var MigrationGenerator = class _MigrationGenerator {
3866
3801
  this.writer.writeLine(`await knex.raw('ALTER TABLE "${table}" DROP CONSTRAINT "${constraintName}"');`);
3867
3802
  this.writer.blankLine();
3868
3803
  }
3869
- buildExcludeDef(entry) {
3870
- const elementsStr = entry.elements.map((el) => "column" in el ? `"${el.column}" WITH ${el.operator}` : `${el.expression} WITH ${el.operator}`).join(", ");
3871
- const whereClause = entry.where ? ` WHERE (${entry.where})` : "";
3872
- const deferrableClause = entry.deferrable ? ` DEFERRABLE ${entry.deferrable}` : "";
3873
- return `EXCLUDE USING ${entry.using} (${elementsStr})${whereClause}${deferrableClause}`;
3874
- }
3875
- addExcludeConstraint(table, constraintName, entry) {
3876
- const def = this.buildExcludeDef(entry);
3877
- const escaped = this.escapeExpressionForRaw(def);
3878
- this.writer.writeLine(`await knex.raw(\`ALTER TABLE "${table}" ADD CONSTRAINT "${constraintName}" ${escaped}\`);`);
3879
- this.writer.blankLine();
3880
- }
3881
- dropExcludeConstraint(table, constraintName) {
3882
- this.writer.writeLine(`await knex.raw('ALTER TABLE "${table}" DROP CONSTRAINT "${constraintName}"');`);
3883
- this.writer.blankLine();
3884
- }
3885
- buildConstraintTriggerDef(table, constraintName, entry) {
3886
- const eventsStr = entry.events.join(" OR ");
3887
- const deferrableClause = entry.deferrable ? ` DEFERRABLE ${entry.deferrable}` : "";
3888
- const argsStr = entry.function.args?.length ? entry.function.args.map((a) => `"${a}"`).join(", ") : "";
3889
- const executeClause = argsStr ? `EXECUTE FUNCTION ${entry.function.name}(${argsStr})` : `EXECUTE FUNCTION ${entry.function.name}()`;
3890
- return `CREATE CONSTRAINT TRIGGER "${constraintName}" ${entry.when} ${eventsStr} ON "${table}"${deferrableClause} FOR EACH ${entry.forEach} ${executeClause}`;
3891
- }
3892
- addConstraintTrigger(table, constraintName, entry) {
3893
- const eventsStr = entry.events.join(" OR ");
3894
- const deferrableClause = entry.deferrable ? ` DEFERRABLE ${entry.deferrable}` : "";
3895
- const argsStr = entry.function.args?.length ? entry.function.args.map((a) => `"${a}"`).join(", ") : "";
3896
- const executeClause = argsStr ? `EXECUTE FUNCTION ${entry.function.name}(${argsStr})` : `EXECUTE FUNCTION ${entry.function.name}()`;
3897
- this.writer.writeLine(
3898
- `await knex.raw(\`CREATE CONSTRAINT TRIGGER "${constraintName}" ${entry.when} ${eventsStr} ON "${table}"${deferrableClause} FOR EACH ${entry.forEach} ${executeClause}\`);`
3899
- );
3900
- this.writer.blankLine();
3901
- }
3902
- dropConstraintTrigger(table, constraintName) {
3903
- this.writer.writeLine(`await knex.raw('ALTER TABLE "${table}" DROP CONSTRAINT "${constraintName}"');`);
3904
- this.writer.blankLine();
3905
- }
3906
3804
  value(value2) {
3907
3805
  if (typeof value2 === "string") {
3908
3806
  return `'${value2}'`;
@@ -4929,6 +4827,5 @@ var printSchemaFromModels = (models) => printSchema((0, import_graphql6.buildAST
4929
4827
  updateEntity,
4930
4828
  updateFunctions,
4931
4829
  validateCheckConstraint,
4932
- validateExcludeConstraint,
4933
4830
  value
4934
4831
  });
@@ -6,7 +6,6 @@ export const generateFunctionsFromDatabase = async (knex) => {
6
6
  JOIN pg_namespace n ON p.pronamespace = n.oid
7
7
  WHERE n.nspname = 'public'
8
8
  AND NOT EXISTS (SELECT 1 FROM pg_aggregate a WHERE a.aggfnoid = p.oid)
9
- AND NOT EXISTS (SELECT 1 FROM pg_depend d WHERE d.objid = p.oid AND d.deptype = 'e')
10
9
  ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
11
10
  `);
12
11
  const aggregateFunctions = await knex.raw(`
@@ -21,7 +20,6 @@ export const generateFunctionsFromDatabase = async (knex) => {
21
20
  JOIN pg_aggregate a ON p.oid = a.aggfnoid
22
21
  JOIN pg_namespace n ON p.pronamespace = n.oid
23
22
  WHERE n.nspname = 'public'
24
- AND NOT EXISTS (SELECT 1 FROM pg_depend d WHERE d.objid = p.oid AND d.deptype = 'e')
25
23
  ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
26
24
  `);
27
25
  const functions = [];
@@ -1 +1 @@
1
- {"version":3,"file":"generate-functions.js","sourceRoot":"","sources":["../../../src/migrations/generate-functions.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,6BAA6B,GAAG,KAAK,EAAE,IAAU,EAAmB,EAAE;IACjF,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC;;;;;;;;;GASvC,CAAC,CAAC;IAEH,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC;;;;;;;;;;;;;;GAczC,CAAC,CAAC;IAEH,MAAM,SAAS,GAAa,EAAE,CAAC;IAE/B,KAAK,MAAM,GAAG,IAAI,gBAAgB,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;QAC9C,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;YACnB,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,kBAAkB,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;QAChD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;QAC5B,MAAM,YAAY,GAAG,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC;QACvC,MAAM,SAAS,GAAG,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC;QAC7B,MAAM,SAAS,GAAG,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC;QAEvC,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,SAAS;QACX,CAAC;QAED,IAAI,YAAY,GAAG,oBAAoB,IAAI,IAAI,YAAY,OAAO,CAAC;QACnE,YAAY,IAAI,aAAa,SAAS,KAAK,CAAC;QAC5C,YAAY,IAAI,aAAa,SAAS,EAAE,CAAC;QAEzC,IAAI,SAAS,EAAE,CAAC;YACd,YAAY,IAAI,oBAAoB,SAAS,EAAE,CAAC;QAClD,CAAC;QAED,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC9C,MAAM,UAAU,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAClF,YAAY,IAAI,mBAAmB,UAAU,EAAE,CAAC;QAClD,CAAC;QAED,YAAY,IAAI,MAAM,CAAC;QAEvB,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,0CAA0C,CAAC;IACpD,CAAC;IAED,MAAM,oBAAoB,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAE9F,OAAO,yCAAyC,oBAAoB,SAAS,CAAC;AAChF,CAAC,CAAC"}
1
+ {"version":3,"file":"generate-functions.js","sourceRoot":"","sources":["../../../src/migrations/generate-functions.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,6BAA6B,GAAG,KAAK,EAAE,IAAU,EAAmB,EAAE;IACjF,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC;;;;;;;;GAQvC,CAAC,CAAC;IAEH,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC;;;;;;;;;;;;;GAazC,CAAC,CAAC;IAEH,MAAM,SAAS,GAAa,EAAE,CAAC;IAE/B,KAAK,MAAM,GAAG,IAAI,gBAAgB,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;QAC9C,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;YACnB,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,kBAAkB,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;QAChD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;QAC5B,MAAM,YAAY,GAAG,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC;QACvC,MAAM,SAAS,GAAG,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC;QAC7B,MAAM,SAAS,GAAG,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC;QAEvC,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,SAAS;QACX,CAAC;QAED,IAAI,YAAY,GAAG,oBAAoB,IAAI,IAAI,YAAY,OAAO,CAAC;QACnE,YAAY,IAAI,aAAa,SAAS,KAAK,CAAC;QAC5C,YAAY,IAAI,aAAa,SAAS,EAAE,CAAC;QAEzC,IAAI,SAAS,EAAE,CAAC;YACd,YAAY,IAAI,oBAAoB,SAAS,EAAE,CAAC;QAClD,CAAC;QAED,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC9C,MAAM,UAAU,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAClF,YAAY,IAAI,mBAAmB,UAAU,EAAE,CAAC;QAClD,CAAC;QAED,YAAY,IAAI,MAAM,CAAC;QAEvB,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,0CAA0C,CAAC;IACpD,CAAC;IAED,MAAM,oBAAoB,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAE9F,OAAO,yCAAyC,oBAAoB,SAAS,CAAC;AAChF,CAAC,CAAC"}
@@ -9,10 +9,6 @@ export declare class MigrationGenerator {
9
9
  private columns;
10
10
  /** table name -> constraint name -> check clause expression */
11
11
  private existingCheckConstraints;
12
- /** table name -> constraint name -> exclude definition (normalized) */
13
- private existingExcludeConstraints;
14
- /** table name -> constraint name -> trigger definition (normalized) */
15
- private existingConstraintTriggers;
16
12
  private uuidUsed?;
17
13
  private nowUsed?;
18
14
  needsMigration: boolean;
@@ -34,22 +30,19 @@ export declare class MigrationGenerator {
34
30
  private dropTable;
35
31
  private renameTable;
36
32
  private renameColumn;
37
- private getConstraintName;
38
- private static readonly SQL_KEYWORDS;
39
- private normalizeSqlIdentifiers;
33
+ private getCheckConstraintName;
40
34
  private normalizeCheckExpression;
41
- private normalizeExcludeDef;
42
- private normalizeTriggerDef;
35
+ private isWrappedByOuterParentheses;
36
+ private findExistingConstraint;
37
+ private equalExpressions;
38
+ private canonicalizeCheckExpressionWithPostgres;
39
+ private extractCheckExpressionFromDefinition;
40
+ private quoteIdentifier;
41
+ private quoteQualifiedIdentifier;
43
42
  /** Escape expression for embedding inside a template literal in generated code */
44
43
  private escapeExpressionForRaw;
45
44
  private addCheckConstraint;
46
45
  private dropCheckConstraint;
47
- private buildExcludeDef;
48
- private addExcludeConstraint;
49
- private dropExcludeConstraint;
50
- private buildConstraintTriggerDef;
51
- private addConstraintTrigger;
52
- private dropConstraintTrigger;
53
46
  private value;
54
47
  private columnRaw;
55
48
  private column;