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.
- package/README.md +26 -25
- package/dist/checkout.d.ts +27 -2
- package/dist/checkout.js +75 -4
- package/dist/cjs/checkout.d.ts +27 -2
- package/dist/cjs/checkout.js +76 -3
- package/dist/cjs/cli/code-first-tags.d.ts +62 -0
- package/dist/cjs/cli/code-first-tags.js +124 -0
- package/dist/cjs/cli/compile-query.js +9 -0
- package/dist/cjs/cli/config.d.ts +35 -6
- package/dist/cjs/cli/config.js +17 -1
- package/dist/cjs/cli/destructive.d.ts +7 -4
- package/dist/cjs/cli/destructive.js +224 -20
- package/dist/cjs/cli/error-catalog.js +36 -0
- package/dist/cjs/cli/error-text.d.ts +15 -0
- package/dist/cjs/cli/error-text.js +40 -0
- package/dist/cjs/cli/index.d.ts +62 -4
- package/dist/cjs/cli/index.js +568 -108
- package/dist/cjs/cli/local-server-guard.d.ts +53 -0
- package/dist/cjs/cli/local-server-guard.js +119 -0
- package/dist/cjs/cli/local-server-output.d.ts +41 -0
- package/dist/cjs/cli/local-server-output.js +103 -0
- package/dist/cjs/cli/mcp.d.ts +8 -0
- package/dist/cjs/cli/mcp.js +121 -32
- package/dist/cjs/cli/migrate.d.ts +113 -5
- package/dist/cjs/cli/migrate.js +270 -21
- package/dist/cjs/cli/observe.d.ts +6 -1
- package/dist/cjs/cli/observe.js +85 -55
- package/dist/cjs/cli/pii-predicate-guard.d.ts +43 -23
- package/dist/cjs/cli/pii-predicate-guard.js +98 -37
- package/dist/cjs/cli/prisma-resolve.js +17 -13
- package/dist/cjs/cli/prisma-schema.js +12 -4
- package/dist/cjs/cli/studio-ui.generated.js +1 -1
- package/dist/cjs/cli/studio.d.ts +14 -2
- package/dist/cjs/cli/studio.js +244 -69
- package/dist/cjs/cli/ui.d.ts +1 -1
- package/dist/cjs/client.d.ts +558 -85
- package/dist/cjs/client.js +1270 -395
- package/dist/cjs/connection-guard.d.ts +13 -0
- package/dist/cjs/connection-guard.js +28 -0
- package/dist/cjs/connection-url.d.ts +51 -16
- package/dist/cjs/connection-url.js +67 -34
- package/dist/cjs/diagnostics.d.ts +81 -0
- package/dist/cjs/diagnostics.js +147 -0
- package/dist/cjs/dialect.d.ts +449 -20
- package/dist/cjs/dialect.js +117 -76
- package/dist/cjs/engine-config.d.ts +7 -6
- package/dist/cjs/errors.d.ts +126 -6
- package/dist/cjs/errors.js +256 -13
- package/dist/cjs/generate.d.ts +57 -7
- package/dist/cjs/generate.js +635 -279
- package/dist/cjs/global-filters-config.d.ts +59 -0
- package/dist/cjs/global-filters-config.js +367 -0
- package/dist/cjs/index.d.ts +9 -4
- package/dist/cjs/index.js +10 -2
- package/dist/cjs/introspect.d.ts +31 -6
- package/dist/cjs/introspect.js +108 -50
- package/dist/cjs/log-codes.d.ts +12 -0
- package/dist/cjs/log-codes.js +77 -0
- package/dist/cjs/logger.d.ts +87 -0
- package/dist/cjs/logger.js +98 -0
- package/dist/cjs/mssql.d.ts +8 -5
- package/dist/cjs/mssql.js +352 -65
- package/dist/cjs/mysql.d.ts +3 -5
- package/dist/cjs/mysql.js +420 -70
- package/dist/cjs/nested-write.d.ts +3 -0
- package/dist/cjs/nested-write.js +179 -114
- package/dist/cjs/pipeline-submittable.d.ts +12 -0
- package/dist/cjs/pipeline-submittable.js +118 -44
- package/dist/cjs/pipeline.js +21 -26
- package/dist/cjs/powdb-introspect.d.ts +5 -2
- package/dist/cjs/powdb-introspect.js +20 -15
- package/dist/cjs/powdb-shared.d.ts +36 -5
- package/dist/cjs/powdb-shared.js +67 -8
- package/dist/cjs/powdb.d.ts +4 -0
- package/dist/cjs/powdb.js +183 -51
- package/dist/cjs/powql.d.ts +394 -51
- package/dist/cjs/powql.js +1829 -284
- package/dist/cjs/prisma-compat.d.ts +23 -15
- package/dist/cjs/prisma-compat.js +507 -372
- package/dist/cjs/query/aggregates.d.ts +17 -1
- package/dist/cjs/query/aggregates.js +261 -29
- package/dist/cjs/query/batched-loader.d.ts +25 -6
- package/dist/cjs/query/batched-loader.js +103 -20
- package/dist/cjs/query/builder.d.ts +325 -184
- package/dist/cjs/query/builder.js +1452 -490
- package/dist/cjs/query/column-ref.d.ts +61 -0
- package/dist/cjs/query/column-ref.js +73 -0
- package/dist/cjs/query/compound-unique.d.ts +21 -0
- package/dist/cjs/query/compound-unique.js +98 -18
- package/dist/cjs/query/deferred.d.ts +53 -16
- package/dist/cjs/query/expr.d.ts +217 -0
- package/dist/cjs/query/expr.js +859 -0
- package/dist/cjs/query/filters.d.ts +155 -53
- package/dist/cjs/query/filters.js +613 -76
- package/dist/cjs/query/index.d.ts +2 -0
- package/dist/cjs/query/index.js +7 -1
- package/dist/cjs/query/json-value.d.ts +43 -0
- package/dist/cjs/query/json-value.js +59 -0
- package/dist/cjs/query/normalize-args.d.ts +87 -0
- package/dist/cjs/query/normalize-args.js +527 -0
- package/dist/cjs/query/option-surface.d.ts +16 -4
- package/dist/cjs/query/option-surface.js +57 -14
- package/dist/cjs/query/relation-names.d.ts +14 -0
- package/dist/cjs/query/relation-names.js +77 -18
- package/dist/cjs/query/relations.d.ts +30 -3
- package/dist/cjs/query/relations.js +219 -63
- package/dist/cjs/query/row-lock.d.ts +49 -0
- package/dist/cjs/query/row-lock.js +138 -0
- package/dist/cjs/query/sql-comment.d.ts +161 -0
- package/dist/cjs/query/sql-comment.js +381 -0
- package/dist/cjs/query/stream-idle.d.ts +132 -0
- package/dist/cjs/query/stream-idle.js +212 -0
- package/dist/cjs/query/table-client.d.ts +101 -0
- package/dist/cjs/query/table-client.js +74 -0
- package/dist/cjs/query/types.d.ts +677 -298
- package/dist/cjs/query/utils.d.ts +105 -6
- package/dist/cjs/query/utils.js +426 -19
- package/dist/cjs/query/warn-registry.d.ts +18 -0
- package/dist/cjs/query/warn-registry.js +18 -0
- package/dist/cjs/query/where-compile.d.ts +138 -14
- package/dist/cjs/query/where-compile.js +513 -29
- package/dist/cjs/query/where.d.ts +159 -59
- package/dist/cjs/query/where.js +716 -246
- package/dist/cjs/query/writes.d.ts +112 -50
- package/dist/cjs/query/writes.js +1498 -200
- package/dist/cjs/query-events.d.ts +4 -2
- package/dist/cjs/query-events.js +3 -1
- package/dist/cjs/realtime.d.ts +7 -3
- package/dist/cjs/realtime.js +13 -2
- package/dist/cjs/schema-builder.d.ts +55 -4
- package/dist/cjs/schema-builder.js +382 -18
- package/dist/cjs/schema-metadata.d.ts +21 -1
- package/dist/cjs/schema-metadata.js +29 -7
- package/dist/cjs/schema-sql.d.ts +75 -5
- package/dist/cjs/schema-sql.js +497 -45
- package/dist/cjs/schema.d.ts +26 -5
- package/dist/cjs/schema.js +110 -13
- package/dist/cjs/sql-placeholders.d.ts +56 -0
- package/dist/cjs/sql-placeholders.js +204 -0
- package/dist/cjs/sqlite.d.ts +75 -20
- package/dist/cjs/sqlite.js +593 -95
- package/dist/cjs/supplied-pool-types.d.ts +48 -0
- package/dist/cjs/supplied-pool-types.js +256 -0
- package/dist/cjs/transaction-control.d.ts +51 -0
- package/dist/cjs/transaction-control.js +316 -0
- package/dist/cjs/transaction-state.d.ts +342 -0
- package/dist/cjs/transaction-state.js +707 -0
- package/dist/cjs/typed-sql.d.ts +37 -3
- package/dist/cjs/typed-sql.js +102 -8
- package/dist/cli/code-first-tags.d.ts +62 -0
- package/dist/cli/code-first-tags.js +120 -0
- package/dist/cli/compile-query.js +9 -0
- package/dist/cli/config.d.ts +35 -6
- package/dist/cli/config.js +16 -1
- package/dist/cli/destructive.d.ts +7 -4
- package/dist/cli/destructive.js +224 -20
- package/dist/cli/error-catalog.js +36 -0
- package/dist/cli/error-text.d.ts +15 -0
- package/dist/cli/error-text.js +37 -0
- package/dist/cli/index.d.ts +62 -4
- package/dist/cli/index.js +569 -112
- package/dist/cli/local-server-guard.d.ts +53 -0
- package/dist/cli/local-server-guard.js +113 -0
- package/dist/cli/local-server-output.d.ts +41 -0
- package/dist/cli/local-server-output.js +98 -0
- package/dist/cli/mcp.d.ts +8 -0
- package/dist/cli/mcp.js +121 -34
- package/dist/cli/migrate.d.ts +113 -5
- package/dist/cli/migrate.js +261 -21
- package/dist/cli/observe.d.ts +6 -1
- package/dist/cli/observe.js +84 -54
- package/dist/cli/pii-predicate-guard.d.ts +43 -23
- package/dist/cli/pii-predicate-guard.js +100 -35
- package/dist/cli/prisma-resolve.js +15 -11
- package/dist/cli/prisma-schema.js +12 -4
- package/dist/cli/studio-ui.generated.js +1 -1
- package/dist/cli/studio.d.ts +14 -2
- package/dist/cli/studio.js +246 -71
- package/dist/cli/ui.d.ts +1 -1
- package/dist/client.d.ts +558 -85
- package/dist/client.js +1275 -400
- package/dist/connection-guard.d.ts +13 -0
- package/dist/connection-guard.js +27 -0
- package/dist/connection-url.d.ts +51 -16
- package/dist/connection-url.js +63 -34
- package/dist/diagnostics.d.ts +81 -0
- package/dist/diagnostics.js +144 -0
- package/dist/dialect.d.ts +449 -20
- package/dist/dialect.js +115 -43
- package/dist/engine-config.d.ts +7 -6
- package/dist/errors.d.ts +126 -6
- package/dist/errors.js +252 -12
- package/dist/generate.d.ts +57 -7
- package/dist/generate.js +635 -281
- package/dist/global-filters-config.d.ts +59 -0
- package/dist/global-filters-config.js +361 -0
- package/dist/index.d.ts +9 -4
- package/dist/index.js +4 -2
- package/dist/introspect.d.ts +31 -6
- package/dist/introspect.js +106 -50
- package/dist/log-codes.d.ts +12 -0
- package/dist/log-codes.js +74 -0
- package/dist/logger.d.ts +87 -0
- package/dist/logger.js +93 -0
- package/dist/mssql.d.ts +8 -5
- package/dist/mssql.js +354 -67
- package/dist/mysql.d.ts +3 -5
- package/dist/mysql.js +423 -73
- package/dist/nested-write.d.ts +3 -0
- package/dist/nested-write.js +177 -112
- package/dist/pipeline-submittable.d.ts +12 -0
- package/dist/pipeline-submittable.js +117 -44
- package/dist/pipeline.js +21 -26
- package/dist/powdb-introspect.d.ts +5 -2
- package/dist/powdb-introspect.js +21 -16
- package/dist/powdb-shared.d.ts +36 -5
- package/dist/powdb-shared.js +65 -8
- package/dist/powdb.d.ts +4 -0
- package/dist/powdb.js +183 -51
- package/dist/powql.d.ts +394 -51
- package/dist/powql.js +1836 -291
- package/dist/prisma-compat.d.ts +23 -15
- package/dist/prisma-compat.js +508 -373
- package/dist/query/aggregates.d.ts +17 -1
- package/dist/query/aggregates.js +263 -32
- package/dist/query/batched-loader.d.ts +25 -6
- package/dist/query/batched-loader.js +101 -21
- package/dist/query/builder.d.ts +325 -184
- package/dist/query/builder.js +1458 -495
- package/dist/query/column-ref.d.ts +61 -0
- package/dist/query/column-ref.js +66 -0
- package/dist/query/compound-unique.d.ts +21 -0
- package/dist/query/compound-unique.js +97 -19
- package/dist/query/deferred.d.ts +53 -16
- package/dist/query/expr.d.ts +217 -0
- package/dist/query/expr.js +848 -0
- package/dist/query/filters.d.ts +155 -53
- package/dist/query/filters.js +597 -72
- package/dist/query/index.d.ts +2 -0
- package/dist/query/index.js +4 -0
- package/dist/query/json-value.d.ts +43 -0
- package/dist/query/json-value.js +54 -0
- package/dist/query/normalize-args.d.ts +87 -0
- package/dist/query/normalize-args.js +517 -0
- package/dist/query/option-surface.d.ts +16 -4
- package/dist/query/option-surface.js +56 -13
- package/dist/query/relation-names.d.ts +14 -0
- package/dist/query/relation-names.js +77 -19
- package/dist/query/relations.d.ts +30 -3
- package/dist/query/relations.js +220 -67
- package/dist/query/row-lock.d.ts +49 -0
- package/dist/query/row-lock.js +131 -0
- package/dist/query/sql-comment.d.ts +161 -0
- package/dist/query/sql-comment.js +374 -0
- package/dist/query/stream-idle.d.ts +132 -0
- package/dist/query/stream-idle.js +203 -0
- package/dist/query/table-client.d.ts +101 -0
- package/dist/query/table-client.js +70 -0
- package/dist/query/types.d.ts +677 -298
- package/dist/query/utils.d.ts +105 -6
- package/dist/query/utils.js +414 -18
- package/dist/query/warn-registry.d.ts +18 -0
- package/dist/query/warn-registry.js +18 -0
- package/dist/query/where-compile.d.ts +138 -14
- package/dist/query/where-compile.js +508 -31
- package/dist/query/where.d.ts +159 -59
- package/dist/query/where.js +711 -248
- package/dist/query/writes.d.ts +112 -50
- package/dist/query/writes.js +1496 -202
- package/dist/query-events.d.ts +4 -2
- package/dist/query-events.js +3 -1
- package/dist/realtime.d.ts +7 -3
- package/dist/realtime.js +13 -2
- package/dist/schema-builder.d.ts +55 -4
- package/dist/schema-builder.js +381 -18
- package/dist/schema-metadata.d.ts +21 -1
- package/dist/schema-metadata.js +28 -7
- package/dist/schema-sql.d.ts +75 -5
- package/dist/schema-sql.js +494 -44
- package/dist/schema.d.ts +26 -5
- package/dist/schema.js +109 -13
- package/dist/sql-placeholders.d.ts +56 -0
- package/dist/sql-placeholders.js +200 -0
- package/dist/sqlite.d.ts +75 -20
- package/dist/sqlite.js +597 -99
- package/dist/supplied-pool-types.d.ts +48 -0
- package/dist/supplied-pool-types.js +247 -0
- package/dist/transaction-control.d.ts +51 -0
- package/dist/transaction-control.js +311 -0
- package/dist/transaction-state.d.ts +342 -0
- package/dist/transaction-state.js +696 -0
- package/dist/typed-sql.d.ts +37 -3
- package/dist/typed-sql.js +100 -8
- package/package.json +7 -4
- package/skills/turbine-orm/SKILL.md +56 -6
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import pg from '#pg';
|
|
20
20
|
import { PipelineError, TimeoutError, wrapPgError } from './errors.js';
|
|
21
|
+
import { rolledBackError } from './transaction-state.js';
|
|
21
22
|
// Read off pg's own module object (`pg.Result` IS `pg/lib/result`, `pg.utils`
|
|
22
23
|
// IS `pg/lib/utils`) rather than imported by subpath, so the whole driver comes
|
|
23
24
|
// through the one `#pg` alias that edge bundles swap out (see src/pg-edge.ts).
|
|
@@ -86,6 +87,16 @@ function restoreListeners(emitter, snapshot) {
|
|
|
86
87
|
// ---------------------------------------------------------------------------
|
|
87
88
|
// Core pipeline execution
|
|
88
89
|
// ---------------------------------------------------------------------------
|
|
90
|
+
/** A statement that only reads: its transform may run after COMMIT, since there is nothing to undo. */
|
|
91
|
+
const READ_ONLY_STATEMENT = /^\s*select\b/i;
|
|
92
|
+
/**
|
|
93
|
+
* Whether a transactional batch must hold its COMMIT until the transforms have
|
|
94
|
+
* run. Anything that is not a plain SELECT counts as a write, so a statement
|
|
95
|
+
* this cannot classify costs a round trip rather than correctness.
|
|
96
|
+
*/
|
|
97
|
+
export function batchMayWrite(queries) {
|
|
98
|
+
return queries.some((q) => !READ_ONLY_STATEMENT.test(q.sql));
|
|
99
|
+
}
|
|
89
100
|
/**
|
|
90
101
|
* Execute multiple queries using the Postgres extended-query pipeline protocol.
|
|
91
102
|
*
|
|
@@ -112,11 +123,20 @@ export async function runPipelined(client, queries, options = {}) {
|
|
|
112
123
|
// State machine
|
|
113
124
|
// -----------------------------------------------------------------------
|
|
114
125
|
/**
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
126
|
+
* True when the batch is sent as BEGIN + queries + Sync and the COMMIT
|
|
127
|
+
* follows only once every transform has succeeded (see
|
|
128
|
+
* {@link PipelineRunOptions.transactional}).
|
|
118
129
|
*/
|
|
119
|
-
const
|
|
130
|
+
const holdCommit = transactional && batchMayWrite(queries);
|
|
131
|
+
/**
|
|
132
|
+
* Where the exchange is: the batch itself, or the single follow-up
|
|
133
|
+
* statement (the held COMMIT, or the recovery ROLLBACK) sent after it.
|
|
134
|
+
*/
|
|
135
|
+
let phase = 'batch';
|
|
136
|
+
/** The command tag the held COMMIT came back with (`ROLLBACK` when the server rolled back). */
|
|
137
|
+
let commitTag;
|
|
138
|
+
/** Transformed results, computed before a held COMMIT is sent. */
|
|
139
|
+
let transformed;
|
|
120
140
|
/**
|
|
121
141
|
* Expected readyForQuery events:
|
|
122
142
|
* - Transactional: 1 (single Sync at end)
|
|
@@ -142,20 +162,17 @@ export async function runPipelined(client, queries, options = {}) {
|
|
|
142
162
|
let cleaned = false;
|
|
143
163
|
/** Transaction status reported by the most recent ReadyForQuery. */
|
|
144
164
|
let txStatus;
|
|
145
|
-
/** Whether the recovery ROLLBACK has already been sent (it is sent at most once). */
|
|
146
|
-
let rollbackSent = false;
|
|
147
165
|
/**
|
|
148
166
|
* Map commandComplete index to the corresponding results[] index.
|
|
149
167
|
* In transactional mode: index 0 = BEGIN, 1..N = queries, N+1 = COMMIT
|
|
150
|
-
* In non-transactional mode:
|
|
168
|
+
* (absent when the COMMIT is held). In non-transactional mode: 1:1.
|
|
169
|
+
* Follow-up statements belong to no query.
|
|
151
170
|
*/
|
|
152
171
|
function commandToQueryIndex(cmdIdx) {
|
|
153
|
-
if (
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
return cmdIdx;
|
|
172
|
+
if (phase !== 'batch')
|
|
173
|
+
return null;
|
|
174
|
+
const qIdx = transactional ? cmdIdx - 1 : cmdIdx;
|
|
175
|
+
return qIdx >= 0 && qIdx < queries.length ? qIdx : null;
|
|
159
176
|
}
|
|
160
177
|
/** Get the current query-results index for row data */
|
|
161
178
|
function currentQueryIndex() {
|
|
@@ -214,30 +231,56 @@ export async function runPipelined(client, queries, options = {}) {
|
|
|
214
231
|
return true;
|
|
215
232
|
if (txStatus === undefined && !(transactional && pipelineError))
|
|
216
233
|
return true;
|
|
217
|
-
if (!transactional
|
|
218
|
-
//
|
|
219
|
-
//
|
|
220
|
-
|
|
221
|
-
if (txStatus === 'E' || txStatus === 'T') {
|
|
222
|
-
Object.defineProperty(client, PIPELINE_DISCARD, { value: true, enumerable: false, configurable: true });
|
|
223
|
-
}
|
|
234
|
+
if (!transactional) {
|
|
235
|
+
// Non-transactional mode opens no transaction of its own, so there is
|
|
236
|
+
// nothing to roll back. Hand the client back marked for disposal.
|
|
237
|
+
markDiscardIfInTransaction();
|
|
224
238
|
return true;
|
|
225
239
|
}
|
|
226
|
-
|
|
240
|
+
return !sendFollowUp('ROLLBACK', 'rollback');
|
|
241
|
+
}
|
|
242
|
+
/** Mark the client for disposal when the backend still reports an open or failed transaction. */
|
|
243
|
+
function markDiscardIfInTransaction() {
|
|
244
|
+
if (txStatus === 'E' || txStatus === 'T') {
|
|
245
|
+
Object.defineProperty(client, PIPELINE_DISCARD, { value: true, enumerable: false, configurable: true });
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Send one statement after the batch (the held COMMIT or the recovery
|
|
250
|
+
* ROLLBACK) with its own Sync; its ReadyForQuery finishes the exchange.
|
|
251
|
+
* Returns false when the socket would not take it, in which case the
|
|
252
|
+
* connection is marked for disposal, since it cannot be repaired from here.
|
|
253
|
+
*/
|
|
254
|
+
function sendFollowUp(text, next) {
|
|
255
|
+
phase = next;
|
|
227
256
|
try {
|
|
228
|
-
connection.
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
257
|
+
connection.stream.cork?.();
|
|
258
|
+
try {
|
|
259
|
+
connection.parse({ text, name: '' });
|
|
260
|
+
connection.bind({ portal: '', statement: '', values: [], valueMapper: prepareValue });
|
|
261
|
+
connection.execute({ portal: '', rows: 0 });
|
|
262
|
+
connection.sync();
|
|
263
|
+
}
|
|
264
|
+
finally {
|
|
265
|
+
connection.stream.uncork?.();
|
|
266
|
+
}
|
|
267
|
+
return true;
|
|
233
268
|
}
|
|
234
|
-
catch {
|
|
235
|
-
// The socket would not take the rollback, so this connection cannot be
|
|
236
|
-
// repaired from here. Mark it and let the caller drop it.
|
|
269
|
+
catch (err) {
|
|
237
270
|
Object.defineProperty(client, PIPELINE_DISCARD, { value: true, enumerable: false, configurable: true });
|
|
238
|
-
|
|
271
|
+
if (!pipelineError)
|
|
272
|
+
pipelineError = err instanceof Error ? err : new Error(String(err));
|
|
273
|
+
return false;
|
|
239
274
|
}
|
|
240
275
|
}
|
|
276
|
+
/** Run every query's transform, in order; the first throw propagates. */
|
|
277
|
+
function transformAll() {
|
|
278
|
+
const out = [];
|
|
279
|
+
for (let i = 0; i < queries.length; i++) {
|
|
280
|
+
out.push(queries[i].transform(results[i]));
|
|
281
|
+
}
|
|
282
|
+
return out;
|
|
283
|
+
}
|
|
241
284
|
function finalize() {
|
|
242
285
|
cleanup();
|
|
243
286
|
if (transactional && pipelineError) {
|
|
@@ -280,14 +323,14 @@ export async function runPipelined(client, queries, options = {}) {
|
|
|
280
323
|
}));
|
|
281
324
|
return;
|
|
282
325
|
}
|
|
283
|
-
// All succeeded
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
for (let i = 0; i < queries.length; i++) {
|
|
287
|
-
const q = queries[i];
|
|
288
|
-
transformed.push(q.transform(results[i]));
|
|
289
|
-
}
|
|
326
|
+
// All succeeded. A held COMMIT ran the transforms before committing;
|
|
327
|
+
// a read-only batch runs them now (there is nothing to undo).
|
|
328
|
+
if (transformed) {
|
|
290
329
|
resolve(transformed);
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
try {
|
|
333
|
+
resolve(transformAll());
|
|
291
334
|
}
|
|
292
335
|
catch (err) {
|
|
293
336
|
reject(err);
|
|
@@ -320,6 +363,8 @@ export async function runPipelined(client, queries, options = {}) {
|
|
|
320
363
|
}
|
|
321
364
|
}
|
|
322
365
|
function onCommandComplete(msg) {
|
|
366
|
+
if (phase === 'commit')
|
|
367
|
+
commitTag = msg.command ?? msg.text;
|
|
323
368
|
const qIdx = currentQueryIndex();
|
|
324
369
|
if (qIdx !== null && qIdx >= 0 && qIdx < results.length) {
|
|
325
370
|
results[qIdx].addCommandComplete(msg);
|
|
@@ -366,15 +411,41 @@ export async function runPipelined(client, queries, options = {}) {
|
|
|
366
411
|
}
|
|
367
412
|
function onReadyForQuery(msg) {
|
|
368
413
|
txStatus = msg?.status;
|
|
369
|
-
//
|
|
414
|
+
// A follow-up statement's own ReadyForQuery is not one of the batch's, so
|
|
370
415
|
// it must not advance the counter that decides when the batch is done.
|
|
371
|
-
if (
|
|
416
|
+
if (phase === 'rollback') {
|
|
417
|
+
markDiscardIfInTransaction();
|
|
418
|
+
finalize();
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
if (phase === 'commit') {
|
|
422
|
+
// PostgreSQL answers COMMIT in a failed transaction with the tag
|
|
423
|
+
// ROLLBACK and no error. Nothing here sends COMMIT after an error, but
|
|
424
|
+
// the answer is checked rather than assumed.
|
|
425
|
+
if (!pipelineError && commitTag === 'ROLLBACK')
|
|
426
|
+
pipelineError = rolledBackError(undefined, 'transaction');
|
|
427
|
+
markDiscardIfInTransaction();
|
|
372
428
|
finalize();
|
|
373
429
|
return;
|
|
374
430
|
}
|
|
375
431
|
rfqCount++;
|
|
376
432
|
if (rfqCount < expectedRfq)
|
|
377
433
|
return;
|
|
434
|
+
if (holdCommit && !pipelineError && txStatus !== 'E') {
|
|
435
|
+
try {
|
|
436
|
+
transformed = transformAll();
|
|
437
|
+
}
|
|
438
|
+
catch (err) {
|
|
439
|
+
// A transform refused its result: roll the batch's writes back.
|
|
440
|
+
pipelineError = err instanceof Error ? err : new Error(String(err));
|
|
441
|
+
if (!sendFollowUp('ROLLBACK', 'rollback'))
|
|
442
|
+
finalize();
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
if (!sendFollowUp('COMMIT', 'commit'))
|
|
446
|
+
finalize();
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
378
449
|
if (settleTransactionState())
|
|
379
450
|
finalize();
|
|
380
451
|
}
|
|
@@ -421,7 +492,8 @@ export async function runPipelined(client, queries, options = {}) {
|
|
|
421
492
|
if (transactional) {
|
|
422
493
|
// ---- Transactional mode ----
|
|
423
494
|
// BEGIN + N×(parse+bind+describe+execute) + COMMIT + sync
|
|
424
|
-
// One sync = one ReadyForQuery
|
|
495
|
+
// One sync = one ReadyForQuery. A batch that may write leaves the
|
|
496
|
+
// COMMIT out here and sends it after the transforms (holdCommit).
|
|
425
497
|
// BEGIN
|
|
426
498
|
connection.parse({ text: 'BEGIN', name: '' });
|
|
427
499
|
connection.bind({ portal: '', statement: '', values: [], valueMapper: prepareValue });
|
|
@@ -438,10 +510,11 @@ export async function runPipelined(client, queries, options = {}) {
|
|
|
438
510
|
connection.describe({ type: 'P', name: '' });
|
|
439
511
|
connection.execute({ portal: '', rows: 0 });
|
|
440
512
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
513
|
+
if (!holdCommit) {
|
|
514
|
+
connection.parse({ text: 'COMMIT', name: '' });
|
|
515
|
+
connection.bind({ portal: '', statement: '', values: [], valueMapper: prepareValue });
|
|
516
|
+
connection.execute({ portal: '', rows: 0 });
|
|
517
|
+
}
|
|
445
518
|
// Single Sync
|
|
446
519
|
connection.sync();
|
|
447
520
|
}
|
package/dist/pipeline.js
CHANGED
|
@@ -18,10 +18,21 @@
|
|
|
18
18
|
* Sequential fallback covers HTTP-based drivers (Neon HTTP, Vercel Postgres, Cloudflare
|
|
19
19
|
* Hyperdrive), mock pools in tests, and any pool that doesn't expose pg internals.
|
|
20
20
|
*/
|
|
21
|
+
import { acquireConnection } from './checkout.js';
|
|
21
22
|
import { guardCheckout } from './connection-guard.js';
|
|
22
23
|
import { postgresDialect } from './dialect.js';
|
|
23
24
|
import { explainConnectionLoss, PipelineError, TurbineError, wrapPgError } from './errors.js';
|
|
24
25
|
import { pipelineClientNeedsDiscard, runPipelined, supportsExtendedPipeline, } from './pipeline-submittable.js';
|
|
26
|
+
import { commitTransaction } from './transaction-state.js';
|
|
27
|
+
/**
|
|
28
|
+
* Run one deferred query on the batch's connection. An engine without
|
|
29
|
+
* RETURNING (MySQL) attaches a `reselect` plan that runs the write and then
|
|
30
|
+
* fetches its row; sending `q.sql` alone would hand the transform a row-less
|
|
31
|
+
* result, which a single-row write reads as "not found".
|
|
32
|
+
*/
|
|
33
|
+
function runOne(client, q) {
|
|
34
|
+
return q.reselect ? q.reselect((sql, params) => client.query(sql, params)) : client.query(q.sql, q.params);
|
|
35
|
+
}
|
|
25
36
|
/**
|
|
26
37
|
* Execute queries sequentially on an already-acquired connection.
|
|
27
38
|
* This is the fallback path for clients that don't support the extended-query
|
|
@@ -51,19 +62,16 @@ async function runSequential(client, queries, dialect, options = {}) {
|
|
|
51
62
|
for (const q of queries) {
|
|
52
63
|
let raw;
|
|
53
64
|
try {
|
|
54
|
-
raw = await client
|
|
65
|
+
raw = await runOne(client, q);
|
|
55
66
|
}
|
|
56
67
|
catch (err) {
|
|
57
68
|
throw wrapPgError(err);
|
|
58
69
|
}
|
|
70
|
+
// Transformed BEFORE the COMMIT, so a transform that refuses its result
|
|
71
|
+
// (a `...OrThrow` miss, an optimistic-lock conflict) rolls the batch back.
|
|
59
72
|
results.push(q.transform(raw));
|
|
60
73
|
}
|
|
61
|
-
|
|
62
|
-
await client.query(dialect.commitStatement());
|
|
63
|
-
}
|
|
64
|
-
catch (err) {
|
|
65
|
-
throw wrapPgError(err);
|
|
66
|
-
}
|
|
74
|
+
await commitTransaction(client, dialect.commitStatement());
|
|
67
75
|
return results;
|
|
68
76
|
}
|
|
69
77
|
catch (err) {
|
|
@@ -141,7 +149,7 @@ async function runIndependent(client, queries) {
|
|
|
141
149
|
const q = queries[i];
|
|
142
150
|
let raw;
|
|
143
151
|
try {
|
|
144
|
-
raw = await client
|
|
152
|
+
raw = await runOne(client, q);
|
|
145
153
|
}
|
|
146
154
|
catch (err) {
|
|
147
155
|
const wrapped = wrapPgError(err);
|
|
@@ -188,24 +196,11 @@ export async function executePipeline(pool, queries, options) {
|
|
|
188
196
|
if (queries.length === 0) {
|
|
189
197
|
return [];
|
|
190
198
|
}
|
|
191
|
-
//
|
|
192
|
-
//
|
|
193
|
-
//
|
|
194
|
-
//
|
|
195
|
-
|
|
196
|
-
// so a caller switching on `.code` silently receives a value from a foreign
|
|
197
|
-
// namespace. The transaction and nested-write checkouts were wrapped for this
|
|
198
|
-
// reason; this was the last sibling still bare.
|
|
199
|
-
let client;
|
|
200
|
-
try {
|
|
201
|
-
client = await pool.connect();
|
|
202
|
-
}
|
|
203
|
-
catch (err) {
|
|
204
|
-
throw wrapPgError(err);
|
|
205
|
-
}
|
|
206
|
-
// Guarded for the checkout window, see connection-guard.ts: a connection that
|
|
207
|
-
// dies mid-batch emits 'error', which with no listener exits the process.
|
|
208
|
-
const checkout = guardCheckout(client);
|
|
199
|
+
// One client, reused for both capability check and execution. The shared
|
|
200
|
+
// checkout types a connection-level failure (wrong password, TLS, refused,
|
|
201
|
+
// an exhausted pool) and guards the checkout window: a connection that dies
|
|
202
|
+
// mid-batch emits 'error', which with no listener exits the process.
|
|
203
|
+
const { client, checkout } = await acquireConnection(pool);
|
|
209
204
|
try {
|
|
210
205
|
if (supportsExtendedPipeline(client)) {
|
|
211
206
|
// Real pipeline path, uses extended-query protocol wire methods
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* shape the SQL introspectors produce, so a code-first PowDB database can be
|
|
14
14
|
* introspected for bootstrap/verification. It is transport-agnostic: the caller
|
|
15
15
|
* supplies an `exec(powql)` that returns row objects **keyed by column name**.
|
|
16
|
-
* - Embedded / owned pool: `exec = async (q) => ({ rows: await db.
|
|
17
|
-
* using a live `turbinePowDB` client
|
|
16
|
+
* - Embedded / owned pool: `exec = async (q) => ({ rows: await db.rawUnsafe(q) })`
|
|
17
|
+
* using a live `turbinePowDB` client.
|
|
18
18
|
* - Networked: the raw `@zvndev/powdb-client` returns POSITIONAL rows
|
|
19
19
|
* (`{ columns: string[], rows: string[][] }`), so zip them into records.
|
|
20
20
|
* A bare `(await client.query(q)).rows` would hand this function `string[][]`
|
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
* wired to a networked `exec`, and `cli/config.ts` teaching the generate
|
|
67
67
|
* funnel to construct a PowDB client instead of a `pg` client for `powdb://`.
|
|
68
68
|
*/
|
|
69
|
+
import { type TurbineLogger } from './logger.js';
|
|
69
70
|
import { type PowdbCapabilities } from './powdb-shared.js';
|
|
70
71
|
import type { SchemaMetadata } from './schema.js';
|
|
71
72
|
/** A minimal rows-returning executor over a PowDB connection (embedded or networked). */
|
|
@@ -86,6 +87,8 @@ export interface PowdbIntrospectOptions {
|
|
|
86
87
|
* to run ungated; the pool paths that know the version pass it through.
|
|
87
88
|
*/
|
|
88
89
|
capabilities?: PowdbCapabilities;
|
|
90
|
+
/** Where a table without a usable primary key is reported. Defaults to the console logger. */
|
|
91
|
+
logger?: TurbineLogger;
|
|
89
92
|
}
|
|
90
93
|
/**
|
|
91
94
|
* Read a live PowDB database into {@link SchemaMetadata} via `schema` +
|
package/dist/powdb-introspect.js
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* shape the SQL introspectors produce, so a code-first PowDB database can be
|
|
14
14
|
* introspected for bootstrap/verification. It is transport-agnostic: the caller
|
|
15
15
|
* supplies an `exec(powql)` that returns row objects **keyed by column name**.
|
|
16
|
-
* - Embedded / owned pool: `exec = async (q) => ({ rows: await db.
|
|
17
|
-
* using a live `turbinePowDB` client
|
|
16
|
+
* - Embedded / owned pool: `exec = async (q) => ({ rows: await db.rawUnsafe(q) })`
|
|
17
|
+
* using a live `turbinePowDB` client.
|
|
18
18
|
* - Networked: the raw `@zvndev/powdb-client` returns POSITIONAL rows
|
|
19
19
|
* (`{ columns: string[], rows: string[][] }`), so zip them into records.
|
|
20
20
|
* A bare `(await client.query(q)).rows` would hand this function `string[][]`
|
|
@@ -67,7 +67,8 @@
|
|
|
67
67
|
* funnel to construct a PowDB client instead of a `pg` client for `powdb://`.
|
|
68
68
|
*/
|
|
69
69
|
import { ValidationError } from './errors.js';
|
|
70
|
-
import { applyTableFilters } from './introspect.js';
|
|
70
|
+
import { applyTableFilters, assertDistinctColumnFields, nullRecord, printableCatalogName } from './introspect.js';
|
|
71
|
+
import { consoleLogger, logTo } from './logger.js';
|
|
71
72
|
import { quotePowqlIdent, requireCapability } from './powdb-shared.js';
|
|
72
73
|
import { singularize, snakeToCamel } from './schema.js';
|
|
73
74
|
/** Coerce a wire cell to string (legacy wire cells are strings; native cells may be typed). */
|
|
@@ -133,7 +134,9 @@ export async function introspectPowdbDatabase(exec, options = {}) {
|
|
|
133
134
|
}
|
|
134
135
|
// include / exclude + default bookkeeping-table exclusions (F12).
|
|
135
136
|
const tableNames = applyTableFilters(candidateTables, options);
|
|
136
|
-
|
|
137
|
+
// Keyed by catalog names, so prototype-less: a table or column named
|
|
138
|
+
// `__proto__`, `constructor` or `toString` is data, never a prototype member.
|
|
139
|
+
const tables = nullRecord();
|
|
137
140
|
for (const tableName of tableNames) {
|
|
138
141
|
// `describe` needs the table name in bare-identifier position → quote it so
|
|
139
142
|
// a reserved-word / non-bare table name (`order`) does not become a parse
|
|
@@ -154,11 +157,11 @@ export async function introspectPowdbDatabase(exec, options = {}) {
|
|
|
154
157
|
index: asString(r.index),
|
|
155
158
|
}));
|
|
156
159
|
const columns = [];
|
|
157
|
-
const columnMap =
|
|
158
|
-
const reverseColumnMap =
|
|
160
|
+
const columnMap = nullRecord();
|
|
161
|
+
const reverseColumnMap = nullRecord();
|
|
159
162
|
const dateColumns = new Set();
|
|
160
|
-
const dialectTypes =
|
|
161
|
-
const pgTypes =
|
|
163
|
+
const dialectTypes = nullRecord();
|
|
164
|
+
const pgTypes = nullRecord();
|
|
162
165
|
const allColumns = [];
|
|
163
166
|
const uniqueColumns = [];
|
|
164
167
|
const indexes = [];
|
|
@@ -206,15 +209,17 @@ export async function introspectPowdbDatabase(exec, options = {}) {
|
|
|
206
209
|
});
|
|
207
210
|
}
|
|
208
211
|
}
|
|
212
|
+
// Two columns resolving to one field would fold into one property on read.
|
|
213
|
+
assertDistinctColumnFields(tableName, columns);
|
|
209
214
|
// Primary key: first non-nullable unique column, preferring one named `id`.
|
|
210
215
|
let primaryKey = [];
|
|
211
216
|
if (pkCandidates.length > 0) {
|
|
212
217
|
primaryKey = [pkCandidates.includes('id') ? 'id' : pkCandidates[0]];
|
|
213
218
|
}
|
|
214
219
|
else {
|
|
215
|
-
|
|
220
|
+
logTo(options.logger ?? consoleLogger, 'warn', `PowDB introspection: table "${printableCatalogName(tableName)}" has no non-nullable unique column; ` +
|
|
216
221
|
'primaryKey is [] (single-row operations will fail). Supply a primary key via code-first ' +
|
|
217
|
-
'`defineSchema` metadata if this table needs findUnique/update/delete by id.');
|
|
222
|
+
'`defineSchema` metadata if this table needs findUnique/update/delete by id.', { code: 'powdb-introspect-no-primary-key', table: tableName });
|
|
218
223
|
}
|
|
219
224
|
tables[tableName] = {
|
|
220
225
|
name: tableName,
|
|
@@ -230,7 +235,7 @@ export async function introspectPowdbDatabase(exec, options = {}) {
|
|
|
230
235
|
// Populated below from `schema links` when the engine supports link
|
|
231
236
|
// introspection (>= 0.19.1); stays `{}` otherwise (PowDB has no declared
|
|
232
237
|
// foreign keys, so pre-link introspection reports no relations).
|
|
233
|
-
relations:
|
|
238
|
+
relations: nullRecord(),
|
|
234
239
|
indexes,
|
|
235
240
|
};
|
|
236
241
|
}
|
|
@@ -240,7 +245,7 @@ export async function introspectPowdbDatabase(exec, options = {}) {
|
|
|
240
245
|
if (options.capabilities?.linkIntrospection) {
|
|
241
246
|
await introspectPowdbLinks(exec, tables);
|
|
242
247
|
}
|
|
243
|
-
return { tables, enums:
|
|
248
|
+
return { tables, enums: nullRecord() };
|
|
244
249
|
}
|
|
245
250
|
/**
|
|
246
251
|
* Read `schema links` and populate {@link TableMetadata.relations}: the first
|
|
@@ -275,8 +280,8 @@ async function introspectPowdbLinks(exec, tables) {
|
|
|
275
280
|
cardinality: asString(r.cardinality),
|
|
276
281
|
}));
|
|
277
282
|
for (const link of linkRows) {
|
|
278
|
-
const owner = tables[link.owner];
|
|
279
|
-
const target = tables[link.target];
|
|
283
|
+
const owner = Object.hasOwn(tables, link.owner) ? tables[link.owner] : undefined;
|
|
284
|
+
const target = Object.hasOwn(tables, link.target) ? tables[link.target] : undefined;
|
|
280
285
|
// A link referencing a filtered-out (include/exclude) table is skipped: we
|
|
281
286
|
// cannot describe the target, so the relation would be unusable.
|
|
282
287
|
if (!owner || !target)
|
|
@@ -321,13 +326,13 @@ async function introspectPowdbLinks(exec, tables) {
|
|
|
321
326
|
}
|
|
322
327
|
/** True when `name` already names a relation OR a column field/name on `meta`. */
|
|
323
328
|
function relationNameTaken(meta, name) {
|
|
324
|
-
if (meta.relations
|
|
329
|
+
if (Object.hasOwn(meta.relations, name))
|
|
325
330
|
return true;
|
|
326
331
|
return meta.columns.some((c) => c.field === name || c.name === name);
|
|
327
332
|
}
|
|
328
333
|
/** Add a relation to a table's relations map (keyed by its camelCase name). */
|
|
329
334
|
function addRelation(meta, rel) {
|
|
330
|
-
if (meta.relations
|
|
335
|
+
if (Object.hasOwn(meta.relations, rel.name))
|
|
331
336
|
return; // never clobber an existing relation
|
|
332
337
|
meta.relations[rel.name] = rel;
|
|
333
338
|
}
|
package/dist/powdb-shared.d.ts
CHANGED
|
@@ -233,15 +233,36 @@ export type PowqlType = 'str' | 'int' | 'float' | 'bool' | 'json';
|
|
|
233
233
|
* asserts the equivalence over a corpus rather than asserting my reading of it.
|
|
234
234
|
*/
|
|
235
235
|
export declare function baseTsType(tsType: string): string;
|
|
236
|
+
/** A schema's enum types (`SchemaMetadata.enums`): type name to labels, in declaration order. */
|
|
237
|
+
export type PowdbEnums = Readonly<Record<string, readonly string[]>>;
|
|
236
238
|
/**
|
|
237
|
-
*
|
|
239
|
+
* The labels of the enum type this column is declared as, or `undefined` when
|
|
240
|
+
* it is not an enum column of `enums`.
|
|
241
|
+
*
|
|
242
|
+
* An enum column carries its TYPE NAME as `dialectType` / `pgType` and a
|
|
243
|
+
* `tsType` that says nothing useful (`unknown` from `defineSchema`, a union of
|
|
244
|
+
* the labels from introspection), so the column's own metadata cannot answer
|
|
245
|
+
* the question: the schema's `enums` map is the only authority. PowDB has no
|
|
246
|
+
* enum type, so such a column is a `str` holding the label text, which is what
|
|
247
|
+
* PostgreSQL stores and returns. Without this the tsType heuristic in
|
|
248
|
+
* {@link isJsonColumn} declared a `defineSchema` enum column as `json`, and
|
|
249
|
+
* writing a label failed as invalid JSON.
|
|
250
|
+
*/
|
|
251
|
+
export declare function powdbEnumLabels(col: ColumnMetadata, enums: PowdbEnums | undefined): readonly string[] | undefined;
|
|
252
|
+
/**
|
|
253
|
+
* Does this column map to PowDB's native `json` document type? An enum column
|
|
254
|
+
* of `enums` never does (see {@link powdbEnumLabels}). A Postgres
|
|
238
255
|
* `json`/`jsonb` type (via `dialectType`/`pgType`) is authoritative; otherwise
|
|
239
256
|
* the tsType heuristic (`Record<…>`, `object`, `unknown`, an object/array
|
|
240
257
|
* literal) that the four scalar branches do not claim. Array columns never map
|
|
241
258
|
* to json, a PowDB array only exists INSIDE a json document, so a Postgres
|
|
242
259
|
* array column has no PowDB shape and still throws in {@link powqlColumnType}.
|
|
260
|
+
*
|
|
261
|
+
* `enums` is optional for callers outside Turbine; every call inside the
|
|
262
|
+
* engine passes the schema's map (a source scan in fx-powdb-r2.test.ts
|
|
263
|
+
* checks it).
|
|
243
264
|
*/
|
|
244
|
-
export declare function isJsonColumn(col: ColumnMetadata): boolean;
|
|
265
|
+
export declare function isJsonColumn(col: ColumnMetadata, enums?: PowdbEnums): boolean;
|
|
245
266
|
/**
|
|
246
267
|
* Map a Turbine column to the PowQL DDL type used in `defineSchema` →
|
|
247
268
|
* `type T { … }`. Turbine never emits PowDB's `uuid`/`datetime`/`bytes` types,
|
|
@@ -249,10 +270,20 @@ export declare function isJsonColumn(col: ColumnMetadata): boolean;
|
|
|
249
270
|
* - `Date` → `int` (epoch micros) - `boolean` → `bool`
|
|
250
271
|
* - integral `number`/`bigint` → `int` - fractional `number` → `float`
|
|
251
272
|
* - JSON / object columns → `json` (native PowDB document type, ≥ 0.12)
|
|
273
|
+
* - an enum column of `enums` → `str` (the label text)
|
|
252
274
|
* - everything else (incl. UUID/PK strings) → `str`
|
|
253
275
|
* Array (non-json) and bytes columns throw, they have no PowDB equivalent.
|
|
254
276
|
*/
|
|
255
|
-
export declare function powqlColumnType(col: ColumnMetadata): PowqlType;
|
|
277
|
+
export declare function powqlColumnType(col: ColumnMetadata, enums?: PowdbEnums): PowqlType;
|
|
278
|
+
/**
|
|
279
|
+
* Is this a `numeric` / `decimal` / `money` column that PowDB stores as `str`?
|
|
280
|
+
*
|
|
281
|
+
* A Postgres-sourced decimal surfaces as a JS string (so its digits survive),
|
|
282
|
+
* and PowDB has no decimal type, so the column is DDL'd as PowQL `str`. Every
|
|
283
|
+
* comparison, ordering and aggregate the engine runs on it is then a TEXT
|
|
284
|
+
* operation, which is why the query generator refuses those on such a column.
|
|
285
|
+
*/
|
|
286
|
+
export declare function isPowdbDecimalTextColumn(col: ColumnMetadata, enums?: PowdbEnums): boolean;
|
|
256
287
|
/**
|
|
257
288
|
* Is a column stored as `int` epoch micros but surfaced as a JS `Date`?
|
|
258
289
|
*
|
|
@@ -325,7 +356,7 @@ export declare function quotePowqlDotted(name: string): string;
|
|
|
325
356
|
* Every PowDB value arrives as a string; NULL arrives as the bareword `"null"`.
|
|
326
357
|
* Metadata resolves the `"null"` ambiguity for nullable non-string columns.
|
|
327
358
|
*/
|
|
328
|
-
export declare function coerceValue(raw: string, col: ColumnMetadata): unknown;
|
|
359
|
+
export declare function coerceValue(raw: string, col: ColumnMetadata, enums?: PowdbEnums): unknown;
|
|
329
360
|
/**
|
|
330
361
|
* Coerce a single cell that arrived over the NATIVE typed wire (decoded from a
|
|
331
362
|
* {@link PowdbWireValue}, so already a JS `bigint`/`number`/`boolean`/`string`/
|
|
@@ -354,7 +385,7 @@ export declare function coerceNativeValue(value: unknown, col: ColumnMetadata):
|
|
|
354
385
|
* cells arrive pre-typed and go through {@link coerceNativeValue} (see F3).
|
|
355
386
|
* Callers on the native transport pass `this.pool.capabilities.nativeRaw`.
|
|
356
387
|
*/
|
|
357
|
-
export declare function rowToEntity(raw: Record<string, unknown>, meta: TableMetadata, native?: boolean): Record<string, unknown>;
|
|
388
|
+
export declare function rowToEntity(raw: Record<string, unknown>, meta: TableMetadata, native?: boolean, enums?: PowdbEnums): Record<string, unknown>;
|
|
358
389
|
/**
|
|
359
390
|
* True when `err` is the stale-wire-frame {@link ConnectionError} produced by
|
|
360
391
|
* {@link wrapPowdbError} (its `.cause` is a `protocol_error` PowDBError, or the
|