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.mjs CHANGED
@@ -1681,6 +1681,44 @@ const columnCode = (type, ctx, key, code) => {
1681
1681
  if (data.modifyQuery && !ctx.migration) addCode(code, `.modifyQuery(${data.modifyQuery.toString()})`);
1682
1682
  return code.length === 1 && typeof code[0] === "string" ? code[0] : code;
1683
1683
  };
1684
+ /**
1685
+ * generic utility to add a parser to the query object
1686
+ * @param query - the query object, it will be mutated
1687
+ * @param key - the name of the column in the data loaded by the query
1688
+ * @param parser - function to process the value of the column with.
1689
+ */
1690
+ const setParserToQuery = (query, key, parser) => {
1691
+ if (parser) if (query.parsers) query.parsers[key] = parser;
1692
+ else query.parsers = { [key]: parser };
1693
+ else if (query.parsers) delete query.parsers[key];
1694
+ };
1695
+ const getQueryParsers = (q, hookSelect) => {
1696
+ if (hookSelect) {
1697
+ const parsers = { ...q.q.parsers };
1698
+ const { defaultParsers } = q.q;
1699
+ if (defaultParsers) for (const [key, value] of hookSelect) {
1700
+ const parser = defaultParsers[key];
1701
+ if (parser) parsers[value.as || key] = parser;
1702
+ }
1703
+ return parsers;
1704
+ }
1705
+ return q.q.select ? q.q.parsers : q.q.defaultParsers;
1706
+ };
1707
+ const addColumnParserToQuery = (q, key, column) => {
1708
+ if (column._parse) setObjectValueImmutable(q, "parsers", key, column._parse);
1709
+ };
1710
+ const setValueParserToQuery = (q, column) => {
1711
+ addColumnParserToQuery(q, "v", column);
1712
+ };
1713
+ const getValueParser = (parsers) => {
1714
+ return parsers?.v;
1715
+ };
1716
+ const setValueParser = (q, parser) => {
1717
+ setObjectValueImmutable(q, "parsers", "v", parser);
1718
+ };
1719
+ const addParserForRawExpression = (q, key, raw) => {
1720
+ if (raw.result.value) addColumnParserToQuery(q.q, key, raw.result.value);
1721
+ };
1684
1722
  var CustomTypeColumn = class extends Column {
1685
1723
  constructor(schema, typeName, typeSchema, extension) {
1686
1724
  super(schema, schema.unknown(), schema.unknown(), schema.unknown());
@@ -1728,9 +1766,6 @@ var EnumColumn = class extends Column {
1728
1766
  return `"${index === -1 ? name : `${name.slice(0, index)}"."${name.slice(index + 1)}`}"`;
1729
1767
  }
1730
1768
  };
1731
- const addColumnParserToQuery = (q, key, column) => {
1732
- if (column._parse) setObjectValueImmutable(q, "parsers", key, column._parse);
1733
- };
1734
1769
  const setColumnDefaultParse = (column, parse) => {
1735
1770
  column.data.parse = parse;
1736
1771
  column._parse = (input) => input === null ? null : parse(input);
@@ -1772,178 +1807,6 @@ const setColumnEncode = (column, fn, inputSchema) => {
1772
1807
  const getColumnBaseType = (column, domainsMap, type) => {
1773
1808
  return column instanceof EnumColumn ? "text" : column instanceof DomainColumn ? domainsMap[column.dataType]?.dataType : type;
1774
1809
  };
1775
- const getValueKey = Symbol("get");
1776
- let moveMutativeQueryToCte$1;
1777
- const setMoveMutativeQueryToCte = (fn) => {
1778
- moveMutativeQueryToCte$1 = fn;
1779
- };
1780
- let prepareSubQueryForSql$1;
1781
- const setPrepareSubQueryForSql = (fn) => {
1782
- prepareSubQueryForSql$1 = fn;
1783
- };
1784
- let dbClass;
1785
- const setDb = (db) => {
1786
- dbClass = db;
1787
- };
1788
- function setQueryOperators(query, operators) {
1789
- const q = query.q;
1790
- if (q.operators !== operators) {
1791
- q.operators = operators;
1792
- Object.assign(query, operators);
1793
- }
1794
- return query;
1795
- }
1796
- /**
1797
- * Makes operator function that has `_op` property.
1798
- *
1799
- * @param _op - function to turn the operator call into SQL.
1800
- */
1801
- const make = (_op) => {
1802
- return Object.assign(function(value) {
1803
- const { q } = this;
1804
- const val = prepareOpArg(this, value);
1805
- (q.chain ??= []).push(_op, val || value);
1806
- if (q.parsers?.[getValueKey]) setObjectValueImmutable(q, "parsers", getValueKey, void 0);
1807
- return setQueryOperators(this, boolean);
1808
- }, { _op });
1809
- };
1810
- const makeVarArg = (_op) => {
1811
- return Object.assign(function(...args) {
1812
- const { q } = this;
1813
- args.forEach((arg, i) => {
1814
- const val = prepareOpArg(this, arg);
1815
- if (val) args[i] = val;
1816
- });
1817
- (q.chain ??= []).push(_op, args);
1818
- if (q.parsers?.[getValueKey]) setObjectValueImmutable(q, "parsers", getValueKey, void 0);
1819
- return setQueryOperators(this, boolean);
1820
- }, { _op });
1821
- };
1822
- const prepareOpArg = (q, arg) => {
1823
- return arg instanceof dbClass ? prepareSubQueryForSql$1(q, arg) : void 0;
1824
- };
1825
- const quoteValue = (arg, ctx, quotedAs, IN) => {
1826
- if (arg && typeof arg === "object") {
1827
- if (IN && isIterable(arg)) return `(${(Array.isArray(arg) ? arg : [...arg]).map((value) => addValue(ctx.values, value)).join(", ")})`;
1828
- if (isExpression(arg)) return arg.toSQL(ctx, quotedAs);
1829
- if ("toSQL" in arg) return `(${moveMutativeQueryToCte$1(ctx, arg)})`;
1830
- if (!(arg instanceof Date) && !Array.isArray(arg)) arg = JSON.stringify(arg);
1831
- }
1832
- return addValue(ctx.values, arg);
1833
- };
1834
- const quoteLikeValue = (arg, ctx, quotedAs, jsonArray) => {
1835
- if (arg && typeof arg === "object") {
1836
- if (!jsonArray && Array.isArray(arg)) return `(${arg.map((value) => addValue(ctx.values, value)).join(", ")})`;
1837
- if (isExpression(arg)) return arg.toSQL(ctx, quotedAs);
1838
- if ("toSQL" in arg) return `replace(replace((${moveMutativeQueryToCte$1(ctx, arg)}), '%', '\\\\%'), '_', '\\\\_')`;
1839
- }
1840
- return addValue(ctx.values, arg.replace(/[%_]/g, "\\$&"));
1841
- };
1842
- const base = {
1843
- equals: make((key, value, ctx, quotedAs) => value === null ? `${key} IS NULL` : `${key} = ${quoteValue(value, ctx, quotedAs)}`),
1844
- not: make((key, value, ctx, quotedAs) => value === null ? `${key} IS NOT NULL` : `${key} <> ${quoteValue(value, ctx, quotedAs)}`),
1845
- isDistinctFrom: make((key, value, ctx, quotedAs) => `${key} IS DISTINCT FROM ${quoteValue(value, ctx, quotedAs)}`),
1846
- isNotDistinctFrom: make((key, value, ctx, quotedAs) => `${key} IS NOT DISTINCT FROM ${quoteValue(value, ctx, quotedAs)}`),
1847
- in: make((key, value, ctx, quotedAs) => Array.isArray(value) && !value.length ? "false" : `${key} IN ${quoteValue(value, ctx, quotedAs, true)}`),
1848
- notIn: make((key, value, ctx, quotedAs) => Array.isArray(value) && !value.length ? "true" : `NOT ${key} IN ${quoteValue(value, ctx, quotedAs, true)}`)
1849
- };
1850
- const ord = {
1851
- ...base,
1852
- lt: make((key, value, ctx, quotedAs) => `${key} < ${quoteValue(value, ctx, quotedAs)}`),
1853
- lte: make((key, value, ctx, quotedAs) => `${key} <= ${quoteValue(value, ctx, quotedAs)}`),
1854
- gt: make((key, value, ctx, quotedAs) => `${key} > ${quoteValue(value, ctx, quotedAs)}`),
1855
- gte: make((key, value, ctx, quotedAs) => `${key} >= ${quoteValue(value, ctx, quotedAs)}`),
1856
- between: make((key, [from, to], ctx, quotedAs) => `${key} BETWEEN ${quoteValue(from, ctx, quotedAs)} AND ${quoteValue(to, ctx, quotedAs)}`)
1857
- };
1858
- const boolean = {
1859
- ...ord,
1860
- and: make((key, value, ctx, quotedAs) => `${key} AND ${value.q.expr.toSQL(ctx, quotedAs)}`),
1861
- or: make((key, value, ctx, quotedAs) => `(${key}) OR (${value.q.expr.toSQL(ctx, quotedAs)})`)
1862
- };
1863
- const text = {
1864
- ...base,
1865
- contains: make((key, value, ctx, quotedAs) => `${key} ILIKE '%' || ${quoteLikeValue(value, ctx, quotedAs)} || '%'`),
1866
- containsSensitive: make((key, value, ctx, quotedAs) => `${key} LIKE '%' || ${quoteLikeValue(value, ctx, quotedAs)} || '%'`),
1867
- startsWith: make((key, value, ctx, quotedAs) => `${key} ILIKE ${quoteLikeValue(value, ctx, quotedAs)} || '%'`),
1868
- startsWithSensitive: make((key, value, ctx, quotedAs) => `${key} LIKE ${quoteLikeValue(value, ctx, quotedAs)} || '%'`),
1869
- endsWith: make((key, value, ctx, quotedAs) => `${key} ILIKE '%' || ${quoteLikeValue(value, ctx, quotedAs)}`),
1870
- endsWithSensitive: make((key, value, ctx, quotedAs) => `${key} LIKE '%' || ${quoteLikeValue(value, ctx, quotedAs)}`)
1871
- };
1872
- const ordinalText = {
1873
- ...ord,
1874
- ...text
1875
- };
1876
- const encodeJsonPath = (ctx, path) => addValue(ctx.values, `{${Array.isArray(path) ? path.join(", ") : path}}`);
1877
- 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" : ""})`;
1878
- const shouldEncodeJson = (ctx) => ctx.q.adapter.driverAdapter.schemaConfig?.jsonEncodedByDriver === false;
1879
- const quoteJsonValue = (arg, ctx, quotedAs, IN) => {
1880
- if (arg && typeof arg === "object") {
1881
- if (IN && Array.isArray(arg)) return `(${arg.map((value) => shouldEncodeJson(ctx) ? addValue(ctx.values, JSON.stringify(value)) : addValue(ctx.values, value)).join(", ")})`;
1882
- if (Array.isArray(arg)) return shouldEncodeJson(ctx) ? addValue(ctx.values, JSON.stringify(arg)) : addValue(ctx.values, arg);
1883
- if (isExpression(arg)) return "to_jsonb(" + arg.toSQL(ctx, quotedAs) + ")";
1884
- if ("toSQL" in arg) return `to_jsonb((${moveMutativeQueryToCte$1(ctx, arg)}))`;
1885
- }
1886
- return addValue(ctx.values, JSON.stringify(arg)) + "::jsonb";
1887
- };
1888
- const serializeJsonValue = (arg, ctx, quotedAs) => {
1889
- if (arg && typeof arg === "object") {
1890
- if (isExpression(arg)) return "to_jsonb(" + arg.toSQL(ctx, quotedAs) + ")";
1891
- if ("toSQL" in arg) return `to_jsonb((${moveMutativeQueryToCte$1(ctx, arg)}))`;
1892
- }
1893
- return addValue(ctx.values, JSON.stringify(arg));
1894
- };
1895
- const Operators = {
1896
- any: base,
1897
- boolean,
1898
- ordinalText,
1899
- number: ord,
1900
- date: ord,
1901
- time: ord,
1902
- text,
1903
- json: {
1904
- ...ord,
1905
- equals: make((key, value, ctx, quotedAs) => value === null ? `nullif(${key}, 'null'::jsonb) IS NULL` : `${key} = ${quoteJsonValue(value, ctx, quotedAs)}`),
1906
- not: make((key, value, ctx, quotedAs) => value === null ? `nullif(${key}, 'null'::jsonb) IS NOT NULL` : `${key} != ${quoteJsonValue(value, ctx, quotedAs)}`),
1907
- isDistinctFrom: make((key, value, ctx, quotedAs) => `${key} IS DISTINCT FROM ${quoteJsonValue(value, ctx, quotedAs)}`),
1908
- isNotDistinctFrom: make((key, value, ctx, quotedAs) => `${key} IS NOT DISTINCT FROM ${quoteJsonValue(value, ctx, quotedAs)}`),
1909
- in: make((key, value, ctx, quotedAs) => Array.isArray(value) && !value.length ? "false" : `${key} IN ${quoteJsonValue(value, ctx, quotedAs, true)}`),
1910
- notIn: make((key, value, ctx, quotedAs) => Array.isArray(value) && !value.length ? "true" : `NOT ${key} IN ${quoteJsonValue(value, ctx, quotedAs, true)}`),
1911
- jsonPathQueryFirst: Object.assign(function(path, options) {
1912
- const { q, columnTypes } = this;
1913
- const chain = q.chain ??= [];
1914
- chain.push(jsonPathQueryOp, [path, options]);
1915
- if (q.parsers?.[getValueKey]) setObjectValueImmutable(q, "parsers", getValueKey, void 0);
1916
- if (options?.type) {
1917
- const type = options.type(columnTypes);
1918
- addColumnParserToQuery(q, getValueKey, type);
1919
- chain.push = (...args) => {
1920
- chain.push = Array.prototype.push;
1921
- chain.push((s) => `${s}::${type.dataType}`, emptyArray);
1922
- return chain.push(...args);
1923
- };
1924
- return setQueryOperators(this, type.operators);
1925
- }
1926
- return this;
1927
- }, { _op: jsonPathQueryOp }),
1928
- jsonSupersetOf: make((key, value, ctx, quotedAs) => `${key} @> ${quoteValue(value, ctx, quotedAs)}`),
1929
- jsonSubsetOf: make((key, value, ctx, quotedAs) => `${key} <@ ${quoteValue(value, ctx, quotedAs)}`),
1930
- jsonSet: makeVarArg((key, [path, value], ctx, quotedAs) => `jsonb_set(${key}, ${encodeJsonPath(ctx, path)}, ${serializeJsonValue(value, ctx, quotedAs)})`),
1931
- jsonReplace: makeVarArg((key, [path, value], ctx, quotedAs) => `jsonb_set(${key}, ${encodeJsonPath(ctx, path)}, ${serializeJsonValue(value, ctx, quotedAs)}, false)`),
1932
- jsonInsert: makeVarArg((key, [path, value, options], ctx, quotedAs) => `jsonb_insert(${key}, ${encodeJsonPath(ctx, path)}, ${serializeJsonValue(value, ctx, quotedAs)}${options?.after ? ", true" : ""})`),
1933
- jsonRemove: makeVarArg((key, [path], ctx) => `(${key} #- ${encodeJsonPath(ctx, path)})`)
1934
- },
1935
- array: {
1936
- ...ord,
1937
- has: make((key, value, ctx, quotedAs) => `${quoteValue(value, ctx, quotedAs)} = ANY(${key})`),
1938
- hasEvery: make((key, value, ctx, quotedAs) => `${key} @> ${quoteValue(value, ctx, quotedAs)}`),
1939
- hasSome: make((key, value, ctx, quotedAs) => `${key} && ${quoteValue(value, ctx, quotedAs)}`),
1940
- containedIn: make((key, value, ctx, quotedAs) => `${key} <@ ${quoteValue(value, ctx, quotedAs)}`),
1941
- length: make((key, value, ctx, quotedAs) => {
1942
- const expr = `COALESCE(array_length(${key}, 1), 0)`;
1943
- return typeof value === "number" ? `${expr} = ${quoteValue(value, ctx, quotedAs)}` : Object.keys(value).map((key) => ord[key]._op(expr, value[key], ctx, quotedAs)).join(" AND ");
1944
- })
1945
- }
1946
- };
1947
1810
  const dateToString = (value) => value.toISOString();
1948
1811
  const dateTimeEncode = (value) => {
1949
1812
  return typeof value === "number" ? new Date(value) : value;
@@ -2071,7 +1934,6 @@ var ArrayColumn = class ArrayColumn extends Column {
2071
1934
  this.dataType = "array";
2072
1935
  this.operators = Operators.array;
2073
1936
  item.data.isNullable = true;
2074
- setColumnDefaultParse(this, (input) => parse$1.call(this, input));
2075
1937
  if (defaultEncode) setColumnDefaultEncode(this, defaultEncode);
2076
1938
  this.data.item = item instanceof ArrayColumn ? item.data.item : item;
2077
1939
  this.data.name = item.data.name;
@@ -2097,54 +1959,6 @@ var ArrayColumn = class ArrayColumn extends Column {
2097
1959
  return columnCode(this, ctx, key, code);
2098
1960
  }
2099
1961
  };
2100
- const parse$1 = function(source) {
2101
- if (typeof source !== "string") return source;
2102
- const entries = [];
2103
- parsePostgresArray(source, entries, this.data.item.data.parseItem);
2104
- return entries;
2105
- };
2106
- /**
2107
- * based on https://github.com/bendrucker/postgres-array/tree/master
2108
- * and slightly optimized
2109
- */
2110
- const parsePostgresArray = (source, entries, transform) => {
2111
- let pos = 0;
2112
- if (source[0] === "[") {
2113
- pos = source.indexOf("=") + 1;
2114
- if (!pos) pos = source.length;
2115
- }
2116
- if (source[pos] === "{") pos++;
2117
- let recorded = "";
2118
- while (pos < source.length) {
2119
- const character = source[pos++];
2120
- if (character === "{") {
2121
- const innerEntries = [];
2122
- entries.push(innerEntries);
2123
- pos += parsePostgresArray(source.slice(pos - 1), innerEntries, transform) - 1;
2124
- } else if (character === "}") {
2125
- if (recorded) entries.push(recorded === "NULL" ? null : transform ? transform(recorded) : recorded);
2126
- return pos;
2127
- } else if (character === "\"") {
2128
- let esc = false;
2129
- let rec = "";
2130
- while (pos < source.length) {
2131
- let char;
2132
- while ((char = source[pos++]) === "\\") if (!(esc = !esc)) rec += "\\";
2133
- if (esc) esc = false;
2134
- else if (char === "\"") break;
2135
- rec += char;
2136
- }
2137
- entries.push(transform ? transform(rec) : rec);
2138
- recorded = "";
2139
- } else if (character === ",") {
2140
- if (recorded) {
2141
- entries.push(recorded === "NULL" ? null : transform ? transform(recorded) : recorded);
2142
- recorded = "";
2143
- }
2144
- } else recorded += character;
2145
- }
2146
- return pos;
2147
- };
2148
1962
  const encodeJson = (x) => x === null ? x : JSON.stringify(x);
2149
1963
  var JSONColumn = class extends Column {
2150
1964
  constructor(schema, __inputType, encodedByDriver = true) {
@@ -2341,65 +2155,261 @@ const defaultSchemaConfig = (options) => {
2341
2155
  },
2342
2156
  narrowAllTypes() {
2343
2157
  return this;
2344
- },
2345
- dateAsNumber() {
2346
- return this.parse(getDateAsNumberFn(this));
2347
- },
2348
- dateAsDate() {
2349
- return this.parse(getDateAsDateFn(this));
2350
- },
2351
- enum(dataType, type) {
2352
- return new EnumColumn(schemaConfig, dataType, type, void 0);
2353
- },
2354
- array(item) {
2355
- return new ArrayColumn(schemaConfig, item, void 0, options?.arrayEncode);
2356
- },
2357
- boolean: noop,
2358
- buffer: noop,
2359
- unknown: noop,
2360
- never: noop,
2361
- stringSchema: noop,
2362
- stringMin: noop,
2363
- stringMax: noop,
2364
- stringMinMax: noop,
2365
- number: noop,
2366
- int: noop,
2367
- stringNumberDate: noop,
2368
- timeInterval: noop,
2369
- bit: noop,
2370
- uuid: noop,
2371
- nullable() {
2372
- return setColumnData(this, "isNullable", true);
2373
- },
2374
- json() {
2375
- return new JSONColumn(schemaConfig, void 0, options?.jsonEncodedByDriver);
2376
- },
2377
- jsonText() {
2378
- return new JSONTextColumn(schemaConfig, void 0);
2379
- },
2380
- setErrors: noop,
2381
- smallint: () => new SmallIntColumn(schemaConfig),
2382
- integer: () => new IntegerColumn(schemaConfig),
2383
- real: () => new RealColumn(schemaConfig),
2384
- smallSerial: () => new SmallSerialColumn(schemaConfig),
2385
- serial: () => new SerialColumn(schemaConfig),
2386
- bigint: () => new BigIntColumn(schemaConfig),
2387
- decimal: (precision, scale) => new DecimalColumn(schemaConfig, precision, scale),
2388
- doublePrecision: () => new DoublePrecisionColumn(schemaConfig),
2389
- bigSerial: () => new BigSerialColumn(schemaConfig),
2390
- money: () => new MoneyColumn(schemaConfig),
2391
- varchar: (limit) => new VarCharColumn(schemaConfig, limit),
2392
- text: () => new TextColumn(schemaConfig),
2393
- string: (limit) => new StringColumn(schemaConfig, limit),
2394
- citext: () => new CitextColumn(schemaConfig),
2395
- date: () => new DateColumn(schemaConfig, options?.dateParsedByDriver),
2396
- timestampNoTZ: (precision) => new TimestampColumn(schemaConfig, precision, options?.dateParsedByDriver),
2397
- timestamp: (precision) => new TimestampTZColumn(schemaConfig, precision, options?.dateParsedByDriver),
2398
- geographyPointSchema: noop
2399
- };
2400
- return schemaConfig;
2158
+ },
2159
+ dateAsNumber() {
2160
+ return this.parse(getDateAsNumberFn(this));
2161
+ },
2162
+ dateAsDate() {
2163
+ return this.parse(getDateAsDateFn(this));
2164
+ },
2165
+ enum(dataType, type) {
2166
+ return new EnumColumn(schemaConfig, dataType, type, void 0);
2167
+ },
2168
+ array(item) {
2169
+ return new ArrayColumn(schemaConfig, item, void 0, options?.arrayEncode);
2170
+ },
2171
+ boolean: noop,
2172
+ buffer: noop,
2173
+ unknown: noop,
2174
+ never: noop,
2175
+ stringSchema: noop,
2176
+ stringMin: noop,
2177
+ stringMax: noop,
2178
+ stringMinMax: noop,
2179
+ number: noop,
2180
+ int: noop,
2181
+ stringNumberDate: noop,
2182
+ timeInterval: noop,
2183
+ bit: noop,
2184
+ uuid: noop,
2185
+ nullable() {
2186
+ return setColumnData(this, "isNullable", true);
2187
+ },
2188
+ json() {
2189
+ return new JSONColumn(schemaConfig, void 0, options?.jsonEncodedByDriver);
2190
+ },
2191
+ jsonText() {
2192
+ return new JSONTextColumn(schemaConfig, void 0);
2193
+ },
2194
+ setErrors: noop,
2195
+ smallint: () => new SmallIntColumn(schemaConfig),
2196
+ integer: () => new IntegerColumn(schemaConfig),
2197
+ real: () => new RealColumn(schemaConfig),
2198
+ smallSerial: () => new SmallSerialColumn(schemaConfig),
2199
+ serial: () => new SerialColumn(schemaConfig),
2200
+ bigint: () => new BigIntColumn(schemaConfig),
2201
+ decimal: (precision, scale) => new DecimalColumn(schemaConfig, precision, scale),
2202
+ doublePrecision: () => new DoublePrecisionColumn(schemaConfig),
2203
+ bigSerial: () => new BigSerialColumn(schemaConfig),
2204
+ money: () => new MoneyColumn(schemaConfig),
2205
+ varchar: (limit) => new VarCharColumn(schemaConfig, limit),
2206
+ text: () => new TextColumn(schemaConfig),
2207
+ string: (limit) => new StringColumn(schemaConfig, limit),
2208
+ citext: () => new CitextColumn(schemaConfig),
2209
+ date: () => new DateColumn(schemaConfig, options?.dateParsedByDriver),
2210
+ timestampNoTZ: (precision) => new TimestampColumn(schemaConfig, precision, options?.dateParsedByDriver),
2211
+ timestamp: (precision) => new TimestampTZColumn(schemaConfig, precision, options?.dateParsedByDriver),
2212
+ geographyPointSchema: noop
2213
+ };
2214
+ return schemaConfig;
2215
+ };
2216
+ const internalSchemaConfig = defaultSchemaConfig();
2217
+ var BooleanColumn = class BooleanColumn extends Column {
2218
+ static get instance() {
2219
+ return this._instance ??= new BooleanColumn(internalSchemaConfig);
2220
+ }
2221
+ static get instanceSkipValueToArray() {
2222
+ let instance = this._instanceSkipValueToArray;
2223
+ if (!instance) {
2224
+ instance = this._instanceSkipValueToArray = Object.create(this.instance);
2225
+ instance.data.skipValueToArray = true;
2226
+ }
2227
+ return instance;
2228
+ }
2229
+ constructor(schema) {
2230
+ super(schema, schema.boolean());
2231
+ this.dataType = "bool";
2232
+ this.operators = Operators.boolean;
2233
+ this.data.alias = "boolean";
2234
+ this.data.parseItem = parseItem;
2235
+ }
2236
+ toCode(ctx, key) {
2237
+ return columnCode(this, ctx, key, "boolean()");
2238
+ }
2239
+ };
2240
+ const parseItem = (input) => input[0] === "t";
2241
+ let moveMutativeQueryToCte$1;
2242
+ const setMoveMutativeQueryToCte = (fn) => {
2243
+ moveMutativeQueryToCte$1 = fn;
2244
+ };
2245
+ let prepareSubQueryForSql$1;
2246
+ const setPrepareSubQueryForSql = (fn) => {
2247
+ prepareSubQueryForSql$1 = fn;
2248
+ };
2249
+ let dbClass;
2250
+ const setDb = (db) => {
2251
+ dbClass = db;
2252
+ };
2253
+ function setQueryOperators(query, operators) {
2254
+ const q = query.q;
2255
+ if (q.operators !== operators) {
2256
+ q.operators = operators;
2257
+ Object.assign(query, operators);
2258
+ }
2259
+ return query;
2260
+ }
2261
+ /**
2262
+ * Makes operator function that has `_op` property.
2263
+ *
2264
+ * @param _op - function to turn the operator call into SQL.
2265
+ */
2266
+ const make = (_op) => {
2267
+ return Object.assign(function(value) {
2268
+ const { q } = this;
2269
+ const val = prepareOpArg(this, value);
2270
+ (q.chain ??= []).push(_op, val || value);
2271
+ if (getValueParser(q.parsers)) setValueParser(q, void 0);
2272
+ q.getColumn = BooleanColumn.instance;
2273
+ return setQueryOperators(this, boolean);
2274
+ }, { _op });
2275
+ };
2276
+ const makeVarArg = (_op) => {
2277
+ return Object.assign(function(...args) {
2278
+ const { q } = this;
2279
+ args.forEach((arg, i) => {
2280
+ const val = prepareOpArg(this, arg);
2281
+ if (val) args[i] = val;
2282
+ });
2283
+ (q.chain ??= []).push(_op, args);
2284
+ if (getValueParser(q.parsers)) setValueParser(q, void 0);
2285
+ return setQueryOperators(this, boolean);
2286
+ }, { _op });
2287
+ };
2288
+ const prepareOpArg = (q, arg) => {
2289
+ return arg instanceof dbClass ? prepareSubQueryForSql$1(q, arg) : void 0;
2290
+ };
2291
+ const quoteValue = (arg, ctx, quotedAs, IN) => {
2292
+ if (arg && typeof arg === "object") {
2293
+ if (IN && isIterable(arg)) return `(${(Array.isArray(arg) ? arg : [...arg]).map((value) => addValue(ctx.values, value)).join(", ")})`;
2294
+ if (isExpression(arg)) return arg.toSQL(ctx, quotedAs);
2295
+ if ("toSQL" in arg) return `(${moveMutativeQueryToCte$1(ctx, arg)})`;
2296
+ if (!(arg instanceof Date) && !Array.isArray(arg)) arg = JSON.stringify(arg);
2297
+ }
2298
+ return addValue(ctx.values, arg);
2299
+ };
2300
+ const quoteLikeValue = (arg, ctx, quotedAs, jsonArray) => {
2301
+ if (arg && typeof arg === "object") {
2302
+ if (!jsonArray && Array.isArray(arg)) return `(${arg.map((value) => addValue(ctx.values, value)).join(", ")})`;
2303
+ if (isExpression(arg)) return arg.toSQL(ctx, quotedAs);
2304
+ if ("toSQL" in arg) return `replace(replace((${moveMutativeQueryToCte$1(ctx, arg)}), '%', '\\\\%'), '_', '\\\\_')`;
2305
+ }
2306
+ return addValue(ctx.values, arg.replace(/[%_]/g, "\\$&"));
2307
+ };
2308
+ const base = {
2309
+ equals: make((key, value, ctx, quotedAs) => value === null ? `${key} IS NULL` : `${key} = ${quoteValue(value, ctx, quotedAs)}`),
2310
+ not: make((key, value, ctx, quotedAs) => value === null ? `${key} IS NOT NULL` : `${key} <> ${quoteValue(value, ctx, quotedAs)}`),
2311
+ isDistinctFrom: make((key, value, ctx, quotedAs) => `${key} IS DISTINCT FROM ${quoteValue(value, ctx, quotedAs)}`),
2312
+ isNotDistinctFrom: make((key, value, ctx, quotedAs) => `${key} IS NOT DISTINCT FROM ${quoteValue(value, ctx, quotedAs)}`),
2313
+ in: make((key, value, ctx, quotedAs) => Array.isArray(value) && !value.length ? "false" : `${key} IN ${quoteValue(value, ctx, quotedAs, true)}`),
2314
+ notIn: make((key, value, ctx, quotedAs) => Array.isArray(value) && !value.length ? "true" : `NOT ${key} IN ${quoteValue(value, ctx, quotedAs, true)}`)
2315
+ };
2316
+ const ord = {
2317
+ ...base,
2318
+ lt: make((key, value, ctx, quotedAs) => `${key} < ${quoteValue(value, ctx, quotedAs)}`),
2319
+ lte: make((key, value, ctx, quotedAs) => `${key} <= ${quoteValue(value, ctx, quotedAs)}`),
2320
+ gt: make((key, value, ctx, quotedAs) => `${key} > ${quoteValue(value, ctx, quotedAs)}`),
2321
+ gte: make((key, value, ctx, quotedAs) => `${key} >= ${quoteValue(value, ctx, quotedAs)}`),
2322
+ between: make((key, [from, to], ctx, quotedAs) => `${key} BETWEEN ${quoteValue(from, ctx, quotedAs)} AND ${quoteValue(to, ctx, quotedAs)}`)
2323
+ };
2324
+ const boolean = {
2325
+ ...ord,
2326
+ and: make((key, value, ctx, quotedAs) => `${key} AND ${value.q.expr.toSQL(ctx, quotedAs)}`),
2327
+ or: make((key, value, ctx, quotedAs) => `(${key}) OR (${value.q.expr.toSQL(ctx, quotedAs)})`)
2328
+ };
2329
+ const text = {
2330
+ ...base,
2331
+ contains: make((key, value, ctx, quotedAs) => `${key} ILIKE '%' || ${quoteLikeValue(value, ctx, quotedAs)} || '%'`),
2332
+ containsSensitive: make((key, value, ctx, quotedAs) => `${key} LIKE '%' || ${quoteLikeValue(value, ctx, quotedAs)} || '%'`),
2333
+ startsWith: make((key, value, ctx, quotedAs) => `${key} ILIKE ${quoteLikeValue(value, ctx, quotedAs)} || '%'`),
2334
+ startsWithSensitive: make((key, value, ctx, quotedAs) => `${key} LIKE ${quoteLikeValue(value, ctx, quotedAs)} || '%'`),
2335
+ endsWith: make((key, value, ctx, quotedAs) => `${key} ILIKE '%' || ${quoteLikeValue(value, ctx, quotedAs)}`),
2336
+ endsWithSensitive: make((key, value, ctx, quotedAs) => `${key} LIKE '%' || ${quoteLikeValue(value, ctx, quotedAs)}`)
2337
+ };
2338
+ const ordinalText = {
2339
+ ...ord,
2340
+ ...text
2341
+ };
2342
+ const encodeJsonPath = (ctx, path) => addValue(ctx.values, `{${Array.isArray(path) ? path.join(", ") : path}}`);
2343
+ 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" : ""})`;
2344
+ const shouldEncodeJson = (ctx) => ctx.q.adapter.driverAdapter.schemaConfig?.jsonEncodedByDriver === false;
2345
+ const quoteJsonValue = (arg, ctx, quotedAs, IN) => {
2346
+ if (arg && typeof arg === "object") {
2347
+ if (IN && Array.isArray(arg)) return `(${arg.map((value) => shouldEncodeJson(ctx) ? addValue(ctx.values, JSON.stringify(value)) : addValue(ctx.values, value)).join(", ")})`;
2348
+ if (Array.isArray(arg)) return shouldEncodeJson(ctx) ? addValue(ctx.values, JSON.stringify(arg)) : addValue(ctx.values, arg);
2349
+ if (isExpression(arg)) return "to_jsonb(" + arg.toSQL(ctx, quotedAs) + ")";
2350
+ if ("toSQL" in arg) return `to_jsonb((${moveMutativeQueryToCte$1(ctx, arg)}))`;
2351
+ }
2352
+ return shouldEncodeJson(ctx) ? addValue(ctx.values, JSON.stringify(arg)) : addValue(ctx.values, arg);
2353
+ };
2354
+ const serializeJsonValue = (arg, ctx, quotedAs) => {
2355
+ if (arg && typeof arg === "object") {
2356
+ if (isExpression(arg)) return "to_jsonb(" + arg.toSQL(ctx, quotedAs) + ")";
2357
+ if ("toSQL" in arg) return `to_jsonb((${moveMutativeQueryToCte$1(ctx, arg)}))`;
2358
+ }
2359
+ return addValue(ctx.values, JSON.stringify(arg));
2360
+ };
2361
+ const Operators = {
2362
+ any: base,
2363
+ boolean,
2364
+ ordinalText,
2365
+ number: ord,
2366
+ date: ord,
2367
+ time: ord,
2368
+ text,
2369
+ json: {
2370
+ ...ord,
2371
+ equals: make((key, value, ctx, quotedAs) => value === null ? `nullif(${key}, 'null'::jsonb) IS NULL` : `${key} = ${quoteJsonValue(value, ctx, quotedAs)}`),
2372
+ not: make((key, value, ctx, quotedAs) => value === null ? `nullif(${key}, 'null'::jsonb) IS NOT NULL` : `${key} != ${quoteJsonValue(value, ctx, quotedAs)}`),
2373
+ isDistinctFrom: make((key, value, ctx, quotedAs) => `${key} IS DISTINCT FROM ${quoteJsonValue(value, ctx, quotedAs)}`),
2374
+ isNotDistinctFrom: make((key, value, ctx, quotedAs) => `${key} IS NOT DISTINCT FROM ${quoteJsonValue(value, ctx, quotedAs)}`),
2375
+ in: make((key, value, ctx, quotedAs) => Array.isArray(value) && !value.length ? "false" : `${key} IN ${quoteJsonValue(value, ctx, quotedAs, true)}`),
2376
+ notIn: make((key, value, ctx, quotedAs) => Array.isArray(value) && !value.length ? "true" : `NOT ${key} IN ${quoteJsonValue(value, ctx, quotedAs, true)}`),
2377
+ jsonPathQueryFirst: Object.assign(function(path, options) {
2378
+ const { q, columnTypes } = this;
2379
+ const chain = q.chain ??= [];
2380
+ chain.push(jsonPathQueryOp, [path, options]);
2381
+ if (getValueParser(q.parsers)) setValueParser(q, void 0);
2382
+ if (options?.type) {
2383
+ const type = options.type(columnTypes);
2384
+ setValueParserToQuery(q, type);
2385
+ chain.push = (...args) => {
2386
+ chain.push = Array.prototype.push;
2387
+ chain.push((s) => `${s}::${type.dataType}`, emptyArray);
2388
+ return chain.push(...args);
2389
+ };
2390
+ return setQueryOperators(this, type.operators);
2391
+ }
2392
+ return this;
2393
+ }, { _op: jsonPathQueryOp }),
2394
+ jsonSupersetOf: make((key, value, ctx, quotedAs) => `${key} @> ${quoteValue(value, ctx, quotedAs)}`),
2395
+ jsonSubsetOf: make((key, value, ctx, quotedAs) => `${key} <@ ${quoteValue(value, ctx, quotedAs)}`),
2396
+ jsonSet: makeVarArg((key, [path, value], ctx, quotedAs) => `jsonb_set(${key}, ${encodeJsonPath(ctx, path)}, ${serializeJsonValue(value, ctx, quotedAs)})`),
2397
+ jsonReplace: makeVarArg((key, [path, value], ctx, quotedAs) => `jsonb_set(${key}, ${encodeJsonPath(ctx, path)}, ${serializeJsonValue(value, ctx, quotedAs)}, false)`),
2398
+ jsonInsert: makeVarArg((key, [path, value, options], ctx, quotedAs) => `jsonb_insert(${key}, ${encodeJsonPath(ctx, path)}, ${serializeJsonValue(value, ctx, quotedAs)}${options?.after ? ", true" : ""})`),
2399
+ jsonRemove: makeVarArg((key, [path], ctx) => `(${key} #- ${encodeJsonPath(ctx, path)})`)
2400
+ },
2401
+ array: {
2402
+ ...ord,
2403
+ has: make((key, value, ctx, quotedAs) => `${quoteValue(value, ctx, quotedAs)} = ANY(${key})`),
2404
+ hasEvery: make((key, value, ctx, quotedAs) => `${key} @> ${quoteValue(value, ctx, quotedAs)}`),
2405
+ hasSome: make((key, value, ctx, quotedAs) => `${key} && ${quoteValue(value, ctx, quotedAs)}`),
2406
+ containedIn: make((key, value, ctx, quotedAs) => `${key} <@ ${quoteValue(value, ctx, quotedAs)}`),
2407
+ length: make((key, value, ctx, quotedAs) => {
2408
+ const expr = `COALESCE(array_length(${key}, 1), 0)`;
2409
+ return typeof value === "number" ? `${expr} = ${quoteValue(value, ctx, quotedAs)}` : Object.keys(value).map((key) => ord[key]._op(expr, value[key], ctx, quotedAs)).join(" AND ");
2410
+ })
2411
+ }
2401
2412
  };
2402
- const internalSchemaConfig = defaultSchemaConfig();
2403
2413
  var TextBaseColumn = class extends Column {
2404
2414
  constructor(schema, schemaType = schema.stringSchema()) {
2405
2415
  super(schema, schemaType);
@@ -2759,22 +2769,6 @@ var CitextColumn = class extends TextBaseColumn {
2759
2769
  return textColumnToCode(this, ctx, key);
2760
2770
  }
2761
2771
  };
2762
- var BooleanColumn = class BooleanColumn extends Column {
2763
- static get instance() {
2764
- return this._instance ??= new BooleanColumn(internalSchemaConfig);
2765
- }
2766
- constructor(schema) {
2767
- super(schema, schema.boolean());
2768
- this.dataType = "bool";
2769
- this.operators = Operators.boolean;
2770
- this.data.alias = "boolean";
2771
- this.data.parseItem = parseItem;
2772
- }
2773
- toCode(ctx, key) {
2774
- return columnCode(this, ctx, key, "boolean()");
2775
- }
2776
- };
2777
- const parseItem = (input) => input[0] === "t";
2778
2772
  var SimpleRawSQL = class extends RawSql {
2779
2773
  makeSQL() {
2780
2774
  return this._sql;
@@ -3411,29 +3405,6 @@ var QueryHooks = class {
3411
3405
  }
3412
3406
  };
3413
3407
  /**
3414
- * generic utility to add a parser to the query object
3415
- * @param query - the query object, it will be mutated
3416
- * @param key - the name of the column in the data loaded by the query
3417
- * @param parser - function to process the value of the column with.
3418
- */
3419
- const setParserToQuery = (query, key, parser) => {
3420
- if (parser) if (query.parsers) query.parsers[key] = parser;
3421
- else query.parsers = { [key]: parser };
3422
- else if (query.parsers) delete query.parsers[key];
3423
- };
3424
- const getQueryParsers = (q, hookSelect) => {
3425
- if (hookSelect) {
3426
- const parsers = { ...q.q.parsers };
3427
- const { defaultParsers } = q.q;
3428
- if (defaultParsers) for (const [key, value] of hookSelect) {
3429
- const parser = defaultParsers[key];
3430
- if (parser) parsers[value.as || key] = parser;
3431
- }
3432
- return parsers;
3433
- }
3434
- return q.q.select ? q.q.parsers : q.q.defaultParsers;
3435
- };
3436
- /**
3437
3408
  * In snake case mode, or when columns have custom names,
3438
3409
  * use this method to exchange a db column name to its runtime key.
3439
3410
  */
@@ -4484,7 +4455,7 @@ const requirePrimaryKeys = (q, message) => {
4484
4455
  };
4485
4456
  const collectPrimaryKeys = (q) => {
4486
4457
  const primaryKeys = [];
4487
- const { shape } = q.q;
4458
+ const { shape } = q;
4488
4459
  for (const key in shape) if (shape[key].data.primaryKey) primaryKeys.push(key);
4489
4460
  const pkey = q.internal.tableData.primaryKey;
4490
4461
  if (pkey) primaryKeys.push(...pkey.columns);
@@ -4726,7 +4697,7 @@ const then = async (q, adapter, state, beforeHooks, afterHooks, afterSaveHooks,
4726
4697
  }
4727
4698
  const { tableHook, cteHooks } = sql;
4728
4699
  const { returnType = "all" } = query;
4729
- const tempReturnType = tableHook?.select || cteHooks?.hasSelect || returnType === "rows" && (q.q.batchParsers || adapter.driverAdapter.noFieldsForArrays) || checkIfNeedResultAllForMutativeQueriesSelectRelations(sql) ? "all" : returnType;
4700
+ const tempReturnType = tableHook?.select || cteHooks?.hasSelect || q.q.batchParsers || adapter.driverAdapter.noFieldsForArrays || checkIfNeedResultAllForMutativeQueriesSelectRelations(sql) ? "all" : returnType;
4730
4701
  let result;
4731
4702
  let queryResult;
4732
4703
  let cteData;
@@ -4982,12 +4953,25 @@ const execQuery = (adapter, method, sql, startingSavepoint, releasingSavepoint,
4982
4953
  });
4983
4954
  };
4984
4955
  const handleResult = (q, returnType, result, sql, isSubQuery) => {
4985
- const parsers = getQueryParsers(q, sql.tableHook?.select);
4956
+ let parsers = getQueryParsers(q, sql.tableHook?.select);
4986
4957
  switch (returnType) {
4987
4958
  case "all": {
4988
4959
  if (q.q.throwOnNotFound && result.rows.length === 0) throw new NotFoundError(q);
4989
4960
  const { rows } = result;
4990
- if (parsers) for (const row of rows) parseRecord(parsers, row);
4961
+ if (q.q.returnType === "value" || q.q.returnType === "valueOrThrow") {
4962
+ if (!rows.length) if (!q.q.select) return rows;
4963
+ else {
4964
+ if (q.q.returnType === "valueOrThrow") throw new NotFoundError(q);
4965
+ return [{ value: q.q.notFoundDefault }];
4966
+ }
4967
+ if (parsers) {
4968
+ const parser = getValueParser(parsers);
4969
+ if (parser) {
4970
+ const hookSelect = sql.tableHook?.select;
4971
+ for (const row of rows) for (const key in row) if (!hookSelect?.has(key)) row[key] = parser(row[key]);
4972
+ }
4973
+ }
4974
+ } else if (parsers) for (const row of rows) parseRecord(parsers, row);
4991
4975
  return rows;
4992
4976
  }
4993
4977
  case "one": {
@@ -5009,7 +4993,7 @@ const handleResult = (q, returnType, result, sql, isSubQuery) => {
5009
4993
  }
5010
4994
  case "pluck": {
5011
4995
  const { rows } = result;
5012
- parsePluck(parsers, isSubQuery, rows);
4996
+ parsePluck(q, parsers, isSubQuery, rows);
5013
4997
  return rows;
5014
4998
  }
5015
4999
  case "value": {
@@ -5046,14 +5030,26 @@ const parseRows = (parsers, fields, rows) => {
5046
5030
  if (parser) for (const row of rows) row[i] = parser(row[i]);
5047
5031
  }
5048
5032
  };
5049
- const parsePluck = (parsers, isSubQuery, rows) => {
5050
- const pluck = parsers?.pluck;
5051
- if (pluck) for (let i = 0; i < rows.length; i++) rows[i] = pluck(isSubQuery ? rows[i] : rows[i][0]);
5033
+ const parsePluck = (query, parsers, isSubQuery, rows) => {
5034
+ const valueToArray = query.q.getColumn?.data?.valueToArray;
5035
+ const parse = parsers?.pluck;
5036
+ if (parse) if (valueToArray) for (let i = 0; i < rows.length; i++) {
5037
+ const value = isSubQuery ? rows[i] : rows[i][0];
5038
+ rows[i] = value === null ? void 0 : value[0] === null ? null : parse(value[0]);
5039
+ }
5040
+ else for (let i = 0; i < rows.length; i++) {
5041
+ const value = isSubQuery ? rows[i] : rows[i][0];
5042
+ rows[i] = value === null ? value : parse(value);
5043
+ }
5044
+ else if (valueToArray) for (let i = 0; i < rows.length; i++) {
5045
+ const value = isSubQuery ? rows[i] : rows[i][0];
5046
+ rows[i] = value === null ? void 0 : value[0];
5047
+ }
5052
5048
  else if (!isSubQuery) for (let i = 0; i < rows.length; i++) rows[i] = rows[i][0];
5053
5049
  };
5054
5050
  const parseValue = (value, parsers) => {
5055
- const parser = parsers?.[getValueKey];
5056
- return parser ? parser(value) : value;
5051
+ const parse = getValueParser(parsers);
5052
+ return parse ? parse(value) : value;
5057
5053
  };
5058
5054
  const filterResult = (q, returnType, queryResult, result, tempColumns, hasAfterHook) => {
5059
5055
  if (returnType === "all") return filterAllResult(result, tempColumns, hasAfterHook);
@@ -5086,7 +5082,7 @@ const filterResult = (q, returnType, queryResult, result, tempColumns, hasAfterH
5086
5082
  }
5087
5083
  };
5088
5084
  const getFirstResultKey = (q, queryResult) => {
5089
- if (q.q.select) return queryResult.fields[0].name;
5085
+ if (q.q.select) return queryResult.fields[0] ? queryResult.fields[0].name : "value";
5090
5086
  else for (const key in q.q.selectedComputeds) return key;
5091
5087
  };
5092
5088
  const filterAllResult = (result, tempColumns, hasAfterHook) => {
@@ -5345,7 +5341,7 @@ function queryFrom(self, arg) {
5345
5341
  if (typeof arg === "string") {
5346
5342
  data.as ||= arg;
5347
5343
  const w = data.withShapes?.[arg];
5348
- data.shape = w?.shape ?? anyShape;
5344
+ data.selectShape = w?.shape ?? anyShape;
5349
5345
  data.runtimeComputeds = w?.computeds;
5350
5346
  const parsers = {};
5351
5347
  data.defaultParsers = parsers;
@@ -5356,7 +5352,7 @@ function queryFrom(self, arg) {
5356
5352
  arg = arg.slice(i + 1);
5357
5353
  } else if (w) data.schema = void 0;
5358
5354
  } else if (Array.isArray(arg)) {
5359
- const shape = { ...data.shape };
5355
+ const shape = { ...data.selectShape };
5360
5356
  const joinedParsers = {};
5361
5357
  for (const item of arg) if (typeof item === "string") {
5362
5358
  const w = data.withShapes[item];
@@ -5378,7 +5374,7 @@ function queryFrom(self, arg) {
5378
5374
  } else {
5379
5375
  const q = prepareSubQueryForSql(self, arg);
5380
5376
  data.as ||= q.q.as || q.table || "t";
5381
- data.shape = getShapeFromSelect(q, true);
5377
+ data.selectShape = getShapeFromSelect(q, true);
5382
5378
  data.defaultParsers = getQueryParsers(q);
5383
5379
  data.batchParsers = q.q.batchParsers;
5384
5380
  }
@@ -5575,7 +5571,7 @@ const processJoinArgs = (joinTo, first, args, joinSubQuery, shape, whereExists,
5575
5571
  const j = joinTo.qb.baseQuery.clone();
5576
5572
  j.table = first;
5577
5573
  j.q = {
5578
- shape: w.shape,
5574
+ selectShape: w.shape,
5579
5575
  runtimeComputeds: w.computeds,
5580
5576
  adapter: joinToQ.adapter,
5581
5577
  handleResult: joinToQ.handleResult,
@@ -5657,7 +5653,7 @@ const makeJoinQueryBuilder = (joinedQuery, joinedShapes, joinTo, shape) => {
5657
5653
  q.q.joinedShapes = joinedShapes;
5658
5654
  q.q.joinTo = joinTo;
5659
5655
  if (q.q.scopes) q.q.scopes = void 0;
5660
- if (shape) q.q.shape = shape;
5656
+ if (shape) q.q.selectShape = shape;
5661
5657
  return q;
5662
5658
  };
5663
5659
  const isRelationQuery = (q) => "joinQuery" in q;
@@ -6484,7 +6480,7 @@ const _chain = (fromQuery, toQuery, rel) => {
6484
6480
  }];
6485
6481
  _applyRelationAliases(self, q);
6486
6482
  q.joinedShapes = {
6487
- [getQueryAs(self)]: self.q.shape,
6483
+ [getQueryAs(self)]: self.q.selectShape,
6488
6484
  ...self.q.joinedShapes
6489
6485
  };
6490
6486
  rel.modifyRelatedQuery?.(query)?.(self);
@@ -6521,14 +6517,14 @@ const resolveSubQueryCallback = (q, cb) => {
6521
6517
  _setSubQueryAliases(arg);
6522
6518
  return cb(arg);
6523
6519
  };
6524
- function simpleColumnToSQL(ctx, queryData, shape, key, column, quotedAs, select, as, jsonList, useSelectList, skipSelectSql) {
6520
+ function simpleColumnToSQL(ctx, queryData, shape, key, column, quotedAs, select, as, jsonList, useSelectList, skipSelectSql, skipValueToArray) {
6525
6521
  let sql;
6526
6522
  let dontAlias;
6527
6523
  if (useSelectList && queryData.select) {
6528
6524
  for (const s of queryData.select) if (typeof s === "object" && "selectAs" in s) {
6529
6525
  if (key in s.selectAs) {
6530
6526
  dontAlias = true;
6531
- sql = simpleColumnToSQL(ctx, queryData, shape, key, shape[key]);
6527
+ sql = simpleColumnToSQL(ctx, queryData, shape, key, shape[key], void 0, void 0, void 0, void 0, void 0, void 0, true);
6532
6528
  break;
6533
6529
  }
6534
6530
  }
@@ -6544,27 +6540,33 @@ function simpleColumnToSQL(ctx, queryData, shape, key, column, quotedAs, select,
6544
6540
  else {
6545
6541
  const name = data.name || key;
6546
6542
  dontAlias = name === as;
6543
+ if (!select) {
6544
+ const joinAs = !select && queryData.valuesJoinedAs?.[key];
6545
+ if (joinAs) quotedAs = `"${joinAs}"`;
6546
+ }
6547
6547
  sql = `${quotedAs ? `${quotedAs}.` : ""}"${name}"`;
6548
6548
  }
6549
6549
  }
6550
+ if (!select && !useSelectList && column?.data.valueToArray && !column.data.skipValueToArray) sql += "[1]";
6551
+ else if (queryData.getColumn?.data.valueToArray && !skipValueToArray) sql = `array[${sql}]`;
6550
6552
  if (as && !dontAlias) sql = `${sql} "${as}"`;
6551
6553
  return sql;
6552
6554
  }
6553
- const tableColumnToSql = (ctx, data, shape, table, key, quotedAs, select, as, jsonList) => {
6555
+ const tableColumnToSql = (ctx, queryData, shape, table, key, quotedAs, select, as, jsonList, skipValueToArray) => {
6554
6556
  let sql;
6555
6557
  let dontAlias;
6556
6558
  if (key === "*") {
6557
6559
  if (jsonList && as) jsonList[as] = void 0;
6558
- const shape = data.joinedShapes?.[table];
6560
+ const shape = queryData.joinedShapes?.[table];
6559
6561
  if (shape) sql = select ? makeRowToJson(ctx, table, shape, true) : `"${table}".*`;
6560
6562
  else {
6561
6563
  sql = `"${table}"."${key}"`;
6562
6564
  dontAlias = true;
6563
6565
  }
6564
6566
  } else {
6565
- const tableName = _getQueryAliasOrName(data, table);
6567
+ const tableName = _getQueryAliasOrName(queryData, table);
6566
6568
  const quoted = `"${table}"`;
6567
- const col = quoted === quotedAs ? shape[key] : data.joinedShapes?.[tableName]?.[key];
6569
+ const col = quoted === quotedAs ? shape[key] : queryData.joinedShapes?.[tableName]?.[key];
6568
6570
  if (jsonList && as) jsonList[as] = col && getSelectedColumnData(col);
6569
6571
  if (col?.data.selectSql) sql = `(${col.data.selectSql.toSQL(ctx, quoted)})`;
6570
6572
  else if (col?.data.name) sql = `"${tableName}"."${col.data.name}"`;
@@ -6573,24 +6575,20 @@ const tableColumnToSql = (ctx, data, shape, table, key, quotedAs, select, as, js
6573
6575
  sql = `"${tableName}"."${key}"`;
6574
6576
  dontAlias = key === as;
6575
6577
  }
6578
+ if (!select && col?.data.valueToArray && !col.data.skipValueToArray) sql += "[1]";
6579
+ else if (queryData.getColumn?.data.valueToArray && !skipValueToArray) sql = `array[${sql}]`;
6576
6580
  }
6577
6581
  if (as && !dontAlias) sql = `${sql} "${as}"`;
6578
6582
  return sql;
6579
6583
  };
6580
- const columnToSql = (ctx, data, shape, column, quotedAs, select, as, jsonList, useSelectList) => {
6584
+ const columnToSqlNotSelect = (ctx, data, shape, column, quotedAs, useSelectList) => columnToSql(ctx, data, shape, column, quotedAs, void 0, void 0, void 0, useSelectList, true);
6585
+ const columnToSql = (ctx, data, shape, column, quotedAs, select, as, jsonList, useSelectList, skipValueToArray) => {
6581
6586
  let index = column.indexOf(".");
6582
- if (index === -1 && !select) {
6583
- const joinAs = data.valuesJoinedAs?.[column];
6584
- if (joinAs) {
6585
- column = joinAs + "." + column;
6586
- index = joinAs.length;
6587
- }
6588
- }
6589
- if (index !== -1) return tableColumnToSql(ctx, data, shape, column.slice(0, index), column.slice(index + 1), quotedAs, select, as, jsonList);
6590
- return simpleColumnToSQL(ctx, data, shape, column, shape[column], quotedAs, select, as, jsonList, useSelectList);
6587
+ if (index !== -1) return tableColumnToSql(ctx, data, shape, column.slice(0, index), column.slice(index + 1), quotedAs, select, as, jsonList, skipValueToArray);
6588
+ return simpleColumnToSQL(ctx, data, shape, column, shape[column], quotedAs, select, as, jsonList, useSelectList, void 0, skipValueToArray);
6591
6589
  };
6592
- const rawOrColumnToSql = (ctx, data, shape, expr, quotedAs, select) => {
6593
- return typeof expr === "string" ? columnToSql(ctx, data, shape, expr, quotedAs, select) : expr.toSQL(ctx, quotedAs);
6590
+ const rawOrColumnToSql = (ctx, data, shape, expr, quotedAs, select, skipValueToArray) => {
6591
+ return typeof expr === "string" ? columnToSql(ctx, data, shape, expr, quotedAs, select, void 0, void 0, void 0, skipValueToArray) : expr.toSQL(ctx, quotedAs);
6594
6592
  };
6595
6593
  const processJoinItem = (ctx, table, query, args, quotedAs) => {
6596
6594
  let target;
@@ -6650,7 +6648,7 @@ const processJoinItem = (ctx, table, query, args, quotedAs) => {
6650
6648
  joinedShapes: {
6651
6649
  ...query.joinedShapes,
6652
6650
  ...q.q.joinedShapes,
6653
- [table.q.as || table.table]: table.q.shape
6651
+ [table.q.as || table.table]: table.q.selectShape
6654
6652
  }
6655
6653
  }, joinAs);
6656
6654
  if (whereSql) if (on) on += ` AND ${whereSql}`;
@@ -6699,17 +6697,17 @@ const getConditionsFor3Or4LengthItem = (ctx, query, target, quotedAs, args, join
6699
6697
  const [leftColumn, opOrRightColumn, maybeRightColumn] = args;
6700
6698
  const op = maybeRightColumn ? opOrRightColumn : "=";
6701
6699
  const rightColumn = maybeRightColumn ? maybeRightColumn : opOrRightColumn;
6702
- return `${rawOrColumnToSql(ctx, query, joinShape, leftColumn, target)} ${op} ${rawOrColumnToSql(ctx, query, query.shape, rightColumn, quotedAs)}`;
6700
+ return `${rawOrColumnToSql(ctx, query, joinShape, leftColumn, target)} ${op} ${rawOrColumnToSql(ctx, query, query.selectShape, rightColumn, quotedAs)}`;
6703
6701
  };
6704
6702
  const getObjectOrRawConditions = (ctx, query, data, quotedAs, joinAs, joinShape) => {
6705
6703
  if (data === true) return "true";
6706
6704
  else if (isExpression(data)) return data.toSQL(ctx, quotedAs);
6707
6705
  else {
6708
6706
  const pairs = [];
6709
- const shape = query.shape;
6707
+ const shape = query.selectShape;
6710
6708
  for (const key in data) {
6711
6709
  const value = data[key];
6712
- pairs.push(`${columnToSql(ctx, query, joinShape, key, joinAs)} = ${rawOrColumnToSql(ctx, query, shape, value, quotedAs)}`);
6710
+ pairs.push(`${columnToSqlNotSelect(ctx, query, joinShape, key, joinAs)} = ${rawOrColumnToSql(ctx, query, shape, value, quotedAs)}`);
6713
6711
  }
6714
6712
  return pairs.join(", ");
6715
6713
  }
@@ -6741,11 +6739,11 @@ var SelectItemExpression = class extends Expression {
6741
6739
  }
6742
6740
  makeSQL(ctx, quotedAs) {
6743
6741
  const q = this.q;
6744
- 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);
6742
+ 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);
6745
6743
  }
6746
6744
  };
6747
6745
  const _getSelectableColumn = (q, arg) => {
6748
- let type = q.q.shape[arg];
6746
+ let type = q.q.selectShape[arg];
6749
6747
  if (!type) {
6750
6748
  const index = arg.indexOf(".");
6751
6749
  if (index !== -1) {
@@ -6762,30 +6760,17 @@ const _get = (query, returnType, arg) => {
6762
6760
  const q = query.q;
6763
6761
  if (q.returning) q.returning = void 0;
6764
6762
  q.returnType = returnType;
6765
- let type;
6766
6763
  let value = arg;
6767
- if (typeof value === "function") {
6768
- const item = processSelectAsArg(query, getQueryAs(query), "value", value);
6769
- if (item !== false) value = item;
6770
- }
6771
- if (typeof value === "string") {
6772
- const joinedAs = q.valuesJoinedAs?.[value];
6773
- type = joinedAs ? q.joinedShapes?.[joinedAs]?.value : _getSelectableColumn(query, value);
6774
- q.getColumn = type;
6775
- const selected = setParserForSelectedString(query, joinedAs ? joinedAs + "." + value : value, getQueryAs(query), getValueKey);
6776
- q.select = selected ? [q.expr = new SelectItemExpression(query, selected, type)] : void 0;
6777
- } else if (isExpression(value)) {
6778
- type = value.result.value;
6779
- q.getColumn = type;
6780
- addParserForRawExpression(query, getValueKey, value);
6781
- q.select = [q.expr = value];
6782
- } else {
6783
- const selected = value;
6784
- q.getColumn = selected.q.getColumn;
6785
- if (q.getColumn) addColumnParserToQuery(q, getValueKey, q.getColumn);
6786
- q.select = selected ? [{ selectAs: { value: selected } }] : void 0;
6764
+ const selectAs = {};
6765
+ let column;
6766
+ const selected = processSelectAsArg(query, selectAs, getQueryAs(query), "v", value, void 0, returnType);
6767
+ if (selected !== false) {
6768
+ q.getColumn = column = selected;
6769
+ value = selectAs.v || value;
6787
6770
  }
6788
- return setQueryOperators(query, type?.operators || Operators.any);
6771
+ if (typeof value === "string") value = selectAs.v && new SelectItemExpression(query, selectAs.v, column);
6772
+ q.select = isExpression(value) ? [q.expr = value] : value ? [{ selectAs: { v: value } }] : void 0;
6773
+ return setQueryOperators(query, column?.operators || Operators.any);
6789
6774
  };
6790
6775
  function _queryGet(self, arg) {
6791
6776
  return _get(self, "valueOrThrow", arg);
@@ -7034,13 +7019,13 @@ const selectToSqlList = (ctx, table, query, quotedAs, hookSelect = query.hookSel
7034
7019
  (selected ??= {})[key] = `"${tableName}"`;
7035
7020
  (selectedAs ??= {})[key] = key;
7036
7021
  }
7037
- sql = tableColumnToSql(ctx, table.q, table.q.shape, tableName, key, quotedAs, true, key === "*" ? tableName : key, jsonList);
7022
+ sql = tableColumnToSql(ctx, query, query.selectShape, tableName, key, quotedAs, true, key === "*" ? tableName : key, jsonList);
7038
7023
  } else {
7039
7024
  if (hookSelect?.get(item)) {
7040
7025
  (selected ??= {})[item] = quotedAs;
7041
7026
  (selectedAs ??= {})[item] = item;
7042
7027
  }
7043
- sql = simpleColumnToSQL(ctx, table.q, table.q.shape, item, table.q.shape[item], quotedAs, true, item, jsonList);
7028
+ sql = simpleColumnToSQL(ctx, query, query.selectShape, item, query.selectShape[item], quotedAs, true, item, jsonList);
7044
7029
  }
7045
7030
  }
7046
7031
  list.push(sql);
@@ -7052,7 +7037,9 @@ const selectToSqlList = (ctx, table, query, quotedAs, hookSelect = query.hookSel
7052
7037
  if (hookSelect) (selected ??= {})[as] = true;
7053
7038
  const value = obj[as];
7054
7039
  if (typeof value === "object") if (isExpression(value)) {
7055
- list.push(`${value.toSQL(ctx, quotedAs)} "${as}"`);
7040
+ let sql = value.toSQL(ctx, quotedAs);
7041
+ if (value.q.getColumn?.data.valueToArray) sql = `array[${sql}]`;
7042
+ list.push(`${sql} "${as}"`);
7056
7043
  if (jsonList) jsonList[as] = value.result.value;
7057
7044
  aliases?.push(as);
7058
7045
  } else if (delayedRelationSelect && isRelationQuery(value)) setMutativeQueriesSelectRelationsSqlState(delayedRelationSelect, as, value);
@@ -7062,13 +7049,14 @@ const selectToSqlList = (ctx, table, query, quotedAs, hookSelect = query.hookSel
7062
7049
  }
7063
7050
  else if (value) {
7064
7051
  if (hookSelect) (selectedAs ??= {})[value] = as;
7065
- list.push(columnToSql(ctx, table.q, table.q.shape, value, quotedAs, true, as, jsonList));
7052
+ list.push(columnToSql(ctx, table.q, table.q.selectShape, value, quotedAs, true, as, jsonList));
7066
7053
  aliases?.push(as);
7067
7054
  }
7068
7055
  }
7069
7056
  } else {
7070
7057
  ctx.selectedCount++;
7071
- const sql = item.toSQL(ctx, quotedAs);
7058
+ let sql = item.toSQL(ctx, quotedAs);
7059
+ if (item.q.getColumn?.data.valueToArray) sql = `array[${sql}]`;
7072
7060
  if (hookSelect && item instanceof SelectItemExpression && typeof item.item === "string" && item.item !== "*") {
7073
7061
  const i = item.item.indexOf(".");
7074
7062
  let key;
@@ -7076,7 +7064,7 @@ const selectToSqlList = (ctx, table, query, quotedAs, hookSelect = query.hookSel
7076
7064
  if (item.item.slice(0, i) === table.table) key = item.item.slice(i + 1);
7077
7065
  } else key = item.item;
7078
7066
  if (key) {
7079
- const column = item.q.shape[key];
7067
+ const column = item.q.selectShape[key];
7080
7068
  (selectedAs ??= {})[key] = column?.data.name || key;
7081
7069
  }
7082
7070
  }
@@ -7098,12 +7086,12 @@ const selectToSqlList = (ctx, table, query, quotedAs, hookSelect = query.hookSel
7098
7086
  quotedTable = `"${tableName}"`;
7099
7087
  columnName = select.slice(index + 1);
7100
7088
  col = table.q.joinedShapes?.[tableName]?.[columnName];
7101
- sql = columnToSql(ctx, table.q, table.q.shape, select, void 0, true);
7089
+ sql = columnToSql(ctx, table.q, table.shape, select, void 0, true, void 0, void 0, void 0, true);
7102
7090
  } else {
7103
7091
  quotedTable = quotedAs;
7104
7092
  columnName = select;
7105
- col = query.shape[select];
7106
- sql = columnToSql(ctx, table.q, query.shape, select, quotedAs, true);
7093
+ col = table.shape[select];
7094
+ sql = columnToSql(ctx, table.q, table.shape, select, quotedAs, true, void 0, void 0, void 0, true);
7107
7095
  }
7108
7096
  } else {
7109
7097
  columnName = column;
@@ -7148,15 +7136,15 @@ const internalSelectAllSql = (ctx, query, quotedAs, jsonList) => {
7148
7136
  jsonList[key] = getSelectedColumnData(column);
7149
7137
  }
7150
7138
  let columnsCount;
7151
- if (query.shape !== anyShape) {
7139
+ if (query.selectShape !== anyShape) {
7152
7140
  columnsCount = 0;
7153
- for (const key in query.shape) if (!query.shape[key].data.explicitSelect) columnsCount++;
7141
+ for (const key in query.selectShape) if (!query.selectShape[key].data.explicitSelect) columnsCount++;
7154
7142
  ctx.selectedCount += columnsCount;
7155
7143
  }
7156
7144
  return selectAllSql(query, quotedAs, columnsCount, ctx);
7157
7145
  };
7158
7146
  const selectAllSql = (q, quotedAs, columnsCount, ctx) => {
7159
- 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) ? [] : ["*"];
7147
+ 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) ? [] : ["*"];
7160
7148
  };
7161
7149
  const selectAllColumnToSql = (item, ctx, quotedAs, prefix) => {
7162
7150
  if (typeof item !== "string") return item(ctx, quotedAs);
@@ -7332,9 +7320,9 @@ const processWhere = (ands, ctx, table, query, data, quotedAs) => {
7332
7320
  ands.push(`NOT ${processAnds(arr, ctx, table, query, quotedAs, true)}`);
7333
7321
  } else if (key === "ON") if (Array.isArray(value)) {
7334
7322
  const item = value;
7335
- const leftColumn = columnToSql(ctx, query, query.shape, item[0], quotedAs);
7323
+ const leftColumn = columnToSqlNotSelect(ctx, query, query.selectShape, item[0], quotedAs);
7336
7324
  const leftPath = item[1];
7337
- const rightColumn = columnToSql(ctx, query, query.shape, item[2], quotedAs);
7325
+ const rightColumn = columnToSqlNotSelect(ctx, query, query.selectShape, item[2], quotedAs);
7338
7326
  const rightPath = item[3];
7339
7327
  ands.push(`jsonb_path_query_first(${leftColumn}, ${addValue(ctx.values, leftPath)}) = jsonb_path_query_first(${rightColumn}, ${addValue(ctx.values, rightPath)})`);
7340
7328
  } else {
@@ -7343,7 +7331,7 @@ const processWhere = (ands, ctx, table, query, data, quotedAs) => {
7343
7331
  const q = item.useOuterAliases ? {
7344
7332
  joinedShapes: query.joinedShapes,
7345
7333
  aliases: _getQueryOuterAliases(query),
7346
- shape: query.shape
7334
+ selectShape: query.selectShape
7347
7335
  } : query;
7348
7336
  ands.push(`${onColumnToSql(ctx, q, joinAs, item.from)} ${item.op || "="} ${onColumnToSql(ctx, q, joinAs, item.to)}`);
7349
7337
  }
@@ -7367,31 +7355,26 @@ const processWhere = (ands, ctx, table, query, data, quotedAs) => {
7367
7355
  ands.push(`${search.vectorSQL} @@ "${search.as}"`);
7368
7356
  } else if (typeof value === "object" && value && !(value instanceof Date) && !Array.isArray(value)) whereExprOrQuery(ctx, ands, query, key, value, quotedAs);
7369
7357
  else {
7370
- const column = columnToSql(ctx, query, query.shape, key, quotedAs);
7358
+ const column = columnToSqlNotSelect(ctx, query, query.selectShape, key, quotedAs);
7371
7359
  ands.push(`${column} ${value === null ? "IS NULL" : `= ${addValue(ctx.values, value)}`}`);
7372
7360
  }
7373
7361
  }
7374
7362
  };
7375
7363
  const whereExprOrQuery = (ctx, ands, query, key, value, quotedAs) => {
7376
- if (isExpression(value)) ands.push(`${columnToSql(ctx, query, query.shape, key, quotedAs)} = ${value.toSQL(ctx, quotedAs)}`);
7364
+ if (isExpression(value)) ands.push(`${columnToSqlNotSelect(ctx, query, query.selectShape, key, quotedAs)} = ${value.toSQL(ctx, quotedAs)}`);
7377
7365
  else {
7378
- let column = query.shape[key];
7379
- let quotedColumn;
7380
- if (column) quotedColumn = simpleColumnToSQL(ctx, query, query.shape, key, column, quotedAs);
7381
- else if (!column) {
7366
+ let column = query.selectShape[key];
7367
+ if (!column) {
7382
7368
  const index = key.indexOf(".");
7383
- if (index !== -1) {
7369
+ if (index === -1) column = query.joinedShapes?.[key]?.value;
7370
+ else if (index !== -1) {
7384
7371
  const table = key.slice(0, index);
7385
- const quoted = `"${table}"`;
7386
7372
  const name = key.slice(index + 1);
7387
- column = quotedAs === quoted ? query.shape[name] : query.joinedShapes?.[table]?.[name];
7388
- quotedColumn = simpleColumnToSQL(ctx, query, query.shape, name, column, quoted);
7389
- } else {
7390
- column = query.joinedShapes?.[key]?.value;
7391
- quotedColumn = `"${key}"."${key}"`;
7373
+ column = quotedAs === `"${table}"` ? query.selectShape[name] : query.joinedShapes?.[table]?.[name];
7392
7374
  }
7393
- if (!column || !quotedColumn) throw new Error(`Unknown column ${key} provided to condition`);
7394
7375
  }
7376
+ if (!column) throw new Error(`Unknown column ${key} provided to condition`);
7377
+ const quotedColumn = columnToSqlNotSelect(ctx, query, query.selectShape, key, quotedAs);
7395
7378
  if (value instanceof ctx.qb.constructor) {
7396
7379
  const subQuerySql = moveMutativeQueryToCte(ctx, value);
7397
7380
  ands.push(`${quotedColumn} = (${subQuerySql})`);
@@ -7403,7 +7386,7 @@ const whereExprOrQuery = (ctx, ands, query, key, value, quotedAs) => {
7403
7386
  }
7404
7387
  }
7405
7388
  };
7406
- const onColumnToSql = (ctx, query, joinAs, column) => columnToSql(ctx, query, query.shape, column, joinAs);
7389
+ const onColumnToSql = (ctx, query, joinAs, column) => columnToSqlNotSelect(ctx, query, query.selectShape, column, joinAs);
7407
7390
  const getJoinItemSource = (joinItem) => {
7408
7391
  return typeof joinItem === "string" ? joinItem : getQueryAs(joinItem);
7409
7392
  };
@@ -7415,13 +7398,14 @@ const pushIn = (ctx, query, ands, quotedAs, arg) => {
7415
7398
  value = `(${value})`;
7416
7399
  } else if (isExpression(arg.values)) value = arg.values.toSQL(ctx, quotedAs);
7417
7400
  else value = `(${moveMutativeQueryToCte(ctx, arg.values)})`;
7418
- const columnsSql = arg.columns.map((column) => columnToSql(ctx, query, query.shape, column, quotedAs)).join(", ");
7401
+ const columnsSql = arg.columns.map((column) => columnToSqlNotSelect(ctx, query, query.selectShape, column, quotedAs)).join(", ");
7419
7402
  ands.push(`${multiple ? `(${columnsSql})` : columnsSql} IN ${value}`);
7420
7403
  };
7421
7404
  const MAX_BINDING_PARAMS = 65533;
7422
7405
  const makeInsertSql = (ctx, q, query, quotedAs, isSubSql) => {
7423
7406
  let { columns } = query;
7424
- const { shape, hookCreateSet } = query;
7407
+ const shape = q.shape;
7408
+ const { hookCreateSet } = query;
7425
7409
  const QueryClass = ctx.qb.constructor;
7426
7410
  let { insertFrom, queryColumnsCount, values } = query;
7427
7411
  let hookSetSql;
@@ -7458,7 +7442,7 @@ const makeInsertSql = (ctx, q, query, quotedAs, isSubSql) => {
7458
7442
  insertSql: `INSERT INTO ${quoteTableWithSchema(q)}${quotedColumns.length ? "(" + quotedColumns.join(", ") + ")" : ""}`
7459
7443
  };
7460
7444
  ctx.sql.push(null, null);
7461
- const hasOnConflictWhere = pushOnConflictSql(ctx, query, quotedAs, columns, quotedColumns, runtimeDefaultColumns);
7445
+ const hasOnConflictWhere = pushOnConflictSql(ctx, q, query, quotedAs, columns, quotedColumns, runtimeDefaultColumns);
7462
7446
  const upsert = query.type === "upsert";
7463
7447
  if (upsert || insertFrom && !isRelationQuery(q) || hasOnConflictWhere) pushWhereStatementSql(ctx, q, query, quotedAs);
7464
7448
  sqlState.relationSelectState = newMutativeQueriesSelectRelationsSqlState(q);
@@ -7525,9 +7509,9 @@ const makeInsertSql = (ctx, q, query, quotedAs, isSubSql) => {
7525
7509
  values: ctx.values
7526
7510
  };
7527
7511
  };
7528
- const pushOnConflictSql = (ctx, query, quotedAs, columns, quotedColumns, runtimeDefaultColumns) => {
7512
+ const pushOnConflictSql = (ctx, q, query, quotedAs, columns, quotedColumns, runtimeDefaultColumns) => {
7529
7513
  if (!query.onConflict) return false;
7530
- const { shape } = query;
7514
+ const shape = q.shape;
7531
7515
  ctx.sql.push("ON CONFLICT");
7532
7516
  const { target } = query.onConflict;
7533
7517
  if (target) if (typeof target === "string") ctx.sql.push(`("${shape[target]?.data.name || target}")`);
@@ -7740,7 +7724,7 @@ const pushUpdateSqlWithoutValuesJoinedAs = (ctx, query, q, quotedAs, isSubSql) =
7740
7724
  let updateManyValuesSql;
7741
7725
  if (q.updateMany) {
7742
7726
  for (const key of q.updateMany.primaryKeys) usedSetKeys.add(key);
7743
- updateManyValuesSql = makeUpdateManyValuesSql(ctx, query, q, q.updateMany, set, usedSetKeys, quotedAs);
7727
+ updateManyValuesSql = makeUpdateManyValuesSql(ctx, query, q.updateMany, set, usedSetKeys, quotedAs);
7744
7728
  }
7745
7729
  if (!set.length) pushSelectForEmptySet(ctx, query, q, quotedAs, from, isSubSql, updateManyValuesSql, relationSelectState);
7746
7730
  else {
@@ -7815,7 +7799,7 @@ const processData = (ctx, query, set, data, hookSet, usedSetKeys, quotedAs) => {
7815
7799
  };
7816
7800
  const applySet = (ctx, query, set, item, skipColumns, usedSetKeys, quotedAs) => {
7817
7801
  const QueryClass = ctx.qb.constructor;
7818
- const shape = query.q.shape;
7802
+ const shape = query.shape;
7819
7803
  for (const key in item) {
7820
7804
  if (usedSetKeys.has(key)) continue;
7821
7805
  usedSetKeys.add(key);
@@ -7831,12 +7815,12 @@ const processValue = (ctx, query, QueryClass, key, value, quotedAs) => {
7831
7815
  const subQuery = value;
7832
7816
  if (subQuery.q.subQuery === 1) return selectToSql(ctx, query, subQuery.q, quotedAs);
7833
7817
  return `(${moveMutativeQueryToCte(ctx, subQuery)})`;
7834
- } else if ("op" in value && "arg" in value) return `"${query.q.shape[key].data.name || key}" ${value.op} ${addValue(ctx.values, value.arg)}`;
7818
+ } else if ("op" in value && "arg" in value) return `"${query.shape[key].data.name || key}" ${value.op} ${addValue(ctx.values, value.arg)}`;
7835
7819
  }
7836
7820
  return addValue(ctx.values, value);
7837
7821
  };
7838
- const makeUpdateManyValuesSql = (ctx, query, q, updateMany, set, usedSetKeys, quotedAs) => {
7839
- const { shape } = q;
7822
+ const makeUpdateManyValuesSql = (ctx, query, updateMany, set, usedSetKeys, quotedAs) => {
7823
+ const shape = query.shape;
7840
7824
  const keysSet = /* @__PURE__ */ new Set();
7841
7825
  const valueRows = [];
7842
7826
  const quotedColumnNames = [];
@@ -7945,13 +7929,13 @@ const addOrder = (ctx, data, column, quotedAs, dir) => {
7945
7929
  const order = dir || (!search.order || search.order === true ? emptyObject : search.order);
7946
7930
  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"}`;
7947
7931
  }
7948
- return `${columnToSql(ctx, data, data.shape, column, quotedAs, void 0, void 0, void 0, true)} ${dir || "ASC"}`;
7932
+ return `${columnToSqlNotSelect(ctx, data, data.selectShape, column, quotedAs, true)} ${dir || "ASC"}`;
7949
7933
  };
7950
7934
  const windowToSql = (ctx, data, window, quotedAs) => {
7951
7935
  if (typeof window === "string") return `"${window}"`;
7952
7936
  if (isExpression(window)) return `(${window.toSQL(ctx, quotedAs)})`;
7953
7937
  const sql = [];
7954
- 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)}`);
7938
+ 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)}`);
7955
7939
  if (window.order) sql.push(`ORDER BY ${orderByToSql(ctx, data, window.order, quotedAs)}`);
7956
7940
  return `(${sql.join(" ")})`;
7957
7941
  };
@@ -7972,12 +7956,6 @@ var FnExpression = class extends Expression {
7972
7956
  this.result = { value };
7973
7957
  this.q = query.q;
7974
7958
  this.q.expr = this;
7975
- Object.assign(query, value.operators);
7976
- query.q.returnType = "valueOrThrow";
7977
- query.q.returnsOne = true;
7978
- query.q.getColumn = value;
7979
- query.q.select = [this];
7980
- addColumnParserToQuery(query.q, getValueKey, value);
7981
7959
  }
7982
7960
  makeSQL(ctx, quotedAs) {
7983
7961
  const sql = [`${this.fn}(`];
@@ -8006,7 +7984,7 @@ var FnExpression = class extends Expression {
8006
7984
  const whereSql = whereToSql(ctx, this.query, {
8007
7985
  and: options.filter ? [options.filter] : void 0,
8008
7986
  or: options.filterOr?.map((item) => [item]),
8009
- shape: q.shape,
7987
+ selectShape: q.selectShape,
8010
7988
  joinedShapes: q.joinedShapes
8011
7989
  }, quotedAs);
8012
7990
  if (whereSql) sql.push(` FILTER (WHERE ${whereSql})`);
@@ -8017,16 +7995,22 @@ var FnExpression = class extends Expression {
8017
7995
  };
8018
7996
  const fnArgToSql = (ctx, data, arg, quotedAs) => {
8019
7997
  if (typeof arg === "string") {
8020
- if (arg.endsWith(".*") || data.valuesJoinedAs?.[arg]) return columnToSql(ctx, data, data.shape, arg, quotedAs);
8021
- return columnToSql(ctx, data, data.shape, arg, quotedAs, true);
7998
+ if (arg.endsWith(".*") || data.valuesJoinedAs?.[arg]) return columnToSql(ctx, data, data.selectShape, arg, quotedAs, void 0, void 0, void 0, void 0, true);
7999
+ return columnToSql(ctx, data, data.selectShape, arg, quotedAs, true, void 0, void 0, void 0, true);
8022
8000
  }
8023
8001
  return arg.toSQL(ctx, quotedAs);
8024
8002
  };
8025
8003
  function makeFnExpression(self, type, fn, args, options) {
8026
8004
  const q = extendQuery(self, type.operators);
8027
8005
  q.baseQuery.type = ExpressionTypeMethod.prototype.type;
8028
- new FnExpression(q, fn, args, options, type);
8006
+ q.q.select = [new FnExpression(q, fn, args, options, type)];
8007
+ q.q.getColumn = type;
8008
+ Object.assign(q, type.operators);
8009
+ setValueParserToQuery(q.q, type);
8010
+ q.q.returnType = "valueOrThrow";
8011
+ q.q.returnsOne = true;
8029
8012
  q.q.transform = void 0;
8013
+ q.q.batchParsers = void 0;
8030
8014
  return q;
8031
8015
  }
8032
8016
  const isSelectingCount = (q) => {
@@ -8035,34 +8019,16 @@ const isSelectingCount = (q) => {
8035
8019
  };
8036
8020
  const intNullable = new IntegerColumn(internalSchemaConfig).nullable().parse(parseInt);
8037
8021
  const floatNullable = new RealColumn(internalSchemaConfig).nullable().parse(parseFloat);
8038
- const booleanNullable = BooleanColumn.instance.nullable();
8022
+ const booleanNullable = BooleanColumn.instanceSkipValueToArray.nullable();
8039
8023
  const textNullable = TextColumn.instance.nullable();
8040
8024
  const jsonTextNullable = JSONTextColumn.instance.nullable();
8041
8025
  const xmlNullable = XMLColumn.instance.nullable();
8042
8026
  const stringAsNumberNullable = new NumberAsStringBaseColumn(internalSchemaConfig).nullable();
8027
+ intNullable.data.skipValueToArray = floatNullable.data.skipValueToArray = textNullable.data.skipValueToArray = jsonTextNullable.data.skipValueToArray = xmlNullable.data.skipValueToArray = stringAsNumberNullable.data.skipValueToArray = true;
8043
8028
  const numericResultColumn = (q, arg) => {
8044
- const query = q;
8045
- let column = (typeof arg === "string" ? _getSelectableColumn(query, arg) : arg.result.value) instanceof NumberBaseColumn ? floatNullable : stringAsNumberNullable;
8046
- const parse = typeof arg === "string" && query.q.parsers?.[arg];
8047
- if (parse) column = column.parse(parse);
8048
- return column;
8029
+ return (typeof arg === "string" ? _getSelectableColumn(q, arg) : arg.result.value) instanceof NumberBaseColumn ? floatNullable : stringAsNumberNullable;
8049
8030
  };
8050
8031
  var AggregateMethods = class {
8051
- /**
8052
- * Use `exists()` to check if there is at least one record-matching condition.
8053
- *
8054
- * It will discard previous `select` statements if any. Returns a boolean.
8055
- *
8056
- * ```ts
8057
- * const exists: boolean = await db.table.where(...conditions).exists();
8058
- * ```
8059
- */
8060
- exists() {
8061
- const q = _queryGetOptional(_clone(this), new RawSql("true"));
8062
- q.q.notFoundDefault = false;
8063
- q.q.coalesceValue = new RawSql("false");
8064
- return q;
8065
- }
8066
8032
  /**
8067
8033
  * Count records with the `count` function:
8068
8034
  *
@@ -8822,7 +8788,7 @@ const createSelect = (q) => {
8822
8788
  * @param createHandlers - collects column `create` functions per column having it, and collects row indexes having a value for this column
8823
8789
  */
8824
8790
  const processCreateItem = (q, item, rowIndex, ctx, encoders, createHandlers) => {
8825
- const { shape } = q.q;
8791
+ const shape = q.shape;
8826
8792
  for (const key in item) {
8827
8793
  const column = shape[key];
8828
8794
  if (!column) continue;
@@ -9373,7 +9339,7 @@ var OnConflictQueryBuilder = class {
9373
9339
  const pushDistinctSql = (ctx, table, distinct, quotedAs) => {
9374
9340
  ctx.sql.push("DISTINCT");
9375
9341
  if (distinct.length) {
9376
- const columns = distinct?.map((item) => rawOrColumnToSql(ctx, table.q, table.q.shape, item, quotedAs));
9342
+ const columns = distinct?.map((item) => rawOrColumnToSql(ctx, table.q, table.q.selectShape, item, quotedAs));
9377
9343
  ctx.sql.push(`ON (${columns?.join(", ") || ""})`);
9378
9344
  }
9379
9345
  };
@@ -9407,20 +9373,20 @@ const searchSourcesToSql = (ctx, data, sources, sql, quotedAs) => {
9407
9373
  return sql;
9408
9374
  };
9409
9375
  const getSearchLang = (ctx, data, source, quotedAs) => {
9410
- 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");
9376
+ 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");
9411
9377
  };
9412
9378
  const getSearchText = (ctx, data, source, quotedAs, forHeadline) => {
9413
9379
  let sql = source.textSQL;
9414
9380
  if (sql) return sql;
9415
- if ("in" in source) if (typeof source.in === "string") sql = columnToSql(ctx, data, data.shape, source.in, quotedAs);
9416
- else if (Array.isArray(source.in)) sql = `concat_ws(' ', ${source.in.map((column) => columnToSql(ctx, data, data.shape, column, quotedAs)).join(", ")})`;
9381
+ if ("in" in source) if (typeof source.in === "string") sql = columnToSqlNotSelect(ctx, data, data.selectShape, source.in, quotedAs);
9382
+ else if (Array.isArray(source.in)) sql = `concat_ws(' ', ${source.in.map((column) => columnToSqlNotSelect(ctx, data, data.selectShape, column, quotedAs)).join(", ")})`;
9417
9383
  else {
9418
9384
  sql = [];
9419
- for (const key in source.in) sql.push(columnToSql(ctx, data, data.shape, key, quotedAs));
9385
+ for (const key in source.in) sql.push(columnToSqlNotSelect(ctx, data, data.selectShape, key, quotedAs));
9420
9386
  }
9421
9387
  else if ("vector" in source) {
9422
9388
  if (forHeadline) throw new Error("Cannot use a search based on a vector column for a search headline");
9423
- sql = columnToSql(ctx, data, data.shape, source.vector, quotedAs);
9389
+ sql = columnToSqlNotSelect(ctx, data, data.selectShape, source.vector, quotedAs);
9424
9390
  } else if (typeof source.text === "string") sql = addValue(ctx.values, source.text);
9425
9391
  else sql = source.text.toSQL(ctx, quotedAs);
9426
9392
  return source.textSQL = sql;
@@ -9636,7 +9602,7 @@ const toSql = (table, type, topCtx, isSubSql, cteName, calledByThen, dontAddTabl
9636
9602
  if (isExpression(item)) return item.toSQL(ctx, quotedAs);
9637
9603
  else {
9638
9604
  const i = aliases.indexOf(item);
9639
- return i !== -1 ? i + 1 : columnToSql(ctx, table.q, table.shape, item, quotedAs);
9605
+ return i !== -1 ? i + 1 : columnToSqlNotSelect(ctx, table.q, table.shape, item, quotedAs);
9640
9606
  }
9641
9607
  });
9642
9608
  sql.push(`GROUP BY ${group.join(", ")}`);
@@ -10058,19 +10024,11 @@ const _joinLateral = (self, type, joinQuery, as, innerJoinLateral) => {
10058
10024
  }
10059
10025
  if (!existingValue) {
10060
10026
  const joinedAs = getQueryAs(query);
10061
- setObjectValueImmutable(joinQuery.q, "joinedShapes", joinedAs, query.q.shape);
10027
+ setObjectValueImmutable(joinQuery.q, "joinedShapes", joinedAs, query.q.selectShape);
10062
10028
  }
10063
10029
  const shape = getShapeFromSelect(joinQuery, true);
10064
10030
  setObjectValueImmutable(query.q, "joinedShapes", joinAs, shape);
10065
- const parsers = getQueryParsers(joinQuery);
10066
- if (joinValue) {
10067
- setObjectValueImmutable(query.q, "valuesJoinedAs", joinAs, joinValueAs);
10068
- if (parsers && getValueKey in parsers) {
10069
- const parse = parsers[getValueKey];
10070
- setParserToQuery(query.q, joinAs, parse);
10071
- parsers[joinAs] = parse;
10072
- }
10073
- }
10031
+ if (joinValue) setObjectValueImmutable(query.q, "valuesJoinedAs", joinAs, joinValueAs);
10074
10032
  setObjectValueImmutable(query.q, "joinedParsers", joinValueAs || joinAs, getQueryParsers(joinQuery));
10075
10033
  if (joinQuery.q.batchParsers) setObjectValueImmutable(query.q, "joinedBatchParsers", joinAs, joinQuery.q.batchParsers);
10076
10034
  if (joinValueAs) {
@@ -10830,15 +10788,12 @@ var OnMethods = class {
10830
10788
  const setSelectRelation = (q) => {
10831
10789
  q.selectRelation = true;
10832
10790
  };
10833
- const addParserForRawExpression = (q, key, raw) => {
10834
- if (raw.result.value) addColumnParserToQuery(q.q, key, raw.result.value);
10835
- };
10836
10791
  const addParsersForSelectJoined = (q, arg, as = arg) => {
10837
10792
  const parsers = q.q.joinedParsers?.[arg];
10838
10793
  if (parsers) setParserToQuery(q.q, as, (row) => parseRecord(parsers, row));
10839
10794
  const batchParsers = q.q.joinedBatchParsers?.[arg];
10840
10795
  if (batchParsers) pushQueryArrayImmutable(q, "batchParsers", batchParsers.map((x) => ({
10841
- path: [as, ...x.path],
10796
+ path: [{ key: as }, ...x.path],
10842
10797
  fn: x.fn
10843
10798
  })));
10844
10799
  };
@@ -10846,19 +10801,24 @@ const addParserForSelectItem = (query, as, key, arg, columnAlias, joinQuery) =>
10846
10801
  if (typeof arg === "object") {
10847
10802
  const { q } = arg;
10848
10803
  if (q.batchParsers) pushQueryArrayImmutable(query, "batchParsers", q.batchParsers.map((bp) => ({
10849
- path: [key, ...bp.path],
10804
+ path: [{
10805
+ key,
10806
+ returnType: q.returnType
10807
+ }, ...bp.path],
10850
10808
  fn: bp.fn
10851
10809
  })));
10852
10810
  const parsers = isExpression(arg) ? void 0 : getQueryParsers(arg);
10853
10811
  if (parsers || q.hookSelect || q.transform || q.returnType === "oneOrThrow" || q.returnType === "valueOrThrow" || q.returnType === "one" || q.returnType === "value") pushQueryValueImmutable(query, "batchParsers", {
10854
- path: [key],
10812
+ path: [{
10813
+ key,
10814
+ returnType: q.returnType
10815
+ }],
10855
10816
  fn: (path, queryResult) => {
10856
10817
  const { rows } = queryResult;
10857
10818
  const originalReturnType = q.returnType || "all";
10858
10819
  let returnType = originalReturnType;
10859
10820
  const { hookSelect } = q;
10860
10821
  const batches = [];
10861
- const last = path.length;
10862
10822
  if (returnType === "value" || returnType === "valueOrThrow") {
10863
10823
  if (hookSelect) batches.push = (item) => {
10864
10824
  if (!(key in item)) returnType = returnType === "value" ? "one" : "oneOrThrow";
@@ -10866,7 +10826,7 @@ const addParserForSelectItem = (query, as, key, arg, columnAlias, joinQuery) =>
10866
10826
  return batches.push(item);
10867
10827
  };
10868
10828
  }
10869
- collectNestedSelectBatches(batches, rows, path, last);
10829
+ collectNestedSelectBatches(batches, rows, path);
10870
10830
  switch (returnType) {
10871
10831
  case "all":
10872
10832
  if (parsers) for (const { data } of batches) for (const one of data) parseRecord(parsers, one);
@@ -10891,16 +10851,28 @@ const addParserForSelectItem = (query, as, key, arg, columnAlias, joinQuery) =>
10891
10851
  }
10892
10852
  case "value":
10893
10853
  case "valueOrThrow": {
10894
- const notNullable = !q.getColumn?.data.isNullable;
10895
- const parse = parsers?.[getValueKey];
10896
- if (parse) if (returnType === "value") for (const item of batches) item.parent[item.key] = item.data = item.data === null ? q.notFoundDefault : parse(item.data);
10854
+ const data = q.getColumn?.data;
10855
+ const notNullable = !data?.isNullable;
10856
+ const valueToArray = data?.valueToArray;
10857
+ const parse = getValueParser(parsers);
10858
+ 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;
10859
+ else for (const item of batches) item.parent[item.key] = item.data = item.data === null ? q.notFoundDefault : parse(item.data);
10860
+ else if (valueToArray) for (const item of batches) {
10861
+ if (!item.data) throw new NotFoundError(arg);
10862
+ item.parent[item.key] = item.data = item.data[0] === null ? null : parse(item.data[0]);
10863
+ }
10897
10864
  else for (const item of batches) {
10898
10865
  if (notNullable && item.data === null) throw new NotFoundError(arg);
10899
10866
  item.parent[item.key] = item.data = parse(item.data);
10900
10867
  }
10901
10868
  else if (returnType === "value") {
10902
- for (const item of batches) if (item.data === null) item.parent[item.key] = item.data = q.notFoundDefault;
10903
- } else if (notNullable) {
10869
+ if (valueToArray) for (const item of batches) item.parent[item.key] = item.data = item.data ? item.data[0] : q.notFoundDefault;
10870
+ else for (const item of batches) if (item.data === void 0) item.parent[item.key] = item.data = q.notFoundDefault;
10871
+ } else if (valueToArray) for (const item of batches) {
10872
+ if (!item.data) throw new NotFoundError(arg);
10873
+ item.parent[item.key] = item.data = item.data[0];
10874
+ }
10875
+ else if (notNullable) {
10904
10876
  for (const { data } of batches) if (data === null) throw new NotFoundError(arg);
10905
10877
  }
10906
10878
  if (hookSelect) for (const batch of batches) batch.data = [batch.data];
@@ -10938,59 +10910,52 @@ const addParserForSelectItem = (query, as, key, arg, columnAlias, joinQuery) =>
10938
10910
  }
10939
10911
  return arg;
10940
10912
  }
10941
- return setParserForSelectedString(query, arg, as, key, columnAlias);
10913
+ const joinedAs = query.q.valuesJoinedAs?.[arg];
10914
+ return setParserForSelectedString(query, joinedAs ? joinedAs + "." + arg : arg, as, key, columnAlias);
10942
10915
  };
10943
- const collectNestedSelectBatches = (batches, rows, path, last) => {
10944
- const stack = rows.map((row) => ({
10945
- data: row,
10946
- parent: row,
10947
- i: 0,
10948
- key: path[0]
10949
- }));
10950
- while (stack.length > 0) {
10951
- const item = stack.pop();
10952
- const { i } = item;
10953
- if (i === last) {
10954
- batches.push(item);
10955
- continue;
10956
- }
10957
- const { data } = item;
10958
- const key = path[i];
10959
- if (Array.isArray(data)) for (let key = 0; key < data.length; key++) stack.push({
10960
- data: data[key],
10961
- parent: data,
10962
- key,
10963
- i
10964
- });
10965
- else if (data && typeof data === "object") stack.push({
10966
- data: data[key],
10967
- parent: data,
10968
- key,
10969
- i: i + 1
10970
- });
10916
+ const collectNestedSelectBatches = (batches, rows, path) => {
10917
+ const last = path.length - 1;
10918
+ const { key, returnType } = path[0];
10919
+ for (const row of rows) processNestedSelectPathEntry(batches, path, key, returnType, 0, last, row);
10920
+ };
10921
+ const processNestedSelectPathEntry = (batches, path, thisKey, thisReturnType, i, last, parent) => {
10922
+ const data = parent[thisKey];
10923
+ if (i === last) batches.push({
10924
+ data,
10925
+ parent,
10926
+ key: thisKey
10927
+ });
10928
+ else {
10929
+ const { key, returnType } = path[++i];
10930
+ if (!thisReturnType || thisReturnType === "all") for (const row of data) processNestedSelectPathEntry(batches, path, key, returnType, i, last, row);
10931
+ else processNestedSelectPathEntry(batches, path, key, returnType, i, last, data);
10971
10932
  }
10972
10933
  };
10973
10934
  const emptyArrSQL = new RawSql("'[]'");
10974
10935
  const processSelectArg = (q, as, arg, columnAs) => {
10975
- if (typeof arg === "string") return setParserForSelectedString(q, arg, as, columnAs);
10936
+ const query = q;
10937
+ if (typeof arg === "string") return setParserForSelectedString(query, arg, as, columnAs);
10976
10938
  const selectAs = {};
10939
+ const selectShape = query.q.selectShape = { ...query.q.selectShape };
10977
10940
  for (const key in arg) {
10978
- const item = processSelectAsArg(q, as, key, arg[key]);
10979
- if (item === false) return false;
10980
- selectAs[key] = item;
10941
+ const item = processSelectAsArg(q, selectAs, as, key, arg[key], key);
10942
+ if (item) selectShape[key] = item;
10943
+ else if (item === false) return false;
10981
10944
  }
10982
10945
  return { selectAs };
10983
10946
  };
10984
- const processSelectAsArg = (q, as, key, arg) => {
10947
+ const processSelectAsArg = (q, selectAs, as, key, arg, columnAlias, outerReturnType) => {
10985
10948
  const query = q;
10986
10949
  let value = arg;
10987
10950
  let joinQuery;
10951
+ let column;
10988
10952
  if (typeof value === "function") {
10989
10953
  value = resolveSubQueryCallback(q, value);
10990
10954
  if (isQueryNone(value)) {
10991
10955
  if (value.q.innerJoinLateral) return false;
10992
10956
  }
10993
- if (!isExpression(value)) {
10957
+ if (isExpression(value)) column = value.result.value;
10958
+ else {
10994
10959
  if (isRelationQuery(value) && value.q.subQuery !== 1) {
10995
10960
  joinQuery = true;
10996
10961
  setSelectRelation(query.q);
@@ -11011,10 +10976,27 @@ const processSelectAsArg = (q, as, key, arg) => {
11011
10976
  const as = _joinLateral(q, innerJoinLateral || query.q.returnType === "valueOrThrow" ? "JOIN" : "LEFT JOIN", subQuery, key, innerJoinLateral && returnType !== "one" && returnType !== "oneOrThrow");
11012
10977
  if (as) value.q.joinedForSelect = _copyQueryAliasToQuery(value, q, as);
11013
10978
  }
10979
+ if (value.q.getColumn?.data.skipValueToArray) value.q.notFoundDefault ??= null;
10980
+ else if (!value.q.type && (value.q.returnType === "value" || value.q.returnType === "valueOrThrow")) {
10981
+ const column = Object.create(value.q.getColumn || UnknownColumn.instance);
10982
+ column.data = {
10983
+ ...column.data,
10984
+ name: void 0,
10985
+ valueToArray: true
10986
+ };
10987
+ value.q.getColumn = column;
10988
+ if (value.q.expr) value.q.expr.q.getColumn = column;
10989
+ }
10990
+ if (outerReturnType === "value" && value.q.returnType === "valueOrThrow") value.q.returnType = "value";
10991
+ column = value.q.getColumn;
11014
10992
  value = prepareSubQueryForSql(q, value);
11015
10993
  }
11016
- }
11017
- return addParserForSelectItem(query, as, key, value, key, joinQuery);
10994
+ } else if (typeof value === "string") {
10995
+ const joinedAs = query.q.valuesJoinedAs?.[value];
10996
+ column = joinedAs ? query.q.joinedShapes?.[joinedAs]?.value : _getSelectableColumn(query, value);
10997
+ } else column = value.result.value;
10998
+ selectAs[key] = addParserForSelectItem(query, as, key, value, columnAlias, joinQuery);
10999
+ return column;
11018
11000
  };
11019
11001
  const setParserForSelectedString = (query, arg, as, columnAs, columnAlias) => {
11020
11002
  const { q } = query;
@@ -11032,7 +11014,7 @@ const setParserForSelectedString = (query, arg, as, columnAs, columnAlias) => {
11032
11014
  const batchParsers = q.joinedBatchParsers?.[table];
11033
11015
  if (batchParsers) {
11034
11016
  let cloned = false;
11035
- for (const bp of batchParsers) if (bp.path[0] === column) {
11017
+ for (const bp of batchParsers) if (bp.path[0].key === column) {
11036
11018
  if (!cloned) {
11037
11019
  q.batchParsers = [...q.batchParsers || []];
11038
11020
  cloned = true;
@@ -11070,7 +11052,7 @@ const selectColumn = (query, q, key, columnAs, columnAlias) => {
11070
11052
  };
11071
11053
  const getShapeFromSelect = (q, isSubQuery) => {
11072
11054
  const query = q.q;
11073
- const { shape } = query;
11055
+ const { selectShape: shape } = query;
11074
11056
  let select;
11075
11057
  if (query.selectedComputeds) {
11076
11058
  select = query.select ? [...query.select] : [];
@@ -11547,14 +11529,14 @@ var RefExpression = class extends Expression {
11547
11529
  makeSQL(ctx) {
11548
11530
  const q = this.q;
11549
11531
  const as = q.as || this.table;
11550
- return columnToSql(ctx, q, q.shape, this.ref, as && `"${as}"`);
11532
+ return columnToSqlNotSelect(ctx, q, q.selectShape, this.ref, as && `"${as}"`);
11551
11533
  }
11552
11534
  };
11553
11535
  const _queryUpdateMany = (self, primaryKeys, data, strict) => {
11554
11536
  const query = self;
11555
11537
  throwIfReadOnly(query);
11556
11538
  const { q } = query;
11557
- const { shape } = q;
11539
+ const shape = query.shape;
11558
11540
  q.type = "update";
11559
11541
  setUpdateReturning(q);
11560
11542
  if (!data.length) return _queryNone(query);
@@ -11610,7 +11592,7 @@ const _queryUpdate = (updateSelf, arg) => {
11610
11592
  q.type = "update";
11611
11593
  const set = { ...arg };
11612
11594
  pushQueryValueImmutable(query, "updateData", set);
11613
- const { shape } = q;
11595
+ const shape = query.shape;
11614
11596
  let selectQuery;
11615
11597
  for (const key in arg) {
11616
11598
  const item = shape[key];
@@ -12370,16 +12352,16 @@ var QueryExpressions = class {
12370
12352
  */
12371
12353
  ref(arg) {
12372
12354
  const q = _clone(this);
12373
- const { shape } = q.q;
12355
+ const { selectShape } = q.q;
12374
12356
  let column;
12375
12357
  const index = arg.indexOf(".");
12376
12358
  if (index !== -1) {
12377
12359
  const as = q.q.as || q.table;
12378
12360
  const table = getFullColumnTable(q, arg, index, as);
12379
12361
  const col = arg.slice(index + 1);
12380
- if (table === as) column = shape[col];
12362
+ if (table === as) column = selectShape[col];
12381
12363
  else column = q.q.joinedShapes?.[table][col];
12382
- } else column = shape[arg];
12364
+ } else column = selectShape[arg];
12383
12365
  return new RefExpression(column || UnknownColumn.instance, q, arg);
12384
12366
  }
12385
12367
  val(value) {
@@ -12422,7 +12404,7 @@ var QueryExpressions = class {
12422
12404
  * @param options
12423
12405
  */
12424
12406
  fn(fn, args, options) {
12425
- return makeFnExpression(this, emptyObject, fn, args, options);
12407
+ return makeFnExpression(this, UnknownColumn.instance, fn, args, options);
12426
12408
  }
12427
12409
  or(...args) {
12428
12410
  return new OrExpression(args);
@@ -12435,7 +12417,7 @@ const _appendQueryOnUpsertCreate = (main, append, asFn) => {
12435
12417
  return pushQueryValueImmutable(pushQueryValueImmutable(main, "upsertCreateAppendQueries", prepareSubQueryForSql(main, append)), "upsertCreateAsFns", asFn);
12436
12418
  };
12437
12419
  const mergableObjects = new Set([
12438
- "shape",
12420
+ "selectShape",
12439
12421
  "withShapes",
12440
12422
  "defaultParsers",
12441
12423
  "parsers",
@@ -12639,7 +12621,7 @@ var Headline = class extends Expression {
12639
12621
  const { source, params } = this;
12640
12622
  const q = this.q;
12641
12623
  const lang = getSearchLang(ctx, q, source, quotedAs);
12642
- 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);
12624
+ 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);
12643
12625
  const options = params?.options ? `, ${params.options instanceof Expression ? params.options.toSQL(ctx, quotedAs) : addValue(ctx.values, params.options)}` : "";
12644
12626
  return `ts_headline(${lang}, ${text}, "${source.as}"${options})`;
12645
12627
  }
@@ -12965,10 +12947,12 @@ var QueryPluck = class {
12965
12947
  const q = _clone(this);
12966
12948
  q.q.returnType = "pluck";
12967
12949
  let selected;
12968
- if (typeof select === "function") {
12969
- const item = processSelectAsArg(q, q.q.as || q.table, "pluck", select);
12970
- if (item !== false) selected = isExpression(item) ? item : { selectAs: { pluck: item } };
12971
- } else selected = addParserForSelectItem(q, q.q.as || q.table, "pluck", select);
12950
+ const selectAs = {};
12951
+ const item = processSelectAsArg(q, selectAs, q.q.as || q.table, "pluck", select, void 0, "value");
12952
+ if (item !== false) {
12953
+ q.q.getColumn = item;
12954
+ selected = typeof selectAs.pluck === "object" && !isExpression(selectAs.pluck) ? { selectAs } : selectAs.pluck;
12955
+ }
12972
12956
  q.q.select = selected ? [selected] : void 0;
12973
12957
  return q;
12974
12958
  }
@@ -13265,6 +13249,39 @@ var QueryWindow = class {
13265
13249
  return pushQueryValueImmutable(_clone(this), "window", arg);
13266
13250
  }
13267
13251
  };
13252
+ const _exists = (query, value) => {
13253
+ const q = _queryGetOptional(_clone(query), new RawSql(String(value)));
13254
+ q.q.notFoundDefault = !value;
13255
+ q.q.coalesceValue = new RawSql(String(!value));
13256
+ q.q.getColumn = BooleanColumn.instanceSkipValueToArray;
13257
+ return q;
13258
+ };
13259
+ var QueryExistsMethods = class {
13260
+ /**
13261
+ * Use `exists()` to check if there is at least one record-matching condition.
13262
+ *
13263
+ * It will discard previous `select` statements if any. Returns a boolean.
13264
+ *
13265
+ * ```ts
13266
+ * const exists: boolean = await db.table.where(...conditions).exists();
13267
+ * ```
13268
+ */
13269
+ exists() {
13270
+ return _exists(this, true);
13271
+ }
13272
+ /**
13273
+ * Use `notExists()` to check if there are no matching records.
13274
+ *
13275
+ * It will discard previous `select` statements if any. Returns a boolean.
13276
+ *
13277
+ * ```ts
13278
+ * const exists: boolean = await db.table.where(...conditions).notExists();
13279
+ * ```
13280
+ */
13281
+ notExists() {
13282
+ return _exists(this, false);
13283
+ }
13284
+ };
13268
13285
  var QueryMethods = class {
13269
13286
  /**
13270
13287
  * `.all` is a default behavior, that returns an array of objects:
@@ -13338,6 +13355,30 @@ var QueryMethods = class {
13338
13355
  return _queryExec(_clone(this));
13339
13356
  }
13340
13357
  /**
13358
+ * For relation selects, `require` changes LEFT JOIN LATERAL to JOIN LATERAL.
13359
+ *
13360
+ * ```ts
13361
+ * // only the records that have `related` will be loaded:
13362
+ * await db.table.select({ related: (q) => q.related.required() });
13363
+ * ```
13364
+ */
13365
+ require() {
13366
+ const query = _clone(this);
13367
+ switch (query.q.returnType) {
13368
+ case void 0:
13369
+ case "all":
13370
+ case "valueOrThrow":
13371
+ case "pluck":
13372
+ case "void": break;
13373
+ case "value":
13374
+ query.q.returnType = "valueOrThrow";
13375
+ break;
13376
+ default: query.q.returnType = "oneOrThrow";
13377
+ }
13378
+ query.q.innerJoinLateral = true;
13379
+ return query;
13380
+ }
13381
+ /**
13341
13382
  * Call `toSQL` on a query to get an object with a `text` SQL string and a `values` array of binding values:
13342
13383
  *
13343
13384
  * ```ts
@@ -13541,7 +13582,7 @@ var QueryMethods = class {
13541
13582
  * // all the following queries will resolve into empty arrays
13542
13583
  *
13543
13584
  * await db.user.select({
13544
- * pets: (q) => q.pets.join().none(),
13585
+ * pets: (q) => q.pets.require().none(),
13545
13586
  * });
13546
13587
  *
13547
13588
  * await db.user.join((q) => q.pets.none());
@@ -13791,7 +13832,8 @@ applyMixins(QueryMethods, [
13791
13832
  SoftDeleteMethods,
13792
13833
  QueryExpressions,
13793
13834
  QueryWrap,
13794
- QueryWindow
13835
+ QueryWindow,
13836
+ QueryExistsMethods
13795
13837
  ]);
13796
13838
  const performQuery = async (q, args, method) => {
13797
13839
  const trx = q.internal.asyncStorage.getStore();
@@ -13906,7 +13948,7 @@ var Db = class extends QueryMethods {
13906
13948
  };
13907
13949
  this.q = {
13908
13950
  adapter: adapterNotInTransaction,
13909
- shape,
13951
+ selectShape: shape,
13910
13952
  handleResult,
13911
13953
  logger,
13912
13954
  log: logParamToLogObject(logger, options.log),
@@ -14244,7 +14286,7 @@ const makeColumnInfoSql = (query, column) => {
14244
14286
  const values = [];
14245
14287
  const schema = getQuerySchema(query);
14246
14288
  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()"}`;
14247
- if (column) text += ` AND column_name = ${addValue(values, query.q.shape[column]?.data.name || column)}`;
14289
+ if (column) text += ` AND column_name = ${addValue(values, query.shape[column]?.data.name || column)}`;
14248
14290
  return {
14249
14291
  text,
14250
14292
  values
@@ -14300,7 +14342,7 @@ const makeCopySql = (table, copy) => {
14300
14342
  const ctx = newToSqlCtx(table);
14301
14343
  const { q } = table;
14302
14344
  const quotedAs = `"${q.as || table.table}"`;
14303
- const columns = copy.columns ? `(${copy.columns.map((item) => `"${q.shape[item]?.data.name || item}"`).join(", ")})` : "";
14345
+ const columns = copy.columns ? `(${copy.columns.map((item) => `"${table.shape[item]?.data.name || item}"`).join(", ")})` : "";
14304
14346
  const target = "from" in copy ? copy.from : copy.to;
14305
14347
  const quotedTable = quoteTableWithSchema(table);
14306
14348
  ctx.sql.push(`COPY ${quotedTable}${columns} ${"from" in copy ? "FROM" : "TO"} ${typeof target === "string" ? escapeString(target) : `PROGRAM ${escapeString(target.program)}`}`);