turbine-orm 0.81.0 → 0.90.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 (295) hide show
  1. package/README.md +26 -25
  2. package/dist/checkout.d.ts +27 -2
  3. package/dist/checkout.js +75 -4
  4. package/dist/cjs/checkout.d.ts +27 -2
  5. package/dist/cjs/checkout.js +76 -3
  6. package/dist/cjs/cli/code-first-tags.d.ts +62 -0
  7. package/dist/cjs/cli/code-first-tags.js +124 -0
  8. package/dist/cjs/cli/compile-query.js +9 -0
  9. package/dist/cjs/cli/config.d.ts +35 -6
  10. package/dist/cjs/cli/config.js +17 -1
  11. package/dist/cjs/cli/destructive.d.ts +7 -4
  12. package/dist/cjs/cli/destructive.js +224 -20
  13. package/dist/cjs/cli/error-catalog.js +36 -0
  14. package/dist/cjs/cli/error-text.d.ts +15 -0
  15. package/dist/cjs/cli/error-text.js +40 -0
  16. package/dist/cjs/cli/index.d.ts +62 -4
  17. package/dist/cjs/cli/index.js +568 -108
  18. package/dist/cjs/cli/local-server-guard.d.ts +53 -0
  19. package/dist/cjs/cli/local-server-guard.js +119 -0
  20. package/dist/cjs/cli/local-server-output.d.ts +41 -0
  21. package/dist/cjs/cli/local-server-output.js +103 -0
  22. package/dist/cjs/cli/mcp.d.ts +8 -0
  23. package/dist/cjs/cli/mcp.js +121 -32
  24. package/dist/cjs/cli/migrate.d.ts +113 -5
  25. package/dist/cjs/cli/migrate.js +270 -21
  26. package/dist/cjs/cli/observe.d.ts +6 -1
  27. package/dist/cjs/cli/observe.js +85 -55
  28. package/dist/cjs/cli/pii-predicate-guard.d.ts +43 -23
  29. package/dist/cjs/cli/pii-predicate-guard.js +98 -37
  30. package/dist/cjs/cli/prisma-resolve.js +17 -13
  31. package/dist/cjs/cli/prisma-schema.js +12 -4
  32. package/dist/cjs/cli/studio-ui.generated.js +1 -1
  33. package/dist/cjs/cli/studio.d.ts +14 -2
  34. package/dist/cjs/cli/studio.js +244 -69
  35. package/dist/cjs/cli/ui.d.ts +1 -1
  36. package/dist/cjs/client.d.ts +558 -85
  37. package/dist/cjs/client.js +1270 -395
  38. package/dist/cjs/connection-guard.d.ts +13 -0
  39. package/dist/cjs/connection-guard.js +28 -0
  40. package/dist/cjs/connection-url.d.ts +51 -16
  41. package/dist/cjs/connection-url.js +67 -34
  42. package/dist/cjs/diagnostics.d.ts +81 -0
  43. package/dist/cjs/diagnostics.js +147 -0
  44. package/dist/cjs/dialect.d.ts +449 -20
  45. package/dist/cjs/dialect.js +117 -76
  46. package/dist/cjs/engine-config.d.ts +7 -6
  47. package/dist/cjs/errors.d.ts +126 -6
  48. package/dist/cjs/errors.js +256 -13
  49. package/dist/cjs/generate.d.ts +57 -7
  50. package/dist/cjs/generate.js +635 -279
  51. package/dist/cjs/global-filters-config.d.ts +59 -0
  52. package/dist/cjs/global-filters-config.js +367 -0
  53. package/dist/cjs/index.d.ts +9 -4
  54. package/dist/cjs/index.js +10 -2
  55. package/dist/cjs/introspect.d.ts +31 -6
  56. package/dist/cjs/introspect.js +108 -50
  57. package/dist/cjs/log-codes.d.ts +12 -0
  58. package/dist/cjs/log-codes.js +77 -0
  59. package/dist/cjs/logger.d.ts +87 -0
  60. package/dist/cjs/logger.js +98 -0
  61. package/dist/cjs/mssql.d.ts +8 -5
  62. package/dist/cjs/mssql.js +352 -65
  63. package/dist/cjs/mysql.d.ts +3 -5
  64. package/dist/cjs/mysql.js +420 -70
  65. package/dist/cjs/nested-write.d.ts +3 -0
  66. package/dist/cjs/nested-write.js +179 -114
  67. package/dist/cjs/pipeline-submittable.d.ts +12 -0
  68. package/dist/cjs/pipeline-submittable.js +118 -44
  69. package/dist/cjs/pipeline.js +21 -26
  70. package/dist/cjs/powdb-introspect.d.ts +5 -2
  71. package/dist/cjs/powdb-introspect.js +20 -15
  72. package/dist/cjs/powdb-shared.d.ts +36 -5
  73. package/dist/cjs/powdb-shared.js +67 -8
  74. package/dist/cjs/powdb.d.ts +4 -0
  75. package/dist/cjs/powdb.js +183 -51
  76. package/dist/cjs/powql.d.ts +394 -51
  77. package/dist/cjs/powql.js +1829 -284
  78. package/dist/cjs/prisma-compat.d.ts +23 -15
  79. package/dist/cjs/prisma-compat.js +507 -372
  80. package/dist/cjs/query/aggregates.d.ts +17 -1
  81. package/dist/cjs/query/aggregates.js +261 -29
  82. package/dist/cjs/query/batched-loader.d.ts +25 -6
  83. package/dist/cjs/query/batched-loader.js +103 -20
  84. package/dist/cjs/query/builder.d.ts +325 -184
  85. package/dist/cjs/query/builder.js +1452 -490
  86. package/dist/cjs/query/column-ref.d.ts +61 -0
  87. package/dist/cjs/query/column-ref.js +73 -0
  88. package/dist/cjs/query/compound-unique.d.ts +21 -0
  89. package/dist/cjs/query/compound-unique.js +98 -18
  90. package/dist/cjs/query/deferred.d.ts +53 -16
  91. package/dist/cjs/query/expr.d.ts +217 -0
  92. package/dist/cjs/query/expr.js +859 -0
  93. package/dist/cjs/query/filters.d.ts +155 -53
  94. package/dist/cjs/query/filters.js +613 -76
  95. package/dist/cjs/query/index.d.ts +2 -0
  96. package/dist/cjs/query/index.js +7 -1
  97. package/dist/cjs/query/json-value.d.ts +43 -0
  98. package/dist/cjs/query/json-value.js +59 -0
  99. package/dist/cjs/query/normalize-args.d.ts +87 -0
  100. package/dist/cjs/query/normalize-args.js +527 -0
  101. package/dist/cjs/query/option-surface.d.ts +16 -4
  102. package/dist/cjs/query/option-surface.js +57 -14
  103. package/dist/cjs/query/relation-names.d.ts +14 -0
  104. package/dist/cjs/query/relation-names.js +77 -18
  105. package/dist/cjs/query/relations.d.ts +30 -3
  106. package/dist/cjs/query/relations.js +219 -63
  107. package/dist/cjs/query/row-lock.d.ts +49 -0
  108. package/dist/cjs/query/row-lock.js +138 -0
  109. package/dist/cjs/query/sql-comment.d.ts +161 -0
  110. package/dist/cjs/query/sql-comment.js +381 -0
  111. package/dist/cjs/query/stream-idle.d.ts +132 -0
  112. package/dist/cjs/query/stream-idle.js +212 -0
  113. package/dist/cjs/query/table-client.d.ts +101 -0
  114. package/dist/cjs/query/table-client.js +74 -0
  115. package/dist/cjs/query/types.d.ts +677 -298
  116. package/dist/cjs/query/utils.d.ts +105 -6
  117. package/dist/cjs/query/utils.js +426 -19
  118. package/dist/cjs/query/warn-registry.d.ts +18 -0
  119. package/dist/cjs/query/warn-registry.js +18 -0
  120. package/dist/cjs/query/where-compile.d.ts +138 -14
  121. package/dist/cjs/query/where-compile.js +513 -29
  122. package/dist/cjs/query/where.d.ts +159 -59
  123. package/dist/cjs/query/where.js +716 -246
  124. package/dist/cjs/query/writes.d.ts +112 -50
  125. package/dist/cjs/query/writes.js +1498 -200
  126. package/dist/cjs/query-events.d.ts +4 -2
  127. package/dist/cjs/query-events.js +3 -1
  128. package/dist/cjs/realtime.d.ts +7 -3
  129. package/dist/cjs/realtime.js +13 -2
  130. package/dist/cjs/schema-builder.d.ts +55 -4
  131. package/dist/cjs/schema-builder.js +382 -18
  132. package/dist/cjs/schema-metadata.d.ts +21 -1
  133. package/dist/cjs/schema-metadata.js +29 -7
  134. package/dist/cjs/schema-sql.d.ts +75 -5
  135. package/dist/cjs/schema-sql.js +497 -45
  136. package/dist/cjs/schema.d.ts +26 -5
  137. package/dist/cjs/schema.js +110 -13
  138. package/dist/cjs/sql-placeholders.d.ts +56 -0
  139. package/dist/cjs/sql-placeholders.js +204 -0
  140. package/dist/cjs/sqlite.d.ts +75 -20
  141. package/dist/cjs/sqlite.js +593 -95
  142. package/dist/cjs/supplied-pool-types.d.ts +48 -0
  143. package/dist/cjs/supplied-pool-types.js +256 -0
  144. package/dist/cjs/transaction-control.d.ts +51 -0
  145. package/dist/cjs/transaction-control.js +316 -0
  146. package/dist/cjs/transaction-state.d.ts +342 -0
  147. package/dist/cjs/transaction-state.js +707 -0
  148. package/dist/cjs/typed-sql.d.ts +37 -3
  149. package/dist/cjs/typed-sql.js +102 -8
  150. package/dist/cli/code-first-tags.d.ts +62 -0
  151. package/dist/cli/code-first-tags.js +120 -0
  152. package/dist/cli/compile-query.js +9 -0
  153. package/dist/cli/config.d.ts +35 -6
  154. package/dist/cli/config.js +16 -1
  155. package/dist/cli/destructive.d.ts +7 -4
  156. package/dist/cli/destructive.js +224 -20
  157. package/dist/cli/error-catalog.js +36 -0
  158. package/dist/cli/error-text.d.ts +15 -0
  159. package/dist/cli/error-text.js +37 -0
  160. package/dist/cli/index.d.ts +62 -4
  161. package/dist/cli/index.js +569 -112
  162. package/dist/cli/local-server-guard.d.ts +53 -0
  163. package/dist/cli/local-server-guard.js +113 -0
  164. package/dist/cli/local-server-output.d.ts +41 -0
  165. package/dist/cli/local-server-output.js +98 -0
  166. package/dist/cli/mcp.d.ts +8 -0
  167. package/dist/cli/mcp.js +121 -34
  168. package/dist/cli/migrate.d.ts +113 -5
  169. package/dist/cli/migrate.js +261 -21
  170. package/dist/cli/observe.d.ts +6 -1
  171. package/dist/cli/observe.js +84 -54
  172. package/dist/cli/pii-predicate-guard.d.ts +43 -23
  173. package/dist/cli/pii-predicate-guard.js +100 -35
  174. package/dist/cli/prisma-resolve.js +15 -11
  175. package/dist/cli/prisma-schema.js +12 -4
  176. package/dist/cli/studio-ui.generated.js +1 -1
  177. package/dist/cli/studio.d.ts +14 -2
  178. package/dist/cli/studio.js +246 -71
  179. package/dist/cli/ui.d.ts +1 -1
  180. package/dist/client.d.ts +558 -85
  181. package/dist/client.js +1275 -400
  182. package/dist/connection-guard.d.ts +13 -0
  183. package/dist/connection-guard.js +27 -0
  184. package/dist/connection-url.d.ts +51 -16
  185. package/dist/connection-url.js +63 -34
  186. package/dist/diagnostics.d.ts +81 -0
  187. package/dist/diagnostics.js +144 -0
  188. package/dist/dialect.d.ts +449 -20
  189. package/dist/dialect.js +115 -43
  190. package/dist/engine-config.d.ts +7 -6
  191. package/dist/errors.d.ts +126 -6
  192. package/dist/errors.js +252 -12
  193. package/dist/generate.d.ts +57 -7
  194. package/dist/generate.js +635 -281
  195. package/dist/global-filters-config.d.ts +59 -0
  196. package/dist/global-filters-config.js +361 -0
  197. package/dist/index.d.ts +9 -4
  198. package/dist/index.js +4 -2
  199. package/dist/introspect.d.ts +31 -6
  200. package/dist/introspect.js +106 -50
  201. package/dist/log-codes.d.ts +12 -0
  202. package/dist/log-codes.js +74 -0
  203. package/dist/logger.d.ts +87 -0
  204. package/dist/logger.js +93 -0
  205. package/dist/mssql.d.ts +8 -5
  206. package/dist/mssql.js +354 -67
  207. package/dist/mysql.d.ts +3 -5
  208. package/dist/mysql.js +423 -73
  209. package/dist/nested-write.d.ts +3 -0
  210. package/dist/nested-write.js +177 -112
  211. package/dist/pipeline-submittable.d.ts +12 -0
  212. package/dist/pipeline-submittable.js +117 -44
  213. package/dist/pipeline.js +21 -26
  214. package/dist/powdb-introspect.d.ts +5 -2
  215. package/dist/powdb-introspect.js +21 -16
  216. package/dist/powdb-shared.d.ts +36 -5
  217. package/dist/powdb-shared.js +65 -8
  218. package/dist/powdb.d.ts +4 -0
  219. package/dist/powdb.js +183 -51
  220. package/dist/powql.d.ts +394 -51
  221. package/dist/powql.js +1836 -291
  222. package/dist/prisma-compat.d.ts +23 -15
  223. package/dist/prisma-compat.js +508 -373
  224. package/dist/query/aggregates.d.ts +17 -1
  225. package/dist/query/aggregates.js +263 -32
  226. package/dist/query/batched-loader.d.ts +25 -6
  227. package/dist/query/batched-loader.js +101 -21
  228. package/dist/query/builder.d.ts +325 -184
  229. package/dist/query/builder.js +1458 -495
  230. package/dist/query/column-ref.d.ts +61 -0
  231. package/dist/query/column-ref.js +66 -0
  232. package/dist/query/compound-unique.d.ts +21 -0
  233. package/dist/query/compound-unique.js +97 -19
  234. package/dist/query/deferred.d.ts +53 -16
  235. package/dist/query/expr.d.ts +217 -0
  236. package/dist/query/expr.js +848 -0
  237. package/dist/query/filters.d.ts +155 -53
  238. package/dist/query/filters.js +597 -72
  239. package/dist/query/index.d.ts +2 -0
  240. package/dist/query/index.js +4 -0
  241. package/dist/query/json-value.d.ts +43 -0
  242. package/dist/query/json-value.js +54 -0
  243. package/dist/query/normalize-args.d.ts +87 -0
  244. package/dist/query/normalize-args.js +517 -0
  245. package/dist/query/option-surface.d.ts +16 -4
  246. package/dist/query/option-surface.js +56 -13
  247. package/dist/query/relation-names.d.ts +14 -0
  248. package/dist/query/relation-names.js +77 -19
  249. package/dist/query/relations.d.ts +30 -3
  250. package/dist/query/relations.js +220 -67
  251. package/dist/query/row-lock.d.ts +49 -0
  252. package/dist/query/row-lock.js +131 -0
  253. package/dist/query/sql-comment.d.ts +161 -0
  254. package/dist/query/sql-comment.js +374 -0
  255. package/dist/query/stream-idle.d.ts +132 -0
  256. package/dist/query/stream-idle.js +203 -0
  257. package/dist/query/table-client.d.ts +101 -0
  258. package/dist/query/table-client.js +70 -0
  259. package/dist/query/types.d.ts +677 -298
  260. package/dist/query/utils.d.ts +105 -6
  261. package/dist/query/utils.js +414 -18
  262. package/dist/query/warn-registry.d.ts +18 -0
  263. package/dist/query/warn-registry.js +18 -0
  264. package/dist/query/where-compile.d.ts +138 -14
  265. package/dist/query/where-compile.js +508 -31
  266. package/dist/query/where.d.ts +159 -59
  267. package/dist/query/where.js +711 -248
  268. package/dist/query/writes.d.ts +112 -50
  269. package/dist/query/writes.js +1496 -202
  270. package/dist/query-events.d.ts +4 -2
  271. package/dist/query-events.js +3 -1
  272. package/dist/realtime.d.ts +7 -3
  273. package/dist/realtime.js +13 -2
  274. package/dist/schema-builder.d.ts +55 -4
  275. package/dist/schema-builder.js +381 -18
  276. package/dist/schema-metadata.d.ts +21 -1
  277. package/dist/schema-metadata.js +28 -7
  278. package/dist/schema-sql.d.ts +75 -5
  279. package/dist/schema-sql.js +494 -44
  280. package/dist/schema.d.ts +26 -5
  281. package/dist/schema.js +109 -13
  282. package/dist/sql-placeholders.d.ts +56 -0
  283. package/dist/sql-placeholders.js +200 -0
  284. package/dist/sqlite.d.ts +75 -20
  285. package/dist/sqlite.js +597 -99
  286. package/dist/supplied-pool-types.d.ts +48 -0
  287. package/dist/supplied-pool-types.js +247 -0
  288. package/dist/transaction-control.d.ts +51 -0
  289. package/dist/transaction-control.js +311 -0
  290. package/dist/transaction-state.d.ts +342 -0
  291. package/dist/transaction-state.js +696 -0
  292. package/dist/typed-sql.d.ts +37 -3
  293. package/dist/typed-sql.js +100 -8
  294. package/package.json +7 -4
  295. package/skills/turbine-orm/SKILL.md +56 -6
package/dist/dialect.d.ts CHANGED
@@ -5,7 +5,8 @@
5
5
  * PostgreSQL-native by default, but query generation now depends on this
6
6
  * contract for the SQL primitives that vary across MySQL and SQLite.
7
7
  */
8
- import type { WithOptions } from './query/types.js';
8
+ import type { TurbineLogger } from './logger.js';
9
+ import type { RowLockMode, WithOptions } from './query/types.js';
9
10
  import { type RelationDef, type SchemaMetadata, type TableMetadata } from './schema.js';
10
11
  export type DialectName = 'postgresql' | 'mysql' | 'sqlite' | (string & {});
11
12
  /**
@@ -52,6 +53,33 @@ export interface BulkInsertStatementInput {
52
53
  */
53
54
  requireRowValues?: boolean;
54
55
  }
56
+ /**
57
+ * The rendered references a multi-row upsert's conflict-UPDATE reads through:
58
+ * the existing row (`"daily_stats"`, SQL Server's MERGE alias `T`) and the
59
+ * proposed row (`EXCLUDED`, `excluded`, MySQL's row alias, `S`). The
60
+ * statement hook names them, because it is the statement that declares them.
61
+ */
62
+ export interface BulkUpsertRefs {
63
+ readonly target: string;
64
+ readonly incoming: string;
65
+ }
66
+ /** The compiled conflict-UPDATE of a multi-row upsert. */
67
+ export interface BulkUpsertUpdate {
68
+ /** `col = expr` assignments, columns bare on the left. */
69
+ readonly setClauses: string[];
70
+ /** A predicate on the existing row (no `WHERE` keyword), or `null`. */
71
+ readonly where: string | null;
72
+ }
73
+ export interface BulkUpsertStatementInput extends BulkInsertStatementInput {
74
+ /** SQL-ready quoted conflict-target columns (a primary key or one unique key). */
75
+ conflictColumns: string[];
76
+ /**
77
+ * Compile the conflict-UPDATE. Called once, AFTER the row values are bound,
78
+ * with the statement's params so its own placeholders continue after them.
79
+ * `null` skips conflicting rows instead (`DO NOTHING`).
80
+ */
81
+ update: ((params: unknown[], refs: BulkUpsertRefs) => BulkUpsertUpdate) | null;
82
+ }
55
83
  export interface DefaultValuesInsertStatementInput {
56
84
  /** SQL-ready quoted table name. */
57
85
  table: string;
@@ -66,6 +94,37 @@ export interface DefaultValuesInsertStatementInput {
66
94
  /** Optional SQL-ready RETURNING selection. */
67
95
  returning?: ReturningSelection;
68
96
  }
97
+ /**
98
+ * Input for {@link Dialect.buildJsonPathEquals}. The hook runs on the SQL build
99
+ * AND on the cache-hit param-collect pass with the same `value`, so it binds
100
+ * the same parameters in the same order on both; on the collect pass `bind`
101
+ * returns an empty string and the returned SQL is discarded.
102
+ */
103
+ export interface JsonPathEqualsInput {
104
+ /** The qualified JSON column expression. */
105
+ readonly column: string;
106
+ /**
107
+ * Placeholder of the already-bound JSONPath for `path` (see `encodePath`),
108
+ * or `undefined` for a whole-document `equals` (no `path`), which compares
109
+ * the column itself.
110
+ */
111
+ readonly pathRef: string | undefined;
112
+ /** The path segments as the caller wrote them; empty for a whole-document `equals`. */
113
+ readonly path: readonly (string | number)[];
114
+ /**
115
+ * The operand: a string, number, boolean, bigint, null, array or object.
116
+ * A Date arrives as its ISO string (the form JSON stores it in); functions,
117
+ * symbols, column references and non-finite numbers are refused before the
118
+ * hook runs.
119
+ */
120
+ readonly value: unknown;
121
+ /** The column as it should read in an error message. */
122
+ readonly label: string;
123
+ /** Bind one parameter and return its placeholder. */
124
+ bind(value: unknown): string;
125
+ /** The engine's JSONPath string for a path, the same encoding `pathRef` carries. */
126
+ encodePath(path: readonly (string | number)[]): string;
127
+ }
69
128
  /**
70
129
  * The cast/decode pair for one JSON-divergent column type. See
71
130
  * {@link Dialect.jsonWireRule}. The two halves MUST agree: a cast with no
@@ -278,8 +337,9 @@ export interface PartitionLimitInput {
278
337
  * dialect. **Param-push ordering contract:** the override MUST push values to
279
338
  * {@link params} in the same order the builder's collect path expects so the SQL
280
339
  * cache and pipeline batching stay in sync -
281
- * - to-many with `limit`/`orderBy` (the "wrap" path) and manyToMany:
282
- * `buildWhere(...)` → push `limit` → `recurse(...)` for each nested relation;
340
+ * - to-many with `limit`/`offset`/`orderBy` (the "wrap" path) and manyToMany:
341
+ * `buildWhere(...)` → push `limit` → push `offset` → `recurse(...)` for each
342
+ * nested relation;
283
343
  * - everything else (to-one, unordered/unlimited to-many): `recurse(...)` for each
284
344
  * nested relation → `buildWhere(...)` (no limit param).
285
345
  */
@@ -317,9 +377,223 @@ export interface RelationSubqueryContext {
317
377
  */
318
378
  recurse(relDef: RelationDef, spec: true | WithOptions, parentRef: string, depth: number, path: string[]): string;
319
379
  }
380
+ /**
381
+ * What an engine can do, stated in full by every engine dialect.
382
+ *
383
+ * Every engine dialect is built by spreading `postgresDialect`, so a flag or
384
+ * hook added to PostgreSQL is inherited by every engine that does not override
385
+ * it (the inheritance trap). This object closes the trap for the questions it
386
+ * answers: each engine dialect sets its OWN `capabilities` as a fresh object
387
+ * literal checked with `satisfies EngineCapabilities`, so adding a key here is
388
+ * a compile error in every engine file until each one decides, and a unit test
389
+ * refuses an engine whose `capabilities` is inherited or shared.
390
+ *
391
+ * Code asks these questions instead of testing `dialect.name`; a source scan
392
+ * (src/test/capabilities-guard.test.ts) refuses a new engine-name comparison
393
+ * outside a short, commented allowlist. Rendering differences are not
394
+ * capabilities: they belong in the dialect's hooks (a few still switch on the
395
+ * name, allowlisted, until engines stop spreading `postgresDialect`).
396
+ */
397
+ export interface EngineCapabilities {
398
+ /** `SELECT DISTINCT ON (...)`: findMany `distinct` and groupBy `distinctOn`. Else E017. */
399
+ readonly distinctOn: boolean;
400
+ /**
401
+ * The positional relation encoding (`json_build_array`, see
402
+ * {@link Dialect.buildJsonArray}). One flag answers both questions about it:
403
+ * it is the default `jsonEncoding` where true, and refused (E017) where
404
+ * false, so the default can never pick an encoding the builder refuses.
405
+ */
406
+ readonly positionalJson: boolean;
407
+ /** The `NULLS FIRST` / `NULLS LAST` ordering clause. Explicit `nulls` placement is E017 without it. */
408
+ readonly nullsOrderingClause: boolean;
409
+ /**
410
+ * NULL sorts after every value in an ascending order (PostgreSQL), rather
411
+ * than before it (SQLite, MySQL, SQL Server). A cursor seek places NULL keys
412
+ * where the engine sorts them.
413
+ */
414
+ readonly nullsSortHigh: boolean;
415
+ /** `mode: 'insensitive'` on `in` / `notIn`, which folds every list element in SQL. Else E017. */
416
+ readonly insensitiveInList: boolean;
417
+ /**
418
+ * How two whole JSON documents compare:
419
+ * - `'jsonb'`: as jsonb, in the where compiler's own PostgreSQL form
420
+ * (`::jsonb = $1::jsonb`, `#>` path equality); the dialect takes no
421
+ * {@link Dialect.buildJsonPathEquals}.
422
+ * - `'exact'`: exactly, key order and whitespace aside, through the
423
+ * dialect's `buildJsonPathEquals` (MySQL).
424
+ * - `'text'`: not exactly (SQLite, SQL Server), so a bare array operand and
425
+ * a document `not` are refused (E017) rather than compared as text. A
426
+ * path `equals` still uses the dialect's `buildJsonPathEquals` when it
427
+ * has one.
428
+ */
429
+ readonly jsonDocumentEquality: 'jsonb' | 'exact' | 'text';
430
+ /**
431
+ * JSON path extraction returns SQL-typed values: a JSON number as a number,
432
+ * `true` / `false` as 1 / 0 (SQLite). A path `equals` then binds a number as
433
+ * a number and refuses a boolean.
434
+ */
435
+ readonly jsonExtractTyped: boolean;
436
+ /**
437
+ * A JSON path range filter (`gt`, `lte`, ...) casts the extracted value to an
438
+ * exact `numeric` (`(expr)::numeric`, PostgreSQL); without it the cast is the
439
+ * dialect's float {@link Dialect.castAggregate}.
440
+ */
441
+ readonly jsonExactNumericCast: boolean;
442
+ /**
443
+ * A number compared with a text column converts the stored TEXT to a number
444
+ * (MySQL: `'0zz' = 0` is true), so a number, bigint or boolean bound against
445
+ * a text column binds as its text instead.
446
+ */
447
+ readonly numericTextComparison: boolean;
448
+ /**
449
+ * Declared foreign keys are always enforced, so the mass-mutation guard may
450
+ * trust that a non-null foreign key points at a row. SQLite enforces them
451
+ * only when the connection turned `foreign_keys` on.
452
+ */
453
+ readonly enforcesForeignKeys: boolean;
454
+ /**
455
+ * The batched relation loader pushes a per-parent `limit` into its follow-up
456
+ * query through {@link Dialect.buildPartitionLimit}. Without it the loader
457
+ * fetches every matching child and slices client-side.
458
+ */
459
+ readonly partitionLimitPushdown: boolean;
460
+ /**
461
+ * The `utcTimestamps` rewrite covers zone-less `timestamp` columns and raw
462
+ * `Date` parameters, as well as `date` columns (which take the UTC day on
463
+ * every SQL engine). PostgreSQL only: MySQL reads a zone-less literal in the
464
+ * session time zone. A table with untyped columns is reported where true.
465
+ */
466
+ readonly utcTimestampRewrite: boolean;
467
+ /**
468
+ * Bound values inside an update expression carry a `::type` cast (the target
469
+ * column's type, `::numeric`, `::int8`), because the driver sends parameters
470
+ * untyped and the server would infer `text`. PostgreSQL only.
471
+ */
472
+ readonly paramTypeCasts: boolean;
473
+ /**
474
+ * An enum is a named database type: `CREATE TYPE ... AS ENUM` in DDL and a
475
+ * `::"EnumName"` cast on writes and filters. Elsewhere an enum column is
476
+ * declared with its labels on the column ({@link Dialect.buildEnumColumn}).
477
+ */
478
+ readonly namedEnumTypes: boolean;
479
+ /**
480
+ * Which columns refuse a plain object or an array written to them (E003):
481
+ * - `'pg-scalars'`: PostgreSQL's scalar types by their PostgreSQL names,
482
+ * text types included.
483
+ * - `'scalars-and-text'`: every non-text scalar type and the text types,
484
+ * for an engine with a JSON column type (MySQL).
485
+ * - `'scalars'`: non-text scalar types only; a text column holds
486
+ * serialized JSON on an engine with no JSON type (SQLite, SQL Server).
487
+ */
488
+ readonly structuredValueColumns: 'pg-scalars' | 'scalars-and-text' | 'scalars';
489
+ /**
490
+ * The most bind parameters one statement may carry; `Infinity` for no
491
+ * known limit. Past PostgreSQL's 65535 node-postgres does not refuse: the
492
+ * count wraps and the server answers with a protocol error that reads like
493
+ * a lost connection.
494
+ */
495
+ readonly maxBindParameters: number;
496
+ /**
497
+ * The most rows one plain `INSERT ... VALUES` may carry; `Infinity` for no
498
+ * limit beyond the bind-parameter one (SQL Server: 1000, error 10738 past
499
+ * it). An `onConflict` statement that reads its rows as a derived table is
500
+ * not bound by it.
501
+ */
502
+ readonly maxInsertRows: number;
503
+ /**
504
+ * What a single-statement upsert conflicts on. `'explicit'`: the conflict
505
+ * target it names. `'any-unique-key'`: whichever unique key collides first
506
+ * (MySQL `ON DUPLICATE KEY UPDATE`), so a `create` that can collide on a key
507
+ * `where` does not pin is looked up first, and a multi-row upsert must target
508
+ * the only key its rows can violate.
509
+ */
510
+ readonly upsertConflictTarget: 'explicit' | 'any-unique-key';
511
+ /**
512
+ * How an UPDATE's SET list reads columns. `'snapshot'`: every expression
513
+ * reads the row as it was. `'left-to-right'` (MySQL): a later expression
514
+ * reads an earlier assignment, so Turbine orders the clauses.
515
+ */
516
+ readonly setClauseOrder: 'snapshot' | 'left-to-right';
517
+ /** The reads inside a reselect write's transaction take `FOR UPDATE`, so a concurrent write waits. */
518
+ readonly reselectLocksRows: boolean;
519
+ /**
520
+ * The operator that divides an integer by an integer with truncation: `/`
521
+ * (PostgreSQL, SQLite, SQL Server) or `DIV` (MySQL, whose `/` is decimal).
522
+ */
523
+ readonly integerDivision: '/' | 'DIV';
524
+ /** Update expressions (`expr.*`, `col()` in update data) compile here. Else E017. */
525
+ readonly updateExpressions: boolean;
526
+ /**
527
+ * One multi-row upsert statement applies two rows whose keys are equal only
528
+ * under the column's collation as an insert and an update of one row,
529
+ * rather than refusing (PostgreSQL 21000, SQL Server 8672). Turbine detects
530
+ * it afterwards, so the statement runs in a transaction it can roll back.
531
+ */
532
+ readonly bulkUpsertAppliesRepeatedKeys: boolean;
533
+ /** `$transaction({ readOnly: true })`: `READ ONLY` after the dialect's BEGIN. Else E017. */
534
+ readonly readOnlyTransactions: boolean;
535
+ /**
536
+ * Server settings as connection parameters (`options=-c name=value`), which
537
+ * is how `statementTimeoutMs` is applied. Else E017.
538
+ */
539
+ readonly connectionParameters: boolean;
540
+ /**
541
+ * A timed-out statement can be cancelled on the server with a protocol
542
+ * cancel request (node-postgres pools), so a timeout can report
543
+ * `outcome: 'not-executed'`.
544
+ */
545
+ readonly backendCancel: boolean;
546
+ /**
547
+ * A transaction can bound its own idle time on the server
548
+ * (`idle_in_transaction_session_timeout`), which a cursor stream's BEGIN sets
549
+ * as the backstop for its idle timeout.
550
+ */
551
+ readonly idleTransactionTimeout: boolean;
552
+ /**
553
+ * A failed statement aborts the whole transaction until it rolls back
554
+ * (PostgreSQL), so the next statement is refused locally rather than sent.
555
+ */
556
+ readonly abortsTransactionOnError: boolean;
557
+ /**
558
+ * What connection object backs a transaction, for `tx.$connection()` and
559
+ * Turbine's own type parsers: `'pg-compatible'` (a node-postgres client or a
560
+ * driver with its interface), `'engine-driver'` (the engine's own driver
561
+ * behind Turbine's pool shim), or `'none'` (no driver connection, E017).
562
+ */
563
+ readonly connectionDriver: 'pg-compatible' | 'engine-driver' | 'none';
564
+ /**
565
+ * The engine prepares every distinct statement text on the server, under a
566
+ * server-wide cap (MySQL's `max_prepared_stmt_count`), so per-statement text
567
+ * such as `sqlComment.dynamic` would exhaust it. Else allowed.
568
+ */
569
+ readonly preparesEveryStatement: boolean;
570
+ /**
571
+ * The SQL grammar the engine's statements are written in, which picks the
572
+ * lexer that screens raw SQL for transaction control (`COMMIT` inside
573
+ * `$transaction` and the rest). `null` is no SQL lexer (PowDB speaks PowQL),
574
+ * so nothing is screened.
575
+ */
576
+ readonly statementSyntax: 'postgresql' | 'mysql' | 'sqlite' | 'mssql' | null;
577
+ /**
578
+ * A column's inline `REFERENCES` creates a foreign key. MySQL parses one and
579
+ * ignores it, so its foreign keys are table-level `FOREIGN KEY` clauses.
580
+ */
581
+ readonly inlineForeignKeys: boolean;
582
+ /**
583
+ * An unbounded text or binary column can be a key (primary, unique, index,
584
+ * foreign). MySQL and SQL Server refuse that, so a keyed `text` / `bytea`
585
+ * column is declared with a bounded type there.
586
+ */
587
+ readonly unboundedTextKeys: boolean;
588
+ }
320
589
  export interface Dialect {
321
590
  /** Dialect identifier. */
322
591
  readonly name: DialectName;
592
+ /**
593
+ * What this engine can do. Every engine dialect sets its OWN object, never
594
+ * PostgreSQL's by inheritance; see {@link EngineCapabilities}.
595
+ */
596
+ readonly capabilities: EngineCapabilities;
323
597
  /**
324
598
  * How write statements surface their affected rows. PostgreSQL uses
325
599
  * `'returning'`; the executor branches on this so non-RETURNING engines
@@ -344,9 +618,9 @@ export interface Dialect {
344
618
  * `jsonEncoding: 'positional'` mode. Emitting `json_build_array(v1, v2, …)`
345
619
  * instead of `json_build_object('k1', v1, …)` drops every repeated key name
346
620
  * from every nested object of every row (the decode side maps positions back
347
- * to keys via a build-time shape descriptor). Postgres-only in v1, other
348
- * engines never reach this because the builder gates positional encoding to
349
- * `dialect.name === 'postgresql'`, so the method is optional on the contract.
621
+ * to keys via a build-time shape descriptor). Reached only on an engine
622
+ * whose {@link EngineCapabilities.positionalJson} is true (PostgreSQL), so
623
+ * the method is optional on the contract.
350
624
  */
351
625
  buildJsonArray?(exprs: string[]): string;
352
626
  /** Build a JSON array aggregation expression with a dialect-specific empty-array fallback. */
@@ -486,6 +760,39 @@ export interface Dialect {
486
760
  * lateral plan (else E017). PostgreSQL only in this release.
487
761
  */
488
762
  readonly supportsLateralJoin?: boolean;
763
+ /**
764
+ * The row-lock strengths a locking read (`lock`) may use on this dialect.
765
+ * The builder appends `FOR <mode> OF <table>` after pagination for a mode in
766
+ * this list and throws {@link UnsupportedFeatureError} (E017) for any other.
767
+ * Optional: absent means none.
768
+ *
769
+ * Every engine dialect sets this as its OWN property, never by inheritance:
770
+ * each one spreads `postgresDialect`, which allows all four, so an engine
771
+ * that forgot it would silently emit PostgreSQL's locking clause. A unit test
772
+ * asserts `Object.hasOwn` for every engine.
773
+ */
774
+ readonly rowLockModes?: readonly RowLockMode[];
775
+ /**
776
+ * Whether `_percentile` aggregates compile here (`percentile_cont` /
777
+ * `percentile_disc ... WITHIN GROUP (ORDER BY ...)`). Optional: absent means
778
+ * E017. Set as an own property on every engine dialect, like
779
+ * {@link rowLockModes}.
780
+ */
781
+ readonly supportsPercentileAggregates?: boolean;
782
+ /**
783
+ * Whether `createMany({ onConflict })` (a multi-row upsert on one named
784
+ * unique key) compiles here. Optional: absent means E017. Set as an own
785
+ * property on every engine dialect, like {@link rowLockModes}.
786
+ */
787
+ readonly supportsBulkUpsert?: boolean;
788
+ /**
789
+ * The alias this dialect's upsert statement gives its target table (SQL
790
+ * Server's `MERGE ... AS T`), which the conflict-UPDATE's column references
791
+ * must use. Absent: the statement names the table directly and references
792
+ * are qualified with the table name. Set only by an engine whose upsert
793
+ * aliases its target, so no other engine can inherit it.
794
+ */
795
+ readonly upsertTargetAlias?: string;
489
796
  /**
490
797
  * How this dialect surfaces a query plan for a compiled SELECT. When present,
491
798
  * `QueryInterface.explain()` prepends `prefix` (plus a single space) to the
@@ -526,6 +833,15 @@ export interface Dialect {
526
833
  buildDefaultValuesInsertStatement?(input: DefaultValuesInsertStatementInput): string;
527
834
  /** Build an upsert statement. Inputs are SQL-ready quoted fragments. */
528
835
  buildUpsertStatement(input: UpsertStatementInput): string;
836
+ /**
837
+ * Build a multi-row upsert (`createMany({ onConflict })`): insert the rows
838
+ * and, for each row whose conflict key already exists, run `input.update`'s
839
+ * assignments or skip it. Returns the statement and its params, the row
840
+ * values first. Reached only when {@link supportsBulkUpsert} is true, and
841
+ * every engine that sets that flag implements this itself (each one's
842
+ * grammar differs), so the PostgreSQL version is never inherited by use.
843
+ */
844
+ buildBulkUpsertStatement?(input: BulkUpsertStatementInput): BuiltStatement;
529
845
  /** Whether native ILIKE is supported. */
530
846
  readonly supportsILike: boolean;
531
847
  /** Build a case-insensitive LIKE equivalent. */
@@ -546,18 +862,54 @@ export interface Dialect {
546
862
  * of the ENGINE's pattern grammar, not of the SQL text, which is why it is a
547
863
  * dialect hook rather than a branch in the where builder.
548
864
  *
549
- * Whatever a dialect returns MUST be escaped for the same `ESCAPE '\'`
550
- * clause, i.e. a backslash prefix, and MUST be identical on the SQL-build and
551
- * the cache-hit param-collect paths (both call this one hook, so they cannot
552
- * drift).
865
+ * Whatever a dialect returns MUST be escaped for the character its
866
+ * {@link likeEscapeCharacter} names (a backslash when that is absent), and
867
+ * MUST be identical on the SQL-build and the cache-hit param-collect paths
868
+ * (both call this one hook, so they cannot drift). A dialect that sets
869
+ * `likeEscapeCharacter` must define this hook too: the shared default
870
+ * escapes with a backslash.
553
871
  */
554
872
  escapeLikePattern?(value: string): string;
873
+ /**
874
+ * The character the emitted `LIKE ... ESCAPE '<c>'` clause names, which
875
+ * {@link escapeLikePattern} prefixes to every metacharacter it escapes.
876
+ * Optional: absent means `\`, the clause every other engine emits, and it is
877
+ * absent on `postgresDialect`, so a dialect built by spreading it inherits
878
+ * nothing.
879
+ *
880
+ * MySQL sets it because a backslash cannot be written as a string literal
881
+ * that means the same thing in every session. With the server default
882
+ * `sql_mode`, `\` escapes inside a literal and `ESCAPE '\'` is an
883
+ * unterminated string (a syntax error); with `NO_BACKSLASH_ESCAPES` it is one
884
+ * backslash. Turbine sets that mode on the connections it opens, but a pool
885
+ * the caller supplies keeps the caller's mode, and changing a session mode on
886
+ * a connection Turbine does not own would change how the caller's own SQL
887
+ * parses. A character with no meaning inside a string literal reads the same
888
+ * in both modes.
889
+ *
890
+ * It must be one character that needs no escaping inside a single-quoted
891
+ * literal (never `'` or `\`) and is not itself a LIKE metacharacter.
892
+ */
893
+ readonly likeEscapeCharacter?: string;
555
894
  /** JSON operator support level for this dialect. */
556
895
  readonly jsonPathSupport: 'native' | 'function' | 'limited';
557
896
  /** Build a JSON containment check. */
558
897
  buildJsonContains(column: string, paramRef: string): string;
559
898
  /** Build a JSON path text extraction expression. */
560
899
  buildJsonPathExtract(column: string, pathParamRef: string): string;
900
+ /**
901
+ * `{ path, equals }` (and a whole-document `equals`, see
902
+ * {@link JsonPathEqualsInput.pathRef}) as a TYPED comparison: the JSON value
903
+ * equals the operand as JSON, so `5` and `"5"` differ and `true` does not
904
+ * match `1`.
905
+ * Throws `UnsupportedFeatureError` (E017) for an operand the engine cannot
906
+ * compare exactly. OPTIONAL and deliberately absent on `postgresDialect`
907
+ * (the where compiler owns the PostgreSQL form, read when
908
+ * {@link EngineCapabilities.jsonDocumentEquality} is `'jsonb'`), so no engine
909
+ * inherits it by spreading; an engine without it compares the text its
910
+ * `buildJsonPathExtract` returns.
911
+ */
912
+ buildJsonPathEquals?(input: JsonPathEqualsInput): string;
561
913
  /** Build a correlation clause across single or composite keys. */
562
914
  buildCorrelation(leftRef: string, leftColumns: string | string[], rightRef: string, rightColumns: string | string[]): string;
563
915
  /**
@@ -582,6 +934,19 @@ export interface Dialect {
582
934
  * its wire format.
583
935
  */
584
936
  jsonWireRule?(columnType: string): JsonWireRule | undefined;
937
+ /**
938
+ * How a value the driver hands back for a column of `columnType` (a schema
939
+ * type, e.g. `jsonb`) becomes the value PostgreSQL returns for it, or
940
+ * `undefined` when the driver's value already is that. The row parser applies
941
+ * it to top-level and nested rows alike, so the two cannot disagree.
942
+ *
943
+ * For an engine whose STORAGE differs from the declared type in a way only
944
+ * the schema knows: SQL Server has no JSON column type (2016 to 2022), so a
945
+ * json/jsonb column is NVARCHAR text on every read path. The decode must be
946
+ * safe to apply to exactly what the driver and the engine's JSON builder
947
+ * produce, once. Optional, and absent on PostgreSQL.
948
+ */
949
+ decodeColumnValue?(columnType: string): ((value: unknown) => unknown) | undefined;
585
950
  /** Optional type mapping hook for code generation/introspection. */
586
951
  typeToTypeScript?(dialectType: string, nullable: boolean): string;
587
952
  /**
@@ -593,23 +958,70 @@ export interface Dialect {
593
958
  * this hook keep emitting byte-identical SQL.
594
959
  */
595
960
  castAggregate?(expr: string, target: 'int' | 'float'): string;
961
+ /**
962
+ * The argument `AVG` takes for a column of `columnType`, given the column
963
+ * reference, or `undefined` to average the column as it is. PostgreSQL's
964
+ * `avg` over an integer column is an exact fraction (`avg(int4)` is
965
+ * `numeric`), while SQL Server averages an INT as an INT (56.4 becomes 56)
966
+ * and MySQL as a DECIMAL with four more digits of scale (4/3 becomes
967
+ * 1.3333). An engine like that widens the input instead. Optional, and
968
+ * absent on PostgreSQL, so its SQL is unchanged.
969
+ */
970
+ averageArgument?(columnRef: string, columnType: string): string | undefined;
596
971
  /**
597
972
  * Build a membership (`IN` / `NOT IN`) predicate from a column/expression and
598
973
  * a single bound parameter reference. PostgreSQL binds the whole list as one
599
974
  * array param (`expr = ANY($n)` / `expr != ALL($n)`), so the placeholder count
600
975
  * stays independent of the list length and the SQL cache remains valid.
601
- * Engines without array parameters (SQLite) override this together with
602
- * {@link inClauseParam} to use a length-independent single-placeholder form
603
- * (e.g. `expr IN (SELECT value FROM json_each(?))`). Optional: the query
604
- * builder falls back to the PostgreSQL `ANY`/`ALL` form when absent.
976
+ * Engines without array parameters override this together with
977
+ * {@link inClauseParam}: SQLite and SQL Server unpack one bound JSON list in a
978
+ * subquery, and MySQL emits `expr IN (:pN)`, which its pool shim expands into
979
+ * one placeholder per element. The builder's text stays length-independent
980
+ * either way. Optional: the query builder falls back to the PostgreSQL
981
+ * `ANY`/`ALL` form when absent.
605
982
  */
606
983
  buildInClause?(expr: string, paramRef: string, negated: boolean): string;
607
984
  /**
608
985
  * The single bound value for an `IN` list (paired with {@link buildInClause}).
609
- * PostgreSQL passes the array through unchanged; SQLite serializes it to a
610
- * JSON string consumed by `json_each`. Optional: defaults to the array itself.
986
+ * PostgreSQL passes the array through unchanged; SQLite and SQL Server
987
+ * serialize it to JSON, element by element as the scalar binds; MySQL wraps it
988
+ * for its shim to expand. Optional: defaults to the array itself.
611
989
  */
612
990
  inClauseParam?(values: unknown[]): unknown;
991
+ /**
992
+ * Check a string about to be written to a column: return the refusal
993
+ * message, or `undefined` to bind the string as is. `columnType` is the
994
+ * column's declared (PostgreSQL-flavored) type. The write path throws the
995
+ * message as a ValidationError (E003) before any SQL runs.
996
+ *
997
+ * Optional, and absent on every engine whose server refuses text its column
998
+ * cannot hold (PostgreSQL, MySQL in strict mode, SQL Server), where the
999
+ * server's error is the refusal. SQLite defines it, because its type affinity
1000
+ * stores such text in a numeric column instead of refusing it. Only the
1001
+ * SQLite dialect sets it and no dialect spreads SQLite's, so testing for its
1002
+ * presence is sound (unlike a hook on `postgresDialect`, which every engine
1003
+ * inherits).
1004
+ */
1005
+ checkTextWrite?(table: string, column: string, columnType: string, value: string): string | undefined;
1006
+ /**
1007
+ * How `schemaToSQL` declares a column of a schema-level enum on an engine
1008
+ * with no named enum type. Returns the column's type as an input to this
1009
+ * dialect's own `buildColumnType`, and optionally a CHECK expression over
1010
+ * `column` (already quoted) that admits exactly the labels. Throws E003 for a
1011
+ * label the engine cannot declare.
1012
+ *
1013
+ * PostgreSQL does not use it: it declares the type with `CREATE TYPE ... AS
1014
+ * ENUM` and the column names the type. `schemaToSQL` decides that by
1015
+ * {@link EngineCapabilities.namedEnumTypes}, not by this hook's absence; an
1016
+ * engine without named enum types that does not define the hook gets an
1017
+ * UnsupportedFeatureError (E017) for an enum column instead of PostgreSQL's
1018
+ * DDL.
1019
+ */
1020
+ buildEnumColumn?(column: string, labels: readonly string[]): {
1021
+ type: string;
1022
+ maxLength?: number | null;
1023
+ check?: string;
1024
+ };
613
1025
  /** Optional array-cast hook for bulk insert implementations. */
614
1026
  arrayType?(baseType: string): string;
615
1027
  /** Map a schema-builder column type to dialect DDL. */
@@ -663,8 +1075,9 @@ export interface Dialect {
663
1075
  openStream(connection: StreamableConnection, sql: string, params: unknown[], batchSize: number, opts?: OpenStreamOptions): AsyncGenerator<Record<string, unknown>[], void, undefined>;
664
1076
  /**
665
1077
  * Schema introspector for this engine. `introspect()` routes through it so
666
- * engines can override the catalog SQL. PostgreSQL wraps the
667
- * information_schema / pg_catalog reader in `introspect.ts`.
1078
+ * engines can override the catalog SQL. Absent on PostgreSQL, whose
1079
+ * information_schema / pg_catalog reader in `introspect.ts` is what
1080
+ * `introspect()` uses when a dialect has no introspector.
668
1081
  */
669
1082
  readonly introspector?: DialectIntrospector;
670
1083
  /**
@@ -711,8 +1124,10 @@ export interface Dialect {
711
1124
  * correct but unbounded in bytes over the wire (200 parents x ~505 children
712
1125
  * with `limit: 3` measured 101,000 rows fetched to keep 600, +52.9 MB peak
713
1126
  * heap against +0.5 MB for the join plan), which is why PostgreSQL
714
- * implements it. Only PostgreSQL does in this release; the other engines keep
715
- * the client-side slice, so their emitted SQL is byte-identical to before.
1127
+ * implements it. The loader uses it only where
1128
+ * {@link EngineCapabilities.partitionLimitPushdown} is true (PostgreSQL in
1129
+ * this release), since every engine inherits this hook by spreading; the
1130
+ * other engines keep the client-side slice.
716
1131
  *
717
1132
  * The client-side slice is NOT removed when a dialect implements this: it
718
1133
  * stays as the belt-and-braces bound, and is a no-op once the engine has
@@ -733,6 +1148,12 @@ export interface IntrospectOptions {
733
1148
  schema?: string;
734
1149
  include?: string[];
735
1150
  exclude?: string[];
1151
+ /**
1152
+ * Where relation-naming notes go (a renamed or shadowing relation). Absent
1153
+ * means the console logger. `introspect()` hands an engine introspector its
1154
+ * whole options object, so this is the caller's `IntrospectOptions.logger`.
1155
+ */
1156
+ logger?: TurbineLogger;
736
1157
  }
737
1158
  /**
738
1159
  * @deprecated Migration locking is owned by the {@link DatabaseAdapter} seam
@@ -745,5 +1166,13 @@ export interface DialectMigrator {
745
1166
  acquireLock(lockId: number): Promise<boolean>;
746
1167
  releaseLock(lockId: number): Promise<void>;
747
1168
  }
1169
+ /** The bind-parameter limit for one statement on this dialect, or `undefined` when it has none. */
1170
+ export declare function maxBindParameters(dialect: Pick<Dialect, 'capabilities'>): number | undefined;
1171
+ /**
1172
+ * `DO NOTHING`, or `DO UPDATE SET ... [WHERE ...]`: the action of an
1173
+ * `ON CONFLICT (target)` clause, shared by PostgreSQL and SQLite, whose
1174
+ * grammars agree here. The update compiles after the row values are bound.
1175
+ */
1176
+ export declare function onConflictAction(input: BulkUpsertStatementInput, params: unknown[], refs: BulkUpsertRefs): string;
748
1177
  /** PostgreSQL implementation of the dialect contract. */
749
1178
  export declare const postgresDialect: Dialect;