sqllens 1.1.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 (234) hide show
  1. package/README.md +2 -74
  2. package/THIRD-PARTY-NOTICES.md +50 -5
  3. package/dist/api.d.ts +5 -3
  4. package/dist/api.js +11 -4
  5. package/dist/bigquery/behavior.d.ts +2 -0
  6. package/dist/bigquery/behavior.js +20 -0
  7. package/dist/bigquery/dot-path.d.ts +0 -2
  8. package/dist/bigquery/dot-path.js +0 -1
  9. package/dist/bigquery/fold.d.ts +8 -0
  10. package/dist/bigquery/fold.js +39 -0
  11. package/dist/bigquery/index.d.ts +7 -0
  12. package/dist/bigquery/index.js +10 -0
  13. package/dist/{infer/bigquery.d.ts → bigquery/infer.d.ts} +2 -2
  14. package/dist/{infer/bigquery.js → bigquery/infer.js} +4 -3
  15. package/dist/bigquery/lower.js +35 -12
  16. package/dist/bigquery/signatures.generated.d.ts +6 -0
  17. package/dist/bigquery/signatures.generated.js +1068 -0
  18. package/dist/completion/atn-walk.d.ts +13 -2
  19. package/dist/completion/atn-walk.js +13 -10
  20. package/dist/completion/complete.d.ts +4 -3
  21. package/dist/completion/complete.js +101 -45
  22. package/dist/completion/jinja-slot.d.ts +24 -0
  23. package/dist/completion/jinja-slot.js +126 -0
  24. package/dist/completion/parser-factory.d.ts +13 -1
  25. package/dist/completion/parser-factory.js +12 -0
  26. package/dist/databricks/behavior.d.ts +2 -0
  27. package/dist/databricks/behavior.js +19 -0
  28. package/dist/databricks/fold.d.ts +8 -0
  29. package/dist/databricks/fold.js +27 -0
  30. package/dist/databricks/index.d.ts +7 -0
  31. package/dist/databricks/index.js +10 -0
  32. package/dist/databricks/infer.d.ts +6 -0
  33. package/dist/databricks/infer.js +638 -0
  34. package/dist/databricks/signatures.generated.d.ts +6 -0
  35. package/dist/databricks/signatures.generated.js +1745 -0
  36. package/dist/dialect-behavior/behavior.d.ts +26 -0
  37. package/dist/dialect-behavior/behavior.js +1 -0
  38. package/dist/dialect-behavior/carrier.d.ts +5 -0
  39. package/dist/dialect-behavior/carrier.js +5 -0
  40. package/dist/dialect-behavior/coerce-rules.d.ts +7 -0
  41. package/dist/dialect-behavior/coerce-rules.js +69 -0
  42. package/dist/dialect-behavior/public-fold.d.ts +6 -0
  43. package/dist/dialect-behavior/public-fold.js +9 -0
  44. package/dist/dialect-behavior/registry.d.ts +6 -0
  45. package/dist/dialect-behavior/registry.js +34 -0
  46. package/dist/dialect-symbols.js +16 -19
  47. package/dist/document/document.d.ts +1 -1
  48. package/dist/document/document.js +8 -7
  49. package/dist/duckdb/behavior.d.ts +2 -0
  50. package/dist/duckdb/behavior.js +21 -0
  51. package/dist/duckdb/fold.d.ts +8 -0
  52. package/dist/duckdb/fold.js +29 -0
  53. package/dist/duckdb/index.d.ts +7 -0
  54. package/dist/duckdb/index.js +10 -0
  55. package/dist/{infer/duckdb.d.ts → duckdb/infer.d.ts} +2 -2
  56. package/dist/{infer/duckdb.js → duckdb/infer.js} +4 -3
  57. package/dist/duckdb/lower.js +47 -15
  58. package/dist/duckdb/signatures.generated.d.ts +6 -0
  59. package/dist/duckdb/signatures.generated.js +1072 -0
  60. package/dist/generated/bigquery/GoogleSQLParser.js +0 -7060
  61. package/dist/generated/databricks/DatabricksParser.js +0 -4800
  62. package/dist/generated/duckdb/DuckdbParser.js +0 -9100
  63. package/dist/generated/minijinja/MinijinjaParser.js +0 -380
  64. package/dist/generated/mysql/MysqlParser.js +0 -6330
  65. package/dist/generated/postgres/PostgresParser.js +0 -8530
  66. package/dist/generated/redshift/RedshiftParser.js +0 -10970
  67. package/dist/generated/snowflake/SnowflakeParser.js +0 -7320
  68. package/dist/generated/sqlite/SqliteParser.js +0 -1150
  69. package/dist/generated/trino/TrinoParser.js +0 -3770
  70. package/dist/generated/tsql/TSqlParser.js +0 -8420
  71. package/dist/ident/fold.d.ts +24 -15
  72. package/dist/ident/fold.js +12 -194
  73. package/dist/index.d.ts +2 -2
  74. package/dist/index.js +10 -8
  75. package/dist/infer/functions.d.ts +22 -11
  76. package/dist/infer/functions.js +26 -888
  77. package/dist/infer/infer.js +16 -14
  78. package/dist/infer/nullability.js +3 -4
  79. package/dist/infer/types.d.ts +1 -1
  80. package/dist/infer/types.js +7 -7
  81. package/dist/ir/ir.d.ts +26 -17
  82. package/dist/ir/span.js +0 -2
  83. package/dist/ir/walk.js +3 -3
  84. package/dist/lineage/hops.js +13 -10
  85. package/dist/lineage/lineage.js +10 -7
  86. package/dist/minijinja/apply-tags.d.ts +14 -7
  87. package/dist/minijinja/apply-tags.js +66 -121
  88. package/dist/minijinja/parse.js +5 -5
  89. package/dist/minijinja/tag-ast.d.ts +29 -36
  90. package/dist/minijinja/tag-ast.js +210 -90
  91. package/dist/mysql/behavior.d.ts +2 -0
  92. package/dist/mysql/behavior.js +21 -0
  93. package/dist/mysql/fold.d.ts +8 -0
  94. package/dist/mysql/fold.js +49 -0
  95. package/dist/mysql/index.d.ts +7 -0
  96. package/dist/mysql/index.js +10 -0
  97. package/dist/{infer/mysql.d.ts → mysql/infer.d.ts} +2 -2
  98. package/dist/{infer/mysql.js → mysql/infer.js} +3 -2
  99. package/dist/mysql/signatures.generated.d.ts +6 -0
  100. package/dist/mysql/signatures.generated.js +508 -0
  101. package/dist/postgres/behavior.d.ts +2 -0
  102. package/dist/postgres/behavior.js +19 -0
  103. package/dist/postgres/fold.d.ts +8 -0
  104. package/dist/postgres/fold.js +30 -0
  105. package/dist/postgres/index.d.ts +7 -0
  106. package/dist/postgres/index.js +10 -0
  107. package/dist/{infer/postgres.d.ts → postgres/infer.d.ts} +2 -2
  108. package/dist/{infer/postgres.js → postgres/infer.js} +4 -3
  109. package/dist/postgres/lower.js +2 -2
  110. package/dist/postgres/signatures.generated.d.ts +6 -0
  111. package/dist/postgres/signatures.generated.js +2973 -0
  112. package/dist/qualify/check-calls.js +80 -161
  113. package/dist/qualify/qualify.js +16 -14
  114. package/dist/qualify/schema-provider.js +2 -2
  115. package/dist/qualify/schema.js +3 -3
  116. package/dist/qualify/template-provider.d.ts +45 -12
  117. package/dist/qualify/template-provider.js +69 -38
  118. package/dist/redshift/behavior.d.ts +2 -0
  119. package/dist/redshift/behavior.js +19 -0
  120. package/dist/redshift/fold.d.ts +8 -0
  121. package/dist/redshift/fold.js +31 -0
  122. package/dist/redshift/index.d.ts +7 -0
  123. package/dist/redshift/index.js +10 -0
  124. package/dist/{infer/redshift.d.ts → redshift/infer.d.ts} +2 -2
  125. package/dist/{infer/redshift.js → redshift/infer.js} +4 -3
  126. package/dist/redshift/lower.js +2 -2
  127. package/dist/redshift/signatures.generated.d.ts +6 -0
  128. package/dist/redshift/signatures.generated.js +757 -0
  129. package/dist/references/references.js +17 -12
  130. package/dist/scope/like-pattern.d.ts +2 -0
  131. package/dist/scope/like-pattern.js +15 -0
  132. package/dist/scope/scope.d.ts +5 -5
  133. package/dist/scope/scope.js +48 -42
  134. package/dist/sema/resolve.js +17 -12
  135. package/dist/session.d.ts +2 -2
  136. package/dist/signature/signature.d.ts +14 -6
  137. package/dist/signature/signature.js +30 -22
  138. package/dist/signature/signatures.d.ts +14 -12
  139. package/dist/signature/signatures.js +42 -721
  140. package/dist/snowflake/behavior.d.ts +2 -0
  141. package/dist/snowflake/behavior.js +22 -0
  142. package/dist/snowflake/fold.d.ts +8 -0
  143. package/dist/snowflake/fold.js +25 -0
  144. package/dist/snowflake/index.d.ts +7 -0
  145. package/dist/snowflake/index.js +10 -0
  146. package/dist/{infer/snowflake.d.ts → snowflake/infer.d.ts} +2 -2
  147. package/dist/{infer/snowflake.js → snowflake/infer.js} +4 -3
  148. package/dist/snowflake/lower.js +59 -19
  149. package/dist/snowflake/signatures.generated.d.ts +6 -0
  150. package/dist/snowflake/signatures.generated.js +2080 -0
  151. package/dist/sqlite/behavior.d.ts +2 -0
  152. package/dist/sqlite/behavior.js +19 -0
  153. package/dist/sqlite/fold.d.ts +8 -0
  154. package/dist/sqlite/fold.js +41 -0
  155. package/dist/sqlite/index.d.ts +7 -0
  156. package/dist/sqlite/index.js +10 -0
  157. package/dist/{infer/sqlite.d.ts → sqlite/infer.d.ts} +2 -2
  158. package/dist/{infer/sqlite.js → sqlite/infer.js} +4 -3
  159. package/dist/sqlite/signatures.generated.d.ts +6 -0
  160. package/dist/sqlite/signatures.generated.js +277 -0
  161. package/dist/symbols/symbols.js +14 -12
  162. package/dist/trino/behavior.d.ts +2 -0
  163. package/dist/trino/behavior.js +21 -0
  164. package/dist/trino/fold.d.ts +8 -0
  165. package/dist/trino/fold.js +39 -0
  166. package/dist/trino/index.d.ts +7 -0
  167. package/dist/trino/index.js +10 -0
  168. package/dist/{infer/trino.d.ts → trino/infer.d.ts} +2 -2
  169. package/dist/{infer/trino.js → trino/infer.js} +4 -3
  170. package/dist/trino/lower.js +5 -5
  171. package/dist/trino/signatures.generated.d.ts +6 -0
  172. package/dist/trino/signatures.generated.js +968 -0
  173. package/dist/tsql/behavior.d.ts +2 -0
  174. package/dist/tsql/behavior.js +20 -0
  175. package/dist/tsql/fold.d.ts +8 -0
  176. package/dist/tsql/fold.js +34 -0
  177. package/dist/tsql/index.d.ts +7 -0
  178. package/dist/tsql/index.js +10 -0
  179. package/dist/tsql/infer.d.ts +16 -0
  180. package/dist/tsql/infer.js +289 -0
  181. package/dist/tsql/lower.js +4 -4
  182. package/dist/tsql/signatures.generated.d.ts +6 -0
  183. package/dist/tsql/signatures.generated.js +640 -0
  184. package/package.json +5 -10
  185. package/dist/generated/bigquery/GoogleSQLLexer.d.ts +0 -407
  186. package/dist/generated/bigquery/GoogleSQLParser.d.ts +0 -9558
  187. package/dist/generated/bigquery/GoogleSQLParserListener.d.ts +0 -7777
  188. package/dist/generated/bigquery/GoogleSQLParserListener.js +0 -7070
  189. package/dist/generated/databricks/DatabricksLexer.d.ts +0 -566
  190. package/dist/generated/databricks/DatabricksParser.d.ts +0 -7771
  191. package/dist/generated/databricks/DatabricksParserListener.d.ts +0 -5737
  192. package/dist/generated/databricks/DatabricksParserListener.js +0 -5256
  193. package/dist/generated/duckdb/DuckdbLexer.d.ts +0 -691
  194. package/dist/generated/duckdb/DuckdbParser.d.ts +0 -13932
  195. package/dist/generated/duckdb/DuckdbParserListener.d.ts +0 -10049
  196. package/dist/generated/duckdb/DuckdbParserListener.js +0 -9138
  197. package/dist/generated/minijinja/MinijinjaLexer.d.ts +0 -108
  198. package/dist/generated/minijinja/MinijinjaParser.d.ts +0 -604
  199. package/dist/generated/minijinja/MinijinjaParserListener.d.ts +0 -449
  200. package/dist/generated/minijinja/MinijinjaParserListener.js +0 -410
  201. package/dist/generated/mysql/MysqlLexer.d.ts +0 -1198
  202. package/dist/generated/mysql/MysqlParser.d.ts +0 -10992
  203. package/dist/generated/mysql/MysqlParserListener.d.ts +0 -7592
  204. package/dist/generated/mysql/MysqlParserListener.js +0 -6958
  205. package/dist/generated/postgres/PostgresLexer.d.ts +0 -663
  206. package/dist/generated/postgres/PostgresParser.d.ts +0 -12963
  207. package/dist/generated/postgres/PostgresParserListener.d.ts +0 -9408
  208. package/dist/generated/postgres/PostgresParserListener.js +0 -8554
  209. package/dist/generated/redshift/RedshiftLexer.d.ts +0 -954
  210. package/dist/generated/redshift/RedshiftParser.d.ts +0 -16939
  211. package/dist/generated/redshift/RedshiftParserListener.d.ts +0 -12092
  212. package/dist/generated/redshift/RedshiftParserListener.js +0 -10994
  213. package/dist/generated/snowflake/SnowflakeLexer.d.ts +0 -1046
  214. package/dist/generated/snowflake/SnowflakeParser.d.ts +0 -14196
  215. package/dist/generated/snowflake/SnowflakeParserListener.d.ts +0 -8063
  216. package/dist/generated/snowflake/SnowflakeParserListener.js +0 -7330
  217. package/dist/generated/sqlite/SqliteLexer.d.ts +0 -210
  218. package/dist/generated/sqlite/SqliteParser.d.ts +0 -2115
  219. package/dist/generated/sqlite/SqliteParserListener.d.ts +0 -1276
  220. package/dist/generated/sqlite/SqliteParserListener.js +0 -1160
  221. package/dist/generated/trino/TrinoLexer.d.ts +0 -381
  222. package/dist/generated/trino/TrinoParser.d.ts +0 -5340
  223. package/dist/generated/trino/TrinoParserListener.d.ts +0 -4704
  224. package/dist/generated/trino/TrinoParserListener.js +0 -4326
  225. package/dist/generated/tsql/TSqlLexer.d.ts +0 -1278
  226. package/dist/generated/tsql/TSqlParser.d.ts +0 -17267
  227. package/dist/generated/tsql/TSqlParserListener.d.ts +0 -9697
  228. package/dist/generated/tsql/TSqlParserListener.js +0 -8854
  229. package/dist/infer/dialect.d.ts +0 -21
  230. package/dist/infer/dialect.js +0 -100
  231. package/dist/infer/literals.d.ts +0 -6
  232. package/dist/infer/literals.js +0 -44
  233. package/dist/signature/generated/tsql.d.ts +0 -3
  234. package/dist/signature/generated/tsql.js +0 -260
@@ -0,0 +1,2 @@
1
+ import type { DialectBehavior } from "../dialect-behavior/behavior.js";
2
+ export declare const snowflakeBehavior: DialectBehavior;
@@ -0,0 +1,22 @@
1
+ import { acceptsFor } from "../dialect-behavior/coerce-rules.js";
2
+ import { likePatternToRegExp } from "../scope/like-pattern.js";
3
+ import { SIGNATURES } from "../signature/signatures.js";
4
+ import { displayName, fold, foldTableName, matchesSourceKey } from "./fold.js";
5
+ import { snowflakeLiteral, snowflakeParseType, SNOWFLAKE_FUNCTION_RETURNS, snowflakeSpecial } from "./infer.js";
6
+ // Snowflake implicit coercion: VARCHAR containing a number coerces to NUMBER (str->num), no bool<->num.
7
+ const STR_TO_NUM = true;
8
+ const BOOL_NUM = false;
9
+ export const snowflakeBehavior = {
10
+ fold,
11
+ displayName,
12
+ foldTableName,
13
+ matchesSourceKey,
14
+ likeMatch: (pattern, value) => likePatternToRegExp(pattern).test(value),
15
+ literal: snowflakeLiteral,
16
+ parseType: snowflakeParseType,
17
+ functions: SNOWFLAKE_FUNCTION_RETURNS,
18
+ division: "decimal", // Snowflake: 10/3 -> 3.333333, a scaled NUMBER unless a float is involved
19
+ special: snowflakeSpecial,
20
+ signatures: SIGNATURES.snowflake,
21
+ accepts: (argType, paramText) => acceptsFor(snowflakeParseType, STR_TO_NUM, BOOL_NUM, argType, paramText),
22
+ };
@@ -0,0 +1,8 @@
1
+ import { type FoldRule, type IdentKind } from "../ident/fold.js";
2
+ export declare const SNOWFLAKE_FOLD_RULE: FoldRule;
3
+ /** Fold an identifier to its Snowflake identity key. */
4
+ export declare function fold(raw: string, kind?: IdentKind): string;
5
+ /** Presentation twin: strip delimiters, no case change. */
6
+ export declare function displayName(raw: string): string;
7
+ export declare function foldTableName(parts: string[]): string[];
8
+ export declare function matchesSourceKey(key: string, rawPart: string): boolean;
@@ -0,0 +1,25 @@
1
+ // Snowflake identifier folding. The FoldRule plus its bound engine, colocated here because BOTH the
2
+ // upstream lower() and the downstream DialectBehavior need it (the fold rule is the one dialect concern
3
+ // used at two stages). Snowflake unquoted identifiers fold to UPPER; quoted identifiers preserve case
4
+ // (docs.snowflake.com/en/sql-reference/identifiers-syntax); double-quote is the delimiter, doubled to escape.
5
+ import { displayWith, foldWith } from "../ident/fold.js";
6
+ const DOUBLE_QUOTE = ['"', '"'];
7
+ export const SNOWFLAKE_FOLD_RULE = {
8
+ delimiters: [DOUBLE_QUOTE],
9
+ unquoted: "upper",
10
+ quoted: "preserve",
11
+ };
12
+ /** Fold an identifier to its Snowflake identity key. */
13
+ export function fold(raw, kind = "other") {
14
+ return foldWith(SNOWFLAKE_FOLD_RULE, raw, kind);
15
+ }
16
+ /** Presentation twin: strip delimiters, no case change. */
17
+ export function displayName(raw) {
18
+ return displayWith(SNOWFLAKE_FOLD_RULE, raw);
19
+ }
20
+ export function foldTableName(parts) {
21
+ return parts.map((p) => fold(p, "table"));
22
+ }
23
+ export function matchesSourceKey(key, rawPart) {
24
+ return key === fold(rawPart) || key === fold(rawPart, "table");
25
+ }
@@ -0,0 +1,7 @@
1
+ import { lower } from "./lower.js";
2
+ import { parseSnowflake } from "./parse.js";
3
+ export declare const snowflake: {
4
+ parse: typeof parseSnowflake;
5
+ lower: typeof lower;
6
+ behavior: import("../dialect-behavior/behavior.js").DialectBehavior;
7
+ };
@@ -0,0 +1,10 @@
1
+ // The complete snowflake dialect module: parse + lower (front end) and behavior (semantic knowledge).
2
+ // The registry wires this; to understand everything sqllens does for snowflake, read this folder.
3
+ import { snowflakeBehavior } from "./behavior.js";
4
+ import { lower } from "./lower.js";
5
+ import { parseSnowflake } from "./parse.js";
6
+ export const snowflake = {
7
+ parse: parseSnowflake,
8
+ lower,
9
+ behavior: snowflakeBehavior,
10
+ };
@@ -1,6 +1,6 @@
1
1
  import type { Expr } from "../ir/ir.js";
2
- import type { FnRule } from "./functions.js";
3
- import { type Type } from "./types.js";
2
+ import type { FnRule } from "../infer/functions.js";
3
+ import { type Type } from "../infer/types.js";
4
4
  export declare const SNOWFLAKE_FUNCTION_RETURNS: Record<string, FnRule>;
5
5
  /** Snowflake literal forms: '…' / $$…$$ → string; integers are NUMBER(38,0) (int
6
6
  * canonically); non-integers are NUMBER (decimal); 1e3 is approximate (double). */
@@ -1,5 +1,6 @@
1
- import { commonType, widenSum } from "./coerce.js";
2
- import { parseType, scalar, UNKNOWN } from "./types.js";
1
+ import { commonType, widenSum } from "../infer/coerce.js";
2
+ import { parseType, scalar, UNKNOWN } from "../infer/types.js";
3
+ import { fold } from "./fold.js";
3
4
  // Snowflake inference knowledge — function return types, literal forms, and scalar-type
4
5
  // aliases — from the SQL function reference (docs.snowflake.com/en/sql-reference/functions).
5
6
  // Same contract as the other dialects: a rule is absent (→ unknown) only when the documented
@@ -557,7 +558,7 @@ export const SNOWFLAKE_ALIASES = {
557
558
  bool: "boolean",
558
559
  };
559
560
  export function snowflakeParseType(text) {
560
- return parseType(text, SNOWFLAKE_ALIASES, "snowflake");
561
+ return parseType(text, SNOWFLAKE_ALIASES, fold);
561
562
  }
562
563
  /** Pre-registry hook for calls a plain FnRule can't key. `<seq>.NEXTVAL` carries the sequence as a
563
564
  * (variable) qualifier, so no registry key can enumerate it; NEXTVAL always returns NUMBER(38,0)
@@ -3,7 +3,7 @@ import { SnowflakeParser as P } from "../generated/snowflake/SnowflakeParser.js"
3
3
  import { keywordCategory, swallowedCategories, swallowedStatements } from "../ir/statement.js";
4
4
  import { partSpansOf } from "../ir/part-span.js";
5
5
  import { freezeIR } from "../ir/freeze.js";
6
- import { displayName } from "../ident/fold.js";
6
+ import { displayName } from "./fold.js";
7
7
  // ---------------------------------------------------------------------------
8
8
  // Lowering — Snowflake (grammars-v4 sql/snowflake fork) CST -> the shared,
9
9
  // dialect-neutral IR (src/ir/ir.ts). The semantic layer runs on the IR
@@ -958,15 +958,16 @@ function lowerExpr(node) {
958
958
  // expr ! method ( args ) — class-instance method call
959
959
  if (hasDirectToken(node, P.BANG)) {
960
960
  const method = directChildrenOfRule(node, P.RULE_id_)[0];
961
- const args = [
962
- ...exprListExprs(node).map(lowerExpr),
963
- ...directChildrenOfRule(node, P.RULE_param_assoc_list).flatMap(paramAssocValues),
964
- ];
961
+ const positional = exprListExprs(node).map(lowerExpr);
962
+ const paramAssoc = directChildrenOfRule(node, P.RULE_param_assoc_list).flatMap(paramAssocValues);
965
963
  const base = exprs[0] ? lowerExpr(exprs[0]) : otherExpr(node);
964
+ const args = [base, ...positional, ...paramAssoc.map((v) => v.arg)];
965
+ const argNames = [undefined, ...positional.map(() => undefined), ...paramAssoc.map((v) => v.name)];
966
966
  return {
967
967
  kind: "function",
968
968
  name: method ? method.getText() : "",
969
- args: [base, ...args],
969
+ args,
970
+ ...(argNames.some((n) => n !== undefined) ? { argNames } : {}),
970
971
  aggregate: false,
971
972
  distinct: false,
972
973
  cst: node,
@@ -1236,7 +1237,7 @@ function lowerFunctionCall(node) {
1236
1237
  const agg = directChildrenOfRule(node, P.RULE_aggregate_function)[0];
1237
1238
  if (agg) {
1238
1239
  const id = directChildrenOfRule(agg, P.RULE_id_)[0];
1239
- const name = (id ? displayName(id.getText(), "snowflake") : (leftmostToken(agg) ?? "")).toLowerCase();
1240
+ const name = (id ? displayName(id.getText()) : (leftmostToken(agg) ?? "")).toLowerCase();
1240
1241
  const args = [
1241
1242
  ...exprListExprs(agg).map(lowerExpr),
1242
1243
  ...directChildrenOfRule(agg, P.RULE_expr).map(lowerExpr),
@@ -1252,40 +1253,79 @@ function lowerFunctionCall(node) {
1252
1253
  cst: node,
1253
1254
  };
1254
1255
  }
1256
+ // EXTRACT LR_BRACKET (id_ | string) (FROM | COMMA) expr RR_BRACKET: the date-part operand is an
1257
+ // id_/string child, not an expr, so the generic collection below drops it and every
1258
+ // EXTRACT(part FROM ts) call under-counts to one argument (a wrong-arity false positive on valid
1259
+ // SQL once the arity checker trusts the generated signatures). Lowered as a literal, never a
1260
+ // column ref: a date part must not join name resolution.
1261
+ if (hasTokenShallow(node, P.EXTRACT)) {
1262
+ const part = directChildrenOfRule(node, P.RULE_id_)[0] ?? directChildrenOfRule(node, P.RULE_string)[0];
1263
+ const partArgs = part ? [{ kind: "literal", text: part.getText(), cst: part }] : [];
1264
+ return {
1265
+ kind: "function",
1266
+ name: "extract",
1267
+ args: [...partArgs, ...directChildrenOfRule(node, P.RULE_expr).map(lowerExpr)],
1268
+ aggregate: false,
1269
+ distinct: false,
1270
+ cst: node,
1271
+ };
1272
+ }
1255
1273
  const name = functionName(node);
1256
- const args = [
1274
+ const positional = [
1257
1275
  ...exprListExprs(node).map(lowerExpr),
1258
1276
  ...directChildrenOfRule(node, P.RULE_expr).map(lowerExpr),
1259
- ...directChildrenOfRule(node, P.RULE_param_assoc_list).flatMap(paramAssocValues),
1260
- // the object_name(func_arg_list) alternative — positional exprs and named-arg values
1261
- // (STAR / stage / spread / TYPE args carry no expr payload and add nothing here).
1262
- // Also the SLL-surgery wave's home for plain f(args) calls (2026-07-03).
1263
- ...directChildrenOfRule(node, P.RULE_func_arg_list).flatMap(funcArgValues),
1277
+ ];
1278
+ const paramAssoc = directChildrenOfRule(node, P.RULE_param_assoc_list).flatMap(paramAssocValues);
1279
+ // the object_name(func_arg_list) alternative — positional exprs and named-arg values
1280
+ // (STAR / stage / spread / TYPE args carry no expr payload and add nothing here).
1281
+ // Also the SLL-surgery wave's home for plain f(args) calls (2026-07-03).
1282
+ const funcArg = directChildrenOfRule(node, P.RULE_func_arg_list).flatMap(funcArgValues);
1283
+ const args = [...positional, ...paramAssoc.map((v) => v.arg), ...funcArg.map((v) => v.arg)];
1284
+ const argNames = [
1285
+ ...positional.map(() => undefined),
1286
+ ...paramAssoc.map((v) => v.name),
1287
+ ...funcArg.map((v) => v.name),
1264
1288
  ];
1265
1289
  return {
1266
1290
  kind: "function",
1267
1291
  name: name.toLowerCase(),
1268
1292
  args,
1293
+ // Named-argument invocation `fn(name => value)`: the per-arg names make the call
1294
+ // conservation-visible and let the arity checker's named-arg bypass fire (a named call's
1295
+ // positional count says nothing about the documented positional signature).
1296
+ ...(argNames.some((n) => n !== undefined) ? { argNames } : {}),
1269
1297
  aggregate: AGGREGATES.has(name.toLowerCase()),
1270
1298
  distinct: hasTokenShallow(node, P.DISTINCT),
1271
1299
  cst: node,
1272
1300
  };
1273
1301
  }
1302
+ /** One func_arg's lowered value plus its `name =>` parameter name (undefined for a plain positional
1303
+ * expr). STAR / stage / spread / TYPE / TABLE(...) args carry no expr payload and are skipped. */
1274
1304
  function funcArgValues(list) {
1275
1305
  return directChildrenOfRule(list, P.RULE_func_arg).flatMap((fa) => {
1276
1306
  const e = directChildrenOfRule(fa, P.RULE_expr)[0];
1277
1307
  if (e)
1278
- return [lowerExpr(e)];
1308
+ return [{ arg: lowerExpr(e), name: undefined }];
1279
1309
  const pa = directChildrenOfRule(fa, P.RULE_param_assoc)[0];
1280
- const pe = pa ? directChildrenOfRule(pa, P.RULE_expr)[0] : undefined;
1281
- return pe ? [lowerExpr(pe)] : [];
1310
+ const one = pa ? oneParamAssoc(pa) : undefined;
1311
+ return one ? [one] : [];
1282
1312
  });
1283
1313
  }
1314
+ /** param_assoc_list: every param_assoc child, each lowered via oneParamAssoc. */
1284
1315
  function paramAssocValues(list) {
1285
1316
  return directChildrenOfRule(list, P.RULE_param_assoc)
1286
- .map((pa) => directChildrenOfRule(pa, P.RULE_expr)[0])
1287
- .filter((e) => e !== undefined)
1288
- .map(lowerExpr);
1317
+ .map(oneParamAssoc)
1318
+ .filter((v) => v !== undefined);
1319
+ }
1320
+ /** param_assoc: `(id_ | FILE_FORMAT | PATTERN | LIMIT) ASSOC expr`; the name is the id_ rule when
1321
+ * present, else the leading keyword token itself. */
1322
+ function oneParamAssoc(pa) {
1323
+ const e = directChildrenOfRule(pa, P.RULE_expr)[0];
1324
+ if (!e)
1325
+ return undefined;
1326
+ const id = directChildrenOfRule(pa, P.RULE_id_)[0];
1327
+ const name = id ? id.getText() : leftmostToken(pa);
1328
+ return { arg: lowerExpr(e), name };
1289
1329
  }
1290
1330
  function functionName(node) {
1291
1331
  const obj = directChildrenOfRule(node, P.RULE_object_name)[0];
@@ -0,0 +1,6 @@
1
+ import type { FnSignature } from "../signature/signatures.js";
2
+ /** The merged function-signature table for snowflake: curated overrides folded over the harvested
3
+ * doc-derived long tail (overrides win by key, replacing the whole overload set), keyed by
4
+ * lowercased name. Each name maps to an ORDERED overload set - a name with one documented shape
5
+ * is a one-element array. `origin` says which layer produced the set. */
6
+ export declare const SNOWFLAKE_SIGNATURES: Record<string, FnSignature[]>;