pqb 0.57.1 → 0.57.3

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/dist/index.mjs CHANGED
@@ -1,8 +1,1051 @@
1
- import { ExpressionTypeMethod, Expression, RawSQLBase, emptyObject, isTemplateLiteralArgs, ColumnTypeBase, setColumnData, pushColumnData, templateLiteralSQLToCode, quoteObjectKey, toArray, emptyArray, singleQuote, addCode, singleQuoteArray, objectHasValues, toSnakeCase, columnDefaultArgumentToCode, columnErrorMessagesToCode, setObjectValueImmutable, getValueKey, addValue, isIterable, isExpression, dateDataToCode, joinTruthy, arrayDataToCode, numberDataToCode, noop, stringDataToCode, getDefaultLanguage, setDefaultNowFn, setDefaultLanguage, setCurrentColumnName, timestampHelpers, _getQueryAliasOrName, _getQueryOuterAliases, returnArg, pushQueryValueImmutable, NotFoundError, applyTransforms, OrchidOrmInternalError, _setSubQueryAliases, _applyRelationAliases, isRelationQuery, getFreeAlias, _checkIfAliased, getQueryParsers, logColors, OrchidOrmError, callWithThis, requirePrimaryKeys, _setQueryAs, _copyQueryAliasToQuery, setParserToQuery, _addToHookSelectWithTable, spreadObjectValues, _addToHookSelect, newDelayedRelationSelect, pushOrNewArray, getPrimaryKeys, setDelayedRelation, UnhandledTypeError, isRawSQL, pushOrNewArrayToObjectImmutable, _getQueryFreeAlias, _setQueryAlias, QueryHookUtils, MoreThanOneRowError, isObjectEmpty, ValExpression, applyMixins, _getQueryAs, QueryError, snakeCaseKey } from 'orchid-core';
1
+ import url from 'url';
2
+ import path from 'node:path';
3
+ import { setTimeout } from 'timers/promises';
2
4
  import { inspect } from 'node:util';
3
5
  import { AsyncLocalStorage } from 'node:async_hooks';
4
6
  import { templateLiteralToSQL as templateLiteralToSQL$1 } from 'pqb';
5
7
 
8
+ const colors = {
9
+ yellow: (s) => `\x1B[33m${s}\x1B[0m`,
10
+ green: (s) => `\x1B[32m${s}\x1B[0m`,
11
+ red: (s) => `\x1B[31m${s}\x1B[0m`,
12
+ blue: (s) => `\x1B[34m${s}\x1B[0m`,
13
+ bright: (s) => `\x1B[1m${s}\x1B[0m`,
14
+ blueBold: (s) => `\x1B[1m\x1B[34m${s}\x1B[0m`,
15
+ yellowBold: (s) => `\x1B[1m\x1B[33m${s}\x1B[0m`,
16
+ greenBold: (s) => `\x1B[1m\x1B[32m${s}\x1B[0m`,
17
+ pale: (s) => `\x1B[2m${s}\x1B[0m`
18
+ };
19
+
20
+ function applyMixins(derivedCtor, constructors) {
21
+ constructors.forEach((baseCtor) => {
22
+ Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => {
23
+ Object.defineProperty(
24
+ derivedCtor.prototype,
25
+ name,
26
+ Object.getOwnPropertyDescriptor(baseCtor.prototype, name) || /* @__PURE__ */ Object.create(null)
27
+ );
28
+ });
29
+ });
30
+ }
31
+ const joinTruthy = (...strings) => {
32
+ return strings.filter((string) => string).join("");
33
+ };
34
+ const toArray = (item) => Array.isArray(item) ? item : [item];
35
+ const noop = () => {
36
+ };
37
+ const returnArg = (a) => a;
38
+ const emptyObject = {};
39
+ const emptyArray = [];
40
+ const pushOrNewArrayToObjectImmutable = (obj, key, value) => {
41
+ obj[key] = obj[key] ? [...obj[key], value] : [value];
42
+ };
43
+ const setObjectValueImmutable = (q, object, key, value) => {
44
+ q[object] = {
45
+ ...q[object],
46
+ [key]: value
47
+ };
48
+ return q;
49
+ };
50
+ const spreadObjectValues = (q, object, value) => {
51
+ q[object] = {
52
+ ...q[object],
53
+ ...value
54
+ };
55
+ };
56
+ const pushOrNewArray = (arr, value) => {
57
+ if (arr) {
58
+ arr.push(value);
59
+ return arr;
60
+ } else {
61
+ return [value];
62
+ }
63
+ };
64
+ const singleQuote = (s) => {
65
+ return `'${s.replaceAll("\\", "\\\\").replaceAll("'", "\\'")}'`;
66
+ };
67
+ const backtickQuote = (s) => {
68
+ return `\`${s.replaceAll("\\", "\\\\").replaceAll("`", "\\`")}\``;
69
+ };
70
+ const singleQuoteArray = (arr) => {
71
+ return `[${arr.map(singleQuote).join(", ")}]`;
72
+ };
73
+ const quoteObjectKey = (key, toCamel) => {
74
+ if (toCamel) key = toCamelCase(key);
75
+ return /^[a-zA-Z_$][\w$]*$/.test(key) ? key : singleQuote(key);
76
+ };
77
+ const isObjectEmpty = (obj) => !objectHasValues(obj);
78
+ const objectHasValues = (obj) => {
79
+ if (!obj) return false;
80
+ for (const key in obj) {
81
+ if (obj[key] !== void 0) return true;
82
+ }
83
+ return false;
84
+ };
85
+ const pathToLog = (path2) => {
86
+ return process.platform === "win32" ? path2 : url.pathToFileURL(path2).toString();
87
+ };
88
+ const toCamelCase = (str) => {
89
+ return str.replace(/^_+/g, "").replace(/_+./g, (a) => a[a.length - 1].toUpperCase()).replace(/_+$/g, "");
90
+ };
91
+ const toPascalCase = (str) => {
92
+ const camel = toCamelCase(str);
93
+ return camel[0].toUpperCase() + camel.slice(1);
94
+ };
95
+ const toSnakeCase = (str) => {
96
+ return str.replace(/[A-Z]/g, (a) => `_${a.toLowerCase()}`);
97
+ };
98
+ const deepCompare = (a, b) => {
99
+ if (a === b) return true;
100
+ if (typeof a !== typeof b) {
101
+ if (a === void 0 && typeof b === "object") {
102
+ a = emptyObject;
103
+ } else if (typeof a === "object" && b === void 0) {
104
+ b = emptyObject;
105
+ } else {
106
+ return false;
107
+ }
108
+ }
109
+ if (typeof a === "object") {
110
+ if (a === null) return b === null;
111
+ if (Array.isArray(a)) {
112
+ if (!Array.isArray(b) || a.length !== b.length) return false;
113
+ return a.every((item, i) => deepCompare(item, b[i]));
114
+ }
115
+ for (const key in a) {
116
+ if (!deepCompare(a[key], b[key]))
117
+ return false;
118
+ }
119
+ for (const key in b) {
120
+ if (!(key in a) && b[key] !== void 0) return false;
121
+ }
122
+ return true;
123
+ }
124
+ return a === b;
125
+ };
126
+ const getImportPath = (from, to) => {
127
+ const rel = path.relative(path.dirname(from), to).split(path.sep).join(path.posix.sep);
128
+ const importPath = rel.startsWith("./") || rel.startsWith("../") ? rel : `./${rel}`;
129
+ return importPath.replace(/\.[tj]s$/, "");
130
+ };
131
+ const getStackTrace = () => {
132
+ let stack;
133
+ const original = Error.prepareStackTrace;
134
+ Error.prepareStackTrace = (_, s) => stack = s;
135
+ new Error().stack;
136
+ Error.prepareStackTrace = original;
137
+ return stack;
138
+ };
139
+ const getCallerFilePath = (stack = getStackTrace()) => {
140
+ if (stack) {
141
+ const coreLibFile = stack[0]?.getFileName();
142
+ let i = 1;
143
+ if (stack[1]?.getFileName() === coreLibFile) {
144
+ i++;
145
+ }
146
+ const libFile = stack[i]?.getFileName();
147
+ const libDir = libFile && path.dirname(libFile);
148
+ for (; i < stack.length; i++) {
149
+ const item = stack[i];
150
+ let file = item.getFileName();
151
+ if (!file || // skip files in the caller orchid library
152
+ path.dirname(file) === libDir || // skip any files in the node_modules
153
+ /\bnode_modules\b/.test(file)) {
154
+ continue;
155
+ }
156
+ if (/file:\/\/\/\w+:\//.test(file)) {
157
+ file = decodeURI(file.slice(8));
158
+ } else {
159
+ try {
160
+ file = new URL(file).pathname;
161
+ } catch (_) {
162
+ }
163
+ }
164
+ return file;
165
+ }
166
+ }
167
+ return;
168
+ };
169
+ const callWithThis = function(cb) {
170
+ return cb(this);
171
+ };
172
+ const pick = (obj, keys) => {
173
+ const res = {};
174
+ for (const key of keys) {
175
+ res[key] = obj[key];
176
+ }
177
+ return res;
178
+ };
179
+ const omit = (obj, keys) => {
180
+ const res = { ...obj };
181
+ for (const key of keys) {
182
+ delete res[key];
183
+ }
184
+ return res;
185
+ };
186
+ const addValue = (values, value) => {
187
+ values.push(value);
188
+ return `$${values.length}`;
189
+ };
190
+ const getFreeAlias = (obj, as) => {
191
+ if (obj?.[as]) {
192
+ let suffix = 2;
193
+ let name;
194
+ while (obj[name = as + suffix]) {
195
+ suffix++;
196
+ }
197
+ as = name;
198
+ }
199
+ return as;
200
+ };
201
+ const getFreeSetAlias = (set, as, start = 2) => {
202
+ if (set.has(as)) {
203
+ let suffix = start;
204
+ let name;
205
+ while (set.has(name = as + suffix)) {
206
+ suffix++;
207
+ }
208
+ as = name;
209
+ }
210
+ return as;
211
+ };
212
+ const exhaustive = (_) => {
213
+ throw new Error("Condition was not exhaustive");
214
+ };
215
+ const pluralize = (w, count, append = "s") => {
216
+ return count === 1 ? w : w + append;
217
+ };
218
+ const isIterable = (x) => !!(x && typeof x === "object" && typeof x[Symbol.iterator] === "function");
219
+
220
+ const setConnectRetryConfig = (adapter, config) => {
221
+ adapter.connectRetryConfig = {
222
+ attempts: config.attempts ?? 10,
223
+ strategy: typeof config.strategy === "function" ? config.strategy : defaultConnectRetryStrategy(config.strategy ?? emptyObject)
224
+ };
225
+ };
226
+ const wrapAdapterFnWithConnectRetry = (adapter, fn) => {
227
+ return async function(...args) {
228
+ let attempt = 1;
229
+ for (; ; ) {
230
+ try {
231
+ return await fn.call(this, ...args);
232
+ } catch (err) {
233
+ const config = adapter.connectRetryConfig;
234
+ if (!err || typeof err !== "object" || err.code !== "ECONNREFUSED" || !config || attempt >= config.attempts) {
235
+ throw err;
236
+ }
237
+ await config.strategy(attempt, config.attempts);
238
+ attempt++;
239
+ }
240
+ }
241
+ };
242
+ };
243
+ const defaultConnectRetryStrategy = (param) => {
244
+ return (attempt) => setTimeout((param.factor ?? 1.5) ** (attempt - 1) * (param.delay ?? 50));
245
+ };
246
+
247
+ const getValueKey = Symbol("get");
248
+ const applyTransforms = (queryData, returnType, fns, result) => {
249
+ for (const fn of fns) {
250
+ if ("map" in fn) {
251
+ if (!returnType || returnType === "all" || returnType === "pluck") {
252
+ result = result.map(fn.map, fn.thisArg);
253
+ } else if (result !== void 0) {
254
+ result = result === null ? null : fn.map.call(fn.thisArg, result, 0, result);
255
+ }
256
+ } else {
257
+ result = fn(result, queryData);
258
+ }
259
+ }
260
+ return result;
261
+ };
262
+ const pushQueryValueImmutable = (q, key, value) => {
263
+ pushOrNewArrayToObjectImmutable(
264
+ q.q,
265
+ key,
266
+ value
267
+ );
268
+ return q;
269
+ };
270
+
271
+ const numberMethodNames = ["gt", "gte", "lt", "lte", "step", "int", "finite", "safe"];
272
+ const stringMethodNames = [
273
+ "nonEmpty",
274
+ "min",
275
+ "max",
276
+ "length",
277
+ "email",
278
+ "url",
279
+ "emoji",
280
+ "uuid",
281
+ "cuid",
282
+ "cuid2",
283
+ "ulid",
284
+ "regex",
285
+ "includes",
286
+ "startsWith",
287
+ "endsWith",
288
+ "datetime",
289
+ "ipv4",
290
+ "ipv6",
291
+ "trim",
292
+ "toLowerCase",
293
+ "toUpperCase"
294
+ ];
295
+ const dateMethodNames = ["min", "max"];
296
+ const arrayMethodNames = [
297
+ "min",
298
+ "max",
299
+ "length",
300
+ "nonEmpty"
301
+ ];
302
+
303
+ class Expression {
304
+ // Produce SQL string by calling `makeSQL` and applying operators from the `q.chain`, push query variables into given `values` array.
305
+ toSQL(ctx, quotedAs) {
306
+ let sql = this.makeSQL(ctx, quotedAs);
307
+ if (this.q.chain) {
308
+ const { chain } = this.q;
309
+ for (let i = 0, len = chain.length; i < len; i += 2) {
310
+ sql = chain[i](
311
+ sql,
312
+ chain[i + 1],
313
+ ctx,
314
+ quotedAs
315
+ );
316
+ }
317
+ }
318
+ return sql;
319
+ }
320
+ }
321
+ const isExpression = (arg) => arg instanceof Expression;
322
+ const isTemplateLiteralArgs = (args) => Array.isArray(args[0]) && "raw" in args[0] && Array.isArray(args[0].raw);
323
+ class ExpressionTypeMethod {
324
+ // Define the resulting column type for the raw SQL.
325
+ type(fn) {
326
+ const column = fn(this.columnTypes);
327
+ this.q.expr.result.value = column;
328
+ Object.assign(
329
+ "baseQuery" in this ? this.baseQuery : this,
330
+ column.operators
331
+ );
332
+ return this;
333
+ }
334
+ }
335
+ class RawSQLBase extends Expression {
336
+ constructor(_sql, _values) {
337
+ super();
338
+ this._sql = _sql;
339
+ this._values = _values;
340
+ this.q = { expr: this };
341
+ }
342
+ // Attach query variables to the raw SQL.
343
+ values(values) {
344
+ this._values = values;
345
+ return this;
346
+ }
347
+ // Convert raw SQL to code for a code generator.
348
+ toCode(t) {
349
+ const { _sql: sql, _values: values } = this;
350
+ let code = `${t}.sql`;
351
+ code += typeof sql === "string" ? `({ raw: '${sql.replace(/'/g, "\\'")}' })` : templateLiteralSQLToCode(sql);
352
+ if (values) {
353
+ code += `.values(${JSON.stringify(values)})`;
354
+ }
355
+ return code;
356
+ }
357
+ }
358
+ const templateLiteralSQLToCode = (sql) => {
359
+ let code = "`";
360
+ const parts = sql[0];
361
+ let i = 0;
362
+ for (let last = parts.length - 1; i < last; i++) {
363
+ code += parts[i] + `\${${sql[i + 1]}}`;
364
+ }
365
+ code += parts[i];
366
+ return code + "`";
367
+ };
368
+ RawSQLBase.prototype.type = ExpressionTypeMethod.prototype.type;
369
+ const isRawSQL = (arg) => arg instanceof RawSQLBase;
370
+ class ValExpression extends Expression {
371
+ constructor(value) {
372
+ super();
373
+ this.value = value;
374
+ // TODO: move unknown column to core and use it here
375
+ this.result = { value: emptyObject };
376
+ this.q = { expr: this };
377
+ }
378
+ makeSQL(ctx) {
379
+ return addValue(ctx.values, this.value);
380
+ }
381
+ }
382
+
383
+ const addCode = (code, add) => {
384
+ if (typeof add === "object") {
385
+ code.push(add);
386
+ } else {
387
+ const last = code.length - 1;
388
+ if (typeof code[last] === "string") {
389
+ code[last] = code[last] + add;
390
+ } else {
391
+ code.push(add);
392
+ }
393
+ }
394
+ };
395
+ const codeToString = (code, tabs, shift) => {
396
+ if (typeof code === "string") return `${tabs}${code}`;
397
+ const lines = [];
398
+ for (const item of code) {
399
+ if (typeof item === "string") {
400
+ lines.push(`${tabs}${item}`);
401
+ } else {
402
+ lines.push(codeToString(item, tabs + shift, shift));
403
+ }
404
+ }
405
+ return lines.length ? lines.join("\n") : "";
406
+ };
407
+ const columnDefaultArgumentToCode = (t, value) => {
408
+ if (typeof value === "object" && value && isRawSQL(value)) {
409
+ return value.toCode(t);
410
+ } else if (typeof value === "function") {
411
+ return value.toString();
412
+ } else if (typeof value === "string") {
413
+ return singleQuote(value);
414
+ } else {
415
+ return JSON.stringify(value);
416
+ }
417
+ };
418
+ const columnMethodsToCode = (methodNames, skip, aliases) => {
419
+ return (data, migration, skipLocal) => {
420
+ return migration ? "" : methodNames.map(
421
+ (key) => (skipLocal || skip)?.[key] || key === "min" && data.nonEmpty && data.min === 1 ? "" : columnMethodToCode(data, key, aliases?.[key])
422
+ ).join("");
423
+ };
424
+ };
425
+ const columnMethodToCode = (data, key, name = key) => {
426
+ const param = data[key];
427
+ if (param === void 0) return "";
428
+ const error = data.errors?.[key];
429
+ let params;
430
+ if (typeof param === "object" && param && param?.constructor === Object) {
431
+ const props = [];
432
+ for (const key2 in param) {
433
+ if (key2 === "message") continue;
434
+ const value = param[key2];
435
+ if (value !== void 0) {
436
+ props.push(
437
+ `${key2}: ${typeof value === "string" ? singleQuote(value) : value}`
438
+ );
439
+ }
440
+ }
441
+ if (error) props.push(`message: ${singleQuote(error)}`);
442
+ params = props.length ? `{ ${props.join(", ")} }` : "";
443
+ } else {
444
+ params = param === true ? "" : typeof param === "string" ? singleQuote(param) : param instanceof Date ? `new Date('${param.toISOString()}')` : param;
445
+ if (error) {
446
+ if (param !== true) params += ", ";
447
+ params += singleQuote(error);
448
+ }
449
+ }
450
+ return `.${name}(${params})`;
451
+ };
452
+ const stringDataToCode = columnMethodsToCode(stringMethodNames);
453
+ const numberDataToCode = columnMethodsToCode(
454
+ numberMethodNames,
455
+ void 0,
456
+ { lte: "max", gte: "min" }
457
+ );
458
+ const dateDataToCode = columnMethodsToCode(dateMethodNames);
459
+ const arrayDataToCode = columnMethodsToCode(arrayMethodNames);
460
+ const columnErrorMessagesToCode = (errors) => {
461
+ const props = [];
462
+ if (errors.required) {
463
+ props.push(`required: ${singleQuote(errors.required)},`);
464
+ }
465
+ if (errors.invalidType) {
466
+ props.push(`invalidType: ${singleQuote(errors.invalidType)},`);
467
+ }
468
+ const code = [];
469
+ if (!props.length) return code;
470
+ addCode(code, ".error({");
471
+ code.push(props);
472
+ addCode(code, "})");
473
+ return code;
474
+ };
475
+
476
+ function makeColumnNullable(column, inputSchema, outputSchema, querySchema) {
477
+ const c = setColumnData(column, "isNullable", true);
478
+ c.inputSchema = inputSchema;
479
+ c.outputSchema = outputSchema;
480
+ c.querySchema = querySchema;
481
+ return c;
482
+ }
483
+ const setColumnData = (q, key, value) => {
484
+ const cloned = Object.create(q);
485
+ cloned.data = { ...q.data, [key]: value };
486
+ return cloned;
487
+ };
488
+ const pushColumnData = (q, key, value) => {
489
+ const arr = q.data[key];
490
+ return setColumnData(
491
+ q,
492
+ key,
493
+ arr ? [...arr, value] : [value]
494
+ );
495
+ };
496
+ const setDataValue = (item, key, value, params) => {
497
+ var _a;
498
+ const cloned = Object.create(item);
499
+ cloned.data = { ...item.data, [key]: value };
500
+ if (params && (typeof params === "string" || params.message)) {
501
+ ((_a = cloned.data).errors ?? (_a.errors = {}))[key] = typeof params === "string" ? params : params.message;
502
+ }
503
+ return cloned;
504
+ };
505
+ let currentName;
506
+ function setCurrentColumnName(name) {
507
+ currentName = name;
508
+ }
509
+ const consumeColumnName = () => {
510
+ const name = currentName;
511
+ currentName = void 0;
512
+ return name;
513
+ };
514
+ const defaultNowFn = "now()";
515
+ let currentNowFn = defaultNowFn;
516
+ const setDefaultNowFn = (sql) => {
517
+ currentNowFn = `(${sql})`;
518
+ };
519
+ const getDefaultNowFn = () => currentNowFn;
520
+ let defaultLanguage = "english";
521
+ const setDefaultLanguage = (lang) => {
522
+ defaultLanguage = lang || "english";
523
+ };
524
+ const getDefaultLanguage = () => defaultLanguage;
525
+ class ColumnTypeBase {
526
+ constructor(schema, inputSchema, outputSchema = inputSchema, querySchema = inputSchema) {
527
+ this.inputSchema = inputSchema;
528
+ this.outputSchema = outputSchema;
529
+ this.querySchema = querySchema;
530
+ this.parse = schema.parse;
531
+ this.parseNull = schema.parseNull;
532
+ this.encode = schema.encode;
533
+ this.asType = schema.asType;
534
+ this.narrowType = schema.narrowType;
535
+ this.narrowAllTypes = schema.narrowAllTypes;
536
+ this.nullable = schema.nullable;
537
+ this.error = schema.error;
538
+ const name = consumeColumnName();
539
+ this.data = name ? { name } : {};
540
+ }
541
+ /**
542
+ * Set a default value to a column. Columns that have defaults become optional when creating a record.
543
+ *
544
+ * If you provide a value or a raw SQL, such default should be set on the column in migration to be applied on a database level.
545
+ *
546
+ * Or you can specify a callback that returns a value. This function will be called for each creating record. Such a default won't be applied to a database.
547
+ *
548
+ * ```ts
549
+ * export class Table extends BaseTable {
550
+ * readonly table = 'table';
551
+ * columns = this.setColumns((t) => ({
552
+ * // values as defaults:
553
+ * int: t.integer().default(123),
554
+ * text: t.text().default('text'),
555
+ *
556
+ * // raw SQL default:
557
+ * timestamp: t.timestamp().default(t.sql`now()`),
558
+ *
559
+ * // runtime default, each new records gets a new random value:
560
+ * random: t.numeric().default(() => Math.random()),
561
+ * }));
562
+ * }
563
+ * ```
564
+ *
565
+ * @param value - default value or a function returning a value
566
+ */
567
+ default(value) {
568
+ return setColumnData(this, "default", value);
569
+ }
570
+ /**
571
+ * Use `hasDefault` to let the column be omitted when creating records.
572
+ *
573
+ * It's better to use {@link default} instead so the value is explicit and serves as a hint.
574
+ */
575
+ hasDefault() {
576
+ return this;
577
+ }
578
+ /**
579
+ * Set a database-level validation check to a column. `check` accepts a raw SQL.
580
+ *
581
+ * ```ts
582
+ * import { change } from '../dbScript';
583
+ *
584
+ * change(async (db) => {
585
+ * await db.createTable('table', (t) => ({
586
+ * // validate rank to be from 1 to 10
587
+ * rank: t.integer().check(t.sql`1 >= "rank" AND "rank" <= 10`),
588
+ * // constraint name can be passed as a second argument
589
+ * column: t.integer().check(t.sql`...`, 'check_name'),
590
+ * // a single column can have multiple checks
591
+ * multiChecksColumn: t
592
+ * .integer()
593
+ * .check(t.sql`...`)
594
+ * .check(t.sql`...`, 'optional_name'),
595
+ * }));
596
+ * });
597
+ * ```
598
+ *
599
+ * @param sql - raw SQL expression
600
+ * @param name - to specify a constraint name
601
+ */
602
+ check(sql, name) {
603
+ return pushColumnData(this, "checks", { sql, name });
604
+ }
605
+ /**
606
+ * This method changes a column type without modifying its behavior.
607
+ * This is needed when converting columns to a validation schema, the converter will pick a different type specified by `.as`.
608
+ *
609
+ * Before calling `.as` need to use `.encode` with the input of the same type as the input of the target column,
610
+ * and `.parse` which returns the correct type.
611
+ *
612
+ * ```ts
613
+ * // column has the same type as t.integer()
614
+ * const column = t
615
+ * .string()
616
+ * .encode((input: number) => input)
617
+ * .parse((text) => parseInt(text))
618
+ * .as(t.integer());
619
+ * ```
620
+ *
621
+ * @param column - other column type to inherit from
622
+ */
623
+ as(column) {
624
+ return setColumnData(
625
+ this,
626
+ "as",
627
+ column
628
+ );
629
+ }
630
+ input(fn) {
631
+ const cloned = Object.create(this);
632
+ cloned.inputSchema = fn(this.inputSchema);
633
+ return cloned;
634
+ }
635
+ output(fn) {
636
+ const cloned = Object.create(this);
637
+ cloned.outputSchema = fn(this.outputSchema);
638
+ return cloned;
639
+ }
640
+ query(fn) {
641
+ const cloned = Object.create(this);
642
+ cloned.querySchema = fn(this.querySchema);
643
+ return cloned;
644
+ }
645
+ /**
646
+ * Set a database column name.
647
+ *
648
+ * @param name - name of the column in database.
649
+ */
650
+ name(name) {
651
+ return setColumnData(this, "name", name);
652
+ }
653
+ /**
654
+ * Append `select(false)` to a column to exclude it from the default selection.
655
+ * It won't be selected with `selectAll` or `select('*')` as well.
656
+ *
657
+ * ```ts
658
+ * export class UserTable extends BaseTable {
659
+ * readonly table = 'user';
660
+ * columns = this.setColumns((t) => ({
661
+ * id: t.identity().primaryKey(),
662
+ * name: t.string(),
663
+ * password: t.string().select(false),
664
+ * }));
665
+ * }
666
+ *
667
+ * // only id and name are selected, without password
668
+ * const user = await db.user.find(123);
669
+ *
670
+ * // password is still omitted, even with the wildcard
671
+ * const same = await db.user.find(123).select('*');
672
+ *
673
+ * const comment = await db.comment.find(123).select({
674
+ * // password is omitted in the sub-selects as well
675
+ * author: (q) => q.author,
676
+ * });
677
+ *
678
+ * // password is omitted here as well
679
+ * const created = await db.user.create(userData);
680
+ * ```
681
+ *
682
+ * Such a column can only be selected explicitly.
683
+ *
684
+ * ```ts
685
+ * const userWithPassword = await db.user.find(123).select('*', 'password');
686
+ * ```
687
+ */
688
+ select(value) {
689
+ return setColumnData(this, "explicitSelect", !value);
690
+ }
691
+ /**
692
+ * Forbid the column to be used in [create](/guide/create-update-delete.html#create-insert) and [update](/guide/create-update-delete.html#update) methods.
693
+ *
694
+ * `readOnly` column is still can be set from a [hook](http://localhost:5173/guide/hooks.html#set-values-before-create-or-update).
695
+ *
696
+ * `readOnly` column can be used together with a `default`.
697
+ *
698
+ * ```ts
699
+ * export class Table extends BaseTable {
700
+ * readonly table = 'table';
701
+ * columns = this.setColumns((t) => ({
702
+ * id: t.identity().primaryKey(),
703
+ * column: t.string().default(() => 'default value'),
704
+ * another: t.string().readOnly(),
705
+ * }));
706
+ *
707
+ * init(orm: typeof db) {
708
+ * this.beforeSave(({ set }) => {
709
+ * set({ another: 'value' });
710
+ * });
711
+ * }
712
+ * }
713
+ *
714
+ * // later in the code
715
+ * db.table.create({ column: 'value' }); // TS error, runtime error
716
+ * ```
717
+ */
718
+ readOnly() {
719
+ return setColumnData(this, "appReadOnly", true);
720
+ }
721
+ /**
722
+ * Set a column value when creating a record.
723
+ * This works for [readOnly](#readonly) columns as well.
724
+ *
725
+ * If no value or undefined is returned, the hook won't have any effect.
726
+ *
727
+ * ```ts
728
+ * export class Table extends BaseTable {
729
+ * readonly table = 'table';
730
+ * columns = this.setColumns((t) => ({
731
+ * id: t.identity().primaryKey(),
732
+ * column: t.string().setOnCreate(() => 'value'),
733
+ * }));
734
+ * }
735
+ * ```
736
+ */
737
+ setOnCreate(fn) {
738
+ return setColumnData(this, "setOnCreate", fn);
739
+ }
740
+ /**
741
+ * Set a column value when updating a record.
742
+ * This works for [readOnly](#readonly) columns as well.
743
+ *
744
+ * If no value or undefined is returned, the hook won't have any effect.
745
+ *
746
+ * ```ts
747
+ * export class Table extends BaseTable {
748
+ * readonly table = 'table';
749
+ * columns = this.setColumns((t) => ({
750
+ * id: t.identity().primaryKey(),
751
+ * column: t.string().setOnUpdate(() => 'value'),
752
+ * }));
753
+ * }
754
+ * ```
755
+ */
756
+ setOnUpdate(fn) {
757
+ return setColumnData(this, "setOnUpdate", fn);
758
+ }
759
+ /**
760
+ * Set a column value when creating or updating a record.
761
+ * This works for [readOnly](#readonly) columns as well.
762
+ *
763
+ * If no value or undefined is returned, the hook won't have any effect.
764
+ *
765
+ * ```ts
766
+ * export class Table extends BaseTable {
767
+ * readonly table = 'table';
768
+ * columns = this.setColumns((t) => ({
769
+ * id: t.identity().primaryKey(),
770
+ * column: t.string().setOnSave(() => 'value'),
771
+ * }));
772
+ * }
773
+ * ```
774
+ */
775
+ setOnSave(fn) {
776
+ return setColumnData(this, "setOnSave", fn);
777
+ }
778
+ }
779
+
780
+ const snakeCaseKey = Symbol("snakeCase");
781
+
782
+ class SimpleRawSQL extends RawSQLBase {
783
+ // Simply returning SQL provided in the constructor.
784
+ makeSQL() {
785
+ return this._sql;
786
+ }
787
+ }
788
+ const raw$1 = (sql) => new SimpleRawSQL(sql);
789
+ const makeTimestamps = (timestamp) => {
790
+ const now = getDefaultNowFn();
791
+ const nowRaw = raw$1(now);
792
+ const updatedAt = timestamp().default(nowRaw);
793
+ let updater;
794
+ updatedAt.data.modifyQuery = (q, column) => {
795
+ if (!updater) {
796
+ const key = column.data.key;
797
+ updater = (data) => {
798
+ if (data.some((item) => {
799
+ return typeof item !== "function" && item[key];
800
+ }))
801
+ return;
802
+ return { [column.data.key]: nowRaw };
803
+ };
804
+ }
805
+ pushOrNewArrayToObjectImmutable(
806
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
807
+ q.q,
808
+ "updateData",
809
+ updater
810
+ );
811
+ };
812
+ updatedAt.data.defaultTimestamp = "updatedAt";
813
+ const createdAt = timestamp().default(nowRaw);
814
+ createdAt.data.defaultTimestamp = "createdAt";
815
+ return {
816
+ createdAt,
817
+ updatedAt
818
+ };
819
+ };
820
+ const timestampHelpers = {
821
+ timestamps() {
822
+ return makeTimestamps(this.timestamp);
823
+ },
824
+ timestampsNoTZ() {
825
+ return makeTimestamps(this.timestampNoTZ);
826
+ }
827
+ };
828
+
829
+ const logColors = {
830
+ boldCyanBright: (message) => `\x1B[1m\x1B[96m${message}\x1B[39m\x1B[22m`,
831
+ boldBlue: (message) => `\x1B[1m\x1B[34m${message}\x1B[39m\x1B[22m`,
832
+ boldYellow: (message) => `\x1B[1m\x1B[33m${message}\x1B[39m\x1B[22m`,
833
+ boldMagenta: (message) => `\x1B[1m\x1B[33m${message}\x1B[39m\x1B[22m`,
834
+ boldRed: (message) => `\x1B[1m\x1B[31m${message}\x1B[39m\x1B[22m`
835
+ };
836
+
837
+ class QueryHookUtils {
838
+ constructor(query, columns, key) {
839
+ this.query = query;
840
+ this.columns = columns;
841
+ this.key = key;
842
+ this.set = (data) => {
843
+ const set = {};
844
+ for (const key in data) {
845
+ if (data[key] !== void 0) {
846
+ set[key] = data[key];
847
+ }
848
+ }
849
+ pushQueryValueImmutable(this.query, this.key, set);
850
+ };
851
+ }
852
+ }
853
+
854
+ const queryColumnNameToKey = (q, name) => {
855
+ let map = q.internal.columnNameToKeyMap;
856
+ if (!map) {
857
+ q.internal.columnNameToKeyMap = map = /* @__PURE__ */ new Map();
858
+ const { shape } = q;
859
+ for (const key in q.shape) {
860
+ const column = shape[key];
861
+ map.set(column.data.name ?? key, key);
862
+ }
863
+ }
864
+ return map.get(name);
865
+ };
866
+
867
+ var __typeError = (msg) => {
868
+ throw TypeError(msg);
869
+ };
870
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
871
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
872
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
873
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
874
+ var _query, _query2;
875
+ class OrchidOrmError extends Error {
876
+ }
877
+ class NotFoundError extends OrchidOrmError {
878
+ constructor(query, message = "Record is not found") {
879
+ super(message);
880
+ // `#query` is private to prevent it from serializing to not cause problems to test runner reports
881
+ __privateAdd(this, _query);
882
+ __privateSet(this, _query, query);
883
+ }
884
+ get query() {
885
+ return __privateGet(this, _query);
886
+ }
887
+ }
888
+ _query = new WeakMap();
889
+ class OrchidOrmInternalError extends Error {
890
+ constructor(query, message, data) {
891
+ super(message);
892
+ this.data = data;
893
+ // `#query` is private to prevent it from serializing to not cause problems to test runner reports
894
+ __privateAdd(this, _query2);
895
+ __privateSet(this, _query2, query);
896
+ }
897
+ get query() {
898
+ return __privateGet(this, _query2);
899
+ }
900
+ }
901
+ _query2 = new WeakMap();
902
+ class QueryError extends OrchidOrmInternalError {
903
+ get isUnique() {
904
+ return this.code === "23505";
905
+ }
906
+ get columns() {
907
+ if (this.columnsCache) return this.columnsCache;
908
+ const columns = {};
909
+ if (this.detail) {
910
+ const list = this.detail.match(/\((.*)\)=/)?.[1];
911
+ if (list) {
912
+ list.split(", ").forEach((item) => {
913
+ const column = item.startsWith('"') ? item.slice(1, -1) : item;
914
+ const key = queryColumnNameToKey(this.query, column) ?? column;
915
+ columns[key] = true;
916
+ });
917
+ }
918
+ }
919
+ return this.columnsCache = columns;
920
+ }
921
+ }
922
+ class MoreThanOneRowError extends OrchidOrmInternalError {
923
+ constructor(query, message) {
924
+ super(query, message);
925
+ }
926
+ }
927
+ class UnhandledTypeError extends OrchidOrmInternalError {
928
+ constructor(query, value) {
929
+ super(query, `Unhandled type: ${JSON.stringify(value)} received`);
930
+ }
931
+ }
932
+
933
+ const getPrimaryKeys = (q) => {
934
+ var _a;
935
+ return (_a = q.internal).primaryKeys ?? (_a.primaryKeys = collectPrimaryKeys(q));
936
+ };
937
+ const requirePrimaryKeys = (q, message) => {
938
+ const primaryKeys = getPrimaryKeys(q);
939
+ if (!primaryKeys.length) {
940
+ throw new OrchidOrmInternalError(q, message);
941
+ }
942
+ return primaryKeys;
943
+ };
944
+ const collectPrimaryKeys = (q) => {
945
+ const primaryKeys = [];
946
+ const { shape } = q.q;
947
+ for (const key in shape) {
948
+ if (shape[key].data.primaryKey) {
949
+ primaryKeys.push(key);
950
+ }
951
+ }
952
+ const pkey = q.internal.tableData.primaryKey;
953
+ if (pkey) {
954
+ primaryKeys.push(...pkey.columns);
955
+ }
956
+ return primaryKeys;
957
+ };
958
+
959
+ const newDelayedRelationSelect = (query) => ({
960
+ query
961
+ });
962
+ const setDelayedRelation = (d, as, value) => {
963
+ (d.value ?? (d.value = {}))[as] = value;
964
+ };
965
+
966
+ const isRelationQuery = (q) => "joinQuery" in q;
967
+
968
+ const _getQueryAs = (q) => q.q.as;
969
+ const _getQueryFreeAlias = (q, as) => q.aliases ? getFreeAlias(q.aliases, as) : as;
970
+ const _checkIfAliased = (q, as, name) => {
971
+ return q.q.aliases?.[as] === name;
972
+ };
973
+ const _getQueryAliasOrName = (q, as) => {
974
+ return q.aliases?.[as] || as;
975
+ };
976
+ const _getQueryOuterAliases = (q) => {
977
+ return q.outerAliases;
978
+ };
979
+ const _setQueryAs = (self, as) => {
980
+ const { q } = self;
981
+ q.as = as;
982
+ q.aliases = {
983
+ ...q.aliases,
984
+ [as]: _getQueryFreeAlias(q, as)
985
+ };
986
+ return self;
987
+ };
988
+ const _setQueryAlias = (q, name, as) => {
989
+ q.q.aliases = { ...q.q.aliases, [as]: name };
990
+ };
991
+ const _setSubQueryAliases = (q) => {
992
+ q.q.outerAliases = q.q.aliases;
993
+ };
994
+ const _applyRelationAliases = (query, relQueryData) => {
995
+ const aliases = query.q.as ? { ...query.q.aliases } : { ...query.q.aliases, [query.table]: query.table };
996
+ const relAliases = relQueryData.aliases;
997
+ for (const as in relAliases) {
998
+ aliases[as] = getFreeAlias(aliases, as);
999
+ }
1000
+ relQueryData.as = aliases[relQueryData.as];
1001
+ relQueryData.aliases = aliases;
1002
+ };
1003
+ const _copyQueryAliasToQuery = (fromQuery, toQuery, key) => {
1004
+ const name = _getQueryAliasOrName(fromQuery.q, key);
1005
+ if (name !== key) {
1006
+ _setQueryAlias(toQuery, name, key);
1007
+ }
1008
+ return name;
1009
+ };
1010
+
1011
+ const setParserToQuery = (query, key, parser) => {
1012
+ if (query.parsers) query.parsers[key] = parser;
1013
+ else query.parsers = { [key]: parser };
1014
+ };
1015
+ const getQueryParsers = (q, hookSelect) => {
1016
+ if (hookSelect) {
1017
+ const parsers = { ...q.q.parsers };
1018
+ const { defaultParsers } = q.q;
1019
+ if (defaultParsers) {
1020
+ for (const [key, value] of hookSelect) {
1021
+ const parser = defaultParsers[key];
1022
+ if (parser) {
1023
+ parsers[value.as || key] = parser;
1024
+ }
1025
+ }
1026
+ }
1027
+ return parsers;
1028
+ }
1029
+ return q.q.select ? q.q.parsers : q.q.defaultParsers;
1030
+ };
1031
+
1032
+ const _addToHookSelect = (query, selects) => {
1033
+ const map = query.q.hookSelect = new Map(
1034
+ query.q.hookSelect
1035
+ );
1036
+ for (const key of selects) {
1037
+ map.set(key, { select: key });
1038
+ }
1039
+ };
1040
+ const _addToHookSelectWithTable = (query, selects, table) => {
1041
+ const map = query.q.hookSelect = new Map(
1042
+ query.q.hookSelect
1043
+ );
1044
+ for (const column of selects) {
1045
+ map.set(column, { select: `${table}.${column}` });
1046
+ }
1047
+ };
1048
+
6
1049
  const used = [];
7
1050
  const literalValues = [];
8
1051
  const templateLiteralToSQL = (template, ctx, quotedAs) => {
@@ -5214,11 +6257,12 @@ const then = async (q, adapter, trx, beforeHooks, afterHooks, afterCommitHooks,
5214
6257
  );
5215
6258
  }
5216
6259
  const localSql = sql = q.toSQL();
5217
- const { hookSelect, delayedRelationSelect } = sql;
6260
+ const { tableHook, delayedRelationSelect } = sql;
5218
6261
  const { returnType = "all" } = query;
5219
- const tempReturnType = hookSelect || returnType === "rows" && q.q.batchParsers || delayedRelationSelect?.value ? "all" : returnType;
6262
+ const tempReturnType = tableHook?.select || returnType === "rows" && q.q.batchParsers || delayedRelationSelect?.value ? "all" : returnType;
5220
6263
  let result;
5221
6264
  let queryResult;
6265
+ let cteData;
5222
6266
  if ("text" in sql) {
5223
6267
  if (query.autoPreparedStatements) {
5224
6268
  sql.name = queriesNames[sql.text] || (queriesNames[sql.text] = (nameI++).toString(36));
@@ -5235,8 +6279,20 @@ const then = async (q, adapter, trx, beforeHooks, afterHooks, afterCommitHooks,
5235
6279
  log.afterQuery(sql, logData);
5236
6280
  sql = void 0;
5237
6281
  }
6282
+ if (localSql.cteHooks?.hasSelect) {
6283
+ const lastRowI = queryResult.rows.length - 1;
6284
+ const lastFieldI = queryResult.fields.length - 1;
6285
+ const fieldName = queryResult.fields[lastFieldI].name;
6286
+ cteData = queryResult.rows[lastRowI][fieldName];
6287
+ queryResult.fields.length = lastFieldI;
6288
+ queryResult.rowCount--;
6289
+ queryResult.rows.length = lastRowI;
6290
+ for (const row of queryResult.rows) {
6291
+ delete row[fieldName];
6292
+ }
6293
+ }
5238
6294
  if (query.patchResult) {
5239
- await query.patchResult(q, hookSelect, queryResult);
6295
+ await query.patchResult(q, tableHook?.select, queryResult);
5240
6296
  }
5241
6297
  result = query.handleResult(q, tempReturnType, queryResult, localSql);
5242
6298
  } else {
@@ -5274,15 +6330,15 @@ const then = async (q, adapter, trx, beforeHooks, afterHooks, afterCommitHooks,
5274
6330
  if (log) log.afterQuery(commitSql, logData);
5275
6331
  }
5276
6332
  if (query.patchResult) {
5277
- await query.patchResult(q, hookSelect, queryResult);
6333
+ await query.patchResult(q, tableHook?.select, queryResult);
5278
6334
  }
5279
6335
  result = query.handleResult(q, tempReturnType, queryResult, localSql);
5280
6336
  }
5281
6337
  let tempColumns;
5282
6338
  let renames;
5283
- if (hookSelect) {
5284
- for (const column of hookSelect.keys()) {
5285
- const { as, temp } = hookSelect.get(column);
6339
+ if (tableHook?.select) {
6340
+ for (const column of tableHook.select.keys()) {
6341
+ const { as, temp } = tableHook.select.get(column);
5286
6342
  if (as) {
5287
6343
  (renames ?? (renames = {}))[column] = as;
5288
6344
  }
@@ -5304,42 +6360,103 @@ const then = async (q, adapter, trx, beforeHooks, afterHooks, afterCommitHooks,
5304
6360
  if (promise2) await promise2;
5305
6361
  }
5306
6362
  }
5307
- const hasAfterHook = afterHooks || afterCommitHooks || query.after;
6363
+ let cteAfterHooks;
6364
+ let cteAfterCommitHooks;
6365
+ if (localSql.cteHooks) {
6366
+ for (const cteName in localSql.cteHooks.tableHooks) {
6367
+ const hook = localSql.cteHooks.tableHooks[cteName];
6368
+ const data = cteData?.[cteName];
6369
+ if (data) {
6370
+ let hasParsers;
6371
+ const parsers = {};
6372
+ for (const key in hook.shape) {
6373
+ if (hook.shape[key]._parse) {
6374
+ hasParsers = true;
6375
+ parsers[key] = hook.shape[key]._parse;
6376
+ }
6377
+ }
6378
+ if (hasParsers) {
6379
+ for (const row of data) {
6380
+ parseRecord(parsers, row);
6381
+ }
6382
+ }
6383
+ }
6384
+ if (hook.tableHook.after) {
6385
+ (cteAfterHooks ?? (cteAfterHooks = [])).push(
6386
+ ...hook.tableHook.after.map(
6387
+ (fn) => () => fn(cteData?.[cteName], q)
6388
+ )
6389
+ );
6390
+ }
6391
+ if (hook.tableHook.afterCommit) {
6392
+ (cteAfterCommitHooks ?? (cteAfterCommitHooks = [])).push(
6393
+ ...hook.tableHook.afterCommit.map(
6394
+ (fn) => () => fn(cteData?.[cteName], q)
6395
+ )
6396
+ );
6397
+ }
6398
+ }
6399
+ }
6400
+ const hasAfterHook = afterHooks || afterCommitHooks || query.after || cteAfterHooks || cteAfterCommitHooks;
5308
6401
  if (hasAfterHook) {
5309
6402
  if (queryResult.rowCount) {
5310
- if (afterHooks || query.after) {
6403
+ if (afterHooks || query.after || cteAfterHooks) {
5311
6404
  const args = [result, q];
5312
6405
  await Promise.all(
5313
- [...afterHooks || emptyArray, ...query.after || emptyArray].map(
5314
- callAfterHook,
5315
- args
5316
- )
6406
+ [
6407
+ ...afterHooks || emptyArray,
6408
+ ...query.after || emptyArray,
6409
+ ...cteAfterHooks || emptyArray
6410
+ ].map(callAfterHook, args)
5317
6411
  );
5318
6412
  }
5319
- if (afterCommitHooks) {
6413
+ if (afterCommitHooks || cteAfterCommitHooks) {
5320
6414
  if (isInUserTransaction(trx)) {
5321
- (trx.afterCommit ?? (trx.afterCommit = [])).push(
5322
- result,
5323
- q,
5324
- afterCommitHooks
5325
- );
6415
+ if (afterCommitHooks) {
6416
+ (trx.afterCommit ?? (trx.afterCommit = [])).push(
6417
+ result,
6418
+ q,
6419
+ afterCommitHooks
6420
+ );
6421
+ }
6422
+ if (cteAfterCommitHooks) {
6423
+ (trx.afterCommit ?? (trx.afterCommit = [])).push(
6424
+ result,
6425
+ q,
6426
+ cteAfterCommitHooks
6427
+ );
6428
+ }
5326
6429
  } else {
5327
6430
  const localResult = result;
5328
6431
  queueMicrotask(async () => {
5329
6432
  const promises = [];
5330
- for (const fn of afterCommitHooks) {
5331
- try {
5332
- promises.push(
5333
- fn(localResult, q)
5334
- );
5335
- } catch (err) {
5336
- promises.push(Promise.reject(err));
6433
+ if (afterCommitHooks) {
6434
+ for (const fn of afterCommitHooks) {
6435
+ try {
6436
+ promises.push(
6437
+ fn(localResult, q)
6438
+ );
6439
+ } catch (err) {
6440
+ promises.push(Promise.reject(err));
6441
+ }
6442
+ }
6443
+ }
6444
+ if (cteAfterCommitHooks) {
6445
+ for (const fn of cteAfterCommitHooks) {
6446
+ try {
6447
+ promises.push(fn());
6448
+ } catch (err) {
6449
+ promises.push(Promise.reject(err));
6450
+ }
5337
6451
  }
5338
6452
  }
5339
6453
  await _runAfterCommitHooks(
5340
6454
  localResult,
5341
6455
  promises,
5342
- () => afterCommitHooks.map((h) => h.name),
6456
+ () => [
6457
+ ...afterCommitHooks || emptyArray,
6458
+ ...cteAfterCommitHooks || emptyArray
6459
+ ].map((h) => h.name),
5343
6460
  q.q.catchAfterCommitErrors
5344
6461
  );
5345
6462
  });
@@ -5400,7 +6517,7 @@ const then = async (q, adapter, trx, beforeHooks, afterHooks, afterCommitHooks,
5400
6517
  }
5401
6518
  const promise = parseBatch(q, queryResult, delayedRelationSelect);
5402
6519
  if (promise) await promise;
5403
- if (hookSelect || tempReturnType !== returnType) {
6520
+ if (tableHook?.select || tempReturnType !== returnType) {
5404
6521
  if (renames) {
5405
6522
  const renamedResult = Array.from({
5406
6523
  length: result.length
@@ -5468,7 +6585,7 @@ const execQuery = (adapter, method, sql) => {
5468
6585
  });
5469
6586
  };
5470
6587
  const handleResult = (q, returnType, result, sql, isSubQuery) => {
5471
- const parsers = getQueryParsers(q, sql.hookSelect);
6588
+ const parsers = getQueryParsers(q, sql.tableHook?.select);
5472
6589
  switch (returnType) {
5473
6590
  case "all": {
5474
6591
  if (q.q.throwOnNotFound && result.rows.length === 0)
@@ -6393,6 +7510,7 @@ class RowToJsonExpression extends Expression {
6393
7510
  q.q,
6394
7511
  `"${getQueryAs(q)}"`,
6395
7512
  q.q.hookSelect,
7513
+ void 0,
6396
7514
  aliases,
6397
7515
  void 0,
6398
7516
  jsonList
@@ -6433,7 +7551,7 @@ const withToSql = (ctx, items) => {
6433
7551
  if (!item) continue;
6434
7552
  let inner;
6435
7553
  if (item.q) {
6436
- inner = getSqlText(toSQL(item.q, ctx));
7554
+ inner = toSubSqlText(item.q, item.n, ctx);
6437
7555
  } else {
6438
7556
  inner = item.s.toSQL(ctx, `"${item.n}"`);
6439
7557
  }
@@ -6461,7 +7579,7 @@ const pushOrAppendWithSql = (ctx, query, items) => {
6461
7579
  }
6462
7580
  };
6463
7581
 
6464
- const makeInsertSql = (ctx, q, query, quotedAs) => {
7582
+ const makeInsertSql = (ctx, q, query, quotedAs, isSubSql) => {
6465
7583
  let { columns } = query;
6466
7584
  const { shape, inCTE, hookCreateSet } = query;
6467
7585
  const QueryClass = ctx.qb.constructor;
@@ -6482,14 +7600,17 @@ const makeInsertSql = (ctx, q, query, quotedAs) => {
6482
7600
  (column) => `"${shape[column]?.data.name || column}"`
6483
7601
  );
6484
7602
  let runtimeDefaults;
7603
+ let runtimeDefaultColumns;
6485
7604
  if (q.internal.runtimeDefaultColumns) {
6486
7605
  runtimeDefaults = [];
7606
+ runtimeDefaultColumns = [];
6487
7607
  for (const key of q.internal.runtimeDefaultColumns) {
6488
7608
  if (!columns.includes(key)) {
6489
7609
  const column = shape[key];
6490
7610
  columns.push(key);
6491
7611
  quotedColumns.push(`"${column.data.name || key}"`);
6492
7612
  runtimeDefaults.push(column.data.runtimeDefault);
7613
+ runtimeDefaultColumns.push(key);
6493
7614
  }
6494
7615
  }
6495
7616
  }
@@ -6551,7 +7672,10 @@ const makeInsertSql = (ctx, q, query, quotedAs) => {
6551
7672
  const name = shape[merge]?.data.name || merge;
6552
7673
  sql = `DO UPDATE SET "${name}" = excluded."${name}"`;
6553
7674
  } else if ("except" in merge) {
6554
- sql = mergeColumnsSql(columns, quotedColumns, target, merge.except);
7675
+ sql = mergeColumnsSql(columns, quotedColumns, target, [
7676
+ ...toArray(merge.except),
7677
+ ...runtimeDefaultColumns || emptyArray
7678
+ ]);
6555
7679
  } else {
6556
7680
  sql = `DO UPDATE SET ${merge.reduce((sql2, item, i) => {
6557
7681
  const name = shape[item]?.data.name || item;
@@ -6559,7 +7683,12 @@ const makeInsertSql = (ctx, q, query, quotedAs) => {
6559
7683
  }, "")}`;
6560
7684
  }
6561
7685
  } else {
6562
- sql = mergeColumnsSql(columns, quotedColumns, target);
7686
+ sql = mergeColumnsSql(
7687
+ columns,
7688
+ quotedColumns,
7689
+ target,
7690
+ runtimeDefaultColumns
7691
+ );
6563
7692
  }
6564
7693
  ctx.sql.push(sql);
6565
7694
  } else if (query.onConflict.set) {
@@ -6576,26 +7705,11 @@ const makeInsertSql = (ctx, q, query, quotedAs) => {
6576
7705
  }
6577
7706
  }
6578
7707
  pushWhereStatementSql(ctx, q, query, quotedAs);
6579
- let returning;
6580
7708
  let delayedRelationSelect;
6581
- if (inCTE) {
6582
- const select = inCTE.returning?.select;
6583
- returning = {
6584
- select: inCTE.selectNum || !select ? select ? "1, " + select : "1" : select,
6585
- hookSelect: inCTE.returning?.hookSelect
6586
- };
6587
- } else {
7709
+ if (!inCTE) {
6588
7710
  delayedRelationSelect = q.q.selectRelation ? newDelayedRelationSelect(q) : void 0;
6589
- returning = makeReturningSql(
6590
- ctx,
6591
- q,
6592
- query,
6593
- quotedAs,
6594
- delayedRelationSelect,
6595
- 2
6596
- );
6597
7711
  }
6598
- if (returning.select) ctx.sql.push("RETURNING", returning.select);
7712
+ const returningPos = ctx.sql.length;
6599
7713
  let insertManyFromValuesAs;
6600
7714
  if (insertFrom) {
6601
7715
  if (values.length < 2) {
@@ -6664,6 +7778,17 @@ const makeInsertSql = (ctx, q, query, quotedAs) => {
6664
7778
  addWithSqls(ctx, hasWith, withSqls, valuesPos, insertSql);
6665
7779
  ctx.sql[valuesPos] = startingKeyword + valuesSql.join(", ") + valuesAppend;
6666
7780
  ctxValues.length = currentValuesLen;
7781
+ const returning2 = makeInsertReturning(
7782
+ ctx,
7783
+ q,
7784
+ query,
7785
+ quotedAs,
7786
+ delayedRelationSelect,
7787
+ isSubSql
7788
+ );
7789
+ if (returning2.select) {
7790
+ ctx.sql[returningPos] = "RETURNING " + returning2.select;
7791
+ }
6667
7792
  batch = pushOrNewArray(batch, {
6668
7793
  text: ctx.sql.join(" "),
6669
7794
  values: ctxValues
@@ -6691,8 +7816,19 @@ const makeInsertSql = (ctx, q, query, quotedAs) => {
6691
7816
  text: ctx.sql.join(" "),
6692
7817
  values: ctxValues
6693
7818
  });
7819
+ const returning2 = makeInsertReturning(
7820
+ ctx,
7821
+ q,
7822
+ query,
7823
+ quotedAs,
7824
+ delayedRelationSelect,
7825
+ isSubSql
7826
+ );
7827
+ if (returning2.select) {
7828
+ ctx.sql[returningPos] = "RETURNING " + returning2.select;
7829
+ }
6694
7830
  return {
6695
- hookSelect: returning.hookSelect,
7831
+ tableHook: returning2.tableHook,
6696
7832
  delayedRelationSelect,
6697
7833
  batch
6698
7834
  };
@@ -6703,13 +7839,47 @@ const makeInsertSql = (ctx, q, query, quotedAs) => {
6703
7839
  ctx.sql[valuesPos] += ' WHERE NOT EXISTS (SELECT 1 FROM "f")';
6704
7840
  }
6705
7841
  }
7842
+ const returning = makeInsertReturning(
7843
+ ctx,
7844
+ q,
7845
+ query,
7846
+ quotedAs,
7847
+ delayedRelationSelect,
7848
+ isSubSql
7849
+ );
7850
+ if (returning.select) {
7851
+ ctx.sql[returningPos] = "RETURNING " + returning.select;
7852
+ }
6706
7853
  return {
6707
- hookSelect: returning.hookSelect,
7854
+ tableHook: returning.tableHook,
6708
7855
  delayedRelationSelect,
6709
7856
  text: ctx.sql.join(" "),
6710
7857
  values: ctx.values
6711
7858
  };
6712
7859
  };
7860
+ const makeInsertReturning = (ctx, q, query, quotedAs, delayedRelationSelect, isSubSql) => {
7861
+ const { inCTE } = query;
7862
+ if (inCTE) {
7863
+ const select = inCTE.returning?.select;
7864
+ return {
7865
+ select: inCTE.selectNum || !select ? select ? "1, " + select : "1" : select,
7866
+ tableHook: inCTE.returning?.hookSelect && {
7867
+ select: inCTE.returning?.hookSelect
7868
+ }
7869
+ };
7870
+ } else {
7871
+ return makeReturningSql(
7872
+ ctx,
7873
+ q,
7874
+ query,
7875
+ quotedAs,
7876
+ delayedRelationSelect,
7877
+ "Create",
7878
+ void 0,
7879
+ isSubSql
7880
+ );
7881
+ }
7882
+ };
6713
7883
  const addWithSqls = (ctx, hasWith, withSqls, valuesPos, insertSql) => {
6714
7884
  if (withSqls.length) {
6715
7885
  if (hasWith) {
@@ -6886,33 +8056,32 @@ const encodeValue = (ctx, values, q, QueryClass, value, quotedAs) => {
6886
8056
  if (value instanceof Expression) {
6887
8057
  return value.toSQL(ctx, quotedAs);
6888
8058
  } else if (value instanceof QueryClass) {
6889
- return `(${getSqlText(joinSubQuery(q, value).toSQL(ctx))})`;
8059
+ return `(${toSubSqlText(
8060
+ joinSubQuery(q, value),
8061
+ value.q.as,
8062
+ ctx
8063
+ )})`;
6890
8064
  } else if ("fromHook" in value) {
6891
8065
  return value.fromHook;
6892
8066
  }
6893
8067
  }
6894
8068
  return value === void 0 ? "DEFAULT" : addValue(values, value);
6895
8069
  };
6896
- const hookSelectKeys = [
6897
- null,
6898
- "afterUpdateSelect",
6899
- "afterCreateSelect",
6900
- "afterDeleteSelect"
6901
- ];
6902
- const makeReturningSql = (ctx, q, data, quotedAs, delayedRelationSelect, hookSelectI, addHookSelectI) => {
8070
+ const makeReturningSql = (ctx, q, data, quotedAs, delayedRelationSelect, hookPurpose, addHookPurpose, isSubSql) => {
6903
8071
  if (data.inCTE) {
6904
- if (hookSelectI !== 2) {
8072
+ if (hookPurpose !== "Create") {
6905
8073
  const returning = makeReturningSql(
6906
8074
  ctx,
6907
8075
  q,
6908
8076
  data,
6909
8077
  quotedAs,
6910
8078
  delayedRelationSelect,
6911
- 2,
6912
- hookSelectI
8079
+ "Create",
8080
+ hookPurpose,
8081
+ isSubSql
6913
8082
  );
6914
- if (returning.hookSelect) {
6915
- for (const [key, value] of returning.hookSelect) {
8083
+ if (returning.tableHook?.select) {
8084
+ for (const [key, value] of returning.tableHook.select) {
6916
8085
  data.inCTE.targetHookSelect.set(key, value);
6917
8086
  }
6918
8087
  }
@@ -6922,12 +8091,18 @@ const makeReturningSql = (ctx, q, data, quotedAs, delayedRelationSelect, hookSel
6922
8091
  return data.inCTE.returning;
6923
8092
  }
6924
8093
  }
6925
- const hookSelect = hookSelectI && data[hookSelectKeys[hookSelectI]];
8094
+ const hookSelect = hookPurpose && data[`after${hookPurpose}Select`];
6926
8095
  const { select } = data;
6927
- if (!q.q.hookSelect && !hookSelect?.size && !select?.length && !addHookSelectI) {
6928
- return { hookSelect: hookSelect && /* @__PURE__ */ new Map() };
8096
+ if (!q.q.hookSelect && !hookSelect?.size && !select?.length && !hookPurpose) {
8097
+ const select2 = hookSelect && /* @__PURE__ */ new Map();
8098
+ return {
8099
+ select: !isSubSql && ctx.cteHooks?.hasSelect ? "NULL" : void 0,
8100
+ tableHook: select2 && {
8101
+ select: select2
8102
+ }
8103
+ };
6929
8104
  }
6930
- const otherCTEHookSelect = addHookSelectI && data[hookSelectKeys[addHookSelectI]];
8105
+ const otherCTEHookSelect = addHookPurpose && data[`after${addHookPurpose}Select`];
6931
8106
  let tempSelect;
6932
8107
  if (q.q.hookSelect || hookSelect || otherCTEHookSelect || q.q.selectRelation) {
6933
8108
  tempSelect = new Map(q.q.hookSelect);
@@ -6956,18 +8131,25 @@ const makeReturningSql = (ctx, q, data, quotedAs, delayedRelationSelect, hookSel
6956
8131
  quotedAs,
6957
8132
  tempSelect,
6958
8133
  void 0,
8134
+ void 0,
6959
8135
  true,
6960
8136
  void 0,
6961
8137
  delayedRelationSelect
6962
8138
  );
6963
8139
  }
8140
+ const after = hookPurpose && data[`after${hookPurpose}`];
8141
+ const afterCommit = hookPurpose && data[`after${hookPurpose}Commit`];
6964
8142
  return {
6965
- select: sql,
6966
- hookSelect: tempSelect
8143
+ select: !isSubSql && ctx.cteHooks?.hasSelect ? sql ? "NULL, " + sql : "NULL" : sql,
8144
+ tableHook: (tempSelect || after || afterCommit) && {
8145
+ select: tempSelect,
8146
+ after: data.after && after ? [...data.after, ...after] : after ? after : data.after,
8147
+ afterCommit
8148
+ }
6967
8149
  };
6968
8150
  };
6969
8151
 
6970
- const pushSelectSql = (ctx, table, query, quotedAs, aliases) => {
8152
+ const pushSelectSql = (ctx, table, query, quotedAs, isSubSql, aliases) => {
6971
8153
  if (query.selectCache) {
6972
8154
  ctx.sql.push(query.selectCache.sql);
6973
8155
  if (aliases) aliases.push(...query.selectCache.aliases);
@@ -6978,12 +8160,13 @@ const pushSelectSql = (ctx, table, query, quotedAs, aliases) => {
6978
8160
  query,
6979
8161
  quotedAs,
6980
8162
  query.hookSelect,
8163
+ isSubSql,
6981
8164
  aliases
6982
8165
  );
6983
8166
  if (sql) ctx.sql.push(sql);
6984
8167
  }
6985
8168
  };
6986
- const selectToSql = (ctx, table, query, quotedAs, hookSelect = query.hookSelect, aliases, skipCTE, jsonList, delayedRelationSelect) => {
8169
+ const selectToSql = (ctx, table, query, quotedAs, hookSelect = query.hookSelect, isSubSql, aliases, skipCTE, jsonList, delayedRelationSelect) => {
6987
8170
  if (query.inCTE && !skipCTE) {
6988
8171
  const { select } = makeReturningSql(
6989
8172
  ctx,
@@ -7148,6 +8331,10 @@ const selectToSql = (ctx, table, query, quotedAs, hookSelect = query.hookSelect,
7148
8331
  list.push(sql);
7149
8332
  }
7150
8333
  }
8334
+ if (!isSubSql && ctx.cteHooks?.hasSelect) {
8335
+ const count = ctx.selectedCount = list.length || query.selectAllColumns?.length || 0;
8336
+ return count ? (list.length ? list.join(", ") : selectAllSql(query, quotedAs, jsonList)) + ", NULL" : "";
8337
+ }
7151
8338
  return list.length ? list.join(", ") : query.select ? "" : selectAllSql(query, quotedAs, jsonList);
7152
8339
  };
7153
8340
  const selectAllSql = (query, quotedAs, jsonList) => {
@@ -7492,7 +8679,7 @@ const getTsVector = (ctx, data, lang, source, quotedAs) => {
7492
8679
  }
7493
8680
  };
7494
8681
 
7495
- const pushUpdateSql = (ctx, table, query, quotedAs) => {
8682
+ const pushUpdateSql = (ctx, table, query, quotedAs, isSubSql) => {
7496
8683
  const quotedTable = quoteSchemaAndTable(
7497
8684
  query.schema,
7498
8685
  table.table || query.from
@@ -7511,19 +8698,20 @@ const pushUpdateSql = (ctx, table, query, quotedAs) => {
7511
8698
  if (query.hookUpdateSet) {
7512
8699
  applySet(ctx, table, set, hookSet, emptyObject, quotedAs);
7513
8700
  }
7514
- let hookSelect;
8701
+ let tableHook;
7515
8702
  const delayedRelationSelect = query.selectRelation ? newDelayedRelationSelect(table) : void 0;
7516
8703
  if (!set.length) {
7517
8704
  if (!query.select) {
7518
8705
  query.select = countSelect;
7519
8706
  }
7520
- hookSelect = pushUpdateReturning(
8707
+ tableHook = pushUpdateReturning(
7521
8708
  ctx,
7522
8709
  table,
7523
8710
  query,
7524
8711
  quotedAs,
7525
8712
  "SELECT",
7526
- delayedRelationSelect
8713
+ delayedRelationSelect,
8714
+ isSubSql
7527
8715
  );
7528
8716
  ctx.sql.push(`FROM ${quotedTable}`);
7529
8717
  pushWhereStatementSql(ctx, table, query, quotedAs);
@@ -7574,36 +8762,38 @@ const pushUpdateSql = (ctx, table, query, quotedAs) => {
7574
8762
  if (whereSql) {
7575
8763
  ctx.sql.push("WHERE", whereSql);
7576
8764
  }
7577
- hookSelect = pushUpdateReturning(
8765
+ tableHook = pushUpdateReturning(
7578
8766
  ctx,
7579
8767
  table,
7580
8768
  query,
7581
8769
  quotedAs,
7582
8770
  "RETURNING",
7583
- delayedRelationSelect
8771
+ delayedRelationSelect,
8772
+ isSubSql
7584
8773
  );
7585
8774
  }
7586
8775
  return {
7587
- hookSelect,
8776
+ tableHook,
7588
8777
  delayedRelationSelect,
7589
8778
  text: ctx.sql.join(" "),
7590
8779
  values: ctx.values
7591
8780
  };
7592
8781
  };
7593
- const pushUpdateReturning = (ctx, table, query, quotedAs, keyword, delayedRelationSelect) => {
8782
+ const pushUpdateReturning = (ctx, table, query, quotedAs, keyword, delayedRelationSelect, isSubSql) => {
7594
8783
  const { inCTE } = query;
7595
- const { select, hookSelect } = makeReturningSql(
8784
+ const { select, tableHook } = makeReturningSql(
7596
8785
  ctx,
7597
8786
  table,
7598
8787
  query,
7599
8788
  quotedAs,
7600
8789
  delayedRelationSelect,
7601
- 1,
7602
- inCTE && 2
8790
+ "Update",
8791
+ inCTE && "Create",
8792
+ isSubSql
7603
8793
  );
7604
8794
  const s = inCTE && (inCTE.selectNum || !select) ? select ? "0, " + select : "0" : select;
7605
8795
  if (s) ctx.sql.push(keyword, s);
7606
- return hookSelect;
8796
+ return tableHook;
7607
8797
  };
7608
8798
  const processData = (ctx, table, set, data, hookSet, quotedAs) => {
7609
8799
  let append;
@@ -7653,7 +8843,7 @@ const processValue = (ctx, table, QueryClass, key, value, quotedAs) => {
7653
8843
  return addValue(ctx.values, value);
7654
8844
  };
7655
8845
 
7656
- const pushDeleteSql = (ctx, table, query, quotedAs) => {
8846
+ const pushDeleteSql = (ctx, table, query, quotedAs, isSubSql) => {
7657
8847
  const from = `"${table.table || query.from}"`;
7658
8848
  ctx.sql.push(`DELETE FROM ${from}`);
7659
8849
  if (from !== quotedAs) {
@@ -7704,11 +8894,13 @@ const pushDeleteSql = (ctx, table, query, quotedAs) => {
7704
8894
  query,
7705
8895
  quotedAs,
7706
8896
  delayedRelationSelect,
7707
- 3
8897
+ "Delete",
8898
+ void 0,
8899
+ isSubSql
7708
8900
  );
7709
8901
  if (returning.select) ctx.sql.push("RETURNING", returning.select);
7710
8902
  return {
7711
- hookSelect: returning.hookSelect,
8903
+ tableHook: returning.tableHook,
7712
8904
  delayedRelationSelect,
7713
8905
  text: ctx.sql.join(" "),
7714
8906
  values: ctx.values
@@ -7774,7 +8966,34 @@ const pushCopySql = (ctx, table, query, quotedAs) => {
7774
8966
  pushWhereStatementSql(ctx, table, query, quotedAs);
7775
8967
  };
7776
8968
 
7777
- const toSQL = (table, options) => {
8969
+ const toSubSqlText = (q, cteName, options) => getSqlText(subToSql(q, cteName, options));
8970
+ const subToSql = (q, cteName, options) => {
8971
+ var _a;
8972
+ const sql = toSQL(q, options, true);
8973
+ if (sql.tableHook && (sql.tableHook.after || sql.tableHook.afterCommit) && !q.q.inCTE) {
8974
+ const shape = {};
8975
+ if (sql.tableHook.select) {
8976
+ for (const key of sql.tableHook.select.keys()) {
8977
+ shape[key] = q.shape[key];
8978
+ }
8979
+ }
8980
+ const item = {
8981
+ shape,
8982
+ tableHook: sql.tableHook
8983
+ };
8984
+ if (options.cteHooks) {
8985
+ if (sql.tableHook.select) options.cteHooks.hasSelect = true;
8986
+ (_a = options.cteHooks.tableHooks)[cteName] ?? (_a[cteName] = item);
8987
+ } else {
8988
+ options.cteHooks = {
8989
+ hasSelect: !!sql.tableHook.select,
8990
+ tableHooks: { [cteName]: item }
8991
+ };
8992
+ }
8993
+ }
8994
+ return sql;
8995
+ };
8996
+ const toSQL = (table, options, isSubSql) => {
7778
8997
  const query = table.q;
7779
8998
  const sql = [];
7780
8999
  const values = options?.values || [];
@@ -7785,7 +9004,8 @@ const toSQL = (table, options) => {
7785
9004
  values,
7786
9005
  aliasValue: options?.aliasValue,
7787
9006
  skipBatchCheck: options?.skipBatchCheck,
7788
- hasNonSelect: options?.hasNonSelect
9007
+ hasNonSelect: options?.hasNonSelect,
9008
+ cteHooks: options?.cteHooks
7789
9009
  };
7790
9010
  if (query.with) {
7791
9011
  pushWithSql(ctx, query.with);
@@ -7804,11 +9024,11 @@ const toSQL = (table, options) => {
7804
9024
  } else {
7805
9025
  const quotedAs = `"${query.as || tableName}"`;
7806
9026
  if (query.type === "insert") {
7807
- result = makeInsertSql(ctx, table, query, `"${tableName}"`);
9027
+ result = makeInsertSql(ctx, table, query, `"${tableName}"`, isSubSql);
7808
9028
  } else if (query.type === "update") {
7809
- result = pushUpdateSql(ctx, table, query, quotedAs);
9029
+ result = pushUpdateSql(ctx, table, query, quotedAs, isSubSql);
7810
9030
  } else if (query.type === "delete") {
7811
- result = pushDeleteSql(ctx, table, query, quotedAs);
9031
+ result = pushDeleteSql(ctx, table, query, quotedAs, isSubSql);
7812
9032
  } else if (query.type === "copy") {
7813
9033
  pushCopySql(ctx, table, query, quotedAs);
7814
9034
  result = { text: sql.join(" "), values };
@@ -7833,7 +9053,7 @@ const toSQL = (table, options) => {
7833
9053
  pushDistinctSql(ctx, table, query.distinct, quotedAs);
7834
9054
  }
7835
9055
  const aliases = query.group ? [] : void 0;
7836
- pushSelectSql(ctx, table, query, quotedAs, aliases);
9056
+ pushSelectSql(ctx, table, query, quotedAs, isSubSql, aliases);
7837
9057
  fromQuery = (table.table || query.from) && pushFromAndAs(ctx, table, query, quotedAs) || void 0;
7838
9058
  if (query.join) {
7839
9059
  pushJoinSql(
@@ -7907,13 +9127,29 @@ const toSQL = (table, options) => {
7907
9127
  result = {
7908
9128
  text: sql.join(" "),
7909
9129
  values,
7910
- hookSelect: query.hookSelect,
9130
+ tableHook: query.hookSelect && {
9131
+ select: query.hookSelect
9132
+ },
7911
9133
  delayedRelationSelect: ctx.delayedRelationSelect
7912
9134
  };
7913
9135
  }
7914
9136
  if (options && (query.type || ctx.hasNonSelect)) {
7915
9137
  options.hasNonSelect = true;
7916
9138
  }
9139
+ if (!isSubSql && ctx.cteHooks && "text" in result) {
9140
+ result.cteHooks = ctx.cteHooks;
9141
+ if (ctx.cteHooks.hasSelect) {
9142
+ result.text += ` UNION ALL SELECT ${"NULL, ".repeat(
9143
+ ctx.selectedCount || 0
9144
+ )}json_build_object(${Object.entries(ctx.cteHooks.tableHooks).map(
9145
+ ([cteName, data]) => `'${cteName}', (SELECT json_agg(${makeRowToJson(
9146
+ cteName,
9147
+ data.shape,
9148
+ false
9149
+ )}) FROM "${cteName}")`
9150
+ ).join(", ")})`;
9151
+ }
9152
+ }
7917
9153
  return result;
7918
9154
  };
7919
9155
  function pushLimitSQL(sql, values, q) {
@@ -8837,7 +10073,10 @@ const moveQueryValueToWith = (q, withStore, value, withKey, set, key) => {
8837
10073
  withKey
8838
10074
  );
8839
10075
  if (set) {
8840
- set[key] = new RawSQL(`(SELECT * FROM "${as}")`);
10076
+ const sub = _clone(value.baseQuery);
10077
+ sub.q.select = value.q.select;
10078
+ sub.q.as = sub.q.from = as;
10079
+ set[key] = sub;
8841
10080
  }
8842
10081
  return as;
8843
10082
  }
@@ -13676,5 +14915,5 @@ function copyTableData(query, arg) {
13676
14915
  return q;
13677
14916
  }
13678
14917
 
13679
- export { AfterCommitError, AggregateMethods, ArrayColumn, BigIntColumn, BigSerialColumn, BitColumn, BitVaryingColumn, BooleanColumn, BoxColumn, ByteaColumn, CidrColumn, CircleColumn, CitextColumn, Clear, ColumnRefExpression, ColumnType, ComputedColumn, CustomTypeColumn, DateBaseColumn, DateColumn, DateTimeBaseClass, DateTimeTzBaseClass, Db, DecimalColumn, Delete, DomainColumn, DoublePrecisionColumn, DynamicRawSQL, EnumColumn, ExpressionMethods, FnExpression, For, FromMethods, Having, InetColumn, IntegerBaseColumn, IntegerColumn, IntervalColumn, JSONColumn, JSONTextColumn, Join, JsonMethods, LimitedTextBaseColumn, LineColumn, LsegColumn, MacAddr8Column, MacAddrColumn, MergeQueryMethods, MoneyColumn, NumberAsStringBaseColumn, NumberBaseColumn, OnMethods, Operators, OrExpression, PathColumn, PointColumn, PolygonColumn, PostgisGeographyPointColumn, QueryAsMethods, QueryGet, QueryHooks, QueryLog, QueryMethods, QueryUpsert, RawSQL, RealColumn, RefExpression, SearchMethods, Select, SerialColumn, SmallIntColumn, SmallSerialColumn, SqlMethod, StringColumn, TextBaseColumn, TextColumn, Then, TimeColumn, TimestampColumn, TimestampTZColumn, Transaction, TransformMethods, TsQueryColumn, TsVectorColumn, UUIDColumn, Union, UnknownColumn, Update, VarCharColumn, VirtualColumn, Where, WithMethods, XMLColumn, _addWith, _clone, _getSelectableColumn, _initQueryBuilder, _queryAfterSaveCommit, _queryAll, _queryChangeCounter, _queryCreate, _queryCreateForEachFrom, _queryCreateMany, _queryCreateManyFrom, _queryCreateOneFrom, _queryDefaults, _queryDelete, _queryExec, _queryFindBy, _queryFindByOptional, _queryGet, _queryGetOptional, _queryHookAfterCreate, _queryHookAfterCreateCommit, _queryHookAfterDelete, _queryHookAfterDeleteCommit, _queryHookAfterQuery, _queryHookAfterSave, _queryHookAfterUpdate, _queryHookAfterUpdateCommit, _queryHookBeforeCreate, _queryHookBeforeDelete, _queryHookBeforeQuery, _queryHookBeforeSave, _queryHookBeforeUpdate, _queryInsert, _queryInsertForEachFrom, _queryInsertMany, _queryInsertManyFrom, _queryInsertOneFrom, _queryJoinOn, _queryJoinOnJsonPathEquals, _queryJoinOrOn, _queryOr, _queryOrNot, _queryRows, _querySelect, _querySelectAll, _queryTake, _queryTakeOptional, _queryUnion, _queryUpdate, _queryUpdateOrThrow, _queryWhere, _queryWhereExists, _queryWhereIn, _queryWhereNot, _queryWhereNotOneOf, _queryWhereNotSql, _queryWhereOneOf, _queryWhereSql, _runAfterCommitHooks, addColumnParserToQuery, addParserForRawExpression, addParserForSelectItem, addQueryOn, anyShape, applyComputedColumns, assignDbDataToColumn, checkIfASimpleQuery, cloneQueryBaseUnscoped, columnCheckToCode, columnCode, columnExcludesToCode, columnForeignKeysToCode, columnIndexesToCode, columnsShapeToCode, commitSql, constraintInnerToCode, constraintToCode, copyTableData, countSelect, createDbWithAdapter, defaultSchemaConfig, escapeForLog, escapeForMigration, escapeString, excludeInnerToCode, excludeToCode, extendQuery, filterResult, foreignKeyArgumentToCode, getClonedQueryData, getColumnBaseType, getColumnInfo, getColumnTypes, getFullColumnTable, getQueryAs, getShapeFromSelect, getSqlText, handleResult, identityToCode, indexInnerToCode, indexToCode, isDefaultTimeStamp, isInUserTransaction, isQueryReturnsAll, isSelectingCount, joinSubQuery, logParamToLogObject, makeColumnTypes, makeColumnsByType, makeFnExpression, moveQueryValueToWith, parseRecord, parseTableData, parseTableDataInput, postgisTypmodToSql, primaryKeyInnerToCode, processComputedBatches, processComputedResult, processSelectArg, pushLimitSQL, pushQueryArrayImmutable, pushQueryOn, pushQueryOnForOuter, pushQueryOrOn, pushTableDataCode, queryFrom, queryFromSql, queryJson, queryMethodByReturnType, queryTypeWithLimitOne, queryWrap, raw, referencesArgsToCode, resolveSubQueryCallbackV2, rollbackSql, saveAliasedShape, setColumnDefaultParse, setColumnEncode, setColumnParse, setColumnParseNull, setParserForSelectedString, setQueryObjectValueImmutable, setQueryOperators, simplifyColumnDefault, sqlFn, sqlQueryArgsToExpression, tableDataMethods, templateLiteralToSQL, testTransaction, throwIfJoinLateral, throwIfNoWhere, toSQL };
14918
+ export { AfterCommitError, AggregateMethods, ArrayColumn, BigIntColumn, BigSerialColumn, BitColumn, BitVaryingColumn, BooleanColumn, BoxColumn, ByteaColumn, CidrColumn, CircleColumn, CitextColumn, Clear, ColumnRefExpression, ColumnType, ColumnTypeBase, ComputedColumn, CustomTypeColumn, DateBaseColumn, DateColumn, DateTimeBaseClass, DateTimeTzBaseClass, Db, DecimalColumn, Delete, DomainColumn, DoublePrecisionColumn, DynamicRawSQL, EnumColumn, Expression, ExpressionMethods, ExpressionTypeMethod, FnExpression, For, FromMethods, Having, InetColumn, IntegerBaseColumn, IntegerColumn, IntervalColumn, JSONColumn, JSONTextColumn, Join, JsonMethods, LimitedTextBaseColumn, LineColumn, LsegColumn, MacAddr8Column, MacAddrColumn, MergeQueryMethods, MoneyColumn, MoreThanOneRowError, NotFoundError, NumberAsStringBaseColumn, NumberBaseColumn, OnMethods, Operators, OrExpression, OrchidOrmError, OrchidOrmInternalError, PathColumn, PointColumn, PolygonColumn, PostgisGeographyPointColumn, QueryAsMethods, QueryError, QueryGet, QueryHookUtils, QueryHooks, QueryLog, QueryMethods, QueryUpsert, RawSQL, RawSQLBase, RealColumn, RefExpression, SearchMethods, Select, SerialColumn, SmallIntColumn, SmallSerialColumn, SqlMethod, StringColumn, TextBaseColumn, TextColumn, Then, TimeColumn, TimestampColumn, TimestampTZColumn, Transaction, TransformMethods, TsQueryColumn, TsVectorColumn, UUIDColumn, UnhandledTypeError, Union, UnknownColumn, Update, ValExpression, VarCharColumn, VirtualColumn, Where, WithMethods, XMLColumn, _addToHookSelect, _addToHookSelectWithTable, _addWith, _applyRelationAliases, _checkIfAliased, _clone, _copyQueryAliasToQuery, _getQueryAliasOrName, _getQueryAs, _getQueryFreeAlias, _getQueryOuterAliases, _getSelectableColumn, _initQueryBuilder, _queryAfterSaveCommit, _queryAll, _queryChangeCounter, _queryCreate, _queryCreateForEachFrom, _queryCreateMany, _queryCreateManyFrom, _queryCreateOneFrom, _queryDefaults, _queryDelete, _queryExec, _queryFindBy, _queryFindByOptional, _queryGet, _queryGetOptional, _queryHookAfterCreate, _queryHookAfterCreateCommit, _queryHookAfterDelete, _queryHookAfterDeleteCommit, _queryHookAfterQuery, _queryHookAfterSave, _queryHookAfterUpdate, _queryHookAfterUpdateCommit, _queryHookBeforeCreate, _queryHookBeforeDelete, _queryHookBeforeQuery, _queryHookBeforeSave, _queryHookBeforeUpdate, _queryInsert, _queryInsertForEachFrom, _queryInsertMany, _queryInsertManyFrom, _queryInsertOneFrom, _queryJoinOn, _queryJoinOnJsonPathEquals, _queryJoinOrOn, _queryOr, _queryOrNot, _queryRows, _querySelect, _querySelectAll, _queryTake, _queryTakeOptional, _queryUnion, _queryUpdate, _queryUpdateOrThrow, _queryWhere, _queryWhereExists, _queryWhereIn, _queryWhereNot, _queryWhereNotOneOf, _queryWhereNotSql, _queryWhereOneOf, _queryWhereSql, _runAfterCommitHooks, _setQueryAlias, _setQueryAs, _setSubQueryAliases, addCode, addColumnParserToQuery, addParserForRawExpression, addParserForSelectItem, addQueryOn, addValue, anyShape, applyComputedColumns, applyMixins, applyTransforms, arrayDataToCode, assignDbDataToColumn, backtickQuote, callWithThis, checkIfASimpleQuery, cloneQueryBaseUnscoped, codeToString, colors, columnCheckToCode, columnCode, columnDefaultArgumentToCode, columnErrorMessagesToCode, columnExcludesToCode, columnForeignKeysToCode, columnIndexesToCode, columnsShapeToCode, commitSql, constraintInnerToCode, constraintToCode, consumeColumnName, copyTableData, countSelect, createDbWithAdapter, dateDataToCode, deepCompare, defaultSchemaConfig, emptyArray, emptyObject, escapeForLog, escapeForMigration, escapeString, excludeInnerToCode, excludeToCode, exhaustive, extendQuery, filterResult, foreignKeyArgumentToCode, getCallerFilePath, getClonedQueryData, getColumnBaseType, getColumnInfo, getColumnTypes, getDefaultLanguage, getFreeAlias, getFreeSetAlias, getFullColumnTable, getImportPath, getPrimaryKeys, getQueryAs, getQueryParsers, getShapeFromSelect, getSqlText, getStackTrace, getValueKey, handleResult, identityToCode, indexInnerToCode, indexToCode, isDefaultTimeStamp, isExpression, isInUserTransaction, isIterable, isObjectEmpty, isQueryReturnsAll, isRawSQL, isRelationQuery, isSelectingCount, isTemplateLiteralArgs, joinSubQuery, joinTruthy, logColors, logParamToLogObject, makeColumnNullable, makeColumnTypes, makeColumnsByType, makeFnExpression, moveQueryValueToWith, newDelayedRelationSelect, noop, numberDataToCode, objectHasValues, omit, parseRecord, parseTableData, parseTableDataInput, pathToLog, pick, pluralize, postgisTypmodToSql, primaryKeyInnerToCode, processComputedBatches, processComputedResult, processSelectArg, pushColumnData, pushLimitSQL, pushOrNewArray, pushOrNewArrayToObjectImmutable, pushQueryArrayImmutable, pushQueryOn, pushQueryOnForOuter, pushQueryOrOn, pushQueryValueImmutable, pushTableDataCode, queryColumnNameToKey, queryFrom, queryFromSql, queryJson, queryMethodByReturnType, queryTypeWithLimitOne, queryWrap, quoteObjectKey, raw, referencesArgsToCode, requirePrimaryKeys, resolveSubQueryCallbackV2, returnArg, rollbackSql, saveAliasedShape, setColumnData, setColumnDefaultParse, setColumnEncode, setColumnParse, setColumnParseNull, setConnectRetryConfig, setCurrentColumnName, setDataValue, setDefaultLanguage, setDefaultNowFn, setDelayedRelation, setObjectValueImmutable, setParserForSelectedString, setParserToQuery, setQueryObjectValueImmutable, setQueryOperators, simplifyColumnDefault, singleQuote, singleQuoteArray, snakeCaseKey, spreadObjectValues, sqlFn, sqlQueryArgsToExpression, stringDataToCode, tableDataMethods, templateLiteralSQLToCode, templateLiteralToSQL, testTransaction, throwIfJoinLateral, throwIfNoWhere, timestampHelpers, toArray, toCamelCase, toPascalCase, toSQL, toSnakeCase, toSubSqlText, wrapAdapterFnWithConnectRetry };
13680
14919
  //# sourceMappingURL=index.mjs.map