@smartive/graphql-magic 23.6.1-next.2 → 23.7.0-next.1

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.
Files changed (46) hide show
  1. package/.gqmrc.json +2 -1
  2. package/CHANGELOG.md +3 -3
  3. package/dist/bin/gqm.cjs +278 -115
  4. package/dist/cjs/index.cjs +288 -125
  5. package/dist/esm/db/generate.js +5 -5
  6. package/dist/esm/db/generate.js.map +1 -1
  7. package/dist/esm/migrations/generate.d.ts +13 -1
  8. package/dist/esm/migrations/generate.js +197 -41
  9. package/dist/esm/migrations/generate.js.map +1 -1
  10. package/dist/esm/migrations/index.d.ts +2 -1
  11. package/dist/esm/migrations/index.js +2 -1
  12. package/dist/esm/migrations/index.js.map +1 -1
  13. package/dist/esm/models/model-definitions.d.ts +27 -2
  14. package/dist/esm/models/models.d.ts +1 -5
  15. package/dist/esm/models/models.js +4 -1
  16. package/dist/esm/models/models.js.map +1 -1
  17. package/dist/esm/models/utils.d.ts +16 -7
  18. package/dist/esm/models/utils.js +16 -6
  19. package/dist/esm/models/utils.js.map +1 -1
  20. package/dist/esm/permissions/check.js +2 -2
  21. package/dist/esm/permissions/check.js.map +1 -1
  22. package/dist/esm/resolvers/mutations.js +6 -6
  23. package/dist/esm/resolvers/mutations.js.map +1 -1
  24. package/dist/esm/resolvers/resolvers.js +3 -9
  25. package/dist/esm/resolvers/resolvers.js.map +1 -1
  26. package/dist/esm/schema/generate.js +3 -9
  27. package/dist/esm/schema/generate.js.map +1 -1
  28. package/docker-compose.yml +2 -3
  29. package/docs/docs/2-models.md +18 -4
  30. package/docs/docs/5-migrations.md +11 -5
  31. package/package.json +3 -3
  32. package/src/bin/gqm/parse-knexfile.ts +1 -0
  33. package/src/bin/gqm/settings.ts +4 -0
  34. package/src/db/generate.ts +5 -15
  35. package/src/migrations/generate.ts +257 -42
  36. package/src/migrations/index.ts +2 -1
  37. package/src/models/model-definitions.ts +20 -1
  38. package/src/models/models.ts +4 -1
  39. package/src/models/utils.ts +27 -8
  40. package/src/permissions/check.ts +2 -2
  41. package/src/resolvers/mutations.ts +6 -6
  42. package/src/resolvers/resolvers.ts +7 -13
  43. package/src/schema/generate.ts +28 -26
  44. package/tests/unit/constraints.spec.ts +98 -2
  45. package/tests/unit/generate-as.spec.ts +6 -6
  46. package/tests/utils/functions.ts +1 -0
@@ -1,5 +1,5 @@
1
1
  import CodeBlockWriter from 'code-block-writer';
2
- import { get, getColumnName, isCustomField, isGenerateAsField, isInTable, isRootModel, isStoredInDatabase, not, } from '..';
2
+ import { and, get, getColumnName, isDynamicField, isInTable, isRootModel, isStoredInDatabase, not } from '..';
3
3
  import { DATE_CLASS, DATE_CLASS_IMPORT } from '../utils/dates';
4
4
  export const PRIMITIVE_TYPES = {
5
5
  ID: 'string',
@@ -49,7 +49,7 @@ export const generateDBModels = (models, dateLibrary) => {
49
49
  writer
50
50
  .write(`export type ${model.name} = `)
51
51
  .inlineBlock(() => {
52
- for (const field of fields.filter(not(isCustomField)).filter(isStoredInDatabase)) {
52
+ for (const field of fields.filter(isStoredInDatabase)) {
53
53
  writer
54
54
  .write(`'${getColumnName(field)}': ${getFieldType(field, dateLibrary)}${field.nonNull ? '' : ' | null'};`)
55
55
  .newLine();
@@ -59,7 +59,7 @@ export const generateDBModels = (models, dateLibrary) => {
59
59
  writer
60
60
  .write(`export type ${model.name}Initializer = `)
61
61
  .inlineBlock(() => {
62
- for (const field of fields.filter(not(isCustomField)).filter(isInTable).filter(not(isGenerateAsField))) {
62
+ for (const field of fields.filter(and(isInTable, not(isDynamicField)))) {
63
63
  writer
64
64
  .write(`'${getColumnName(field)}'${field.nonNull && field.defaultValue === undefined ? '' : '?'}: ${getFieldType(field, dateLibrary, true)}${field.list ? ' | string' : ''}${field.nonNull ? '' : ' | null'};`)
65
65
  .newLine();
@@ -69,7 +69,7 @@ export const generateDBModels = (models, dateLibrary) => {
69
69
  writer
70
70
  .write(`export type ${model.name}Mutator = `)
71
71
  .inlineBlock(() => {
72
- for (const field of fields.filter(not(isCustomField)).filter(isInTable).filter(not(isGenerateAsField))) {
72
+ for (const field of fields.filter(and(isInTable, not(isDynamicField)))) {
73
73
  writer
74
74
  .write(`'${getColumnName(field)}'?: ${getFieldType(field, dateLibrary, true)}${field.list ? ' | string' : ''}${field.nonNull ? '' : ' | null'};`)
75
75
  .newLine();
@@ -80,7 +80,7 @@ export const generateDBModels = (models, dateLibrary) => {
80
80
  writer
81
81
  .write(`export type ${model.name}Seed = `)
82
82
  .inlineBlock(() => {
83
- for (const field of fields.filter(not(isCustomField)).filter(not(isGenerateAsField))) {
83
+ for (const field of fields.filter(not(isDynamicField))) {
84
84
  if (model.parent && field.name === 'type') {
85
85
  continue;
86
86
  }
@@ -1 +1 @@
1
- {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../src/db/generate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../src/db/generate.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,10 @@ 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;
12
16
  private uuidUsed?;
13
17
  private nowUsed?;
14
18
  needsMigration: boolean;
@@ -30,12 +34,20 @@ export declare class MigrationGenerator {
30
34
  private dropTable;
31
35
  private renameTable;
32
36
  private renameColumn;
33
- private getCheckConstraintName;
37
+ private getConstraintName;
34
38
  private normalizeCheckExpression;
39
+ private normalizeExcludeDef;
40
+ private normalizeTriggerDef;
35
41
  /** Escape expression for embedding inside a template literal in generated code */
36
42
  private escapeExpressionForRaw;
37
43
  private addCheckConstraint;
38
44
  private dropCheckConstraint;
45
+ private buildExcludeDef;
46
+ private addExcludeConstraint;
47
+ private dropExcludeConstraint;
48
+ private buildConstraintTriggerDef;
49
+ private addConstraintTrigger;
50
+ private dropConstraintTrigger;
39
51
  private value;
40
52
  private columnRaw;
41
53
  private column;
@@ -1,7 +1,7 @@
1
1
  import CodeBlockWriter from 'code-block-writer';
2
2
  import { SchemaInspector } from 'knex-schema-inspector';
3
3
  import lowerFirst from 'lodash/lowerFirst';
4
- import { and, get, isCreatableModel, isGenerateAsField, isInherited, isUpdatableField, isUpdatableModel, modelNeedsTable, not, summonByName, typeToField, validateCheckConstraint, } from '../models/utils';
4
+ import { and, get, isCreatableModel, isInherited, isStoredInDatabase, isUpdatableField, isUpdatableModel, modelNeedsTable, not, summonByName, typeToField, validateCheckConstraint, validateExcludeConstraint, } from '../models/utils';
5
5
  import { getColumnName } from '../resolvers';
6
6
  import { getDatabaseFunctions, normalizeAggregateDefinition, normalizeFunctionBody, } from './update-functions';
7
7
  export class MigrationGenerator {
@@ -16,6 +16,10 @@ export class MigrationGenerator {
16
16
  columns = {};
17
17
  /** table name -> constraint name -> check clause expression */
18
18
  existingCheckConstraints = {};
19
+ /** table name -> constraint name -> exclude definition (normalized) */
20
+ existingExcludeConstraints = {};
21
+ /** table name -> constraint name -> trigger definition (normalized) */
22
+ existingConstraintTriggers = {};
19
23
  uuidUsed;
20
24
  nowUsed;
21
25
  needsMigration = false;
@@ -48,8 +52,44 @@ export class MigrationGenerator {
48
52
  }
49
53
  this.existingCheckConstraints[tableName].set(row.constraint_name, row.check_clause);
50
54
  }
55
+ const excludeResult = await schema.knex.raw(`SELECT c.conrelid::regclass::text as table_name, c.conname as constraint_name, pg_get_constraintdef(c.oid) as constraint_def
56
+ FROM pg_constraint c
57
+ JOIN pg_namespace n ON c.connamespace = n.oid
58
+ WHERE n.nspname = 'public' AND c.contype = 'x'`);
59
+ const excludeRows = 'rows' in excludeResult && Array.isArray(excludeResult.rows)
60
+ ? excludeResult.rows
61
+ : [];
62
+ for (const row of excludeRows) {
63
+ const tableName = row.table_name.split('.').pop()?.replace(/^"|"$/g, '') ?? row.table_name;
64
+ if (!this.existingExcludeConstraints[tableName]) {
65
+ this.existingExcludeConstraints[tableName] = new Map();
66
+ }
67
+ this.existingExcludeConstraints[tableName].set(row.constraint_name, this.normalizeExcludeDef(row.constraint_def));
68
+ }
69
+ const triggerResult = await schema.knex.raw(`SELECT c.conrelid::regclass::text as table_name, c.conname as constraint_name, pg_get_triggerdef(t.oid) as trigger_def
70
+ FROM pg_constraint c
71
+ JOIN pg_trigger t ON t.tgconstraint = c.oid
72
+ JOIN pg_namespace n ON c.connamespace = n.oid
73
+ WHERE n.nspname = 'public' AND c.contype = 't'`);
74
+ const triggerRows = 'rows' in triggerResult && Array.isArray(triggerResult.rows)
75
+ ? triggerResult.rows
76
+ : [];
77
+ for (const row of triggerRows) {
78
+ const tableName = row.table_name.split('.').pop()?.replace(/^"|"$/g, '') ?? row.table_name;
79
+ if (!this.existingConstraintTriggers[tableName]) {
80
+ this.existingConstraintTriggers[tableName] = new Map();
81
+ }
82
+ this.existingConstraintTriggers[tableName].set(row.constraint_name, this.normalizeTriggerDef(row.trigger_def));
83
+ }
51
84
  const up = [];
52
85
  const down = [];
86
+ const needsBtreeGist = models.entities.some((model) => model.constraints?.some((c) => c.kind === 'exclude' && c.elements.some((el) => 'column' in el && el.operator === '=')));
87
+ if (needsBtreeGist) {
88
+ up.unshift(() => {
89
+ this.writer.writeLine(`await knex.raw('CREATE EXTENSION IF NOT EXISTS btree_gist');`);
90
+ this.writer.blankLine();
91
+ });
92
+ }
53
93
  this.createEnums(this.models.enums.filter((enm) => !enums.includes(lowerFirst(enm.name))), up, down);
54
94
  await this.handleFunctions(up, down);
55
95
  for (const model of models.entities) {
@@ -129,10 +169,24 @@ export class MigrationGenerator {
129
169
  if (entry.kind === 'check') {
130
170
  validateCheckConstraint(model, entry);
131
171
  const table = model.name;
132
- const constraintName = this.getCheckConstraintName(model, entry, i);
133
- const expression = entry.expression;
172
+ const constraintName = this.getConstraintName(model, entry, i);
134
173
  up.push(() => {
135
- this.addCheckConstraint(table, constraintName, expression);
174
+ this.addCheckConstraint(table, constraintName, entry.expression, entry.deferrable);
175
+ });
176
+ }
177
+ else if (entry.kind === 'exclude') {
178
+ validateExcludeConstraint(model, entry);
179
+ const table = model.name;
180
+ const constraintName = this.getConstraintName(model, entry, i);
181
+ up.push(() => {
182
+ this.addExcludeConstraint(table, constraintName, entry);
183
+ });
184
+ }
185
+ else if (entry.kind === 'constraint_trigger') {
186
+ const table = model.name;
187
+ const constraintName = this.getConstraintName(model, entry, i);
188
+ up.push(() => {
189
+ this.addConstraintTrigger(table, constraintName, entry);
136
190
  });
137
191
  }
138
192
  }
@@ -171,34 +225,84 @@ export class MigrationGenerator {
171
225
  const existingFields = model.fields.filter((field) => (!field.generateAs || field.generateAs.type === 'expression') && this.hasChanged(model, field));
172
226
  this.updateFields(model, existingFields, up, down);
173
227
  if (model.constraints?.length) {
174
- const existingMap = this.existingCheckConstraints[model.name];
228
+ const existingCheckMap = this.existingCheckConstraints[model.name];
229
+ const existingExcludeMap = this.existingExcludeConstraints[model.name];
230
+ const existingTriggerMap = this.existingConstraintTriggers[model.name];
175
231
  for (let i = 0; i < model.constraints.length; i++) {
176
232
  const entry = model.constraints[i];
177
- if (entry.kind !== 'check') {
178
- continue;
179
- }
180
- validateCheckConstraint(model, entry);
181
233
  const table = model.name;
182
- const constraintName = this.getCheckConstraintName(model, entry, i);
183
- const newExpression = entry.expression;
184
- const existingExpression = existingMap?.get(constraintName);
185
- if (existingExpression === undefined) {
186
- up.push(() => {
187
- this.addCheckConstraint(table, constraintName, newExpression);
188
- });
189
- down.push(() => {
190
- this.dropCheckConstraint(table, constraintName);
191
- });
234
+ const constraintName = this.getConstraintName(model, entry, i);
235
+ if (entry.kind === 'check') {
236
+ validateCheckConstraint(model, entry);
237
+ const newExpression = entry.expression;
238
+ const existingExpression = existingCheckMap?.get(constraintName);
239
+ if (existingExpression === undefined) {
240
+ up.push(() => {
241
+ this.addCheckConstraint(table, constraintName, newExpression, entry.deferrable);
242
+ });
243
+ down.push(() => {
244
+ this.dropCheckConstraint(table, constraintName);
245
+ });
246
+ }
247
+ else if (this.normalizeCheckExpression(existingExpression) !== this.normalizeCheckExpression(newExpression)) {
248
+ up.push(() => {
249
+ this.dropCheckConstraint(table, constraintName);
250
+ this.addCheckConstraint(table, constraintName, newExpression, entry.deferrable);
251
+ });
252
+ down.push(() => {
253
+ this.dropCheckConstraint(table, constraintName);
254
+ this.addCheckConstraint(table, constraintName, existingExpression);
255
+ });
256
+ }
192
257
  }
193
- else if (this.normalizeCheckExpression(existingExpression) !== this.normalizeCheckExpression(newExpression)) {
194
- up.push(() => {
195
- this.dropCheckConstraint(table, constraintName);
196
- this.addCheckConstraint(table, constraintName, newExpression);
197
- });
198
- down.push(() => {
199
- this.dropCheckConstraint(table, constraintName);
200
- this.addCheckConstraint(table, constraintName, existingExpression);
201
- });
258
+ else if (entry.kind === 'exclude') {
259
+ validateExcludeConstraint(model, entry);
260
+ const newDef = this.normalizeExcludeDef(this.buildExcludeDef(entry));
261
+ const existingDef = existingExcludeMap?.get(constraintName);
262
+ if (existingDef === undefined) {
263
+ up.push(() => {
264
+ this.addExcludeConstraint(table, constraintName, entry);
265
+ });
266
+ down.push(() => {
267
+ this.dropExcludeConstraint(table, constraintName);
268
+ });
269
+ }
270
+ else if (existingDef !== newDef) {
271
+ up.push(() => {
272
+ this.dropExcludeConstraint(table, constraintName);
273
+ this.addExcludeConstraint(table, constraintName, entry);
274
+ });
275
+ down.push(() => {
276
+ this.dropExcludeConstraint(table, constraintName);
277
+ const escaped = this.escapeExpressionForRaw(existingDef);
278
+ this.writer.writeLine(`await knex.raw(\`ALTER TABLE "${table}" ADD CONSTRAINT "${constraintName}" ${escaped}\`);`);
279
+ this.writer.blankLine();
280
+ });
281
+ }
282
+ }
283
+ else if (entry.kind === 'constraint_trigger') {
284
+ const newDef = this.normalizeTriggerDef(this.buildConstraintTriggerDef(table, constraintName, entry));
285
+ const existingDef = existingTriggerMap?.get(constraintName);
286
+ if (existingDef === undefined) {
287
+ up.push(() => {
288
+ this.addConstraintTrigger(table, constraintName, entry);
289
+ });
290
+ down.push(() => {
291
+ this.dropConstraintTrigger(table, constraintName);
292
+ });
293
+ }
294
+ else if (existingDef !== newDef) {
295
+ up.push(() => {
296
+ this.dropConstraintTrigger(table, constraintName);
297
+ this.addConstraintTrigger(table, constraintName, entry);
298
+ });
299
+ down.push(() => {
300
+ this.dropConstraintTrigger(table, constraintName);
301
+ const escaped = existingDef.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$/g, '\\$');
302
+ this.writer.writeLine(`await knex.raw(\`${escaped}\`);`);
303
+ this.writer.blankLine();
304
+ });
305
+ }
202
306
  }
203
307
  }
204
308
  }
@@ -228,9 +332,7 @@ export class MigrationGenerator {
228
332
  writer.writeLine(`deleteRootType: row.deleteRootType,`);
229
333
  writer.writeLine(`deleteRootId: row.deleteRootId,`);
230
334
  }
231
- for (const { name, kind } of model.fields
232
- .filter(isUpdatableField)
233
- .filter(not(isGenerateAsField))) {
335
+ for (const { name, kind } of model.fields.filter(and(isUpdatableField, isStoredInDatabase))) {
234
336
  const col = kind === 'relation' ? `${name}Id` : name;
235
337
  writer.writeLine(`${col}: row.${col},`);
236
338
  }
@@ -253,10 +355,8 @@ export class MigrationGenerator {
253
355
  .filter(not(isInherited))
254
356
  .filter(({ oldName }) => oldName), up, down);
255
357
  const missingRevisionFields = model.fields
256
- .filter(isUpdatableField)
257
- .filter(not(isGenerateAsField))
258
- .filter(({ name, ...field }) => field.kind !== 'custom' &&
259
- !this.getColumn(revisionTable, field.kind === 'relation' ? field.foreignKey || `${name}Id` : name));
358
+ .filter(and(isUpdatableField, isStoredInDatabase))
359
+ .filter(({ name, ...field }) => !this.getColumn(revisionTable, field.kind === 'relation' ? field.foreignKey || `${name}Id` : name));
260
360
  this.createRevisionFields(model, missingRevisionFields, up, down);
261
361
  const revisionFieldsToRemove = model.fields.filter(({ name, updatable, generated, ...field }) => !generated &&
262
362
  field.kind !== 'custom' &&
@@ -407,7 +507,7 @@ export class MigrationGenerator {
407
507
  });
408
508
  });
409
509
  if (isUpdatableModel(model)) {
410
- const updatableFields = fields.filter(isUpdatableField).filter(not(isGenerateAsField));
510
+ const updatableFields = fields.filter(and(isUpdatableField, isStoredInDatabase));
411
511
  if (!updatableFields.length) {
412
512
  return;
413
513
  }
@@ -446,7 +546,7 @@ export class MigrationGenerator {
446
546
  });
447
547
  });
448
548
  if (isUpdatableModel(model)) {
449
- const updatableFields = fields.filter(isUpdatableField).filter(not(isGenerateAsField));
549
+ const updatableFields = fields.filter(and(isUpdatableField, isStoredInDatabase));
450
550
  if (!updatableFields.length) {
451
551
  return;
452
552
  }
@@ -481,7 +581,7 @@ export class MigrationGenerator {
481
581
  writer.writeLine(`table.uuid('deleteRootId');`);
482
582
  }
483
583
  }
484
- for (const field of model.fields.filter(and(isUpdatableField, not(isInherited))).filter(not(isGenerateAsField))) {
584
+ for (const field of model.fields.filter(and(isUpdatableField, not(isInherited), isStoredInDatabase))) {
485
585
  this.column(field, { setUnique: false, setDefault: false });
486
586
  }
487
587
  });
@@ -585,25 +685,81 @@ export class MigrationGenerator {
585
685
  renameColumn(from, to) {
586
686
  this.writer.writeLine(`table.renameColumn('${from}', '${to}');`);
587
687
  }
588
- getCheckConstraintName(model, entry, index) {
688
+ getConstraintName(model, entry, index) {
589
689
  return `${model.name}_${entry.name}_${entry.kind}_${index}`;
590
690
  }
591
691
  normalizeCheckExpression(expr) {
592
692
  return expr.replace(/\s+/g, ' ').trim();
593
693
  }
694
+ normalizeExcludeDef(def) {
695
+ return def
696
+ .replace(/\s+/g, ' ')
697
+ .replace(/\s*\(\s*/g, '(')
698
+ .replace(/\s*\)\s*/g, ')')
699
+ .trim();
700
+ }
701
+ normalizeTriggerDef(def) {
702
+ return def
703
+ .replace(/\s+/g, ' ')
704
+ .replace(/\s*\(\s*/g, '(')
705
+ .replace(/\s*\)\s*/g, ')')
706
+ .trim();
707
+ }
594
708
  /** Escape expression for embedding inside a template literal in generated code */
595
709
  escapeExpressionForRaw(expr) {
596
710
  return expr.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$/g, '\\$');
597
711
  }
598
- addCheckConstraint(table, constraintName, expression) {
712
+ addCheckConstraint(table, constraintName, expression, deferrable) {
599
713
  const escaped = this.escapeExpressionForRaw(expression);
600
- this.writer.writeLine(`await knex.raw(\`ALTER TABLE "${table}" ADD CONSTRAINT "${constraintName}" CHECK (${escaped})\`);`);
714
+ const deferrableClause = deferrable ? ` DEFERRABLE ${deferrable}` : '';
715
+ this.writer.writeLine(`await knex.raw(\`ALTER TABLE "${table}" ADD CONSTRAINT "${constraintName}" CHECK (${escaped})${deferrableClause}\`);`);
601
716
  this.writer.blankLine();
602
717
  }
603
718
  dropCheckConstraint(table, constraintName) {
604
719
  this.writer.writeLine(`await knex.raw('ALTER TABLE "${table}" DROP CONSTRAINT "${constraintName}"');`);
605
720
  this.writer.blankLine();
606
721
  }
722
+ buildExcludeDef(entry) {
723
+ const elementsStr = entry.elements
724
+ .map((el) => ('column' in el ? `"${el.column}" WITH ${el.operator}` : `${el.expression} WITH ${el.operator}`))
725
+ .join(', ');
726
+ const whereClause = entry.where ? ` WHERE (${entry.where})` : '';
727
+ const deferrableClause = entry.deferrable ? ` DEFERRABLE ${entry.deferrable}` : '';
728
+ return `EXCLUDE USING ${entry.using} (${elementsStr})${whereClause}${deferrableClause}`;
729
+ }
730
+ addExcludeConstraint(table, constraintName, entry) {
731
+ const def = this.buildExcludeDef(entry);
732
+ const escaped = this.escapeExpressionForRaw(def);
733
+ this.writer.writeLine(`await knex.raw(\`ALTER TABLE "${table}" ADD CONSTRAINT "${constraintName}" ${escaped}\`);`);
734
+ this.writer.blankLine();
735
+ }
736
+ dropExcludeConstraint(table, constraintName) {
737
+ this.writer.writeLine(`await knex.raw('ALTER TABLE "${table}" DROP CONSTRAINT "${constraintName}"');`);
738
+ this.writer.blankLine();
739
+ }
740
+ buildConstraintTriggerDef(table, constraintName, entry) {
741
+ const eventsStr = entry.events.join(' OR ');
742
+ const deferrableClause = entry.deferrable ? ` DEFERRABLE ${entry.deferrable}` : '';
743
+ const argsStr = entry.function.args?.length ? entry.function.args.map((a) => `"${a}"`).join(', ') : '';
744
+ const executeClause = argsStr
745
+ ? `EXECUTE FUNCTION ${entry.function.name}(${argsStr})`
746
+ : `EXECUTE FUNCTION ${entry.function.name}()`;
747
+ return `CREATE CONSTRAINT TRIGGER "${constraintName}" ${entry.when} ${eventsStr} ON "${table}" FOR EACH ${entry.forEach}${deferrableClause} ${executeClause}`;
748
+ }
749
+ addConstraintTrigger(table, constraintName, entry) {
750
+ const eventsStr = entry.events.join(' OR ');
751
+ const deferrableClause = entry.deferrable ? ` DEFERRABLE ${entry.deferrable}` : '';
752
+ const argsStr = entry.function.args?.length ? entry.function.args.map((a) => `"${a}"`).join(', ') : '';
753
+ const executeClause = argsStr
754
+ ? `EXECUTE FUNCTION ${entry.function.name}(${argsStr})`
755
+ : `EXECUTE FUNCTION ${entry.function.name}()`;
756
+ this.writer.writeLine(`await knex.raw(\`CREATE CONSTRAINT TRIGGER "${constraintName}" ${entry.when} ${eventsStr} ON "${table}" FOR EACH ${entry.forEach}${deferrableClause} ${executeClause}\`);`);
757
+ this.writer.blankLine();
758
+ }
759
+ dropConstraintTrigger(table, constraintName) {
760
+ this.writer.writeLine(`await knex.raw('ALTER TABLE "${table}" DROP CONSTRAINT "${constraintName}"');`);
761
+ this.writer.blankLine();
762
+ }
607
763
  value(value) {
608
764
  if (typeof value === 'string') {
609
765
  return `'${value}'`;