ts-prorm-orm 1.2.3 → 2.1.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.
Files changed (204) hide show
  1. package/CHANGELOG.md +331 -1
  2. package/README.md +32 -24
  3. package/dist/compliance/data-classifier.d.ts +6 -0
  4. package/dist/compliance/data-classifier.js +6 -0
  5. package/dist/compliance/data-lineage.d.ts +4 -0
  6. package/dist/compliance/data-lineage.js +4 -0
  7. package/dist/compliance/data-masker.d.ts +4 -0
  8. package/dist/compliance/data-masker.js +4 -0
  9. package/dist/compliance/index.d.ts +4 -0
  10. package/dist/compliance/index.js +15 -1
  11. package/dist/compliance/pseudonymization.d.ts +4 -0
  12. package/dist/compliance/pseudonymization.js +4 -0
  13. package/dist/compliance/query-firewall.d.ts +9 -9
  14. package/dist/compliance/query-firewall.js +9 -9
  15. package/dist/compliance/rate-limiter.d.ts +4 -0
  16. package/dist/compliance/rate-limiter.js +4 -0
  17. package/dist/compliance/row-level-security.d.ts +2 -0
  18. package/dist/compliance/row-level-security.js +2 -0
  19. package/dist/compliance/security-decorator.d.ts +8 -0
  20. package/dist/compliance/security-decorator.js +8 -0
  21. package/dist/compliance/session-isolation.d.ts +4 -0
  22. package/dist/compliance/session-isolation.js +4 -0
  23. package/dist/compliance/worm-storage.d.ts +4 -0
  24. package/dist/compliance/worm-storage.js +4 -0
  25. package/dist/connection-manager.js +13 -1
  26. package/dist/core/expressions.d.ts +58 -0
  27. package/dist/core/expressions.js +83 -0
  28. package/dist/core/hooks-manager.d.ts +179 -0
  29. package/dist/core/hooks-manager.js +291 -0
  30. package/dist/core/types.d.ts +235 -0
  31. package/dist/core/types.js +9 -0
  32. package/dist/decorators/audit.d.ts +3 -1
  33. package/dist/decorators/audit.js +3 -1
  34. package/dist/decorators/check.d.ts +15 -15
  35. package/dist/decorators/check.js +15 -15
  36. package/dist/decorators/collate.d.ts +16 -0
  37. package/dist/decorators/collate.js +16 -0
  38. package/dist/decorators/comment.d.ts +3 -1
  39. package/dist/decorators/comment.js +3 -1
  40. package/dist/decorators/database-settings.d.ts +6 -0
  41. package/dist/decorators/database-settings.js +6 -0
  42. package/dist/decorators/default.d.ts +2 -0
  43. package/dist/decorators/default.js +2 -0
  44. package/dist/decorators/encryption.d.ts +7 -1
  45. package/dist/decorators/encryption.js +7 -1
  46. package/dist/decorators/engine.d.ts +4 -0
  47. package/dist/decorators/engine.js +4 -0
  48. package/dist/decorators/fk-constraints.d.ts +32 -32
  49. package/dist/decorators/fk-constraints.js +32 -32
  50. package/dist/decorators/foreign-table.d.ts +1 -1
  51. package/dist/decorators/generated.d.ts +8 -0
  52. package/dist/decorators/generated.js +8 -0
  53. package/dist/decorators/hstore.d.ts +6 -0
  54. package/dist/decorators/hstore.js +6 -0
  55. package/dist/decorators/index.d.ts +2 -0
  56. package/dist/decorators/index.js +11 -1
  57. package/dist/decorators/json-column.d.ts +2 -0
  58. package/dist/decorators/json-column.js +2 -0
  59. package/dist/decorators/jsonb.d.ts +6 -0
  60. package/dist/decorators/jsonb.js +6 -0
  61. package/dist/decorators/permissions.d.ts +12 -0
  62. package/dist/decorators/permissions.js +12 -0
  63. package/dist/decorators/procedure.d.ts +4 -2
  64. package/dist/decorators/procedure.js +4 -2
  65. package/dist/decorators/query-options.d.ts +24 -0
  66. package/dist/decorators/query-options.js +24 -0
  67. package/dist/decorators/range.d.ts +8 -0
  68. package/dist/decorators/range.js +8 -0
  69. package/dist/decorators/set-column.d.ts +2 -0
  70. package/dist/decorators/set-column.js +2 -0
  71. package/dist/decorators/spatial.d.ts +2 -0
  72. package/dist/decorators/spatial.js +2 -0
  73. package/dist/decorators/storage.d.ts +24 -0
  74. package/dist/decorators/storage.js +24 -0
  75. package/dist/decorators/timezone.d.ts +7 -7
  76. package/dist/decorators/timezone.js +7 -7
  77. package/dist/decorators/trigger.d.ts +3 -1
  78. package/dist/decorators/trigger.js +3 -1
  79. package/dist/decorators/uuid.d.ts +6 -0
  80. package/dist/decorators/uuid.js +6 -0
  81. package/dist/decorators/view.d.ts +7 -1
  82. package/dist/decorators/view.js +7 -1
  83. package/dist/diagrams/chen-diagram.d.ts +15 -12
  84. package/dist/diagrams/chen-diagram.js +76 -85
  85. package/dist/diagrams/class-diagram.d.ts +9 -8
  86. package/dist/diagrams/class-diagram.js +60 -82
  87. package/dist/diagrams/core/index.d.ts +13 -0
  88. package/dist/diagrams/core/index.js +33 -0
  89. package/dist/diagrams/core/layout.d.ts +104 -0
  90. package/dist/diagrams/core/layout.js +223 -0
  91. package/dist/diagrams/{svg-dom.d.ts → core/svg.d.ts} +8 -20
  92. package/dist/diagrams/{svg-dom.js → core/svg.js} +21 -29
  93. package/dist/diagrams/core/theme.d.ts +84 -0
  94. package/dist/diagrams/core/theme.js +62 -0
  95. package/dist/diagrams/dependency-diagram.d.ts +15 -14
  96. package/dist/diagrams/dependency-diagram.js +71 -105
  97. package/dist/diagrams/er-diagram.d.ts +13 -26
  98. package/dist/diagrams/er-diagram.js +180 -259
  99. package/dist/diagrams/flow-diagram.d.ts +16 -11
  100. package/dist/diagrams/flow-diagram.js +96 -91
  101. package/dist/diagrams/gantt-diagram.d.ts +10 -5
  102. package/dist/diagrams/gantt-diagram.js +77 -103
  103. package/dist/diagrams/index-diagram.d.ts +10 -10
  104. package/dist/diagrams/index-diagram.js +106 -116
  105. package/dist/diagrams/index.d.ts +6 -9
  106. package/dist/diagrams/index.js +9 -24
  107. package/dist/diagrams/migration-diagram.d.ts +8 -4
  108. package/dist/diagrams/migration-diagram.js +189 -161
  109. package/dist/diagrams/model-diagram.d.ts +34 -34
  110. package/dist/diagrams/model-diagram.js +106 -485
  111. package/dist/diagrams/package-diagram.d.ts +9 -6
  112. package/dist/diagrams/package-diagram.js +64 -101
  113. package/dist/diagrams/relational-diagram.d.ts +12 -10
  114. package/dist/diagrams/relational-diagram.js +87 -114
  115. package/dist/diagrams/schemadoc-diagram.d.ts +8 -8
  116. package/dist/diagrams/schemadoc-diagram.js +71 -93
  117. package/dist/diagrams/sequence-diagram.d.ts +10 -10
  118. package/dist/diagrams/sequence-diagram.js +64 -89
  119. package/dist/diagrams/state-diagram.d.ts +10 -9
  120. package/dist/diagrams/state-diagram.js +69 -92
  121. package/dist/diagrams/tree-diagram.d.ts +11 -5
  122. package/dist/diagrams/tree-diagram.js +41 -65
  123. package/dist/dialects/clickhouse/index.js +15 -0
  124. package/dist/dialects/cockroachdb/index.d.ts +1 -1
  125. package/dist/dialects/cockroachdb/index.js +32 -63
  126. package/dist/dialects/db2/index.js +23 -8
  127. package/dist/dialects/dialect.d.ts +141 -5
  128. package/dist/dialects/duckdb/index.js +9 -2
  129. package/dist/dialects/hana/index.js +22 -5
  130. package/dist/dialects/lock-clause-helper.d.ts +167 -0
  131. package/dist/dialects/lock-clause-helper.js +316 -0
  132. package/dist/dialects/mariadb/index.d.ts +7 -4
  133. package/dist/dialects/mariadb/index.js +36 -60
  134. package/dist/dialects/mssql/index.js +34 -3
  135. package/dist/dialects/mysql/index.d.ts +1 -1
  136. package/dist/dialects/mysql/index.js +17 -45
  137. package/dist/dialects/oracle/index.d.ts +14 -3
  138. package/dist/dialects/oracle/index.js +66 -36
  139. package/dist/dialects/order-expression-helper.d.ts +72 -0
  140. package/dist/dialects/order-expression-helper.js +154 -0
  141. package/dist/dialects/partial-index.d.ts +52 -0
  142. package/dist/dialects/partial-index.js +251 -0
  143. package/dist/dialects/postgres/index.d.ts +1 -1
  144. package/dist/dialects/postgres/index.js +43 -68
  145. package/dist/dialects/redshift/index.js +9 -2
  146. package/dist/dialects/snowflake/index.js +17 -0
  147. package/dist/dialects/spanner/index.js +7 -2
  148. package/dist/dialects/sqlite/driver.d.ts +55 -0
  149. package/dist/dialects/sqlite/driver.js +102 -0
  150. package/dist/dialects/sqlite/index.d.ts +1 -1
  151. package/dist/dialects/sqlite/index.js +49 -27
  152. package/dist/external-fields/decorator.d.ts +2 -0
  153. package/dist/external-fields/decorator.js +2 -0
  154. package/dist/graph/base-graph-dialect.d.ts +24 -3
  155. package/dist/graph/base-graph-dialect.js +43 -2
  156. package/dist/graph/dgraph/index.js +6 -0
  157. package/dist/graph/gremlin/index.d.ts +6 -0
  158. package/dist/graph/gremlin/index.js +12 -1
  159. package/dist/graph/index.d.ts +1 -1
  160. package/dist/graph/neo4j/index.d.ts +2 -0
  161. package/dist/graph/neo4j/index.js +6 -1
  162. package/dist/graph/types.d.ts +12 -1
  163. package/dist/index.d.ts +12 -3
  164. package/dist/index.js +53 -7
  165. package/dist/logging/index.d.ts +10 -0
  166. package/dist/logging/index.js +23 -0
  167. package/dist/logging/query-logging.d.ts +82 -0
  168. package/dist/logging/query-logging.js +102 -0
  169. package/dist/models/associations.d.ts +38 -0
  170. package/dist/models/associations.js +16 -0
  171. package/dist/models/decorators.d.ts +55 -19
  172. package/dist/models/decorators.js +95 -19
  173. package/dist/models/eager-load.d.ts +99 -0
  174. package/dist/models/eager-load.js +348 -5
  175. package/dist/models/indexes.d.ts +3 -2
  176. package/dist/models/indexes.js +7 -1
  177. package/dist/models/model.js +69 -43
  178. package/dist/prorm.d.ts +175 -409
  179. package/dist/prorm.js +1132 -553
  180. package/dist/query-builders/order-limit-builder.js +12 -10
  181. package/dist/query-builders/sql-compiler.d.ts +10 -3
  182. package/dist/query-builders/sql-compiler.js +14 -43
  183. package/dist/query-interface.d.ts +2 -1
  184. package/dist/schema-objects.d.ts +42 -0
  185. package/dist/schema-objects.js +28 -0
  186. package/dist/sql-constants.d.ts +44 -0
  187. package/dist/sql-constants.js +138 -1
  188. package/dist/types/index.d.ts +387 -17
  189. package/dist/types/index.js +10 -15
  190. package/dist/types/query-types.d.ts +26 -0
  191. package/dist/types/query-types.js +30 -0
  192. package/package.json +39 -8
  193. package/dist/decorators/belongs-to-many.js +0 -115
  194. package/dist/decorators/belongs-to.js +0 -115
  195. package/dist/decorators/has-many.js +0 -127
  196. package/dist/decorators/has-one.js +0 -116
  197. package/dist/diagrams/palette.d.ts +0 -138
  198. package/dist/diagrams/palette.js +0 -194
  199. package/dist/hooks/hooks-manager.d.ts +0 -189
  200. package/dist/hooks/hooks-manager.js +0 -350
  201. package/dist/hooks/index.d.ts +0 -8
  202. package/dist/hooks/index.js +0 -37
  203. /package/dist/{logging.d.ts → logging/logger.d.ts} +0 -0
  204. /package/dist/{logging.js → logging/logger.js} +0 -0
@@ -9,6 +9,8 @@ exports.createOrderBuilder = createOrderBuilder;
9
9
  exports.createOrderLimitBuilder = createOrderLimitBuilder;
10
10
  exports.buildOrder = buildOrder;
11
11
  exports.buildLimitOffset = buildLimitOffset;
12
+ const operators_1 = require("../operators");
13
+ const order_expression_helper_1 = require("../dialects/order-expression-helper");
12
14
  /**
13
15
  * OrderBuilder class for building ORDER BY clauses
14
16
  */
@@ -45,18 +47,18 @@ class OrderBuilder {
45
47
  return item;
46
48
  }
47
49
  // Handle OrderExpression from order helper functions (asc, desc, random)
48
- if (item && typeof item === 'object' && item.__type === 'order') {
49
- const direction = item.direction;
50
- if (direction === 'RANDOM') {
51
- // RANDOM() for SQLite/PostgreSQL, RAND() for MySQL/MariaDB
52
- const dialectName = this.options.dialect?.name;
53
- if (dialectName === 'mysql' || dialectName === 'mariadb') {
54
- return 'RAND()';
55
- }
56
- // Default to RANDOM() (SQLite/PostgreSQL)
50
+ if ((0, operators_1.isOrderExpression)(item)) {
51
+ const dialectName = this.options.dialect?.name;
52
+ if (!dialectName && item.direction === 'RANDOM') {
53
+ // Standalone builder with no dialect configured: there is nothing to
54
+ // look the random function up by, so keep the historical default
55
+ // rather than throwing.
57
56
  return 'RANDOM()';
58
57
  }
59
- return `${this.escapeId(item.field)} ${direction}`;
58
+ // Otherwise render through the same shared helper the dialects' own
59
+ // buildOrderClause() uses, so `order: [desc('name')]` / `random()`
60
+ // produce identical SQL whichever of the two paths a query takes.
61
+ return (0, order_expression_helper_1.renderOrderExpression)({ name: dialectName, escapeId: (id) => this.escapeId(id) }, item);
60
62
  }
61
63
  // Handle array: ['field', 'ASC'] or [['field', 'ASC'], ['field2', 'DESC']]
62
64
  if (Array.isArray(item)) {
@@ -468,11 +468,18 @@ export declare class SqlCompiler {
468
468
  */
469
469
  private compileFrameBound;
470
470
  /**
471
- * Compile lock options for row-level locking
472
- * Supports NOWAIT and SKIP LOCKED for PostgreSQL and MySQL 8.0+
471
+ * Compile lock options for row-level locking.
472
+ *
473
+ * Delegates to the shared dialect lock compiler so this and each dialect's
474
+ * own `buildSelectQuery()` can never disagree about what a given `lock` shape
475
+ * means. Supports `true`, a level string, and the
476
+ * `{ level, nowait, skipLocked, of }` object form; throws when the named
477
+ * dialect cannot express the requested lock.
478
+ *
473
479
  * @param lock - Lock options
474
480
  * @param dialect - The database dialect
475
- * @returns The compiled lock SQL clause
481
+ * @returns The compiled lock SQL clause, or an empty string for no lock and
482
+ * for dialects with no trailing locking clause (SQLite, SQL Server, ...)
476
483
  */
477
484
  compileLockOptions(lock: any, dialect?: string): string;
478
485
  /**
@@ -15,6 +15,7 @@ exports.jsonKeys = jsonKeys;
15
15
  exports.jsonLength = jsonLength;
16
16
  exports.jsonContains = jsonContains;
17
17
  exports.jsonSearch = jsonSearch;
18
+ const lock_clause_helper_1 = require("../dialects/lock-clause-helper");
18
19
  const operators_1 = require("../operators");
19
20
  /**
20
21
  * Default compiler options
@@ -1816,55 +1817,25 @@ class SqlCompiler {
1816
1817
  return bound === 1 ? '1 FOLLOWING' : `${bound} FOLLOWING`;
1817
1818
  }
1818
1819
  /**
1819
- * Compile lock options for row-level locking
1820
- * Supports NOWAIT and SKIP LOCKED for PostgreSQL and MySQL 8.0+
1820
+ * Compile lock options for row-level locking.
1821
+ *
1822
+ * Delegates to the shared dialect lock compiler so this and each dialect's
1823
+ * own `buildSelectQuery()` can never disagree about what a given `lock` shape
1824
+ * means. Supports `true`, a level string, and the
1825
+ * `{ level, nowait, skipLocked, of }` object form; throws when the named
1826
+ * dialect cannot express the requested lock.
1827
+ *
1821
1828
  * @param lock - Lock options
1822
1829
  * @param dialect - The database dialect
1823
- * @returns The compiled lock SQL clause
1830
+ * @returns The compiled lock SQL clause, or an empty string for no lock and
1831
+ * for dialects with no trailing locking clause (SQLite, SQL Server, ...)
1824
1832
  */
1825
1833
  compileLockOptions(lock, dialect = 'postgres') {
1826
- if (!lock) {
1834
+ const spec = (0, lock_clause_helper_1.getLockSpecForDialect)(dialect);
1835
+ if (!spec) {
1827
1836
  return '';
1828
1837
  }
1829
- let lockType;
1830
- let nowait = false;
1831
- let skipLocked = false;
1832
- // Extract lock configuration
1833
- if (lock === true) {
1834
- lockType = 'UPDATE';
1835
- }
1836
- else if (typeof lock === 'string') {
1837
- lockType = lock;
1838
- }
1839
- else if (typeof lock === 'object') {
1840
- lockType = lock.level || lock;
1841
- nowait = lock.nowait === true;
1842
- skipLocked = lock.skipLocked === true;
1843
- }
1844
- // Build base lock clause
1845
- let lockClause = '';
1846
- if (lockType === 'UPDATE' || lockType === 'UPDATE') {
1847
- lockClause = 'FOR UPDATE';
1848
- }
1849
- else if (lockType === 'SHARE') {
1850
- if (dialect === 'mysql') {
1851
- lockClause = 'LOCK IN SHARE MODE';
1852
- }
1853
- else {
1854
- lockClause = 'FOR SHARE';
1855
- }
1856
- }
1857
- else if (lockType === 'KEY SHARE') {
1858
- lockClause = 'FOR KEY SHARE';
1859
- }
1860
- // Add NOWAIT or SKIP LOCKED (PostgreSQL and MySQL 8.0+)
1861
- if (nowait && (dialect === 'postgres' || dialect === 'mysql')) {
1862
- lockClause += ' NOWAIT';
1863
- }
1864
- else if (skipLocked && (dialect === 'postgres' || dialect === 'mysql')) {
1865
- lockClause += ' SKIP LOCKED';
1866
- }
1867
- return lockClause;
1838
+ return (0, lock_clause_helper_1.buildLockClause)(lock, spec);
1868
1839
  }
1869
1840
  /**
1870
1841
  * Compile OVER clause with partition, order, and window frame
@@ -57,7 +57,8 @@ export interface ConstraintDefinition {
57
57
  };
58
58
  onDelete?: string;
59
59
  onUpdate?: string;
60
- where?: WhereOptions;
60
+ /** Partial-index predicate; see `IndexOptions.where` in `src/dialects/dialect.ts`. */
61
+ where?: WhereOptions | string;
61
62
  }
62
63
  /**
63
64
  * Bulk operation options
@@ -16,6 +16,9 @@ export type SqlDialectName = 'mysql' | 'mariadb' | 'postgres' | 'cockroachdb' |
16
16
  export declare class UnsupportedSchemaObjectError extends Error {
17
17
  constructor(object: string, dialect: string, hint?: string);
18
18
  }
19
+ /**
20
+ * A named sequence: its start, increment, bounds and caching.
21
+ */
19
22
  export interface SequenceOptions {
20
23
  /** Value the sequence starts at (default 1) */
21
24
  start?: number;
@@ -32,8 +35,18 @@ export interface SequenceOptions {
32
35
  /** Emit IF NOT EXISTS where supported */
33
36
  ifNotExists?: boolean;
34
37
  }
38
+ /**
39
+ * Builds `CREATE SEQUENCE` for the dialect.
40
+ */
35
41
  export declare function buildCreateSequenceSQL(name: string, options: SequenceOptions, dialect: SqlDialectName, quoteId: (id: string) => string): string;
42
+ /**
43
+ * Builds `DROP SEQUENCE` for the dialect.
44
+ */
36
45
  export declare function buildDropSequenceSQL(name: string, dialect: SqlDialectName, quoteId: (id: string) => string, ifExists?: boolean): string;
46
+ /**
47
+ * A row-level security policy: who it applies to, which command, and the
48
+ * expressions that decide visibility (`using`) and writability (`withCheck`).
49
+ */
37
50
  export interface PolicyOptions {
38
51
  /** Table the policy applies to */
39
52
  table: string;
@@ -48,9 +61,23 @@ export interface PolicyOptions {
48
61
  /** Roles the policy applies to */
49
62
  to?: string[];
50
63
  }
64
+ /**
65
+ * Builds the statement that turns row-level security on for a table. Until
66
+ * this runs, policies are defined but not enforced.
67
+ */
51
68
  export declare function buildEnableRowLevelSecuritySQL(table: string, dialect: SqlDialectName, quoteTable: (t: string) => string, enable?: boolean): string;
69
+ /**
70
+ * Builds `CREATE POLICY` for a row-level security rule.
71
+ */
52
72
  export declare function buildCreatePolicySQL(options: PolicyOptions, dialect: SqlDialectName, quoteId: (id: string) => string, quoteTable: (t: string) => string): string;
73
+ /**
74
+ * Builds `DROP POLICY`.
75
+ */
53
76
  export declare function buildDropPolicySQL(name: string, table: string, dialect: SqlDialectName, quoteId: (id: string) => string, quoteTable: (t: string) => string, ifExists?: boolean): string;
77
+ /**
78
+ * A full-text index: the columns it covers, the language configuration, and
79
+ * any per-column weighting the engine supports.
80
+ */
54
81
  export interface FullTextIndexOptions {
55
82
  /** Index name */
56
83
  name: string;
@@ -61,7 +88,14 @@ export interface FullTextIndexOptions {
61
88
  /** Text search configuration (PostgreSQL), e.g. 'english' */
62
89
  language?: string;
63
90
  }
91
+ /**
92
+ * Builds the engine's full-text index statement — a GIN index over a tsvector
93
+ * on PostgreSQL, `FULLTEXT` on MySQL, an FTS5 virtual table on SQLite.
94
+ */
64
95
  export declare function buildCreateFullTextIndexSQL(options: FullTextIndexOptions, dialect: SqlDialectName, quoteId: (id: string) => string, quoteTable: (t: string) => string): string;
96
+ /**
97
+ * A trigger: when it fires, on which events, and the body it runs.
98
+ */
65
99
  export interface TriggerDefinition {
66
100
  name: string;
67
101
  table: string;
@@ -74,5 +108,13 @@ export interface TriggerDefinition {
74
108
  /** Condition guarding the trigger */
75
109
  when?: string;
76
110
  }
111
+ /**
112
+ * Builds the statements a trigger needs. Some engines want a separate
113
+ * function or procedure before the trigger itself, so this returns a list
114
+ * rather than one statement.
115
+ */
77
116
  export declare function buildCreateTriggerStatements(trigger: TriggerDefinition, dialect: SqlDialectName, quoteId: (id: string) => string, quoteTable: (t: string) => string): string[];
117
+ /**
118
+ * Builds `DROP TRIGGER`.
119
+ */
78
120
  export declare function buildDropTriggerSQL(name: string, table: string, dialect: SqlDialectName, quoteId: (id: string) => string, quoteTable: (t: string) => string, ifExists?: boolean): string;
@@ -54,6 +54,9 @@ class UnsupportedSchemaObjectError extends Error {
54
54
  }
55
55
  }
56
56
  exports.UnsupportedSchemaObjectError = UnsupportedSchemaObjectError;
57
+ /**
58
+ * Builds `CREATE SEQUENCE` for the dialect.
59
+ */
57
60
  function buildCreateSequenceSQL(name, options, dialect, quoteId) {
58
61
  if (isSqliteFamily(dialect)) {
59
62
  throw new UnsupportedSchemaObjectError('CREATE SEQUENCE', dialect, 'SQLite has no sequences - use an INTEGER PRIMARY KEY AUTOINCREMENT column instead.');
@@ -83,6 +86,9 @@ function buildCreateSequenceSQL(name, options, dialect, quoteId) {
83
86
  parts.push('CYCLE');
84
87
  return parts.join(' ');
85
88
  }
89
+ /**
90
+ * Builds `DROP SEQUENCE` for the dialect.
91
+ */
86
92
  function buildDropSequenceSQL(name, dialect, quoteId, ifExists = true) {
87
93
  if (isSqliteFamily(dialect) || dialect === 'mysql') {
88
94
  throw new UnsupportedSchemaObjectError('DROP SEQUENCE', dialect);
@@ -91,6 +97,10 @@ function buildDropSequenceSQL(name, dialect, quoteId, ifExists = true) {
91
97
  const guard = ifExists && dialect !== 'oracle' ? 'IF EXISTS ' : '';
92
98
  return `DROP SEQUENCE ${guard}${quoteId(name)}`;
93
99
  }
100
+ /**
101
+ * Builds the statement that turns row-level security on for a table. Until
102
+ * this runs, policies are defined but not enforced.
103
+ */
94
104
  function buildEnableRowLevelSecuritySQL(table, dialect, quoteTable, enable = true) {
95
105
  if (!isPostgresFamily(dialect)) {
96
106
  throw new UnsupportedSchemaObjectError('Row-level security', dialect, dialect === 'mssql'
@@ -99,6 +109,9 @@ function buildEnableRowLevelSecuritySQL(table, dialect, quoteTable, enable = tru
99
109
  }
100
110
  return `ALTER TABLE ${quoteTable(table)} ${enable ? 'ENABLE' : 'DISABLE'} ROW LEVEL SECURITY`;
101
111
  }
112
+ /**
113
+ * Builds `CREATE POLICY` for a row-level security rule.
114
+ */
102
115
  function buildCreatePolicySQL(options, dialect, quoteId, quoteTable) {
103
116
  if (!isPostgresFamily(dialect)) {
104
117
  throw new UnsupportedSchemaObjectError('CREATE POLICY', dialect);
@@ -114,12 +127,19 @@ function buildCreatePolicySQL(options, dialect, quoteId, quoteTable) {
114
127
  sql += ` WITH CHECK (${options.withCheck})`;
115
128
  return sql;
116
129
  }
130
+ /**
131
+ * Builds `DROP POLICY`.
132
+ */
117
133
  function buildDropPolicySQL(name, table, dialect, quoteId, quoteTable, ifExists = true) {
118
134
  if (!isPostgresFamily(dialect)) {
119
135
  throw new UnsupportedSchemaObjectError('DROP POLICY', dialect);
120
136
  }
121
137
  return `DROP POLICY ${ifExists ? 'IF EXISTS ' : ''}${quoteId(name)} ON ${quoteTable(table)}`;
122
138
  }
139
+ /**
140
+ * Builds the engine's full-text index statement — a GIN index over a tsvector
141
+ * on PostgreSQL, `FULLTEXT` on MySQL, an FTS5 virtual table on SQLite.
142
+ */
123
143
  function buildCreateFullTextIndexSQL(options, dialect, quoteId, quoteTable) {
124
144
  const { name, table, columns, language = 'english' } = options;
125
145
  if (!columns.length) {
@@ -145,6 +165,11 @@ function buildCreateFullTextIndexSQL(options, dialect, quoteId, quoteTable) {
145
165
  }
146
166
  throw new UnsupportedSchemaObjectError('Full-text index', dialect);
147
167
  }
168
+ /**
169
+ * Builds the statements a trigger needs. Some engines want a separate
170
+ * function or procedure before the trigger itself, so this returns a list
171
+ * rather than one statement.
172
+ */
148
173
  function buildCreateTriggerStatements(trigger, dialect, quoteId, quoteTable) {
149
174
  const { name, table, timing, event, body, forEach = 'ROW', when } = trigger;
150
175
  if (isPostgresFamily(dialect)) {
@@ -188,6 +213,9 @@ function buildCreateTriggerStatements(trigger, dialect, quoteId, quoteTable) {
188
213
  }
189
214
  throw new UnsupportedSchemaObjectError('CREATE TRIGGER', dialect);
190
215
  }
216
+ /**
217
+ * Builds `DROP TRIGGER`.
218
+ */
191
219
  function buildDropTriggerSQL(name, table, dialect, quoteId, quoteTable, ifExists = true) {
192
220
  const guard = ifExists ? 'IF EXISTS ' : '';
193
221
  if (isMysqlFamily(dialect) || isSqliteFamily(dialect)) {
@@ -113,6 +113,14 @@ export interface PostgresConstants {
113
113
  SEARCH_PATH: SearchPath;
114
114
  AUTOCOMMIT: Autocommit;
115
115
  CACHE: Cache;
116
+ /**
117
+ * Optional: PostgreSQL has no `SET FOREIGN_KEY_CHECKS`. The session-level
118
+ * equivalent is `session_replication_role`, which is present on true
119
+ * PostgreSQL and CockroachDB but absent from some PostgreSQL-derived engines
120
+ * (Redshift does not enforce foreign keys at all), so this is deliberately
121
+ * optional rather than a required member with a fake value.
122
+ */
123
+ FOREIGN_KEY_CHECKS?: ForeignKeyChecks;
116
124
  }
117
125
  /**
118
126
  * SQLite SQL constants
@@ -193,6 +201,10 @@ export declare const COCKROACHDB: CockroachDBConstants;
193
201
  * Amazon Redshift SQL constants
194
202
  * Redshift is derived from PostgreSQL 8.0.2 and only supports the
195
203
  * SERIALIZABLE (default) and READ COMMITTED isolation levels.
204
+ *
205
+ * No FOREIGN_KEY_CHECKS: Redshift treats foreign keys as informational only -
206
+ * it never enforces them and has no `session_replication_role` - so there is
207
+ * nothing to turn off.
196
208
  */
197
209
  export declare const REDSHIFT: RedshiftConstants;
198
210
  /**
@@ -225,6 +237,38 @@ export declare const SQL: SQLConstants;
225
237
  * 'cockroachdb', 'redshift', 'db2', 'snowflake', 'clickhouse')
226
238
  */
227
239
  export declare function getConstantsForDialect(dialect: string): MySQLConstants | PostgresConstants | SQLiteConstants | DB2Constants | SnowflakeConstants | ClickHouseConstants;
240
+ /** Which end of the switch is wanted. */
241
+ export type ForeignKeyChecksMode = 'disable' | 'enable';
242
+ /**
243
+ * Raised when a dialect has no session-level foreign key switch.
244
+ *
245
+ * Mirrors `UnsupportedSchemaObjectError` in ./schema-objects: name the database
246
+ * and say what to do instead, rather than returning SQL that fails at the
247
+ * server. Declared here (not imported) to keep this module dependency-free.
248
+ */
249
+ export declare class UnsupportedForeignKeyChecksError extends Error {
250
+ constructor(dialect: string, hint?: string);
251
+ }
252
+ /**
253
+ * SQL that turns foreign key enforcement off/on for the current session.
254
+ *
255
+ * Every family has its own statement and they are not interchangeable:
256
+ * SQLite/Turso use a PRAGMA, the MySQL family a session variable, and the
257
+ * PostgreSQL family `session_replication_role`. Handing MySQL's
258
+ * `SET FOREIGN_KEY_CHECKS` to anything else - which is what the default branch
259
+ * used to do for every unlisted dialect, PostgreSQL included - produces a
260
+ * syntax error at the server, and the caller only finds out at runtime.
261
+ *
262
+ * The PostgreSQL form needs superuser, or a role granted
263
+ * `SET ON PARAMETER session_replication_role` (PostgreSQL 15+); on an ordinary
264
+ * application role the server answers `permission denied to set parameter`.
265
+ *
266
+ * @throws {UnsupportedForeignKeyChecksError} when the dialect has no
267
+ * session-level equivalent (SQL Server, Oracle and Db2 are per-table or
268
+ * per-constraint; Redshift, Snowflake, ClickHouse and friends do not enforce
269
+ * foreign keys at all).
270
+ */
271
+ export declare function getForeignKeyChecksSQL(dialect: string, mode: ForeignKeyChecksMode): string;
228
272
  /**
229
273
  * Transaction isolation level enum
230
274
  */
@@ -5,8 +5,9 @@
5
5
  * like foreign key checks, transaction isolation levels, etc.
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.IsolationLevelEnum = exports.SQL = exports.CLICKHOUSE = exports.SNOWFLAKE = exports.DB2 = exports.REDSHIFT = exports.COCKROACHDB = exports.SQLITE = exports.POSTGRES = exports.MARIADB = exports.MYSQL = void 0;
8
+ exports.IsolationLevelEnum = exports.UnsupportedForeignKeyChecksError = exports.SQL = exports.CLICKHOUSE = exports.SNOWFLAKE = exports.DB2 = exports.REDSHIFT = exports.COCKROACHDB = exports.SQLITE = exports.POSTGRES = exports.MARIADB = exports.MYSQL = void 0;
9
9
  exports.getConstantsForDialect = getConstantsForDialect;
10
+ exports.getForeignKeyChecksSQL = getForeignKeyChecksSQL;
10
11
  /**
11
12
  * MySQL/MariaDB SQL constants
12
13
  */
@@ -87,6 +88,22 @@ exports.POSTGRES = {
87
88
  on: 'SET SESSION statement_cache_mode = ON',
88
89
  off: 'SET SESSION statement_cache_mode = OFF',
89
90
  },
91
+ /**
92
+ * PostgreSQL suppresses foreign key (and trigger) enforcement for the session
93
+ * by pretending to be a replication target. There is no `SET
94
+ * FOREIGN_KEY_CHECKS` - that is MySQL syntax and PostgreSQL rejects it with a
95
+ * syntax error.
96
+ *
97
+ * Requires superuser, or (PostgreSQL 15+) a role that has been granted
98
+ * `SET ON PARAMETER session_replication_role`. On a plain application role
99
+ * the server raises `permission denied to set parameter`; that error is left
100
+ * to surface rather than being swallowed, because silently continuing with
101
+ * foreign keys still enforced is the failure mode this replaced.
102
+ */
103
+ FOREIGN_KEY_CHECKS: {
104
+ disable: "SET session_replication_role = 'replica'",
105
+ enable: "SET session_replication_role = 'origin'",
106
+ },
90
107
  };
91
108
  /**
92
109
  * SQLite SQL constants
@@ -150,11 +167,21 @@ exports.COCKROACHDB = {
150
167
  on: 'SET SESSION statement_cache_mode = ON',
151
168
  off: 'SET SESSION statement_cache_mode = OFF',
152
169
  },
170
+ /** CockroachDB implements `session_replication_role` (v22.2+) with the same
171
+ * `replica`/`origin` values as PostgreSQL. */
172
+ FOREIGN_KEY_CHECKS: {
173
+ disable: "SET session_replication_role = 'replica'",
174
+ enable: "SET session_replication_role = 'origin'",
175
+ },
153
176
  };
154
177
  /**
155
178
  * Amazon Redshift SQL constants
156
179
  * Redshift is derived from PostgreSQL 8.0.2 and only supports the
157
180
  * SERIALIZABLE (default) and READ COMMITTED isolation levels.
181
+ *
182
+ * No FOREIGN_KEY_CHECKS: Redshift treats foreign keys as informational only -
183
+ * it never enforces them and has no `session_replication_role` - so there is
184
+ * nothing to turn off.
158
185
  */
159
186
  exports.REDSHIFT = {
160
187
  ISOLATION_LEVEL: {
@@ -284,10 +311,120 @@ function getConstantsForDialect(dialect) {
284
311
  return exports.SNOWFLAKE;
285
312
  case 'clickhouse':
286
313
  return exports.CLICKHOUSE;
314
+ // Derived dialects report their own name but run the parent server's
315
+ // session SQL. Without these, `getConstantsForDialect('timescaledb')` fell
316
+ // through to the MySQL constants and handed MySQL syntax to a PostgreSQL
317
+ // server.
318
+ case 'timescaledb':
319
+ case 'greenplum':
320
+ case 'yugabytedb':
321
+ return exports.POSTGRES;
322
+ case 'turso':
323
+ return exports.SQLITE;
324
+ case 'tidb':
325
+ return exports.MYSQL;
287
326
  default:
288
327
  return exports.MYSQL;
289
328
  }
290
329
  }
330
+ // ==================== Foreign key checks ====================
331
+ /**
332
+ * Dialects whose session-level foreign key switch is SQLite's PRAGMA.
333
+ * Turso/libSQL is SQLite over the wire and shares the pragma verbatim.
334
+ */
335
+ const SQLITE_FK_DIALECTS = new Set(['sqlite', 'turso']);
336
+ /**
337
+ * Dialects that implement MySQL's `SET FOREIGN_KEY_CHECKS` session variable.
338
+ *
339
+ * TiDB implements the variable for MySQL compatibility. SingleStore and
340
+ * Databricks extend the MySQL dialect class in this codebase but do not support
341
+ * enforced foreign keys at all, so they are deliberately absent - an explicit
342
+ * error naming the database beats a statement the server rejects.
343
+ */
344
+ const MYSQL_FK_DIALECTS = new Set(['mysql', 'mariadb', 'tidb']);
345
+ /**
346
+ * Dialects that implement PostgreSQL's `session_replication_role`.
347
+ *
348
+ * TimescaleDB and Greenplum are PostgreSQL servers; YugabyteDB and CockroachDB
349
+ * reimplement the parameter with the same `replica`/`origin` values. Trino,
350
+ * CrateDB, QuestDB, Exasol, Vertica and Redshift extend the Postgres dialect
351
+ * class here but are separate engines with no such parameter (Redshift never
352
+ * enforces foreign keys in the first place), so they are left out.
353
+ */
354
+ const POSTGRES_FK_DIALECTS = new Set([
355
+ 'postgres',
356
+ 'timescaledb',
357
+ 'greenplum',
358
+ 'yugabytedb',
359
+ 'cockroachdb',
360
+ ]);
361
+ /**
362
+ * Why a given dialect cannot switch foreign key enforcement for a whole
363
+ * session, and what to do instead. Used to build the thrown error message.
364
+ */
365
+ const FK_CHECKS_UNSUPPORTED_HINTS = {
366
+ mssql: 'Use ALTER TABLE <table> NOCHECK CONSTRAINT ALL per table instead.',
367
+ oracle: 'Use ALTER TABLE <table> DISABLE CONSTRAINT <name> per constraint instead.',
368
+ db2: 'Use SET INTEGRITY FOR <table> OFF / IMMEDIATE CHECKED per table instead.',
369
+ redshift: 'Redshift treats foreign keys as informational only and never enforces them.',
370
+ snowflake: 'Snowflake does not enforce foreign keys, so there is nothing to disable.',
371
+ clickhouse: 'ClickHouse has no foreign key constraints.',
372
+ duckdb: 'DuckDB has no session-level switch; drop and recreate the constraint instead.',
373
+ singlestore: 'SingleStore does not support enforced foreign key constraints.',
374
+ databricks: 'Databricks foreign keys are informational only and are never enforced.',
375
+ spanner: 'Spanner has no session-level switch; drop and recreate the constraint instead.',
376
+ };
377
+ /**
378
+ * Raised when a dialect has no session-level foreign key switch.
379
+ *
380
+ * Mirrors `UnsupportedSchemaObjectError` in ./schema-objects: name the database
381
+ * and say what to do instead, rather than returning SQL that fails at the
382
+ * server. Declared here (not imported) to keep this module dependency-free.
383
+ */
384
+ class UnsupportedForeignKeyChecksError extends Error {
385
+ constructor(dialect, hint) {
386
+ super(`Session-level foreign key checks are not supported on ${dialect}` +
387
+ `${hint ? `. ${hint}` : ''}`);
388
+ this.name = 'UnsupportedForeignKeyChecksError';
389
+ }
390
+ }
391
+ exports.UnsupportedForeignKeyChecksError = UnsupportedForeignKeyChecksError;
392
+ /**
393
+ * SQL that turns foreign key enforcement off/on for the current session.
394
+ *
395
+ * Every family has its own statement and they are not interchangeable:
396
+ * SQLite/Turso use a PRAGMA, the MySQL family a session variable, and the
397
+ * PostgreSQL family `session_replication_role`. Handing MySQL's
398
+ * `SET FOREIGN_KEY_CHECKS` to anything else - which is what the default branch
399
+ * used to do for every unlisted dialect, PostgreSQL included - produces a
400
+ * syntax error at the server, and the caller only finds out at runtime.
401
+ *
402
+ * The PostgreSQL form needs superuser, or a role granted
403
+ * `SET ON PARAMETER session_replication_role` (PostgreSQL 15+); on an ordinary
404
+ * application role the server answers `permission denied to set parameter`.
405
+ *
406
+ * @throws {UnsupportedForeignKeyChecksError} when the dialect has no
407
+ * session-level equivalent (SQL Server, Oracle and Db2 are per-table or
408
+ * per-constraint; Redshift, Snowflake, ClickHouse and friends do not enforce
409
+ * foreign keys at all).
410
+ */
411
+ function getForeignKeyChecksSQL(dialect, mode) {
412
+ if (SQLITE_FK_DIALECTS.has(dialect)) {
413
+ return mode === 'disable' ? exports.SQLITE.PRAGMA.foreign_keys.off : exports.SQLITE.PRAGMA.foreign_keys.on;
414
+ }
415
+ if (MYSQL_FK_DIALECTS.has(dialect)) {
416
+ return exports.MYSQL.FOREIGN_KEY_CHECKS[mode];
417
+ }
418
+ if (POSTGRES_FK_DIALECTS.has(dialect)) {
419
+ // COCKROACHDB carries its own copy of the constant; both resolve to the
420
+ // same `session_replication_role` statement.
421
+ const constants = dialect === 'cockroachdb' ? exports.COCKROACHDB : exports.POSTGRES;
422
+ const checks = constants.FOREIGN_KEY_CHECKS;
423
+ if (checks)
424
+ return checks[mode];
425
+ }
426
+ throw new UnsupportedForeignKeyChecksError(dialect, FK_CHECKS_UNSUPPORTED_HINTS[dialect]);
427
+ }
291
428
  /**
292
429
  * Transaction isolation level enum
293
430
  */