@typed-sql/postgres 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/CHANGELOG.md +289 -0
  2. package/README.md +17 -0
  3. package/dist/packages/postgres/src/bulk.d.ts.map +1 -1
  4. package/dist/packages/postgres/src/bulk.js +1 -1
  5. package/dist/packages/postgres/src/bulk.js.map +1 -1
  6. package/dist/packages/postgres/src/capabilities.d.ts +19 -0
  7. package/dist/packages/postgres/src/capabilities.d.ts.map +1 -0
  8. package/dist/packages/postgres/src/capabilities.js +120 -0
  9. package/dist/packages/postgres/src/capabilities.js.map +1 -0
  10. package/dist/packages/postgres/src/catalog/generated/14.d.ts +4 -0
  11. package/dist/packages/postgres/src/catalog/generated/14.d.ts.map +1 -0
  12. package/dist/packages/postgres/src/catalog/generated/14.js +2018 -0
  13. package/dist/packages/postgres/src/catalog/generated/14.js.map +1 -0
  14. package/dist/packages/postgres/src/catalog/generated/15.d.ts +4 -0
  15. package/dist/packages/postgres/src/catalog/generated/15.d.ts.map +1 -0
  16. package/dist/packages/postgres/src/catalog/generated/15.js +2012 -0
  17. package/dist/packages/postgres/src/catalog/generated/15.js.map +1 -0
  18. package/dist/packages/postgres/src/catalog/generated/16.d.ts +4 -0
  19. package/dist/packages/postgres/src/catalog/generated/16.d.ts.map +1 -0
  20. package/dist/packages/postgres/src/catalog/generated/16.js +2012 -0
  21. package/dist/packages/postgres/src/catalog/generated/16.js.map +1 -0
  22. package/dist/packages/postgres/src/catalog/generated/17.d.ts +4 -0
  23. package/dist/packages/postgres/src/catalog/generated/17.d.ts.map +1 -0
  24. package/dist/packages/postgres/src/catalog/generated/17.js +2012 -0
  25. package/dist/packages/postgres/src/catalog/generated/17.js.map +1 -0
  26. package/dist/packages/postgres/src/catalog/generated/18.d.ts +4 -0
  27. package/dist/packages/postgres/src/catalog/generated/18.d.ts.map +1 -0
  28. package/dist/packages/postgres/src/catalog/generated/18.js +2048 -0
  29. package/dist/packages/postgres/src/catalog/generated/18.js.map +1 -0
  30. package/dist/packages/postgres/src/catalog/generated/19.d.ts +4 -0
  31. package/dist/packages/postgres/src/catalog/generated/19.d.ts.map +1 -0
  32. package/dist/packages/postgres/src/catalog/generated/19.js +2048 -0
  33. package/dist/packages/postgres/src/catalog/generated/19.js.map +1 -0
  34. package/dist/packages/postgres/src/catalog/index.d.ts +14 -0
  35. package/dist/packages/postgres/src/catalog/index.d.ts.map +1 -0
  36. package/dist/packages/postgres/src/catalog/index.js +86 -0
  37. package/dist/packages/postgres/src/catalog/index.js.map +1 -0
  38. package/dist/packages/postgres/src/catalog/types.d.ts +46 -0
  39. package/dist/packages/postgres/src/catalog/types.d.ts.map +1 -0
  40. package/dist/packages/postgres/src/catalog/types.js +2 -0
  41. package/dist/packages/postgres/src/catalog/types.js.map +1 -0
  42. package/dist/packages/postgres/src/expression-evidence.d.ts +11 -0
  43. package/dist/packages/postgres/src/expression-evidence.d.ts.map +1 -0
  44. package/dist/packages/postgres/src/expression-evidence.js +33 -0
  45. package/dist/packages/postgres/src/expression-evidence.js.map +1 -0
  46. package/dist/packages/postgres/src/extensions.d.ts +61 -0
  47. package/dist/packages/postgres/src/extensions.d.ts.map +1 -0
  48. package/dist/packages/postgres/src/extensions.js +311 -0
  49. package/dist/packages/postgres/src/extensions.js.map +1 -0
  50. package/dist/packages/postgres/src/index.d.ts +13 -0
  51. package/dist/packages/postgres/src/index.d.ts.map +1 -1
  52. package/dist/packages/postgres/src/index.js +51 -17
  53. package/dist/packages/postgres/src/index.js.map +1 -1
  54. package/dist/packages/postgres/src/parser/index.d.ts +8 -0
  55. package/dist/packages/postgres/src/parser/index.d.ts.map +1 -0
  56. package/dist/packages/postgres/src/parser/index.js +4 -0
  57. package/dist/packages/postgres/src/parser/index.js.map +1 -0
  58. package/dist/packages/postgres/src/parser/parser.d.ts +14 -0
  59. package/dist/packages/postgres/src/parser/parser.d.ts.map +1 -0
  60. package/dist/packages/postgres/src/parser/parser.js +2683 -0
  61. package/dist/packages/postgres/src/parser/parser.js.map +1 -0
  62. package/dist/packages/postgres/src/parser/tokenizer.d.ts +15 -0
  63. package/dist/packages/postgres/src/parser/tokenizer.d.ts.map +1 -0
  64. package/dist/packages/postgres/src/parser/tokenizer.js +470 -0
  65. package/dist/packages/postgres/src/parser/tokenizer.js.map +1 -0
  66. package/dist/packages/postgres/src/parser/types.d.ts +652 -0
  67. package/dist/packages/postgres/src/parser/types.d.ts.map +1 -0
  68. package/dist/packages/postgres/src/parser/types.js +9 -0
  69. package/dist/packages/postgres/src/parser/types.js.map +1 -0
  70. package/dist/packages/postgres/src/parser/walk.d.ts +13 -0
  71. package/dist/packages/postgres/src/parser/walk.d.ts.map +1 -0
  72. package/dist/packages/postgres/src/parser/walk.js +374 -0
  73. package/dist/packages/postgres/src/parser/walk.js.map +1 -0
  74. package/dist/packages/postgres/src/pg.d.ts +35 -4
  75. package/dist/packages/postgres/src/pg.d.ts.map +1 -1
  76. package/dist/packages/postgres/src/pg.js +355 -40
  77. package/dist/packages/postgres/src/pg.js.map +1 -1
  78. package/dist/packages/postgres/src/prepared.d.ts +5 -3
  79. package/dist/packages/postgres/src/prepared.d.ts.map +1 -1
  80. package/dist/packages/postgres/src/prepared.js +23 -15
  81. package/dist/packages/postgres/src/prepared.js.map +1 -1
  82. package/dist/packages/postgres/src/provider.d.ts +149 -11
  83. package/dist/packages/postgres/src/provider.d.ts.map +1 -1
  84. package/dist/packages/postgres/src/provider.js +652 -42
  85. package/dist/packages/postgres/src/provider.js.map +1 -1
  86. package/dist/packages/postgres/src/resolver.d.ts +1 -1
  87. package/dist/packages/postgres/src/resolver.d.ts.map +1 -1
  88. package/dist/packages/postgres/src/resolver.js +2767 -203
  89. package/dist/packages/postgres/src/resolver.js.map +1 -1
  90. package/dist/packages/postgres/src/routing.d.ts.map +1 -1
  91. package/dist/packages/postgres/src/routing.js +1 -1
  92. package/dist/packages/postgres/src/routing.js.map +1 -1
  93. package/dist/packages/postgres/src/runtime-compatibility.d.ts +14 -0
  94. package/dist/packages/postgres/src/runtime-compatibility.d.ts.map +1 -0
  95. package/dist/packages/postgres/src/runtime-compatibility.js +63 -0
  96. package/dist/packages/postgres/src/runtime-compatibility.js.map +1 -0
  97. package/dist/packages/postgres/src/runtime.d.ts +10 -1
  98. package/dist/packages/postgres/src/runtime.d.ts.map +1 -1
  99. package/dist/packages/postgres/src/runtime.js +50 -2
  100. package/dist/packages/postgres/src/runtime.js.map +1 -1
  101. package/dist/packages/postgres/src/semantics.d.ts +1 -1
  102. package/dist/packages/postgres/src/semantics.d.ts.map +1 -1
  103. package/dist/packages/postgres/src/semantics.js +19 -6
  104. package/dist/packages/postgres/src/semantics.js.map +1 -1
  105. package/dist/packages/postgres/src/support.d.ts +29 -0
  106. package/dist/packages/postgres/src/support.d.ts.map +1 -0
  107. package/dist/packages/postgres/src/support.js +45 -0
  108. package/dist/packages/postgres/src/support.js.map +1 -0
  109. package/dist/packages/postgres/src/type-policy.d.ts.map +1 -1
  110. package/dist/packages/postgres/src/type-policy.js +34 -43
  111. package/dist/packages/postgres/src/type-policy.js.map +1 -1
  112. package/dist/packages/postgres/src/type-resolution.d.ts +33 -0
  113. package/dist/packages/postgres/src/type-resolution.d.ts.map +1 -0
  114. package/dist/packages/postgres/src/type-resolution.js +906 -0
  115. package/dist/packages/postgres/src/type-resolution.js.map +1 -0
  116. package/package.json +7 -4
@@ -0,0 +1,906 @@
1
+ import { upgradeSchemaSnapshotV1, } from "@typed-sql/schema";
2
+ import { postgresCatalogCanCast, postgresCatalogOperatorRule, postgresCatalogType, postgresCoreCatalogForSchema, } from "./catalog/index.js";
3
+ import { postgresExtensionCasts, postgresExtensionOperators } from "./extensions.js";
4
+ const comparisonOperators = new Set([
5
+ "<",
6
+ "<=",
7
+ "=",
8
+ ">",
9
+ ">=",
10
+ "!=",
11
+ "<>",
12
+ "IS DISTINCT FROM",
13
+ "IS NOT DISTINCT FROM",
14
+ ]);
15
+ const patternOperators = new Set([
16
+ "LIKE",
17
+ "NOT LIKE",
18
+ "ILIKE",
19
+ "NOT ILIKE",
20
+ "SIMILAR TO",
21
+ "NOT SIMILAR",
22
+ "~",
23
+ "~*",
24
+ "!~",
25
+ "!~*",
26
+ ]);
27
+ const simplePolymorphicTypes = new Set([
28
+ "anyelement",
29
+ "anyarray",
30
+ "anynonarray",
31
+ "anyenum",
32
+ "anyrange",
33
+ "anymultirange",
34
+ ]);
35
+ const compatiblePolymorphicTypes = new Set([
36
+ "anycompatible",
37
+ "anycompatiblearray",
38
+ "anycompatiblenonarray",
39
+ "anycompatiblerange",
40
+ "anycompatiblemultirange",
41
+ ]);
42
+ const numericOperatorTypes = new Set(["smallint", "integer", "bigint", "numeric", "real", "double precision"]);
43
+ // Operator candidate construction expands PostgreSQL type categories and applies schema-owned
44
+ // extension casts. A snapshot is immutable analysis evidence, so retain the expansion alongside
45
+ // the other snapshot-indexed resolver caches instead of rebuilding it for every expression.
46
+ const operatorCandidatesBySchema = new WeakMap();
47
+ const defaultOperatorCandidates = new Map();
48
+ const upgradedSchemas = new WeakMap();
49
+ const operatorResolutionsBySchema = new WeakMap();
50
+ const defaultOperatorResolutions = new Map();
51
+ function normalize(value) {
52
+ return value
53
+ .trim()
54
+ .toLowerCase()
55
+ .replace(/\(\d+(?:,\s*\d+)?\)/gu, "")
56
+ .replace(/\s+/gu, " ");
57
+ }
58
+ function schemaTypes(schema) {
59
+ if (schema === undefined)
60
+ return [];
61
+ if (schema.formatVersion === 2)
62
+ return Object.values(schema.types);
63
+ const cached = upgradedSchemas.get(schema);
64
+ if (cached !== undefined)
65
+ return Object.values(cached.types);
66
+ const upgraded = upgradeSchemaSnapshotV1(schema);
67
+ upgradedSchemas.set(schema, upgraded);
68
+ return Object.values(upgraded.types);
69
+ }
70
+ function typeEvidence(databaseType, schema) {
71
+ const normalized = normalize(databaseType);
72
+ const types = schemaTypes(schema);
73
+ const exact = types.find((type) => normalize(type.databaseType) === normalized ||
74
+ normalize(type.identity) === normalized ||
75
+ normalize(`${type.schema === undefined ? "" : `${type.schema}.`}${type.name}`) === normalized);
76
+ if (exact !== undefined)
77
+ return exact;
78
+ const unqualified = types.filter((type) => normalize(type.name) === normalized);
79
+ return unqualified.length === 1 ? unqualified[0] : undefined;
80
+ }
81
+ /** Canonical PostgreSQL type identity for overload and coercion decisions. */
82
+ export function postgresCanonicalType(databaseType, schema) {
83
+ const normalized = normalize(databaseType);
84
+ if (normalized.endsWith("[]")) {
85
+ return `${postgresCanonicalType(normalized.slice(0, -2), schema)}[]`;
86
+ }
87
+ return postgresCatalogType(normalized, schema)?.name ?? typeEvidence(normalized, schema)?.databaseType ?? normalized;
88
+ }
89
+ function baseType(databaseType, schema) {
90
+ const canonical = postgresCanonicalType(databaseType, schema);
91
+ const evidence = typeEvidence(canonical, schema);
92
+ if (evidence?.kind !== "domain")
93
+ return canonical;
94
+ const base = schemaTypes(schema).find((type) => type.identity === evidence.baseTypeIdentity);
95
+ return postgresCanonicalType(base?.databaseType ?? evidence.baseTypeIdentity, schema);
96
+ }
97
+ function category(databaseType, schema) {
98
+ const canonical = baseType(databaseType, schema);
99
+ if (canonical.endsWith("[]"))
100
+ return "array";
101
+ const catalogType = postgresCatalogType(canonical, schema);
102
+ if (catalogType !== undefined)
103
+ return catalogType.category;
104
+ const evidence = typeEvidence(canonical, schema);
105
+ if (evidence?.kind === "enum")
106
+ return "enum";
107
+ if (evidence?.kind === "composite")
108
+ return "composite";
109
+ if (evidence?.kind === "range" || evidence?.kind === "multirange")
110
+ return "range";
111
+ return evidence === undefined ? undefined : "user";
112
+ }
113
+ /** PostgreSQL type category after aliases and domains are resolved. */
114
+ export function postgresTypeCategory(databaseType, schema) {
115
+ return category(databaseType, schema);
116
+ }
117
+ function isPreferred(databaseType, schema) {
118
+ return postgresCatalogType(baseType(databaseType, schema), schema)?.preferred ?? false;
119
+ }
120
+ function elementType(databaseType, schema) {
121
+ const canonical = postgresCanonicalType(databaseType, schema);
122
+ if (canonical.endsWith("[]"))
123
+ return canonical.slice(0, -2);
124
+ const evidence = typeEvidence(canonical, schema);
125
+ if (evidence?.kind !== "collection")
126
+ return undefined;
127
+ const element = schemaTypes(schema).find((type) => type.identity === evidence.elementTypeIdentity);
128
+ return element === undefined ? undefined : postgresCanonicalType(element.databaseType, schema);
129
+ }
130
+ /** Returns the element identity for a PostgreSQL array or snapshot collection type. */
131
+ export function postgresElementType(databaseType, schema) {
132
+ return elementType(databaseType, schema);
133
+ }
134
+ function rangeSubtype(databaseType, schema) {
135
+ const evidence = typeEvidence(databaseType, schema);
136
+ if (evidence?.kind !== "range" && evidence?.kind !== "multirange")
137
+ return undefined;
138
+ const subtype = schemaTypes(schema).find((type) => type.identity === evidence.subtypeIdentity);
139
+ return subtype === undefined ? undefined : postgresCanonicalType(subtype.databaseType, schema);
140
+ }
141
+ /** PostgreSQL common-type selection used by compatible polymorphic inputs. */
142
+ export function postgresCommonType(databaseTypes, schema) {
143
+ const known = databaseTypes
144
+ .filter((value) => value !== undefined)
145
+ .map((value) => baseType(value, schema));
146
+ if (known.length === 0)
147
+ return "text";
148
+ if (known.every((value) => value === known[0]))
149
+ return known[0];
150
+ const firstCategory = category(known[0], schema);
151
+ if (firstCategory === undefined || known.some((value) => category(value, schema) !== firstCategory))
152
+ return undefined;
153
+ let candidate = known[0];
154
+ for (const value of known.slice(1)) {
155
+ if (candidate === value)
156
+ continue;
157
+ const candidateToValue = postgresCanCoerce(candidate, value, "implicit", schema);
158
+ const valueToCandidate = postgresCanCoerce(value, candidate, "implicit", schema);
159
+ if (!candidateToValue && !valueToCandidate)
160
+ return undefined;
161
+ if (candidateToValue && !valueToCandidate)
162
+ candidate = value;
163
+ if (isPreferred(candidate, schema))
164
+ break;
165
+ }
166
+ return known.every((value) => postgresCanCoerce(value, candidate, "implicit", schema)) ? candidate : undefined;
167
+ }
168
+ export function postgresCanCoerce(source, target, context, schema) {
169
+ const sourceType = baseType(source, schema);
170
+ const targetType = baseType(target, schema);
171
+ if (sourceType.endsWith("[]") && targetType.endsWith("[]")) {
172
+ return postgresCanCoerce(sourceType.slice(0, -2), targetType.slice(0, -2), context, schema);
173
+ }
174
+ const sourceCategory = category(sourceType, schema);
175
+ const targetCategory = category(targetType, schema);
176
+ if (sourceCategory !== undefined &&
177
+ targetCategory !== undefined &&
178
+ ((context !== "implicit" && targetCategory === "string") || (context === "explicit" && sourceCategory === "string"))) {
179
+ return true;
180
+ }
181
+ if (postgresCatalogCanCast(sourceType, targetType, context, schema))
182
+ return true;
183
+ const cast = postgresExtensionCasts(schema).find((candidate) => postgresCanonicalType(candidate.sourceType, schema) === sourceType &&
184
+ postgresCanonicalType(candidate.targetType, schema) === targetType);
185
+ return (cast !== undefined &&
186
+ (context === "explicit" ||
187
+ cast.context === "implicit" ||
188
+ (context === "assignment" && cast.context === "assignment")));
189
+ }
190
+ function bindExact(binding, value) {
191
+ return binding === undefined || binding === value ? value : false;
192
+ }
193
+ function bindPolymorphic(declared, actual, bindings, compatibleInputs, schema) {
194
+ if (actual === undefined)
195
+ return true;
196
+ const canonical = postgresCanonicalType(actual, schema);
197
+ if (simplePolymorphicTypes.has(declared)) {
198
+ if (declared === "anyarray") {
199
+ const element = elementType(canonical, schema);
200
+ if (element === undefined)
201
+ return false;
202
+ const array = bindExact(bindings.simpleArray, canonical);
203
+ const simple = bindExact(bindings.simple, element);
204
+ if (array === false || simple === false)
205
+ return false;
206
+ bindings.simpleArray = array;
207
+ bindings.simple = simple;
208
+ return true;
209
+ }
210
+ if (declared === "anyrange" || declared === "anymultirange") {
211
+ const subtype = rangeSubtype(canonical, schema);
212
+ if (subtype === undefined)
213
+ return false;
214
+ const key = declared === "anyrange" ? "simpleRange" : "simpleMultirange";
215
+ const range = bindExact(bindings[key], canonical);
216
+ const simple = bindExact(bindings.simple, subtype);
217
+ if (range === false || simple === false)
218
+ return false;
219
+ bindings[key] = range;
220
+ bindings.simple = simple;
221
+ return true;
222
+ }
223
+ if (declared === "anynonarray" && elementType(canonical, schema) !== undefined)
224
+ return false;
225
+ if (declared === "anyenum" && category(canonical, schema) !== "enum")
226
+ return false;
227
+ const simple = bindExact(bindings.simple, canonical);
228
+ if (simple === false)
229
+ return false;
230
+ bindings.simple = simple;
231
+ return true;
232
+ }
233
+ if (!compatiblePolymorphicTypes.has(declared))
234
+ return false;
235
+ if (declared === "anycompatiblearray") {
236
+ const element = elementType(canonical, schema);
237
+ if (element === undefined)
238
+ return false;
239
+ compatibleInputs.push(element);
240
+ bindings.compatibleArray = canonical;
241
+ return true;
242
+ }
243
+ if (declared === "anycompatiblerange" || declared === "anycompatiblemultirange") {
244
+ const subtype = rangeSubtype(canonical, schema);
245
+ if (subtype === undefined)
246
+ return false;
247
+ compatibleInputs.push(subtype);
248
+ const key = declared === "anycompatiblerange" ? "compatibleRange" : "compatibleMultirange";
249
+ const current = bindExact(bindings[key], canonical);
250
+ if (current === false)
251
+ return false;
252
+ bindings[key] = current;
253
+ return true;
254
+ }
255
+ if (declared === "anycompatiblenonarray" && elementType(canonical, schema) !== undefined)
256
+ return false;
257
+ compatibleInputs.push(canonical);
258
+ return true;
259
+ }
260
+ function instantiate(declared, bindings) {
261
+ if (declared === "anyelement" || declared === "anynonarray" || declared === "anyenum")
262
+ return bindings.simple;
263
+ if (declared === "anyarray")
264
+ return bindings.simpleArray ?? (bindings.simple === undefined ? undefined : `${bindings.simple}[]`);
265
+ if (declared === "anyrange")
266
+ return bindings.simpleRange;
267
+ if (declared === "anymultirange")
268
+ return bindings.simpleMultirange;
269
+ if (declared === "anycompatible" || declared === "anycompatiblenonarray")
270
+ return bindings.compatible;
271
+ if (declared === "anycompatiblearray")
272
+ return bindings.compatible === undefined ? bindings.compatibleArray : `${bindings.compatible}[]`;
273
+ if (declared === "anycompatiblerange")
274
+ return bindings.compatibleRange;
275
+ if (declared === "anycompatiblemultirange")
276
+ return bindings.compatibleMultirange;
277
+ return declared;
278
+ }
279
+ function rankCandidate(candidate, actualTypes, schema) {
280
+ if (candidate.argumentTypes.length !== actualTypes.length)
281
+ return undefined;
282
+ const bindings = {};
283
+ const compatibleInputs = [];
284
+ let exact = 0;
285
+ let preferred = 0;
286
+ let unknownString = 0;
287
+ for (const [index, declaredValue] of candidate.argumentTypes.entries()) {
288
+ const declared = postgresCanonicalType(declaredValue, schema);
289
+ const actualValue = actualTypes[index];
290
+ const actual = actualValue === undefined ? undefined : postgresCanonicalType(actualValue, schema);
291
+ if (simplePolymorphicTypes.has(declared) || compatiblePolymorphicTypes.has(declared)) {
292
+ if (!bindPolymorphic(declared, actual, bindings, compatibleInputs, schema))
293
+ return undefined;
294
+ continue;
295
+ }
296
+ if (actual === undefined) {
297
+ if (category(declared, schema) === "string")
298
+ unknownString += 1;
299
+ if (isPreferred(declared, schema))
300
+ preferred += 1;
301
+ continue;
302
+ }
303
+ if (baseType(actual, schema) === baseType(declared, schema))
304
+ exact += 1;
305
+ else if (!postgresCanCoerce(actual, declared, "implicit", schema))
306
+ return undefined;
307
+ else if (isPreferred(declared, schema))
308
+ preferred += 1;
309
+ }
310
+ if (compatibleInputs.length > 0 ||
311
+ candidate.argumentTypes.some((type) => compatiblePolymorphicTypes.has(normalize(type)))) {
312
+ const common = postgresCommonType(compatibleInputs.length === 0 ? [undefined] : compatibleInputs, schema);
313
+ if (common === undefined)
314
+ return undefined;
315
+ bindings.compatible = common;
316
+ }
317
+ const argumentTypes = candidate.argumentTypes.map((declared) => instantiate(declared, bindings) ?? declared);
318
+ const resultType = instantiate(candidate.resultType, bindings);
319
+ if (resultType === undefined)
320
+ return undefined;
321
+ return { kind: "selected", candidate: candidate.value, argumentTypes, resultType, exact, preferred, unknownString };
322
+ }
323
+ /** Selects a PostgreSQL overload using exact, implicit-cast, preferred-type, and unknown-category evidence. */
324
+ export function resolvePostgresCandidates(candidates, actualTypes, schema) {
325
+ let matches = candidates
326
+ .map((candidate) => rankCandidate(candidate, actualTypes, schema))
327
+ .filter((candidate) => candidate !== undefined);
328
+ if (matches.length === 0)
329
+ return { kind: "none" };
330
+ for (const [index, actual] of actualTypes.entries()) {
331
+ if (actual !== undefined)
332
+ continue;
333
+ const categories = new Set(matches
334
+ .map((candidate) => category(candidate.argumentTypes[index], schema))
335
+ .filter((candidate) => candidate !== undefined));
336
+ const selectedCategory = categories.has("string")
337
+ ? "string"
338
+ : categories.size === 1
339
+ ? [...categories][0]
340
+ : undefined;
341
+ if (selectedCategory === undefined)
342
+ return { kind: "ambiguous" };
343
+ matches = matches.filter((candidate) => category(candidate.argumentTypes[index], schema) === selectedCategory);
344
+ const preferred = matches.filter((candidate) => isPreferred(candidate.argumentTypes[index], schema));
345
+ if (preferred.length > 0)
346
+ matches = preferred;
347
+ if (matches.length === 1)
348
+ return matches[0];
349
+ }
350
+ for (const score of ["exact", "preferred", "unknownString"]) {
351
+ const maximum = Math.max(...matches.map((candidate) => candidate[score]));
352
+ if (maximum > 0)
353
+ matches = matches.filter((candidate) => candidate[score] === maximum);
354
+ if (matches.length === 1)
355
+ return matches[0];
356
+ }
357
+ const known = actualTypes
358
+ .filter((value) => value !== undefined)
359
+ .map((value) => baseType(value, schema));
360
+ if (known.length > 0 && known.every((value) => value === known[0])) {
361
+ const sameType = matches.filter((candidate) => candidate.argumentTypes.every((declared, index) => actualTypes[index] !== undefined || declared === known[0]));
362
+ if (sameType.length === 1)
363
+ return sameType[0];
364
+ }
365
+ return { kind: "ambiguous" };
366
+ }
367
+ function categoryPairs(categoryName, schema) {
368
+ const types = postgresCoreCatalogForSchema(schema)
369
+ .types.filter(({ category: candidateCategory }) => candidateCategory === categoryName)
370
+ .map(({ name }) => name);
371
+ return types.flatMap((left) => types.flatMap((right) => {
372
+ const result = postgresCommonType([left, right], schema);
373
+ return result === undefined ? [] : [[left, right, result]];
374
+ }));
375
+ }
376
+ function categoryTypes(categoryName, schema) {
377
+ return postgresCoreCatalogForSchema(schema)
378
+ .types.filter(({ category: candidateCategory }) => candidateCategory === categoryName)
379
+ .map(({ name }) => name);
380
+ }
381
+ function numericOperatorCandidates(operator) {
382
+ const candidates = [];
383
+ const add = (left, right, resultType) => {
384
+ candidates.push({ value: operator, argumentTypes: [left, right], resultType });
385
+ };
386
+ const integral = ["smallint", "integer", "bigint"];
387
+ const integralResult = (left, right) => integral[Math.max(integral.indexOf(left), integral.indexOf(right))];
388
+ if (["+", "-", "*", "/"].includes(operator)) {
389
+ for (const left of integral) {
390
+ for (const right of integral)
391
+ add(left, right, integralResult(left, right));
392
+ }
393
+ add("real", "real", "real");
394
+ add("real", "double precision", "double precision");
395
+ add("double precision", "real", "double precision");
396
+ add("double precision", "double precision", "double precision");
397
+ add("numeric", "numeric", "numeric");
398
+ }
399
+ else if (operator === "%") {
400
+ for (const type of integral)
401
+ add(type, type, type);
402
+ add("numeric", "numeric", "numeric");
403
+ }
404
+ else if (operator === "^") {
405
+ add("numeric", "numeric", "numeric");
406
+ add("double precision", "double precision", "double precision");
407
+ }
408
+ return candidates;
409
+ }
410
+ function temporalOperatorCandidates(operator) {
411
+ const candidates = [];
412
+ const add = (left, right, resultType) => {
413
+ candidates.push({ value: operator, argumentTypes: [left, right], resultType });
414
+ };
415
+ if (operator === "+") {
416
+ add("date", "integer", "date");
417
+ add("integer", "date", "date");
418
+ for (const type of ["timestamp", "timestamptz", "time"]) {
419
+ add(type, "interval", type);
420
+ add("interval", type, type);
421
+ }
422
+ add("interval", "interval", "interval");
423
+ }
424
+ else if (operator === "-") {
425
+ add("date", "integer", "date");
426
+ add("date", "date", "integer");
427
+ for (const type of ["timestamp", "timestamptz", "time"]) {
428
+ add(type, type, "interval");
429
+ add(type, "interval", type);
430
+ }
431
+ add("interval", "interval", "interval");
432
+ }
433
+ else if (operator === "*") {
434
+ for (const numeric of numericOperatorTypes) {
435
+ add("interval", numeric, "interval");
436
+ add(numeric, "interval", "interval");
437
+ }
438
+ }
439
+ else if (operator === "/") {
440
+ for (const numeric of numericOperatorTypes)
441
+ add("interval", numeric, "interval");
442
+ }
443
+ return candidates;
444
+ }
445
+ const builtInRangeFamilies = [
446
+ ["int4range", "int4multirange", "integer"],
447
+ ["int8range", "int8multirange", "bigint"],
448
+ ["numrange", "nummultirange", "numeric"],
449
+ ["tsrange", "tsmultirange", "timestamp"],
450
+ ["tstzrange", "tstzmultirange", "timestamptz"],
451
+ ["daterange", "datemultirange", "date"],
452
+ ];
453
+ function specialOperatorCandidates(operator) {
454
+ const candidates = [];
455
+ const add = (left, right, resultType) => {
456
+ if (candidates.some((candidate) => candidate.argumentTypes[0] === left &&
457
+ candidate.argumentTypes[1] === right &&
458
+ candidate.resultType === resultType))
459
+ return;
460
+ candidates.push({ value: operator, argumentTypes: [left, right], resultType });
461
+ };
462
+ for (const [range, multirange, element] of builtInRangeFamilies) {
463
+ if (operator === "@>") {
464
+ for (const [left, right] of [
465
+ [range, range],
466
+ [range, element],
467
+ [range, multirange],
468
+ [multirange, multirange],
469
+ [multirange, range],
470
+ [multirange, element],
471
+ ])
472
+ add(left, right, "boolean");
473
+ }
474
+ else if (operator === "<@") {
475
+ for (const [left, right] of [
476
+ [range, range],
477
+ [element, range],
478
+ [multirange, multirange],
479
+ [multirange, range],
480
+ [range, multirange],
481
+ [element, multirange],
482
+ ])
483
+ add(left, right, "boolean");
484
+ }
485
+ else if (["&&", "<<", ">>", "&<", "&>"].includes(operator)) {
486
+ for (const [left, right] of [
487
+ [range, range],
488
+ [multirange, multirange],
489
+ [range, multirange],
490
+ [multirange, range],
491
+ ])
492
+ add(left, right, "boolean");
493
+ }
494
+ else if (operator === "-\u007c-") {
495
+ for (const [left, right] of [
496
+ [range, range],
497
+ [multirange, multirange],
498
+ [range, multirange],
499
+ [multirange, range],
500
+ ])
501
+ add(left, right, "boolean");
502
+ }
503
+ else if (["+", "*", "-"].includes(operator)) {
504
+ add(range, range, range);
505
+ add(multirange, multirange, multirange);
506
+ }
507
+ }
508
+ const geometric = ["point", "box", "lseg", "line", "path", "polygon", "circle"];
509
+ const sameGeometric = (types, resultType) => {
510
+ for (const type of types)
511
+ add(type, type, resultType);
512
+ };
513
+ if (["+", "-", "*", "/"].includes(operator)) {
514
+ for (const type of ["point", "box", "path", "circle"])
515
+ add(type, "point", type);
516
+ if (operator === "+")
517
+ add("path", "path", "path");
518
+ }
519
+ else if (operator === "#") {
520
+ add("lseg", "lseg", "point");
521
+ add("line", "line", "point");
522
+ add("box", "box", "box");
523
+ }
524
+ else if (operator === "##") {
525
+ for (const [left, right] of [
526
+ ["point", "box"],
527
+ ["point", "lseg"],
528
+ ["point", "line"],
529
+ ["lseg", "box"],
530
+ ["lseg", "lseg"],
531
+ ["line", "lseg"],
532
+ ])
533
+ add(left, right, "point");
534
+ }
535
+ else if (operator === "<->") {
536
+ sameGeometric(geometric, "double precision");
537
+ for (const type of geometric) {
538
+ add("point", type, "double precision");
539
+ add(type, "point", "double precision");
540
+ }
541
+ for (const [left, right] of [
542
+ ["box", "lseg"],
543
+ ["lseg", "line"],
544
+ ["polygon", "circle"],
545
+ ]) {
546
+ add(left, right, "double precision");
547
+ add(right, left, "double precision");
548
+ }
549
+ }
550
+ else if (operator === "@>") {
551
+ for (const [left, right] of [
552
+ ["box", "point"],
553
+ ["box", "box"],
554
+ ["path", "point"],
555
+ ["polygon", "point"],
556
+ ["polygon", "polygon"],
557
+ ["circle", "point"],
558
+ ["circle", "circle"],
559
+ ])
560
+ add(left, right, "boolean");
561
+ }
562
+ else if (operator === "<@") {
563
+ for (const [left, right] of [
564
+ ["point", "box"],
565
+ ["point", "lseg"],
566
+ ["point", "line"],
567
+ ["point", "path"],
568
+ ["point", "polygon"],
569
+ ["point", "circle"],
570
+ ["box", "box"],
571
+ ["lseg", "box"],
572
+ ["lseg", "line"],
573
+ ["polygon", "polygon"],
574
+ ["circle", "circle"],
575
+ ])
576
+ add(left, right, "boolean");
577
+ }
578
+ else if (operator === "&&")
579
+ sameGeometric(["box", "polygon", "circle"], "boolean");
580
+ else if (operator === "<<" || operator === ">>")
581
+ sameGeometric(["point", "box", "polygon", "circle"], "boolean");
582
+ else if (["&<", "&>", "&<|", "|&>"].includes(operator))
583
+ sameGeometric(["box", "polygon", "circle"], "boolean");
584
+ else if (operator === "<<|" || operator === "|>>")
585
+ sameGeometric(["point", "box", "polygon", "circle"], "boolean");
586
+ else if (operator === "<^" || operator === ">^") {
587
+ add("box", "box", "boolean");
588
+ add("point", "point", "boolean");
589
+ }
590
+ else if (operator === "?#") {
591
+ for (const [left, right] of [
592
+ ["box", "box"],
593
+ ["lseg", "box"],
594
+ ["lseg", "lseg"],
595
+ ["lseg", "line"],
596
+ ["line", "box"],
597
+ ["line", "line"],
598
+ ["path", "path"],
599
+ ])
600
+ add(left, right, "boolean");
601
+ }
602
+ else if (operator === "?-" || operator === "?|")
603
+ add("point", "point", "boolean");
604
+ else if (operator === "?-|" || operator === "?||")
605
+ sameGeometric(["line", "lseg"], "boolean");
606
+ else if (operator === "~=")
607
+ sameGeometric(["point", "box", "polygon", "circle"], "boolean");
608
+ if (operator === "<<" || operator === ">>") {
609
+ for (const type of ["smallint", "integer", "bigint"])
610
+ add(type, "integer", type);
611
+ add("bit", "integer", "bit");
612
+ }
613
+ if (["<<", "<<=", ">>", ">>=", "&&"].includes(operator))
614
+ add("inet", "inet", "boolean");
615
+ if (operator === "&" || operator === "|") {
616
+ add("inet", "inet", "inet");
617
+ add("macaddr", "macaddr", "macaddr");
618
+ add("macaddr8", "macaddr8", "macaddr8");
619
+ }
620
+ if (operator === "+") {
621
+ add("inet", "bigint", "inet");
622
+ add("bigint", "inet", "inet");
623
+ add("money", "money", "money");
624
+ add("pg_lsn", "numeric", "pg_lsn");
625
+ add("numeric", "pg_lsn", "pg_lsn");
626
+ }
627
+ else if (operator === "-") {
628
+ add("inet", "bigint", "inet");
629
+ add("inet", "inet", "bigint");
630
+ add("jsonb", "text", "jsonb");
631
+ add("jsonb", "text[]", "jsonb");
632
+ add("jsonb", "integer", "jsonb");
633
+ add("money", "money", "money");
634
+ add("pg_lsn", "numeric", "pg_lsn");
635
+ add("pg_lsn", "pg_lsn", "numeric");
636
+ }
637
+ else if (operator === "*") {
638
+ for (const numeric of ["smallint", "integer", "bigint", "real", "double precision"]) {
639
+ add("money", numeric, "money");
640
+ add(numeric, "money", "money");
641
+ }
642
+ }
643
+ else if (operator === "/") {
644
+ for (const numeric of ["smallint", "integer", "bigint", "real", "double precision"])
645
+ add("money", numeric, "money");
646
+ add("money", "money", "double precision");
647
+ }
648
+ else if (operator === "#-")
649
+ add("jsonb", "text[]", "jsonb");
650
+ else if (operator === "@?")
651
+ add("jsonb", "jsonpath", "boolean");
652
+ else if (operator === "@@") {
653
+ add("jsonb", "jsonpath", "boolean");
654
+ add("tsvector", "tsquery", "boolean");
655
+ add("tsquery", "tsvector", "boolean");
656
+ add("text", "tsquery", "boolean");
657
+ }
658
+ else if (operator === "&&")
659
+ add("tsquery", "tsquery", "tsquery");
660
+ else if (operator === "||") {
661
+ add("text", "anynonarray", "text");
662
+ add("anynonarray", "text", "text");
663
+ add("bytea", "bytea", "bytea");
664
+ add("varbit", "varbit", "varbit");
665
+ add("jsonb", "jsonb", "jsonb");
666
+ add("tsvector", "tsvector", "tsvector");
667
+ add("tsquery", "tsquery", "tsquery");
668
+ }
669
+ else if (operator === "^@")
670
+ add("text", "text", "boolean");
671
+ if (comparisonOperators.has(operator)) {
672
+ add("tsvector", "tsvector", "boolean");
673
+ add("tsquery", "tsquery", "boolean");
674
+ }
675
+ return candidates;
676
+ }
677
+ function operatorCandidates(operator, schema) {
678
+ const cache = schema === undefined
679
+ ? defaultOperatorCandidates
680
+ : (operatorCandidatesBySchema.get(schema) ??
681
+ (() => {
682
+ const created = new Map();
683
+ operatorCandidatesBySchema.set(schema, created);
684
+ return created;
685
+ })());
686
+ const cached = cache.get(operator);
687
+ if (cached !== undefined)
688
+ return cached;
689
+ const extension = postgresExtensionOperators(schema)
690
+ .filter((candidate) => candidate.name.toUpperCase() === operator && candidate.argumentTypes.length === 2)
691
+ .map((candidate) => ({
692
+ value: operator,
693
+ argumentTypes: candidate.argumentTypes,
694
+ resultType: candidate.resultType,
695
+ }));
696
+ const rule = postgresCatalogOperatorRule(operator, schema);
697
+ const special = specialOperatorCandidates(operator);
698
+ let candidates;
699
+ if (rule === "numeric")
700
+ candidates = [
701
+ ...numericOperatorCandidates(operator),
702
+ ...temporalOperatorCandidates(operator),
703
+ ...special,
704
+ ...extension,
705
+ ];
706
+ else if (rule === "bitwise") {
707
+ candidates = [
708
+ ...["smallint", "integer", "bigint"].map((type) => ({
709
+ value: operator,
710
+ argumentTypes: [type, type],
711
+ resultType: type,
712
+ })),
713
+ { value: operator, argumentTypes: ["bit", "bit"], resultType: "bit" },
714
+ ...special,
715
+ ...extension,
716
+ ];
717
+ }
718
+ else if (rule === "concatenation") {
719
+ candidates = [
720
+ { value: operator, argumentTypes: ["text", "text"], resultType: "text" },
721
+ {
722
+ value: operator,
723
+ argumentTypes: ["anycompatiblearray", "anycompatiblearray"],
724
+ resultType: "anycompatiblearray",
725
+ },
726
+ { value: operator, argumentTypes: ["anycompatible", "anycompatiblearray"], resultType: "anycompatiblearray" },
727
+ { value: operator, argumentTypes: ["anycompatiblearray", "anycompatible"], resultType: "anycompatiblearray" },
728
+ ...special,
729
+ ...extension,
730
+ ];
731
+ }
732
+ else if (rule === "json" || rule === "json-text") {
733
+ const result = rule === "json-text" ? "text" : undefined;
734
+ const path = operator.startsWith("#") ? "text[]" : undefined;
735
+ candidates = [
736
+ ...["json", "jsonb"].flatMap((left) => (path === undefined ? ["integer", "text"] : [path]).map((right) => ({
737
+ value: operator,
738
+ argumentTypes: [left, right],
739
+ resultType: result ?? left,
740
+ }))),
741
+ ...special,
742
+ ...extension,
743
+ ];
744
+ }
745
+ else if (rule === "special" || rule !== "boolean")
746
+ candidates = [...special, ...extension];
747
+ else if (operator === "AND" || operator === "OR") {
748
+ candidates = [
749
+ { value: operator, argumentTypes: ["boolean", "boolean"], resultType: "boolean" },
750
+ ...special,
751
+ ...extension,
752
+ ];
753
+ }
754
+ else if (patternOperators.has(operator)) {
755
+ candidates = [
756
+ { value: operator, argumentTypes: ["text", "text"], resultType: "boolean" },
757
+ ...special,
758
+ ...extension,
759
+ ];
760
+ }
761
+ else if (operator === "?" || operator === "?&" || operator === "?|") {
762
+ candidates = [
763
+ {
764
+ value: operator,
765
+ argumentTypes: ["jsonb", operator === "?" ? "text" : "text[]"],
766
+ resultType: "boolean",
767
+ },
768
+ ...special,
769
+ ...extension,
770
+ ];
771
+ }
772
+ else if (operator === "@>" || operator === "<@" || operator === "&&") {
773
+ candidates = [
774
+ { value: operator, argumentTypes: ["anyarray", "anyarray"], resultType: "boolean" },
775
+ ...(operator === "&&" ? [] : [{ value: operator, argumentTypes: ["jsonb", "jsonb"], resultType: "boolean" }]),
776
+ ...special,
777
+ ...extension,
778
+ ];
779
+ }
780
+ else if (!comparisonOperators.has(operator))
781
+ candidates = extension;
782
+ else {
783
+ const categoryCandidates = ["numeric", "string", "datetime", "timespan", "bit-string", "network", "range"].flatMap((categoryName) => categoryPairs(categoryName, schema).map(([left, right]) => ({
784
+ value: operator,
785
+ argumentTypes: [left, right],
786
+ resultType: "boolean",
787
+ })));
788
+ candidates = [
789
+ ...categoryCandidates,
790
+ { value: operator, argumentTypes: ["boolean", "boolean"], resultType: "boolean" },
791
+ { value: operator, argumentTypes: ["uuid", "uuid"], resultType: "boolean" },
792
+ { value: operator, argumentTypes: ["bytea", "bytea"], resultType: "boolean" },
793
+ { value: operator, argumentTypes: ["jsonb", "jsonb"], resultType: "boolean" },
794
+ { value: operator, argumentTypes: ["pg_lsn", "pg_lsn"], resultType: "boolean" },
795
+ { value: operator, argumentTypes: ["tid", "tid"], resultType: "boolean" },
796
+ { value: operator, argumentTypes: ["anyenum", "anyenum"], resultType: "boolean" },
797
+ { value: operator, argumentTypes: ["anyarray", "anyarray"], resultType: "boolean" },
798
+ ...special,
799
+ ...extension,
800
+ ];
801
+ }
802
+ cache.set(operator, candidates);
803
+ return candidates;
804
+ }
805
+ /** Resolves PostgreSQL prefix operators through grammar-owned operator candidates. */
806
+ export function resolvePostgresUnaryOperator(operator, operand, schema) {
807
+ const normalizedOperator = operator.toUpperCase();
808
+ const builtins = normalizedOperator === "NOT"
809
+ ? [{ value: normalizedOperator, argumentTypes: ["boolean"], resultType: "boolean" }]
810
+ : normalizedOperator === "+" || normalizedOperator === "-"
811
+ ? categoryTypes("numeric", schema)
812
+ .filter((type) => numericOperatorTypes.has(type))
813
+ .map((type) => ({
814
+ value: normalizedOperator,
815
+ argumentTypes: [type],
816
+ resultType: type,
817
+ }))
818
+ : normalizedOperator === "~"
819
+ ? ["smallint", "integer", "bigint", "bit", "inet", "macaddr", "macaddr8"].map((type) => ({
820
+ value: normalizedOperator,
821
+ argumentTypes: [type],
822
+ resultType: type,
823
+ }))
824
+ : normalizedOperator === "!!"
825
+ ? [{ value: normalizedOperator, argumentTypes: ["tsquery"], resultType: "tsquery" }]
826
+ : normalizedOperator === "@"
827
+ ? [...numericOperatorTypes].map((type) => ({
828
+ value: normalizedOperator,
829
+ argumentTypes: [type],
830
+ resultType: type,
831
+ }))
832
+ : normalizedOperator === "|/" || normalizedOperator === "||/"
833
+ ? [
834
+ {
835
+ value: normalizedOperator,
836
+ argumentTypes: ["double precision"],
837
+ resultType: "double precision",
838
+ },
839
+ ]
840
+ : normalizedOperator === "@-@"
841
+ ? ["lseg", "path"].map((type) => ({
842
+ value: normalizedOperator,
843
+ argumentTypes: [type],
844
+ resultType: "double precision",
845
+ }))
846
+ : normalizedOperator === "@@"
847
+ ? ["box", "lseg", "polygon", "circle"].map((type) => ({
848
+ value: normalizedOperator,
849
+ argumentTypes: [type],
850
+ resultType: "point",
851
+ }))
852
+ : normalizedOperator === "#"
853
+ ? ["path", "polygon"].map((type) => ({
854
+ value: normalizedOperator,
855
+ argumentTypes: [type],
856
+ resultType: "integer",
857
+ }))
858
+ : normalizedOperator === "?-" || normalizedOperator === "?|"
859
+ ? ["line", "lseg"].map((type) => ({
860
+ value: normalizedOperator,
861
+ argumentTypes: [type],
862
+ resultType: "boolean",
863
+ }))
864
+ : [];
865
+ const extension = postgresExtensionOperators(schema)
866
+ .filter((candidate) => candidate.name.toUpperCase() === normalizedOperator && candidate.argumentTypes.length === 1)
867
+ .map((candidate) => ({
868
+ value: normalizedOperator,
869
+ argumentTypes: candidate.argumentTypes,
870
+ resultType: candidate.resultType,
871
+ }));
872
+ const candidates = [...builtins, ...extension];
873
+ if (operand === undefined && candidates.length !== 1) {
874
+ return candidates.length === 0 ? { kind: "none" } : { kind: "ambiguous" };
875
+ }
876
+ return resolvePostgresCandidates(candidates, [operand], schema);
877
+ }
878
+ /** Resolves built-in binary operators through the same candidate machinery as routine calls. */
879
+ export function resolvePostgresOperator(operator, left, right, schema) {
880
+ const normalizedOperator = operator.toUpperCase();
881
+ const cache = schema === undefined
882
+ ? defaultOperatorResolutions
883
+ : (operatorResolutionsBySchema.get(schema) ??
884
+ (() => {
885
+ const created = new Map();
886
+ operatorResolutionsBySchema.set(schema, created);
887
+ return created;
888
+ })());
889
+ const cacheKey = `${normalizedOperator}\0${left ?? "?"}\0${right ?? "?"}`;
890
+ const cached = cache.get(cacheKey);
891
+ if (cached !== undefined)
892
+ return cached;
893
+ const candidates = operatorCandidates(normalizedOperator, schema);
894
+ let inputs = [left, right];
895
+ if (left === undefined && right !== undefined)
896
+ inputs = [right, right];
897
+ else if (right === undefined && left !== undefined)
898
+ inputs = [left, left];
899
+ const assumedExact = resolvePostgresCandidates(candidates, inputs, schema);
900
+ const resolved = assumedExact.kind === "selected" || (left !== undefined && right !== undefined)
901
+ ? assumedExact
902
+ : resolvePostgresCandidates(candidates, [left, right], schema);
903
+ cache.set(cacheKey, resolved);
904
+ return resolved;
905
+ }
906
+ //# sourceMappingURL=type-resolution.js.map