sqllens 1.0.0 → 1.2.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 (244) hide show
  1. package/LICENSE +0 -10
  2. package/README.md +95 -85
  3. package/THIRD-PARTY-NOTICES.md +70 -5
  4. package/dist/api.d.ts +5 -3
  5. package/dist/api.js +17 -4
  6. package/dist/bigquery/behavior.d.ts +2 -0
  7. package/dist/bigquery/behavior.js +20 -0
  8. package/dist/bigquery/dot-path.d.ts +0 -2
  9. package/dist/bigquery/dot-path.js +0 -1
  10. package/dist/bigquery/fold.d.ts +8 -0
  11. package/dist/bigquery/fold.js +39 -0
  12. package/dist/bigquery/index.d.ts +7 -0
  13. package/dist/bigquery/index.js +10 -0
  14. package/dist/{infer/bigquery.d.ts → bigquery/infer.d.ts} +2 -2
  15. package/dist/{infer/bigquery.js → bigquery/infer.js} +4 -3
  16. package/dist/bigquery/lower.js +35 -12
  17. package/dist/bigquery/signatures.generated.d.ts +6 -0
  18. package/dist/bigquery/signatures.generated.js +1068 -0
  19. package/dist/completion/atn-walk.d.ts +13 -2
  20. package/dist/completion/atn-walk.js +13 -10
  21. package/dist/completion/complete.d.ts +4 -3
  22. package/dist/completion/complete.js +101 -45
  23. package/dist/completion/config.js +66 -0
  24. package/dist/completion/jinja-slot.d.ts +24 -0
  25. package/dist/completion/jinja-slot.js +126 -0
  26. package/dist/completion/parser-factory.d.ts +13 -1
  27. package/dist/completion/parser-factory.js +48 -0
  28. package/dist/databricks/behavior.d.ts +2 -0
  29. package/dist/databricks/behavior.js +19 -0
  30. package/dist/databricks/fold.d.ts +8 -0
  31. package/dist/databricks/fold.js +27 -0
  32. package/dist/databricks/index.d.ts +7 -0
  33. package/dist/databricks/index.js +10 -0
  34. package/dist/databricks/infer.d.ts +6 -0
  35. package/dist/databricks/infer.js +638 -0
  36. package/dist/databricks/signatures.generated.d.ts +6 -0
  37. package/dist/databricks/signatures.generated.js +1745 -0
  38. package/dist/derived-dialects.js +19 -1
  39. package/dist/dialect-behavior/behavior.d.ts +26 -0
  40. package/dist/dialect-behavior/behavior.js +1 -0
  41. package/dist/dialect-behavior/carrier.d.ts +5 -0
  42. package/dist/dialect-behavior/carrier.js +5 -0
  43. package/dist/dialect-behavior/coerce-rules.d.ts +7 -0
  44. package/dist/dialect-behavior/coerce-rules.js +69 -0
  45. package/dist/dialect-behavior/public-fold.d.ts +6 -0
  46. package/dist/dialect-behavior/public-fold.js +9 -0
  47. package/dist/dialect-behavior/registry.d.ts +6 -0
  48. package/dist/dialect-behavior/registry.js +34 -0
  49. package/dist/dialect-symbols.js +22 -17
  50. package/dist/dialect.d.ts +2 -2
  51. package/dist/document/document.d.ts +1 -1
  52. package/dist/document/document.js +8 -7
  53. package/dist/duckdb/behavior.d.ts +2 -0
  54. package/dist/duckdb/behavior.js +21 -0
  55. package/dist/duckdb/fold.d.ts +8 -0
  56. package/dist/duckdb/fold.js +29 -0
  57. package/dist/duckdb/index.d.ts +7 -0
  58. package/dist/duckdb/index.js +10 -0
  59. package/dist/{infer/duckdb.d.ts → duckdb/infer.d.ts} +2 -2
  60. package/dist/{infer/duckdb.js → duckdb/infer.js} +4 -3
  61. package/dist/duckdb/lower.js +47 -15
  62. package/dist/duckdb/signatures.generated.d.ts +6 -0
  63. package/dist/duckdb/signatures.generated.js +1072 -0
  64. package/dist/generated/bigquery/GoogleSQLParser.js +0 -7060
  65. package/dist/generated/databricks/DatabricksParser.js +0 -4800
  66. package/dist/generated/duckdb/DuckdbParser.js +0 -9100
  67. package/dist/generated/minijinja/MinijinjaParser.js +0 -380
  68. package/dist/generated/mysql/MysqlLexer.js +7357 -0
  69. package/dist/generated/mysql/MysqlParser.js +78520 -0
  70. package/dist/generated/postgres/PostgresParser.js +0 -8530
  71. package/dist/generated/redshift/RedshiftParser.js +0 -10970
  72. package/dist/generated/snowflake/SnowflakeParser.js +0 -7320
  73. package/dist/generated/sqlite/SqliteLexer.js +945 -0
  74. package/dist/generated/sqlite/SqliteParser.js +14682 -0
  75. package/dist/generated/trino/TrinoParser.js +0 -3770
  76. package/dist/generated/tsql/TSqlParser.js +0 -8420
  77. package/dist/ident/fold.d.ts +24 -15
  78. package/dist/ident/fold.js +12 -145
  79. package/dist/index.d.ts +6 -2
  80. package/dist/index.js +14 -8
  81. package/dist/infer/functions.d.ts +22 -11
  82. package/dist/infer/functions.js +26 -888
  83. package/dist/infer/infer.js +16 -14
  84. package/dist/infer/nullability.js +3 -4
  85. package/dist/infer/types.d.ts +1 -1
  86. package/dist/infer/types.js +7 -7
  87. package/dist/ir/ir.d.ts +26 -17
  88. package/dist/ir/part-span.d.ts +16 -1
  89. package/dist/ir/part-span.js +38 -10
  90. package/dist/ir/span.js +0 -2
  91. package/dist/ir/walk.js +3 -3
  92. package/dist/lineage/hops.js +13 -10
  93. package/dist/lineage/lineage.js +10 -7
  94. package/dist/minijinja/apply-tags.d.ts +14 -7
  95. package/dist/minijinja/apply-tags.js +66 -121
  96. package/dist/minijinja/parse.js +6 -6
  97. package/dist/minijinja/tag-ast.d.ts +29 -36
  98. package/dist/minijinja/tag-ast.js +210 -90
  99. package/dist/mysql/behavior.d.ts +2 -0
  100. package/dist/mysql/behavior.js +21 -0
  101. package/dist/mysql/fold.d.ts +8 -0
  102. package/dist/mysql/fold.js +49 -0
  103. package/dist/mysql/index.d.ts +7 -0
  104. package/dist/mysql/index.js +10 -0
  105. package/dist/mysql/infer.d.ts +20 -0
  106. package/dist/mysql/infer.js +156 -0
  107. package/dist/mysql/lower.d.ts +13 -0
  108. package/dist/mysql/lower.js +1443 -0
  109. package/dist/mysql/parse.d.ts +10 -0
  110. package/dist/mysql/parse.js +70 -0
  111. package/dist/mysql/signatures.generated.d.ts +6 -0
  112. package/dist/mysql/signatures.generated.js +508 -0
  113. package/dist/postgres/behavior.d.ts +2 -0
  114. package/dist/postgres/behavior.js +19 -0
  115. package/dist/postgres/fold.d.ts +8 -0
  116. package/dist/postgres/fold.js +30 -0
  117. package/dist/postgres/index.d.ts +7 -0
  118. package/dist/postgres/index.js +10 -0
  119. package/dist/{infer/postgres.d.ts → postgres/infer.d.ts} +2 -2
  120. package/dist/{infer/postgres.js → postgres/infer.js} +4 -3
  121. package/dist/postgres/lower.js +2 -2
  122. package/dist/postgres/signatures.generated.d.ts +6 -0
  123. package/dist/postgres/signatures.generated.js +2973 -0
  124. package/dist/qualify/check-calls.js +80 -134
  125. package/dist/qualify/qualify.js +16 -14
  126. package/dist/qualify/schema-provider.js +2 -2
  127. package/dist/qualify/schema.js +3 -3
  128. package/dist/qualify/template-provider.d.ts +45 -12
  129. package/dist/qualify/template-provider.js +69 -38
  130. package/dist/redshift/behavior.d.ts +2 -0
  131. package/dist/redshift/behavior.js +19 -0
  132. package/dist/redshift/fold.d.ts +8 -0
  133. package/dist/redshift/fold.js +31 -0
  134. package/dist/redshift/index.d.ts +7 -0
  135. package/dist/redshift/index.js +10 -0
  136. package/dist/{infer/redshift.d.ts → redshift/infer.d.ts} +2 -2
  137. package/dist/{infer/redshift.js → redshift/infer.js} +4 -3
  138. package/dist/redshift/lower.js +2 -2
  139. package/dist/redshift/signatures.generated.d.ts +6 -0
  140. package/dist/redshift/signatures.generated.js +757 -0
  141. package/dist/references/references.js +17 -12
  142. package/dist/scope/like-pattern.d.ts +2 -0
  143. package/dist/scope/like-pattern.js +15 -0
  144. package/dist/scope/scope.d.ts +5 -5
  145. package/dist/scope/scope.js +48 -42
  146. package/dist/sema/resolve.js +17 -12
  147. package/dist/session.d.ts +2 -2
  148. package/dist/signature/signature.d.ts +14 -6
  149. package/dist/signature/signature.js +30 -22
  150. package/dist/signature/signatures.d.ts +14 -12
  151. package/dist/signature/signatures.js +42 -582
  152. package/dist/snowflake/behavior.d.ts +2 -0
  153. package/dist/snowflake/behavior.js +22 -0
  154. package/dist/snowflake/fold.d.ts +8 -0
  155. package/dist/snowflake/fold.js +25 -0
  156. package/dist/snowflake/index.d.ts +7 -0
  157. package/dist/snowflake/index.js +10 -0
  158. package/dist/{infer/snowflake.d.ts → snowflake/infer.d.ts} +2 -2
  159. package/dist/{infer/snowflake.js → snowflake/infer.js} +4 -3
  160. package/dist/snowflake/lower.js +59 -19
  161. package/dist/snowflake/signatures.generated.d.ts +6 -0
  162. package/dist/snowflake/signatures.generated.js +2080 -0
  163. package/dist/sqlite/behavior.d.ts +2 -0
  164. package/dist/sqlite/behavior.js +19 -0
  165. package/dist/sqlite/fold.d.ts +8 -0
  166. package/dist/sqlite/fold.js +41 -0
  167. package/dist/sqlite/index.d.ts +7 -0
  168. package/dist/sqlite/index.js +10 -0
  169. package/dist/sqlite/infer.d.ts +12 -0
  170. package/dist/sqlite/infer.js +122 -0
  171. package/dist/sqlite/lower.d.ts +11 -0
  172. package/dist/sqlite/lower.js +1093 -0
  173. package/dist/sqlite/parse.d.ts +10 -0
  174. package/dist/sqlite/parse.js +70 -0
  175. package/dist/sqlite/signatures.generated.d.ts +6 -0
  176. package/dist/sqlite/signatures.generated.js +277 -0
  177. package/dist/symbols/symbols.js +14 -12
  178. package/dist/token/classify.js +31 -0
  179. package/dist/token/tokenize.js +4 -0
  180. package/dist/trino/behavior.d.ts +2 -0
  181. package/dist/trino/behavior.js +21 -0
  182. package/dist/trino/fold.d.ts +8 -0
  183. package/dist/trino/fold.js +39 -0
  184. package/dist/trino/index.d.ts +7 -0
  185. package/dist/trino/index.js +10 -0
  186. package/dist/{infer/trino.d.ts → trino/infer.d.ts} +2 -2
  187. package/dist/{infer/trino.js → trino/infer.js} +4 -3
  188. package/dist/trino/lower.js +5 -5
  189. package/dist/trino/signatures.generated.d.ts +6 -0
  190. package/dist/trino/signatures.generated.js +968 -0
  191. package/dist/tsql/behavior.d.ts +2 -0
  192. package/dist/tsql/behavior.js +20 -0
  193. package/dist/tsql/fold.d.ts +8 -0
  194. package/dist/tsql/fold.js +34 -0
  195. package/dist/tsql/index.d.ts +7 -0
  196. package/dist/tsql/index.js +10 -0
  197. package/dist/tsql/infer.d.ts +16 -0
  198. package/dist/tsql/infer.js +289 -0
  199. package/dist/tsql/lower.js +4 -4
  200. package/dist/tsql/signatures.generated.d.ts +6 -0
  201. package/dist/tsql/signatures.generated.js +640 -0
  202. package/package.json +15 -11
  203. package/dist/generated/bigquery/GoogleSQLLexer.d.ts +0 -407
  204. package/dist/generated/bigquery/GoogleSQLParser.d.ts +0 -9558
  205. package/dist/generated/bigquery/GoogleSQLParserListener.d.ts +0 -7777
  206. package/dist/generated/bigquery/GoogleSQLParserListener.js +0 -7070
  207. package/dist/generated/databricks/DatabricksLexer.d.ts +0 -566
  208. package/dist/generated/databricks/DatabricksParser.d.ts +0 -7771
  209. package/dist/generated/databricks/DatabricksParserListener.d.ts +0 -5737
  210. package/dist/generated/databricks/DatabricksParserListener.js +0 -5256
  211. package/dist/generated/duckdb/DuckdbLexer.d.ts +0 -691
  212. package/dist/generated/duckdb/DuckdbParser.d.ts +0 -13932
  213. package/dist/generated/duckdb/DuckdbParserListener.d.ts +0 -10049
  214. package/dist/generated/duckdb/DuckdbParserListener.js +0 -9138
  215. package/dist/generated/minijinja/MinijinjaLexer.d.ts +0 -108
  216. package/dist/generated/minijinja/MinijinjaParser.d.ts +0 -604
  217. package/dist/generated/minijinja/MinijinjaParserListener.d.ts +0 -449
  218. package/dist/generated/minijinja/MinijinjaParserListener.js +0 -410
  219. package/dist/generated/postgres/PostgresLexer.d.ts +0 -663
  220. package/dist/generated/postgres/PostgresParser.d.ts +0 -12963
  221. package/dist/generated/postgres/PostgresParserListener.d.ts +0 -9408
  222. package/dist/generated/postgres/PostgresParserListener.js +0 -8554
  223. package/dist/generated/redshift/RedshiftLexer.d.ts +0 -954
  224. package/dist/generated/redshift/RedshiftParser.d.ts +0 -16939
  225. package/dist/generated/redshift/RedshiftParserListener.d.ts +0 -12092
  226. package/dist/generated/redshift/RedshiftParserListener.js +0 -10994
  227. package/dist/generated/snowflake/SnowflakeLexer.d.ts +0 -1046
  228. package/dist/generated/snowflake/SnowflakeParser.d.ts +0 -14196
  229. package/dist/generated/snowflake/SnowflakeParserListener.d.ts +0 -8063
  230. package/dist/generated/snowflake/SnowflakeParserListener.js +0 -7330
  231. package/dist/generated/trino/TrinoLexer.d.ts +0 -381
  232. package/dist/generated/trino/TrinoParser.d.ts +0 -5340
  233. package/dist/generated/trino/TrinoParserListener.d.ts +0 -4704
  234. package/dist/generated/trino/TrinoParserListener.js +0 -4326
  235. package/dist/generated/tsql/TSqlLexer.d.ts +0 -1278
  236. package/dist/generated/tsql/TSqlParser.d.ts +0 -17267
  237. package/dist/generated/tsql/TSqlParserListener.d.ts +0 -9697
  238. package/dist/generated/tsql/TSqlParserListener.js +0 -8854
  239. package/dist/infer/dialect.d.ts +0 -21
  240. package/dist/infer/dialect.js +0 -74
  241. package/dist/infer/literals.d.ts +0 -6
  242. package/dist/infer/literals.js +0 -44
  243. package/dist/signature/generated/tsql.d.ts +0 -3
  244. package/dist/signature/generated/tsql.js +0 -260
@@ -1,10 +1,14 @@
1
1
  import { nodeAt } from "../document/node-at.js";
2
- import { displayName, foldIdentifier, foldTableName } from "../ident/fold.js";
2
+ import { behaviorOf } from "../dialect-behavior/carrier.js";
3
+ import { resolveBehavior } from "../dialect-behavior/registry.js";
3
4
  import { endPosition } from "../ir/span.js";
4
5
  import { originsOf } from "../lineage/lineage.js";
5
6
  import { OPEN_PROVIDER } from "../qualify/template-provider.js";
6
7
  import { resolveColumnRef, resolveColumnSource } from "../sema/resolve.js";
7
- const originKey = (o, dialect) => `${foldTableName(o.table, dialect).join(".")}.${foldIdentifier(o.column, dialect)}`;
8
+ const originKey = (o, dialect) => {
9
+ const b = resolveBehavior(dialect);
10
+ return `${b.foldTableName(o.table).join(".")}.${b.fold(o.column)}`;
11
+ };
8
12
  /**
9
13
  * Find the declaration + every occurrence of the symbol under `offset`. Schema-free works for
10
14
  * in-query columns and CTE/alias/source names; a base-table column's cross-boundary identity
@@ -27,7 +31,7 @@ function compute(scopes, offset, schema, ast) {
27
31
  const id = columnIdentity(hit.scope, ref, schema);
28
32
  const raw = hit.expr.parts[hit.expr.parts.length - 1] ?? "";
29
33
  if (id)
30
- return collectColumn(scopes, id, schema, displayName(raw, scopes.root.dialect));
34
+ return collectColumn(scopes, id, schema, behaviorOf(scopes.root).displayName(raw));
31
35
  }
32
36
  // 2. Else: a NAME under the cursor (a CTE name, a source/table name, a source alias). Find the
33
37
  // smallest declaring cst that covers the offset, keyed by its declaring scope.
@@ -46,13 +50,13 @@ function columnIdentity(scope, ref, schema) {
46
50
  return {
47
51
  tag: "origins",
48
52
  keys: new Set(origins.map((o) => originKey(o, d))),
49
- column: foldIdentifier(last ?? "", d),
53
+ column: resolveBehavior(d).fold(last ?? ""),
50
54
  };
51
55
  }
52
56
  // Schema-free / no origin: bind to the in-query source and key on (source object, column).
53
57
  const bySource = resolveColumnSource(scope, ref.parts, schema) ?? boundColumn(scope, ref);
54
58
  if (bySource)
55
- return { tag: "source", source: bySource.source, column: foldIdentifier(bySource.column, d) };
59
+ return { tag: "source", source: bySource.source, column: resolveBehavior(d).fold(bySource.column) };
56
60
  return undefined;
57
61
  }
58
62
  /** Schema-free bind via the unified binder, normalized to the (source, column) shape. */
@@ -72,7 +76,7 @@ function columnMatches(id, scope, ref, schema) {
72
76
  }
73
77
  // source identity: same ResolvedSource object + same column name
74
78
  const b = resolveColumnSource(scope, ref.parts, schema) ?? boundColumn(scope, ref);
75
- return b !== undefined && b.source === id.source && foldIdentifier(b.column, scope.dialect) === id.column;
79
+ return b !== undefined && b.source === id.source && behaviorOf(scope).fold(b.column) === id.column;
76
80
  }
77
81
  function collectColumn(scopes, id, schema, symbol) {
78
82
  const occ = [];
@@ -113,7 +117,7 @@ function columnDeclaration(root, id, schema) {
113
117
  continue;
114
118
  if (p.name === undefined)
115
119
  continue;
116
- if (foldIdentifier(p.name, scope.dialect) !== want)
120
+ if (behaviorOf(scope).fold(p.name) !== want)
117
121
  continue;
118
122
  // This projection produces a column of the target name. Confirm it shares the identity
119
123
  // by resolving the projection's own column refs — for `origins` identity check overlap,
@@ -188,7 +192,8 @@ function declCstFor(scope, src) {
188
192
  }
189
193
  function collectName(scopes, hit) {
190
194
  const dialect = scopes.root.dialect;
191
- const target = foldIdentifier(hit.name, dialect);
195
+ const b = resolveBehavior(dialect);
196
+ const target = b.fold(hit.name);
192
197
  const occ = [];
193
198
  const seen = new Set();
194
199
  const add = (cst, role) => {
@@ -217,7 +222,7 @@ function collectName(scopes, hit) {
217
222
  if (src.kind === "relation" || src.kind === "pivot")
218
223
  continue;
219
224
  const n = sourceName(src);
220
- if (n !== undefined && foldIdentifier(n, dialect) === target) {
225
+ if (n !== undefined && b.fold(n) === target) {
221
226
  const cst = sourceCst(src);
222
227
  // Don't double-count the declaration cst as a reference.
223
228
  if (cst && cst !== declCst)
@@ -226,7 +231,7 @@ function collectName(scopes, hit) {
226
231
  // An alias use also references the name when the symbol IS the alias.
227
232
  if (hit.kind === "alias") {
228
233
  const a = aliasName(src);
229
- if (a !== undefined && foldIdentifier(a, dialect) === target)
234
+ if (a !== undefined && b.fold(a) === target)
230
235
  add(sourceAliasCst(src), "reference");
231
236
  }
232
237
  }
@@ -235,7 +240,7 @@ function collectName(scopes, hit) {
235
240
  };
236
241
  visit(scopes.root);
237
242
  return {
238
- symbol: displayName(hit.name, dialect),
243
+ symbol: b.displayName(hit.name),
239
244
  kind: hit.kind,
240
245
  declaration: declCst ? spanOf(declCst) : undefined,
241
246
  occurrences: occ,
@@ -249,7 +254,7 @@ function cteDefCst(root, target) {
249
254
  const visit = (scope) => {
250
255
  for (const [name, cteRef] of scope.ctes) {
251
256
  // Map keys are already folded; the def name is raw and folds here.
252
- if (name === target || foldIdentifier(cteRef.def.name, scope.dialect) === target) {
257
+ if (name === target || behaviorOf(scope).fold(cteRef.def.name) === target) {
253
258
  found = found ?? cteRef.def.cst;
254
259
  }
255
260
  }
@@ -0,0 +1,2 @@
1
+ /** SQL LIKE pattern to an anchored case-insensitive RegExp (`%` to `.*`, `_` to `.`). */
2
+ export declare function likePatternToRegExp(pattern: string): RegExp;
@@ -0,0 +1,15 @@
1
+ // SQL LIKE/ILIKE pattern matching. A leaf module (no scope/IR imports) so the dialect-behavior
2
+ // registry can depend on it without pulling in scope.ts — which imports the behavior carrier, which
3
+ // imports the registry (the cycle this split breaks).
4
+ //
5
+ // NOTE: LIKE pattern semantics are dialect-specific (T-SQL adds `[a-c]` / `[^…]` character classes and
6
+ // an ESCAPE clause; Postgres/Snowflake treat `[` as a literal). This shared `%`/`_` translation is the
7
+ // current floor, exposed per-dialect via DialectBehavior.likeMatch so a dialect can override it later.
8
+ /** SQL LIKE pattern to an anchored case-insensitive RegExp (`%` to `.*`, `_` to `.`). */
9
+ export function likePatternToRegExp(pattern) {
10
+ const escaped = pattern
11
+ .replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
12
+ .replace(/%/g, ".*")
13
+ .replace(/_/g, ".");
14
+ return new RegExp(`^${escaped}$`, "i");
15
+ }
@@ -1,5 +1,6 @@
1
1
  import type { ColumnRef, CteDef, GraphTableSource, LateralViewSource, PipeStage, PivotInfo, QueryBody, QueryExpr, SubquerySource, TableSource, UnpivotInfo } from "../ir/ir.js";
2
2
  import type { StatementCategory } from "../ir/statement.js";
3
+ import { likePatternToRegExp } from "./like-pattern.js";
3
4
  export interface ScopeTree {
4
5
  /** Discriminant tag — lets api.ts's `isScopeTree` identify a ScopeTree structurally
5
6
  * instead of shape-sniffing `root`/`statement`. */
@@ -126,7 +127,7 @@ export declare function splitColumnRefInScope(scope: Scope, parts: string[]): Sp
126
127
  * the unified binder (src/sema/resolve.ts) for the projection-alias fallback. */
127
128
  export declare function aliasVisibleClause(clause: ColumnRef["clause"] | undefined): boolean;
128
129
  export declare function matchesProjectionAlias(scope: Scope, name: string): boolean;
129
- export declare function applyPivotCols(base: string[], p: PivotInfo, dialect?: string): string[];
130
+ export declare function applyPivotCols(base: string[], p: PivotInfo, dialect?: string): string[] | "unknown";
130
131
  export declare function applyUnpivotCols(base: string[], u: UnpivotInfo, dialect?: string): string[];
131
132
  /** `UNION BY NAME` output: left columns in order, then right-only columns appended. */
132
133
  export declare function mergeByName(left: string[] | "unknown", right: string[] | "unknown", dialect?: string): string[] | "unknown";
@@ -140,15 +141,14 @@ export declare function applyStarModifiers(cols: string[], star: {
140
141
  to: string;
141
142
  }[];
142
143
  }, dialect?: string): string[];
143
- /** SQL LIKE pattern → an anchored case-insensitive RegExp (`%` → `.*`, `_` → `.`). */
144
- export declare function likePatternToRegExp(pattern: string): RegExp;
144
+ export { likePatternToRegExp };
145
145
  /** The columns a resolved source exposes, or "unknown" when it needs a schema (a bare table).
146
146
  * Exported for the unified binder's schema-free path (src/sema/resolve.ts). */
147
- export declare function sourceOutputs(src: ResolvedSource): string[] | "unknown";
147
+ export declare function sourceOutputs(src: ResolvedSource, dialect: string): string[] | "unknown";
148
148
  /** The reshaped columns of an aliased PIVOT/UNPIVOT source: its base columns (via `cols`) with the
149
149
  * pivot/unpivot transform applied. "unknown" if any base relation's columns need a schema we lack.
150
150
  * Shared by the schema-free scope path and the schema-fed qualify / resolve / lineage passes (each
151
151
  * passes its own column resolver), so an aliased pivot exposes the same reshaped set everywhere. */
152
152
  export declare function pivotSourceOutputs(src: Extract<ResolvedSource, {
153
153
  kind: "pivot";
154
- }>, cols: (s: ResolvedSource) => string[] | "unknown"): string[] | "unknown";
154
+ }>, cols: (s: ResolvedSource) => string[] | "unknown", dialect: string | undefined): string[] | "unknown";
@@ -1,4 +1,6 @@
1
- import { foldIdentifier } from "../ident/fold.js";
1
+ import { behaviorOf } from "../dialect-behavior/carrier.js";
2
+ import { resolveBehavior } from "../dialect-behavior/registry.js";
3
+ import { likePatternToRegExp } from "./like-pattern.js";
2
4
  export function resolveScopes(query, dialect) {
3
5
  const d = dialect ?? query.dialect;
4
6
  if (!d)
@@ -15,11 +17,12 @@ export function resolveScopes(query, dialect) {
15
17
  * or the table fold (these differ only for BigQuery's case-preserving table identifiers).
16
18
  */
17
19
  export function splitColumnRef(parts, isSource, dialect) {
20
+ const b = resolveBehavior(dialect);
18
21
  const keyOf = (part) => {
19
- const k = foldIdentifier(part, dialect);
22
+ const k = b.fold(part);
20
23
  if (isSource(k))
21
24
  return k;
22
- const kt = foldIdentifier(part, dialect, "table");
25
+ const kt = b.fold(part, "table");
23
26
  return kt !== k && isSource(kt) ? kt : undefined;
24
27
  };
25
28
  // `schema.table.col[.field…]` — the 2-token qualifier is keyed by the table (its last part).
@@ -54,8 +57,9 @@ export function aliasVisibleClause(clause) {
54
57
  return clause === "groupBy" || clause === "having" || clause === "qualify" || clause === "orderBy";
55
58
  }
56
59
  export function matchesProjectionAlias(scope, name) {
57
- const n = foldIdentifier(name, scope.dialect);
58
- return aliasNames(scope).some((a) => foldIdentifier(a, scope.dialect) === n);
60
+ const b = behaviorOf(scope);
61
+ const n = b.fold(name);
62
+ return aliasNames(scope).some((a) => b.fold(a) === n);
59
63
  }
60
64
  /** The output alias names of a scope — a select's projection names, or (for a set op) the
61
65
  * left branch's, since a union's output columns come from its first branch. */
@@ -90,7 +94,7 @@ function buildQueryScope(query, parent, dialect) {
90
94
  // Declared column aliases (WITH c (x, y) AS …) rename what the CTE exposes.
91
95
  if (cte.columnAliases)
92
96
  cteScope.outputs = cte.columnAliases;
93
- scope.ctes.set(foldIdentifier(cte.name, scope.dialect), { def: cte, scope: cteScope });
97
+ scope.ctes.set(behaviorOf(scope).fold(cte.name), { def: cte, scope: cteScope });
94
98
  scope.children.push(cteScope);
95
99
  }
96
100
  fillScope(scope);
@@ -126,7 +130,7 @@ function fillScope(scope) {
126
130
  const pivotAlias = body.pivot?.alias ?? body.unpivot?.alias;
127
131
  if (pivotAlias) {
128
132
  const base = body.from.map((source) => resolveSource(scope, source));
129
- scope.sources.set(foldIdentifier(pivotAlias, scope.dialect), {
133
+ scope.sources.set(behaviorOf(scope).fold(pivotAlias), {
130
134
  kind: "pivot",
131
135
  alias: pivotAlias,
132
136
  base,
@@ -213,7 +217,7 @@ function buildStageScope(pipeScope, stage, incoming) {
213
217
  const cteScope = buildQueryScope(cte.body, ss);
214
218
  if (cte.columnAliases)
215
219
  cteScope.outputs = cte.columnAliases;
216
- ss.ctes.set(foldIdentifier(cte.name, ss.dialect), { def: cte, scope: cteScope });
220
+ ss.ctes.set(behaviorOf(ss).fold(cte.name), { def: cte, scope: cteScope });
217
221
  ss.children.push(cteScope);
218
222
  }
219
223
  }
@@ -285,7 +289,7 @@ function buildGraphScope(parent, src) {
285
289
  alias: el.variable,
286
290
  cst: el.variableCst ?? el.cst,
287
291
  };
288
- scope.sources.set(foldIdentifier(el.variable, scope.dialect), {
292
+ scope.sources.set(behaviorOf(scope).fold(el.variable), {
289
293
  kind: "table",
290
294
  name: [el.variable],
291
295
  source: ts,
@@ -324,13 +328,13 @@ function stageOutputsFree(stage, incoming, scope) {
324
328
  case "drop":
325
329
  if (incoming === "unknown")
326
330
  return "unknown";
327
- return incoming.filter((c) => !stage.drop.some((d) => foldIdentifier(d, scope.dialect) === foldIdentifier(c, scope.dialect)));
331
+ return incoming.filter((c) => !stage.drop.some((d) => behaviorOf(scope).fold(d) === behaviorOf(scope).fold(c)));
328
332
  case "rename":
329
333
  if (incoming === "unknown")
330
334
  return "unknown";
331
335
  return applyRenameList(incoming, stage.renames, scope.dialect);
332
336
  case "select":
333
- return projectionOutputsFree(stage.projections, incoming);
337
+ return projectionOutputsFree(stage.projections, incoming, scope.dialect);
334
338
  case "aggregate":
335
339
  return aggregateOutputsFree(stage, incoming);
336
340
  case "extend":
@@ -348,7 +352,7 @@ function stageOutputsFree(stage, incoming, scope) {
348
352
  }
349
353
  /** Project a star-or-named list against the incoming columns (schema-free: incoming is the only source,
350
354
  * so a qualified `t.*` or an anonymous expression yields "unknown"). */
351
- function projectionOutputsFree(projections, incoming) {
355
+ function projectionOutputsFree(projections, incoming, dialect) {
352
356
  if (projections.length === 0)
353
357
  return "unknown";
354
358
  const names = [];
@@ -359,7 +363,7 @@ function projectionOutputsFree(projections, incoming) {
359
363
  const star = p.expr.kind === "star" ? p.expr : undefined;
360
364
  if (star?.qualifier)
361
365
  return "unknown";
362
- names.push(...(star ? applyStarModifiers(incoming, star) : incoming));
366
+ names.push(...(star ? applyStarModifiers(incoming, star, dialect) : incoming));
363
367
  }
364
368
  else if (p.name !== undefined) {
365
369
  names.push(p.name);
@@ -395,8 +399,9 @@ function simpleProjNames(projections) {
395
399
  return names;
396
400
  }
397
401
  function applyRenameList(cols, renames, dialect) {
398
- const map = new Map(renames.map((r) => [foldIdentifier(r.from, dialect), r.to]));
399
- return cols.map((c) => map.get(foldIdentifier(c, dialect)) ?? c);
402
+ const b = resolveBehavior(dialect);
403
+ const map = new Map(renames.map((r) => [b.fold(r.from), r.to]));
404
+ return cols.map((c) => map.get(b.fold(c)) ?? c);
400
405
  }
401
406
  /** A select's output columns, accounting for a PIVOT/UNPIVOT transforming the FROM relation. */
402
407
  function computeOutputs(scope, body) {
@@ -412,7 +417,7 @@ function computeOutputs(scope, body) {
412
417
  function baseRelationColumns(scope) {
413
418
  for (const src of scope.sources.values()) {
414
419
  if (src.kind !== "lateral")
415
- return sourceOutputs(src);
420
+ return sourceOutputs(src, scope.dialect);
416
421
  }
417
422
  return "unknown";
418
423
  }
@@ -421,12 +426,15 @@ function baseRelationColumns(scope) {
421
426
  // in scope.outputs). PIVOT consumes the FOR + aggregate columns and adds the IN-list value columns;
422
427
  // UNPIVOT consumes the IN-list columns and adds the name + value columns; both keep the passthrough rest.
423
428
  export function applyPivotCols(base, p, dialect) {
424
- const fold = (n) => foldIdentifier(n, dialect);
429
+ // Data-dependent pivot (no static IN-list): output columns are not enumerable — never guess.
430
+ if (p.dynamic)
431
+ return "unknown";
432
+ const fold = (n) => resolveBehavior(dialect).fold(n);
425
433
  const consumed = new Set([...p.forColumns, ...p.aggColumns].map(fold));
426
434
  return [...base.filter((c) => !consumed.has(fold(c))), ...p.values];
427
435
  }
428
436
  export function applyUnpivotCols(base, u, dialect) {
429
- const fold = (n) => foldIdentifier(n, dialect);
437
+ const fold = (n) => resolveBehavior(dialect).fold(n);
430
438
  const removed = new Set(u.removed.map(fold));
431
439
  return [...base.filter((c) => !removed.has(fold(c))), u.nameColumn, u.valueColumn];
432
440
  }
@@ -442,21 +450,23 @@ function pivotOutputs(scope, p) {
442
450
  export function mergeByName(left, right, dialect) {
443
451
  if (left === "unknown" || right === "unknown")
444
452
  return "unknown";
445
- const seen = new Set(left.map((c) => foldIdentifier(c, dialect)));
446
- return [...left, ...right.filter((c) => !seen.has(foldIdentifier(c, dialect)))];
453
+ const b = resolveBehavior(dialect);
454
+ const seen = new Set(left.map((c) => b.fold(c)));
455
+ return [...left, ...right.filter((c) => !seen.has(b.fold(c)))];
447
456
  }
448
457
  /** Apply a star node's modifiers to an expansion: EXCLUDE/EXCEPT removes, ILIKE filters by
449
458
  * pattern, RENAME renames (REPLACE keeps name and position — no expansion change). */
450
459
  export function applyStarModifiers(cols, star, dialect) {
451
- const fold = (n) => foldIdentifier(n, dialect);
460
+ const fold = (n) => resolveBehavior(dialect).fold(n);
452
461
  let out = cols;
453
462
  if (star.exclude) {
454
463
  const removed = new Set(star.exclude.map(fold));
455
464
  out = out.filter((c) => !removed.has(fold(c)));
456
465
  }
457
466
  if (star.ilike !== undefined) {
458
- const rx = likePatternToRegExp(star.ilike);
459
- out = out.filter((c) => rx.test(fold(c)));
467
+ const b = resolveBehavior(dialect);
468
+ const pat = star.ilike;
469
+ out = out.filter((c) => b.likeMatch(pat, fold(c)));
460
470
  }
461
471
  if (star.rename) {
462
472
  const renames = new Map(star.rename.map((r) => [fold(r.from), r.to]));
@@ -464,14 +474,9 @@ export function applyStarModifiers(cols, star, dialect) {
464
474
  }
465
475
  return out;
466
476
  }
467
- /** SQL LIKE pattern → an anchored case-insensitive RegExp (`%` → `.*`, `_` → `.`). */
468
- export function likePatternToRegExp(pattern) {
469
- const escaped = pattern
470
- .replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
471
- .replace(/%/g, ".*")
472
- .replace(/_/g, ".");
473
- return new RegExp(`^${escaped}$`, "i");
474
- }
477
+ // likePatternToRegExp moved to ./like-pattern.js (leaf module, breaks the scope->carrier->registry
478
+ // cycle); re-exported here so existing importers keep resolving it from scope.ts.
479
+ export { likePatternToRegExp };
475
480
  function outputsOf(body) {
476
481
  if (body.projections.length === 0)
477
482
  return "unknown";
@@ -486,7 +491,7 @@ function outputsOf(body) {
486
491
  function lookupCte(scope, name) {
487
492
  if (!scope)
488
493
  return undefined;
489
- const key = foldIdentifier(name, scope.dialect);
494
+ const key = behaviorOf(scope).fold(name);
490
495
  for (let s = scope; s; s = s.parent) {
491
496
  const hit = s.ctes.get(key);
492
497
  if (hit)
@@ -499,23 +504,24 @@ function lookupCte(scope, name) {
499
504
  * `o.col` binds to `"O"` but not `"o"`). Aliases fold as "other"; a table's own name part folds
500
505
  * as kind "table" (BigQuery preserves table case). */
501
506
  function sourceKey(source, dialect, isCte = false) {
507
+ const b = resolveBehavior(dialect);
502
508
  if (source.kind === "lateral")
503
- return foldIdentifier(source.alias ?? "", dialect);
509
+ return b.fold(source.alias ?? "");
504
510
  if (source.kind === "graphtable") {
505
511
  return source.alias
506
- ? foldIdentifier(source.alias, dialect)
507
- : foldIdentifier(source.graph[source.graph.length - 1] ?? "graph_table", dialect, "table");
512
+ ? b.fold(source.alias)
513
+ : b.fold(source.graph[source.graph.length - 1] ?? "graph_table", "table");
508
514
  }
509
515
  if (source.alias)
510
- return foldIdentifier(source.alias, dialect);
516
+ return b.fold(source.alias);
511
517
  if (source.kind === "table") {
512
- return foldIdentifier(source.name[source.name.length - 1] ?? "", dialect, isCte ? "other" : "table");
518
+ return b.fold(source.name[source.name.length - 1] ?? "", isCte ? "other" : "table");
513
519
  }
514
520
  return "";
515
521
  }
516
522
  /** The columns a resolved source exposes, or "unknown" when it needs a schema (a bare table).
517
523
  * Exported for the unified binder's schema-free path (src/sema/resolve.ts). */
518
- export function sourceOutputs(src) {
524
+ export function sourceOutputs(src, dialect) {
519
525
  if (src.kind === "table")
520
526
  return src.source.columnAliases ?? "unknown";
521
527
  if (src.kind === "cte")
@@ -527,21 +533,21 @@ export function sourceOutputs(src) {
527
533
  if (src.kind === "graphtable")
528
534
  return src.scope.outputs;
529
535
  if (src.kind === "pivot")
530
- return pivotSourceOutputs(src, (s) => sourceOutputs(s));
536
+ return pivotSourceOutputs(src, (s) => sourceOutputs(s, dialect), dialect);
531
537
  return src.scope.outputs; // subquery
532
538
  }
533
539
  /** The reshaped columns of an aliased PIVOT/UNPIVOT source: its base columns (via `cols`) with the
534
540
  * pivot/unpivot transform applied. "unknown" if any base relation's columns need a schema we lack.
535
541
  * Shared by the schema-free scope path and the schema-fed qualify / resolve / lineage passes (each
536
542
  * passes its own column resolver), so an aliased pivot exposes the same reshaped set everywhere. */
537
- export function pivotSourceOutputs(src, cols) {
543
+ export function pivotSourceOutputs(src, cols, dialect) {
538
544
  const parts = src.base.map(cols);
539
545
  if (parts.some((p) => p === "unknown"))
540
546
  return "unknown";
541
547
  const base = parts.flat();
542
548
  if (src.pivot)
543
- return applyPivotCols(base, src.pivot);
549
+ return applyPivotCols(base, src.pivot, dialect);
544
550
  if (src.unpivot)
545
- return applyUnpivotCols(base, src.unpivot);
551
+ return applyUnpivotCols(base, src.unpivot, dialect);
546
552
  return "unknown";
547
553
  }
@@ -1,4 +1,5 @@
1
- import { foldIdentifier, matchesSourceKey } from "../ident/fold.js";
1
+ import { behaviorOf } from "../dialect-behavior/carrier.js";
2
+ import { resolveBehavior } from "../dialect-behavior/registry.js";
2
3
  import { tableSourceColumns } from "../qualify/relation-columns.js";
3
4
  import { aliasVisibleClause, applyPivotCols, applyStarModifiers, applyUnpivotCols, matchesProjectionAlias, mergeByName, pivotSourceOutputs, sourceOutputs, splitColumnRefInScope, } from "../scope/scope.js";
4
5
  /**
@@ -54,12 +55,12 @@ function resolveParts(scope, parts, clause, schema) {
54
55
  * outward; without a schema an unknown source yields `needs-schema`.
55
56
  */
56
57
  function resolveByName(scope, column, fields, schema) {
57
- const name = foldIdentifier(column, scope.dialect);
58
+ const name = behaviorOf(scope).fold(column);
58
59
  const sources = [...scope.sources.values()];
59
- const colsOf = (src) => schema ? (columnNamesOf(src, schema, undefined, scope.dialect) ?? "unknown") : sourceOutputs(src);
60
+ const colsOf = (src) => schema ? (columnNamesOf(src, schema, undefined, scope.dialect) ?? "unknown") : sourceOutputs(src, scope.dialect);
60
61
  const matches = sources.filter((s) => {
61
62
  const cols = colsOf(s);
62
- return cols !== "unknown" && cols.some((c) => foldIdentifier(c, scope.dialect) === name);
63
+ return cols !== "unknown" && cols.some((c) => behaviorOf(scope).fold(c) === name);
63
64
  });
64
65
  if (matches.length === 1)
65
66
  return { kind: "bound", source: matches[0], column, fields };
@@ -93,12 +94,13 @@ export function resolveColumnSource(scope, parts, schema) {
93
94
  * name folds equal. Returns undefined when no projection produces the column (a bare `*`/source).
94
95
  */
95
96
  export function findProducerProjection(projections, column, aliases, dialect) {
96
- const want = foldIdentifier(column, dialect);
97
+ const b = resolveBehavior(dialect);
98
+ const want = b.fold(column);
97
99
  if (aliases) {
98
- const i = aliases.findIndex((a) => foldIdentifier(a, dialect) === want);
100
+ const i = aliases.findIndex((a) => b.fold(a) === want);
99
101
  return i >= 0 ? projections[i] : undefined;
100
102
  }
101
- return projections.find((p) => !p.isStar && p.name !== undefined && foldIdentifier(p.name, dialect) === want);
103
+ return projections.find((p) => !p.isStar && p.name !== undefined && b.fold(p.name) === want);
102
104
  }
103
105
  /** The output column names a source exposes — schema for a table, the (schema-expanded) output
104
106
  * names for a derived relation (column aliases rename them), the AS columns for a lateral view.
@@ -119,7 +121,7 @@ export function columnNamesOf(src, schema, visited = new Set(), dialect) {
119
121
  if (src.kind === "graphtable")
120
122
  return outputNames(src.scope, schema, visited);
121
123
  if (src.kind === "pivot") {
122
- const r = pivotSourceOutputs(src, (s) => columnNamesOf(s, schema, visited, dialect) ?? "unknown");
124
+ const r = pivotSourceOutputs(src, (s) => columnNamesOf(s, schema, visited, dialect) ?? "unknown", dialect);
123
125
  return r === "unknown" ? undefined : r;
124
126
  }
125
127
  return src.source.columns; // lateral
@@ -166,7 +168,10 @@ function computeOutputNames(scope, schema, visited) {
166
168
  // A PIVOT/UNPIVOT with no result alias reshapes the FROM relation — expand the sources, transform.
167
169
  if (body.pivot && !body.pivot.alias) {
168
170
  const base = sourceColumnsAll(scope, schema, visited);
169
- return base ? applyPivotCols(base, body.pivot, scope.dialect) : undefined;
171
+ if (!base)
172
+ return undefined;
173
+ const out = applyPivotCols(base, body.pivot, scope.dialect);
174
+ return out === "unknown" ? undefined : out; // dynamic pivot → unknown, resolved as undefined here
170
175
  }
171
176
  if (body.unpivot && !body.unpivot.alias) {
172
177
  const base = sourceColumnsAll(scope, schema, visited);
@@ -194,7 +199,7 @@ function projectionNames(scope, projections, schema, visited) {
194
199
  const want = star?.qualifier ? (star.qualifier[star.qualifier.length - 1] ?? "") : undefined;
195
200
  const expanded = [];
196
201
  for (const [key, src] of scope.sources) {
197
- if (want !== undefined && !matchesSourceKey(key, want, scope.dialect))
202
+ if (want !== undefined && !behaviorOf(scope).matchesSourceKey(key, want))
198
203
  continue;
199
204
  const cols = columnNamesOf(src, schema, visited, scope.dialect);
200
205
  if (!cols)
@@ -240,13 +245,13 @@ function pipeStageNames(scope, schema, visited) {
240
245
  return [...aggs, ...keys];
241
246
  }
242
247
  case "drop": {
243
- const fold = (n) => foldIdentifier(n, scope.dialect);
248
+ const fold = (n) => behaviorOf(scope).fold(n);
244
249
  return incoming ? incoming.filter((c) => !stage.drop.some((d) => fold(d) === fold(c))) : undefined;
245
250
  }
246
251
  case "rename": {
247
252
  if (!incoming)
248
253
  return undefined;
249
- const fold = (n) => foldIdentifier(n, scope.dialect);
254
+ const fold = (n) => behaviorOf(scope).fold(n);
250
255
  const m = new Map(stage.renames.map((r) => [fold(r.from), r.to]));
251
256
  return incoming.map((c) => m.get(fold(c)) ?? c);
252
257
  }
package/dist/session.d.ts CHANGED
@@ -14,7 +14,7 @@ import type { SchemaProvider } from "./qualify/schema-provider.js";
14
14
  import { type TemplateProvider } from "./qualify/template-provider.js";
15
15
  import type { Occurrences } from "./references/references.js";
16
16
  import type { LineageHop } from "./lineage/hops.js";
17
- import { type SignatureInfo } from "./signature/signature.js";
17
+ import { type SignatureHelpInfo } from "./signature/signature.js";
18
18
  import type { Scope, ScopeTree } from "./scope/scope.js";
19
19
  import type { Span, Sym } from "./symbols/symbols.js";
20
20
  import type { TemplateEngine } from "./template/engine.js";
@@ -69,7 +69,7 @@ export declare class SqlSession {
69
69
  * infers it. A miss returns Type's own `unknown` (src/infer/types.ts's UNKNOWN), never a throw. */
70
70
  typeAt(offset: number): Type;
71
71
  completeAt(offset: number): Completion[];
72
- signatureAt(offset: number): SignatureInfo | null;
72
+ signatureAt(offset: number): SignatureHelpInfo | null;
73
73
  referencesAt(offset: number): Occurrences | null;
74
74
  lineageAt(offset: number): LineageHop | undefined;
75
75
  variantAt(offset: number): DocumentVariant | undefined;
@@ -1,14 +1,22 @@
1
1
  import type { SqlDocument } from "../document/document.js";
2
2
  import type { SchemaProvider } from "../qualify/schema-provider.js";
3
- /** What the editor shows while typing inside a call's parens. */
4
- export interface SignatureInfo {
5
- /** e.g. "date_add(start_date: date, num_days: int)" — or just "myfunc" when uncurated. */
3
+ /** One rendered overload: e.g. "date_add(start_date: date, num_days: int)". */
4
+ export interface SignatureLabel {
6
5
  label: string;
7
- /** One per param; [] when uncurated. */
6
+ /** One per param; [] for the name-only fallback entry. */
8
7
  parameters: {
9
8
  label: string;
10
9
  }[];
11
- /** 0-based arg index the caret is in. */
10
+ }
11
+ /** What the editor shows while typing inside a call's parens: every overload of the called name,
12
+ * which one is active, and which of ITS params the caret is in. */
13
+ export interface SignatureHelpInfo {
14
+ /** Every overload of the called name, in harvested/authored order; a single one-element array for
15
+ * an uncurated name (the name-only fallback) or a name with one documented shape. */
16
+ signatures: SignatureLabel[];
17
+ /** Index into `signatures` of the overload the editor should highlight. */
18
+ activeSignature: number;
19
+ /** 0-based arg index the caret is in, within the active signature. */
12
20
  activeParameter: number;
13
21
  }
14
22
  /**
@@ -16,4 +24,4 @@ export interface SignatureInfo {
16
24
  * recognizable call. `schema` is accepted for parity with the other features (and future
17
25
  * overload selection) but the curated tables don't need it today. NEVER throws.
18
26
  */
19
- export declare function signatureAt(doc: SqlDocument, offset: number, _schema?: SchemaProvider): SignatureInfo | null;
27
+ export declare function signatureAt(doc: SqlDocument, offset: number, _schema?: SchemaProvider): SignatureHelpInfo | null;