pqb 0.68.1 → 0.70.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/dist/index.js CHANGED
@@ -1704,6 +1704,44 @@ const columnCode = (type, ctx, key, code) => {
1704
1704
  if (data.modifyQuery && !ctx.migration) addCode(code, `.modifyQuery(${data.modifyQuery.toString()})`);
1705
1705
  return code.length === 1 && typeof code[0] === "string" ? code[0] : code;
1706
1706
  };
1707
+ /**
1708
+ * generic utility to add a parser to the query object
1709
+ * @param query - the query object, it will be mutated
1710
+ * @param key - the name of the column in the data loaded by the query
1711
+ * @param parser - function to process the value of the column with.
1712
+ */
1713
+ const setParserToQuery = (query, key, parser) => {
1714
+ if (parser) if (query.parsers) query.parsers[key] = parser;
1715
+ else query.parsers = { [key]: parser };
1716
+ else if (query.parsers) delete query.parsers[key];
1717
+ };
1718
+ const getQueryParsers = (q, hookSelect) => {
1719
+ if (hookSelect) {
1720
+ const parsers = { ...q.q.parsers };
1721
+ const { defaultParsers } = q.q;
1722
+ if (defaultParsers) for (const [key, value] of hookSelect) {
1723
+ const parser = defaultParsers[key];
1724
+ if (parser) parsers[value.as || key] = parser;
1725
+ }
1726
+ return parsers;
1727
+ }
1728
+ return q.q.select ? q.q.parsers : q.q.defaultParsers;
1729
+ };
1730
+ const addColumnParserToQuery = (q, key, column) => {
1731
+ if (column._parse) setObjectValueImmutable(q, "parsers", key, column._parse);
1732
+ };
1733
+ const setValueParserToQuery = (q, column) => {
1734
+ addColumnParserToQuery(q, "v", column);
1735
+ };
1736
+ const getValueParser = (parsers) => {
1737
+ return parsers?.v;
1738
+ };
1739
+ const setValueParser = (q, parser) => {
1740
+ setObjectValueImmutable(q, "parsers", "v", parser);
1741
+ };
1742
+ const addParserForRawExpression = (q, key, raw) => {
1743
+ if (raw.result.value) addColumnParserToQuery(q.q, key, raw.result.value);
1744
+ };
1707
1745
  var CustomTypeColumn = class extends Column {
1708
1746
  constructor(schema, typeName, typeSchema, extension) {
1709
1747
  super(schema, schema.unknown(), schema.unknown(), schema.unknown());
@@ -1751,9 +1789,6 @@ var EnumColumn = class extends Column {
1751
1789
  return `"${index === -1 ? name : `${name.slice(0, index)}"."${name.slice(index + 1)}`}"`;
1752
1790
  }
1753
1791
  };
1754
- const addColumnParserToQuery = (q, key, column) => {
1755
- if (column._parse) setObjectValueImmutable(q, "parsers", key, column._parse);
1756
- };
1757
1792
  const setColumnDefaultParse = (column, parse) => {
1758
1793
  column.data.parse = parse;
1759
1794
  column._parse = (input) => input === null ? null : parse(input);
@@ -1795,178 +1830,6 @@ const setColumnEncode = (column, fn, inputSchema) => {
1795
1830
  const getColumnBaseType = (column, domainsMap, type) => {
1796
1831
  return column instanceof EnumColumn ? "text" : column instanceof DomainColumn ? domainsMap[column.dataType]?.dataType : type;
1797
1832
  };
1798
- const getValueKey = Symbol("get");
1799
- let moveMutativeQueryToCte$1;
1800
- const setMoveMutativeQueryToCte = (fn) => {
1801
- moveMutativeQueryToCte$1 = fn;
1802
- };
1803
- let prepareSubQueryForSql$1;
1804
- const setPrepareSubQueryForSql = (fn) => {
1805
- prepareSubQueryForSql$1 = fn;
1806
- };
1807
- let dbClass;
1808
- const setDb = (db) => {
1809
- dbClass = db;
1810
- };
1811
- function setQueryOperators(query, operators) {
1812
- const q = query.q;
1813
- if (q.operators !== operators) {
1814
- q.operators = operators;
1815
- Object.assign(query, operators);
1816
- }
1817
- return query;
1818
- }
1819
- /**
1820
- * Makes operator function that has `_op` property.
1821
- *
1822
- * @param _op - function to turn the operator call into SQL.
1823
- */
1824
- const make = (_op) => {
1825
- return Object.assign(function(value) {
1826
- const { q } = this;
1827
- const val = prepareOpArg(this, value);
1828
- (q.chain ??= []).push(_op, val || value);
1829
- if (q.parsers?.[getValueKey]) setObjectValueImmutable(q, "parsers", getValueKey, void 0);
1830
- return setQueryOperators(this, boolean);
1831
- }, { _op });
1832
- };
1833
- const makeVarArg = (_op) => {
1834
- return Object.assign(function(...args) {
1835
- const { q } = this;
1836
- args.forEach((arg, i) => {
1837
- const val = prepareOpArg(this, arg);
1838
- if (val) args[i] = val;
1839
- });
1840
- (q.chain ??= []).push(_op, args);
1841
- if (q.parsers?.[getValueKey]) setObjectValueImmutable(q, "parsers", getValueKey, void 0);
1842
- return setQueryOperators(this, boolean);
1843
- }, { _op });
1844
- };
1845
- const prepareOpArg = (q, arg) => {
1846
- return arg instanceof dbClass ? prepareSubQueryForSql$1(q, arg) : void 0;
1847
- };
1848
- const quoteValue = (arg, ctx, quotedAs, IN) => {
1849
- if (arg && typeof arg === "object") {
1850
- if (IN && isIterable(arg)) return `(${(Array.isArray(arg) ? arg : [...arg]).map((value) => addValue(ctx.values, value)).join(", ")})`;
1851
- if (isExpression(arg)) return arg.toSQL(ctx, quotedAs);
1852
- if ("toSQL" in arg) return `(${moveMutativeQueryToCte$1(ctx, arg)})`;
1853
- if (!(arg instanceof Date) && !Array.isArray(arg)) arg = JSON.stringify(arg);
1854
- }
1855
- return addValue(ctx.values, arg);
1856
- };
1857
- const quoteLikeValue = (arg, ctx, quotedAs, jsonArray) => {
1858
- if (arg && typeof arg === "object") {
1859
- if (!jsonArray && Array.isArray(arg)) return `(${arg.map((value) => addValue(ctx.values, value)).join(", ")})`;
1860
- if (isExpression(arg)) return arg.toSQL(ctx, quotedAs);
1861
- if ("toSQL" in arg) return `replace(replace((${moveMutativeQueryToCte$1(ctx, arg)}), '%', '\\\\%'), '_', '\\\\_')`;
1862
- }
1863
- return addValue(ctx.values, arg.replace(/[%_]/g, "\\$&"));
1864
- };
1865
- const base = {
1866
- equals: make((key, value, ctx, quotedAs) => value === null ? `${key} IS NULL` : `${key} = ${quoteValue(value, ctx, quotedAs)}`),
1867
- not: make((key, value, ctx, quotedAs) => value === null ? `${key} IS NOT NULL` : `${key} <> ${quoteValue(value, ctx, quotedAs)}`),
1868
- isDistinctFrom: make((key, value, ctx, quotedAs) => `${key} IS DISTINCT FROM ${quoteValue(value, ctx, quotedAs)}`),
1869
- isNotDistinctFrom: make((key, value, ctx, quotedAs) => `${key} IS NOT DISTINCT FROM ${quoteValue(value, ctx, quotedAs)}`),
1870
- in: make((key, value, ctx, quotedAs) => Array.isArray(value) && !value.length ? "false" : `${key} IN ${quoteValue(value, ctx, quotedAs, true)}`),
1871
- notIn: make((key, value, ctx, quotedAs) => Array.isArray(value) && !value.length ? "true" : `NOT ${key} IN ${quoteValue(value, ctx, quotedAs, true)}`)
1872
- };
1873
- const ord = {
1874
- ...base,
1875
- lt: make((key, value, ctx, quotedAs) => `${key} < ${quoteValue(value, ctx, quotedAs)}`),
1876
- lte: make((key, value, ctx, quotedAs) => `${key} <= ${quoteValue(value, ctx, quotedAs)}`),
1877
- gt: make((key, value, ctx, quotedAs) => `${key} > ${quoteValue(value, ctx, quotedAs)}`),
1878
- gte: make((key, value, ctx, quotedAs) => `${key} >= ${quoteValue(value, ctx, quotedAs)}`),
1879
- between: make((key, [from, to], ctx, quotedAs) => `${key} BETWEEN ${quoteValue(from, ctx, quotedAs)} AND ${quoteValue(to, ctx, quotedAs)}`)
1880
- };
1881
- const boolean = {
1882
- ...ord,
1883
- and: make((key, value, ctx, quotedAs) => `${key} AND ${value.q.expr.toSQL(ctx, quotedAs)}`),
1884
- or: make((key, value, ctx, quotedAs) => `(${key}) OR (${value.q.expr.toSQL(ctx, quotedAs)})`)
1885
- };
1886
- const text = {
1887
- ...base,
1888
- contains: make((key, value, ctx, quotedAs) => `${key} ILIKE '%' || ${quoteLikeValue(value, ctx, quotedAs)} || '%'`),
1889
- containsSensitive: make((key, value, ctx, quotedAs) => `${key} LIKE '%' || ${quoteLikeValue(value, ctx, quotedAs)} || '%'`),
1890
- startsWith: make((key, value, ctx, quotedAs) => `${key} ILIKE ${quoteLikeValue(value, ctx, quotedAs)} || '%'`),
1891
- startsWithSensitive: make((key, value, ctx, quotedAs) => `${key} LIKE ${quoteLikeValue(value, ctx, quotedAs)} || '%'`),
1892
- endsWith: make((key, value, ctx, quotedAs) => `${key} ILIKE '%' || ${quoteLikeValue(value, ctx, quotedAs)}`),
1893
- endsWithSensitive: make((key, value, ctx, quotedAs) => `${key} LIKE '%' || ${quoteLikeValue(value, ctx, quotedAs)}`)
1894
- };
1895
- const ordinalText = {
1896
- ...ord,
1897
- ...text
1898
- };
1899
- const encodeJsonPath = (ctx, path) => addValue(ctx.values, `{${Array.isArray(path) ? path.join(", ") : path}}`);
1900
- const jsonPathQueryOp = (key, [path, options], ctx) => `jsonb_path_query_first(${key}, ${addValue(ctx.values, path)}${options?.vars ? `, ${addValue(ctx.values, JSON.stringify(options.vars))}${options.silent ? ", true" : ""}` : options?.silent ? ", NULL, true" : ""})`;
1901
- const shouldEncodeJson = (ctx) => ctx.q.adapter.driverAdapter.schemaConfig?.jsonEncodedByDriver === false;
1902
- const quoteJsonValue = (arg, ctx, quotedAs, IN) => {
1903
- if (arg && typeof arg === "object") {
1904
- if (IN && Array.isArray(arg)) return `(${arg.map((value) => shouldEncodeJson(ctx) ? addValue(ctx.values, JSON.stringify(value)) : addValue(ctx.values, value)).join(", ")})`;
1905
- if (Array.isArray(arg)) return shouldEncodeJson(ctx) ? addValue(ctx.values, JSON.stringify(arg)) : addValue(ctx.values, arg);
1906
- if (isExpression(arg)) return "to_jsonb(" + arg.toSQL(ctx, quotedAs) + ")";
1907
- if ("toSQL" in arg) return `to_jsonb((${moveMutativeQueryToCte$1(ctx, arg)}))`;
1908
- }
1909
- return addValue(ctx.values, JSON.stringify(arg)) + "::jsonb";
1910
- };
1911
- const serializeJsonValue = (arg, ctx, quotedAs) => {
1912
- if (arg && typeof arg === "object") {
1913
- if (isExpression(arg)) return "to_jsonb(" + arg.toSQL(ctx, quotedAs) + ")";
1914
- if ("toSQL" in arg) return `to_jsonb((${moveMutativeQueryToCte$1(ctx, arg)}))`;
1915
- }
1916
- return addValue(ctx.values, JSON.stringify(arg));
1917
- };
1918
- const Operators = {
1919
- any: base,
1920
- boolean,
1921
- ordinalText,
1922
- number: ord,
1923
- date: ord,
1924
- time: ord,
1925
- text,
1926
- json: {
1927
- ...ord,
1928
- equals: make((key, value, ctx, quotedAs) => value === null ? `nullif(${key}, 'null'::jsonb) IS NULL` : `${key} = ${quoteJsonValue(value, ctx, quotedAs)}`),
1929
- not: make((key, value, ctx, quotedAs) => value === null ? `nullif(${key}, 'null'::jsonb) IS NOT NULL` : `${key} != ${quoteJsonValue(value, ctx, quotedAs)}`),
1930
- isDistinctFrom: make((key, value, ctx, quotedAs) => `${key} IS DISTINCT FROM ${quoteJsonValue(value, ctx, quotedAs)}`),
1931
- isNotDistinctFrom: make((key, value, ctx, quotedAs) => `${key} IS NOT DISTINCT FROM ${quoteJsonValue(value, ctx, quotedAs)}`),
1932
- in: make((key, value, ctx, quotedAs) => Array.isArray(value) && !value.length ? "false" : `${key} IN ${quoteJsonValue(value, ctx, quotedAs, true)}`),
1933
- notIn: make((key, value, ctx, quotedAs) => Array.isArray(value) && !value.length ? "true" : `NOT ${key} IN ${quoteJsonValue(value, ctx, quotedAs, true)}`),
1934
- jsonPathQueryFirst: Object.assign(function(path, options) {
1935
- const { q, columnTypes } = this;
1936
- const chain = q.chain ??= [];
1937
- chain.push(jsonPathQueryOp, [path, options]);
1938
- if (q.parsers?.[getValueKey]) setObjectValueImmutable(q, "parsers", getValueKey, void 0);
1939
- if (options?.type) {
1940
- const type = options.type(columnTypes);
1941
- addColumnParserToQuery(q, getValueKey, type);
1942
- chain.push = (...args) => {
1943
- chain.push = Array.prototype.push;
1944
- chain.push((s) => `${s}::${type.dataType}`, emptyArray);
1945
- return chain.push(...args);
1946
- };
1947
- return setQueryOperators(this, type.operators);
1948
- }
1949
- return this;
1950
- }, { _op: jsonPathQueryOp }),
1951
- jsonSupersetOf: make((key, value, ctx, quotedAs) => `${key} @> ${quoteValue(value, ctx, quotedAs)}`),
1952
- jsonSubsetOf: make((key, value, ctx, quotedAs) => `${key} <@ ${quoteValue(value, ctx, quotedAs)}`),
1953
- jsonSet: makeVarArg((key, [path, value], ctx, quotedAs) => `jsonb_set(${key}, ${encodeJsonPath(ctx, path)}, ${serializeJsonValue(value, ctx, quotedAs)})`),
1954
- jsonReplace: makeVarArg((key, [path, value], ctx, quotedAs) => `jsonb_set(${key}, ${encodeJsonPath(ctx, path)}, ${serializeJsonValue(value, ctx, quotedAs)}, false)`),
1955
- jsonInsert: makeVarArg((key, [path, value, options], ctx, quotedAs) => `jsonb_insert(${key}, ${encodeJsonPath(ctx, path)}, ${serializeJsonValue(value, ctx, quotedAs)}${options?.after ? ", true" : ""})`),
1956
- jsonRemove: makeVarArg((key, [path], ctx) => `(${key} #- ${encodeJsonPath(ctx, path)})`)
1957
- },
1958
- array: {
1959
- ...ord,
1960
- has: make((key, value, ctx, quotedAs) => `${quoteValue(value, ctx, quotedAs)} = ANY(${key})`),
1961
- hasEvery: make((key, value, ctx, quotedAs) => `${key} @> ${quoteValue(value, ctx, quotedAs)}`),
1962
- hasSome: make((key, value, ctx, quotedAs) => `${key} && ${quoteValue(value, ctx, quotedAs)}`),
1963
- containedIn: make((key, value, ctx, quotedAs) => `${key} <@ ${quoteValue(value, ctx, quotedAs)}`),
1964
- length: make((key, value, ctx, quotedAs) => {
1965
- const expr = `COALESCE(array_length(${key}, 1), 0)`;
1966
- return typeof value === "number" ? `${expr} = ${quoteValue(value, ctx, quotedAs)}` : Object.keys(value).map((key) => ord[key]._op(expr, value[key], ctx, quotedAs)).join(" AND ");
1967
- })
1968
- }
1969
- };
1970
1833
  const dateToString = (value) => value.toISOString();
1971
1834
  const dateTimeEncode = (value) => {
1972
1835
  return typeof value === "number" ? new Date(value) : value;
@@ -2094,7 +1957,6 @@ var ArrayColumn = class ArrayColumn extends Column {
2094
1957
  this.dataType = "array";
2095
1958
  this.operators = Operators.array;
2096
1959
  item.data.isNullable = true;
2097
- setColumnDefaultParse(this, (input) => parse$1.call(this, input));
2098
1960
  if (defaultEncode) setColumnDefaultEncode(this, defaultEncode);
2099
1961
  this.data.item = item instanceof ArrayColumn ? item.data.item : item;
2100
1962
  this.data.name = item.data.name;
@@ -2120,54 +1982,6 @@ var ArrayColumn = class ArrayColumn extends Column {
2120
1982
  return columnCode(this, ctx, key, code);
2121
1983
  }
2122
1984
  };
2123
- const parse$1 = function(source) {
2124
- if (typeof source !== "string") return source;
2125
- const entries = [];
2126
- parsePostgresArray(source, entries, this.data.item.data.parseItem);
2127
- return entries;
2128
- };
2129
- /**
2130
- * based on https://github.com/bendrucker/postgres-array/tree/master
2131
- * and slightly optimized
2132
- */
2133
- const parsePostgresArray = (source, entries, transform) => {
2134
- let pos = 0;
2135
- if (source[0] === "[") {
2136
- pos = source.indexOf("=") + 1;
2137
- if (!pos) pos = source.length;
2138
- }
2139
- if (source[pos] === "{") pos++;
2140
- let recorded = "";
2141
- while (pos < source.length) {
2142
- const character = source[pos++];
2143
- if (character === "{") {
2144
- const innerEntries = [];
2145
- entries.push(innerEntries);
2146
- pos += parsePostgresArray(source.slice(pos - 1), innerEntries, transform) - 1;
2147
- } else if (character === "}") {
2148
- if (recorded) entries.push(recorded === "NULL" ? null : transform ? transform(recorded) : recorded);
2149
- return pos;
2150
- } else if (character === "\"") {
2151
- let esc = false;
2152
- let rec = "";
2153
- while (pos < source.length) {
2154
- let char;
2155
- while ((char = source[pos++]) === "\\") if (!(esc = !esc)) rec += "\\";
2156
- if (esc) esc = false;
2157
- else if (char === "\"") break;
2158
- rec += char;
2159
- }
2160
- entries.push(transform ? transform(rec) : rec);
2161
- recorded = "";
2162
- } else if (character === ",") {
2163
- if (recorded) {
2164
- entries.push(recorded === "NULL" ? null : transform ? transform(recorded) : recorded);
2165
- recorded = "";
2166
- }
2167
- } else recorded += character;
2168
- }
2169
- return pos;
2170
- };
2171
1985
  const encodeJson = (x) => x === null ? x : JSON.stringify(x);
2172
1986
  var JSONColumn = class extends Column {
2173
1987
  constructor(schema, __inputType, encodedByDriver = true) {
@@ -2364,65 +2178,261 @@ const defaultSchemaConfig = (options) => {
2364
2178
  },
2365
2179
  narrowAllTypes() {
2366
2180
  return this;
2367
- },
2368
- dateAsNumber() {
2369
- return this.parse(getDateAsNumberFn(this));
2370
- },
2371
- dateAsDate() {
2372
- return this.parse(getDateAsDateFn(this));
2373
- },
2374
- enum(dataType, type) {
2375
- return new EnumColumn(schemaConfig, dataType, type, void 0);
2376
- },
2377
- array(item) {
2378
- return new ArrayColumn(schemaConfig, item, void 0, options?.arrayEncode);
2379
- },
2380
- boolean: noop,
2381
- buffer: noop,
2382
- unknown: noop,
2383
- never: noop,
2384
- stringSchema: noop,
2385
- stringMin: noop,
2386
- stringMax: noop,
2387
- stringMinMax: noop,
2388
- number: noop,
2389
- int: noop,
2390
- stringNumberDate: noop,
2391
- timeInterval: noop,
2392
- bit: noop,
2393
- uuid: noop,
2394
- nullable() {
2395
- return setColumnData(this, "isNullable", true);
2396
- },
2397
- json() {
2398
- return new JSONColumn(schemaConfig, void 0, options?.jsonEncodedByDriver);
2399
- },
2400
- jsonText() {
2401
- return new JSONTextColumn(schemaConfig, void 0);
2402
- },
2403
- setErrors: noop,
2404
- smallint: () => new SmallIntColumn(schemaConfig),
2405
- integer: () => new IntegerColumn(schemaConfig),
2406
- real: () => new RealColumn(schemaConfig),
2407
- smallSerial: () => new SmallSerialColumn(schemaConfig),
2408
- serial: () => new SerialColumn(schemaConfig),
2409
- bigint: () => new BigIntColumn(schemaConfig),
2410
- decimal: (precision, scale) => new DecimalColumn(schemaConfig, precision, scale),
2411
- doublePrecision: () => new DoublePrecisionColumn(schemaConfig),
2412
- bigSerial: () => new BigSerialColumn(schemaConfig),
2413
- money: () => new MoneyColumn(schemaConfig),
2414
- varchar: (limit) => new VarCharColumn(schemaConfig, limit),
2415
- text: () => new TextColumn(schemaConfig),
2416
- string: (limit) => new StringColumn(schemaConfig, limit),
2417
- citext: () => new CitextColumn(schemaConfig),
2418
- date: () => new DateColumn(schemaConfig, options?.dateParsedByDriver),
2419
- timestampNoTZ: (precision) => new TimestampColumn(schemaConfig, precision, options?.dateParsedByDriver),
2420
- timestamp: (precision) => new TimestampTZColumn(schemaConfig, precision, options?.dateParsedByDriver),
2421
- geographyPointSchema: noop
2422
- };
2423
- return schemaConfig;
2181
+ },
2182
+ dateAsNumber() {
2183
+ return this.parse(getDateAsNumberFn(this));
2184
+ },
2185
+ dateAsDate() {
2186
+ return this.parse(getDateAsDateFn(this));
2187
+ },
2188
+ enum(dataType, type) {
2189
+ return new EnumColumn(schemaConfig, dataType, type, void 0);
2190
+ },
2191
+ array(item) {
2192
+ return new ArrayColumn(schemaConfig, item, void 0, options?.arrayEncode);
2193
+ },
2194
+ boolean: noop,
2195
+ buffer: noop,
2196
+ unknown: noop,
2197
+ never: noop,
2198
+ stringSchema: noop,
2199
+ stringMin: noop,
2200
+ stringMax: noop,
2201
+ stringMinMax: noop,
2202
+ number: noop,
2203
+ int: noop,
2204
+ stringNumberDate: noop,
2205
+ timeInterval: noop,
2206
+ bit: noop,
2207
+ uuid: noop,
2208
+ nullable() {
2209
+ return setColumnData(this, "isNullable", true);
2210
+ },
2211
+ json() {
2212
+ return new JSONColumn(schemaConfig, void 0, options?.jsonEncodedByDriver);
2213
+ },
2214
+ jsonText() {
2215
+ return new JSONTextColumn(schemaConfig, void 0);
2216
+ },
2217
+ setErrors: noop,
2218
+ smallint: () => new SmallIntColumn(schemaConfig),
2219
+ integer: () => new IntegerColumn(schemaConfig),
2220
+ real: () => new RealColumn(schemaConfig),
2221
+ smallSerial: () => new SmallSerialColumn(schemaConfig),
2222
+ serial: () => new SerialColumn(schemaConfig),
2223
+ bigint: () => new BigIntColumn(schemaConfig),
2224
+ decimal: (precision, scale) => new DecimalColumn(schemaConfig, precision, scale),
2225
+ doublePrecision: () => new DoublePrecisionColumn(schemaConfig),
2226
+ bigSerial: () => new BigSerialColumn(schemaConfig),
2227
+ money: () => new MoneyColumn(schemaConfig),
2228
+ varchar: (limit) => new VarCharColumn(schemaConfig, limit),
2229
+ text: () => new TextColumn(schemaConfig),
2230
+ string: (limit) => new StringColumn(schemaConfig, limit),
2231
+ citext: () => new CitextColumn(schemaConfig),
2232
+ date: () => new DateColumn(schemaConfig, options?.dateParsedByDriver),
2233
+ timestampNoTZ: (precision) => new TimestampColumn(schemaConfig, precision, options?.dateParsedByDriver),
2234
+ timestamp: (precision) => new TimestampTZColumn(schemaConfig, precision, options?.dateParsedByDriver),
2235
+ geographyPointSchema: noop
2236
+ };
2237
+ return schemaConfig;
2238
+ };
2239
+ const internalSchemaConfig = defaultSchemaConfig();
2240
+ var BooleanColumn = class BooleanColumn extends Column {
2241
+ static get instance() {
2242
+ return this._instance ??= new BooleanColumn(internalSchemaConfig);
2243
+ }
2244
+ static get instanceSkipValueToArray() {
2245
+ let instance = this._instanceSkipValueToArray;
2246
+ if (!instance) {
2247
+ instance = this._instanceSkipValueToArray = Object.create(this.instance);
2248
+ instance.data.skipValueToArray = true;
2249
+ }
2250
+ return instance;
2251
+ }
2252
+ constructor(schema) {
2253
+ super(schema, schema.boolean());
2254
+ this.dataType = "bool";
2255
+ this.operators = Operators.boolean;
2256
+ this.data.alias = "boolean";
2257
+ this.data.parseItem = parseItem;
2258
+ }
2259
+ toCode(ctx, key) {
2260
+ return columnCode(this, ctx, key, "boolean()");
2261
+ }
2262
+ };
2263
+ const parseItem = (input) => input[0] === "t";
2264
+ let moveMutativeQueryToCte$1;
2265
+ const setMoveMutativeQueryToCte = (fn) => {
2266
+ moveMutativeQueryToCte$1 = fn;
2267
+ };
2268
+ let prepareSubQueryForSql$1;
2269
+ const setPrepareSubQueryForSql = (fn) => {
2270
+ prepareSubQueryForSql$1 = fn;
2271
+ };
2272
+ let dbClass;
2273
+ const setDb = (db) => {
2274
+ dbClass = db;
2275
+ };
2276
+ function setQueryOperators(query, operators) {
2277
+ const q = query.q;
2278
+ if (q.operators !== operators) {
2279
+ q.operators = operators;
2280
+ Object.assign(query, operators);
2281
+ }
2282
+ return query;
2283
+ }
2284
+ /**
2285
+ * Makes operator function that has `_op` property.
2286
+ *
2287
+ * @param _op - function to turn the operator call into SQL.
2288
+ */
2289
+ const make = (_op) => {
2290
+ return Object.assign(function(value) {
2291
+ const { q } = this;
2292
+ const val = prepareOpArg(this, value);
2293
+ (q.chain ??= []).push(_op, val || value);
2294
+ if (getValueParser(q.parsers)) setValueParser(q, void 0);
2295
+ q.getColumn = BooleanColumn.instance;
2296
+ return setQueryOperators(this, boolean);
2297
+ }, { _op });
2298
+ };
2299
+ const makeVarArg = (_op) => {
2300
+ return Object.assign(function(...args) {
2301
+ const { q } = this;
2302
+ args.forEach((arg, i) => {
2303
+ const val = prepareOpArg(this, arg);
2304
+ if (val) args[i] = val;
2305
+ });
2306
+ (q.chain ??= []).push(_op, args);
2307
+ if (getValueParser(q.parsers)) setValueParser(q, void 0);
2308
+ return setQueryOperators(this, boolean);
2309
+ }, { _op });
2310
+ };
2311
+ const prepareOpArg = (q, arg) => {
2312
+ return arg instanceof dbClass ? prepareSubQueryForSql$1(q, arg) : void 0;
2313
+ };
2314
+ const quoteValue = (arg, ctx, quotedAs, IN) => {
2315
+ if (arg && typeof arg === "object") {
2316
+ if (IN && isIterable(arg)) return `(${(Array.isArray(arg) ? arg : [...arg]).map((value) => addValue(ctx.values, value)).join(", ")})`;
2317
+ if (isExpression(arg)) return arg.toSQL(ctx, quotedAs);
2318
+ if ("toSQL" in arg) return `(${moveMutativeQueryToCte$1(ctx, arg)})`;
2319
+ if (!(arg instanceof Date) && !Array.isArray(arg)) arg = JSON.stringify(arg);
2320
+ }
2321
+ return addValue(ctx.values, arg);
2322
+ };
2323
+ const quoteLikeValue = (arg, ctx, quotedAs, jsonArray) => {
2324
+ if (arg && typeof arg === "object") {
2325
+ if (!jsonArray && Array.isArray(arg)) return `(${arg.map((value) => addValue(ctx.values, value)).join(", ")})`;
2326
+ if (isExpression(arg)) return arg.toSQL(ctx, quotedAs);
2327
+ if ("toSQL" in arg) return `replace(replace((${moveMutativeQueryToCte$1(ctx, arg)}), '%', '\\\\%'), '_', '\\\\_')`;
2328
+ }
2329
+ return addValue(ctx.values, arg.replace(/[%_]/g, "\\$&"));
2330
+ };
2331
+ const base = {
2332
+ equals: make((key, value, ctx, quotedAs) => value === null ? `${key} IS NULL` : `${key} = ${quoteValue(value, ctx, quotedAs)}`),
2333
+ not: make((key, value, ctx, quotedAs) => value === null ? `${key} IS NOT NULL` : `${key} <> ${quoteValue(value, ctx, quotedAs)}`),
2334
+ isDistinctFrom: make((key, value, ctx, quotedAs) => `${key} IS DISTINCT FROM ${quoteValue(value, ctx, quotedAs)}`),
2335
+ isNotDistinctFrom: make((key, value, ctx, quotedAs) => `${key} IS NOT DISTINCT FROM ${quoteValue(value, ctx, quotedAs)}`),
2336
+ in: make((key, value, ctx, quotedAs) => Array.isArray(value) && !value.length ? "false" : `${key} IN ${quoteValue(value, ctx, quotedAs, true)}`),
2337
+ notIn: make((key, value, ctx, quotedAs) => Array.isArray(value) && !value.length ? "true" : `NOT ${key} IN ${quoteValue(value, ctx, quotedAs, true)}`)
2338
+ };
2339
+ const ord = {
2340
+ ...base,
2341
+ lt: make((key, value, ctx, quotedAs) => `${key} < ${quoteValue(value, ctx, quotedAs)}`),
2342
+ lte: make((key, value, ctx, quotedAs) => `${key} <= ${quoteValue(value, ctx, quotedAs)}`),
2343
+ gt: make((key, value, ctx, quotedAs) => `${key} > ${quoteValue(value, ctx, quotedAs)}`),
2344
+ gte: make((key, value, ctx, quotedAs) => `${key} >= ${quoteValue(value, ctx, quotedAs)}`),
2345
+ between: make((key, [from, to], ctx, quotedAs) => `${key} BETWEEN ${quoteValue(from, ctx, quotedAs)} AND ${quoteValue(to, ctx, quotedAs)}`)
2346
+ };
2347
+ const boolean = {
2348
+ ...ord,
2349
+ and: make((key, value, ctx, quotedAs) => `${key} AND ${value.q.expr.toSQL(ctx, quotedAs)}`),
2350
+ or: make((key, value, ctx, quotedAs) => `(${key}) OR (${value.q.expr.toSQL(ctx, quotedAs)})`)
2351
+ };
2352
+ const text = {
2353
+ ...base,
2354
+ contains: make((key, value, ctx, quotedAs) => `${key} ILIKE '%' || ${quoteLikeValue(value, ctx, quotedAs)} || '%'`),
2355
+ containsSensitive: make((key, value, ctx, quotedAs) => `${key} LIKE '%' || ${quoteLikeValue(value, ctx, quotedAs)} || '%'`),
2356
+ startsWith: make((key, value, ctx, quotedAs) => `${key} ILIKE ${quoteLikeValue(value, ctx, quotedAs)} || '%'`),
2357
+ startsWithSensitive: make((key, value, ctx, quotedAs) => `${key} LIKE ${quoteLikeValue(value, ctx, quotedAs)} || '%'`),
2358
+ endsWith: make((key, value, ctx, quotedAs) => `${key} ILIKE '%' || ${quoteLikeValue(value, ctx, quotedAs)}`),
2359
+ endsWithSensitive: make((key, value, ctx, quotedAs) => `${key} LIKE '%' || ${quoteLikeValue(value, ctx, quotedAs)}`)
2360
+ };
2361
+ const ordinalText = {
2362
+ ...ord,
2363
+ ...text
2364
+ };
2365
+ const encodeJsonPath = (ctx, path) => addValue(ctx.values, `{${Array.isArray(path) ? path.join(", ") : path}}`);
2366
+ const jsonPathQueryOp = (key, [path, options], ctx) => `jsonb_path_query_first(${key}, ${addValue(ctx.values, path)}${options?.vars ? `, ${addValue(ctx.values, JSON.stringify(options.vars))}${options.silent ? ", true" : ""}` : options?.silent ? ", NULL, true" : ""})`;
2367
+ const shouldEncodeJson = (ctx) => ctx.q.adapter.driverAdapter.schemaConfig?.jsonEncodedByDriver === false;
2368
+ const quoteJsonValue = (arg, ctx, quotedAs, IN) => {
2369
+ if (arg && typeof arg === "object") {
2370
+ if (IN && Array.isArray(arg)) return `(${arg.map((value) => shouldEncodeJson(ctx) ? addValue(ctx.values, JSON.stringify(value)) : addValue(ctx.values, value)).join(", ")})`;
2371
+ if (Array.isArray(arg)) return shouldEncodeJson(ctx) ? addValue(ctx.values, JSON.stringify(arg)) : addValue(ctx.values, arg);
2372
+ if (isExpression(arg)) return "to_jsonb(" + arg.toSQL(ctx, quotedAs) + ")";
2373
+ if ("toSQL" in arg) return `to_jsonb((${moveMutativeQueryToCte$1(ctx, arg)}))`;
2374
+ }
2375
+ return shouldEncodeJson(ctx) ? addValue(ctx.values, JSON.stringify(arg)) : addValue(ctx.values, arg);
2376
+ };
2377
+ const serializeJsonValue = (arg, ctx, quotedAs) => {
2378
+ if (arg && typeof arg === "object") {
2379
+ if (isExpression(arg)) return "to_jsonb(" + arg.toSQL(ctx, quotedAs) + ")";
2380
+ if ("toSQL" in arg) return `to_jsonb((${moveMutativeQueryToCte$1(ctx, arg)}))`;
2381
+ }
2382
+ return addValue(ctx.values, JSON.stringify(arg));
2383
+ };
2384
+ const Operators = {
2385
+ any: base,
2386
+ boolean,
2387
+ ordinalText,
2388
+ number: ord,
2389
+ date: ord,
2390
+ time: ord,
2391
+ text,
2392
+ json: {
2393
+ ...ord,
2394
+ equals: make((key, value, ctx, quotedAs) => value === null ? `nullif(${key}, 'null'::jsonb) IS NULL` : `${key} = ${quoteJsonValue(value, ctx, quotedAs)}`),
2395
+ not: make((key, value, ctx, quotedAs) => value === null ? `nullif(${key}, 'null'::jsonb) IS NOT NULL` : `${key} != ${quoteJsonValue(value, ctx, quotedAs)}`),
2396
+ isDistinctFrom: make((key, value, ctx, quotedAs) => `${key} IS DISTINCT FROM ${quoteJsonValue(value, ctx, quotedAs)}`),
2397
+ isNotDistinctFrom: make((key, value, ctx, quotedAs) => `${key} IS NOT DISTINCT FROM ${quoteJsonValue(value, ctx, quotedAs)}`),
2398
+ in: make((key, value, ctx, quotedAs) => Array.isArray(value) && !value.length ? "false" : `${key} IN ${quoteJsonValue(value, ctx, quotedAs, true)}`),
2399
+ notIn: make((key, value, ctx, quotedAs) => Array.isArray(value) && !value.length ? "true" : `NOT ${key} IN ${quoteJsonValue(value, ctx, quotedAs, true)}`),
2400
+ jsonPathQueryFirst: Object.assign(function(path, options) {
2401
+ const { q, columnTypes } = this;
2402
+ const chain = q.chain ??= [];
2403
+ chain.push(jsonPathQueryOp, [path, options]);
2404
+ if (getValueParser(q.parsers)) setValueParser(q, void 0);
2405
+ if (options?.type) {
2406
+ const type = options.type(columnTypes);
2407
+ setValueParserToQuery(q, type);
2408
+ chain.push = (...args) => {
2409
+ chain.push = Array.prototype.push;
2410
+ chain.push((s) => `${s}::${type.dataType}`, emptyArray);
2411
+ return chain.push(...args);
2412
+ };
2413
+ return setQueryOperators(this, type.operators);
2414
+ }
2415
+ return this;
2416
+ }, { _op: jsonPathQueryOp }),
2417
+ jsonSupersetOf: make((key, value, ctx, quotedAs) => `${key} @> ${quoteValue(value, ctx, quotedAs)}`),
2418
+ jsonSubsetOf: make((key, value, ctx, quotedAs) => `${key} <@ ${quoteValue(value, ctx, quotedAs)}`),
2419
+ jsonSet: makeVarArg((key, [path, value], ctx, quotedAs) => `jsonb_set(${key}, ${encodeJsonPath(ctx, path)}, ${serializeJsonValue(value, ctx, quotedAs)})`),
2420
+ jsonReplace: makeVarArg((key, [path, value], ctx, quotedAs) => `jsonb_set(${key}, ${encodeJsonPath(ctx, path)}, ${serializeJsonValue(value, ctx, quotedAs)}, false)`),
2421
+ jsonInsert: makeVarArg((key, [path, value, options], ctx, quotedAs) => `jsonb_insert(${key}, ${encodeJsonPath(ctx, path)}, ${serializeJsonValue(value, ctx, quotedAs)}${options?.after ? ", true" : ""})`),
2422
+ jsonRemove: makeVarArg((key, [path], ctx) => `(${key} #- ${encodeJsonPath(ctx, path)})`)
2423
+ },
2424
+ array: {
2425
+ ...ord,
2426
+ has: make((key, value, ctx, quotedAs) => `${quoteValue(value, ctx, quotedAs)} = ANY(${key})`),
2427
+ hasEvery: make((key, value, ctx, quotedAs) => `${key} @> ${quoteValue(value, ctx, quotedAs)}`),
2428
+ hasSome: make((key, value, ctx, quotedAs) => `${key} && ${quoteValue(value, ctx, quotedAs)}`),
2429
+ containedIn: make((key, value, ctx, quotedAs) => `${key} <@ ${quoteValue(value, ctx, quotedAs)}`),
2430
+ length: make((key, value, ctx, quotedAs) => {
2431
+ const expr = `COALESCE(array_length(${key}, 1), 0)`;
2432
+ return typeof value === "number" ? `${expr} = ${quoteValue(value, ctx, quotedAs)}` : Object.keys(value).map((key) => ord[key]._op(expr, value[key], ctx, quotedAs)).join(" AND ");
2433
+ })
2434
+ }
2424
2435
  };
2425
- const internalSchemaConfig = defaultSchemaConfig();
2426
2436
  var TextBaseColumn = class extends Column {
2427
2437
  constructor(schema, schemaType = schema.stringSchema()) {
2428
2438
  super(schema, schemaType);
@@ -2782,22 +2792,6 @@ var CitextColumn = class extends TextBaseColumn {
2782
2792
  return textColumnToCode(this, ctx, key);
2783
2793
  }
2784
2794
  };
2785
- var BooleanColumn = class BooleanColumn extends Column {
2786
- static get instance() {
2787
- return this._instance ??= new BooleanColumn(internalSchemaConfig);
2788
- }
2789
- constructor(schema) {
2790
- super(schema, schema.boolean());
2791
- this.dataType = "bool";
2792
- this.operators = Operators.boolean;
2793
- this.data.alias = "boolean";
2794
- this.data.parseItem = parseItem;
2795
- }
2796
- toCode(ctx, key) {
2797
- return columnCode(this, ctx, key, "boolean()");
2798
- }
2799
- };
2800
- const parseItem = (input) => input[0] === "t";
2801
2795
  var SimpleRawSQL = class extends RawSql {
2802
2796
  makeSQL() {
2803
2797
  return this._sql;
@@ -3434,29 +3428,6 @@ var QueryHooks = class {
3434
3428
  }
3435
3429
  };
3436
3430
  /**
3437
- * generic utility to add a parser to the query object
3438
- * @param query - the query object, it will be mutated
3439
- * @param key - the name of the column in the data loaded by the query
3440
- * @param parser - function to process the value of the column with.
3441
- */
3442
- const setParserToQuery = (query, key, parser) => {
3443
- if (parser) if (query.parsers) query.parsers[key] = parser;
3444
- else query.parsers = { [key]: parser };
3445
- else if (query.parsers) delete query.parsers[key];
3446
- };
3447
- const getQueryParsers = (q, hookSelect) => {
3448
- if (hookSelect) {
3449
- const parsers = { ...q.q.parsers };
3450
- const { defaultParsers } = q.q;
3451
- if (defaultParsers) for (const [key, value] of hookSelect) {
3452
- const parser = defaultParsers[key];
3453
- if (parser) parsers[value.as || key] = parser;
3454
- }
3455
- return parsers;
3456
- }
3457
- return q.q.select ? q.q.parsers : q.q.defaultParsers;
3458
- };
3459
- /**
3460
3431
  * In snake case mode, or when columns have custom names,
3461
3432
  * use this method to exchange a db column name to its runtime key.
3462
3433
  */
@@ -4507,7 +4478,7 @@ const requirePrimaryKeys = (q, message) => {
4507
4478
  };
4508
4479
  const collectPrimaryKeys = (q) => {
4509
4480
  const primaryKeys = [];
4510
- const { shape } = q.q;
4481
+ const { shape } = q;
4511
4482
  for (const key in shape) if (shape[key].data.primaryKey) primaryKeys.push(key);
4512
4483
  const pkey = q.internal.tableData.primaryKey;
4513
4484
  if (pkey) primaryKeys.push(...pkey.columns);
@@ -4749,7 +4720,7 @@ const then = async (q, adapter, state, beforeHooks, afterHooks, afterSaveHooks,
4749
4720
  }
4750
4721
  const { tableHook, cteHooks } = sql;
4751
4722
  const { returnType = "all" } = query;
4752
- const tempReturnType = tableHook?.select || cteHooks?.hasSelect || returnType === "rows" && (q.q.batchParsers || adapter.driverAdapter.noFieldsForArrays) || checkIfNeedResultAllForMutativeQueriesSelectRelations(sql) ? "all" : returnType;
4723
+ const tempReturnType = tableHook?.select || cteHooks?.hasSelect || q.q.batchParsers || adapter.driverAdapter.noFieldsForArrays || checkIfNeedResultAllForMutativeQueriesSelectRelations(sql) ? "all" : returnType;
4753
4724
  let result;
4754
4725
  let queryResult;
4755
4726
  let cteData;
@@ -5005,12 +4976,25 @@ const execQuery = (adapter, method, sql, startingSavepoint, releasingSavepoint,
5005
4976
  });
5006
4977
  };
5007
4978
  const handleResult = (q, returnType, result, sql, isSubQuery) => {
5008
- const parsers = getQueryParsers(q, sql.tableHook?.select);
4979
+ let parsers = getQueryParsers(q, sql.tableHook?.select);
5009
4980
  switch (returnType) {
5010
4981
  case "all": {
5011
4982
  if (q.q.throwOnNotFound && result.rows.length === 0) throw new NotFoundError(q);
5012
4983
  const { rows } = result;
5013
- if (parsers) for (const row of rows) parseRecord(parsers, row);
4984
+ if (q.q.returnType === "value" || q.q.returnType === "valueOrThrow") {
4985
+ if (!rows.length) if (!q.q.select) return rows;
4986
+ else {
4987
+ if (q.q.returnType === "valueOrThrow") throw new NotFoundError(q);
4988
+ return [{ value: q.q.notFoundDefault }];
4989
+ }
4990
+ if (parsers) {
4991
+ const parser = getValueParser(parsers);
4992
+ if (parser) {
4993
+ const hookSelect = sql.tableHook?.select;
4994
+ for (const row of rows) for (const key in row) if (!hookSelect?.has(key)) row[key] = parser(row[key]);
4995
+ }
4996
+ }
4997
+ } else if (parsers) for (const row of rows) parseRecord(parsers, row);
5014
4998
  return rows;
5015
4999
  }
5016
5000
  case "one": {
@@ -5032,7 +5016,7 @@ const handleResult = (q, returnType, result, sql, isSubQuery) => {
5032
5016
  }
5033
5017
  case "pluck": {
5034
5018
  const { rows } = result;
5035
- parsePluck(parsers, isSubQuery, rows);
5019
+ parsePluck(q, parsers, isSubQuery, rows);
5036
5020
  return rows;
5037
5021
  }
5038
5022
  case "value": {
@@ -5069,14 +5053,26 @@ const parseRows = (parsers, fields, rows) => {
5069
5053
  if (parser) for (const row of rows) row[i] = parser(row[i]);
5070
5054
  }
5071
5055
  };
5072
- const parsePluck = (parsers, isSubQuery, rows) => {
5073
- const pluck = parsers?.pluck;
5074
- if (pluck) for (let i = 0; i < rows.length; i++) rows[i] = pluck(isSubQuery ? rows[i] : rows[i][0]);
5056
+ const parsePluck = (query, parsers, isSubQuery, rows) => {
5057
+ const valueToArray = query.q.getColumn?.data?.valueToArray;
5058
+ const parse = parsers?.pluck;
5059
+ if (parse) if (valueToArray) for (let i = 0; i < rows.length; i++) {
5060
+ const value = isSubQuery ? rows[i] : rows[i][0];
5061
+ rows[i] = value === null ? void 0 : value[0] === null ? null : parse(value[0]);
5062
+ }
5063
+ else for (let i = 0; i < rows.length; i++) {
5064
+ const value = isSubQuery ? rows[i] : rows[i][0];
5065
+ rows[i] = value === null ? value : parse(value);
5066
+ }
5067
+ else if (valueToArray) for (let i = 0; i < rows.length; i++) {
5068
+ const value = isSubQuery ? rows[i] : rows[i][0];
5069
+ rows[i] = value === null ? void 0 : value[0];
5070
+ }
5075
5071
  else if (!isSubQuery) for (let i = 0; i < rows.length; i++) rows[i] = rows[i][0];
5076
5072
  };
5077
5073
  const parseValue = (value, parsers) => {
5078
- const parser = parsers?.[getValueKey];
5079
- return parser ? parser(value) : value;
5074
+ const parse = getValueParser(parsers);
5075
+ return parse ? parse(value) : value;
5080
5076
  };
5081
5077
  const filterResult = (q, returnType, queryResult, result, tempColumns, hasAfterHook) => {
5082
5078
  if (returnType === "all") return filterAllResult(result, tempColumns, hasAfterHook);
@@ -5109,7 +5105,7 @@ const filterResult = (q, returnType, queryResult, result, tempColumns, hasAfterH
5109
5105
  }
5110
5106
  };
5111
5107
  const getFirstResultKey = (q, queryResult) => {
5112
- if (q.q.select) return queryResult.fields[0].name;
5108
+ if (q.q.select) return queryResult.fields[0] ? queryResult.fields[0].name : "value";
5113
5109
  else for (const key in q.q.selectedComputeds) return key;
5114
5110
  };
5115
5111
  const filterAllResult = (result, tempColumns, hasAfterHook) => {
@@ -5368,7 +5364,7 @@ function queryFrom(self, arg) {
5368
5364
  if (typeof arg === "string") {
5369
5365
  data.as ||= arg;
5370
5366
  const w = data.withShapes?.[arg];
5371
- data.shape = w?.shape ?? anyShape;
5367
+ data.selectShape = w?.shape ?? anyShape;
5372
5368
  data.runtimeComputeds = w?.computeds;
5373
5369
  const parsers = {};
5374
5370
  data.defaultParsers = parsers;
@@ -5379,7 +5375,7 @@ function queryFrom(self, arg) {
5379
5375
  arg = arg.slice(i + 1);
5380
5376
  } else if (w) data.schema = void 0;
5381
5377
  } else if (Array.isArray(arg)) {
5382
- const shape = { ...data.shape };
5378
+ const shape = { ...data.selectShape };
5383
5379
  const joinedParsers = {};
5384
5380
  for (const item of arg) if (typeof item === "string") {
5385
5381
  const w = data.withShapes[item];
@@ -5401,7 +5397,7 @@ function queryFrom(self, arg) {
5401
5397
  } else {
5402
5398
  const q = prepareSubQueryForSql(self, arg);
5403
5399
  data.as ||= q.q.as || q.table || "t";
5404
- data.shape = getShapeFromSelect(q, true);
5400
+ data.selectShape = getShapeFromSelect(q, true);
5405
5401
  data.defaultParsers = getQueryParsers(q);
5406
5402
  data.batchParsers = q.q.batchParsers;
5407
5403
  }
@@ -5598,7 +5594,7 @@ const processJoinArgs = (joinTo, first, args, joinSubQuery, shape, whereExists,
5598
5594
  const j = joinTo.qb.baseQuery.clone();
5599
5595
  j.table = first;
5600
5596
  j.q = {
5601
- shape: w.shape,
5597
+ selectShape: w.shape,
5602
5598
  runtimeComputeds: w.computeds,
5603
5599
  adapter: joinToQ.adapter,
5604
5600
  handleResult: joinToQ.handleResult,
@@ -5680,7 +5676,7 @@ const makeJoinQueryBuilder = (joinedQuery, joinedShapes, joinTo, shape) => {
5680
5676
  q.q.joinedShapes = joinedShapes;
5681
5677
  q.q.joinTo = joinTo;
5682
5678
  if (q.q.scopes) q.q.scopes = void 0;
5683
- if (shape) q.q.shape = shape;
5679
+ if (shape) q.q.selectShape = shape;
5684
5680
  return q;
5685
5681
  };
5686
5682
  const isRelationQuery = (q) => "joinQuery" in q;
@@ -6507,7 +6503,7 @@ const _chain = (fromQuery, toQuery, rel) => {
6507
6503
  }];
6508
6504
  _applyRelationAliases(self, q);
6509
6505
  q.joinedShapes = {
6510
- [getQueryAs(self)]: self.q.shape,
6506
+ [getQueryAs(self)]: self.q.selectShape,
6511
6507
  ...self.q.joinedShapes
6512
6508
  };
6513
6509
  rel.modifyRelatedQuery?.(query)?.(self);
@@ -6544,14 +6540,14 @@ const resolveSubQueryCallback = (q, cb) => {
6544
6540
  _setSubQueryAliases(arg);
6545
6541
  return cb(arg);
6546
6542
  };
6547
- function simpleColumnToSQL(ctx, queryData, shape, key, column, quotedAs, select, as, jsonList, useSelectList, skipSelectSql) {
6543
+ function simpleColumnToSQL(ctx, queryData, shape, key, column, quotedAs, select, as, jsonList, useSelectList, skipSelectSql, skipValueToArray) {
6548
6544
  let sql;
6549
6545
  let dontAlias;
6550
6546
  if (useSelectList && queryData.select) {
6551
6547
  for (const s of queryData.select) if (typeof s === "object" && "selectAs" in s) {
6552
6548
  if (key in s.selectAs) {
6553
6549
  dontAlias = true;
6554
- sql = simpleColumnToSQL(ctx, queryData, shape, key, shape[key]);
6550
+ sql = simpleColumnToSQL(ctx, queryData, shape, key, shape[key], void 0, void 0, void 0, void 0, void 0, void 0, true);
6555
6551
  break;
6556
6552
  }
6557
6553
  }
@@ -6567,27 +6563,33 @@ function simpleColumnToSQL(ctx, queryData, shape, key, column, quotedAs, select,
6567
6563
  else {
6568
6564
  const name = data.name || key;
6569
6565
  dontAlias = name === as;
6566
+ if (!select) {
6567
+ const joinAs = !select && queryData.valuesJoinedAs?.[key];
6568
+ if (joinAs) quotedAs = `"${joinAs}"`;
6569
+ }
6570
6570
  sql = `${quotedAs ? `${quotedAs}.` : ""}"${name}"`;
6571
6571
  }
6572
6572
  }
6573
+ if (!select && !useSelectList && column?.data.valueToArray && !column.data.skipValueToArray) sql += "[1]";
6574
+ else if (queryData.getColumn?.data.valueToArray && !skipValueToArray) sql = `array[${sql}]`;
6573
6575
  if (as && !dontAlias) sql = `${sql} "${as}"`;
6574
6576
  return sql;
6575
6577
  }
6576
- const tableColumnToSql = (ctx, data, shape, table, key, quotedAs, select, as, jsonList) => {
6578
+ const tableColumnToSql = (ctx, queryData, shape, table, key, quotedAs, select, as, jsonList, skipValueToArray) => {
6577
6579
  let sql;
6578
6580
  let dontAlias;
6579
6581
  if (key === "*") {
6580
6582
  if (jsonList && as) jsonList[as] = void 0;
6581
- const shape = data.joinedShapes?.[table];
6583
+ const shape = queryData.joinedShapes?.[table];
6582
6584
  if (shape) sql = select ? makeRowToJson(ctx, table, shape, true) : `"${table}".*`;
6583
6585
  else {
6584
6586
  sql = `"${table}"."${key}"`;
6585
6587
  dontAlias = true;
6586
6588
  }
6587
6589
  } else {
6588
- const tableName = _getQueryAliasOrName(data, table);
6590
+ const tableName = _getQueryAliasOrName(queryData, table);
6589
6591
  const quoted = `"${table}"`;
6590
- const col = quoted === quotedAs ? shape[key] : data.joinedShapes?.[tableName]?.[key];
6592
+ const col = quoted === quotedAs ? shape[key] : queryData.joinedShapes?.[tableName]?.[key];
6591
6593
  if (jsonList && as) jsonList[as] = col && getSelectedColumnData(col);
6592
6594
  if (col?.data.selectSql) sql = `(${col.data.selectSql.toSQL(ctx, quoted)})`;
6593
6595
  else if (col?.data.name) sql = `"${tableName}"."${col.data.name}"`;
@@ -6596,24 +6598,20 @@ const tableColumnToSql = (ctx, data, shape, table, key, quotedAs, select, as, js
6596
6598
  sql = `"${tableName}"."${key}"`;
6597
6599
  dontAlias = key === as;
6598
6600
  }
6601
+ if (!select && col?.data.valueToArray && !col.data.skipValueToArray) sql += "[1]";
6602
+ else if (queryData.getColumn?.data.valueToArray && !skipValueToArray) sql = `array[${sql}]`;
6599
6603
  }
6600
6604
  if (as && !dontAlias) sql = `${sql} "${as}"`;
6601
6605
  return sql;
6602
6606
  };
6603
- const columnToSql = (ctx, data, shape, column, quotedAs, select, as, jsonList, useSelectList) => {
6607
+ const columnToSqlNotSelect = (ctx, data, shape, column, quotedAs, useSelectList) => columnToSql(ctx, data, shape, column, quotedAs, void 0, void 0, void 0, useSelectList, true);
6608
+ const columnToSql = (ctx, data, shape, column, quotedAs, select, as, jsonList, useSelectList, skipValueToArray) => {
6604
6609
  let index = column.indexOf(".");
6605
- if (index === -1 && !select) {
6606
- const joinAs = data.valuesJoinedAs?.[column];
6607
- if (joinAs) {
6608
- column = joinAs + "." + column;
6609
- index = joinAs.length;
6610
- }
6611
- }
6612
- if (index !== -1) return tableColumnToSql(ctx, data, shape, column.slice(0, index), column.slice(index + 1), quotedAs, select, as, jsonList);
6613
- return simpleColumnToSQL(ctx, data, shape, column, shape[column], quotedAs, select, as, jsonList, useSelectList);
6610
+ if (index !== -1) return tableColumnToSql(ctx, data, shape, column.slice(0, index), column.slice(index + 1), quotedAs, select, as, jsonList, skipValueToArray);
6611
+ return simpleColumnToSQL(ctx, data, shape, column, shape[column], quotedAs, select, as, jsonList, useSelectList, void 0, skipValueToArray);
6614
6612
  };
6615
- const rawOrColumnToSql = (ctx, data, shape, expr, quotedAs, select) => {
6616
- return typeof expr === "string" ? columnToSql(ctx, data, shape, expr, quotedAs, select) : expr.toSQL(ctx, quotedAs);
6613
+ const rawOrColumnToSql = (ctx, data, shape, expr, quotedAs, select, skipValueToArray) => {
6614
+ return typeof expr === "string" ? columnToSql(ctx, data, shape, expr, quotedAs, select, void 0, void 0, void 0, skipValueToArray) : expr.toSQL(ctx, quotedAs);
6617
6615
  };
6618
6616
  const processJoinItem = (ctx, table, query, args, quotedAs) => {
6619
6617
  let target;
@@ -6673,7 +6671,7 @@ const processJoinItem = (ctx, table, query, args, quotedAs) => {
6673
6671
  joinedShapes: {
6674
6672
  ...query.joinedShapes,
6675
6673
  ...q.q.joinedShapes,
6676
- [table.q.as || table.table]: table.q.shape
6674
+ [table.q.as || table.table]: table.q.selectShape
6677
6675
  }
6678
6676
  }, joinAs);
6679
6677
  if (whereSql) if (on) on += ` AND ${whereSql}`;
@@ -6722,17 +6720,17 @@ const getConditionsFor3Or4LengthItem = (ctx, query, target, quotedAs, args, join
6722
6720
  const [leftColumn, opOrRightColumn, maybeRightColumn] = args;
6723
6721
  const op = maybeRightColumn ? opOrRightColumn : "=";
6724
6722
  const rightColumn = maybeRightColumn ? maybeRightColumn : opOrRightColumn;
6725
- return `${rawOrColumnToSql(ctx, query, joinShape, leftColumn, target)} ${op} ${rawOrColumnToSql(ctx, query, query.shape, rightColumn, quotedAs)}`;
6723
+ return `${rawOrColumnToSql(ctx, query, joinShape, leftColumn, target)} ${op} ${rawOrColumnToSql(ctx, query, query.selectShape, rightColumn, quotedAs)}`;
6726
6724
  };
6727
6725
  const getObjectOrRawConditions = (ctx, query, data, quotedAs, joinAs, joinShape) => {
6728
6726
  if (data === true) return "true";
6729
6727
  else if (isExpression(data)) return data.toSQL(ctx, quotedAs);
6730
6728
  else {
6731
6729
  const pairs = [];
6732
- const shape = query.shape;
6730
+ const shape = query.selectShape;
6733
6731
  for (const key in data) {
6734
6732
  const value = data[key];
6735
- pairs.push(`${columnToSql(ctx, query, joinShape, key, joinAs)} = ${rawOrColumnToSql(ctx, query, shape, value, quotedAs)}`);
6733
+ pairs.push(`${columnToSqlNotSelect(ctx, query, joinShape, key, joinAs)} = ${rawOrColumnToSql(ctx, query, shape, value, quotedAs)}`);
6736
6734
  }
6737
6735
  return pairs.join(", ");
6738
6736
  }
@@ -6764,11 +6762,11 @@ var SelectItemExpression = class extends Expression {
6764
6762
  }
6765
6763
  makeSQL(ctx, quotedAs) {
6766
6764
  const q = this.q;
6767
- return typeof this.item === "string" ? this.item === "*" ? selectAllSql(q, quotedAs, void 0, ctx).join(", ") : columnToSql(ctx, q, q.shape, this.item, quotedAs, true) : this.item.toSQL(ctx, quotedAs);
6765
+ return typeof this.item === "string" ? this.item === "*" ? selectAllSql(q, quotedAs, void 0, ctx).join(", ") : columnToSql(ctx, q, q.selectShape, this.item, quotedAs, true, void 0, void 0, void 0, true) : this.item.toSQL(ctx, quotedAs);
6768
6766
  }
6769
6767
  };
6770
6768
  const _getSelectableColumn = (q, arg) => {
6771
- let type = q.q.shape[arg];
6769
+ let type = q.q.selectShape[arg];
6772
6770
  if (!type) {
6773
6771
  const index = arg.indexOf(".");
6774
6772
  if (index !== -1) {
@@ -6785,30 +6783,17 @@ const _get = (query, returnType, arg) => {
6785
6783
  const q = query.q;
6786
6784
  if (q.returning) q.returning = void 0;
6787
6785
  q.returnType = returnType;
6788
- let type;
6789
6786
  let value = arg;
6790
- if (typeof value === "function") {
6791
- const item = processSelectAsArg(query, getQueryAs(query), "value", value);
6792
- if (item !== false) value = item;
6793
- }
6794
- if (typeof value === "string") {
6795
- const joinedAs = q.valuesJoinedAs?.[value];
6796
- type = joinedAs ? q.joinedShapes?.[joinedAs]?.value : _getSelectableColumn(query, value);
6797
- q.getColumn = type;
6798
- const selected = setParserForSelectedString(query, joinedAs ? joinedAs + "." + value : value, getQueryAs(query), getValueKey);
6799
- q.select = selected ? [q.expr = new SelectItemExpression(query, selected, type)] : void 0;
6800
- } else if (isExpression(value)) {
6801
- type = value.result.value;
6802
- q.getColumn = type;
6803
- addParserForRawExpression(query, getValueKey, value);
6804
- q.select = [q.expr = value];
6805
- } else {
6806
- const selected = value;
6807
- q.getColumn = selected.q.getColumn;
6808
- if (q.getColumn) addColumnParserToQuery(q, getValueKey, q.getColumn);
6809
- q.select = selected ? [{ selectAs: { value: selected } }] : void 0;
6787
+ const selectAs = {};
6788
+ let column;
6789
+ const selected = processSelectAsArg(query, selectAs, getQueryAs(query), "v", value, void 0, returnType);
6790
+ if (selected !== false) {
6791
+ q.getColumn = column = selected;
6792
+ value = selectAs.v || value;
6810
6793
  }
6811
- return setQueryOperators(query, type?.operators || Operators.any);
6794
+ if (typeof value === "string") value = selectAs.v && new SelectItemExpression(query, selectAs.v, column);
6795
+ q.select = isExpression(value) ? [q.expr = value] : value ? [{ selectAs: { v: value } }] : void 0;
6796
+ return setQueryOperators(query, column?.operators || Operators.any);
6812
6797
  };
6813
6798
  function _queryGet(self, arg) {
6814
6799
  return _get(self, "valueOrThrow", arg);
@@ -7057,13 +7042,13 @@ const selectToSqlList = (ctx, table, query, quotedAs, hookSelect = query.hookSel
7057
7042
  (selected ??= {})[key] = `"${tableName}"`;
7058
7043
  (selectedAs ??= {})[key] = key;
7059
7044
  }
7060
- sql = tableColumnToSql(ctx, table.q, table.q.shape, tableName, key, quotedAs, true, key === "*" ? tableName : key, jsonList);
7045
+ sql = tableColumnToSql(ctx, query, query.selectShape, tableName, key, quotedAs, true, key === "*" ? tableName : key, jsonList);
7061
7046
  } else {
7062
7047
  if (hookSelect?.get(item)) {
7063
7048
  (selected ??= {})[item] = quotedAs;
7064
7049
  (selectedAs ??= {})[item] = item;
7065
7050
  }
7066
- sql = simpleColumnToSQL(ctx, table.q, table.q.shape, item, table.q.shape[item], quotedAs, true, item, jsonList);
7051
+ sql = simpleColumnToSQL(ctx, query, query.selectShape, item, query.selectShape[item], quotedAs, true, item, jsonList);
7067
7052
  }
7068
7053
  }
7069
7054
  list.push(sql);
@@ -7075,7 +7060,9 @@ const selectToSqlList = (ctx, table, query, quotedAs, hookSelect = query.hookSel
7075
7060
  if (hookSelect) (selected ??= {})[as] = true;
7076
7061
  const value = obj[as];
7077
7062
  if (typeof value === "object") if (isExpression(value)) {
7078
- list.push(`${value.toSQL(ctx, quotedAs)} "${as}"`);
7063
+ let sql = value.toSQL(ctx, quotedAs);
7064
+ if (value.q.getColumn?.data.valueToArray) sql = `array[${sql}]`;
7065
+ list.push(`${sql} "${as}"`);
7079
7066
  if (jsonList) jsonList[as] = value.result.value;
7080
7067
  aliases?.push(as);
7081
7068
  } else if (delayedRelationSelect && isRelationQuery(value)) setMutativeQueriesSelectRelationsSqlState(delayedRelationSelect, as, value);
@@ -7085,13 +7072,14 @@ const selectToSqlList = (ctx, table, query, quotedAs, hookSelect = query.hookSel
7085
7072
  }
7086
7073
  else if (value) {
7087
7074
  if (hookSelect) (selectedAs ??= {})[value] = as;
7088
- list.push(columnToSql(ctx, table.q, table.q.shape, value, quotedAs, true, as, jsonList));
7075
+ list.push(columnToSql(ctx, table.q, table.q.selectShape, value, quotedAs, true, as, jsonList));
7089
7076
  aliases?.push(as);
7090
7077
  }
7091
7078
  }
7092
7079
  } else {
7093
7080
  ctx.selectedCount++;
7094
- const sql = item.toSQL(ctx, quotedAs);
7081
+ let sql = item.toSQL(ctx, quotedAs);
7082
+ if (item.q.getColumn?.data.valueToArray) sql = `array[${sql}]`;
7095
7083
  if (hookSelect && item instanceof SelectItemExpression && typeof item.item === "string" && item.item !== "*") {
7096
7084
  const i = item.item.indexOf(".");
7097
7085
  let key;
@@ -7099,7 +7087,7 @@ const selectToSqlList = (ctx, table, query, quotedAs, hookSelect = query.hookSel
7099
7087
  if (item.item.slice(0, i) === table.table) key = item.item.slice(i + 1);
7100
7088
  } else key = item.item;
7101
7089
  if (key) {
7102
- const column = item.q.shape[key];
7090
+ const column = item.q.selectShape[key];
7103
7091
  (selectedAs ??= {})[key] = column?.data.name || key;
7104
7092
  }
7105
7093
  }
@@ -7121,12 +7109,12 @@ const selectToSqlList = (ctx, table, query, quotedAs, hookSelect = query.hookSel
7121
7109
  quotedTable = `"${tableName}"`;
7122
7110
  columnName = select.slice(index + 1);
7123
7111
  col = table.q.joinedShapes?.[tableName]?.[columnName];
7124
- sql = columnToSql(ctx, table.q, table.q.shape, select, void 0, true);
7112
+ sql = columnToSql(ctx, table.q, table.shape, select, void 0, true, void 0, void 0, void 0, true);
7125
7113
  } else {
7126
7114
  quotedTable = quotedAs;
7127
7115
  columnName = select;
7128
- col = query.shape[select];
7129
- sql = columnToSql(ctx, table.q, query.shape, select, quotedAs, true);
7116
+ col = table.shape[select];
7117
+ sql = columnToSql(ctx, table.q, table.shape, select, quotedAs, true, void 0, void 0, void 0, true);
7130
7118
  }
7131
7119
  } else {
7132
7120
  columnName = column;
@@ -7171,15 +7159,15 @@ const internalSelectAllSql = (ctx, query, quotedAs, jsonList) => {
7171
7159
  jsonList[key] = getSelectedColumnData(column);
7172
7160
  }
7173
7161
  let columnsCount;
7174
- if (query.shape !== anyShape) {
7162
+ if (query.selectShape !== anyShape) {
7175
7163
  columnsCount = 0;
7176
- for (const key in query.shape) if (!query.shape[key].data.explicitSelect) columnsCount++;
7164
+ for (const key in query.selectShape) if (!query.selectShape[key].data.explicitSelect) columnsCount++;
7177
7165
  ctx.selectedCount += columnsCount;
7178
7166
  }
7179
7167
  return selectAllSql(query, quotedAs, columnsCount, ctx);
7180
7168
  };
7181
7169
  const selectAllSql = (q, quotedAs, columnsCount, ctx) => {
7182
- return q.join?.length || q.updateFrom || q.updateMany ? q.selectAllColumns?.map((item) => selectAllColumnToSql(item, ctx, quotedAs, true)) || (isEmptySelect(q.shape, columnsCount) ? [] : [`${quotedAs}.*`]) : q.selectAllColumns ? q.selectAllColumns.map((item) => selectAllColumnToSql(item, ctx, quotedAs)) : isEmptySelect(q.shape, columnsCount) ? [] : ["*"];
7170
+ return q.join?.length || q.updateFrom || q.updateMany ? q.selectAllColumns?.map((item) => selectAllColumnToSql(item, ctx, quotedAs, true)) || (isEmptySelect(q.selectShape, columnsCount) ? [] : [`${quotedAs}.*`]) : q.selectAllColumns ? q.selectAllColumns.map((item) => selectAllColumnToSql(item, ctx, quotedAs)) : isEmptySelect(q.selectShape, columnsCount) ? [] : ["*"];
7183
7171
  };
7184
7172
  const selectAllColumnToSql = (item, ctx, quotedAs, prefix) => {
7185
7173
  if (typeof item !== "string") return item(ctx, quotedAs);
@@ -7355,9 +7343,9 @@ const processWhere = (ands, ctx, table, query, data, quotedAs) => {
7355
7343
  ands.push(`NOT ${processAnds(arr, ctx, table, query, quotedAs, true)}`);
7356
7344
  } else if (key === "ON") if (Array.isArray(value)) {
7357
7345
  const item = value;
7358
- const leftColumn = columnToSql(ctx, query, query.shape, item[0], quotedAs);
7346
+ const leftColumn = columnToSqlNotSelect(ctx, query, query.selectShape, item[0], quotedAs);
7359
7347
  const leftPath = item[1];
7360
- const rightColumn = columnToSql(ctx, query, query.shape, item[2], quotedAs);
7348
+ const rightColumn = columnToSqlNotSelect(ctx, query, query.selectShape, item[2], quotedAs);
7361
7349
  const rightPath = item[3];
7362
7350
  ands.push(`jsonb_path_query_first(${leftColumn}, ${addValue(ctx.values, leftPath)}) = jsonb_path_query_first(${rightColumn}, ${addValue(ctx.values, rightPath)})`);
7363
7351
  } else {
@@ -7366,7 +7354,7 @@ const processWhere = (ands, ctx, table, query, data, quotedAs) => {
7366
7354
  const q = item.useOuterAliases ? {
7367
7355
  joinedShapes: query.joinedShapes,
7368
7356
  aliases: _getQueryOuterAliases(query),
7369
- shape: query.shape
7357
+ selectShape: query.selectShape
7370
7358
  } : query;
7371
7359
  ands.push(`${onColumnToSql(ctx, q, joinAs, item.from)} ${item.op || "="} ${onColumnToSql(ctx, q, joinAs, item.to)}`);
7372
7360
  }
@@ -7390,31 +7378,26 @@ const processWhere = (ands, ctx, table, query, data, quotedAs) => {
7390
7378
  ands.push(`${search.vectorSQL} @@ "${search.as}"`);
7391
7379
  } else if (typeof value === "object" && value && !(value instanceof Date) && !Array.isArray(value)) whereExprOrQuery(ctx, ands, query, key, value, quotedAs);
7392
7380
  else {
7393
- const column = columnToSql(ctx, query, query.shape, key, quotedAs);
7381
+ const column = columnToSqlNotSelect(ctx, query, query.selectShape, key, quotedAs);
7394
7382
  ands.push(`${column} ${value === null ? "IS NULL" : `= ${addValue(ctx.values, value)}`}`);
7395
7383
  }
7396
7384
  }
7397
7385
  };
7398
7386
  const whereExprOrQuery = (ctx, ands, query, key, value, quotedAs) => {
7399
- if (isExpression(value)) ands.push(`${columnToSql(ctx, query, query.shape, key, quotedAs)} = ${value.toSQL(ctx, quotedAs)}`);
7387
+ if (isExpression(value)) ands.push(`${columnToSqlNotSelect(ctx, query, query.selectShape, key, quotedAs)} = ${value.toSQL(ctx, quotedAs)}`);
7400
7388
  else {
7401
- let column = query.shape[key];
7402
- let quotedColumn;
7403
- if (column) quotedColumn = simpleColumnToSQL(ctx, query, query.shape, key, column, quotedAs);
7404
- else if (!column) {
7389
+ let column = query.selectShape[key];
7390
+ if (!column) {
7405
7391
  const index = key.indexOf(".");
7406
- if (index !== -1) {
7392
+ if (index === -1) column = query.joinedShapes?.[key]?.value;
7393
+ else if (index !== -1) {
7407
7394
  const table = key.slice(0, index);
7408
- const quoted = `"${table}"`;
7409
7395
  const name = key.slice(index + 1);
7410
- column = quotedAs === quoted ? query.shape[name] : query.joinedShapes?.[table]?.[name];
7411
- quotedColumn = simpleColumnToSQL(ctx, query, query.shape, name, column, quoted);
7412
- } else {
7413
- column = query.joinedShapes?.[key]?.value;
7414
- quotedColumn = `"${key}"."${key}"`;
7396
+ column = quotedAs === `"${table}"` ? query.selectShape[name] : query.joinedShapes?.[table]?.[name];
7415
7397
  }
7416
- if (!column || !quotedColumn) throw new Error(`Unknown column ${key} provided to condition`);
7417
7398
  }
7399
+ if (!column) throw new Error(`Unknown column ${key} provided to condition`);
7400
+ const quotedColumn = columnToSqlNotSelect(ctx, query, query.selectShape, key, quotedAs);
7418
7401
  if (value instanceof ctx.qb.constructor) {
7419
7402
  const subQuerySql = moveMutativeQueryToCte(ctx, value);
7420
7403
  ands.push(`${quotedColumn} = (${subQuerySql})`);
@@ -7426,7 +7409,7 @@ const whereExprOrQuery = (ctx, ands, query, key, value, quotedAs) => {
7426
7409
  }
7427
7410
  }
7428
7411
  };
7429
- const onColumnToSql = (ctx, query, joinAs, column) => columnToSql(ctx, query, query.shape, column, joinAs);
7412
+ const onColumnToSql = (ctx, query, joinAs, column) => columnToSqlNotSelect(ctx, query, query.selectShape, column, joinAs);
7430
7413
  const getJoinItemSource = (joinItem) => {
7431
7414
  return typeof joinItem === "string" ? joinItem : getQueryAs(joinItem);
7432
7415
  };
@@ -7438,13 +7421,14 @@ const pushIn = (ctx, query, ands, quotedAs, arg) => {
7438
7421
  value = `(${value})`;
7439
7422
  } else if (isExpression(arg.values)) value = arg.values.toSQL(ctx, quotedAs);
7440
7423
  else value = `(${moveMutativeQueryToCte(ctx, arg.values)})`;
7441
- const columnsSql = arg.columns.map((column) => columnToSql(ctx, query, query.shape, column, quotedAs)).join(", ");
7424
+ const columnsSql = arg.columns.map((column) => columnToSqlNotSelect(ctx, query, query.selectShape, column, quotedAs)).join(", ");
7442
7425
  ands.push(`${multiple ? `(${columnsSql})` : columnsSql} IN ${value}`);
7443
7426
  };
7444
7427
  const MAX_BINDING_PARAMS = 65533;
7445
7428
  const makeInsertSql = (ctx, q, query, quotedAs, isSubSql) => {
7446
7429
  let { columns } = query;
7447
- const { shape, hookCreateSet } = query;
7430
+ const shape = q.shape;
7431
+ const { hookCreateSet } = query;
7448
7432
  const QueryClass = ctx.qb.constructor;
7449
7433
  let { insertFrom, queryColumnsCount, values } = query;
7450
7434
  let hookSetSql;
@@ -7481,7 +7465,7 @@ const makeInsertSql = (ctx, q, query, quotedAs, isSubSql) => {
7481
7465
  insertSql: `INSERT INTO ${quoteTableWithSchema(q)}${quotedColumns.length ? "(" + quotedColumns.join(", ") + ")" : ""}`
7482
7466
  };
7483
7467
  ctx.sql.push(null, null);
7484
- const hasOnConflictWhere = pushOnConflictSql(ctx, query, quotedAs, columns, quotedColumns, runtimeDefaultColumns);
7468
+ const hasOnConflictWhere = pushOnConflictSql(ctx, q, query, quotedAs, columns, quotedColumns, runtimeDefaultColumns);
7485
7469
  const upsert = query.type === "upsert";
7486
7470
  if (upsert || insertFrom && !isRelationQuery(q) || hasOnConflictWhere) pushWhereStatementSql(ctx, q, query, quotedAs);
7487
7471
  sqlState.relationSelectState = newMutativeQueriesSelectRelationsSqlState(q);
@@ -7548,9 +7532,9 @@ const makeInsertSql = (ctx, q, query, quotedAs, isSubSql) => {
7548
7532
  values: ctx.values
7549
7533
  };
7550
7534
  };
7551
- const pushOnConflictSql = (ctx, query, quotedAs, columns, quotedColumns, runtimeDefaultColumns) => {
7535
+ const pushOnConflictSql = (ctx, q, query, quotedAs, columns, quotedColumns, runtimeDefaultColumns) => {
7552
7536
  if (!query.onConflict) return false;
7553
- const { shape } = query;
7537
+ const shape = q.shape;
7554
7538
  ctx.sql.push("ON CONFLICT");
7555
7539
  const { target } = query.onConflict;
7556
7540
  if (target) if (typeof target === "string") ctx.sql.push(`("${shape[target]?.data.name || target}")`);
@@ -7763,7 +7747,7 @@ const pushUpdateSqlWithoutValuesJoinedAs = (ctx, query, q, quotedAs, isSubSql) =
7763
7747
  let updateManyValuesSql;
7764
7748
  if (q.updateMany) {
7765
7749
  for (const key of q.updateMany.primaryKeys) usedSetKeys.add(key);
7766
- updateManyValuesSql = makeUpdateManyValuesSql(ctx, query, q, q.updateMany, set, usedSetKeys, quotedAs);
7750
+ updateManyValuesSql = makeUpdateManyValuesSql(ctx, query, q.updateMany, set, usedSetKeys, quotedAs);
7767
7751
  }
7768
7752
  if (!set.length) pushSelectForEmptySet(ctx, query, q, quotedAs, from, isSubSql, updateManyValuesSql, relationSelectState);
7769
7753
  else {
@@ -7838,7 +7822,7 @@ const processData = (ctx, query, set, data, hookSet, usedSetKeys, quotedAs) => {
7838
7822
  };
7839
7823
  const applySet = (ctx, query, set, item, skipColumns, usedSetKeys, quotedAs) => {
7840
7824
  const QueryClass = ctx.qb.constructor;
7841
- const shape = query.q.shape;
7825
+ const shape = query.shape;
7842
7826
  for (const key in item) {
7843
7827
  if (usedSetKeys.has(key)) continue;
7844
7828
  usedSetKeys.add(key);
@@ -7854,12 +7838,12 @@ const processValue = (ctx, query, QueryClass, key, value, quotedAs) => {
7854
7838
  const subQuery = value;
7855
7839
  if (subQuery.q.subQuery === 1) return selectToSql(ctx, query, subQuery.q, quotedAs);
7856
7840
  return `(${moveMutativeQueryToCte(ctx, subQuery)})`;
7857
- } else if ("op" in value && "arg" in value) return `"${query.q.shape[key].data.name || key}" ${value.op} ${addValue(ctx.values, value.arg)}`;
7841
+ } else if ("op" in value && "arg" in value) return `"${query.shape[key].data.name || key}" ${value.op} ${addValue(ctx.values, value.arg)}`;
7858
7842
  }
7859
7843
  return addValue(ctx.values, value);
7860
7844
  };
7861
- const makeUpdateManyValuesSql = (ctx, query, q, updateMany, set, usedSetKeys, quotedAs) => {
7862
- const { shape } = q;
7845
+ const makeUpdateManyValuesSql = (ctx, query, updateMany, set, usedSetKeys, quotedAs) => {
7846
+ const shape = query.shape;
7863
7847
  const keysSet = /* @__PURE__ */ new Set();
7864
7848
  const valueRows = [];
7865
7849
  const quotedColumnNames = [];
@@ -7968,13 +7952,13 @@ const addOrder = (ctx, data, column, quotedAs, dir) => {
7968
7952
  const order = dir || (!search.order || search.order === true ? emptyObject : search.order);
7969
7953
  return `${order.coverDensity ? "ts_rank_cd" : "ts_rank"}(${order.weights ? `${addValue(ctx.values, `{${order.weights}}`)}, ` : ""}${search.vectorSQL}, "${column}"${order.normalization !== void 0 ? `, ${addValue(ctx.values, order.normalization)}` : ""}) ${order.dir || "DESC"}`;
7970
7954
  }
7971
- return `${columnToSql(ctx, data, data.shape, column, quotedAs, void 0, void 0, void 0, true)} ${dir || "ASC"}`;
7955
+ return `${columnToSqlNotSelect(ctx, data, data.selectShape, column, quotedAs, true)} ${dir || "ASC"}`;
7972
7956
  };
7973
7957
  const windowToSql = (ctx, data, window, quotedAs) => {
7974
7958
  if (typeof window === "string") return `"${window}"`;
7975
7959
  if (isExpression(window)) return `(${window.toSQL(ctx, quotedAs)})`;
7976
7960
  const sql = [];
7977
- if (window.partitionBy) sql.push(`PARTITION BY ${Array.isArray(window.partitionBy) ? window.partitionBy.map((partitionBy) => rawOrColumnToSql(ctx, data, data.shape, partitionBy, quotedAs)).join(", ") : rawOrColumnToSql(ctx, data, data.shape, window.partitionBy, quotedAs)}`);
7961
+ if (window.partitionBy) sql.push(`PARTITION BY ${Array.isArray(window.partitionBy) ? window.partitionBy.map((partitionBy) => rawOrColumnToSql(ctx, data, data.selectShape, partitionBy, quotedAs, void 0, true)).join(", ") : rawOrColumnToSql(ctx, data, data.selectShape, window.partitionBy, quotedAs, void 0, true)}`);
7978
7962
  if (window.order) sql.push(`ORDER BY ${orderByToSql(ctx, data, window.order, quotedAs)}`);
7979
7963
  return `(${sql.join(" ")})`;
7980
7964
  };
@@ -7995,12 +7979,6 @@ var FnExpression = class extends Expression {
7995
7979
  this.result = { value };
7996
7980
  this.q = query.q;
7997
7981
  this.q.expr = this;
7998
- Object.assign(query, value.operators);
7999
- query.q.returnType = "valueOrThrow";
8000
- query.q.returnsOne = true;
8001
- query.q.getColumn = value;
8002
- query.q.select = [this];
8003
- addColumnParserToQuery(query.q, getValueKey, value);
8004
7982
  }
8005
7983
  makeSQL(ctx, quotedAs) {
8006
7984
  const sql = [`${this.fn}(`];
@@ -8029,7 +8007,7 @@ var FnExpression = class extends Expression {
8029
8007
  const whereSql = whereToSql(ctx, this.query, {
8030
8008
  and: options.filter ? [options.filter] : void 0,
8031
8009
  or: options.filterOr?.map((item) => [item]),
8032
- shape: q.shape,
8010
+ selectShape: q.selectShape,
8033
8011
  joinedShapes: q.joinedShapes
8034
8012
  }, quotedAs);
8035
8013
  if (whereSql) sql.push(` FILTER (WHERE ${whereSql})`);
@@ -8040,16 +8018,22 @@ var FnExpression = class extends Expression {
8040
8018
  };
8041
8019
  const fnArgToSql = (ctx, data, arg, quotedAs) => {
8042
8020
  if (typeof arg === "string") {
8043
- if (arg.endsWith(".*") || data.valuesJoinedAs?.[arg]) return columnToSql(ctx, data, data.shape, arg, quotedAs);
8044
- return columnToSql(ctx, data, data.shape, arg, quotedAs, true);
8021
+ if (arg.endsWith(".*") || data.valuesJoinedAs?.[arg]) return columnToSql(ctx, data, data.selectShape, arg, quotedAs, void 0, void 0, void 0, void 0, true);
8022
+ return columnToSql(ctx, data, data.selectShape, arg, quotedAs, true, void 0, void 0, void 0, true);
8045
8023
  }
8046
8024
  return arg.toSQL(ctx, quotedAs);
8047
8025
  };
8048
8026
  function makeFnExpression(self, type, fn, args, options) {
8049
8027
  const q = extendQuery(self, type.operators);
8050
8028
  q.baseQuery.type = ExpressionTypeMethod.prototype.type;
8051
- new FnExpression(q, fn, args, options, type);
8029
+ q.q.select = [new FnExpression(q, fn, args, options, type)];
8030
+ q.q.getColumn = type;
8031
+ Object.assign(q, type.operators);
8032
+ setValueParserToQuery(q.q, type);
8033
+ q.q.returnType = "valueOrThrow";
8034
+ q.q.returnsOne = true;
8052
8035
  q.q.transform = void 0;
8036
+ q.q.batchParsers = void 0;
8053
8037
  return q;
8054
8038
  }
8055
8039
  const isSelectingCount = (q) => {
@@ -8058,34 +8042,16 @@ const isSelectingCount = (q) => {
8058
8042
  };
8059
8043
  const intNullable = new IntegerColumn(internalSchemaConfig).nullable().parse(parseInt);
8060
8044
  const floatNullable = new RealColumn(internalSchemaConfig).nullable().parse(parseFloat);
8061
- const booleanNullable = BooleanColumn.instance.nullable();
8045
+ const booleanNullable = BooleanColumn.instanceSkipValueToArray.nullable();
8062
8046
  const textNullable = TextColumn.instance.nullable();
8063
8047
  const jsonTextNullable = JSONTextColumn.instance.nullable();
8064
8048
  const xmlNullable = XMLColumn.instance.nullable();
8065
8049
  const stringAsNumberNullable = new NumberAsStringBaseColumn(internalSchemaConfig).nullable();
8050
+ intNullable.data.skipValueToArray = floatNullable.data.skipValueToArray = textNullable.data.skipValueToArray = jsonTextNullable.data.skipValueToArray = xmlNullable.data.skipValueToArray = stringAsNumberNullable.data.skipValueToArray = true;
8066
8051
  const numericResultColumn = (q, arg) => {
8067
- const query = q;
8068
- let column = (typeof arg === "string" ? _getSelectableColumn(query, arg) : arg.result.value) instanceof NumberBaseColumn ? floatNullable : stringAsNumberNullable;
8069
- const parse = typeof arg === "string" && query.q.parsers?.[arg];
8070
- if (parse) column = column.parse(parse);
8071
- return column;
8052
+ return (typeof arg === "string" ? _getSelectableColumn(q, arg) : arg.result.value) instanceof NumberBaseColumn ? floatNullable : stringAsNumberNullable;
8072
8053
  };
8073
8054
  var AggregateMethods = class {
8074
- /**
8075
- * Use `exists()` to check if there is at least one record-matching condition.
8076
- *
8077
- * It will discard previous `select` statements if any. Returns a boolean.
8078
- *
8079
- * ```ts
8080
- * const exists: boolean = await db.table.where(...conditions).exists();
8081
- * ```
8082
- */
8083
- exists() {
8084
- const q = _queryGetOptional(_clone(this), new RawSql("true"));
8085
- q.q.notFoundDefault = false;
8086
- q.q.coalesceValue = new RawSql("false");
8087
- return q;
8088
- }
8089
8055
  /**
8090
8056
  * Count records with the `count` function:
8091
8057
  *
@@ -8845,7 +8811,7 @@ const createSelect = (q) => {
8845
8811
  * @param createHandlers - collects column `create` functions per column having it, and collects row indexes having a value for this column
8846
8812
  */
8847
8813
  const processCreateItem = (q, item, rowIndex, ctx, encoders, createHandlers) => {
8848
- const { shape } = q.q;
8814
+ const shape = q.shape;
8849
8815
  for (const key in item) {
8850
8816
  const column = shape[key];
8851
8817
  if (!column) continue;
@@ -9396,7 +9362,7 @@ var OnConflictQueryBuilder = class {
9396
9362
  const pushDistinctSql = (ctx, table, distinct, quotedAs) => {
9397
9363
  ctx.sql.push("DISTINCT");
9398
9364
  if (distinct.length) {
9399
- const columns = distinct?.map((item) => rawOrColumnToSql(ctx, table.q, table.q.shape, item, quotedAs));
9365
+ const columns = distinct?.map((item) => rawOrColumnToSql(ctx, table.q, table.q.selectShape, item, quotedAs));
9400
9366
  ctx.sql.push(`ON (${columns?.join(", ") || ""})`);
9401
9367
  }
9402
9368
  };
@@ -9430,20 +9396,20 @@ const searchSourcesToSql = (ctx, data, sources, sql, quotedAs) => {
9430
9396
  return sql;
9431
9397
  };
9432
9398
  const getSearchLang = (ctx, data, source, quotedAs) => {
9433
- return source.langSQL ??= "languageColumn" in source ? columnToSql(ctx, data, data.shape, source.languageColumn, quotedAs) : isRawSQL(source.language) ? source.language.toSQL(ctx) : addValue(ctx.values, source.language || data.language || "english");
9399
+ return source.langSQL ??= "languageColumn" in source ? columnToSqlNotSelect(ctx, data, data.selectShape, source.languageColumn, quotedAs) : isRawSQL(source.language) ? source.language.toSQL(ctx) : addValue(ctx.values, source.language || data.language || "english");
9434
9400
  };
9435
9401
  const getSearchText = (ctx, data, source, quotedAs, forHeadline) => {
9436
9402
  let sql = source.textSQL;
9437
9403
  if (sql) return sql;
9438
- if ("in" in source) if (typeof source.in === "string") sql = columnToSql(ctx, data, data.shape, source.in, quotedAs);
9439
- else if (Array.isArray(source.in)) sql = `concat_ws(' ', ${source.in.map((column) => columnToSql(ctx, data, data.shape, column, quotedAs)).join(", ")})`;
9404
+ if ("in" in source) if (typeof source.in === "string") sql = columnToSqlNotSelect(ctx, data, data.selectShape, source.in, quotedAs);
9405
+ else if (Array.isArray(source.in)) sql = `concat_ws(' ', ${source.in.map((column) => columnToSqlNotSelect(ctx, data, data.selectShape, column, quotedAs)).join(", ")})`;
9440
9406
  else {
9441
9407
  sql = [];
9442
- for (const key in source.in) sql.push(columnToSql(ctx, data, data.shape, key, quotedAs));
9408
+ for (const key in source.in) sql.push(columnToSqlNotSelect(ctx, data, data.selectShape, key, quotedAs));
9443
9409
  }
9444
9410
  else if ("vector" in source) {
9445
9411
  if (forHeadline) throw new Error("Cannot use a search based on a vector column for a search headline");
9446
- sql = columnToSql(ctx, data, data.shape, source.vector, quotedAs);
9412
+ sql = columnToSqlNotSelect(ctx, data, data.selectShape, source.vector, quotedAs);
9447
9413
  } else if (typeof source.text === "string") sql = addValue(ctx.values, source.text);
9448
9414
  else sql = source.text.toSQL(ctx, quotedAs);
9449
9415
  return source.textSQL = sql;
@@ -9659,7 +9625,7 @@ const toSql = (table, type, topCtx, isSubSql, cteName, calledByThen, dontAddTabl
9659
9625
  if (isExpression(item)) return item.toSQL(ctx, quotedAs);
9660
9626
  else {
9661
9627
  const i = aliases.indexOf(item);
9662
- return i !== -1 ? i + 1 : columnToSql(ctx, table.q, table.shape, item, quotedAs);
9628
+ return i !== -1 ? i + 1 : columnToSqlNotSelect(ctx, table.q, table.shape, item, quotedAs);
9663
9629
  }
9664
9630
  });
9665
9631
  sql.push(`GROUP BY ${group.join(", ")}`);
@@ -10081,19 +10047,11 @@ const _joinLateral = (self, type, joinQuery, as, innerJoinLateral) => {
10081
10047
  }
10082
10048
  if (!existingValue) {
10083
10049
  const joinedAs = getQueryAs(query);
10084
- setObjectValueImmutable(joinQuery.q, "joinedShapes", joinedAs, query.q.shape);
10050
+ setObjectValueImmutable(joinQuery.q, "joinedShapes", joinedAs, query.q.selectShape);
10085
10051
  }
10086
10052
  const shape = getShapeFromSelect(joinQuery, true);
10087
10053
  setObjectValueImmutable(query.q, "joinedShapes", joinAs, shape);
10088
- const parsers = getQueryParsers(joinQuery);
10089
- if (joinValue) {
10090
- setObjectValueImmutable(query.q, "valuesJoinedAs", joinAs, joinValueAs);
10091
- if (parsers && getValueKey in parsers) {
10092
- const parse = parsers[getValueKey];
10093
- setParserToQuery(query.q, joinAs, parse);
10094
- parsers[joinAs] = parse;
10095
- }
10096
- }
10054
+ if (joinValue) setObjectValueImmutable(query.q, "valuesJoinedAs", joinAs, joinValueAs);
10097
10055
  setObjectValueImmutable(query.q, "joinedParsers", joinValueAs || joinAs, getQueryParsers(joinQuery));
10098
10056
  if (joinQuery.q.batchParsers) setObjectValueImmutable(query.q, "joinedBatchParsers", joinAs, joinQuery.q.batchParsers);
10099
10057
  if (joinValueAs) {
@@ -10853,15 +10811,12 @@ var OnMethods = class {
10853
10811
  const setSelectRelation = (q) => {
10854
10812
  q.selectRelation = true;
10855
10813
  };
10856
- const addParserForRawExpression = (q, key, raw) => {
10857
- if (raw.result.value) addColumnParserToQuery(q.q, key, raw.result.value);
10858
- };
10859
10814
  const addParsersForSelectJoined = (q, arg, as = arg) => {
10860
10815
  const parsers = q.q.joinedParsers?.[arg];
10861
10816
  if (parsers) setParserToQuery(q.q, as, (row) => parseRecord(parsers, row));
10862
10817
  const batchParsers = q.q.joinedBatchParsers?.[arg];
10863
10818
  if (batchParsers) pushQueryArrayImmutable(q, "batchParsers", batchParsers.map((x) => ({
10864
- path: [as, ...x.path],
10819
+ path: [{ key: as }, ...x.path],
10865
10820
  fn: x.fn
10866
10821
  })));
10867
10822
  };
@@ -10869,19 +10824,24 @@ const addParserForSelectItem = (query, as, key, arg, columnAlias, joinQuery) =>
10869
10824
  if (typeof arg === "object") {
10870
10825
  const { q } = arg;
10871
10826
  if (q.batchParsers) pushQueryArrayImmutable(query, "batchParsers", q.batchParsers.map((bp) => ({
10872
- path: [key, ...bp.path],
10827
+ path: [{
10828
+ key,
10829
+ returnType: q.returnType
10830
+ }, ...bp.path],
10873
10831
  fn: bp.fn
10874
10832
  })));
10875
10833
  const parsers = isExpression(arg) ? void 0 : getQueryParsers(arg);
10876
10834
  if (parsers || q.hookSelect || q.transform || q.returnType === "oneOrThrow" || q.returnType === "valueOrThrow" || q.returnType === "one" || q.returnType === "value") pushQueryValueImmutable(query, "batchParsers", {
10877
- path: [key],
10835
+ path: [{
10836
+ key,
10837
+ returnType: q.returnType
10838
+ }],
10878
10839
  fn: (path, queryResult) => {
10879
10840
  const { rows } = queryResult;
10880
10841
  const originalReturnType = q.returnType || "all";
10881
10842
  let returnType = originalReturnType;
10882
10843
  const { hookSelect } = q;
10883
10844
  const batches = [];
10884
- const last = path.length;
10885
10845
  if (returnType === "value" || returnType === "valueOrThrow") {
10886
10846
  if (hookSelect) batches.push = (item) => {
10887
10847
  if (!(key in item)) returnType = returnType === "value" ? "one" : "oneOrThrow";
@@ -10889,7 +10849,7 @@ const addParserForSelectItem = (query, as, key, arg, columnAlias, joinQuery) =>
10889
10849
  return batches.push(item);
10890
10850
  };
10891
10851
  }
10892
- collectNestedSelectBatches(batches, rows, path, last);
10852
+ collectNestedSelectBatches(batches, rows, path);
10893
10853
  switch (returnType) {
10894
10854
  case "all":
10895
10855
  if (parsers) for (const { data } of batches) for (const one of data) parseRecord(parsers, one);
@@ -10914,16 +10874,28 @@ const addParserForSelectItem = (query, as, key, arg, columnAlias, joinQuery) =>
10914
10874
  }
10915
10875
  case "value":
10916
10876
  case "valueOrThrow": {
10917
- const notNullable = !q.getColumn?.data.isNullable;
10918
- const parse = parsers?.[getValueKey];
10919
- if (parse) if (returnType === "value") for (const item of batches) item.parent[item.key] = item.data = item.data === null ? q.notFoundDefault : parse(item.data);
10877
+ const data = q.getColumn?.data;
10878
+ const notNullable = !data?.isNullable;
10879
+ const valueToArray = data?.valueToArray;
10880
+ const parse = getValueParser(parsers);
10881
+ if (parse) if (returnType === "value") if (valueToArray) for (const item of batches) item.parent[item.key] = item.data = item.data ? item.data[0] === null ? null : parse(item.data[0]) : q.notFoundDefault;
10882
+ else for (const item of batches) item.parent[item.key] = item.data = item.data === null ? q.notFoundDefault : parse(item.data);
10883
+ else if (valueToArray) for (const item of batches) {
10884
+ if (!item.data) throw new NotFoundError(arg);
10885
+ item.parent[item.key] = item.data = item.data[0] === null ? null : parse(item.data[0]);
10886
+ }
10920
10887
  else for (const item of batches) {
10921
10888
  if (notNullable && item.data === null) throw new NotFoundError(arg);
10922
10889
  item.parent[item.key] = item.data = parse(item.data);
10923
10890
  }
10924
10891
  else if (returnType === "value") {
10925
- for (const item of batches) if (item.data === null) item.parent[item.key] = item.data = q.notFoundDefault;
10926
- } else if (notNullable) {
10892
+ if (valueToArray) for (const item of batches) item.parent[item.key] = item.data = item.data ? item.data[0] : q.notFoundDefault;
10893
+ else for (const item of batches) if (item.data === void 0) item.parent[item.key] = item.data = q.notFoundDefault;
10894
+ } else if (valueToArray) for (const item of batches) {
10895
+ if (!item.data) throw new NotFoundError(arg);
10896
+ item.parent[item.key] = item.data = item.data[0];
10897
+ }
10898
+ else if (notNullable) {
10927
10899
  for (const { data } of batches) if (data === null) throw new NotFoundError(arg);
10928
10900
  }
10929
10901
  if (hookSelect) for (const batch of batches) batch.data = [batch.data];
@@ -10961,59 +10933,52 @@ const addParserForSelectItem = (query, as, key, arg, columnAlias, joinQuery) =>
10961
10933
  }
10962
10934
  return arg;
10963
10935
  }
10964
- return setParserForSelectedString(query, arg, as, key, columnAlias);
10936
+ const joinedAs = query.q.valuesJoinedAs?.[arg];
10937
+ return setParserForSelectedString(query, joinedAs ? joinedAs + "." + arg : arg, as, key, columnAlias);
10965
10938
  };
10966
- const collectNestedSelectBatches = (batches, rows, path, last) => {
10967
- const stack = rows.map((row) => ({
10968
- data: row,
10969
- parent: row,
10970
- i: 0,
10971
- key: path[0]
10972
- }));
10973
- while (stack.length > 0) {
10974
- const item = stack.pop();
10975
- const { i } = item;
10976
- if (i === last) {
10977
- batches.push(item);
10978
- continue;
10979
- }
10980
- const { data } = item;
10981
- const key = path[i];
10982
- if (Array.isArray(data)) for (let key = 0; key < data.length; key++) stack.push({
10983
- data: data[key],
10984
- parent: data,
10985
- key,
10986
- i
10987
- });
10988
- else if (data && typeof data === "object") stack.push({
10989
- data: data[key],
10990
- parent: data,
10991
- key,
10992
- i: i + 1
10993
- });
10939
+ const collectNestedSelectBatches = (batches, rows, path) => {
10940
+ const last = path.length - 1;
10941
+ const { key, returnType } = path[0];
10942
+ for (const row of rows) processNestedSelectPathEntry(batches, path, key, returnType, 0, last, row);
10943
+ };
10944
+ const processNestedSelectPathEntry = (batches, path, thisKey, thisReturnType, i, last, parent) => {
10945
+ const data = parent[thisKey];
10946
+ if (i === last) batches.push({
10947
+ data,
10948
+ parent,
10949
+ key: thisKey
10950
+ });
10951
+ else {
10952
+ const { key, returnType } = path[++i];
10953
+ if (!thisReturnType || thisReturnType === "all") for (const row of data) processNestedSelectPathEntry(batches, path, key, returnType, i, last, row);
10954
+ else processNestedSelectPathEntry(batches, path, key, returnType, i, last, data);
10994
10955
  }
10995
10956
  };
10996
10957
  const emptyArrSQL = new RawSql("'[]'");
10997
10958
  const processSelectArg = (q, as, arg, columnAs) => {
10998
- if (typeof arg === "string") return setParserForSelectedString(q, arg, as, columnAs);
10959
+ const query = q;
10960
+ if (typeof arg === "string") return setParserForSelectedString(query, arg, as, columnAs);
10999
10961
  const selectAs = {};
10962
+ const selectShape = query.q.selectShape = { ...query.q.selectShape };
11000
10963
  for (const key in arg) {
11001
- const item = processSelectAsArg(q, as, key, arg[key]);
11002
- if (item === false) return false;
11003
- selectAs[key] = item;
10964
+ const item = processSelectAsArg(q, selectAs, as, key, arg[key], key);
10965
+ if (item) selectShape[key] = item;
10966
+ else if (item === false) return false;
11004
10967
  }
11005
10968
  return { selectAs };
11006
10969
  };
11007
- const processSelectAsArg = (q, as, key, arg) => {
10970
+ const processSelectAsArg = (q, selectAs, as, key, arg, columnAlias, outerReturnType) => {
11008
10971
  const query = q;
11009
10972
  let value = arg;
11010
10973
  let joinQuery;
10974
+ let column;
11011
10975
  if (typeof value === "function") {
11012
10976
  value = resolveSubQueryCallback(q, value);
11013
10977
  if (isQueryNone(value)) {
11014
10978
  if (value.q.innerJoinLateral) return false;
11015
10979
  }
11016
- if (!isExpression(value)) {
10980
+ if (isExpression(value)) column = value.result.value;
10981
+ else {
11017
10982
  if (isRelationQuery(value) && value.q.subQuery !== 1) {
11018
10983
  joinQuery = true;
11019
10984
  setSelectRelation(query.q);
@@ -11034,10 +10999,27 @@ const processSelectAsArg = (q, as, key, arg) => {
11034
10999
  const as = _joinLateral(q, innerJoinLateral || query.q.returnType === "valueOrThrow" ? "JOIN" : "LEFT JOIN", subQuery, key, innerJoinLateral && returnType !== "one" && returnType !== "oneOrThrow");
11035
11000
  if (as) value.q.joinedForSelect = _copyQueryAliasToQuery(value, q, as);
11036
11001
  }
11002
+ if (value.q.getColumn?.data.skipValueToArray) value.q.notFoundDefault ??= null;
11003
+ else if (!value.q.type && (value.q.returnType === "value" || value.q.returnType === "valueOrThrow")) {
11004
+ const column = Object.create(value.q.getColumn || UnknownColumn.instance);
11005
+ column.data = {
11006
+ ...column.data,
11007
+ name: void 0,
11008
+ valueToArray: true
11009
+ };
11010
+ value.q.getColumn = column;
11011
+ if (value.q.expr) value.q.expr.q.getColumn = column;
11012
+ }
11013
+ if (outerReturnType === "value" && value.q.returnType === "valueOrThrow") value.q.returnType = "value";
11014
+ column = value.q.getColumn;
11037
11015
  value = prepareSubQueryForSql(q, value);
11038
11016
  }
11039
- }
11040
- return addParserForSelectItem(query, as, key, value, key, joinQuery);
11017
+ } else if (typeof value === "string") {
11018
+ const joinedAs = query.q.valuesJoinedAs?.[value];
11019
+ column = joinedAs ? query.q.joinedShapes?.[joinedAs]?.value : _getSelectableColumn(query, value);
11020
+ } else column = value.result.value;
11021
+ selectAs[key] = addParserForSelectItem(query, as, key, value, columnAlias, joinQuery);
11022
+ return column;
11041
11023
  };
11042
11024
  const setParserForSelectedString = (query, arg, as, columnAs, columnAlias) => {
11043
11025
  const { q } = query;
@@ -11055,7 +11037,7 @@ const setParserForSelectedString = (query, arg, as, columnAs, columnAlias) => {
11055
11037
  const batchParsers = q.joinedBatchParsers?.[table];
11056
11038
  if (batchParsers) {
11057
11039
  let cloned = false;
11058
- for (const bp of batchParsers) if (bp.path[0] === column) {
11040
+ for (const bp of batchParsers) if (bp.path[0].key === column) {
11059
11041
  if (!cloned) {
11060
11042
  q.batchParsers = [...q.batchParsers || []];
11061
11043
  cloned = true;
@@ -11093,7 +11075,7 @@ const selectColumn = (query, q, key, columnAs, columnAlias) => {
11093
11075
  };
11094
11076
  const getShapeFromSelect = (q, isSubQuery) => {
11095
11077
  const query = q.q;
11096
- const { shape } = query;
11078
+ const { selectShape: shape } = query;
11097
11079
  let select;
11098
11080
  if (query.selectedComputeds) {
11099
11081
  select = query.select ? [...query.select] : [];
@@ -11570,14 +11552,14 @@ var RefExpression = class extends Expression {
11570
11552
  makeSQL(ctx) {
11571
11553
  const q = this.q;
11572
11554
  const as = q.as || this.table;
11573
- return columnToSql(ctx, q, q.shape, this.ref, as && `"${as}"`);
11555
+ return columnToSqlNotSelect(ctx, q, q.selectShape, this.ref, as && `"${as}"`);
11574
11556
  }
11575
11557
  };
11576
11558
  const _queryUpdateMany = (self, primaryKeys, data, strict) => {
11577
11559
  const query = self;
11578
11560
  throwIfReadOnly(query);
11579
11561
  const { q } = query;
11580
- const { shape } = q;
11562
+ const shape = query.shape;
11581
11563
  q.type = "update";
11582
11564
  setUpdateReturning(q);
11583
11565
  if (!data.length) return _queryNone(query);
@@ -11633,7 +11615,7 @@ const _queryUpdate = (updateSelf, arg) => {
11633
11615
  q.type = "update";
11634
11616
  const set = { ...arg };
11635
11617
  pushQueryValueImmutable(query, "updateData", set);
11636
- const { shape } = q;
11618
+ const shape = query.shape;
11637
11619
  let selectQuery;
11638
11620
  for (const key in arg) {
11639
11621
  const item = shape[key];
@@ -12393,16 +12375,16 @@ var QueryExpressions = class {
12393
12375
  */
12394
12376
  ref(arg) {
12395
12377
  const q = _clone(this);
12396
- const { shape } = q.q;
12378
+ const { selectShape } = q.q;
12397
12379
  let column;
12398
12380
  const index = arg.indexOf(".");
12399
12381
  if (index !== -1) {
12400
12382
  const as = q.q.as || q.table;
12401
12383
  const table = getFullColumnTable(q, arg, index, as);
12402
12384
  const col = arg.slice(index + 1);
12403
- if (table === as) column = shape[col];
12385
+ if (table === as) column = selectShape[col];
12404
12386
  else column = q.q.joinedShapes?.[table][col];
12405
- } else column = shape[arg];
12387
+ } else column = selectShape[arg];
12406
12388
  return new RefExpression(column || UnknownColumn.instance, q, arg);
12407
12389
  }
12408
12390
  val(value) {
@@ -12445,7 +12427,7 @@ var QueryExpressions = class {
12445
12427
  * @param options
12446
12428
  */
12447
12429
  fn(fn, args, options) {
12448
- return makeFnExpression(this, emptyObject, fn, args, options);
12430
+ return makeFnExpression(this, UnknownColumn.instance, fn, args, options);
12449
12431
  }
12450
12432
  or(...args) {
12451
12433
  return new OrExpression(args);
@@ -12458,7 +12440,7 @@ const _appendQueryOnUpsertCreate = (main, append, asFn) => {
12458
12440
  return pushQueryValueImmutable(pushQueryValueImmutable(main, "upsertCreateAppendQueries", prepareSubQueryForSql(main, append)), "upsertCreateAsFns", asFn);
12459
12441
  };
12460
12442
  const mergableObjects = new Set([
12461
- "shape",
12443
+ "selectShape",
12462
12444
  "withShapes",
12463
12445
  "defaultParsers",
12464
12446
  "parsers",
@@ -12662,7 +12644,7 @@ var Headline = class extends Expression {
12662
12644
  const { source, params } = this;
12663
12645
  const q = this.q;
12664
12646
  const lang = getSearchLang(ctx, q, source, quotedAs);
12665
- const text = params?.text ? params.text instanceof Expression ? params.text.toSQL(ctx, quotedAs) : columnToSql(ctx, q, q.shape, params.text, quotedAs) : getSearchText(ctx, q, source, quotedAs, true);
12647
+ const text = params?.text ? params.text instanceof Expression ? params.text.toSQL(ctx, quotedAs) : columnToSqlNotSelect(ctx, q, q.selectShape, params.text, quotedAs) : getSearchText(ctx, q, source, quotedAs, true);
12666
12648
  const options = params?.options ? `, ${params.options instanceof Expression ? params.options.toSQL(ctx, quotedAs) : addValue(ctx.values, params.options)}` : "";
12667
12649
  return `ts_headline(${lang}, ${text}, "${source.as}"${options})`;
12668
12650
  }
@@ -12988,10 +12970,12 @@ var QueryPluck = class {
12988
12970
  const q = _clone(this);
12989
12971
  q.q.returnType = "pluck";
12990
12972
  let selected;
12991
- if (typeof select === "function") {
12992
- const item = processSelectAsArg(q, q.q.as || q.table, "pluck", select);
12993
- if (item !== false) selected = isExpression(item) ? item : { selectAs: { pluck: item } };
12994
- } else selected = addParserForSelectItem(q, q.q.as || q.table, "pluck", select);
12973
+ const selectAs = {};
12974
+ const item = processSelectAsArg(q, selectAs, q.q.as || q.table, "pluck", select, void 0, "value");
12975
+ if (item !== false) {
12976
+ q.q.getColumn = item;
12977
+ selected = typeof selectAs.pluck === "object" && !isExpression(selectAs.pluck) ? { selectAs } : selectAs.pluck;
12978
+ }
12995
12979
  q.q.select = selected ? [selected] : void 0;
12996
12980
  return q;
12997
12981
  }
@@ -13288,6 +13272,39 @@ var QueryWindow = class {
13288
13272
  return pushQueryValueImmutable(_clone(this), "window", arg);
13289
13273
  }
13290
13274
  };
13275
+ const _exists = (query, value) => {
13276
+ const q = _queryGetOptional(_clone(query), new RawSql(String(value)));
13277
+ q.q.notFoundDefault = !value;
13278
+ q.q.coalesceValue = new RawSql(String(!value));
13279
+ q.q.getColumn = BooleanColumn.instanceSkipValueToArray;
13280
+ return q;
13281
+ };
13282
+ var QueryExistsMethods = class {
13283
+ /**
13284
+ * Use `exists()` to check if there is at least one record-matching condition.
13285
+ *
13286
+ * It will discard previous `select` statements if any. Returns a boolean.
13287
+ *
13288
+ * ```ts
13289
+ * const exists: boolean = await db.table.where(...conditions).exists();
13290
+ * ```
13291
+ */
13292
+ exists() {
13293
+ return _exists(this, true);
13294
+ }
13295
+ /**
13296
+ * Use `notExists()` to check if there are no matching records.
13297
+ *
13298
+ * It will discard previous `select` statements if any. Returns a boolean.
13299
+ *
13300
+ * ```ts
13301
+ * const exists: boolean = await db.table.where(...conditions).notExists();
13302
+ * ```
13303
+ */
13304
+ notExists() {
13305
+ return _exists(this, false);
13306
+ }
13307
+ };
13291
13308
  var QueryMethods = class {
13292
13309
  /**
13293
13310
  * `.all` is a default behavior, that returns an array of objects:
@@ -13361,6 +13378,30 @@ var QueryMethods = class {
13361
13378
  return _queryExec(_clone(this));
13362
13379
  }
13363
13380
  /**
13381
+ * For relation selects, `require` changes LEFT JOIN LATERAL to JOIN LATERAL.
13382
+ *
13383
+ * ```ts
13384
+ * // only the records that have `related` will be loaded:
13385
+ * await db.table.select({ related: (q) => q.related.required() });
13386
+ * ```
13387
+ */
13388
+ require() {
13389
+ const query = _clone(this);
13390
+ switch (query.q.returnType) {
13391
+ case void 0:
13392
+ case "all":
13393
+ case "valueOrThrow":
13394
+ case "pluck":
13395
+ case "void": break;
13396
+ case "value":
13397
+ query.q.returnType = "valueOrThrow";
13398
+ break;
13399
+ default: query.q.returnType = "oneOrThrow";
13400
+ }
13401
+ query.q.innerJoinLateral = true;
13402
+ return query;
13403
+ }
13404
+ /**
13364
13405
  * Call `toSQL` on a query to get an object with a `text` SQL string and a `values` array of binding values:
13365
13406
  *
13366
13407
  * ```ts
@@ -13564,7 +13605,7 @@ var QueryMethods = class {
13564
13605
  * // all the following queries will resolve into empty arrays
13565
13606
  *
13566
13607
  * await db.user.select({
13567
- * pets: (q) => q.pets.join().none(),
13608
+ * pets: (q) => q.pets.require().none(),
13568
13609
  * });
13569
13610
  *
13570
13611
  * await db.user.join((q) => q.pets.none());
@@ -13814,7 +13855,8 @@ applyMixins(QueryMethods, [
13814
13855
  SoftDeleteMethods,
13815
13856
  QueryExpressions,
13816
13857
  QueryWrap,
13817
- QueryWindow
13858
+ QueryWindow,
13859
+ QueryExistsMethods
13818
13860
  ]);
13819
13861
  const performQuery = async (q, args, method) => {
13820
13862
  const trx = q.internal.asyncStorage.getStore();
@@ -13929,7 +13971,7 @@ var Db = class extends QueryMethods {
13929
13971
  };
13930
13972
  this.q = {
13931
13973
  adapter: adapterNotInTransaction,
13932
- shape,
13974
+ selectShape: shape,
13933
13975
  handleResult,
13934
13976
  logger,
13935
13977
  log: logParamToLogObject(logger, options.log),
@@ -14267,7 +14309,7 @@ const makeColumnInfoSql = (query, column) => {
14267
14309
  const values = [];
14268
14310
  const schema = getQuerySchema(query);
14269
14311
  let text = `SELECT * FROM information_schema.columns WHERE table_name = ${addValue(values, query.table)} AND table_catalog = current_database() AND table_schema = ${schema ? addValue(values, schema) : "current_schema()"}`;
14270
- if (column) text += ` AND column_name = ${addValue(values, query.q.shape[column]?.data.name || column)}`;
14312
+ if (column) text += ` AND column_name = ${addValue(values, query.shape[column]?.data.name || column)}`;
14271
14313
  return {
14272
14314
  text,
14273
14315
  values
@@ -14323,7 +14365,7 @@ const makeCopySql = (table, copy) => {
14323
14365
  const ctx = newToSqlCtx(table);
14324
14366
  const { q } = table;
14325
14367
  const quotedAs = `"${q.as || table.table}"`;
14326
- const columns = copy.columns ? `(${copy.columns.map((item) => `"${q.shape[item]?.data.name || item}"`).join(", ")})` : "";
14368
+ const columns = copy.columns ? `(${copy.columns.map((item) => `"${table.shape[item]?.data.name || item}"`).join(", ")})` : "";
14327
14369
  const target = "from" in copy ? copy.from : copy.to;
14328
14370
  const quotedTable = quoteTableWithSchema(table);
14329
14371
  ctx.sql.push(`COPY ${quotedTable}${columns} ${"from" in copy ? "FROM" : "TO"} ${typeof target === "string" ? escapeString(target) : `PROGRAM ${escapeString(target.program)}`}`);