sqllens 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. package/LICENSE +0 -10
  2. package/README.md +95 -85
  3. package/THIRD-PARTY-NOTICES.md +70 -5
  4. package/dist/api.d.ts +5 -3
  5. package/dist/api.js +17 -4
  6. package/dist/bigquery/behavior.d.ts +2 -0
  7. package/dist/bigquery/behavior.js +20 -0
  8. package/dist/bigquery/dot-path.d.ts +0 -2
  9. package/dist/bigquery/dot-path.js +0 -1
  10. package/dist/bigquery/fold.d.ts +8 -0
  11. package/dist/bigquery/fold.js +39 -0
  12. package/dist/bigquery/index.d.ts +7 -0
  13. package/dist/bigquery/index.js +10 -0
  14. package/dist/{infer/bigquery.d.ts → bigquery/infer.d.ts} +2 -2
  15. package/dist/{infer/bigquery.js → bigquery/infer.js} +4 -3
  16. package/dist/bigquery/lower.js +35 -12
  17. package/dist/bigquery/signatures.generated.d.ts +6 -0
  18. package/dist/bigquery/signatures.generated.js +1068 -0
  19. package/dist/completion/atn-walk.d.ts +13 -2
  20. package/dist/completion/atn-walk.js +13 -10
  21. package/dist/completion/complete.d.ts +4 -3
  22. package/dist/completion/complete.js +101 -45
  23. package/dist/completion/config.js +66 -0
  24. package/dist/completion/jinja-slot.d.ts +24 -0
  25. package/dist/completion/jinja-slot.js +126 -0
  26. package/dist/completion/parser-factory.d.ts +13 -1
  27. package/dist/completion/parser-factory.js +48 -0
  28. package/dist/databricks/behavior.d.ts +2 -0
  29. package/dist/databricks/behavior.js +19 -0
  30. package/dist/databricks/fold.d.ts +8 -0
  31. package/dist/databricks/fold.js +27 -0
  32. package/dist/databricks/index.d.ts +7 -0
  33. package/dist/databricks/index.js +10 -0
  34. package/dist/databricks/infer.d.ts +6 -0
  35. package/dist/databricks/infer.js +638 -0
  36. package/dist/databricks/signatures.generated.d.ts +6 -0
  37. package/dist/databricks/signatures.generated.js +1745 -0
  38. package/dist/derived-dialects.js +19 -1
  39. package/dist/dialect-behavior/behavior.d.ts +26 -0
  40. package/dist/dialect-behavior/behavior.js +1 -0
  41. package/dist/dialect-behavior/carrier.d.ts +5 -0
  42. package/dist/dialect-behavior/carrier.js +5 -0
  43. package/dist/dialect-behavior/coerce-rules.d.ts +7 -0
  44. package/dist/dialect-behavior/coerce-rules.js +69 -0
  45. package/dist/dialect-behavior/public-fold.d.ts +6 -0
  46. package/dist/dialect-behavior/public-fold.js +9 -0
  47. package/dist/dialect-behavior/registry.d.ts +6 -0
  48. package/dist/dialect-behavior/registry.js +34 -0
  49. package/dist/dialect-symbols.js +22 -17
  50. package/dist/dialect.d.ts +2 -2
  51. package/dist/document/document.d.ts +1 -1
  52. package/dist/document/document.js +8 -7
  53. package/dist/duckdb/behavior.d.ts +2 -0
  54. package/dist/duckdb/behavior.js +21 -0
  55. package/dist/duckdb/fold.d.ts +8 -0
  56. package/dist/duckdb/fold.js +29 -0
  57. package/dist/duckdb/index.d.ts +7 -0
  58. package/dist/duckdb/index.js +10 -0
  59. package/dist/{infer/duckdb.d.ts → duckdb/infer.d.ts} +2 -2
  60. package/dist/{infer/duckdb.js → duckdb/infer.js} +4 -3
  61. package/dist/duckdb/lower.js +47 -15
  62. package/dist/duckdb/signatures.generated.d.ts +6 -0
  63. package/dist/duckdb/signatures.generated.js +1072 -0
  64. package/dist/generated/bigquery/GoogleSQLParser.js +0 -7060
  65. package/dist/generated/databricks/DatabricksParser.js +0 -4800
  66. package/dist/generated/duckdb/DuckdbParser.js +0 -9100
  67. package/dist/generated/minijinja/MinijinjaParser.js +0 -380
  68. package/dist/generated/mysql/MysqlLexer.js +7357 -0
  69. package/dist/generated/mysql/MysqlParser.js +78520 -0
  70. package/dist/generated/postgres/PostgresParser.js +0 -8530
  71. package/dist/generated/redshift/RedshiftParser.js +0 -10970
  72. package/dist/generated/snowflake/SnowflakeParser.js +0 -7320
  73. package/dist/generated/sqlite/SqliteLexer.js +945 -0
  74. package/dist/generated/sqlite/SqliteParser.js +14682 -0
  75. package/dist/generated/trino/TrinoParser.js +0 -3770
  76. package/dist/generated/tsql/TSqlParser.js +0 -8420
  77. package/dist/ident/fold.d.ts +24 -15
  78. package/dist/ident/fold.js +12 -145
  79. package/dist/index.d.ts +6 -2
  80. package/dist/index.js +14 -8
  81. package/dist/infer/functions.d.ts +22 -11
  82. package/dist/infer/functions.js +26 -888
  83. package/dist/infer/infer.js +16 -14
  84. package/dist/infer/nullability.js +3 -4
  85. package/dist/infer/types.d.ts +1 -1
  86. package/dist/infer/types.js +7 -7
  87. package/dist/ir/ir.d.ts +26 -17
  88. package/dist/ir/part-span.d.ts +16 -1
  89. package/dist/ir/part-span.js +38 -10
  90. package/dist/ir/span.js +0 -2
  91. package/dist/ir/walk.js +3 -3
  92. package/dist/lineage/hops.js +13 -10
  93. package/dist/lineage/lineage.js +10 -7
  94. package/dist/minijinja/apply-tags.d.ts +14 -7
  95. package/dist/minijinja/apply-tags.js +66 -121
  96. package/dist/minijinja/parse.js +6 -6
  97. package/dist/minijinja/tag-ast.d.ts +29 -36
  98. package/dist/minijinja/tag-ast.js +210 -90
  99. package/dist/mysql/behavior.d.ts +2 -0
  100. package/dist/mysql/behavior.js +21 -0
  101. package/dist/mysql/fold.d.ts +8 -0
  102. package/dist/mysql/fold.js +49 -0
  103. package/dist/mysql/index.d.ts +7 -0
  104. package/dist/mysql/index.js +10 -0
  105. package/dist/mysql/infer.d.ts +20 -0
  106. package/dist/mysql/infer.js +156 -0
  107. package/dist/mysql/lower.d.ts +13 -0
  108. package/dist/mysql/lower.js +1443 -0
  109. package/dist/mysql/parse.d.ts +10 -0
  110. package/dist/mysql/parse.js +70 -0
  111. package/dist/mysql/signatures.generated.d.ts +6 -0
  112. package/dist/mysql/signatures.generated.js +508 -0
  113. package/dist/postgres/behavior.d.ts +2 -0
  114. package/dist/postgres/behavior.js +19 -0
  115. package/dist/postgres/fold.d.ts +8 -0
  116. package/dist/postgres/fold.js +30 -0
  117. package/dist/postgres/index.d.ts +7 -0
  118. package/dist/postgres/index.js +10 -0
  119. package/dist/{infer/postgres.d.ts → postgres/infer.d.ts} +2 -2
  120. package/dist/{infer/postgres.js → postgres/infer.js} +4 -3
  121. package/dist/postgres/lower.js +2 -2
  122. package/dist/postgres/signatures.generated.d.ts +6 -0
  123. package/dist/postgres/signatures.generated.js +2973 -0
  124. package/dist/qualify/check-calls.js +80 -134
  125. package/dist/qualify/qualify.js +16 -14
  126. package/dist/qualify/schema-provider.js +2 -2
  127. package/dist/qualify/schema.js +3 -3
  128. package/dist/qualify/template-provider.d.ts +45 -12
  129. package/dist/qualify/template-provider.js +69 -38
  130. package/dist/redshift/behavior.d.ts +2 -0
  131. package/dist/redshift/behavior.js +19 -0
  132. package/dist/redshift/fold.d.ts +8 -0
  133. package/dist/redshift/fold.js +31 -0
  134. package/dist/redshift/index.d.ts +7 -0
  135. package/dist/redshift/index.js +10 -0
  136. package/dist/{infer/redshift.d.ts → redshift/infer.d.ts} +2 -2
  137. package/dist/{infer/redshift.js → redshift/infer.js} +4 -3
  138. package/dist/redshift/lower.js +2 -2
  139. package/dist/redshift/signatures.generated.d.ts +6 -0
  140. package/dist/redshift/signatures.generated.js +757 -0
  141. package/dist/references/references.js +17 -12
  142. package/dist/scope/like-pattern.d.ts +2 -0
  143. package/dist/scope/like-pattern.js +15 -0
  144. package/dist/scope/scope.d.ts +5 -5
  145. package/dist/scope/scope.js +48 -42
  146. package/dist/sema/resolve.js +17 -12
  147. package/dist/session.d.ts +2 -2
  148. package/dist/signature/signature.d.ts +14 -6
  149. package/dist/signature/signature.js +30 -22
  150. package/dist/signature/signatures.d.ts +14 -12
  151. package/dist/signature/signatures.js +42 -582
  152. package/dist/snowflake/behavior.d.ts +2 -0
  153. package/dist/snowflake/behavior.js +22 -0
  154. package/dist/snowflake/fold.d.ts +8 -0
  155. package/dist/snowflake/fold.js +25 -0
  156. package/dist/snowflake/index.d.ts +7 -0
  157. package/dist/snowflake/index.js +10 -0
  158. package/dist/{infer/snowflake.d.ts → snowflake/infer.d.ts} +2 -2
  159. package/dist/{infer/snowflake.js → snowflake/infer.js} +4 -3
  160. package/dist/snowflake/lower.js +59 -19
  161. package/dist/snowflake/signatures.generated.d.ts +6 -0
  162. package/dist/snowflake/signatures.generated.js +2080 -0
  163. package/dist/sqlite/behavior.d.ts +2 -0
  164. package/dist/sqlite/behavior.js +19 -0
  165. package/dist/sqlite/fold.d.ts +8 -0
  166. package/dist/sqlite/fold.js +41 -0
  167. package/dist/sqlite/index.d.ts +7 -0
  168. package/dist/sqlite/index.js +10 -0
  169. package/dist/sqlite/infer.d.ts +12 -0
  170. package/dist/sqlite/infer.js +122 -0
  171. package/dist/sqlite/lower.d.ts +11 -0
  172. package/dist/sqlite/lower.js +1093 -0
  173. package/dist/sqlite/parse.d.ts +10 -0
  174. package/dist/sqlite/parse.js +70 -0
  175. package/dist/sqlite/signatures.generated.d.ts +6 -0
  176. package/dist/sqlite/signatures.generated.js +277 -0
  177. package/dist/symbols/symbols.js +14 -12
  178. package/dist/token/classify.js +31 -0
  179. package/dist/token/tokenize.js +4 -0
  180. package/dist/trino/behavior.d.ts +2 -0
  181. package/dist/trino/behavior.js +21 -0
  182. package/dist/trino/fold.d.ts +8 -0
  183. package/dist/trino/fold.js +39 -0
  184. package/dist/trino/index.d.ts +7 -0
  185. package/dist/trino/index.js +10 -0
  186. package/dist/{infer/trino.d.ts → trino/infer.d.ts} +2 -2
  187. package/dist/{infer/trino.js → trino/infer.js} +4 -3
  188. package/dist/trino/lower.js +5 -5
  189. package/dist/trino/signatures.generated.d.ts +6 -0
  190. package/dist/trino/signatures.generated.js +968 -0
  191. package/dist/tsql/behavior.d.ts +2 -0
  192. package/dist/tsql/behavior.js +20 -0
  193. package/dist/tsql/fold.d.ts +8 -0
  194. package/dist/tsql/fold.js +34 -0
  195. package/dist/tsql/index.d.ts +7 -0
  196. package/dist/tsql/index.js +10 -0
  197. package/dist/tsql/infer.d.ts +16 -0
  198. package/dist/tsql/infer.js +289 -0
  199. package/dist/tsql/lower.js +4 -4
  200. package/dist/tsql/signatures.generated.d.ts +6 -0
  201. package/dist/tsql/signatures.generated.js +640 -0
  202. package/package.json +15 -11
  203. package/dist/generated/bigquery/GoogleSQLLexer.d.ts +0 -407
  204. package/dist/generated/bigquery/GoogleSQLParser.d.ts +0 -9558
  205. package/dist/generated/bigquery/GoogleSQLParserListener.d.ts +0 -7777
  206. package/dist/generated/bigquery/GoogleSQLParserListener.js +0 -7070
  207. package/dist/generated/databricks/DatabricksLexer.d.ts +0 -566
  208. package/dist/generated/databricks/DatabricksParser.d.ts +0 -7771
  209. package/dist/generated/databricks/DatabricksParserListener.d.ts +0 -5737
  210. package/dist/generated/databricks/DatabricksParserListener.js +0 -5256
  211. package/dist/generated/duckdb/DuckdbLexer.d.ts +0 -691
  212. package/dist/generated/duckdb/DuckdbParser.d.ts +0 -13932
  213. package/dist/generated/duckdb/DuckdbParserListener.d.ts +0 -10049
  214. package/dist/generated/duckdb/DuckdbParserListener.js +0 -9138
  215. package/dist/generated/minijinja/MinijinjaLexer.d.ts +0 -108
  216. package/dist/generated/minijinja/MinijinjaParser.d.ts +0 -604
  217. package/dist/generated/minijinja/MinijinjaParserListener.d.ts +0 -449
  218. package/dist/generated/minijinja/MinijinjaParserListener.js +0 -410
  219. package/dist/generated/postgres/PostgresLexer.d.ts +0 -663
  220. package/dist/generated/postgres/PostgresParser.d.ts +0 -12963
  221. package/dist/generated/postgres/PostgresParserListener.d.ts +0 -9408
  222. package/dist/generated/postgres/PostgresParserListener.js +0 -8554
  223. package/dist/generated/redshift/RedshiftLexer.d.ts +0 -954
  224. package/dist/generated/redshift/RedshiftParser.d.ts +0 -16939
  225. package/dist/generated/redshift/RedshiftParserListener.d.ts +0 -12092
  226. package/dist/generated/redshift/RedshiftParserListener.js +0 -10994
  227. package/dist/generated/snowflake/SnowflakeLexer.d.ts +0 -1046
  228. package/dist/generated/snowflake/SnowflakeParser.d.ts +0 -14196
  229. package/dist/generated/snowflake/SnowflakeParserListener.d.ts +0 -8063
  230. package/dist/generated/snowflake/SnowflakeParserListener.js +0 -7330
  231. package/dist/generated/trino/TrinoLexer.d.ts +0 -381
  232. package/dist/generated/trino/TrinoParser.d.ts +0 -5340
  233. package/dist/generated/trino/TrinoParserListener.d.ts +0 -4704
  234. package/dist/generated/trino/TrinoParserListener.js +0 -4326
  235. package/dist/generated/tsql/TSqlLexer.d.ts +0 -1278
  236. package/dist/generated/tsql/TSqlParser.d.ts +0 -17267
  237. package/dist/generated/tsql/TSqlParserListener.d.ts +0 -9697
  238. package/dist/generated/tsql/TSqlParserListener.js +0 -8854
  239. package/dist/infer/dialect.d.ts +0 -21
  240. package/dist/infer/dialect.js +0 -74
  241. package/dist/infer/literals.d.ts +0 -6
  242. package/dist/infer/literals.js +0 -44
  243. package/dist/signature/generated/tsql.d.ts +0 -3
  244. package/dist/signature/generated/tsql.js +0 -260
@@ -1,18 +1,27 @@
1
1
  /** "table" = a table/view identifier — only BigQuery treats these differently from everything
2
2
  * else (columns, aliases, CTE names, struct/field names, …), which is "other". */
3
3
  export type IdentKind = "table" | "other";
4
- /** Unquote (dialect's delimiters, doubled-delimiter unescape) + case-fold per the dialect's
5
- * documented identifier rules. The result is the IDENTITY KEY for name comparison — display
6
- * text always comes from the raw source, never from this. */
7
- export declare function foldIdentifier(raw: string, dialect: string | undefined, kind?: IdentKind): string;
8
- /** PRESENTATION twin of foldIdentifier: strip the dialect's delimiters (unescaping the body) but
9
- * apply NO case change — the string a UI shows for a name. Never use this for comparison; two
10
- * displayName results being equal proves nothing about identity. */
11
- export declare function displayName(raw: string, dialect: string | undefined): string;
12
- /** Fold a multipart table name for a catalog lookup — every part folded with kind "table" (only
13
- * BigQuery treats table parts specially; everywhere else this is the plain fold). */
14
- export declare function foldTableName(parts: string[], dialect: string | undefined): string[];
15
- /** True when a source-map KEY (already folded — an alias folded as "other", or a table's last name
16
- * part folded as "table") matches a RAW qualifier part. Tries both folds; they differ only for
17
- * BigQuery, whose table identifiers preserve case while aliases/columns fold lower. */
18
- export declare function matchesSourceKey(key: string, rawPart: string, dialect: string | undefined): boolean;
4
+ type CaseFold = "lower" | "upper" | "preserve";
5
+ export interface FoldRule {
6
+ /** [open, close] delimiter pairs this dialect recognizes, tried in order. */
7
+ delimiters: readonly (readonly [string, string])[];
8
+ /** Case fold applied to an unquoted identifier. */
9
+ unquoted: "lower" | "upper";
10
+ /** Case fold applied to a quoted (delimited) identifier. */
11
+ quoted: CaseFold;
12
+ /** BigQuery only: table identifiers preserve case whether or not they're backtick-quoted —
13
+ * backticks there are an escaping mechanism, not a case-quoting one. When set, this
14
+ * overrides both `unquoted`/`quoted` for kind:"table". */
15
+ tableCase?: "preserve";
16
+ /** How an escaped delimiter is written inside a quoted identifier's body.
17
+ * "double" (default) — the close delimiter is escaped by doubling it (`""`→`"`, `` `` ``→`` ` ``,
18
+ * `]]`→`]`).
19
+ * "backslash" — BigQuery only (see its rule comment): quoted identifiers use string-literal escape
20
+ * sequences, not doubling. */
21
+ escapeStyle?: "double" | "backslash";
22
+ }
23
+ /** Fold an identifier to its identity key under an explicit rule (the engine each dialect folder binds). */
24
+ export declare function foldWith(rule: FoldRule, raw: string, kind?: IdentKind): string;
25
+ /** Presentation twin of foldWith: strip delimiters, no case change. */
26
+ export declare function displayWith(rule: FoldRule, raw: string): string;
27
+ export {};
@@ -1,128 +1,12 @@
1
- // Dialect-true identifier case-folding — the single fold module every dialect's scope/qualify/
2
- // references pass threads through (Tasks 2-3 wire the callers; this module is self-contained).
1
+ // The dialect-agnostic identifier case-folding ENGINE. A dialect owns its FoldRule (in
2
+ // src/<dialect>/fold.ts) and binds it to these functions; the registry maps a dialect string to that
3
+ // bound behavior. This module holds no per-dialect knowledge — only the rule shape and the fold/display
4
+ // mechanics every dialect's rule runs through.
3
5
  //
4
- // The result of foldIdentifier() is an IDENTITY KEY for name comparison ONLY — display text
5
- // always comes from the raw source text, never from this function's return value. Getting the
6
- // fold DIRECTION wrong silently breaks equality: e.g. Snowflake's unquoted `foo` must equal
7
- // quoted `"FOO"` and must NOT equal quoted `"foo"` — a lowercase fold gets both wrong.
8
- //
9
- // Every rule row below was verified against the LIVE vendor page (not training data) before
10
- // encoding; citations note the verbatim wording that decided the direction, and any place the
11
- // live page diverged from the originally proposed rule.
12
- const DOUBLE_QUOTE = ['"', '"'];
13
- const BACKTICK = ["`", "`"];
14
- const RULES = {
15
- // docs.databricks.com/en/sql/language-manual/sql-ref-identifiers.html — verified live:
16
- // "Identifiers are case-insensitive when referenced." Backtick escaping is doubling, not
17
- // case-quoting: "Use ` to escape ` itself" (example: `` `a``b` `` → `` a`b ``).
18
- databricks: {
19
- delimiters: [BACKTICK],
20
- unquoted: "lower",
21
- quoted: "lower",
22
- },
23
- // learn.microsoft.com/en-us/sql/relational-databases/databases/database-identifiers +
24
- // .../sql/t-sql/statements/collations — verified live: case folding is NOT a hardcoded T-SQL
25
- // rule, it's a function of the identifier's COLLATION: "you can create two tables with names
26
- // that differ only in case in a database that has case-sensitive collation, but you can't...
27
- // in a database that has case-insensitive collation." Most SQL Server / Fabric SQL database
28
- // defaults are case-insensitive (e.g. SQL_Latin1_General_CP1_CI_AS), but this is not universal
29
- // — Fabric Warehouse defaults to the case-SENSITIVE Latin1_General_100_BIN2_UTF8. This module
30
- // encodes the common default-collation (CI) behavior; a caller with a known case-sensitive
31
- // collation is a documented boundary this module does not cross. Delimiting with `[ ]` or
32
- // `" "` does not itself change case behavior — quoting only unlocks reserved words/specials.
33
- tsql: {
34
- delimiters: [["[", "]"], DOUBLE_QUOTE],
35
- unquoted: "lower",
36
- quoted: "lower",
37
- },
38
- // docs.snowflake.com/en/sql-reference/identifiers-syntax — verified live: unquoted identifiers
39
- // "are stored and resolved as uppercase characters (e.g. id is stored and resolved as ID)";
40
- // quoted identifiers — "the case of the identifier is preserved when storing and resolving the
41
- // identifier" (case-sensitive). Doubled-quote escape: "To use the double quote character inside
42
- // a quoted identifier, use two quotes."
43
- snowflake: {
44
- delimiters: [DOUBLE_QUOTE],
45
- unquoted: "upper",
46
- quoted: "preserve",
47
- },
48
- // cloud.google.com/bigquery/docs/reference/standard-sql/lexical — verified live (via search,
49
- // the JS-rendered page would not return body text to WebFetch): "table names are case-sensitive,
50
- // but column names are not" — so table identifiers preserve case and everything else (column,
51
- // field, alias, CTE) folds to lower, REGARDLESS of backtick-quoting either way (backticks are
52
- // required for reserved words/specials, not a case-quoting mechanism — same "not case-quoting"
53
- // shape as Databricks, but the preserved/folded split is per identifier KIND here, not
54
- // per-quoting). Escape mechanism corrected from the originally assumed doubling: "Quoted
55
- // identifiers have the same escape sequences as string literals" (backslash-escaped, e.g.
56
- // `` `a\`b` `` → `` a`b ``) — NOT doubling like every other backtick/quote dialect here. This
57
- // module unescapes the identifier-relevant case (`` \` ``) plus the general `\X`→`X` pattern; it
58
- // does not implement BigQuery's full string-literal escape grammar (\n, \xHH, \uXXXX, octal, …),
59
- // out of scope for an identifier fold — those escapes are exotic in identifier text.
60
- bigquery: {
61
- delimiters: [BACKTICK],
62
- unquoted: "lower",
63
- quoted: "lower",
64
- tableCase: "preserve",
65
- escapeStyle: "backslash",
66
- },
67
- // docs.aws.amazon.com/redshift/latest/dg/r_names.html — verified live: "ASCII letters in
68
- // standard and delimited identifiers are case-insensitive and are folded to lowercase in the
69
- // database" — explicitly covers BOTH unquoted and quoted by default (the
70
- // enable_case_sensitive_identifier parameter can flip quoted identifiers case-sensitive; this
71
- // module encodes the default). Doubled-quote escape: "To use a double quotation mark in a
72
- // string, you must precede it with another double quotation mark character."
73
- redshift: {
74
- delimiters: [DOUBLE_QUOTE],
75
- unquoted: "lower",
76
- quoted: "lower",
77
- },
78
- // postgresql.org/docs/18/sql-syntax-lexical.html §4.1.1 — verified live: "unquoted names are
79
- // always folded to lower case"; "Quoting an identifier also makes it case-sensitive" — example
80
- // "the identifiers FOO, foo, and "foo" are considered the same by PostgreSQL, but "Foo" and
81
- // "FOO" are different." Doubled-quote escape: "To include a double quote, write two double
82
- // quotes."
83
- postgres: {
84
- delimiters: [DOUBLE_QUOTE],
85
- unquoted: "lower",
86
- quoted: "preserve",
87
- },
88
- // duckdb.org/docs/current/sql/dialect/keywords_and_identifiers.html — verified live: "Identifiers
89
- // in DuckDB are always case-insensitive, similarly to PostgreSQL. However, unlike PostgreSQL...
90
- // DuckDB also treats quoted identifiers as case-insensitive" — quoting only preserves the
91
- // identifier for DISPLAY, not identity. Doubled-quote escape: "Double quotes can be escaped by
92
- // repeating the quote character."
93
- duckdb: {
94
- delimiters: [DOUBLE_QUOTE],
95
- unquoted: "lower",
96
- quoted: "lower",
97
- },
98
- // trino.io/docs/current/language/reserved.html — verified live: "Identifiers with other
99
- // characters must be delimited with double quotes (\"). ... Escape a \" with another preceding
100
- // double quote in a delimited identifier." and, blanket, "Identifiers are not treated as case
101
- // sensitive" — no quoted/unquoted distinction is drawn, and no backtick delimiter is documented
102
- // (adjusted from the originally proposed "backtick tolerated" — dropped, unconfirmed by the
103
- // live page). The fold DIRECTION (lower here) is this module's choice, not vendor-documented —
104
- // the live docs only commit to uniform case-insensitivity across quoted/unquoted, which lower-
105
- // folding both forms reproduces; chosen for consistency with the other case-insensitive-quoted
106
- // dialects (redshift/duckdb) and this module's undefined-dialect default. NOTE: Trino's own
107
- // engine source is internally inconsistent with this blanket docs claim — trino-parser's
108
- // Identifier.getCanonicalValue() canonicalizes unquoted to UPPER and preserves quoted verbatim
109
- // (ANSI-style, would make quoted case-sensitive), while trino-main's Field field-matching does
110
- // a blanket case-insensitive compare regardless of quoting. Encoding the documented behavior
111
- // per this module's citation policy; flagged as a discrepancy, not resolved against a live
112
- // engine.
113
- trino: {
114
- delimiters: [DOUBLE_QUOTE],
115
- unquoted: "lower",
116
- quoted: "lower",
117
- },
118
- };
119
- // Today's behavior — the safe default for an unrecognized/absent dialect tag: strip backticks,
120
- // fold to lower.
121
- const DEFAULT_RULE = {
122
- delimiters: [BACKTICK],
123
- unquoted: "lower",
124
- quoted: "lower",
125
- };
6
+ // The result of foldWith() is an IDENTITY KEY for name comparison ONLY — display text always comes from
7
+ // the raw source text, never from a fold result. Getting the fold DIRECTION wrong silently breaks
8
+ // equality: e.g. Snowflake's unquoted `foo` must equal quoted `"FOO"` and must NOT equal quoted `"foo"`
9
+ // — a lowercase fold gets both wrong. Each dialect's rule is doc-cited in its own src/<dialect>/fold.ts.
126
10
  function applyCase(text, fold) {
127
11
  if (fold === "lower")
128
12
  return text.toLowerCase();
@@ -144,31 +28,14 @@ function unwrap(raw, rule) {
144
28
  }
145
29
  return [raw, false];
146
30
  }
147
- /** Unquote (dialect's delimiters, doubled-delimiter unescape) + case-fold per the dialect's
148
- * documented identifier rules. The result is the IDENTITY KEY for name comparison — display
149
- * text always comes from the raw source, never from this. */
150
- export function foldIdentifier(raw, dialect, kind = "other") {
151
- const rule = (dialect && Object.hasOwn(RULES, dialect) ? RULES[dialect] : undefined) || DEFAULT_RULE;
31
+ /** Fold an identifier to its identity key under an explicit rule (the engine each dialect folder binds). */
32
+ export function foldWith(rule, raw, kind = "other") {
152
33
  const [body, wasQuoted] = unwrap(raw, rule);
153
34
  if (kind === "table" && rule.tableCase)
154
35
  return applyCase(body, rule.tableCase);
155
36
  return applyCase(body, wasQuoted ? rule.quoted : rule.unquoted);
156
37
  }
157
- /** PRESENTATION twin of foldIdentifier: strip the dialect's delimiters (unescaping the body) but
158
- * apply NO case change — the string a UI shows for a name. Never use this for comparison; two
159
- * displayName results being equal proves nothing about identity. */
160
- export function displayName(raw, dialect) {
161
- const rule = (dialect && Object.hasOwn(RULES, dialect) ? RULES[dialect] : undefined) || DEFAULT_RULE;
38
+ /** Presentation twin of foldWith: strip delimiters, no case change. */
39
+ export function displayWith(rule, raw) {
162
40
  return unwrap(raw, rule)[0];
163
41
  }
164
- /** Fold a multipart table name for a catalog lookup — every part folded with kind "table" (only
165
- * BigQuery treats table parts specially; everywhere else this is the plain fold). */
166
- export function foldTableName(parts, dialect) {
167
- return parts.map((p) => foldIdentifier(p, dialect, "table"));
168
- }
169
- /** True when a source-map KEY (already folded — an alias folded as "other", or a table's last name
170
- * part folded as "table") matches a RAW qualifier part. Tries both folds; they differ only for
171
- * BigQuery, whose table identifiers preserve case while aliases/columns fold lower. */
172
- export function matchesSourceKey(key, rawPart, dialect) {
173
- return key === foldIdentifier(rawPart, dialect) || key === foldIdentifier(rawPart, dialect, "table");
174
- }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { parse, analyze, toAst, toScopes, qualify, lineage, deriveSymbols, TypeInfo, type Nullability, Lineage, originsOfExpr, lineageAt, lineageOf, type LineageHop, type ViaStep, tokenize, SqlDocument, LineIndex, complete, completeAt, type Completion, signatureAt, FUNCTION_SIGNATURES, HARVESTED_SIGNATURES, lookupSignature, hasSignature, referencesAt, type Occurrence, type Occurrences, dialectSymbols, type DialectSymbols, CallbackSchema, type SchemaProvider, type TableResolver, DERIVED_DIALECTS, resolveDialect, foldIdentifier, displayName, type IdentKind, type SignatureInfo, type FnSignature, type ParamSig, type Dialect, type DialectOpts, type ParseResultIR, type Analysis, type Token, type TokenRole, type DocumentAnalysis, type StatementCell, type StatementCellSpan, type DocumentVariant, type UnionCte, } from "./api.js";
1
+ export { parse, analyze, toAst, toScopes, qualify, lineage, deriveSymbols, TypeInfo, type Nullability, Lineage, originsOfExpr, lineageAt, lineageOf, type LineageHop, type ViaStep, tokenize, SqlDocument, LineIndex, complete, completeAt, type Completion, jinjaSlotAt, type JinjaSlot, signatureAt, SIGNATURES, lookupSignature, hasSignature, referencesAt, type Occurrence, type Occurrences, dialectSymbols, type DialectSymbols, CallbackSchema, type SchemaProvider, type TableResolver, DERIVED_DIALECTS, resolveDialect, foldIdentifier, displayName, type IdentKind, type SignatureHelpInfo, type SignatureLabel, type FnSignature, type ParamSig, type Dialect, type DialectOpts, type ParseResultIR, type Analysis, type Token, type TokenRole, type DocumentAnalysis, type StatementCell, type StatementCellSpan, type DocumentVariant, type UnionCte, } from "./api.js";
2
2
  export { SqlSession, type SessionOptions } from "./session.js";
3
3
  export { parseDatabricks } from "./databricks/parse.js";
4
4
  export { parseTSql } from "./tsql/parse.js";
@@ -8,6 +8,8 @@ export { parseRedshift } from "./redshift/parse.js";
8
8
  export { parsePostgres } from "./postgres/parse.js";
9
9
  export { parseDuckdb } from "./duckdb/parse.js";
10
10
  export { parseTrino } from "./trino/parse.js";
11
+ export { parseSqlite } from "./sqlite/parse.js";
12
+ export { parseMysql } from "./mysql/parse.js";
11
13
  export { lower as lowerDatabricks } from "./databricks/lower.js";
12
14
  export { lower as lowerTSql } from "./tsql/lower.js";
13
15
  export { lower as lowerSnowflake } from "./snowflake/lower.js";
@@ -16,6 +18,8 @@ export { lower as lowerRedshift } from "./redshift/lower.js";
16
18
  export { lower as lowerPostgres } from "./postgres/lower.js";
17
19
  export { lower as lowerDuckdb } from "./duckdb/lower.js";
18
20
  export { lower as lowerTrino } from "./trino/lower.js";
21
+ export { lower as lowerSqlite } from "./sqlite/lower.js";
22
+ export { lower as lowerMysql } from "./mysql/lower.js";
19
23
  export type { ParseResult } from "./parse-result.js";
20
24
  export { type TemplatedParseResult, type TemplatedParseOptions } from "./template/engine.js";
21
25
  export type { Clause, ColumnRef, CteDef, Expr, GraphElement, GraphTableSource, Join, JoinKind, LateralViewSource, LimitInfo, PartSpan, PipeBranch, PipeExpr, PipeSetItem, PipeStage, PivotInfo, Projection, QueryBody, QueryExpr, SelectExpr, SetOpExpr, Source, SubquerySource, TableSource, TemplateExprInfo, TemplateSourceInfo, UnpivotInfo, UnsupportedFlag, WindowSpec, } from "./ir/ir.js";
@@ -30,7 +34,7 @@ export { resolveScopes, type CteRef, type ResolvedSource, type Scope, type Scope
30
34
  export { walk, scopeOf } from "./scope/walk.js";
31
35
  export { type Diagnostic, type Qualification, type ColumnBinding } from "./qualify/qualify.js";
32
36
  export { Schema, type Column, type SchemaMapping, type SchemaLeaf } from "./qualify/schema.js";
33
- export { DefaultTemplateProvider, OPEN_PROVIDER, NO_OUTPUT_BUILTINS, type TemplateProvider, type TemplateCall, type ResolvedExpansion, type ResolvedRelation, type ValueType, type ExpansionShape, } from "./qualify/template-provider.js";
37
+ export { DefaultTemplateProvider, DbtTemplateProvider, OPEN_PROVIDER, NO_OUTPUT_BUILTINS, type TemplateProvider, type TemplateCall, type ResolvedExpansion, type ResolvedRelation, type TemplateCandidate, type ValueType, type ExpansionShape, } from "./qualify/template-provider.js";
34
38
  export type { TemplateEngine } from "./template/engine.js";
35
39
  export { MAIN_FRAME, symbolAt, type Span, type StarExpansion, type Sym, type SymbolKind, type SymbolModifier, } from "./symbols/symbols.js";
36
40
  export { inferType } from "./infer/infer.js";
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@
10
10
  // - Building blocks: the per-dialect parse*/lower and the raw shared passes, for callers who
11
11
  // want a specific tier or the raw CST escape hatch.
12
12
  // --- Uniform entry, lift helpers, typed wrappers, composable passes (src/api.ts) ---
13
- export { parse, analyze, toAst, toScopes, qualify, lineage, deriveSymbols, TypeInfo, Lineage, originsOfExpr, lineageAt, lineageOf, tokenize, SqlDocument, LineIndex, complete, completeAt, signatureAt, FUNCTION_SIGNATURES, HARVESTED_SIGNATURES, lookupSignature, hasSignature, referencesAt, dialectSymbols, CallbackSchema, DERIVED_DIALECTS, resolveDialect, foldIdentifier, displayName, } from "./api.js";
13
+ export { parse, analyze, toAst, toScopes, qualify, lineage, deriveSymbols, TypeInfo, Lineage, originsOfExpr, lineageAt, lineageOf, tokenize, SqlDocument, LineIndex, complete, completeAt, jinjaSlotAt, signatureAt, SIGNATURES, lookupSignature, hasSignature, referencesAt, dialectSymbols, CallbackSchema, DERIVED_DIALECTS, resolveDialect, foldIdentifier, displayName, } from "./api.js";
14
14
  // SqlSession — the verb-shaped facade over one SqlDocument (offset in, answer out; pure delegation).
15
15
  export { SqlSession } from "./session.js";
16
16
  // --- Per-dialect building blocks: parse* (CST + errors) and lower* (CST → IR), kept as one
@@ -25,6 +25,8 @@ export { parseRedshift } from "./redshift/parse.js";
25
25
  export { parsePostgres } from "./postgres/parse.js";
26
26
  export { parseDuckdb } from "./duckdb/parse.js";
27
27
  export { parseTrino } from "./trino/parse.js";
28
+ export { parseSqlite } from "./sqlite/parse.js";
29
+ export { parseMysql } from "./mysql/parse.js";
28
30
  export { lower as lowerDatabricks } from "./databricks/lower.js";
29
31
  export { lower as lowerTSql } from "./tsql/lower.js";
30
32
  export { lower as lowerSnowflake } from "./snowflake/lower.js";
@@ -33,13 +35,15 @@ export { lower as lowerRedshift } from "./redshift/lower.js";
33
35
  export { lower as lowerPostgres } from "./postgres/lower.js";
34
36
  export { lower as lowerDuckdb } from "./duckdb/lower.js";
35
37
  export { lower as lowerTrino } from "./trino/lower.js";
38
+ export { lower as lowerSqlite } from "./sqlite/lower.js";
39
+ export { lower as lowerMysql } from "./mysql/lower.js";
36
40
  export { partSpanOf, partSpansOf } from "./ir/part-span.js";
37
41
  export { endPosition } from "./ir/span.js";
38
42
  // The shared IR walk — expr/query-tree traversal with no scope/document knowledge, single-sourced
39
- // for src/document/node-at.ts and the LSP folding feature (and any other IR-only consumer).
43
+ // for src/document/node-at.ts and any other IR-only consumer.
40
44
  export { childExprs, walkExprs, allQueryExprs } from "./ir/walk.js";
41
- // The CST node-at-offset walk — the one genuinely LSP-shaped capability that lives outside
42
- // src/lsp/: given an offset, the smallest IR Expr (+ owning Scope) that covers it. Backs hover.
45
+ // The CST node-at-offset walk — the one genuinely editor-shaped capability: given an offset, the
46
+ // smallest IR Expr (+ owning Scope) that covers it. Backs hover.
43
47
  export { nodeAt } from "./document/node-at.js";
44
48
  export { coarseKind } from "./ir/statement.js";
45
49
  // --- Shared passes as building blocks (raw forms) + their typed result interfaces ---
@@ -51,10 +55,12 @@ export { walk, scopeOf } from "./scope/walk.js";
51
55
  export { Schema } from "./qualify/schema.js";
52
56
  // The template PROVIDER (the catalog-unification redesign): ONE resolution seam —
53
57
  // `expansion(call)` — for every template expression. `DefaultTemplateProvider` is the shipped,
54
- // concrete, inheritance-designed default (fully functional with zero input; override the granular
55
- // methods with what your host knows; misses + prime() warm lazily). Pass the SAME per-document
56
- // instance to parseTemplated (fills) and qualify/analyze (semantics).
57
- export { DefaultTemplateProvider, OPEN_PROVIDER, NO_OUTPUT_BUILTINS, } from "./qualify/template-provider.js";
58
+ // concrete, inheritance-designed NEUTRAL default (fully functional with zero input, knows no macro
59
+ // vocabulary; override the granular methods with what your host knows; misses + prime() warm
60
+ // lazily). `DbtTemplateProvider` is the shipped dbt overlay (ref/source/env_var/no-output builtins) a
61
+ // dbt consumer extends. Pass the SAME per-document instance to parseTemplated (fills) and
62
+ // qualify/analyze (semantics).
63
+ export { DefaultTemplateProvider, DbtTemplateProvider, OPEN_PROVIDER, NO_OUTPUT_BUILTINS, } from "./qualify/template-provider.js";
58
64
  export { MAIN_FRAME, symbolAt, } from "./symbols/symbols.js";
59
65
  export { inferType } from "./infer/infer.js";
60
66
  export { parseType, formatType } from "./infer/types.js";
@@ -1,13 +1,24 @@
1
- import type { Expr } from "../ir/ir.js";
2
1
  import { type Type } from "./types.js";
3
2
  export type FnRule = (args: Type[]) => Type;
4
- export declare const FUNCTION_RETURNS: Record<string, FnRule>;
5
- export declare const TSQL_FUNCTION_RETURNS: Record<string, FnRule>;
6
- /** T-SQL pre-registry inference hook — the XML data type methods, which `lowerUdtElem` lowers to
7
- * `function` nodes with the receiver as arg 0. `value(xpath, 'sqltype')` is typed by its literal
8
- * sqltype argument (never-wrong: no XML shredding — the declared sqltype is the value's runtime
9
- * type; a non-literal sqltype falls through to unknown); `exist()` → boolean (bit); `query()` → xml.
10
- * https://learn.microsoft.com/en-us/sql/t-sql/xml/xml-data-type-methods */
11
- export declare function tsqlSpecial(fn: Extract<Expr, {
12
- kind: "function";
13
- }>): Type | undefined;
3
+ export declare const S: Type;
4
+ export declare const I: Type;
5
+ export declare const BIG: Type;
6
+ export declare const D: Type;
7
+ export declare const B: Type;
8
+ export declare const DATE: Type;
9
+ export declare const TS: Type;
10
+ export declare const BIN: Type;
11
+ export declare const INTERVAL: Type;
12
+ export declare const fixed: (t: Type) => FnRule;
13
+ export declare const firstArg: FnRule;
14
+ export declare const common: FnRule;
15
+ export declare const restCommon: FnRule;
16
+ export declare const arrayOfFirst: FnRule;
17
+ export declare const arrayOfCommon: FnRule;
18
+ export declare const elementOf: FnRule;
19
+ export declare const mapKeys: FnRule;
20
+ export declare const mapValues: FnRule;
21
+ export declare const concatRule: FnRule;
22
+ /** date_add(unit, n, ts) / dateadd / timestampadd → the date/timestamp argument's type. */
23
+ export declare const dateArg: FnRule;
24
+ export declare function group(rule: FnRule, names: string[]): Record<string, FnRule>;