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.
- package/LICENSE +0 -10
- package/README.md +95 -85
- package/THIRD-PARTY-NOTICES.md +70 -5
- package/dist/api.d.ts +5 -3
- package/dist/api.js +17 -4
- package/dist/bigquery/behavior.d.ts +2 -0
- package/dist/bigquery/behavior.js +20 -0
- package/dist/bigquery/dot-path.d.ts +0 -2
- package/dist/bigquery/dot-path.js +0 -1
- package/dist/bigquery/fold.d.ts +8 -0
- package/dist/bigquery/fold.js +39 -0
- package/dist/bigquery/index.d.ts +7 -0
- package/dist/bigquery/index.js +10 -0
- package/dist/{infer/bigquery.d.ts → bigquery/infer.d.ts} +2 -2
- package/dist/{infer/bigquery.js → bigquery/infer.js} +4 -3
- package/dist/bigquery/lower.js +35 -12
- package/dist/bigquery/signatures.generated.d.ts +6 -0
- package/dist/bigquery/signatures.generated.js +1068 -0
- package/dist/completion/atn-walk.d.ts +13 -2
- package/dist/completion/atn-walk.js +13 -10
- package/dist/completion/complete.d.ts +4 -3
- package/dist/completion/complete.js +101 -45
- package/dist/completion/config.js +66 -0
- package/dist/completion/jinja-slot.d.ts +24 -0
- package/dist/completion/jinja-slot.js +126 -0
- package/dist/completion/parser-factory.d.ts +13 -1
- package/dist/completion/parser-factory.js +48 -0
- package/dist/databricks/behavior.d.ts +2 -0
- package/dist/databricks/behavior.js +19 -0
- package/dist/databricks/fold.d.ts +8 -0
- package/dist/databricks/fold.js +27 -0
- package/dist/databricks/index.d.ts +7 -0
- package/dist/databricks/index.js +10 -0
- package/dist/databricks/infer.d.ts +6 -0
- package/dist/databricks/infer.js +638 -0
- package/dist/databricks/signatures.generated.d.ts +6 -0
- package/dist/databricks/signatures.generated.js +1745 -0
- package/dist/derived-dialects.js +19 -1
- package/dist/dialect-behavior/behavior.d.ts +26 -0
- package/dist/dialect-behavior/behavior.js +1 -0
- package/dist/dialect-behavior/carrier.d.ts +5 -0
- package/dist/dialect-behavior/carrier.js +5 -0
- package/dist/dialect-behavior/coerce-rules.d.ts +7 -0
- package/dist/dialect-behavior/coerce-rules.js +69 -0
- package/dist/dialect-behavior/public-fold.d.ts +6 -0
- package/dist/dialect-behavior/public-fold.js +9 -0
- package/dist/dialect-behavior/registry.d.ts +6 -0
- package/dist/dialect-behavior/registry.js +34 -0
- package/dist/dialect-symbols.js +22 -17
- package/dist/dialect.d.ts +2 -2
- package/dist/document/document.d.ts +1 -1
- package/dist/document/document.js +8 -7
- package/dist/duckdb/behavior.d.ts +2 -0
- package/dist/duckdb/behavior.js +21 -0
- package/dist/duckdb/fold.d.ts +8 -0
- package/dist/duckdb/fold.js +29 -0
- package/dist/duckdb/index.d.ts +7 -0
- package/dist/duckdb/index.js +10 -0
- package/dist/{infer/duckdb.d.ts → duckdb/infer.d.ts} +2 -2
- package/dist/{infer/duckdb.js → duckdb/infer.js} +4 -3
- package/dist/duckdb/lower.js +47 -15
- package/dist/duckdb/signatures.generated.d.ts +6 -0
- package/dist/duckdb/signatures.generated.js +1072 -0
- package/dist/generated/bigquery/GoogleSQLParser.js +0 -7060
- package/dist/generated/databricks/DatabricksParser.js +0 -4800
- package/dist/generated/duckdb/DuckdbParser.js +0 -9100
- package/dist/generated/minijinja/MinijinjaParser.js +0 -380
- package/dist/generated/mysql/MysqlLexer.js +7357 -0
- package/dist/generated/mysql/MysqlParser.js +78520 -0
- package/dist/generated/postgres/PostgresParser.js +0 -8530
- package/dist/generated/redshift/RedshiftParser.js +0 -10970
- package/dist/generated/snowflake/SnowflakeParser.js +0 -7320
- package/dist/generated/sqlite/SqliteLexer.js +945 -0
- package/dist/generated/sqlite/SqliteParser.js +14682 -0
- package/dist/generated/trino/TrinoParser.js +0 -3770
- package/dist/generated/tsql/TSqlParser.js +0 -8420
- package/dist/ident/fold.d.ts +24 -15
- package/dist/ident/fold.js +12 -145
- package/dist/index.d.ts +6 -2
- package/dist/index.js +14 -8
- package/dist/infer/functions.d.ts +22 -11
- package/dist/infer/functions.js +26 -888
- package/dist/infer/infer.js +16 -14
- package/dist/infer/nullability.js +3 -4
- package/dist/infer/types.d.ts +1 -1
- package/dist/infer/types.js +7 -7
- package/dist/ir/ir.d.ts +26 -17
- package/dist/ir/part-span.d.ts +16 -1
- package/dist/ir/part-span.js +38 -10
- package/dist/ir/span.js +0 -2
- package/dist/ir/walk.js +3 -3
- package/dist/lineage/hops.js +13 -10
- package/dist/lineage/lineage.js +10 -7
- package/dist/minijinja/apply-tags.d.ts +14 -7
- package/dist/minijinja/apply-tags.js +66 -121
- package/dist/minijinja/parse.js +6 -6
- package/dist/minijinja/tag-ast.d.ts +29 -36
- package/dist/minijinja/tag-ast.js +210 -90
- package/dist/mysql/behavior.d.ts +2 -0
- package/dist/mysql/behavior.js +21 -0
- package/dist/mysql/fold.d.ts +8 -0
- package/dist/mysql/fold.js +49 -0
- package/dist/mysql/index.d.ts +7 -0
- package/dist/mysql/index.js +10 -0
- package/dist/mysql/infer.d.ts +20 -0
- package/dist/mysql/infer.js +156 -0
- package/dist/mysql/lower.d.ts +13 -0
- package/dist/mysql/lower.js +1443 -0
- package/dist/mysql/parse.d.ts +10 -0
- package/dist/mysql/parse.js +70 -0
- package/dist/mysql/signatures.generated.d.ts +6 -0
- package/dist/mysql/signatures.generated.js +508 -0
- package/dist/postgres/behavior.d.ts +2 -0
- package/dist/postgres/behavior.js +19 -0
- package/dist/postgres/fold.d.ts +8 -0
- package/dist/postgres/fold.js +30 -0
- package/dist/postgres/index.d.ts +7 -0
- package/dist/postgres/index.js +10 -0
- package/dist/{infer/postgres.d.ts → postgres/infer.d.ts} +2 -2
- package/dist/{infer/postgres.js → postgres/infer.js} +4 -3
- package/dist/postgres/lower.js +2 -2
- package/dist/postgres/signatures.generated.d.ts +6 -0
- package/dist/postgres/signatures.generated.js +2973 -0
- package/dist/qualify/check-calls.js +80 -134
- package/dist/qualify/qualify.js +16 -14
- package/dist/qualify/schema-provider.js +2 -2
- package/dist/qualify/schema.js +3 -3
- package/dist/qualify/template-provider.d.ts +45 -12
- package/dist/qualify/template-provider.js +69 -38
- package/dist/redshift/behavior.d.ts +2 -0
- package/dist/redshift/behavior.js +19 -0
- package/dist/redshift/fold.d.ts +8 -0
- package/dist/redshift/fold.js +31 -0
- package/dist/redshift/index.d.ts +7 -0
- package/dist/redshift/index.js +10 -0
- package/dist/{infer/redshift.d.ts → redshift/infer.d.ts} +2 -2
- package/dist/{infer/redshift.js → redshift/infer.js} +4 -3
- package/dist/redshift/lower.js +2 -2
- package/dist/redshift/signatures.generated.d.ts +6 -0
- package/dist/redshift/signatures.generated.js +757 -0
- package/dist/references/references.js +17 -12
- package/dist/scope/like-pattern.d.ts +2 -0
- package/dist/scope/like-pattern.js +15 -0
- package/dist/scope/scope.d.ts +5 -5
- package/dist/scope/scope.js +48 -42
- package/dist/sema/resolve.js +17 -12
- package/dist/session.d.ts +2 -2
- package/dist/signature/signature.d.ts +14 -6
- package/dist/signature/signature.js +30 -22
- package/dist/signature/signatures.d.ts +14 -12
- package/dist/signature/signatures.js +42 -582
- package/dist/snowflake/behavior.d.ts +2 -0
- package/dist/snowflake/behavior.js +22 -0
- package/dist/snowflake/fold.d.ts +8 -0
- package/dist/snowflake/fold.js +25 -0
- package/dist/snowflake/index.d.ts +7 -0
- package/dist/snowflake/index.js +10 -0
- package/dist/{infer/snowflake.d.ts → snowflake/infer.d.ts} +2 -2
- package/dist/{infer/snowflake.js → snowflake/infer.js} +4 -3
- package/dist/snowflake/lower.js +59 -19
- package/dist/snowflake/signatures.generated.d.ts +6 -0
- package/dist/snowflake/signatures.generated.js +2080 -0
- package/dist/sqlite/behavior.d.ts +2 -0
- package/dist/sqlite/behavior.js +19 -0
- package/dist/sqlite/fold.d.ts +8 -0
- package/dist/sqlite/fold.js +41 -0
- package/dist/sqlite/index.d.ts +7 -0
- package/dist/sqlite/index.js +10 -0
- package/dist/sqlite/infer.d.ts +12 -0
- package/dist/sqlite/infer.js +122 -0
- package/dist/sqlite/lower.d.ts +11 -0
- package/dist/sqlite/lower.js +1093 -0
- package/dist/sqlite/parse.d.ts +10 -0
- package/dist/sqlite/parse.js +70 -0
- package/dist/sqlite/signatures.generated.d.ts +6 -0
- package/dist/sqlite/signatures.generated.js +277 -0
- package/dist/symbols/symbols.js +14 -12
- package/dist/token/classify.js +31 -0
- package/dist/token/tokenize.js +4 -0
- package/dist/trino/behavior.d.ts +2 -0
- package/dist/trino/behavior.js +21 -0
- package/dist/trino/fold.d.ts +8 -0
- package/dist/trino/fold.js +39 -0
- package/dist/trino/index.d.ts +7 -0
- package/dist/trino/index.js +10 -0
- package/dist/{infer/trino.d.ts → trino/infer.d.ts} +2 -2
- package/dist/{infer/trino.js → trino/infer.js} +4 -3
- package/dist/trino/lower.js +5 -5
- package/dist/trino/signatures.generated.d.ts +6 -0
- package/dist/trino/signatures.generated.js +968 -0
- package/dist/tsql/behavior.d.ts +2 -0
- package/dist/tsql/behavior.js +20 -0
- package/dist/tsql/fold.d.ts +8 -0
- package/dist/tsql/fold.js +34 -0
- package/dist/tsql/index.d.ts +7 -0
- package/dist/tsql/index.js +10 -0
- package/dist/tsql/infer.d.ts +16 -0
- package/dist/tsql/infer.js +289 -0
- package/dist/tsql/lower.js +4 -4
- package/dist/tsql/signatures.generated.d.ts +6 -0
- package/dist/tsql/signatures.generated.js +640 -0
- package/package.json +15 -11
- package/dist/generated/bigquery/GoogleSQLLexer.d.ts +0 -407
- package/dist/generated/bigquery/GoogleSQLParser.d.ts +0 -9558
- package/dist/generated/bigquery/GoogleSQLParserListener.d.ts +0 -7777
- package/dist/generated/bigquery/GoogleSQLParserListener.js +0 -7070
- package/dist/generated/databricks/DatabricksLexer.d.ts +0 -566
- package/dist/generated/databricks/DatabricksParser.d.ts +0 -7771
- package/dist/generated/databricks/DatabricksParserListener.d.ts +0 -5737
- package/dist/generated/databricks/DatabricksParserListener.js +0 -5256
- package/dist/generated/duckdb/DuckdbLexer.d.ts +0 -691
- package/dist/generated/duckdb/DuckdbParser.d.ts +0 -13932
- package/dist/generated/duckdb/DuckdbParserListener.d.ts +0 -10049
- package/dist/generated/duckdb/DuckdbParserListener.js +0 -9138
- package/dist/generated/minijinja/MinijinjaLexer.d.ts +0 -108
- package/dist/generated/minijinja/MinijinjaParser.d.ts +0 -604
- package/dist/generated/minijinja/MinijinjaParserListener.d.ts +0 -449
- package/dist/generated/minijinja/MinijinjaParserListener.js +0 -410
- package/dist/generated/postgres/PostgresLexer.d.ts +0 -663
- package/dist/generated/postgres/PostgresParser.d.ts +0 -12963
- package/dist/generated/postgres/PostgresParserListener.d.ts +0 -9408
- package/dist/generated/postgres/PostgresParserListener.js +0 -8554
- package/dist/generated/redshift/RedshiftLexer.d.ts +0 -954
- package/dist/generated/redshift/RedshiftParser.d.ts +0 -16939
- package/dist/generated/redshift/RedshiftParserListener.d.ts +0 -12092
- package/dist/generated/redshift/RedshiftParserListener.js +0 -10994
- package/dist/generated/snowflake/SnowflakeLexer.d.ts +0 -1046
- package/dist/generated/snowflake/SnowflakeParser.d.ts +0 -14196
- package/dist/generated/snowflake/SnowflakeParserListener.d.ts +0 -8063
- package/dist/generated/snowflake/SnowflakeParserListener.js +0 -7330
- package/dist/generated/trino/TrinoLexer.d.ts +0 -381
- package/dist/generated/trino/TrinoParser.d.ts +0 -5340
- package/dist/generated/trino/TrinoParserListener.d.ts +0 -4704
- package/dist/generated/trino/TrinoParserListener.js +0 -4326
- package/dist/generated/tsql/TSqlLexer.d.ts +0 -1278
- package/dist/generated/tsql/TSqlParser.d.ts +0 -17267
- package/dist/generated/tsql/TSqlParserListener.d.ts +0 -9697
- package/dist/generated/tsql/TSqlParserListener.js +0 -8854
- package/dist/infer/dialect.d.ts +0 -21
- package/dist/infer/dialect.js +0 -74
- package/dist/infer/literals.d.ts +0 -6
- package/dist/infer/literals.js +0 -44
- package/dist/signature/generated/tsql.d.ts +0 -3
- package/dist/signature/generated/tsql.js +0 -260
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { nodeAt } from "../document/node-at.js";
|
|
2
|
-
import {
|
|
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) =>
|
|
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,
|
|
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:
|
|
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:
|
|
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 &&
|
|
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 (
|
|
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
|
|
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 &&
|
|
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 &&
|
|
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
|
|
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 ||
|
|
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,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
|
+
}
|
package/dist/scope/scope.d.ts
CHANGED
|
@@ -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
|
-
|
|
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";
|
package/dist/scope/scope.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
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 =
|
|
22
|
+
const k = b.fold(part);
|
|
20
23
|
if (isSource(k))
|
|
21
24
|
return k;
|
|
22
|
-
const kt =
|
|
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
|
|
58
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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) =>
|
|
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
|
|
399
|
-
|
|
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
|
-
|
|
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) =>
|
|
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
|
|
446
|
-
|
|
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) =>
|
|
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
|
|
459
|
-
|
|
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
|
-
|
|
468
|
-
|
|
469
|
-
|
|
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 =
|
|
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
|
|
509
|
+
return b.fold(source.alias ?? "");
|
|
504
510
|
if (source.kind === "graphtable") {
|
|
505
511
|
return source.alias
|
|
506
|
-
?
|
|
507
|
-
:
|
|
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
|
|
516
|
+
return b.fold(source.alias);
|
|
511
517
|
if (source.kind === "table") {
|
|
512
|
-
return
|
|
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
|
}
|
package/dist/sema/resolve.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
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 =
|
|
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) =>
|
|
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
|
|
97
|
+
const b = resolveBehavior(dialect);
|
|
98
|
+
const want = b.fold(column);
|
|
97
99
|
if (aliases) {
|
|
98
|
-
const i = aliases.findIndex((a) =>
|
|
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 &&
|
|
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
|
-
|
|
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
|
|
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) =>
|
|
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) =>
|
|
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
|
|
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):
|
|
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
|
-
/**
|
|
4
|
-
export interface
|
|
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; []
|
|
6
|
+
/** One per param; [] for the name-only fallback entry. */
|
|
8
7
|
parameters: {
|
|
9
8
|
label: string;
|
|
10
9
|
}[];
|
|
11
|
-
|
|
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):
|
|
27
|
+
export declare function signatureAt(doc: SqlDocument, offset: number, _schema?: SchemaProvider): SignatureHelpInfo | null;
|