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,51 +1,42 @@
|
|
|
1
1
|
import { endPosition } from "../ir/span.js";
|
|
2
2
|
import { inferType } from "../infer/infer.js";
|
|
3
|
-
import {
|
|
4
|
-
import { FUNCTION_SIGNATURES, HARVESTED_SIGNATURES } from "../signature/signatures.js";
|
|
3
|
+
import { behaviorOf } from "../dialect-behavior/carrier.js";
|
|
5
4
|
// ---------------------------------------------------------------------------
|
|
6
|
-
// Call-signature diagnostics
|
|
5
|
+
// Call-signature diagnostics: arity + operand types, over the modelled function
|
|
7
6
|
// calls in the IR. Never-wrong: a diagnostic fires ONLY when the checker is
|
|
8
7
|
// certain the call is wrong. Two rules, in order of strictness:
|
|
9
8
|
//
|
|
10
|
-
// - ARITY (
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
9
|
+
// - ARITY (both origins): the name is in the dialect's merged signature table
|
|
10
|
+
// (src/<dialect>/signatures.generated.ts, curated overrides folded over the
|
|
11
|
+
// harvested long tail), and it maps to an ORDERED OVERLOAD SET, not a single
|
|
12
|
+
// shape. It fires wrong-arity only when the call's arg count is matched by
|
|
13
|
+
// NO overload's [min, max] window. A variadic overload accepts any count at
|
|
14
|
+
// or above its own min (the last param repeats), so it never itself causes a
|
|
15
|
+
// flag. min = the count of non-optional params; max = the param count. Every
|
|
16
|
+
// overload's origin is trusted for arity (the harvested tables carry a
|
|
17
|
+
// trustworthy optional/variadic encoding, tools/harvest-signatures.mjs's
|
|
18
|
+
// NEVER-WRONG CONTRACT), so this is a union check across the whole set.
|
|
14
19
|
//
|
|
15
|
-
// - OPERAND TYPE
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
//
|
|
20
|
+
// - OPERAND TYPE: only when the name has EXACTLY ONE overload and its origin is
|
|
21
|
+
// "curated", the unambiguous case. A 2+-overload name skips type checking
|
|
22
|
+
// entirely (which specific overload the call means isn't decided here, so no
|
|
23
|
+
// operand-type rejection can be trusted). When it does apply: every argument
|
|
24
|
+
// type is inferable (not unknown) AND some argument position is rejected
|
|
25
|
+
// under `accepts()` (no implicit widening path to the declared param type),
|
|
26
|
+
// so it fires wrong-argument-type. Any `unknown` argument type anywhere makes
|
|
27
|
+
// the whole call silent. A harvested-origin overload never drives a
|
|
28
|
+
// wrong-argument-type diagnostic (its param types aren't reliable enough).
|
|
24
29
|
//
|
|
25
30
|
// A qualified/dotted call (`ns.fn(...)`, sequence `.NEXTVAL`) does NOT match a
|
|
26
|
-
// bare-name
|
|
31
|
+
// bare-name signature: the table is bare-name only, so it stays silent.
|
|
27
32
|
// A named-argument call (`fn(x => v)`) can't be mapped to a positional arg list
|
|
28
33
|
// confidently, so it too stays silent.
|
|
29
34
|
//
|
|
30
35
|
// The checker walks the scope tree; for each scope it inspects THAT scope's own
|
|
31
|
-
// expressions (not nested subquery/EXISTS bodies
|
|
36
|
+
// expressions (not nested subquery/EXISTS bodies: those are checked when their
|
|
32
37
|
// child scope is visited), so an argument's type is inferred in the scope where
|
|
33
38
|
// the call actually lives.
|
|
34
39
|
// ---------------------------------------------------------------------------
|
|
35
|
-
/** Risk-flag (c) escape hatch. Harvested arity data (T-SQL's 151-entry generated table is the only
|
|
36
|
-
* one today) does not encode which params are optional, nor mark variadic reliably, so an arity
|
|
37
|
-
* check over it fires on valid SQL. Kept curated-only, VISIBLY, for every dialect. Flip a dialect
|
|
38
|
-
* on only once its harvested table earns it (optional/variadic encoding proven against the corpus). */
|
|
39
|
-
const ARITY_USES_HARVESTED = {
|
|
40
|
-
databricks: false,
|
|
41
|
-
tsql: false,
|
|
42
|
-
snowflake: false,
|
|
43
|
-
bigquery: false,
|
|
44
|
-
redshift: false,
|
|
45
|
-
postgres: false,
|
|
46
|
-
duckdb: false,
|
|
47
|
-
trino: false,
|
|
48
|
-
};
|
|
49
40
|
export function checkCalls(tree, schema, diagnostics) {
|
|
50
41
|
const visit = (scope) => {
|
|
51
42
|
for (const expr of ownExprs(scope))
|
|
@@ -161,140 +152,95 @@ function checkOneCall(fn, scope, schema, diagnostics) {
|
|
|
161
152
|
// A named-argument invocation (fn(x => v)) can't be mapped to a positional arg list confidently.
|
|
162
153
|
if (fn.argNames?.some((n) => n !== undefined))
|
|
163
154
|
return;
|
|
164
|
-
// A qualified/dotted call must not borrow a bare-name signature (the
|
|
155
|
+
// A qualified/dotted call must not borrow a bare-name signature (the table is bare-name only).
|
|
165
156
|
if (fn.qualifier !== undefined)
|
|
166
157
|
return;
|
|
167
158
|
// Aggregate / window / DISTINCT forms carry modifiers the IR folds into (or out of) the arg list
|
|
168
|
-
// unevenly
|
|
169
|
-
// positional arg count isn't a reliable signal. Per the never-wrong contract, stay SILENT
|
|
159
|
+
// unevenly: count(*) becomes 0 args, sum(x) FILTER/OVER/WITHIN GROUP, a dropped DISTINCT keyword,
|
|
160
|
+
// so the positional arg count isn't a reliable signal. Per the never-wrong contract, stay SILENT.
|
|
170
161
|
if (fn.aggregate || fn.window || fn.distinct)
|
|
171
162
|
return;
|
|
172
|
-
const
|
|
163
|
+
const b = behaviorOf(scope);
|
|
173
164
|
const name = fn.name.toLowerCase();
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
// overload accepts the arg count.
|
|
178
|
-
const overloads = [];
|
|
179
|
-
if (curated)
|
|
180
|
-
overloads.push(curated);
|
|
181
|
-
if (ARITY_USES_HARVESTED[dialect]) {
|
|
182
|
-
const harvested = HARVESTED_SIGNATURES[dialect]?.[name];
|
|
183
|
-
if (harvested && harvested !== curated)
|
|
184
|
-
overloads.push(harvested);
|
|
185
|
-
}
|
|
186
|
-
if (overloads.length === 0)
|
|
187
|
-
return; // uncurated (and no trusted harvested) — silent
|
|
165
|
+
const overloads = b.signatures[name];
|
|
166
|
+
if (!overloads)
|
|
167
|
+
return; // unknown name, silent
|
|
188
168
|
const args = fn.args;
|
|
189
169
|
// Trust the IR arg list ONLY when it faithfully mirrors what was written. Some special call forms
|
|
190
170
|
// lower to an arg list that doesn't match the source positionally: a keyword arg the lowering drops
|
|
191
171
|
// (T-SQL/BigQuery DATEADD/DATE_DIFF's datepart), a boolean condition split into comparands (T-SQL
|
|
192
172
|
// IIF), or the SQL-standard `f(x FROM y FOR z)` / nested-call over-capture (Postgres-family TRIM/
|
|
193
173
|
// SUBSTRING). Comparing the IR arg count to the top-level comma count in the written call catches all
|
|
194
|
-
// of these generically
|
|
174
|
+
// of these generically: a mismatch means the positional shape isn't reliable, so stay SILENT.
|
|
195
175
|
const written = writtenArgCount(fn.cst);
|
|
196
176
|
if (written !== null && written !== args.length)
|
|
197
177
|
return;
|
|
198
|
-
// --- arity:
|
|
199
|
-
if (
|
|
178
|
+
// --- arity: fires only when NO overload's [min, max] window accepts the count ---
|
|
179
|
+
if (!arityAccepts(overloads, args.length)) {
|
|
200
180
|
diagnostics.push(callDiag("wrong-arity", fn.cst, arityMessage(overloads, args.length)));
|
|
201
181
|
return; // one diagnostic per call — don't also type-check a call of the wrong shape
|
|
202
182
|
}
|
|
203
|
-
// --- operand type
|
|
204
|
-
if (
|
|
183
|
+
// --- operand type: only the unambiguous case, exactly one overload and it's curated-origin ---
|
|
184
|
+
if (overloads.length !== 1)
|
|
185
|
+
return;
|
|
186
|
+
const sig = overloads[0];
|
|
187
|
+
if (sig.origin !== "curated")
|
|
205
188
|
return;
|
|
206
189
|
const types = args.map((a) => inferType(a, scope, schema));
|
|
207
190
|
if (types.some((t) => t.kind === "unknown"))
|
|
208
191
|
return; // any unknown → silent
|
|
209
192
|
for (let i = 0; i < types.length; i++) {
|
|
210
|
-
const param =
|
|
211
|
-
if (param && !accepts(types[i], param.type
|
|
212
|
-
diagnostics.push(callDiag("wrong-argument-type", fn.cst, argMessage(
|
|
193
|
+
const param = sig.variadic ? sig.params[Math.min(i, sig.params.length - 1)] : sig.params[i];
|
|
194
|
+
if (param && !b.accepts(types[i], param.type)) {
|
|
195
|
+
diagnostics.push(callDiag("wrong-argument-type", fn.cst, argMessage(sig, i, param.type ?? "?", types[i])));
|
|
213
196
|
return; // one diagnostic per call
|
|
214
197
|
}
|
|
215
198
|
}
|
|
216
199
|
}
|
|
217
|
-
/** Whether
|
|
218
|
-
* param repeats); a fixed one accepts [non-optional count, param
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
function familyOf(name) {
|
|
228
|
-
if (NUMERIC.has(name))
|
|
229
|
-
return "num";
|
|
230
|
-
if (name === "string")
|
|
231
|
-
return "str";
|
|
232
|
-
if (name === "boolean")
|
|
233
|
-
return "bool";
|
|
234
|
-
if (TEMPORAL.has(name))
|
|
235
|
-
return "temporal";
|
|
236
|
-
if (name === "binary")
|
|
237
|
-
return "binary";
|
|
238
|
-
return "other";
|
|
239
|
-
}
|
|
240
|
-
/** Dialects that implicitly bridge STRING→numeric in a function argument, so a str→num mismatch must
|
|
241
|
-
* NOT be flagged. Doc-cited per dialect:
|
|
242
|
-
* - databricks: implicit crosscasting casts STRING to the expected numeric type
|
|
243
|
-
* (docs.databricks.com/sql/language-manual/sql-ref-datatype-rules — the docs corpus itself carries
|
|
244
|
-
* `substring('hello', '1', 2)` and `date_add(date'2011-11-30', '5')` as documented-valid examples);
|
|
245
|
-
* - tsql: char/varchar→int/decimal is an implicit conversion in the CAST/CONVERT conversion chart
|
|
246
|
-
* (learn.microsoft.com/sql/t-sql/functions/cast-and-convert-transact-sql) — `ABS('1')` is valid;
|
|
247
|
-
* - snowflake: VARCHAR containing a number coerces to NUMBER
|
|
248
|
-
* (docs.snowflake.com/en/sql-reference/data-type-conversion — implicit casting/coercion);
|
|
249
|
-
* - redshift: PG-8.0 lineage keeps pre-8.3 implicit text→numeric casts
|
|
250
|
-
* (docs.aws.amazon.com/redshift/latest/dg/c_Supported_data_types.html — type compatibility:
|
|
251
|
-
* CHAR/VARCHAR→numeric implicit);
|
|
252
|
-
* - postgres / duckdb: a quoted constant is initially of UNKNOWN type (postgresql.org/docs/18
|
|
253
|
-
* sql-syntax-lexical §4.1.2.1) and coerces to whatever the call needs — `abs('1')` is valid — but
|
|
254
|
-
* our inference types every quoted literal as `string`, so a str-typed arg may really be an
|
|
255
|
-
* untyped literal; rejecting would false-fire on valid SQL.
|
|
256
|
-
* NOT in the set (rejection stays live, corpus-proven): bigquery — no STRING→numeric coercion in the
|
|
257
|
-
* conversion rules (`ABS('1')` is "No matching signature"; 14.7k analyzer positives sweep clean);
|
|
258
|
-
* trino — implicit coercion is numeric/character widening only (`abs('1')` is "Unexpected
|
|
259
|
-
* parameters"; 635 docs-corpus positives sweep clean). */
|
|
260
|
-
const IMPLICIT_STR_TO_NUM = new Set([
|
|
261
|
-
"databricks",
|
|
262
|
-
"tsql",
|
|
263
|
-
"snowflake",
|
|
264
|
-
"redshift",
|
|
265
|
-
"postgres",
|
|
266
|
-
"duckdb",
|
|
267
|
-
]);
|
|
268
|
-
/** Dialects that implicitly bridge boolean↔numeric: T-SQL only, whose `bit` (aliased to boolean by
|
|
269
|
-
* TSQL_ALIASES) converts to/from int implicitly per the same CAST/CONVERT chart. Everywhere else
|
|
270
|
-
* bool→num / num→bool rejection is safe (Spark: "cannot resolve 'abs(true)' due to data type
|
|
271
|
-
* mismatch"; Snowflake: "Invalid argument types for function 'ABS': (BOOLEAN)"; PG/DuckDB/BigQuery/
|
|
272
|
-
* Trino likewise reject) — and corpus-proven across all eight sweeps. */
|
|
273
|
-
const IMPLICIT_BOOL_NUM = new Set(["tsql"]);
|
|
274
|
-
function accepts(argType, paramText, dialect) {
|
|
275
|
-
if (!paramText)
|
|
276
|
-
return true; // untyped param → no information, accept
|
|
277
|
-
const param = inferDialect(dialect).parseType(paramText);
|
|
278
|
-
if (param.kind !== "scalar" || argType.kind !== "scalar")
|
|
279
|
-
return true; // complex/unknown → accept
|
|
280
|
-
const fa = familyOf(argType.name);
|
|
281
|
-
const fp = familyOf(param.name);
|
|
282
|
-
if (fa === fp)
|
|
283
|
-
return true; // same family → accept
|
|
284
|
-
if (fa === "str" && fp === "num")
|
|
285
|
-
return IMPLICIT_STR_TO_NUM.has(dialect);
|
|
286
|
-
if ((fa === "bool" && fp === "num") || (fa === "num" && fp === "bool"))
|
|
287
|
-
return IMPLICIT_BOOL_NUM.has(dialect);
|
|
288
|
-
return true; // every other cross-family pair (incl. → str, temporal, binary, other) — accept
|
|
200
|
+
/** Whether ANY overload in the set accepts `n` positional args. A variadic overload accepts any count
|
|
201
|
+
* at or above its own min (its last param repeats); a fixed one accepts [non-optional count, param
|
|
202
|
+
* count]. */
|
|
203
|
+
function arityAccepts(overloads, n) {
|
|
204
|
+
return overloads.some((sig) => {
|
|
205
|
+
if (sig.variadic)
|
|
206
|
+
return true;
|
|
207
|
+
const min = sig.params.filter((p) => !p.optional).length;
|
|
208
|
+
return n >= min && n <= sig.params.length;
|
|
209
|
+
});
|
|
289
210
|
}
|
|
290
211
|
// ---------------------------------------------------------------------------
|
|
291
212
|
// Diagnostics
|
|
292
213
|
// ---------------------------------------------------------------------------
|
|
214
|
+
/** One overload's own [min, max] arity window (max is Infinity for a variadic overload). */
|
|
215
|
+
function windowOf(sig) {
|
|
216
|
+
return [sig.params.filter((p) => !p.optional).length, sig.variadic ? Infinity : sig.params.length];
|
|
217
|
+
}
|
|
218
|
+
/** One [lo, hi] window rendered the way a single contiguous range has always been rendered: an exact
|
|
219
|
+
* count, an unbounded "lo+", or a "lo–hi" span (the en dash there is intentional and frozen, this
|
|
220
|
+
* exact message shape is corpus-pinned, see tests/corpus/bigquery.analyzer.test.ts). */
|
|
221
|
+
function rangeStr([lo, hi]) {
|
|
222
|
+
return lo === hi ? `${lo}` : hi === Infinity ? `${lo}+` : `${lo}–${hi}`;
|
|
223
|
+
}
|
|
224
|
+
/** The arity-window UNION across every overload, merged into the fewest disjoint ranges (windows that
|
|
225
|
+
* overlap or touch collapse into one). A single-overload name always reduces to exactly one range, so
|
|
226
|
+
* this reproduces the pre-overload-aware message byte-for-byte in that case; a genuine multi-overload
|
|
227
|
+
* name with a gap between ranges (e.g. 2 args or 4 args, nothing in between) renders each range and
|
|
228
|
+
* joins them with " or ". */
|
|
293
229
|
function arityMessage(overloads, got) {
|
|
294
|
-
const
|
|
295
|
-
const
|
|
296
|
-
const
|
|
297
|
-
|
|
230
|
+
const windows = overloads.map(windowOf).sort((a, b) => a[0] - b[0]);
|
|
231
|
+
const groups = [];
|
|
232
|
+
for (const w of windows) {
|
|
233
|
+
const last = groups[groups.length - 1];
|
|
234
|
+
if (last && w[0] <= last[1] + 1) {
|
|
235
|
+
last[1] = Math.max(last[1], w[1]);
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
groups.push([w[0], w[1]]);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
const want = groups.map(rangeStr).join(" or ");
|
|
242
|
+
const overallHi = Math.max(...groups.map((g) => g[1]));
|
|
243
|
+
return `${overloads[0].name} expects ${want} argument${overallHi === 1 ? "" : "s"}, got ${got}`;
|
|
298
244
|
}
|
|
299
245
|
function argMessage(sig, i, paramType, got) {
|
|
300
246
|
const gotName = got.kind === "scalar" ? got.name : got.kind;
|
package/dist/qualify/qualify.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { behaviorOf } from "../dialect-behavior/carrier.js";
|
|
2
|
+
import { resolveBehavior } from "../dialect-behavior/registry.js";
|
|
3
|
+
import { applyPivotCols, applyStarModifiers, applyUnpivotCols, mergeByName, pivotSourceOutputs, splitColumnRefInScope, } from "../scope/scope.js";
|
|
3
4
|
import { endPosition } from "../ir/span.js";
|
|
4
5
|
import { inferType } from "../infer/infer.js";
|
|
5
6
|
import { checkCalls } from "./check-calls.js";
|
|
@@ -161,7 +162,7 @@ function resolvePipeStage(scope, schema, resolved, diagnostics, starPairs) {
|
|
|
161
162
|
return [...aggs, ...keys];
|
|
162
163
|
}
|
|
163
164
|
case "drop": {
|
|
164
|
-
const fold = (n) =>
|
|
165
|
+
const fold = (n) => behaviorOf(scope).fold(n);
|
|
165
166
|
return incoming === "unknown"
|
|
166
167
|
? "unknown"
|
|
167
168
|
: incoming.filter((c) => !stage.drop.some((d) => fold(d) === fold(c)));
|
|
@@ -169,7 +170,7 @@ function resolvePipeStage(scope, schema, resolved, diagnostics, starPairs) {
|
|
|
169
170
|
case "rename": {
|
|
170
171
|
if (incoming === "unknown")
|
|
171
172
|
return "unknown";
|
|
172
|
-
const fold = (n) =>
|
|
173
|
+
const fold = (n) => behaviorOf(scope).fold(n);
|
|
173
174
|
const map = new Map(stage.renames.map((r) => [fold(r.from), r.to]));
|
|
174
175
|
return incoming.map((c) => map.get(fold(c)) ?? c);
|
|
175
176
|
}
|
|
@@ -211,7 +212,7 @@ function expandStarPairs(scope, schema, resolved, diagnostics, qualifier) {
|
|
|
211
212
|
const cols = [];
|
|
212
213
|
let matched = false;
|
|
213
214
|
for (const [key, src] of scope.sources) {
|
|
214
|
-
if (want !== undefined && !matchesSourceKey(key, want
|
|
215
|
+
if (want !== undefined && !behaviorOf(scope).matchesSourceKey(key, want))
|
|
215
216
|
continue;
|
|
216
217
|
// A pseudo-column source (Snowflake/Oracle CONNECT BY's LEVEL) resolves by name but is
|
|
217
218
|
// excluded from a bare `*` — real pseudo-column semantics. A qualified star can't target
|
|
@@ -237,15 +238,16 @@ function expandStar(scope, schema, resolved, diagnostics, qualifier) {
|
|
|
237
238
|
* has its own established call sites (e.g. projectionColumns below) that don't need sourceKey and
|
|
238
239
|
* whose signature this task leaves untouched. */
|
|
239
240
|
function applyStarModifiersToPairs(pairs, star, dialect) {
|
|
240
|
-
const fold = (n) =>
|
|
241
|
+
const fold = (n) => resolveBehavior(dialect).fold(n);
|
|
241
242
|
let out = pairs;
|
|
242
243
|
if (star.exclude) {
|
|
243
244
|
const removed = new Set(star.exclude.map(fold));
|
|
244
245
|
out = out.filter((p) => !removed.has(fold(p.name)));
|
|
245
246
|
}
|
|
246
247
|
if (star.ilike !== undefined) {
|
|
247
|
-
const
|
|
248
|
-
|
|
248
|
+
const b = resolveBehavior(dialect);
|
|
249
|
+
const pat = star.ilike;
|
|
250
|
+
out = out.filter((p) => b.likeMatch(pat, fold(p.name)));
|
|
249
251
|
}
|
|
250
252
|
if (star.rename) {
|
|
251
253
|
const renames = new Map(star.rename.map((r) => [fold(r.from), r.to]));
|
|
@@ -282,7 +284,7 @@ function checkSourceColumns(src, schema, resolved, diagnostics, dialect) {
|
|
|
282
284
|
if (src.kind === "graphtable")
|
|
283
285
|
return known(resolved.get(src.scope));
|
|
284
286
|
if (src.kind === "pivot") {
|
|
285
|
-
return known(pivotSourceOutputs(src, (s) => checkSourceColumns(s, schema, resolved, diagnostics, dialect) ?? "unknown"));
|
|
287
|
+
return known(pivotSourceOutputs(src, (s) => checkSourceColumns(s, schema, resolved, diagnostics, dialect) ?? "unknown", dialect));
|
|
286
288
|
}
|
|
287
289
|
return src.source.columnAliases ?? known(resolved.get(src.scope));
|
|
288
290
|
}
|
|
@@ -323,14 +325,14 @@ function checkColumn(scope, ref, schema, resolved, diagnostics) {
|
|
|
323
325
|
// path `f` against `c`'s struct type — resolved from a table schema or threaded through a
|
|
324
326
|
// derived (CTE/subquery) column; see checkFieldPath.
|
|
325
327
|
const split = splitColumnRefInScope(scope, ref.parts);
|
|
326
|
-
const name =
|
|
328
|
+
const name = behaviorOf(scope).fold(split.column);
|
|
327
329
|
if (split.qualifier !== undefined) {
|
|
328
330
|
for (let s = scope; s; s = s.parent) {
|
|
329
331
|
const src = s.sources.get(split.qualifier);
|
|
330
332
|
if (!src)
|
|
331
333
|
continue;
|
|
332
334
|
const cols = sourceColumns(src, schema, resolved, s.dialect);
|
|
333
|
-
if (cols && !cols.some((c) =>
|
|
335
|
+
if (cols && !cols.some((c) => behaviorOf(s).fold(c) === name)) {
|
|
334
336
|
diagnostics.push(columnDiag("unknown-column", ref, `Unknown column: ${ref.parts.join(".")}`));
|
|
335
337
|
return; // base column missing — don't also walk its (nonexistent) fields
|
|
336
338
|
}
|
|
@@ -350,7 +352,7 @@ function checkColumn(scope, ref, schema, resolved, diagnostics) {
|
|
|
350
352
|
const cols = sourceColumns(src, schema, resolved, s.dialect);
|
|
351
353
|
if (!cols)
|
|
352
354
|
unknown++;
|
|
353
|
-
else if (cols.some((c) =>
|
|
355
|
+
else if (cols.some((c) => behaviorOf(s).fold(c) === name))
|
|
354
356
|
matches++;
|
|
355
357
|
}
|
|
356
358
|
if (matches > 1) {
|
|
@@ -385,7 +387,7 @@ function checkFieldPath(fields, scope, schema, ref, diagnostics) {
|
|
|
385
387
|
return; // unknown / non-struct — don't flag
|
|
386
388
|
// Struct-field names on a Type are stored FOLDED (parseType folds them at parse time), so
|
|
387
389
|
// only the reference side folds here — re-folding a preserved-case stored name would corrupt it.
|
|
388
|
-
const hit = type.fields.find((f) => f.name ===
|
|
390
|
+
const hit = type.fields.find((f) => f.name === behaviorOf(scope).fold(field));
|
|
389
391
|
if (!hit) {
|
|
390
392
|
diagnostics.push(columnDiag("unknown-field", ref, `Unknown field: ${ref.parts.join(".")}`));
|
|
391
393
|
return;
|
|
@@ -412,7 +414,7 @@ function sourceColumns(src, schema, resolved, dialect) {
|
|
|
412
414
|
if (src.kind === "graphtable")
|
|
413
415
|
return known(resolved.get(src.scope));
|
|
414
416
|
if (src.kind === "pivot")
|
|
415
|
-
return known(pivotSourceOutputs(src, (s) => sourceColumns(s, schema, resolved, dialect) ?? "unknown"));
|
|
417
|
+
return known(pivotSourceOutputs(src, (s) => sourceColumns(s, schema, resolved, dialect) ?? "unknown", dialect));
|
|
416
418
|
return src.source.columnAliases ?? known(resolved.get(src.scope));
|
|
417
419
|
}
|
|
418
420
|
/** Full positioned span of a CST node — 1-based line, 0-based column, endColumn one past the last
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
// FOLDED name parts (the catalog identity key), never the raw source text. A host
|
|
22
22
|
// keys its cache by that folded path.
|
|
23
23
|
// ---------------------------------------------------------------------------
|
|
24
|
-
import {
|
|
24
|
+
import { resolveBehavior } from "../dialect-behavior/registry.js";
|
|
25
25
|
/** A resolve-on-demand catalog. Implements SchemaProvider by delegating each folded lookup to a
|
|
26
26
|
* TableResolver and recording the misses; prime() drains those misses through the resolver's
|
|
27
27
|
* async fetch, re-probes, and bumps `version` when anything new arrived. */
|
|
@@ -48,7 +48,7 @@ export class CallbackSchema {
|
|
|
48
48
|
return this._misses;
|
|
49
49
|
}
|
|
50
50
|
columnsFor(parts, dialect) {
|
|
51
|
-
const folded = parts.map((p) =>
|
|
51
|
+
const folded = parts.map((p) => resolveBehavior(dialect).fold(p, "table"));
|
|
52
52
|
const cols = this.resolver.resolve(folded);
|
|
53
53
|
if (cols === undefined) {
|
|
54
54
|
this.recordMiss(folded);
|
package/dist/qualify/schema.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
// "table") — same as an unquoted table reference in the query. Quoted-key support (a mapping key
|
|
17
17
|
// meant to represent a quoted/case-exact identifier) is out of scope.
|
|
18
18
|
// ---------------------------------------------------------------------------
|
|
19
|
-
import {
|
|
19
|
+
import { resolveBehavior } from "../dialect-behavior/registry.js";
|
|
20
20
|
export class Schema {
|
|
21
21
|
/** A declared mapping is a CLOSED world: a miss means the table does not exist (unknown-table fires). */
|
|
22
22
|
world = "closed";
|
|
@@ -35,7 +35,7 @@ export class Schema {
|
|
|
35
35
|
* (unfolded) — the fold for `dialect` happens here, once. */
|
|
36
36
|
columnsFor(parts, dialect) {
|
|
37
37
|
const idx = this.indexFor(dialect);
|
|
38
|
-
const fold = (p) =>
|
|
38
|
+
const fold = (p) => resolveBehavior(dialect).fold(p, "table");
|
|
39
39
|
const full = parts.map(fold).join(".");
|
|
40
40
|
return idx.byPath.get(full) ?? idx.byTable.get(fold(parts[parts.length - 1] ?? ""));
|
|
41
41
|
}
|
|
@@ -59,7 +59,7 @@ export class Schema {
|
|
|
59
59
|
const isTable = entries.length > 0 && entries.every(([, v]) => typeof v === "string" || isLeaf(v));
|
|
60
60
|
if (isTable) {
|
|
61
61
|
const cols = entries.map(([name, leaf]) => toColumn(name, leaf));
|
|
62
|
-
const fold = (p) =>
|
|
62
|
+
const fold = (p) => resolveBehavior(dialect).fold(p, "table");
|
|
63
63
|
idx.byPath.set(path.map(fold).join("."), cols);
|
|
64
64
|
const bare = fold(path[path.length - 1] ?? "");
|
|
65
65
|
if (!idx.byTable.has(bare))
|
|
@@ -37,6 +37,14 @@ export interface ResolvedRelation {
|
|
|
37
37
|
/** The relation's columns, or undefined until an async describe lands (async warm). */
|
|
38
38
|
columns?: Column[];
|
|
39
39
|
}
|
|
40
|
+
/** A completion candidate a host offers for a template call slot (a dbt model for a ref's arg 0, a
|
|
41
|
+
* source name for a source's arg 0). `label` is what the editor inserts at the caret; `detail` is
|
|
42
|
+
* optional display text (a schema, a path). The neutral provider offers none. See
|
|
43
|
+
* `TemplateProvider.templateCandidates`. */
|
|
44
|
+
export interface TemplateCandidate {
|
|
45
|
+
label: string;
|
|
46
|
+
detail?: string;
|
|
47
|
+
}
|
|
40
48
|
/** Everything known about one call's expansion. Every field optional; `undefined` = unknown. */
|
|
41
49
|
export interface ResolvedExpansion {
|
|
42
50
|
/** Parse-time shape. When absent, derived from the strongest present field:
|
|
@@ -80,23 +88,30 @@ export declare class DefaultTemplateProvider implements SchemaProvider {
|
|
|
80
88
|
tables(_dialect?: string): string[];
|
|
81
89
|
/** Monotonic invalidation signal — bumps when `prime()` warmed anything new. */
|
|
82
90
|
get version(): number;
|
|
83
|
-
/** The relation a call produces.
|
|
84
|
-
* `source
|
|
85
|
-
* overriding provider answers the
|
|
86
|
-
relationOf(
|
|
87
|
-
/** The scalar value a call yields.
|
|
88
|
-
*
|
|
89
|
-
valueOf(
|
|
91
|
+
/** The relation a call produces. The NEUTRAL floor knows no macro vocabulary, so it answers
|
|
92
|
+
* undefined for everything: `ref`/`source` are dbt macros, not minijinja knowledge, and live in
|
|
93
|
+
* `DbtTemplateProvider`. An overriding provider answers the relation (+columns) it knows. */
|
|
94
|
+
relationOf(_call: TemplateCall): ResolvedRelation | undefined;
|
|
95
|
+
/** The scalar value a call yields. Neutral floor: unknown (no macro vocabulary). `env_var` is a
|
|
96
|
+
* dbt builtin known by `DbtTemplateProvider`. */
|
|
97
|
+
valueOf(_call: TemplateCall): {
|
|
90
98
|
type: ValueType;
|
|
91
99
|
} | undefined;
|
|
92
|
-
/** The rendered-output shape of a call.
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
shapeOf(
|
|
100
|
+
/** The rendered-output shape of a call. Neutral floor: unknown (the engine derives a shape from
|
|
101
|
+
* stronger fields, or falls back to its positional fill). The dbt no-output builtins → "nothing"
|
|
102
|
+
* is `DbtTemplateProvider` knowledge. */
|
|
103
|
+
shapeOf(_call: TemplateCall): ExpansionShape | undefined;
|
|
96
104
|
/** The columns a column-list-producing macro emits. Default: unknown. */
|
|
97
105
|
columnsOf(_call: TemplateCall): Column[] | undefined;
|
|
98
106
|
/** The items a loop collection holds. Default: unknown (loops analyze one representative pass). */
|
|
99
107
|
collectionOf(_call: TemplateCall): string[] | undefined;
|
|
108
|
+
/** Completion candidates for a template call slot: the caret sits in `callee`'s positional argument
|
|
109
|
+
* `argIndex` (a dbt ref's arg 0 answers the model names, a source's arg 0 the source names, arg 1
|
|
110
|
+
* the table names). `argIndex` is -1 when the caret is still in the callee name itself, so a host
|
|
111
|
+
* can answer the macro/callee names it knows. `packageName` is the dotted package (`dbt_utils` in
|
|
112
|
+
* `dbt_utils.star(...)`). The NEUTRAL provider knows no vocabulary and offers none; a host answers
|
|
113
|
+
* from its catalog. `completeAt` reads this when the caret is inside a jinja tag. */
|
|
114
|
+
templateCandidates(_callee: string, _argIndex: number, _packageName?: string): TemplateCandidate[];
|
|
100
115
|
/**
|
|
101
116
|
* Everything known about `call`, composed from the granular methods. Field precedence for the
|
|
102
117
|
* shape (channel-agreed): an EXPLICIT `shapeOf` answer always wins; absent, derived
|
|
@@ -134,7 +149,25 @@ export declare class DefaultTemplateProvider implements SchemaProvider {
|
|
|
134
149
|
prime(): Promise<boolean>;
|
|
135
150
|
private drain;
|
|
136
151
|
}
|
|
137
|
-
/**
|
|
152
|
+
/**
|
|
153
|
+
* The shipped dbt overlay: a `DefaultTemplateProvider` that knows dbt's built-in macros and nothing
|
|
154
|
+
* more. `ref(...)` resolves to the dbt-LOGICAL model name, `source(a,b)` to the logical
|
|
155
|
+
* [source, table], `env_var` to a string, and the no-output builtins
|
|
156
|
+
* (config/docs/print/log/return/exceptions) render nothing. Static famous-macro knowledge ONLY: no
|
|
157
|
+
* manifest, no warehouse, no project config, no runtime. A dbt consumer with runtime knowledge
|
|
158
|
+
* extends THIS (not the neutral `DefaultTemplateProvider`) and overrides the granular methods with
|
|
159
|
+
* what its manifest / describe cache resolve to. This class is where the dbt vocabulary lives so the
|
|
160
|
+
* neutral core and default do not carry it.
|
|
161
|
+
*/
|
|
162
|
+
export declare class DbtTemplateProvider extends DefaultTemplateProvider {
|
|
163
|
+
relationOf(call: TemplateCall): ResolvedRelation | undefined;
|
|
164
|
+
valueOf(call: TemplateCall): {
|
|
165
|
+
type: ValueType;
|
|
166
|
+
} | undefined;
|
|
167
|
+
shapeOf(call: TemplateCall): ExpansionShape | undefined;
|
|
168
|
+
}
|
|
169
|
+
/** The provider type the engine consults — the shipped base (or any subclass of it, e.g.
|
|
170
|
+
* `DbtTemplateProvider`). */
|
|
138
171
|
export type TemplateProvider = DefaultTemplateProvider;
|
|
139
172
|
/**
|
|
140
173
|
* The ONE shared no-configuration default — an OPEN world that answers nothing and diagnoses
|