altimate-code 0.5.2 → 0.5.3
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/CHANGELOG.md +12 -0
- package/bin/altimate +6 -0
- package/bin/altimate-code +6 -0
- package/dbt-tools/bin/altimate-dbt +2 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/altimate/__init__.py +0 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/altimate/fetch_schema.py +35 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/altimate/utils.py +353 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/altimate/validate_sql.py +114 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/__init__.py +178 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/__main__.py +96 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/_typing.py +17 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dataframe/__init__.py +3 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dataframe/sql/__init__.py +18 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dataframe/sql/_typing.py +18 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dataframe/sql/column.py +332 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dataframe/sql/dataframe.py +866 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dataframe/sql/functions.py +1267 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dataframe/sql/group.py +59 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dataframe/sql/normalize.py +78 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dataframe/sql/operations.py +53 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dataframe/sql/readwriter.py +108 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dataframe/sql/session.py +190 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dataframe/sql/transforms.py +9 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dataframe/sql/types.py +212 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dataframe/sql/util.py +32 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dataframe/sql/window.py +134 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/__init__.py +118 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/athena.py +166 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/bigquery.py +1331 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/clickhouse.py +1393 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/databricks.py +131 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/dialect.py +1915 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/doris.py +561 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/drill.py +157 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/druid.py +20 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/duckdb.py +1159 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/dune.py +16 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/hive.py +787 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/materialize.py +94 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/mysql.py +1324 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/oracle.py +378 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/postgres.py +778 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/presto.py +788 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/prql.py +203 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/redshift.py +448 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/risingwave.py +78 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/snowflake.py +1464 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/spark.py +202 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/spark2.py +349 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/sqlite.py +320 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/starrocks.py +343 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/tableau.py +61 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/teradata.py +356 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/trino.py +115 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/dialects/tsql.py +1403 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/diff.py +456 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/errors.py +93 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/executor/__init__.py +95 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/executor/context.py +101 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/executor/env.py +246 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/executor/python.py +460 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/executor/table.py +155 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/expressions.py +8870 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/generator.py +4993 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/helper.py +582 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/jsonpath.py +227 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/lineage.py +423 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/optimizer/__init__.py +11 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/optimizer/annotate_types.py +589 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/optimizer/canonicalize.py +222 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/optimizer/eliminate_ctes.py +43 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/optimizer/eliminate_joins.py +181 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/optimizer/eliminate_subqueries.py +189 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/optimizer/isolate_table_selects.py +50 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/optimizer/merge_subqueries.py +415 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/optimizer/normalize.py +200 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/optimizer/normalize_identifiers.py +64 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/optimizer/optimize_joins.py +91 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/optimizer/optimizer.py +94 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/optimizer/pushdown_predicates.py +222 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/optimizer/pushdown_projections.py +172 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/optimizer/qualify.py +104 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/optimizer/qualify_columns.py +1024 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/optimizer/qualify_tables.py +155 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/optimizer/scope.py +904 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/optimizer/simplify.py +1587 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/optimizer/unnest_subqueries.py +302 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/parser.py +8501 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/planner.py +463 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/schema.py +588 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/serde.py +68 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/time.py +687 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/tokens.py +1520 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/transforms.py +1020 -0
- package/dbt-tools/dist/altimate_python_packages/altimate_packages/sqlglot/trie.py +81 -0
- package/dbt-tools/dist/altimate_python_packages/dbt_core_integration.py +825 -0
- package/dbt-tools/dist/altimate_python_packages/dbt_utils.py +157 -0
- package/dbt-tools/dist/index.js +23859 -0
- package/package.json +13 -13
- package/postinstall.mjs +42 -0
- package/skills/altimate-setup/SKILL.md +31 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import itertools
|
|
4
|
+
import typing as t
|
|
5
|
+
|
|
6
|
+
from sqlglot import alias, exp
|
|
7
|
+
from sqlglot.dialects.dialect import DialectType
|
|
8
|
+
from sqlglot.helper import csv_reader, name_sequence
|
|
9
|
+
from sqlglot.optimizer.scope import Scope, traverse_scope
|
|
10
|
+
from sqlglot.schema import Schema
|
|
11
|
+
from sqlglot.dialects.dialect import Dialect
|
|
12
|
+
|
|
13
|
+
if t.TYPE_CHECKING:
|
|
14
|
+
from sqlglot._typing import E
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def qualify_tables(
|
|
18
|
+
expression: E,
|
|
19
|
+
db: t.Optional[str | exp.Identifier] = None,
|
|
20
|
+
catalog: t.Optional[str | exp.Identifier] = None,
|
|
21
|
+
schema: t.Optional[Schema] = None,
|
|
22
|
+
infer_csv_schemas: bool = False,
|
|
23
|
+
dialect: DialectType = None,
|
|
24
|
+
) -> E:
|
|
25
|
+
"""
|
|
26
|
+
Rewrite sqlglot AST to have fully qualified tables. Join constructs such as
|
|
27
|
+
(t1 JOIN t2) AS t will be expanded into (SELECT * FROM t1 AS t1, t2 AS t2) AS t.
|
|
28
|
+
|
|
29
|
+
Examples:
|
|
30
|
+
>>> import sqlglot
|
|
31
|
+
>>> expression = sqlglot.parse_one("SELECT 1 FROM tbl")
|
|
32
|
+
>>> qualify_tables(expression, db="db").sql()
|
|
33
|
+
'SELECT 1 FROM db.tbl AS tbl'
|
|
34
|
+
>>>
|
|
35
|
+
>>> expression = sqlglot.parse_one("SELECT 1 FROM (t1 JOIN t2) AS t")
|
|
36
|
+
>>> qualify_tables(expression).sql()
|
|
37
|
+
'SELECT 1 FROM (SELECT * FROM t1 AS t1, t2 AS t2) AS t'
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
expression: Expression to qualify
|
|
41
|
+
db: Database name
|
|
42
|
+
catalog: Catalog name
|
|
43
|
+
schema: A schema to populate
|
|
44
|
+
infer_csv_schemas: Whether to scan READ_CSV calls in order to infer the CSVs' schemas.
|
|
45
|
+
dialect: The dialect to parse catalog and schema into.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
The qualified expression.
|
|
49
|
+
"""
|
|
50
|
+
next_alias_name = name_sequence("_q_")
|
|
51
|
+
db = exp.parse_identifier(db, dialect=dialect) if db else None
|
|
52
|
+
catalog = exp.parse_identifier(catalog, dialect=dialect) if catalog else None
|
|
53
|
+
dialect = Dialect.get_or_raise(dialect)
|
|
54
|
+
|
|
55
|
+
def _qualify(table: exp.Table) -> None:
|
|
56
|
+
if isinstance(table.this, exp.Identifier):
|
|
57
|
+
if db and not table.args.get("db"):
|
|
58
|
+
table.set("db", db.copy())
|
|
59
|
+
if catalog and not table.args.get("catalog") and table.args.get("db"):
|
|
60
|
+
table.set("catalog", catalog.copy())
|
|
61
|
+
|
|
62
|
+
if (db or catalog) and not isinstance(expression, exp.Query):
|
|
63
|
+
for node in expression.walk(prune=lambda n: isinstance(n, exp.Query)):
|
|
64
|
+
if isinstance(node, exp.Table):
|
|
65
|
+
_qualify(node)
|
|
66
|
+
|
|
67
|
+
for scope in traverse_scope(expression):
|
|
68
|
+
for derived_table in itertools.chain(scope.ctes, scope.derived_tables):
|
|
69
|
+
if isinstance(derived_table, exp.Subquery):
|
|
70
|
+
unnested = derived_table.unnest()
|
|
71
|
+
if isinstance(unnested, exp.Table):
|
|
72
|
+
joins = unnested.args.pop("joins", None)
|
|
73
|
+
derived_table.this.replace(exp.select("*").from_(unnested.copy(), copy=False))
|
|
74
|
+
derived_table.this.set("joins", joins)
|
|
75
|
+
|
|
76
|
+
if not derived_table.args.get("alias"):
|
|
77
|
+
alias_ = next_alias_name()
|
|
78
|
+
derived_table.set("alias", exp.TableAlias(this=exp.to_identifier(alias_)))
|
|
79
|
+
scope.rename_source(None, alias_)
|
|
80
|
+
|
|
81
|
+
pivots = derived_table.args.get("pivots")
|
|
82
|
+
if pivots and not pivots[0].alias:
|
|
83
|
+
pivots[0].set("alias", exp.TableAlias(this=exp.to_identifier(next_alias_name())))
|
|
84
|
+
|
|
85
|
+
table_aliases = {}
|
|
86
|
+
|
|
87
|
+
for name, source in scope.sources.items():
|
|
88
|
+
if isinstance(source, exp.Table):
|
|
89
|
+
pivots = source.args.get("pivots")
|
|
90
|
+
if not source.alias:
|
|
91
|
+
# Don't add the pivot's alias to the pivoted table, use the table's name instead
|
|
92
|
+
if pivots and pivots[0].alias == name:
|
|
93
|
+
name = source.name
|
|
94
|
+
|
|
95
|
+
# Mutates the source by attaching an alias to it
|
|
96
|
+
alias(source, name or source.name or next_alias_name(), copy=False, table=True)
|
|
97
|
+
|
|
98
|
+
table_aliases[".".join(p.name for p in source.parts)] = exp.to_identifier(
|
|
99
|
+
source.alias
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
if pivots:
|
|
103
|
+
pivot = pivots[0]
|
|
104
|
+
if not pivot.alias:
|
|
105
|
+
pivot_alias = source.alias if pivot.unpivot else next_alias_name()
|
|
106
|
+
pivot.set("alias", exp.TableAlias(this=exp.to_identifier(pivot_alias)))
|
|
107
|
+
|
|
108
|
+
# This case corresponds to a pivoted CTE, we don't want to qualify that
|
|
109
|
+
if isinstance(scope.sources.get(source.alias_or_name), Scope):
|
|
110
|
+
continue
|
|
111
|
+
|
|
112
|
+
_qualify(source)
|
|
113
|
+
|
|
114
|
+
if infer_csv_schemas and schema and isinstance(source.this, exp.ReadCSV):
|
|
115
|
+
with csv_reader(source.this) as reader:
|
|
116
|
+
header = next(reader)
|
|
117
|
+
columns = next(reader)
|
|
118
|
+
schema.add_table(
|
|
119
|
+
source,
|
|
120
|
+
{k: type(v).__name__ for k, v in zip(header, columns)},
|
|
121
|
+
match_depth=False,
|
|
122
|
+
)
|
|
123
|
+
elif isinstance(source, Scope) and source.is_udtf:
|
|
124
|
+
udtf = source.expression
|
|
125
|
+
table_alias = udtf.args.get("alias") or exp.TableAlias(
|
|
126
|
+
this=exp.to_identifier(next_alias_name())
|
|
127
|
+
)
|
|
128
|
+
udtf.set("alias", table_alias)
|
|
129
|
+
|
|
130
|
+
if not table_alias.name:
|
|
131
|
+
table_alias.set("this", exp.to_identifier(next_alias_name()))
|
|
132
|
+
if isinstance(udtf, exp.Values) and not table_alias.columns:
|
|
133
|
+
column_aliases = dialect.generate_values_aliases(udtf)
|
|
134
|
+
table_alias.set("columns", column_aliases)
|
|
135
|
+
else:
|
|
136
|
+
for node in scope.walk():
|
|
137
|
+
if (
|
|
138
|
+
isinstance(node, exp.Table)
|
|
139
|
+
and not node.alias
|
|
140
|
+
and isinstance(node.parent, (exp.From, exp.Join))
|
|
141
|
+
):
|
|
142
|
+
# Mutates the table by attaching an alias to it
|
|
143
|
+
alias(node, node.name, copy=False, table=True)
|
|
144
|
+
|
|
145
|
+
for column in scope.columns:
|
|
146
|
+
if column.db:
|
|
147
|
+
table_alias = table_aliases.get(".".join(p.name for p in column.parts[0:-1]))
|
|
148
|
+
|
|
149
|
+
if table_alias:
|
|
150
|
+
for p in exp.COLUMN_PARTS[1:]:
|
|
151
|
+
column.set(p, None)
|
|
152
|
+
|
|
153
|
+
column.set("table", table_alias.copy())
|
|
154
|
+
|
|
155
|
+
return expression
|