1
0
Fork 0

Merging upstream version 17.9.1.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-13 20:48:36 +01:00
parent 2bf6699c56
commit 9777880e00
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
87 changed files with 45907 additions and 42511 deletions

View file

@ -1,6 +1,105 @@
Changelog Changelog
========= =========
## [v17.9.0] - 2023-08-01
### :sparkles: New Features
- [`ea7c7da`](https://github.com/tobymao/sqlglot/commit/ea7c7da1aaf0ea157f73efce7622e326b0d0f419) - **teradata**: parse [COLLECT|HELP] STATISTICS as Commands *(PR [#1979](https://github.com/tobymao/sqlglot/pull/1979) by [@GeorgeSittas](https://github.com/GeorgeSittas))*
- :arrow_lower_right: *addresses issue [#1978](undefined) opened by [@MarkBell920](https://github.com/MarkBell920)*
### :bug: Bug Fixes
- [`4af91a0`](https://github.com/tobymao/sqlglot/commit/4af91a05c2c149011526d294a8e0cc843351fded) - **parser**: parse placeholder as fallback for boolean, null, star *(PR [#1976](https://github.com/tobymao/sqlglot/pull/1976) by [@GeorgeSittas](https://github.com/GeorgeSittas))*
- :arrow_lower_right: *fixes issue [#1975](undefined) opened by [@SoftwareGuy2020](https://github.com/SoftwareGuy2020)*
- [`be7d4e6`](https://github.com/tobymao/sqlglot/commit/be7d4e6f7da143c4eac6f9ad389d088c582b2d03) - control whether quotes are generated for extract's date part *(PR [#1981](https://github.com/tobymao/sqlglot/pull/1981) by [@GeorgeSittas](https://github.com/GeorgeSittas))*
- [`5436f53`](https://github.com/tobymao/sqlglot/commit/5436f53cd5037ab56cb414a178ef1edeb7827885) - Make date_add with incorrect expression more clear *(commit by [@tobymao](https://github.com/tobymao))*
### :recycle: Refactors
- [`8a44cc2`](https://github.com/tobymao/sqlglot/commit/8a44cc22119aa46af20f442645fe496217042722) - **optimizer**: improve handling of DDL optimization *(PR [#1972](https://github.com/tobymao/sqlglot/pull/1972) by [@GeorgeSittas](https://github.com/GeorgeSittas))*
- [`9e77c7b`](https://github.com/tobymao/sqlglot/commit/9e77c7bc72a645603ba9b780323bbd356e9dede1) - **optimizer**: factor out pseudocolumns in qualify columns *(PR [#1984](https://github.com/tobymao/sqlglot/pull/1984) by [@GeorgeSittas](https://github.com/GeorgeSittas))*
### :wrench: Chores
- [`78b0eed`](https://github.com/tobymao/sqlglot/commit/78b0eed515491c7ef53cccea8f5265e9abe89bc0) - update docstring with description of Expression.meta *(commit by [@GeorgeSittas](https://github.com/GeorgeSittas))*
## [v17.8.5] - 2023-07-28
### :sparkles: New Features
- [`9d67283`](https://github.com/tobymao/sqlglot/commit/9d67283b3185baa43f2591a75c01493455948d40) - **optimizer**: add support for resolving CTEs in CREATE statements *(PR [#1949](https://github.com/tobymao/sqlglot/pull/1949) by [@gtoonstra](https://github.com/gtoonstra))*
### :bug: Bug Fixes
- [`2874ae5`](https://github.com/tobymao/sqlglot/commit/2874ae5175c3c522b75bfd7764fdbcd928cc94b4) - **tsql**: improve UDF parsing *(PR [#1973](https://github.com/tobymao/sqlglot/pull/1973) by [@GeorgeSittas](https://github.com/GeorgeSittas))*
- :arrow_lower_right: *fixes issue [#1966](undefined) opened by [@bayees](https://github.com/bayees)*
- [`89c8635`](https://github.com/tobymao/sqlglot/commit/89c8635a73ae3f415d9ed8f13da1ab23400446cc) - **parser,bigquery**: make separator optional in STRING_AGG parser *(PR [#1974](https://github.com/tobymao/sqlglot/pull/1974) by [@GeorgeSittas](https://github.com/GeorgeSittas))*
## [v17.8.4] - 2023-07-28
### :sparkles: New Features
- [`7440e4a`](https://github.com/tobymao/sqlglot/commit/7440e4adbc5b62f53db54c6e50b0e5a69f5bffc2) - **tsql**: improve support for the DATEDIFF function *(PR [#1967](https://github.com/tobymao/sqlglot/pull/1967) by [@GeorgeSittas](https://github.com/GeorgeSittas))*
### :bug: Bug Fixes
- [`2d5d714`](https://github.com/tobymao/sqlglot/commit/2d5d714b33c3b7ac2bcafd4b9484d7b8c3e25032) - **tsql**: revert float-to-datetime coercions *(PR [#1970](https://github.com/tobymao/sqlglot/pull/1970) by [@GeorgeSittas](https://github.com/GeorgeSittas))*
- [`35f55e9`](https://github.com/tobymao/sqlglot/commit/35f55e9434bdb87449abd85683ee93f39d0c740f) - **mysql**: simplify LIMIT, OFFSET when their expression is complex *(PR [#1971](https://github.com/tobymao/sqlglot/pull/1971) by [@GeorgeSittas](https://github.com/GeorgeSittas))*
### :wrench: Chores
- [`5695667`](https://github.com/tobymao/sqlglot/commit/5695667e85adb62821e3ea2210855244982c451c) - add dialect parameter to parse for parity with parse_one *(PR [#1969](https://github.com/tobymao/sqlglot/pull/1969) by [@GeorgeSittas](https://github.com/GeorgeSittas))*
## [v17.8.3] - 2023-07-27
### :bug: Bug Fixes
- [`75b418c`](https://github.com/tobymao/sqlglot/commit/75b418c1a7dd2efc616639285438a67ebc2c6b08) - **mysql**: generate DATETIME instead of TIMESTAMP for TimeStrToTime *(commit by [@GeorgeSittas](https://github.com/GeorgeSittas))*
## [v17.8.2] - 2023-07-27
### :sparkles: New Features
- [`5e641c2`](https://github.com/tobymao/sqlglot/commit/5e641c2aa898aa55dd920fc7cff11bef90408379) - **presto**: add IPADDRESS/IPPREFIX data types *(PR [#1965](https://github.com/tobymao/sqlglot/pull/1965) by [@roykoand](https://github.com/roykoand))*
- [`d2685dd`](https://github.com/tobymao/sqlglot/commit/d2685dd4b52123c70e9b4f62e95b948a5b4b6f5f) - **mysql**: improve support for DDL index column constraints *(PR [#1961](https://github.com/tobymao/sqlglot/pull/1961) by [@GeorgeSittas](https://github.com/GeorgeSittas))*
- :arrow_lower_right: *addresses issue [#1959](undefined) opened by [@ninja96826](https://github.com/ninja96826)*
### :bug: Bug Fixes
- [`7082b61`](https://github.com/tobymao/sqlglot/commit/7082b617e07c8e84e9a3e2a840a4f559d3bd2991) - trino->spark starts_with closes [#1963](https://github.com/tobymao/sqlglot/pull/1963) *(commit by [@tobymao](https://github.com/tobymao))*
- [`9787329`](https://github.com/tobymao/sqlglot/commit/97873293ccfd522867c4ae074a05ce97a44adef9) - trino->spark is_nan closes [#1964](https://github.com/tobymao/sqlglot/pull/1964) *(commit by [@tobymao](https://github.com/tobymao))*
- [`1ebe49f`](https://github.com/tobymao/sqlglot/commit/1ebe49fe475c86bf64ba39e9b67a11be9b2f65cd) - **mysql**: generate TimeStrToTime as a cast to TIMESTAMP *(PR [#1968](https://github.com/tobymao/sqlglot/pull/1968) by [@GeorgeSittas](https://github.com/GeorgeSittas))*
## [v17.8.1] - 2023-07-27
### :sparkles: New Features
- [`59847f5`](https://github.com/tobymao/sqlglot/commit/59847f52e30f61734568c4e02dff5df2c0ea3352) - **parser**: improved comment parsing *(PR [#1956](https://github.com/tobymao/sqlglot/pull/1956) by [@mpf82](https://github.com/mpf82))*
- [`8448141`](https://github.com/tobymao/sqlglot/commit/8448141e100f5408b888fd36cca848b8333ffc48) - **tsql**: improve transpilation of temp table DDLs *(PR [#1958](https://github.com/tobymao/sqlglot/pull/1958) by [@GeorgeSittas](https://github.com/GeorgeSittas))*
### :bug: Bug Fixes
- [`92849bd`](https://github.com/tobymao/sqlglot/commit/92849bdda4edb056db9a7598f1761fbe93635caf) - **optimizer**: traverse UNNEST scope *(PR [#1960](https://github.com/tobymao/sqlglot/pull/1960) by [@GeorgeSittas](https://github.com/GeorgeSittas))*
- [`7f79592`](https://github.com/tobymao/sqlglot/commit/7f79592ed87fe2241ae7924a8f421e66b5feffcc) - using type *(commit by [@tobymao](https://github.com/tobymao))*
### :wrench: Chores
- [`4ed04d5`](https://github.com/tobymao/sqlglot/commit/4ed04d5ab710cd88f26a0eb26593eaa4be5b8a66) - minor README addition *(commit by [@GeorgeSittas](https://github.com/GeorgeSittas))*
## [v17.8.0] - 2023-07-24
### :sparkles: New Features
- [`75d49b7`](https://github.com/tobymao/sqlglot/commit/75d49b736b767496479a1138581960c5322cb7a3) - **schema**: improve overridability of normalization setting *(PR [#1954](https://github.com/tobymao/sqlglot/pull/1954) by [@GeorgeSittas](https://github.com/GeorgeSittas))*
### :bug: Bug Fixes
- [`da5a4d1`](https://github.com/tobymao/sqlglot/commit/da5a4d1d06835d97ec0a01fc193422984a0b9707) - **oracle**: improve handling of KEEP (...) OVER (...) window syntax *(PR [#1953](https://github.com/tobymao/sqlglot/pull/1953) by [@GeorgeSittas](https://github.com/GeorgeSittas))*
- :arrow_lower_right: *fixes issue [#1952](undefined) opened by [@push2prod](https://github.com/push2prod)*
## [v17.7.0] - 2023-07-23
### :boom: BREAKING CHANGES
- due to [`2aa62d1`](https://github.com/tobymao/sqlglot/commit/2aa62d19252c2ed6eb26d962ff8253d988ff32e5) - mysql 5 does not support select * from values *(commit by [@tobymao](https://github.com/tobymao))*:
mysql 5 does not support select * from values
### :sparkles: New Features
- [`b82573b`](https://github.com/tobymao/sqlglot/commit/b82573b1d720c69da221e3dda9dcc00a6aebc222) - **redshift**: improve transpilation of ADD_MONTHS function *(PR [#1945](https://github.com/tobymao/sqlglot/pull/1945) by [@GeorgeSittas](https://github.com/GeorgeSittas))*
### :bug: Bug Fixes
- [`46b5dfa`](https://github.com/tobymao/sqlglot/commit/46b5dfa09bba7c339dd8b0bd077455946dec8d8d) - **duckdb**: ensure 'day' will be generated for exp.DateDiff by default *(PR [#1944](https://github.com/tobymao/sqlglot/pull/1944) by [@GeorgeSittas](https://github.com/GeorgeSittas))*
- :arrow_lower_right: *fixes issue [#1943](undefined) opened by [@richard-a-lott](https://github.com/richard-a-lott)*
- [`327451f`](https://github.com/tobymao/sqlglot/commit/327451f78f049787a5afc68e142f33583150a115) - limit with select subquery closes [#1948](https://github.com/tobymao/sqlglot/pull/1948) *(commit by [@tobymao](https://github.com/tobymao))*
- [`f2f4084`](https://github.com/tobymao/sqlglot/commit/f2f4084f1c78e7b9322222ae6ba30b80ad027b30) - offset subquery *(commit by [@tobymao](https://github.com/tobymao))*
- [`2aa62d1`](https://github.com/tobymao/sqlglot/commit/2aa62d19252c2ed6eb26d962ff8253d988ff32e5) - mysql 5 does not support select * from values *(commit by [@tobymao](https://github.com/tobymao))*
- [`3b5d0a6`](https://github.com/tobymao/sqlglot/commit/3b5d0a6f529346d27c86982aa92cce60fd336d14) - mysql cast only supports a few data types *(commit by [@tobymao](https://github.com/tobymao))*
## [v17.6.1] - 2023-07-21 ## [v17.6.1] - 2023-07-21
### :sparkles: New Features ### :sparkles: New Features
- [`4b7e9f1`](https://github.com/tobymao/sqlglot/commit/4b7e9f1d2e3de9eb9b96acfd9e6d8566663666c4) - **clickhouse**: add support for the logical xor function *(PR [#1937](https://github.com/tobymao/sqlglot/pull/1937) by [@GeorgeSittas](https://github.com/GeorgeSittas))* - [`4b7e9f1`](https://github.com/tobymao/sqlglot/commit/4b7e9f1d2e3de9eb9b96acfd9e6d8566663666c4) - **clickhouse**: add support for the logical xor function *(PR [#1937](https://github.com/tobymao/sqlglot/pull/1937) by [@GeorgeSittas](https://github.com/GeorgeSittas))*
@ -907,3 +1006,11 @@ Changelog
[v17.5.0]: https://github.com/tobymao/sqlglot/compare/v17.4.1...v17.5.0 [v17.5.0]: https://github.com/tobymao/sqlglot/compare/v17.4.1...v17.5.0
[v17.6.0]: https://github.com/tobymao/sqlglot/compare/v17.5.0...v17.6.0 [v17.6.0]: https://github.com/tobymao/sqlglot/compare/v17.5.0...v17.6.0
[v17.6.1]: https://github.com/tobymao/sqlglot/compare/v17.6.0...v17.6.1 [v17.6.1]: https://github.com/tobymao/sqlglot/compare/v17.6.0...v17.6.1
[v17.7.0]: https://github.com/tobymao/sqlglot/compare/v17.6.1...v17.7.0
[v17.8.0]: https://github.com/tobymao/sqlglot/compare/v17.7.0...v17.8.0
[v17.8.1]: https://github.com/tobymao/sqlglot/compare/v17.8.0...v17.8.1
[v17.8.2]: https://github.com/tobymao/sqlglot/compare/v17.8.1...v17.8.2
[v17.8.3]: https://github.com/tobymao/sqlglot/compare/v17.8.2...v17.8.3
[v17.8.4]: https://github.com/tobymao/sqlglot/compare/v17.8.3...v17.8.4
[v17.8.5]: https://github.com/tobymao/sqlglot/compare/v17.8.4...v17.8.5
[v17.9.0]: https://github.com/tobymao/sqlglot/compare/v17.8.6...v17.9.0

View file

@ -1,6 +1,6 @@
![SQLGlot logo](sqlglot.svg) ![SQLGlot logo](sqlglot.svg)
SQLGlot is a no-dependency SQL parser, transpiler, optimizer, and engine. It can be used to format SQL or translate between [19 different dialects](https://github.com/tobymao/sqlglot/blob/main/sqlglot/dialects/__init__.py) like [DuckDB](https://duckdb.org/), [Presto](https://prestodb.io/), [Spark](https://spark.apache.org/), [Snowflake](https://www.snowflake.com/en/), and [BigQuery](https://cloud.google.com/bigquery/). It aims to read a wide variety of SQL inputs and output syntactically correct SQL in the targeted dialects. SQLGlot is a no-dependency SQL parser, transpiler, optimizer, and engine. It can be used to format SQL or translate between [19 different dialects](https://github.com/tobymao/sqlglot/blob/main/sqlglot/dialects/__init__.py) like [DuckDB](https://duckdb.org/), [Presto](https://prestodb.io/), [Spark](https://spark.apache.org/), [Snowflake](https://www.snowflake.com/en/), and [BigQuery](https://cloud.google.com/bigquery/). It aims to read a wide variety of SQL inputs and output syntactically and semantically correct SQL in the targeted dialects.
It is a very comprehensive generic SQL parser with a robust [test suite](https://github.com/tobymao/sqlglot/blob/main/tests/). It is also quite [performant](#benchmarks), while being written purely in Python. It is a very comprehensive generic SQL parser with a robust [test suite](https://github.com/tobymao/sqlglot/blob/main/tests/). It is also quite [performant](#benchmarks), while being written purely in Python.
@ -122,7 +122,7 @@ LEFT JOIN `baz`
ON `f`.`a` = `baz`.`a` ON `f`.`a` = `baz`.`a`
``` ```
Comments are also preserved in a best-effort basis when transpiling SQL code: Comments are also preserved on a best-effort basis when transpiling SQL code:
```python ```python
sql = """ sql = """

File diff suppressed because one or more lines are too long

View file

@ -96,7 +96,7 @@
<div class="docstring"><p><img src="sqlglot.svg" alt="SQLGlot logo" /></p> <div class="docstring"><p><img src="sqlglot.svg" alt="SQLGlot logo" /></p>
<p>SQLGlot is a no-dependency SQL parser, transpiler, optimizer, and engine. It can be used to format SQL or translate between <a href="https://github.com/tobymao/sqlglot/blob/main/sqlglot/dialects/__init__.py">19 different dialects</a> like <a href="https://duckdb.org/">DuckDB</a>, <a href="https://prestodb.io/">Presto</a>, <a href="https://spark.apache.org/">Spark</a>, <a href="https://www.snowflake.com/en/">Snowflake</a>, and <a href="https://cloud.google.com/bigquery/">BigQuery</a>. It aims to read a wide variety of SQL inputs and output syntactically correct SQL in the targeted dialects.</p> <p>SQLGlot is a no-dependency SQL parser, transpiler, optimizer, and engine. It can be used to format SQL or translate between <a href="https://github.com/tobymao/sqlglot/blob/main/sqlglot/dialects/__init__.py">19 different dialects</a> like <a href="https://duckdb.org/">DuckDB</a>, <a href="https://prestodb.io/">Presto</a>, <a href="https://spark.apache.org/">Spark</a>, <a href="https://www.snowflake.com/en/">Snowflake</a>, and <a href="https://cloud.google.com/bigquery/">BigQuery</a>. It aims to read a wide variety of SQL inputs and output syntactically and semantically correct SQL in the targeted dialects.</p>
<p>It is a very comprehensive generic SQL parser with a robust <a href="https://github.com/tobymao/sqlglot/blob/main/tests/">test suite</a>. It is also quite <a href="#benchmarks">performant</a>, while being written purely in Python.</p> <p>It is a very comprehensive generic SQL parser with a robust <a href="https://github.com/tobymao/sqlglot/blob/main/tests/">test suite</a>. It is also quite <a href="#benchmarks">performant</a>, while being written purely in Python.</p>
@ -227,7 +227,7 @@
</code></pre> </code></pre>
</div> </div>
<p>Comments are also preserved in a best-effort basis when transpiling SQL code:</p> <p>Comments are also preserved on a best-effort basis when transpiling SQL code:</p>
<div class="pdoc-code codehilite"> <div class="pdoc-code codehilite">
<pre><span></span><code><span class="n">sql</span> <span class="o">=</span> <span class="s2">&quot;&quot;&quot;</span> <pre><span></span><code><span class="n">sql</span> <span class="o">=</span> <span class="s2">&quot;&quot;&quot;</span>
@ -742,97 +742,100 @@ make check # Full test suite &amp; linter checks
</span><span id="L-67"><a href="#L-67"><span class="linenos"> 67</span></a><span class="sd">&quot;&quot;&quot;The default schema used by SQLGlot (e.g. in the optimizer).&quot;&quot;&quot;</span> </span><span id="L-67"><a href="#L-67"><span class="linenos"> 67</span></a><span class="sd">&quot;&quot;&quot;The default schema used by SQLGlot (e.g. in the optimizer).&quot;&quot;&quot;</span>
</span><span id="L-68"><a href="#L-68"><span class="linenos"> 68</span></a> </span><span id="L-68"><a href="#L-68"><span class="linenos"> 68</span></a>
</span><span id="L-69"><a href="#L-69"><span class="linenos"> 69</span></a> </span><span id="L-69"><a href="#L-69"><span class="linenos"> 69</span></a>
</span><span id="L-70"><a href="#L-70"><span class="linenos"> 70</span></a><span class="k">def</span> <span class="nf">parse</span><span class="p">(</span><span class="n">sql</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">read</span><span class="p">:</span> <span class="n">DialectType</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">List</span><span class="p">[</span><span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">Expression</span><span class="p">]]:</span> </span><span id="L-70"><a href="#L-70"><span class="linenos"> 70</span></a><span class="k">def</span> <span class="nf">parse</span><span class="p">(</span>
</span><span id="L-71"><a href="#L-71"><span class="linenos"> 71</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span> </span><span id="L-71"><a href="#L-71"><span class="linenos"> 71</span></a> <span class="n">sql</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">read</span><span class="p">:</span> <span class="n">DialectType</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="n">dialect</span><span class="p">:</span> <span class="n">DialectType</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span>
</span><span id="L-72"><a href="#L-72"><span class="linenos"> 72</span></a><span class="sd"> Parses the given SQL string into a collection of syntax trees, one per parsed SQL statement.</span> </span><span id="L-72"><a href="#L-72"><span class="linenos"> 72</span></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">List</span><span class="p">[</span><span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">Expression</span><span class="p">]]:</span>
</span><span id="L-73"><a href="#L-73"><span class="linenos"> 73</span></a> </span><span id="L-73"><a href="#L-73"><span class="linenos"> 73</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-74"><a href="#L-74"><span class="linenos"> 74</span></a><span class="sd"> Args:</span> </span><span id="L-74"><a href="#L-74"><span class="linenos"> 74</span></a><span class="sd"> Parses the given SQL string into a collection of syntax trees, one per parsed SQL statement.</span>
</span><span id="L-75"><a href="#L-75"><span class="linenos"> 75</span></a><span class="sd"> sql: the SQL code string to parse.</span> </span><span id="L-75"><a href="#L-75"><span class="linenos"> 75</span></a>
</span><span id="L-76"><a href="#L-76"><span class="linenos"> 76</span></a><span class="sd"> read: the SQL dialect to apply during parsing (eg. &quot;spark&quot;, &quot;hive&quot;, &quot;presto&quot;, &quot;mysql&quot;).</span> </span><span id="L-76"><a href="#L-76"><span class="linenos"> 76</span></a><span class="sd"> Args:</span>
</span><span id="L-77"><a href="#L-77"><span class="linenos"> 77</span></a><span class="sd"> **opts: other `sqlglot.parser.Parser` options.</span> </span><span id="L-77"><a href="#L-77"><span class="linenos"> 77</span></a><span class="sd"> sql: the SQL code string to parse.</span>
</span><span id="L-78"><a href="#L-78"><span class="linenos"> 78</span></a> </span><span id="L-78"><a href="#L-78"><span class="linenos"> 78</span></a><span class="sd"> read: the SQL dialect to apply during parsing (eg. &quot;spark&quot;, &quot;hive&quot;, &quot;presto&quot;, &quot;mysql&quot;).</span>
</span><span id="L-79"><a href="#L-79"><span class="linenos"> 79</span></a><span class="sd"> Returns:</span> </span><span id="L-79"><a href="#L-79"><span class="linenos"> 79</span></a><span class="sd"> dialect: the SQL dialect (alias for read).</span>
</span><span id="L-80"><a href="#L-80"><span class="linenos"> 80</span></a><span class="sd"> The resulting syntax tree collection.</span> </span><span id="L-80"><a href="#L-80"><span class="linenos"> 80</span></a><span class="sd"> **opts: other `sqlglot.parser.Parser` options.</span>
</span><span id="L-81"><a href="#L-81"><span class="linenos"> 81</span></a><span class="sd"> &quot;&quot;&quot;</span> </span><span id="L-81"><a href="#L-81"><span class="linenos"> 81</span></a>
</span><span id="L-82"><a href="#L-82"><span class="linenos"> 82</span></a> <span class="n">dialect</span> <span class="o">=</span> <span class="n">Dialect</span><span class="o">.</span><span class="n">get_or_raise</span><span class="p">(</span><span class="n">read</span><span class="p">)()</span> </span><span id="L-82"><a href="#L-82"><span class="linenos"> 82</span></a><span class="sd"> Returns:</span>
</span><span id="L-83"><a href="#L-83"><span class="linenos"> 83</span></a> <span class="k">return</span> <span class="n">dialect</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span> </span><span id="L-83"><a href="#L-83"><span class="linenos"> 83</span></a><span class="sd"> The resulting syntax tree collection.</span>
</span><span id="L-84"><a href="#L-84"><span class="linenos"> 84</span></a> </span><span id="L-84"><a href="#L-84"><span class="linenos"> 84</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-85"><a href="#L-85"><span class="linenos"> 85</span></a> </span><span id="L-85"><a href="#L-85"><span class="linenos"> 85</span></a> <span class="n">dialect</span> <span class="o">=</span> <span class="n">Dialect</span><span class="o">.</span><span class="n">get_or_raise</span><span class="p">(</span><span class="n">read</span> <span class="ow">or</span> <span class="n">dialect</span><span class="p">)()</span>
</span><span id="L-86"><a href="#L-86"><span class="linenos"> 86</span></a><span class="nd">@t</span><span class="o">.</span><span class="n">overload</span> </span><span id="L-86"><a href="#L-86"><span class="linenos"> 86</span></a> <span class="k">return</span> <span class="n">dialect</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span>
</span><span id="L-87"><a href="#L-87"><span class="linenos"> 87</span></a><span class="k">def</span> <span class="nf">parse_one</span><span class="p">(</span><span class="n">sql</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">into</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Type</span><span class="p">[</span><span class="n">E</span><span class="p">],</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">E</span><span class="p">:</span> </span><span id="L-87"><a href="#L-87"><span class="linenos"> 87</span></a>
</span><span id="L-88"><a href="#L-88"><span class="linenos"> 88</span></a> <span class="o">...</span> </span><span id="L-88"><a href="#L-88"><span class="linenos"> 88</span></a>
</span><span id="L-89"><a href="#L-89"><span class="linenos"> 89</span></a> </span><span id="L-89"><a href="#L-89"><span class="linenos"> 89</span></a><span class="nd">@t</span><span class="o">.</span><span class="n">overload</span>
</span><span id="L-90"><a href="#L-90"><span class="linenos"> 90</span></a> </span><span id="L-90"><a href="#L-90"><span class="linenos"> 90</span></a><span class="k">def</span> <span class="nf">parse_one</span><span class="p">(</span><span class="n">sql</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">into</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Type</span><span class="p">[</span><span class="n">E</span><span class="p">],</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">E</span><span class="p">:</span>
</span><span id="L-91"><a href="#L-91"><span class="linenos"> 91</span></a><span class="nd">@t</span><span class="o">.</span><span class="n">overload</span> </span><span id="L-91"><a href="#L-91"><span class="linenos"> 91</span></a> <span class="o">...</span>
</span><span id="L-92"><a href="#L-92"><span class="linenos"> 92</span></a><span class="k">def</span> <span class="nf">parse_one</span><span class="p">(</span><span class="n">sql</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Expression</span><span class="p">:</span> </span><span id="L-92"><a href="#L-92"><span class="linenos"> 92</span></a>
</span><span id="L-93"><a href="#L-93"><span class="linenos"> 93</span></a> <span class="o">...</span> </span><span id="L-93"><a href="#L-93"><span class="linenos"> 93</span></a>
</span><span id="L-94"><a href="#L-94"><span class="linenos"> 94</span></a> </span><span id="L-94"><a href="#L-94"><span class="linenos"> 94</span></a><span class="nd">@t</span><span class="o">.</span><span class="n">overload</span>
</span><span id="L-95"><a href="#L-95"><span class="linenos"> 95</span></a> </span><span id="L-95"><a href="#L-95"><span class="linenos"> 95</span></a><span class="k">def</span> <span class="nf">parse_one</span><span class="p">(</span><span class="n">sql</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Expression</span><span class="p">:</span>
</span><span id="L-96"><a href="#L-96"><span class="linenos"> 96</span></a><span class="k">def</span> <span class="nf">parse_one</span><span class="p">(</span> </span><span id="L-96"><a href="#L-96"><span class="linenos"> 96</span></a> <span class="o">...</span>
</span><span id="L-97"><a href="#L-97"><span class="linenos"> 97</span></a> <span class="n">sql</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> </span><span id="L-97"><a href="#L-97"><span class="linenos"> 97</span></a>
</span><span id="L-98"><a href="#L-98"><span class="linenos"> 98</span></a> <span class="n">read</span><span class="p">:</span> <span class="n">DialectType</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> </span><span id="L-98"><a href="#L-98"><span class="linenos"> 98</span></a>
</span><span id="L-99"><a href="#L-99"><span class="linenos"> 99</span></a> <span class="n">dialect</span><span class="p">:</span> <span class="n">DialectType</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> </span><span id="L-99"><a href="#L-99"><span class="linenos"> 99</span></a><span class="k">def</span> <span class="nf">parse_one</span><span class="p">(</span>
</span><span id="L-100"><a href="#L-100"><span class="linenos">100</span></a> <span class="n">into</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">exp</span><span class="o">.</span><span class="n">IntoType</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> </span><span id="L-100"><a href="#L-100"><span class="linenos">100</span></a> <span class="n">sql</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span>
</span><span id="L-101"><a href="#L-101"><span class="linenos">101</span></a> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> </span><span id="L-101"><a href="#L-101"><span class="linenos">101</span></a> <span class="n">read</span><span class="p">:</span> <span class="n">DialectType</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="L-102"><a href="#L-102"><span class="linenos">102</span></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Expression</span><span class="p">:</span> </span><span id="L-102"><a href="#L-102"><span class="linenos">102</span></a> <span class="n">dialect</span><span class="p">:</span> <span class="n">DialectType</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="L-103"><a href="#L-103"><span class="linenos">103</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span> </span><span id="L-103"><a href="#L-103"><span class="linenos">103</span></a> <span class="n">into</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">exp</span><span class="o">.</span><span class="n">IntoType</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="L-104"><a href="#L-104"><span class="linenos">104</span></a><span class="sd"> Parses the given SQL string and returns a syntax tree for the first parsed SQL statement.</span> </span><span id="L-104"><a href="#L-104"><span class="linenos">104</span></a> <span class="o">**</span><span class="n">opts</span><span class="p">,</span>
</span><span id="L-105"><a href="#L-105"><span class="linenos">105</span></a> </span><span id="L-105"><a href="#L-105"><span class="linenos">105</span></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Expression</span><span class="p">:</span>
</span><span id="L-106"><a href="#L-106"><span class="linenos">106</span></a><span class="sd"> Args:</span> </span><span id="L-106"><a href="#L-106"><span class="linenos">106</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-107"><a href="#L-107"><span class="linenos">107</span></a><span class="sd"> sql: the SQL code string to parse.</span> </span><span id="L-107"><a href="#L-107"><span class="linenos">107</span></a><span class="sd"> Parses the given SQL string and returns a syntax tree for the first parsed SQL statement.</span>
</span><span id="L-108"><a href="#L-108"><span class="linenos">108</span></a><span class="sd"> read: the SQL dialect to apply during parsing (eg. &quot;spark&quot;, &quot;hive&quot;, &quot;presto&quot;, &quot;mysql&quot;).</span> </span><span id="L-108"><a href="#L-108"><span class="linenos">108</span></a>
</span><span id="L-109"><a href="#L-109"><span class="linenos">109</span></a><span class="sd"> dialect: the SQL dialect (alias for read)</span> </span><span id="L-109"><a href="#L-109"><span class="linenos">109</span></a><span class="sd"> Args:</span>
</span><span id="L-110"><a href="#L-110"><span class="linenos">110</span></a><span class="sd"> into: the SQLGlot Expression to parse into.</span> </span><span id="L-110"><a href="#L-110"><span class="linenos">110</span></a><span class="sd"> sql: the SQL code string to parse.</span>
</span><span id="L-111"><a href="#L-111"><span class="linenos">111</span></a><span class="sd"> **opts: other `sqlglot.parser.Parser` options.</span> </span><span id="L-111"><a href="#L-111"><span class="linenos">111</span></a><span class="sd"> read: the SQL dialect to apply during parsing (eg. &quot;spark&quot;, &quot;hive&quot;, &quot;presto&quot;, &quot;mysql&quot;).</span>
</span><span id="L-112"><a href="#L-112"><span class="linenos">112</span></a> </span><span id="L-112"><a href="#L-112"><span class="linenos">112</span></a><span class="sd"> dialect: the SQL dialect (alias for read)</span>
</span><span id="L-113"><a href="#L-113"><span class="linenos">113</span></a><span class="sd"> Returns:</span> </span><span id="L-113"><a href="#L-113"><span class="linenos">113</span></a><span class="sd"> into: the SQLGlot Expression to parse into.</span>
</span><span id="L-114"><a href="#L-114"><span class="linenos">114</span></a><span class="sd"> The syntax tree for the first parsed statement.</span> </span><span id="L-114"><a href="#L-114"><span class="linenos">114</span></a><span class="sd"> **opts: other `sqlglot.parser.Parser` options.</span>
</span><span id="L-115"><a href="#L-115"><span class="linenos">115</span></a><span class="sd"> &quot;&quot;&quot;</span> </span><span id="L-115"><a href="#L-115"><span class="linenos">115</span></a>
</span><span id="L-116"><a href="#L-116"><span class="linenos">116</span></a> </span><span id="L-116"><a href="#L-116"><span class="linenos">116</span></a><span class="sd"> Returns:</span>
</span><span id="L-117"><a href="#L-117"><span class="linenos">117</span></a> <span class="n">dialect</span> <span class="o">=</span> <span class="n">Dialect</span><span class="o">.</span><span class="n">get_or_raise</span><span class="p">(</span><span class="n">read</span> <span class="ow">or</span> <span class="n">dialect</span><span class="p">)()</span> </span><span id="L-117"><a href="#L-117"><span class="linenos">117</span></a><span class="sd"> The syntax tree for the first parsed statement.</span>
</span><span id="L-118"><a href="#L-118"><span class="linenos">118</span></a> </span><span id="L-118"><a href="#L-118"><span class="linenos">118</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-119"><a href="#L-119"><span class="linenos">119</span></a> <span class="k">if</span> <span class="n">into</span><span class="p">:</span> </span><span id="L-119"><a href="#L-119"><span class="linenos">119</span></a>
</span><span id="L-120"><a href="#L-120"><span class="linenos">120</span></a> <span class="n">result</span> <span class="o">=</span> <span class="n">dialect</span><span class="o">.</span><span class="n">parse_into</span><span class="p">(</span><span class="n">into</span><span class="p">,</span> <span class="n">sql</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span> </span><span id="L-120"><a href="#L-120"><span class="linenos">120</span></a> <span class="n">dialect</span> <span class="o">=</span> <span class="n">Dialect</span><span class="o">.</span><span class="n">get_or_raise</span><span class="p">(</span><span class="n">read</span> <span class="ow">or</span> <span class="n">dialect</span><span class="p">)()</span>
</span><span id="L-121"><a href="#L-121"><span class="linenos">121</span></a> <span class="k">else</span><span class="p">:</span> </span><span id="L-121"><a href="#L-121"><span class="linenos">121</span></a>
</span><span id="L-122"><a href="#L-122"><span class="linenos">122</span></a> <span class="n">result</span> <span class="o">=</span> <span class="n">dialect</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span> </span><span id="L-122"><a href="#L-122"><span class="linenos">122</span></a> <span class="k">if</span> <span class="n">into</span><span class="p">:</span>
</span><span id="L-123"><a href="#L-123"><span class="linenos">123</span></a> </span><span id="L-123"><a href="#L-123"><span class="linenos">123</span></a> <span class="n">result</span> <span class="o">=</span> <span class="n">dialect</span><span class="o">.</span><span class="n">parse_into</span><span class="p">(</span><span class="n">into</span><span class="p">,</span> <span class="n">sql</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span>
</span><span id="L-124"><a href="#L-124"><span class="linenos">124</span></a> <span class="k">for</span> <span class="n">expression</span> <span class="ow">in</span> <span class="n">result</span><span class="p">:</span> </span><span id="L-124"><a href="#L-124"><span class="linenos">124</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-125"><a href="#L-125"><span class="linenos">125</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">expression</span><span class="p">:</span> </span><span id="L-125"><a href="#L-125"><span class="linenos">125</span></a> <span class="n">result</span> <span class="o">=</span> <span class="n">dialect</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span>
</span><span id="L-126"><a href="#L-126"><span class="linenos">126</span></a> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;No expression was parsed from &#39;</span><span class="si">{</span><span class="n">sql</span><span class="si">}</span><span class="s2">&#39;&quot;</span><span class="p">)</span> </span><span id="L-126"><a href="#L-126"><span class="linenos">126</span></a>
</span><span id="L-127"><a href="#L-127"><span class="linenos">127</span></a> <span class="k">return</span> <span class="n">expression</span> </span><span id="L-127"><a href="#L-127"><span class="linenos">127</span></a> <span class="k">for</span> <span class="n">expression</span> <span class="ow">in</span> <span class="n">result</span><span class="p">:</span>
</span><span id="L-128"><a href="#L-128"><span class="linenos">128</span></a> <span class="k">else</span><span class="p">:</span> </span><span id="L-128"><a href="#L-128"><span class="linenos">128</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">expression</span><span class="p">:</span>
</span><span id="L-129"><a href="#L-129"><span class="linenos">129</span></a> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;No expression was parsed from &#39;</span><span class="si">{</span><span class="n">sql</span><span class="si">}</span><span class="s2">&#39;&quot;</span><span class="p">)</span> </span><span id="L-129"><a href="#L-129"><span class="linenos">129</span></a> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;No expression was parsed from &#39;</span><span class="si">{</span><span class="n">sql</span><span class="si">}</span><span class="s2">&#39;&quot;</span><span class="p">)</span>
</span><span id="L-130"><a href="#L-130"><span class="linenos">130</span></a> </span><span id="L-130"><a href="#L-130"><span class="linenos">130</span></a> <span class="k">return</span> <span class="n">expression</span>
</span><span id="L-131"><a href="#L-131"><span class="linenos">131</span></a> </span><span id="L-131"><a href="#L-131"><span class="linenos">131</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-132"><a href="#L-132"><span class="linenos">132</span></a><span class="k">def</span> <span class="nf">transpile</span><span class="p">(</span> </span><span id="L-132"><a href="#L-132"><span class="linenos">132</span></a> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;No expression was parsed from &#39;</span><span class="si">{</span><span class="n">sql</span><span class="si">}</span><span class="s2">&#39;&quot;</span><span class="p">)</span>
</span><span id="L-133"><a href="#L-133"><span class="linenos">133</span></a> <span class="n">sql</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> </span><span id="L-133"><a href="#L-133"><span class="linenos">133</span></a>
</span><span id="L-134"><a href="#L-134"><span class="linenos">134</span></a> <span class="n">read</span><span class="p">:</span> <span class="n">DialectType</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> </span><span id="L-134"><a href="#L-134"><span class="linenos">134</span></a>
</span><span id="L-135"><a href="#L-135"><span class="linenos">135</span></a> <span class="n">write</span><span class="p">:</span> <span class="n">DialectType</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> </span><span id="L-135"><a href="#L-135"><span class="linenos">135</span></a><span class="k">def</span> <span class="nf">transpile</span><span class="p">(</span>
</span><span id="L-136"><a href="#L-136"><span class="linenos">136</span></a> <span class="n">identity</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">True</span><span class="p">,</span> </span><span id="L-136"><a href="#L-136"><span class="linenos">136</span></a> <span class="n">sql</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span>
</span><span id="L-137"><a href="#L-137"><span class="linenos">137</span></a> <span class="n">error_level</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">ErrorLevel</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> </span><span id="L-137"><a href="#L-137"><span class="linenos">137</span></a> <span class="n">read</span><span class="p">:</span> <span class="n">DialectType</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="L-138"><a href="#L-138"><span class="linenos">138</span></a> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> </span><span id="L-138"><a href="#L-138"><span class="linenos">138</span></a> <span class="n">write</span><span class="p">:</span> <span class="n">DialectType</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="L-139"><a href="#L-139"><span class="linenos">139</span></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span> </span><span id="L-139"><a href="#L-139"><span class="linenos">139</span></a> <span class="n">identity</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">True</span><span class="p">,</span>
</span><span id="L-140"><a href="#L-140"><span class="linenos">140</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span> </span><span id="L-140"><a href="#L-140"><span class="linenos">140</span></a> <span class="n">error_level</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">ErrorLevel</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="L-141"><a href="#L-141"><span class="linenos">141</span></a><span class="sd"> Parses the given SQL string in accordance with the source dialect and returns a list of SQL strings transformed</span> </span><span id="L-141"><a href="#L-141"><span class="linenos">141</span></a> <span class="o">**</span><span class="n">opts</span><span class="p">,</span>
</span><span id="L-142"><a href="#L-142"><span class="linenos">142</span></a><span class="sd"> to conform to the target dialect. Each string in the returned list represents a single transformed SQL statement.</span> </span><span id="L-142"><a href="#L-142"><span class="linenos">142</span></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
</span><span id="L-143"><a href="#L-143"><span class="linenos">143</span></a> </span><span id="L-143"><a href="#L-143"><span class="linenos">143</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-144"><a href="#L-144"><span class="linenos">144</span></a><span class="sd"> Args:</span> </span><span id="L-144"><a href="#L-144"><span class="linenos">144</span></a><span class="sd"> Parses the given SQL string in accordance with the source dialect and returns a list of SQL strings transformed</span>
</span><span id="L-145"><a href="#L-145"><span class="linenos">145</span></a><span class="sd"> sql: the SQL code string to transpile.</span> </span><span id="L-145"><a href="#L-145"><span class="linenos">145</span></a><span class="sd"> to conform to the target dialect. Each string in the returned list represents a single transformed SQL statement.</span>
</span><span id="L-146"><a href="#L-146"><span class="linenos">146</span></a><span class="sd"> read: the source dialect used to parse the input string (eg. &quot;spark&quot;, &quot;hive&quot;, &quot;presto&quot;, &quot;mysql&quot;).</span> </span><span id="L-146"><a href="#L-146"><span class="linenos">146</span></a>
</span><span id="L-147"><a href="#L-147"><span class="linenos">147</span></a><span class="sd"> write: the target dialect into which the input should be transformed (eg. &quot;spark&quot;, &quot;hive&quot;, &quot;presto&quot;, &quot;mysql&quot;).</span> </span><span id="L-147"><a href="#L-147"><span class="linenos">147</span></a><span class="sd"> Args:</span>
</span><span id="L-148"><a href="#L-148"><span class="linenos">148</span></a><span class="sd"> identity: if set to `True` and if the target dialect is not specified the source dialect will be used as both:</span> </span><span id="L-148"><a href="#L-148"><span class="linenos">148</span></a><span class="sd"> sql: the SQL code string to transpile.</span>
</span><span id="L-149"><a href="#L-149"><span class="linenos">149</span></a><span class="sd"> the source and the target dialect.</span> </span><span id="L-149"><a href="#L-149"><span class="linenos">149</span></a><span class="sd"> read: the source dialect used to parse the input string (eg. &quot;spark&quot;, &quot;hive&quot;, &quot;presto&quot;, &quot;mysql&quot;).</span>
</span><span id="L-150"><a href="#L-150"><span class="linenos">150</span></a><span class="sd"> error_level: the desired error level of the parser.</span> </span><span id="L-150"><a href="#L-150"><span class="linenos">150</span></a><span class="sd"> write: the target dialect into which the input should be transformed (eg. &quot;spark&quot;, &quot;hive&quot;, &quot;presto&quot;, &quot;mysql&quot;).</span>
</span><span id="L-151"><a href="#L-151"><span class="linenos">151</span></a><span class="sd"> **opts: other `sqlglot.generator.Generator` options.</span> </span><span id="L-151"><a href="#L-151"><span class="linenos">151</span></a><span class="sd"> identity: if set to `True` and if the target dialect is not specified the source dialect will be used as both:</span>
</span><span id="L-152"><a href="#L-152"><span class="linenos">152</span></a> </span><span id="L-152"><a href="#L-152"><span class="linenos">152</span></a><span class="sd"> the source and the target dialect.</span>
</span><span id="L-153"><a href="#L-153"><span class="linenos">153</span></a><span class="sd"> Returns:</span> </span><span id="L-153"><a href="#L-153"><span class="linenos">153</span></a><span class="sd"> error_level: the desired error level of the parser.</span>
</span><span id="L-154"><a href="#L-154"><span class="linenos">154</span></a><span class="sd"> The list of transpiled SQL statements.</span> </span><span id="L-154"><a href="#L-154"><span class="linenos">154</span></a><span class="sd"> **opts: other `sqlglot.generator.Generator` options.</span>
</span><span id="L-155"><a href="#L-155"><span class="linenos">155</span></a><span class="sd"> &quot;&quot;&quot;</span> </span><span id="L-155"><a href="#L-155"><span class="linenos">155</span></a>
</span><span id="L-156"><a href="#L-156"><span class="linenos">156</span></a> <span class="n">write</span> <span class="o">=</span> <span class="p">(</span><span class="n">read</span> <span class="k">if</span> <span class="n">write</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">write</span><span class="p">)</span> <span class="k">if</span> <span class="n">identity</span> <span class="k">else</span> <span class="n">write</span> </span><span id="L-156"><a href="#L-156"><span class="linenos">156</span></a><span class="sd"> Returns:</span>
</span><span id="L-157"><a href="#L-157"><span class="linenos">157</span></a> <span class="k">return</span> <span class="p">[</span> </span><span id="L-157"><a href="#L-157"><span class="linenos">157</span></a><span class="sd"> The list of transpiled SQL statements.</span>
</span><span id="L-158"><a href="#L-158"><span class="linenos">158</span></a> <span class="n">Dialect</span><span class="o">.</span><span class="n">get_or_raise</span><span class="p">(</span><span class="n">write</span><span class="p">)()</span><span class="o">.</span><span class="n">generate</span><span class="p">(</span><span class="n">expression</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span> </span><span id="L-158"><a href="#L-158"><span class="linenos">158</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-159"><a href="#L-159"><span class="linenos">159</span></a> <span class="k">for</span> <span class="n">expression</span> <span class="ow">in</span> <span class="n">parse</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="n">read</span><span class="p">,</span> <span class="n">error_level</span><span class="o">=</span><span class="n">error_level</span><span class="p">)</span> </span><span id="L-159"><a href="#L-159"><span class="linenos">159</span></a> <span class="n">write</span> <span class="o">=</span> <span class="p">(</span><span class="n">read</span> <span class="k">if</span> <span class="n">write</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">write</span><span class="p">)</span> <span class="k">if</span> <span class="n">identity</span> <span class="k">else</span> <span class="n">write</span>
</span><span id="L-160"><a href="#L-160"><span class="linenos">160</span></a> <span class="p">]</span> </span><span id="L-160"><a href="#L-160"><span class="linenos">160</span></a> <span class="k">return</span> <span class="p">[</span>
</span><span id="L-161"><a href="#L-161"><span class="linenos">161</span></a> <span class="n">Dialect</span><span class="o">.</span><span class="n">get_or_raise</span><span class="p">(</span><span class="n">write</span><span class="p">)()</span><span class="o">.</span><span class="n">generate</span><span class="p">(</span><span class="n">expression</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span>
</span><span id="L-162"><a href="#L-162"><span class="linenos">162</span></a> <span class="k">for</span> <span class="n">expression</span> <span class="ow">in</span> <span class="n">parse</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="n">read</span><span class="p">,</span> <span class="n">error_level</span><span class="o">=</span><span class="n">error_level</span><span class="p">)</span>
</span><span id="L-163"><a href="#L-163"><span class="linenos">163</span></a> <span class="p">]</span>
</span></pre></div> </span></pre></div>
@ -882,26 +885,29 @@ make check # Full test suite &amp; linter checks
<div class="attr function"> <div class="attr function">
<span class="def">def</span> <span class="def">def</span>
<span class="name">parse</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="n">sql</span><span class="p">:</span> <span class="nb">str</span>,</span><span class="param"> <span class="n">read</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n"><a href="sqlglot/dialects/dialect.html#Dialect">sqlglot.dialects.dialect.Dialect</a></span><span class="p">,</span> <span class="n">Type</span><span class="p">[</span><span class="n"><a href="sqlglot/dialects/dialect.html#Dialect">sqlglot.dialects.dialect.Dialect</a></span><span class="p">],</span> <span class="n">NoneType</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>,</span><span class="param"> <span class="o">**</span><span class="n">opts</span></span><span class="return-annotation">) -> <span class="n">List</span><span class="p">[</span><span class="n">Optional</span><span class="p">[</span><span class="n"><a href="sqlglot/expressions.html#Expression">sqlglot.expressions.Expression</a></span><span class="p">]]</span>:</span></span> <span class="name">parse</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="n">sql</span><span class="p">:</span> <span class="nb">str</span>,</span><span class="param"> <span class="n">read</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n"><a href="sqlglot/dialects/dialect.html#Dialect">sqlglot.dialects.dialect.Dialect</a></span><span class="p">,</span> <span class="n">Type</span><span class="p">[</span><span class="n"><a href="sqlglot/dialects/dialect.html#Dialect">sqlglot.dialects.dialect.Dialect</a></span><span class="p">],</span> <span class="n">NoneType</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>,</span><span class="param"> <span class="n">dialect</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n"><a href="sqlglot/dialects/dialect.html#Dialect">sqlglot.dialects.dialect.Dialect</a></span><span class="p">,</span> <span class="n">Type</span><span class="p">[</span><span class="n"><a href="sqlglot/dialects/dialect.html#Dialect">sqlglot.dialects.dialect.Dialect</a></span><span class="p">],</span> <span class="n">NoneType</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>,</span><span class="param"> <span class="o">**</span><span class="n">opts</span></span><span class="return-annotation">) -> <span class="n">List</span><span class="p">[</span><span class="n">Optional</span><span class="p">[</span><span class="n"><a href="sqlglot/expressions.html#Expression">sqlglot.expressions.Expression</a></span><span class="p">]]</span>:</span></span>
<label class="view-source-button" for="parse-view-source"><span>View Source</span></label> <label class="view-source-button" for="parse-view-source"><span>View Source</span></label>
</div> </div>
<a class="headerlink" href="#parse"></a> <a class="headerlink" href="#parse"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="parse-71"><a href="#parse-71"><span class="linenos">71</span></a><span class="k">def</span> <span class="nf">parse</span><span class="p">(</span><span class="n">sql</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">read</span><span class="p">:</span> <span class="n">DialectType</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">List</span><span class="p">[</span><span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">Expression</span><span class="p">]]:</span> <div class="pdoc-code codehilite"><pre><span></span><span id="parse-71"><a href="#parse-71"><span class="linenos">71</span></a><span class="k">def</span> <span class="nf">parse</span><span class="p">(</span>
</span><span id="parse-72"><a href="#parse-72"><span class="linenos">72</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span> </span><span id="parse-72"><a href="#parse-72"><span class="linenos">72</span></a> <span class="n">sql</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">read</span><span class="p">:</span> <span class="n">DialectType</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="n">dialect</span><span class="p">:</span> <span class="n">DialectType</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span>
</span><span id="parse-73"><a href="#parse-73"><span class="linenos">73</span></a><span class="sd"> Parses the given SQL string into a collection of syntax trees, one per parsed SQL statement.</span> </span><span id="parse-73"><a href="#parse-73"><span class="linenos">73</span></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">List</span><span class="p">[</span><span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">Expression</span><span class="p">]]:</span>
</span><span id="parse-74"><a href="#parse-74"><span class="linenos">74</span></a> </span><span id="parse-74"><a href="#parse-74"><span class="linenos">74</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="parse-75"><a href="#parse-75"><span class="linenos">75</span></a><span class="sd"> Args:</span> </span><span id="parse-75"><a href="#parse-75"><span class="linenos">75</span></a><span class="sd"> Parses the given SQL string into a collection of syntax trees, one per parsed SQL statement.</span>
</span><span id="parse-76"><a href="#parse-76"><span class="linenos">76</span></a><span class="sd"> sql: the SQL code string to parse.</span> </span><span id="parse-76"><a href="#parse-76"><span class="linenos">76</span></a>
</span><span id="parse-77"><a href="#parse-77"><span class="linenos">77</span></a><span class="sd"> read: the SQL dialect to apply during parsing (eg. &quot;spark&quot;, &quot;hive&quot;, &quot;presto&quot;, &quot;mysql&quot;).</span> </span><span id="parse-77"><a href="#parse-77"><span class="linenos">77</span></a><span class="sd"> Args:</span>
</span><span id="parse-78"><a href="#parse-78"><span class="linenos">78</span></a><span class="sd"> **opts: other `sqlglot.parser.Parser` options.</span> </span><span id="parse-78"><a href="#parse-78"><span class="linenos">78</span></a><span class="sd"> sql: the SQL code string to parse.</span>
</span><span id="parse-79"><a href="#parse-79"><span class="linenos">79</span></a> </span><span id="parse-79"><a href="#parse-79"><span class="linenos">79</span></a><span class="sd"> read: the SQL dialect to apply during parsing (eg. &quot;spark&quot;, &quot;hive&quot;, &quot;presto&quot;, &quot;mysql&quot;).</span>
</span><span id="parse-80"><a href="#parse-80"><span class="linenos">80</span></a><span class="sd"> Returns:</span> </span><span id="parse-80"><a href="#parse-80"><span class="linenos">80</span></a><span class="sd"> dialect: the SQL dialect (alias for read).</span>
</span><span id="parse-81"><a href="#parse-81"><span class="linenos">81</span></a><span class="sd"> The resulting syntax tree collection.</span> </span><span id="parse-81"><a href="#parse-81"><span class="linenos">81</span></a><span class="sd"> **opts: other `sqlglot.parser.Parser` options.</span>
</span><span id="parse-82"><a href="#parse-82"><span class="linenos">82</span></a><span class="sd"> &quot;&quot;&quot;</span> </span><span id="parse-82"><a href="#parse-82"><span class="linenos">82</span></a>
</span><span id="parse-83"><a href="#parse-83"><span class="linenos">83</span></a> <span class="n">dialect</span> <span class="o">=</span> <span class="n">Dialect</span><span class="o">.</span><span class="n">get_or_raise</span><span class="p">(</span><span class="n">read</span><span class="p">)()</span> </span><span id="parse-83"><a href="#parse-83"><span class="linenos">83</span></a><span class="sd"> Returns:</span>
</span><span id="parse-84"><a href="#parse-84"><span class="linenos">84</span></a> <span class="k">return</span> <span class="n">dialect</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span> </span><span id="parse-84"><a href="#parse-84"><span class="linenos">84</span></a><span class="sd"> The resulting syntax tree collection.</span>
</span><span id="parse-85"><a href="#parse-85"><span class="linenos">85</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="parse-86"><a href="#parse-86"><span class="linenos">86</span></a> <span class="n">dialect</span> <span class="o">=</span> <span class="n">Dialect</span><span class="o">.</span><span class="n">get_or_raise</span><span class="p">(</span><span class="n">read</span> <span class="ow">or</span> <span class="n">dialect</span><span class="p">)()</span>
</span><span id="parse-87"><a href="#parse-87"><span class="linenos">87</span></a> <span class="k">return</span> <span class="n">dialect</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span>
</span></pre></div> </span></pre></div>
@ -912,6 +918,7 @@ make check # Full test suite &amp; linter checks
<ul> <ul>
<li><strong>sql:</strong> the SQL code string to parse.</li> <li><strong>sql:</strong> the SQL code string to parse.</li>
<li><strong>read:</strong> the SQL dialect to apply during parsing (eg. "spark", "hive", "presto", "mysql").</li> <li><strong>read:</strong> the SQL dialect to apply during parsing (eg. "spark", "hive", "presto", "mysql").</li>
<li><strong>dialect:</strong> the SQL dialect (alias for read).</li>
<li><strong>**opts:</strong> other <code><a href="sqlglot/parser.html#Parser">sqlglot.parser.Parser</a></code> options.</li> <li><strong>**opts:</strong> other <code><a href="sqlglot/parser.html#Parser">sqlglot.parser.Parser</a></code> options.</li>
</ul> </ul>
@ -935,40 +942,40 @@ make check # Full test suite &amp; linter checks
</div> </div>
<a class="headerlink" href="#parse_one"></a> <a class="headerlink" href="#parse_one"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="parse_one-97"><a href="#parse_one-97"><span class="linenos"> 97</span></a><span class="k">def</span> <span class="nf">parse_one</span><span class="p">(</span> <div class="pdoc-code codehilite"><pre><span></span><span id="parse_one-100"><a href="#parse_one-100"><span class="linenos">100</span></a><span class="k">def</span> <span class="nf">parse_one</span><span class="p">(</span>
</span><span id="parse_one-98"><a href="#parse_one-98"><span class="linenos"> 98</span></a> <span class="n">sql</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> </span><span id="parse_one-101"><a href="#parse_one-101"><span class="linenos">101</span></a> <span class="n">sql</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span>
</span><span id="parse_one-99"><a href="#parse_one-99"><span class="linenos"> 99</span></a> <span class="n">read</span><span class="p">:</span> <span class="n">DialectType</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> </span><span id="parse_one-102"><a href="#parse_one-102"><span class="linenos">102</span></a> <span class="n">read</span><span class="p">:</span> <span class="n">DialectType</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="parse_one-100"><a href="#parse_one-100"><span class="linenos">100</span></a> <span class="n">dialect</span><span class="p">:</span> <span class="n">DialectType</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> </span><span id="parse_one-103"><a href="#parse_one-103"><span class="linenos">103</span></a> <span class="n">dialect</span><span class="p">:</span> <span class="n">DialectType</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="parse_one-101"><a href="#parse_one-101"><span class="linenos">101</span></a> <span class="n">into</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">exp</span><span class="o">.</span><span class="n">IntoType</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> </span><span id="parse_one-104"><a href="#parse_one-104"><span class="linenos">104</span></a> <span class="n">into</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">exp</span><span class="o">.</span><span class="n">IntoType</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="parse_one-102"><a href="#parse_one-102"><span class="linenos">102</span></a> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> </span><span id="parse_one-105"><a href="#parse_one-105"><span class="linenos">105</span></a> <span class="o">**</span><span class="n">opts</span><span class="p">,</span>
</span><span id="parse_one-103"><a href="#parse_one-103"><span class="linenos">103</span></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Expression</span><span class="p">:</span> </span><span id="parse_one-106"><a href="#parse_one-106"><span class="linenos">106</span></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Expression</span><span class="p">:</span>
</span><span id="parse_one-104"><a href="#parse_one-104"><span class="linenos">104</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span> </span><span id="parse_one-107"><a href="#parse_one-107"><span class="linenos">107</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="parse_one-105"><a href="#parse_one-105"><span class="linenos">105</span></a><span class="sd"> Parses the given SQL string and returns a syntax tree for the first parsed SQL statement.</span> </span><span id="parse_one-108"><a href="#parse_one-108"><span class="linenos">108</span></a><span class="sd"> Parses the given SQL string and returns a syntax tree for the first parsed SQL statement.</span>
</span><span id="parse_one-106"><a href="#parse_one-106"><span class="linenos">106</span></a> </span><span id="parse_one-109"><a href="#parse_one-109"><span class="linenos">109</span></a>
</span><span id="parse_one-107"><a href="#parse_one-107"><span class="linenos">107</span></a><span class="sd"> Args:</span> </span><span id="parse_one-110"><a href="#parse_one-110"><span class="linenos">110</span></a><span class="sd"> Args:</span>
</span><span id="parse_one-108"><a href="#parse_one-108"><span class="linenos">108</span></a><span class="sd"> sql: the SQL code string to parse.</span> </span><span id="parse_one-111"><a href="#parse_one-111"><span class="linenos">111</span></a><span class="sd"> sql: the SQL code string to parse.</span>
</span><span id="parse_one-109"><a href="#parse_one-109"><span class="linenos">109</span></a><span class="sd"> read: the SQL dialect to apply during parsing (eg. &quot;spark&quot;, &quot;hive&quot;, &quot;presto&quot;, &quot;mysql&quot;).</span> </span><span id="parse_one-112"><a href="#parse_one-112"><span class="linenos">112</span></a><span class="sd"> read: the SQL dialect to apply during parsing (eg. &quot;spark&quot;, &quot;hive&quot;, &quot;presto&quot;, &quot;mysql&quot;).</span>
</span><span id="parse_one-110"><a href="#parse_one-110"><span class="linenos">110</span></a><span class="sd"> dialect: the SQL dialect (alias for read)</span> </span><span id="parse_one-113"><a href="#parse_one-113"><span class="linenos">113</span></a><span class="sd"> dialect: the SQL dialect (alias for read)</span>
</span><span id="parse_one-111"><a href="#parse_one-111"><span class="linenos">111</span></a><span class="sd"> into: the SQLGlot Expression to parse into.</span> </span><span id="parse_one-114"><a href="#parse_one-114"><span class="linenos">114</span></a><span class="sd"> into: the SQLGlot Expression to parse into.</span>
</span><span id="parse_one-112"><a href="#parse_one-112"><span class="linenos">112</span></a><span class="sd"> **opts: other `sqlglot.parser.Parser` options.</span> </span><span id="parse_one-115"><a href="#parse_one-115"><span class="linenos">115</span></a><span class="sd"> **opts: other `sqlglot.parser.Parser` options.</span>
</span><span id="parse_one-113"><a href="#parse_one-113"><span class="linenos">113</span></a> </span><span id="parse_one-116"><a href="#parse_one-116"><span class="linenos">116</span></a>
</span><span id="parse_one-114"><a href="#parse_one-114"><span class="linenos">114</span></a><span class="sd"> Returns:</span> </span><span id="parse_one-117"><a href="#parse_one-117"><span class="linenos">117</span></a><span class="sd"> Returns:</span>
</span><span id="parse_one-115"><a href="#parse_one-115"><span class="linenos">115</span></a><span class="sd"> The syntax tree for the first parsed statement.</span> </span><span id="parse_one-118"><a href="#parse_one-118"><span class="linenos">118</span></a><span class="sd"> The syntax tree for the first parsed statement.</span>
</span><span id="parse_one-116"><a href="#parse_one-116"><span class="linenos">116</span></a><span class="sd"> &quot;&quot;&quot;</span> </span><span id="parse_one-119"><a href="#parse_one-119"><span class="linenos">119</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="parse_one-117"><a href="#parse_one-117"><span class="linenos">117</span></a> </span><span id="parse_one-120"><a href="#parse_one-120"><span class="linenos">120</span></a>
</span><span id="parse_one-118"><a href="#parse_one-118"><span class="linenos">118</span></a> <span class="n">dialect</span> <span class="o">=</span> <span class="n">Dialect</span><span class="o">.</span><span class="n">get_or_raise</span><span class="p">(</span><span class="n">read</span> <span class="ow">or</span> <span class="n">dialect</span><span class="p">)()</span> </span><span id="parse_one-121"><a href="#parse_one-121"><span class="linenos">121</span></a> <span class="n">dialect</span> <span class="o">=</span> <span class="n">Dialect</span><span class="o">.</span><span class="n">get_or_raise</span><span class="p">(</span><span class="n">read</span> <span class="ow">or</span> <span class="n">dialect</span><span class="p">)()</span>
</span><span id="parse_one-119"><a href="#parse_one-119"><span class="linenos">119</span></a> </span><span id="parse_one-122"><a href="#parse_one-122"><span class="linenos">122</span></a>
</span><span id="parse_one-120"><a href="#parse_one-120"><span class="linenos">120</span></a> <span class="k">if</span> <span class="n">into</span><span class="p">:</span> </span><span id="parse_one-123"><a href="#parse_one-123"><span class="linenos">123</span></a> <span class="k">if</span> <span class="n">into</span><span class="p">:</span>
</span><span id="parse_one-121"><a href="#parse_one-121"><span class="linenos">121</span></a> <span class="n">result</span> <span class="o">=</span> <span class="n">dialect</span><span class="o">.</span><span class="n">parse_into</span><span class="p">(</span><span class="n">into</span><span class="p">,</span> <span class="n">sql</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span> </span><span id="parse_one-124"><a href="#parse_one-124"><span class="linenos">124</span></a> <span class="n">result</span> <span class="o">=</span> <span class="n">dialect</span><span class="o">.</span><span class="n">parse_into</span><span class="p">(</span><span class="n">into</span><span class="p">,</span> <span class="n">sql</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span>
</span><span id="parse_one-122"><a href="#parse_one-122"><span class="linenos">122</span></a> <span class="k">else</span><span class="p">:</span> </span><span id="parse_one-125"><a href="#parse_one-125"><span class="linenos">125</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="parse_one-123"><a href="#parse_one-123"><span class="linenos">123</span></a> <span class="n">result</span> <span class="o">=</span> <span class="n">dialect</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span> </span><span id="parse_one-126"><a href="#parse_one-126"><span class="linenos">126</span></a> <span class="n">result</span> <span class="o">=</span> <span class="n">dialect</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span>
</span><span id="parse_one-124"><a href="#parse_one-124"><span class="linenos">124</span></a> </span><span id="parse_one-127"><a href="#parse_one-127"><span class="linenos">127</span></a>
</span><span id="parse_one-125"><a href="#parse_one-125"><span class="linenos">125</span></a> <span class="k">for</span> <span class="n">expression</span> <span class="ow">in</span> <span class="n">result</span><span class="p">:</span> </span><span id="parse_one-128"><a href="#parse_one-128"><span class="linenos">128</span></a> <span class="k">for</span> <span class="n">expression</span> <span class="ow">in</span> <span class="n">result</span><span class="p">:</span>
</span><span id="parse_one-126"><a href="#parse_one-126"><span class="linenos">126</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">expression</span><span class="p">:</span> </span><span id="parse_one-129"><a href="#parse_one-129"><span class="linenos">129</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">expression</span><span class="p">:</span>
</span><span id="parse_one-127"><a href="#parse_one-127"><span class="linenos">127</span></a> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;No expression was parsed from &#39;</span><span class="si">{</span><span class="n">sql</span><span class="si">}</span><span class="s2">&#39;&quot;</span><span class="p">)</span>
</span><span id="parse_one-128"><a href="#parse_one-128"><span class="linenos">128</span></a> <span class="k">return</span> <span class="n">expression</span>
</span><span id="parse_one-129"><a href="#parse_one-129"><span class="linenos">129</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="parse_one-130"><a href="#parse_one-130"><span class="linenos">130</span></a> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;No expression was parsed from &#39;</span><span class="si">{</span><span class="n">sql</span><span class="si">}</span><span class="s2">&#39;&quot;</span><span class="p">)</span> </span><span id="parse_one-130"><a href="#parse_one-130"><span class="linenos">130</span></a> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;No expression was parsed from &#39;</span><span class="si">{</span><span class="n">sql</span><span class="si">}</span><span class="s2">&#39;&quot;</span><span class="p">)</span>
</span><span id="parse_one-131"><a href="#parse_one-131"><span class="linenos">131</span></a> <span class="k">return</span> <span class="n">expression</span>
</span><span id="parse_one-132"><a href="#parse_one-132"><span class="linenos">132</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="parse_one-133"><a href="#parse_one-133"><span class="linenos">133</span></a> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;No expression was parsed from &#39;</span><span class="si">{</span><span class="n">sql</span><span class="si">}</span><span class="s2">&#39;&quot;</span><span class="p">)</span>
</span></pre></div> </span></pre></div>
@ -1004,35 +1011,35 @@ make check # Full test suite &amp; linter checks
</div> </div>
<a class="headerlink" href="#transpile"></a> <a class="headerlink" href="#transpile"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="transpile-133"><a href="#transpile-133"><span class="linenos">133</span></a><span class="k">def</span> <span class="nf">transpile</span><span class="p">(</span> <div class="pdoc-code codehilite"><pre><span></span><span id="transpile-136"><a href="#transpile-136"><span class="linenos">136</span></a><span class="k">def</span> <span class="nf">transpile</span><span class="p">(</span>
</span><span id="transpile-134"><a href="#transpile-134"><span class="linenos">134</span></a> <span class="n">sql</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> </span><span id="transpile-137"><a href="#transpile-137"><span class="linenos">137</span></a> <span class="n">sql</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span>
</span><span id="transpile-135"><a href="#transpile-135"><span class="linenos">135</span></a> <span class="n">read</span><span class="p">:</span> <span class="n">DialectType</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> </span><span id="transpile-138"><a href="#transpile-138"><span class="linenos">138</span></a> <span class="n">read</span><span class="p">:</span> <span class="n">DialectType</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="transpile-136"><a href="#transpile-136"><span class="linenos">136</span></a> <span class="n">write</span><span class="p">:</span> <span class="n">DialectType</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> </span><span id="transpile-139"><a href="#transpile-139"><span class="linenos">139</span></a> <span class="n">write</span><span class="p">:</span> <span class="n">DialectType</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="transpile-137"><a href="#transpile-137"><span class="linenos">137</span></a> <span class="n">identity</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">True</span><span class="p">,</span> </span><span id="transpile-140"><a href="#transpile-140"><span class="linenos">140</span></a> <span class="n">identity</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">True</span><span class="p">,</span>
</span><span id="transpile-138"><a href="#transpile-138"><span class="linenos">138</span></a> <span class="n">error_level</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">ErrorLevel</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> </span><span id="transpile-141"><a href="#transpile-141"><span class="linenos">141</span></a> <span class="n">error_level</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">ErrorLevel</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="transpile-139"><a href="#transpile-139"><span class="linenos">139</span></a> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> </span><span id="transpile-142"><a href="#transpile-142"><span class="linenos">142</span></a> <span class="o">**</span><span class="n">opts</span><span class="p">,</span>
</span><span id="transpile-140"><a href="#transpile-140"><span class="linenos">140</span></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span> </span><span id="transpile-143"><a href="#transpile-143"><span class="linenos">143</span></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
</span><span id="transpile-141"><a href="#transpile-141"><span class="linenos">141</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span> </span><span id="transpile-144"><a href="#transpile-144"><span class="linenos">144</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="transpile-142"><a href="#transpile-142"><span class="linenos">142</span></a><span class="sd"> Parses the given SQL string in accordance with the source dialect and returns a list of SQL strings transformed</span> </span><span id="transpile-145"><a href="#transpile-145"><span class="linenos">145</span></a><span class="sd"> Parses the given SQL string in accordance with the source dialect and returns a list of SQL strings transformed</span>
</span><span id="transpile-143"><a href="#transpile-143"><span class="linenos">143</span></a><span class="sd"> to conform to the target dialect. Each string in the returned list represents a single transformed SQL statement.</span> </span><span id="transpile-146"><a href="#transpile-146"><span class="linenos">146</span></a><span class="sd"> to conform to the target dialect. Each string in the returned list represents a single transformed SQL statement.</span>
</span><span id="transpile-144"><a href="#transpile-144"><span class="linenos">144</span></a> </span><span id="transpile-147"><a href="#transpile-147"><span class="linenos">147</span></a>
</span><span id="transpile-145"><a href="#transpile-145"><span class="linenos">145</span></a><span class="sd"> Args:</span> </span><span id="transpile-148"><a href="#transpile-148"><span class="linenos">148</span></a><span class="sd"> Args:</span>
</span><span id="transpile-146"><a href="#transpile-146"><span class="linenos">146</span></a><span class="sd"> sql: the SQL code string to transpile.</span> </span><span id="transpile-149"><a href="#transpile-149"><span class="linenos">149</span></a><span class="sd"> sql: the SQL code string to transpile.</span>
</span><span id="transpile-147"><a href="#transpile-147"><span class="linenos">147</span></a><span class="sd"> read: the source dialect used to parse the input string (eg. &quot;spark&quot;, &quot;hive&quot;, &quot;presto&quot;, &quot;mysql&quot;).</span> </span><span id="transpile-150"><a href="#transpile-150"><span class="linenos">150</span></a><span class="sd"> read: the source dialect used to parse the input string (eg. &quot;spark&quot;, &quot;hive&quot;, &quot;presto&quot;, &quot;mysql&quot;).</span>
</span><span id="transpile-148"><a href="#transpile-148"><span class="linenos">148</span></a><span class="sd"> write: the target dialect into which the input should be transformed (eg. &quot;spark&quot;, &quot;hive&quot;, &quot;presto&quot;, &quot;mysql&quot;).</span> </span><span id="transpile-151"><a href="#transpile-151"><span class="linenos">151</span></a><span class="sd"> write: the target dialect into which the input should be transformed (eg. &quot;spark&quot;, &quot;hive&quot;, &quot;presto&quot;, &quot;mysql&quot;).</span>
</span><span id="transpile-149"><a href="#transpile-149"><span class="linenos">149</span></a><span class="sd"> identity: if set to `True` and if the target dialect is not specified the source dialect will be used as both:</span> </span><span id="transpile-152"><a href="#transpile-152"><span class="linenos">152</span></a><span class="sd"> identity: if set to `True` and if the target dialect is not specified the source dialect will be used as both:</span>
</span><span id="transpile-150"><a href="#transpile-150"><span class="linenos">150</span></a><span class="sd"> the source and the target dialect.</span> </span><span id="transpile-153"><a href="#transpile-153"><span class="linenos">153</span></a><span class="sd"> the source and the target dialect.</span>
</span><span id="transpile-151"><a href="#transpile-151"><span class="linenos">151</span></a><span class="sd"> error_level: the desired error level of the parser.</span> </span><span id="transpile-154"><a href="#transpile-154"><span class="linenos">154</span></a><span class="sd"> error_level: the desired error level of the parser.</span>
</span><span id="transpile-152"><a href="#transpile-152"><span class="linenos">152</span></a><span class="sd"> **opts: other `sqlglot.generator.Generator` options.</span> </span><span id="transpile-155"><a href="#transpile-155"><span class="linenos">155</span></a><span class="sd"> **opts: other `sqlglot.generator.Generator` options.</span>
</span><span id="transpile-153"><a href="#transpile-153"><span class="linenos">153</span></a> </span><span id="transpile-156"><a href="#transpile-156"><span class="linenos">156</span></a>
</span><span id="transpile-154"><a href="#transpile-154"><span class="linenos">154</span></a><span class="sd"> Returns:</span> </span><span id="transpile-157"><a href="#transpile-157"><span class="linenos">157</span></a><span class="sd"> Returns:</span>
</span><span id="transpile-155"><a href="#transpile-155"><span class="linenos">155</span></a><span class="sd"> The list of transpiled SQL statements.</span> </span><span id="transpile-158"><a href="#transpile-158"><span class="linenos">158</span></a><span class="sd"> The list of transpiled SQL statements.</span>
</span><span id="transpile-156"><a href="#transpile-156"><span class="linenos">156</span></a><span class="sd"> &quot;&quot;&quot;</span> </span><span id="transpile-159"><a href="#transpile-159"><span class="linenos">159</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="transpile-157"><a href="#transpile-157"><span class="linenos">157</span></a> <span class="n">write</span> <span class="o">=</span> <span class="p">(</span><span class="n">read</span> <span class="k">if</span> <span class="n">write</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">write</span><span class="p">)</span> <span class="k">if</span> <span class="n">identity</span> <span class="k">else</span> <span class="n">write</span> </span><span id="transpile-160"><a href="#transpile-160"><span class="linenos">160</span></a> <span class="n">write</span> <span class="o">=</span> <span class="p">(</span><span class="n">read</span> <span class="k">if</span> <span class="n">write</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">write</span><span class="p">)</span> <span class="k">if</span> <span class="n">identity</span> <span class="k">else</span> <span class="n">write</span>
</span><span id="transpile-158"><a href="#transpile-158"><span class="linenos">158</span></a> <span class="k">return</span> <span class="p">[</span> </span><span id="transpile-161"><a href="#transpile-161"><span class="linenos">161</span></a> <span class="k">return</span> <span class="p">[</span>
</span><span id="transpile-159"><a href="#transpile-159"><span class="linenos">159</span></a> <span class="n">Dialect</span><span class="o">.</span><span class="n">get_or_raise</span><span class="p">(</span><span class="n">write</span><span class="p">)()</span><span class="o">.</span><span class="n">generate</span><span class="p">(</span><span class="n">expression</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span> </span><span id="transpile-162"><a href="#transpile-162"><span class="linenos">162</span></a> <span class="n">Dialect</span><span class="o">.</span><span class="n">get_or_raise</span><span class="p">(</span><span class="n">write</span><span class="p">)()</span><span class="o">.</span><span class="n">generate</span><span class="p">(</span><span class="n">expression</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span>
</span><span id="transpile-160"><a href="#transpile-160"><span class="linenos">160</span></a> <span class="k">for</span> <span class="n">expression</span> <span class="ow">in</span> <span class="n">parse</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="n">read</span><span class="p">,</span> <span class="n">error_level</span><span class="o">=</span><span class="n">error_level</span><span class="p">)</span> </span><span id="transpile-163"><a href="#transpile-163"><span class="linenos">163</span></a> <span class="k">for</span> <span class="n">expression</span> <span class="ow">in</span> <span class="n">parse</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="n">read</span><span class="p">,</span> <span class="n">error_level</span><span class="o">=</span><span class="n">error_level</span><span class="p">)</span>
</span><span id="transpile-161"><a href="#transpile-161"><span class="linenos">161</span></a> <span class="p">]</span> </span><span id="transpile-164"><a href="#transpile-164"><span class="linenos">164</span></a> <span class="p">]</span>
</span></pre></div> </span></pre></div>

View file

@ -51,8 +51,8 @@
<div class="pdoc-code codehilite"><pre><span></span><span id="L-1"><a href="#L-1"><span class="linenos">1</span></a><span class="c1"># file generated by setuptools_scm</span> <div class="pdoc-code codehilite"><pre><span></span><span id="L-1"><a href="#L-1"><span class="linenos">1</span></a><span class="c1"># file generated by setuptools_scm</span>
</span><span id="L-2"><a href="#L-2"><span class="linenos">2</span></a><span class="c1"># don&#39;t change, don&#39;t track in version control</span> </span><span id="L-2"><a href="#L-2"><span class="linenos">2</span></a><span class="c1"># don&#39;t change, don&#39;t track in version control</span>
</span><span id="L-3"><a href="#L-3"><span class="linenos">3</span></a><span class="n">__version__</span> <span class="o">=</span> <span class="n">version</span> <span class="o">=</span> <span class="s1">&#39;17.6.1&#39;</span> </span><span id="L-3"><a href="#L-3"><span class="linenos">3</span></a><span class="n">__version__</span> <span class="o">=</span> <span class="n">version</span> <span class="o">=</span> <span class="s1">&#39;17.9.0&#39;</span>
</span><span id="L-4"><a href="#L-4"><span class="linenos">4</span></a><span class="n">__version_tuple__</span> <span class="o">=</span> <span class="n">version_tuple</span> <span class="o">=</span> <span class="p">(</span><span class="mi">17</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> </span><span id="L-4"><a href="#L-4"><span class="linenos">4</span></a><span class="n">__version_tuple__</span> <span class="o">=</span> <span class="n">version_tuple</span> <span class="o">=</span> <span class="p">(</span><span class="mi">17</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
</span></pre></div> </span></pre></div>

View file

@ -777,7 +777,7 @@
<div class="attr function"> <div class="attr function">
<span class="def">def</span> <span class="def">def</span>
<span class="name">createDataFrame</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">self</span>,</span><span class="param"> <span class="n">data</span><span class="p">:</span> <span class="n">Sequence</span><span class="p">[</span><span class="n">Union</span><span class="p">[</span><span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539402082944&#39;</span><span class="o">&gt;</span><span class="p">],</span> <span class="n">List</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539402082944&#39;</span><span class="o">&gt;</span><span class="p">],</span> <span class="n">Tuple</span><span class="p">]]</span>,</span><span class="param"> <span class="n">schema</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539402129216&#39;</span><span class="o">&gt;</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>,</span><span class="param"> <span class="n">samplingRatio</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">float</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>,</span><span class="param"> <span class="n">verifySchema</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span></span><span class="return-annotation">) -> <span class="n"><a href="#DataFrame">sqlglot.dataframe.sql.DataFrame</a></span>:</span></span> <span class="name">createDataFrame</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">self</span>,</span><span class="param"> <span class="n">data</span><span class="p">:</span> <span class="n">Sequence</span><span class="p">[</span><span class="n">Union</span><span class="p">[</span><span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218889395968&#39;</span><span class="o">&gt;</span><span class="p">],</span> <span class="n">List</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218889395968&#39;</span><span class="o">&gt;</span><span class="p">],</span> <span class="n">Tuple</span><span class="p">]]</span>,</span><span class="param"> <span class="n">schema</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218887587680&#39;</span><span class="o">&gt;</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>,</span><span class="param"> <span class="n">samplingRatio</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">float</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>,</span><span class="param"> <span class="n">verifySchema</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span></span><span class="return-annotation">) -> <span class="n"><a href="#DataFrame">sqlglot.dataframe.sql.DataFrame</a></span>:</span></span>
<label class="view-source-button" for="SparkSession.createDataFrame-view-source"><span>View Source</span></label> <label class="view-source-button" for="SparkSession.createDataFrame-view-source"><span>View Source</span></label>
@ -1681,7 +1681,7 @@
<input id="DataFrame.__init__-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1"> <input id="DataFrame.__init__-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
<div class="attr function"> <div class="attr function">
<span class="name">DataFrame</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="n">spark</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539404916848&#39;</span><span class="o">&gt;</span>,</span><span class="param"> <span class="n">expression</span><span class="p">:</span> <span class="n"><a href="../expressions.html#Select">sqlglot.expressions.Select</a></span>,</span><span class="param"> <span class="n">branch_id</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>,</span><span class="param"> <span class="n">sequence_id</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>,</span><span class="param"> <span class="n">last_op</span><span class="p">:</span> <span class="n">sqlglot</span><span class="o">.</span><span class="n">dataframe</span><span class="o">.</span><span class="n">sql</span><span class="o">.</span><span class="n">operations</span><span class="o">.</span><span class="n">Operation</span> <span class="o">=</span> <span class="o">&lt;</span><span class="n">Operation</span><span class="o">.</span><span class="n">INIT</span><span class="p">:</span> <span class="o">-</span><span class="mi">1</span><span class="o">&gt;</span>,</span><span class="param"> <span class="n">pending_hints</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="n"><a href="../expressions.html#Expression">sqlglot.expressions.Expression</a></span><span class="p">]]</span> <span class="o">=</span> <span class="kc">None</span>,</span><span class="param"> <span class="n">output_expression_container</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539405009872&#39;</span><span class="o">&gt;</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>,</span><span class="param"> <span class="o">**</span><span class="n">kwargs</span></span>)</span> <span class="name">DataFrame</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="n">spark</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218892014624&#39;</span><span class="o">&gt;</span>,</span><span class="param"> <span class="n">expression</span><span class="p">:</span> <span class="n"><a href="../expressions.html#Select">sqlglot.expressions.Select</a></span>,</span><span class="param"> <span class="n">branch_id</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>,</span><span class="param"> <span class="n">sequence_id</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>,</span><span class="param"> <span class="n">last_op</span><span class="p">:</span> <span class="n">sqlglot</span><span class="o">.</span><span class="n">dataframe</span><span class="o">.</span><span class="n">sql</span><span class="o">.</span><span class="n">operations</span><span class="o">.</span><span class="n">Operation</span> <span class="o">=</span> <span class="o">&lt;</span><span class="n">Operation</span><span class="o">.</span><span class="n">INIT</span><span class="p">:</span> <span class="o">-</span><span class="mi">1</span><span class="o">&gt;</span>,</span><span class="param"> <span class="n">pending_hints</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="n"><a href="../expressions.html#Expression">sqlglot.expressions.Expression</a></span><span class="p">]]</span> <span class="o">=</span> <span class="kc">None</span>,</span><span class="param"> <span class="n">output_expression_container</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218892149776&#39;</span><span class="o">&gt;</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>,</span><span class="param"> <span class="o">**</span><span class="n">kwargs</span></span>)</span>
<label class="view-source-button" for="DataFrame.__init__-view-source"><span>View Source</span></label> <label class="view-source-button" for="DataFrame.__init__-view-source"><span>View Source</span></label>
@ -2611,7 +2611,7 @@ is unlikely to come up.</p>
<div class="decorator">@operation(Operation.FROM)</div> <div class="decorator">@operation(Operation.FROM)</div>
<span class="def">def</span> <span class="def">def</span>
<span class="name">fillna</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">self</span>,</span><span class="param"> <span class="n">value</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539400523248&#39;</span><span class="o">&gt;</span>,</span><span class="param"> <span class="n">subset</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Tuple</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="o">...</span><span class="p">],</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">],</span> <span class="n">NoneType</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span></span><span class="return-annotation">) -> <span class="n"><a href="#DataFrame">sqlglot.dataframe.sql.DataFrame</a></span>:</span></span> <span class="name">fillna</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">self</span>,</span><span class="param"> <span class="n">value</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218887508256&#39;</span><span class="o">&gt;</span>,</span><span class="param"> <span class="n">subset</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Tuple</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="o">...</span><span class="p">],</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">],</span> <span class="n">NoneType</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span></span><span class="return-annotation">) -> <span class="n"><a href="#DataFrame">sqlglot.dataframe.sql.DataFrame</a></span>:</span></span>
<label class="view-source-button" for="DataFrame.fillna-view-source"><span>View Source</span></label> <label class="view-source-button" for="DataFrame.fillna-view-source"><span>View Source</span></label>
@ -2680,7 +2680,7 @@ and check if it matches the type of the value provided. If not then make it null
<div class="decorator">@operation(Operation.FROM)</div> <div class="decorator">@operation(Operation.FROM)</div>
<span class="def">def</span> <span class="def">def</span>
<span class="name">replace</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">self</span>,</span><span class="param"> <span class="n">to_replace</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="nb">bool</span><span class="p">,</span> <span class="nb">int</span><span class="p">,</span> <span class="nb">float</span><span class="p">,</span> <span class="nb">str</span><span class="p">,</span> <span class="n">List</span><span class="p">,</span> <span class="n">Dict</span><span class="p">]</span>,</span><span class="param"> <span class="n">value</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="nb">bool</span><span class="p">,</span> <span class="nb">int</span><span class="p">,</span> <span class="nb">float</span><span class="p">,</span> <span class="nb">str</span><span class="p">,</span> <span class="n">List</span><span class="p">,</span> <span class="n">NoneType</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>,</span><span class="param"> <span class="n">subset</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="n">Collection</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539400461696&#39;</span><span class="o">&gt;</span><span class="p">],</span> <span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539400461696&#39;</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">NoneType</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span></span><span class="return-annotation">) -> <span class="n"><a href="#DataFrame">sqlglot.dataframe.sql.DataFrame</a></span>:</span></span> <span class="name">replace</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">self</span>,</span><span class="param"> <span class="n">to_replace</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="nb">bool</span><span class="p">,</span> <span class="nb">int</span><span class="p">,</span> <span class="nb">float</span><span class="p">,</span> <span class="nb">str</span><span class="p">,</span> <span class="n">List</span><span class="p">,</span> <span class="n">Dict</span><span class="p">]</span>,</span><span class="param"> <span class="n">value</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="nb">bool</span><span class="p">,</span> <span class="nb">int</span><span class="p">,</span> <span class="nb">float</span><span class="p">,</span> <span class="nb">str</span><span class="p">,</span> <span class="n">List</span><span class="p">,</span> <span class="n">NoneType</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>,</span><span class="param"> <span class="n">subset</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="n">Collection</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218888263072&#39;</span><span class="o">&gt;</span><span class="p">],</span> <span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218888263072&#39;</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">NoneType</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span></span><span class="return-annotation">) -> <span class="n"><a href="#DataFrame">sqlglot.dataframe.sql.DataFrame</a></span>:</span></span>
<label class="view-source-button" for="DataFrame.replace-view-source"><span>View Source</span></label> <label class="view-source-button" for="DataFrame.replace-view-source"><span>View Source</span></label>
@ -2885,7 +2885,7 @@ and check if it matches the type of the value provided. If not then make it null
<div class="decorator">@operation(Operation.NO_OP)</div> <div class="decorator">@operation(Operation.NO_OP)</div>
<span class="def">def</span> <span class="def">def</span>
<span class="name">repartition</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">self</span>,</span><span class="param"> <span class="n">numPartitions</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539400857312&#39;</span><span class="o">&gt;</span><span class="p">]</span>,</span><span class="param"> <span class="o">*</span><span class="n">cols</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539401003136&#39;</span><span class="o">&gt;</span></span><span class="return-annotation">) -> <span class="n"><a href="#DataFrame">sqlglot.dataframe.sql.DataFrame</a></span>:</span></span> <span class="name">repartition</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">self</span>,</span><span class="param"> <span class="n">numPartitions</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218888300544&#39;</span><span class="o">&gt;</span><span class="p">]</span>,</span><span class="param"> <span class="o">*</span><span class="n">cols</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218888427680&#39;</span><span class="o">&gt;</span></span><span class="return-annotation">) -> <span class="n"><a href="#DataFrame">sqlglot.dataframe.sql.DataFrame</a></span>:</span></span>
<label class="view-source-button" for="DataFrame.repartition-view-source"><span>View Source</span></label> <label class="view-source-button" for="DataFrame.repartition-view-source"><span>View Source</span></label>
@ -3590,7 +3590,7 @@ and check if it matches the type of the value provided. If not then make it null
<input id="Column.__init__-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1"> <input id="Column.__init__-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
<div class="attr function"> <div class="attr function">
<span class="name">Column</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="n">expression</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539402936640&#39;</span><span class="o">&gt;</span><span class="p">,</span> <span class="n"><a href="../expressions.html#Expression">sqlglot.expressions.Expression</a></span><span class="p">,</span> <span class="n">NoneType</span><span class="p">]</span></span>)</span> <span class="name">Column</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="n">expression</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218890254464&#39;</span><span class="o">&gt;</span><span class="p">,</span> <span class="n"><a href="../expressions.html#Expression">sqlglot.expressions.Expression</a></span><span class="p">,</span> <span class="n">NoneType</span><span class="p">]</span></span>)</span>
<label class="view-source-button" for="Column.__init__-view-source"><span>View Source</span></label> <label class="view-source-button" for="Column.__init__-view-source"><span>View Source</span></label>
@ -3633,7 +3633,7 @@ and check if it matches the type of the value provided. If not then make it null
<div class="decorator">@classmethod</div> <div class="decorator">@classmethod</div>
<span class="def">def</span> <span class="def">def</span>
<span class="name">ensure_col</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">cls</span>,</span><span class="param"> <span class="n">value</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539401082464&#39;</span><span class="o">&gt;</span><span class="p">,</span> <span class="n"><a href="../expressions.html#Expression">sqlglot.expressions.Expression</a></span><span class="p">,</span> <span class="n">NoneType</span><span class="p">]</span></span><span class="return-annotation">) -> <span class="n"><a href="#Column">sqlglot.dataframe.sql.Column</a></span>:</span></span> <span class="name">ensure_col</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">cls</span>,</span><span class="param"> <span class="n">value</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218886656432&#39;</span><span class="o">&gt;</span><span class="p">,</span> <span class="n"><a href="../expressions.html#Expression">sqlglot.expressions.Expression</a></span><span class="p">,</span> <span class="n">NoneType</span><span class="p">]</span></span><span class="return-annotation">) -> <span class="n"><a href="#Column">sqlglot.dataframe.sql.Column</a></span>:</span></span>
<label class="view-source-button" for="Column.ensure_col-view-source"><span>View Source</span></label> <label class="view-source-button" for="Column.ensure_col-view-source"><span>View Source</span></label>
@ -3654,7 +3654,7 @@ and check if it matches the type of the value provided. If not then make it null
<div class="decorator">@classmethod</div> <div class="decorator">@classmethod</div>
<span class="def">def</span> <span class="def">def</span>
<span class="name">ensure_cols</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">cls</span>,</span><span class="param"> <span class="n">args</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Union</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539401020528&#39;</span><span class="o">&gt;</span><span class="p">,</span> <span class="n"><a href="../expressions.html#Expression">sqlglot.expressions.Expression</a></span><span class="p">]]</span></span><span class="return-annotation">) -> <span class="n">List</span><span class="p">[</span><span class="n"><a href="#Column">sqlglot.dataframe.sql.Column</a></span><span class="p">]</span>:</span></span> <span class="name">ensure_cols</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">cls</span>,</span><span class="param"> <span class="n">args</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Union</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218886827520&#39;</span><span class="o">&gt;</span><span class="p">,</span> <span class="n"><a href="../expressions.html#Expression">sqlglot.expressions.Expression</a></span><span class="p">]]</span></span><span class="return-annotation">) -> <span class="n">List</span><span class="p">[</span><span class="n"><a href="#Column">sqlglot.dataframe.sql.Column</a></span><span class="p">]</span>:</span></span>
<label class="view-source-button" for="Column.ensure_cols-view-source"><span>View Source</span></label> <label class="view-source-button" for="Column.ensure_cols-view-source"><span>View Source</span></label>
@ -3675,7 +3675,7 @@ and check if it matches the type of the value provided. If not then make it null
<div class="decorator">@classmethod</div> <div class="decorator">@classmethod</div>
<span class="def">def</span> <span class="def">def</span>
<span class="name">invoke_anonymous_function</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">cls</span>,</span><span class="param"> <span class="n">column</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539401141168&#39;</span><span class="o">&gt;</span><span class="p">]</span>,</span><span class="param"> <span class="n">func_name</span><span class="p">:</span> <span class="nb">str</span>,</span><span class="param"> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539401263168&#39;</span><span class="o">&gt;</span><span class="p">]</span></span><span class="return-annotation">) -> <span class="n"><a href="#Column">sqlglot.dataframe.sql.Column</a></span>:</span></span> <span class="name">invoke_anonymous_function</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">cls</span>,</span><span class="param"> <span class="n">column</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218886534096&#39;</span><span class="o">&gt;</span><span class="p">]</span>,</span><span class="param"> <span class="n">func_name</span><span class="p">:</span> <span class="nb">str</span>,</span><span class="param"> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218886435168&#39;</span><span class="o">&gt;</span><span class="p">]</span></span><span class="return-annotation">) -> <span class="n"><a href="#Column">sqlglot.dataframe.sql.Column</a></span>:</span></span>
<label class="view-source-button" for="Column.invoke_anonymous_function-view-source"><span>View Source</span></label> <label class="view-source-button" for="Column.invoke_anonymous_function-view-source"><span>View Source</span></label>
@ -3702,7 +3702,7 @@ and check if it matches the type of the value provided. If not then make it null
<div class="decorator">@classmethod</div> <div class="decorator">@classmethod</div>
<span class="def">def</span> <span class="def">def</span>
<span class="name">invoke_expression_over_column</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">cls</span>,</span><span class="param"> <span class="n">column</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539399493696&#39;</span><span class="o">&gt;</span><span class="p">]</span>,</span><span class="param"> <span class="n">callable_expression</span><span class="p">:</span> <span class="n">Callable</span>,</span><span class="param"> <span class="o">**</span><span class="n">kwargs</span></span><span class="return-annotation">) -> <span class="n"><a href="#Column">sqlglot.dataframe.sql.Column</a></span>:</span></span> <span class="name">invoke_expression_over_column</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">cls</span>,</span><span class="param"> <span class="n">column</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218886411056&#39;</span><span class="o">&gt;</span><span class="p">]</span>,</span><span class="param"> <span class="n">callable_expression</span><span class="p">:</span> <span class="n">Callable</span>,</span><span class="param"> <span class="o">**</span><span class="n">kwargs</span></span><span class="return-annotation">) -> <span class="n"><a href="#Column">sqlglot.dataframe.sql.Column</a></span>:</span></span>
<label class="view-source-button" for="Column.invoke_expression_over_column-view-source"><span>View Source</span></label> <label class="view-source-button" for="Column.invoke_expression_over_column-view-source"><span>View Source</span></label>
@ -3739,7 +3739,7 @@ and check if it matches the type of the value provided. If not then make it null
<div class="attr function"> <div class="attr function">
<span class="def">def</span> <span class="def">def</span>
<span class="name">binary_op</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">self</span>,</span><span class="param"> <span class="n">klass</span><span class="p">:</span> <span class="n">Callable</span>,</span><span class="param"> <span class="n">other</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539399386160&#39;</span><span class="o">&gt;</span>,</span><span class="param"> <span class="o">**</span><span class="n">kwargs</span></span><span class="return-annotation">) -> <span class="n"><a href="#Column">sqlglot.dataframe.sql.Column</a></span>:</span></span> <span class="name">binary_op</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">self</span>,</span><span class="param"> <span class="n">klass</span><span class="p">:</span> <span class="n">Callable</span>,</span><span class="param"> <span class="n">other</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218886368864&#39;</span><span class="o">&gt;</span>,</span><span class="param"> <span class="o">**</span><span class="n">kwargs</span></span><span class="return-annotation">) -> <span class="n"><a href="#Column">sqlglot.dataframe.sql.Column</a></span>:</span></span>
<label class="view-source-button" for="Column.binary_op-view-source"><span>View Source</span></label> <label class="view-source-button" for="Column.binary_op-view-source"><span>View Source</span></label>
@ -3760,7 +3760,7 @@ and check if it matches the type of the value provided. If not then make it null
<div class="attr function"> <div class="attr function">
<span class="def">def</span> <span class="def">def</span>
<span class="name">inverse_binary_op</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">self</span>,</span><span class="param"> <span class="n">klass</span><span class="p">:</span> <span class="n">Callable</span>,</span><span class="param"> <span class="n">other</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539399414416&#39;</span><span class="o">&gt;</span>,</span><span class="param"> <span class="o">**</span><span class="n">kwargs</span></span><span class="return-annotation">) -> <span class="n"><a href="#Column">sqlglot.dataframe.sql.Column</a></span>:</span></span> <span class="name">inverse_binary_op</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">self</span>,</span><span class="param"> <span class="n">klass</span><span class="p">:</span> <span class="n">Callable</span>,</span><span class="param"> <span class="n">other</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218886724272&#39;</span><span class="o">&gt;</span>,</span><span class="param"> <span class="o">**</span><span class="n">kwargs</span></span><span class="return-annotation">) -> <span class="n"><a href="#Column">sqlglot.dataframe.sql.Column</a></span>:</span></span>
<label class="view-source-button" for="Column.inverse_binary_op-view-source"><span>View Source</span></label> <label class="view-source-button" for="Column.inverse_binary_op-view-source"><span>View Source</span></label>
@ -4314,7 +4314,7 @@ Sqlglot doesn't currently replicate this class so it only accepts a string</p>
<div class="attr function"> <div class="attr function">
<span class="def">def</span> <span class="def">def</span>
<span class="name">isin</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">self</span>,</span><span class="param"> <span class="o">*</span><span class="n">cols</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539399635728&#39;</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">Iterable</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539399635728&#39;</span><span class="o">&gt;</span><span class="p">]]</span></span><span class="return-annotation">):</span></span> <span class="name">isin</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">self</span>,</span><span class="param"> <span class="o">*</span><span class="n">cols</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218886946048&#39;</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">Iterable</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218886946048&#39;</span><span class="o">&gt;</span><span class="p">]]</span></span><span class="return-annotation">):</span></span>
<label class="view-source-button" for="Column.isin-view-source"><span>View Source</span></label> <label class="view-source-button" for="Column.isin-view-source"><span>View Source</span></label>
@ -4335,7 +4335,7 @@ Sqlglot doesn't currently replicate this class so it only accepts a string</p>
<div class="attr function"> <div class="attr function">
<span class="def">def</span> <span class="def">def</span>
<span class="name">between</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">self</span>,</span><span class="param"> <span class="n">lowerBound</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539399680064&#39;</span><span class="o">&gt;</span>,</span><span class="param"> <span class="n">upperBound</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539399772416&#39;</span><span class="o">&gt;</span></span><span class="return-annotation">) -> <span class="n"><a href="#Column">sqlglot.dataframe.sql.Column</a></span>:</span></span> <span class="name">between</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">self</span>,</span><span class="param"> <span class="n">lowerBound</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218887044112&#39;</span><span class="o">&gt;</span>,</span><span class="param"> <span class="n">upperBound</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218887115040&#39;</span><span class="o">&gt;</span></span><span class="return-annotation">) -> <span class="n"><a href="#Column">sqlglot.dataframe.sql.Column</a></span>:</span></span>
<label class="view-source-button" for="Column.between-view-source"><span>View Source</span></label> <label class="view-source-button" for="Column.between-view-source"><span>View Source</span></label>
@ -4370,7 +4370,7 @@ Sqlglot doesn't currently replicate this class so it only accepts a string</p>
<div class="attr function"> <div class="attr function">
<span class="def">def</span> <span class="def">def</span>
<span class="name">over</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">self</span>,</span><span class="param"> <span class="n">window</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539399831664&#39;</span><span class="o">&gt;</span></span><span class="return-annotation">) -> <span class="n"><a href="#Column">sqlglot.dataframe.sql.Column</a></span>:</span></span> <span class="name">over</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">self</span>,</span><span class="param"> <span class="n">window</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218887156256&#39;</span><span class="o">&gt;</span></span><span class="return-annotation">) -> <span class="n"><a href="#Column">sqlglot.dataframe.sql.Column</a></span>:</span></span>
<label class="view-source-button" for="Column.over-view-source"><span>View Source</span></label> <label class="view-source-button" for="Column.over-view-source"><span>View Source</span></label>
@ -4615,7 +4615,7 @@ Sqlglot doesn't currently replicate this class so it only accepts a string</p>
<div class="decorator">@classmethod</div> <div class="decorator">@classmethod</div>
<span class="def">def</span> <span class="def">def</span>
<span class="name">partitionBy</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">cls</span>,</span><span class="param"> <span class="o">*</span><span class="n">cols</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539400316976&#39;</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">List</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539400316976&#39;</span><span class="o">&gt;</span><span class="p">]]</span></span><span class="return-annotation">) -> <span class="n"><a href="#WindowSpec">sqlglot.dataframe.sql.WindowSpec</a></span>:</span></span> <span class="name">partitionBy</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">cls</span>,</span><span class="param"> <span class="o">*</span><span class="n">cols</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218887300736&#39;</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">List</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218887300736&#39;</span><span class="o">&gt;</span><span class="p">]]</span></span><span class="return-annotation">) -> <span class="n"><a href="#WindowSpec">sqlglot.dataframe.sql.WindowSpec</a></span>:</span></span>
<label class="view-source-button" for="Window.partitionBy-view-source"><span>View Source</span></label> <label class="view-source-button" for="Window.partitionBy-view-source"><span>View Source</span></label>
@ -4636,7 +4636,7 @@ Sqlglot doesn't currently replicate this class so it only accepts a string</p>
<div class="decorator">@classmethod</div> <div class="decorator">@classmethod</div>
<span class="def">def</span> <span class="def">def</span>
<span class="name">orderBy</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">cls</span>,</span><span class="param"> <span class="o">*</span><span class="n">cols</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539400303328&#39;</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">List</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539400303328&#39;</span><span class="o">&gt;</span><span class="p">]]</span></span><span class="return-annotation">) -> <span class="n"><a href="#WindowSpec">sqlglot.dataframe.sql.WindowSpec</a></span>:</span></span> <span class="name">orderBy</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">cls</span>,</span><span class="param"> <span class="o">*</span><span class="n">cols</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218887344320&#39;</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">List</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218887344320&#39;</span><span class="o">&gt;</span><span class="p">]]</span></span><span class="return-annotation">) -> <span class="n"><a href="#WindowSpec">sqlglot.dataframe.sql.WindowSpec</a></span>:</span></span>
<label class="view-source-button" for="Window.orderBy-view-source"><span>View Source</span></label> <label class="view-source-button" for="Window.orderBy-view-source"><span>View Source</span></label>
@ -4872,7 +4872,7 @@ Sqlglot doesn't currently replicate this class so it only accepts a string</p>
<div class="attr function"> <div class="attr function">
<span class="def">def</span> <span class="def">def</span>
<span class="name">partitionBy</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">self</span>,</span><span class="param"> <span class="o">*</span><span class="n">cols</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539400150784&#39;</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">List</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539400150784&#39;</span><span class="o">&gt;</span><span class="p">]]</span></span><span class="return-annotation">) -> <span class="n"><a href="#WindowSpec">sqlglot.dataframe.sql.WindowSpec</a></span>:</span></span> <span class="name">partitionBy</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">self</span>,</span><span class="param"> <span class="o">*</span><span class="n">cols</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218886020816&#39;</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">List</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218886020816&#39;</span><span class="o">&gt;</span><span class="p">]]</span></span><span class="return-annotation">) -> <span class="n"><a href="#WindowSpec">sqlglot.dataframe.sql.WindowSpec</a></span>:</span></span>
<label class="view-source-button" for="WindowSpec.partitionBy-view-source"><span>View Source</span></label> <label class="view-source-button" for="WindowSpec.partitionBy-view-source"><span>View Source</span></label>
@ -4899,7 +4899,7 @@ Sqlglot doesn't currently replicate this class so it only accepts a string</p>
<div class="attr function"> <div class="attr function">
<span class="def">def</span> <span class="def">def</span>
<span class="name">orderBy</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">self</span>,</span><span class="param"> <span class="o">*</span><span class="n">cols</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539400013664&#39;</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">List</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140539400013664&#39;</span><span class="o">&gt;</span><span class="p">]]</span></span><span class="return-annotation">) -> <span class="n"><a href="#WindowSpec">sqlglot.dataframe.sql.WindowSpec</a></span>:</span></span> <span class="name">orderBy</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="bp">self</span>,</span><span class="param"> <span class="o">*</span><span class="n">cols</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218886219056&#39;</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">List</span><span class="p">[</span><span class="o">&lt;</span><span class="n">MagicMock</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;140218886219056&#39;</span><span class="o">&gt;</span><span class="p">]]</span></span><span class="return-annotation">) -> <span class="n"><a href="#WindowSpec">sqlglot.dataframe.sql.WindowSpec</a></span>:</span></span>
<label class="view-source-button" for="WindowSpec.orderBy-view-source"><span>View Source</span></label> <label class="view-source-button" for="WindowSpec.orderBy-view-source"><span>View Source</span></label>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -761,6 +761,7 @@ For example, a generic mapping type might be defined as::</p>
<dd id="Tables.mapping" class="variable"><a href="../schema.html#AbstractMappingSchema.mapping">mapping</a></dd> <dd id="Tables.mapping" class="variable"><a href="../schema.html#AbstractMappingSchema.mapping">mapping</a></dd>
<dd id="Tables.mapping_trie" class="variable"><a href="../schema.html#AbstractMappingSchema.mapping_trie">mapping_trie</a></dd> <dd id="Tables.mapping_trie" class="variable"><a href="../schema.html#AbstractMappingSchema.mapping_trie">mapping_trie</a></dd>
<dd id="Tables.empty" class="variable"><a href="../schema.html#AbstractMappingSchema.empty">empty</a></dd> <dd id="Tables.empty" class="variable"><a href="../schema.html#AbstractMappingSchema.empty">empty</a></dd>
<dd id="Tables.depth" class="function"><a href="../schema.html#AbstractMappingSchema.depth">depth</a></dd>
<dd id="Tables.supported_table_args" class="variable"><a href="../schema.html#AbstractMappingSchema.supported_table_args">supported_table_args</a></dd> <dd id="Tables.supported_table_args" class="variable"><a href="../schema.html#AbstractMappingSchema.supported_table_args">supported_table_args</a></dd>
<dd id="Tables.table_parts" class="function"><a href="../schema.html#AbstractMappingSchema.table_parts">table_parts</a></dd> <dd id="Tables.table_parts" class="function"><a href="../schema.html#AbstractMappingSchema.table_parts">table_parts</a></dd>
<dd id="Tables.find" class="function"><a href="../schema.html#AbstractMappingSchema.find">find</a></dd> <dd id="Tables.find" class="function"><a href="../schema.html#AbstractMappingSchema.find">find</a></dd>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -194,69 +194,71 @@
</span><span id="L-136"><a href="#L-136"><span class="linenos">136</span></a> </span><span id="L-136"><a href="#L-136"><span class="linenos">136</span></a>
</span><span id="L-137"><a href="#L-137"><span class="linenos">137</span></a> </span><span id="L-137"><a href="#L-137"><span class="linenos">137</span></a>
</span><span id="L-138"><a href="#L-138"><span class="linenos">138</span></a><span class="k">def</span> <span class="nf">_eliminate_derived_table</span><span class="p">(</span><span class="n">scope</span><span class="p">,</span> <span class="n">existing_ctes</span><span class="p">,</span> <span class="n">taken</span><span class="p">):</span> </span><span id="L-138"><a href="#L-138"><span class="linenos">138</span></a><span class="k">def</span> <span class="nf">_eliminate_derived_table</span><span class="p">(</span><span class="n">scope</span><span class="p">,</span> <span class="n">existing_ctes</span><span class="p">,</span> <span class="n">taken</span><span class="p">):</span>
</span><span id="L-139"><a href="#L-139"><span class="linenos">139</span></a> <span class="c1"># This ensures we don&#39;t drop the &quot;pivot&quot; arg from a pivoted subquery</span> </span><span id="L-139"><a href="#L-139"><span class="linenos">139</span></a> <span class="c1"># This makes sure that we don&#39;t:</span>
</span><span id="L-140"><a href="#L-140"><span class="linenos">140</span></a> <span class="k">if</span> <span class="n">scope</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">pivots</span><span class="p">:</span> </span><span id="L-140"><a href="#L-140"><span class="linenos">140</span></a> <span class="c1"># - drop the &quot;pivot&quot; arg from a pivoted subquery</span>
</span><span id="L-141"><a href="#L-141"><span class="linenos">141</span></a> <span class="k">return</span> <span class="kc">None</span> </span><span id="L-141"><a href="#L-141"><span class="linenos">141</span></a> <span class="c1"># - eliminate a lateral correlated subquery</span>
</span><span id="L-142"><a href="#L-142"><span class="linenos">142</span></a> </span><span id="L-142"><a href="#L-142"><span class="linenos">142</span></a> <span class="k">if</span> <span class="n">scope</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">pivots</span> <span class="ow">or</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">scope</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">expression</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Lateral</span><span class="p">):</span>
</span><span id="L-143"><a href="#L-143"><span class="linenos">143</span></a> <span class="n">parent</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="n">expression</span><span class="o">.</span><span class="n">parent</span> </span><span id="L-143"><a href="#L-143"><span class="linenos">143</span></a> <span class="k">return</span> <span class="kc">None</span>
</span><span id="L-144"><a href="#L-144"><span class="linenos">144</span></a> <span class="n">name</span><span class="p">,</span> <span class="n">cte</span> <span class="o">=</span> <span class="n">_new_cte</span><span class="p">(</span><span class="n">scope</span><span class="p">,</span> <span class="n">existing_ctes</span><span class="p">,</span> <span class="n">taken</span><span class="p">)</span> </span><span id="L-144"><a href="#L-144"><span class="linenos">144</span></a>
</span><span id="L-145"><a href="#L-145"><span class="linenos">145</span></a> </span><span id="L-145"><a href="#L-145"><span class="linenos">145</span></a> <span class="n">parent</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="n">expression</span><span class="o">.</span><span class="n">parent</span>
</span><span id="L-146"><a href="#L-146"><span class="linenos">146</span></a> <span class="n">table</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">alias_</span><span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">table_</span><span class="p">(</span><span class="n">name</span><span class="p">),</span> <span class="n">alias</span><span class="o">=</span><span class="n">parent</span><span class="o">.</span><span class="n">alias</span> <span class="ow">or</span> <span class="n">name</span><span class="p">)</span> </span><span id="L-146"><a href="#L-146"><span class="linenos">146</span></a> <span class="n">name</span><span class="p">,</span> <span class="n">cte</span> <span class="o">=</span> <span class="n">_new_cte</span><span class="p">(</span><span class="n">scope</span><span class="p">,</span> <span class="n">existing_ctes</span><span class="p">,</span> <span class="n">taken</span><span class="p">)</span>
</span><span id="L-147"><a href="#L-147"><span class="linenos">147</span></a> <span class="n">table</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;joins&quot;</span><span class="p">,</span> <span class="n">parent</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;joins&quot;</span><span class="p">))</span> </span><span id="L-147"><a href="#L-147"><span class="linenos">147</span></a>
</span><span id="L-148"><a href="#L-148"><span class="linenos">148</span></a> </span><span id="L-148"><a href="#L-148"><span class="linenos">148</span></a> <span class="n">table</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">alias_</span><span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">table_</span><span class="p">(</span><span class="n">name</span><span class="p">),</span> <span class="n">alias</span><span class="o">=</span><span class="n">parent</span><span class="o">.</span><span class="n">alias</span> <span class="ow">or</span> <span class="n">name</span><span class="p">)</span>
</span><span id="L-149"><a href="#L-149"><span class="linenos">149</span></a> <span class="n">parent</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">table</span><span class="p">)</span> </span><span id="L-149"><a href="#L-149"><span class="linenos">149</span></a> <span class="n">table</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;joins&quot;</span><span class="p">,</span> <span class="n">parent</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;joins&quot;</span><span class="p">))</span>
</span><span id="L-150"><a href="#L-150"><span class="linenos">150</span></a> <span class="k">return</span> <span class="n">cte</span> </span><span id="L-150"><a href="#L-150"><span class="linenos">150</span></a>
</span><span id="L-151"><a href="#L-151"><span class="linenos">151</span></a> </span><span id="L-151"><a href="#L-151"><span class="linenos">151</span></a> <span class="n">parent</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">table</span><span class="p">)</span>
</span><span id="L-152"><a href="#L-152"><span class="linenos">152</span></a> </span><span id="L-152"><a href="#L-152"><span class="linenos">152</span></a> <span class="k">return</span> <span class="n">cte</span>
</span><span id="L-153"><a href="#L-153"><span class="linenos">153</span></a><span class="k">def</span> <span class="nf">_eliminate_cte</span><span class="p">(</span><span class="n">scope</span><span class="p">,</span> <span class="n">existing_ctes</span><span class="p">,</span> <span class="n">taken</span><span class="p">):</span> </span><span id="L-153"><a href="#L-153"><span class="linenos">153</span></a>
</span><span id="L-154"><a href="#L-154"><span class="linenos">154</span></a> <span class="n">parent</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="n">expression</span><span class="o">.</span><span class="n">parent</span> </span><span id="L-154"><a href="#L-154"><span class="linenos">154</span></a>
</span><span id="L-155"><a href="#L-155"><span class="linenos">155</span></a> <span class="n">name</span><span class="p">,</span> <span class="n">cte</span> <span class="o">=</span> <span class="n">_new_cte</span><span class="p">(</span><span class="n">scope</span><span class="p">,</span> <span class="n">existing_ctes</span><span class="p">,</span> <span class="n">taken</span><span class="p">)</span> </span><span id="L-155"><a href="#L-155"><span class="linenos">155</span></a><span class="k">def</span> <span class="nf">_eliminate_cte</span><span class="p">(</span><span class="n">scope</span><span class="p">,</span> <span class="n">existing_ctes</span><span class="p">,</span> <span class="n">taken</span><span class="p">):</span>
</span><span id="L-156"><a href="#L-156"><span class="linenos">156</span></a> </span><span id="L-156"><a href="#L-156"><span class="linenos">156</span></a> <span class="n">parent</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="n">expression</span><span class="o">.</span><span class="n">parent</span>
</span><span id="L-157"><a href="#L-157"><span class="linenos">157</span></a> <span class="n">with_</span> <span class="o">=</span> <span class="n">parent</span><span class="o">.</span><span class="n">parent</span> </span><span id="L-157"><a href="#L-157"><span class="linenos">157</span></a> <span class="n">name</span><span class="p">,</span> <span class="n">cte</span> <span class="o">=</span> <span class="n">_new_cte</span><span class="p">(</span><span class="n">scope</span><span class="p">,</span> <span class="n">existing_ctes</span><span class="p">,</span> <span class="n">taken</span><span class="p">)</span>
</span><span id="L-158"><a href="#L-158"><span class="linenos">158</span></a> <span class="n">parent</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span> </span><span id="L-158"><a href="#L-158"><span class="linenos">158</span></a>
</span><span id="L-159"><a href="#L-159"><span class="linenos">159</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">with_</span><span class="o">.</span><span class="n">expressions</span><span class="p">:</span> </span><span id="L-159"><a href="#L-159"><span class="linenos">159</span></a> <span class="n">with_</span> <span class="o">=</span> <span class="n">parent</span><span class="o">.</span><span class="n">parent</span>
</span><span id="L-160"><a href="#L-160"><span class="linenos">160</span></a> <span class="n">with_</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span> </span><span id="L-160"><a href="#L-160"><span class="linenos">160</span></a> <span class="n">parent</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
</span><span id="L-161"><a href="#L-161"><span class="linenos">161</span></a> </span><span id="L-161"><a href="#L-161"><span class="linenos">161</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">with_</span><span class="o">.</span><span class="n">expressions</span><span class="p">:</span>
</span><span id="L-162"><a href="#L-162"><span class="linenos">162</span></a> <span class="c1"># Rename references to this CTE</span> </span><span id="L-162"><a href="#L-162"><span class="linenos">162</span></a> <span class="n">with_</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
</span><span id="L-163"><a href="#L-163"><span class="linenos">163</span></a> <span class="k">for</span> <span class="n">child_scope</span> <span class="ow">in</span> <span class="n">scope</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">traverse</span><span class="p">():</span> </span><span id="L-163"><a href="#L-163"><span class="linenos">163</span></a>
</span><span id="L-164"><a href="#L-164"><span class="linenos">164</span></a> <span class="k">for</span> <span class="n">table</span><span class="p">,</span> <span class="n">source</span> <span class="ow">in</span> <span class="n">child_scope</span><span class="o">.</span><span class="n">selected_sources</span><span class="o">.</span><span class="n">values</span><span class="p">():</span> </span><span id="L-164"><a href="#L-164"><span class="linenos">164</span></a> <span class="c1"># Rename references to this CTE</span>
</span><span id="L-165"><a href="#L-165"><span class="linenos">165</span></a> <span class="k">if</span> <span class="n">source</span> <span class="ow">is</span> <span class="n">scope</span><span class="p">:</span> </span><span id="L-165"><a href="#L-165"><span class="linenos">165</span></a> <span class="k">for</span> <span class="n">child_scope</span> <span class="ow">in</span> <span class="n">scope</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">traverse</span><span class="p">():</span>
</span><span id="L-166"><a href="#L-166"><span class="linenos">166</span></a> <span class="n">new_table</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">alias_</span><span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">table_</span><span class="p">(</span><span class="n">name</span><span class="p">),</span> <span class="n">alias</span><span class="o">=</span><span class="n">table</span><span class="o">.</span><span class="n">alias_or_name</span><span class="p">,</span> <span class="n">copy</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span> </span><span id="L-166"><a href="#L-166"><span class="linenos">166</span></a> <span class="k">for</span> <span class="n">table</span><span class="p">,</span> <span class="n">source</span> <span class="ow">in</span> <span class="n">child_scope</span><span class="o">.</span><span class="n">selected_sources</span><span class="o">.</span><span class="n">values</span><span class="p">():</span>
</span><span id="L-167"><a href="#L-167"><span class="linenos">167</span></a> <span class="n">table</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">new_table</span><span class="p">)</span> </span><span id="L-167"><a href="#L-167"><span class="linenos">167</span></a> <span class="k">if</span> <span class="n">source</span> <span class="ow">is</span> <span class="n">scope</span><span class="p">:</span>
</span><span id="L-168"><a href="#L-168"><span class="linenos">168</span></a> </span><span id="L-168"><a href="#L-168"><span class="linenos">168</span></a> <span class="n">new_table</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">alias_</span><span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">table_</span><span class="p">(</span><span class="n">name</span><span class="p">),</span> <span class="n">alias</span><span class="o">=</span><span class="n">table</span><span class="o">.</span><span class="n">alias_or_name</span><span class="p">,</span> <span class="n">copy</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
</span><span id="L-169"><a href="#L-169"><span class="linenos">169</span></a> <span class="k">return</span> <span class="n">cte</span> </span><span id="L-169"><a href="#L-169"><span class="linenos">169</span></a> <span class="n">table</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">new_table</span><span class="p">)</span>
</span><span id="L-170"><a href="#L-170"><span class="linenos">170</span></a> </span><span id="L-170"><a href="#L-170"><span class="linenos">170</span></a>
</span><span id="L-171"><a href="#L-171"><span class="linenos">171</span></a> </span><span id="L-171"><a href="#L-171"><span class="linenos">171</span></a> <span class="k">return</span> <span class="n">cte</span>
</span><span id="L-172"><a href="#L-172"><span class="linenos">172</span></a><span class="k">def</span> <span class="nf">_new_cte</span><span class="p">(</span><span class="n">scope</span><span class="p">,</span> <span class="n">existing_ctes</span><span class="p">,</span> <span class="n">taken</span><span class="p">):</span> </span><span id="L-172"><a href="#L-172"><span class="linenos">172</span></a>
</span><span id="L-173"><a href="#L-173"><span class="linenos">173</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span> </span><span id="L-173"><a href="#L-173"><span class="linenos">173</span></a>
</span><span id="L-174"><a href="#L-174"><span class="linenos">174</span></a><span class="sd"> Returns:</span> </span><span id="L-174"><a href="#L-174"><span class="linenos">174</span></a><span class="k">def</span> <span class="nf">_new_cte</span><span class="p">(</span><span class="n">scope</span><span class="p">,</span> <span class="n">existing_ctes</span><span class="p">,</span> <span class="n">taken</span><span class="p">):</span>
</span><span id="L-175"><a href="#L-175"><span class="linenos">175</span></a><span class="sd"> tuple of (name, cte)</span> </span><span id="L-175"><a href="#L-175"><span class="linenos">175</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-176"><a href="#L-176"><span class="linenos">176</span></a><span class="sd"> where `name` is a new name for this CTE in the root scope and `cte` is a new CTE instance.</span> </span><span id="L-176"><a href="#L-176"><span class="linenos">176</span></a><span class="sd"> Returns:</span>
</span><span id="L-177"><a href="#L-177"><span class="linenos">177</span></a><span class="sd"> If this CTE duplicates an existing CTE, `cte` will be None.</span> </span><span id="L-177"><a href="#L-177"><span class="linenos">177</span></a><span class="sd"> tuple of (name, cte)</span>
</span><span id="L-178"><a href="#L-178"><span class="linenos">178</span></a><span class="sd"> &quot;&quot;&quot;</span> </span><span id="L-178"><a href="#L-178"><span class="linenos">178</span></a><span class="sd"> where `name` is a new name for this CTE in the root scope and `cte` is a new CTE instance.</span>
</span><span id="L-179"><a href="#L-179"><span class="linenos">179</span></a> <span class="n">duplicate_cte_alias</span> <span class="o">=</span> <span class="n">existing_ctes</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">scope</span><span class="o">.</span><span class="n">expression</span><span class="p">)</span> </span><span id="L-179"><a href="#L-179"><span class="linenos">179</span></a><span class="sd"> If this CTE duplicates an existing CTE, `cte` will be None.</span>
</span><span id="L-180"><a href="#L-180"><span class="linenos">180</span></a> <span class="n">parent</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="n">expression</span><span class="o">.</span><span class="n">parent</span> </span><span id="L-180"><a href="#L-180"><span class="linenos">180</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-181"><a href="#L-181"><span class="linenos">181</span></a> <span class="n">name</span> <span class="o">=</span> <span class="n">parent</span><span class="o">.</span><span class="n">alias</span> </span><span id="L-181"><a href="#L-181"><span class="linenos">181</span></a> <span class="n">duplicate_cte_alias</span> <span class="o">=</span> <span class="n">existing_ctes</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">scope</span><span class="o">.</span><span class="n">expression</span><span class="p">)</span>
</span><span id="L-182"><a href="#L-182"><span class="linenos">182</span></a> </span><span id="L-182"><a href="#L-182"><span class="linenos">182</span></a> <span class="n">parent</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="n">expression</span><span class="o">.</span><span class="n">parent</span>
</span><span id="L-183"><a href="#L-183"><span class="linenos">183</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">name</span><span class="p">:</span> </span><span id="L-183"><a href="#L-183"><span class="linenos">183</span></a> <span class="n">name</span> <span class="o">=</span> <span class="n">parent</span><span class="o">.</span><span class="n">alias</span>
</span><span id="L-184"><a href="#L-184"><span class="linenos">184</span></a> <span class="n">name</span> <span class="o">=</span> <span class="n">find_new_name</span><span class="p">(</span><span class="n">taken</span><span class="o">=</span><span class="n">taken</span><span class="p">,</span> <span class="n">base</span><span class="o">=</span><span class="s2">&quot;cte&quot;</span><span class="p">)</span> </span><span id="L-184"><a href="#L-184"><span class="linenos">184</span></a>
</span><span id="L-185"><a href="#L-185"><span class="linenos">185</span></a> </span><span id="L-185"><a href="#L-185"><span class="linenos">185</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">name</span><span class="p">:</span>
</span><span id="L-186"><a href="#L-186"><span class="linenos">186</span></a> <span class="k">if</span> <span class="n">duplicate_cte_alias</span><span class="p">:</span> </span><span id="L-186"><a href="#L-186"><span class="linenos">186</span></a> <span class="n">name</span> <span class="o">=</span> <span class="n">find_new_name</span><span class="p">(</span><span class="n">taken</span><span class="o">=</span><span class="n">taken</span><span class="p">,</span> <span class="n">base</span><span class="o">=</span><span class="s2">&quot;cte&quot;</span><span class="p">)</span>
</span><span id="L-187"><a href="#L-187"><span class="linenos">187</span></a> <span class="n">name</span> <span class="o">=</span> <span class="n">duplicate_cte_alias</span> </span><span id="L-187"><a href="#L-187"><span class="linenos">187</span></a>
</span><span id="L-188"><a href="#L-188"><span class="linenos">188</span></a> <span class="k">elif</span> <span class="n">taken</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">name</span><span class="p">):</span> </span><span id="L-188"><a href="#L-188"><span class="linenos">188</span></a> <span class="k">if</span> <span class="n">duplicate_cte_alias</span><span class="p">:</span>
</span><span id="L-189"><a href="#L-189"><span class="linenos">189</span></a> <span class="n">name</span> <span class="o">=</span> <span class="n">find_new_name</span><span class="p">(</span><span class="n">taken</span><span class="o">=</span><span class="n">taken</span><span class="p">,</span> <span class="n">base</span><span class="o">=</span><span class="n">name</span><span class="p">)</span> </span><span id="L-189"><a href="#L-189"><span class="linenos">189</span></a> <span class="n">name</span> <span class="o">=</span> <span class="n">duplicate_cte_alias</span>
</span><span id="L-190"><a href="#L-190"><span class="linenos">190</span></a> </span><span id="L-190"><a href="#L-190"><span class="linenos">190</span></a> <span class="k">elif</span> <span class="n">taken</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
</span><span id="L-191"><a href="#L-191"><span class="linenos">191</span></a> <span class="n">taken</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">scope</span> </span><span id="L-191"><a href="#L-191"><span class="linenos">191</span></a> <span class="n">name</span> <span class="o">=</span> <span class="n">find_new_name</span><span class="p">(</span><span class="n">taken</span><span class="o">=</span><span class="n">taken</span><span class="p">,</span> <span class="n">base</span><span class="o">=</span><span class="n">name</span><span class="p">)</span>
</span><span id="L-192"><a href="#L-192"><span class="linenos">192</span></a> </span><span id="L-192"><a href="#L-192"><span class="linenos">192</span></a>
</span><span id="L-193"><a href="#L-193"><span class="linenos">193</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">duplicate_cte_alias</span><span class="p">:</span> </span><span id="L-193"><a href="#L-193"><span class="linenos">193</span></a> <span class="n">taken</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">scope</span>
</span><span id="L-194"><a href="#L-194"><span class="linenos">194</span></a> <span class="n">existing_ctes</span><span class="p">[</span><span class="n">scope</span><span class="o">.</span><span class="n">expression</span><span class="p">]</span> <span class="o">=</span> <span class="n">name</span> </span><span id="L-194"><a href="#L-194"><span class="linenos">194</span></a>
</span><span id="L-195"><a href="#L-195"><span class="linenos">195</span></a> <span class="n">cte</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">CTE</span><span class="p">(</span> </span><span id="L-195"><a href="#L-195"><span class="linenos">195</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">duplicate_cte_alias</span><span class="p">:</span>
</span><span id="L-196"><a href="#L-196"><span class="linenos">196</span></a> <span class="n">this</span><span class="o">=</span><span class="n">scope</span><span class="o">.</span><span class="n">expression</span><span class="p">,</span> </span><span id="L-196"><a href="#L-196"><span class="linenos">196</span></a> <span class="n">existing_ctes</span><span class="p">[</span><span class="n">scope</span><span class="o">.</span><span class="n">expression</span><span class="p">]</span> <span class="o">=</span> <span class="n">name</span>
</span><span id="L-197"><a href="#L-197"><span class="linenos">197</span></a> <span class="n">alias</span><span class="o">=</span><span class="n">exp</span><span class="o">.</span><span class="n">TableAlias</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">name</span><span class="p">)),</span> </span><span id="L-197"><a href="#L-197"><span class="linenos">197</span></a> <span class="n">cte</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">CTE</span><span class="p">(</span>
</span><span id="L-198"><a href="#L-198"><span class="linenos">198</span></a> <span class="p">)</span> </span><span id="L-198"><a href="#L-198"><span class="linenos">198</span></a> <span class="n">this</span><span class="o">=</span><span class="n">scope</span><span class="o">.</span><span class="n">expression</span><span class="p">,</span>
</span><span id="L-199"><a href="#L-199"><span class="linenos">199</span></a> <span class="k">else</span><span class="p">:</span> </span><span id="L-199"><a href="#L-199"><span class="linenos">199</span></a> <span class="n">alias</span><span class="o">=</span><span class="n">exp</span><span class="o">.</span><span class="n">TableAlias</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">name</span><span class="p">)),</span>
</span><span id="L-200"><a href="#L-200"><span class="linenos">200</span></a> <span class="n">cte</span> <span class="o">=</span> <span class="kc">None</span> </span><span id="L-200"><a href="#L-200"><span class="linenos">200</span></a> <span class="p">)</span>
</span><span id="L-201"><a href="#L-201"><span class="linenos">201</span></a> <span class="k">return</span> <span class="n">name</span><span class="p">,</span> <span class="n">cte</span> </span><span id="L-201"><a href="#L-201"><span class="linenos">201</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-202"><a href="#L-202"><span class="linenos">202</span></a> <span class="n">cte</span> <span class="o">=</span> <span class="kc">None</span>
</span><span id="L-203"><a href="#L-203"><span class="linenos">203</span></a> <span class="k">return</span> <span class="n">name</span><span class="p">,</span> <span class="n">cte</span>
</span></pre></div> </span></pre></div>

View file

@ -568,7 +568,7 @@ queries if it would result in multiple table selects in a single query:</p>
<div class="attr variable"> <div class="attr variable">
<span class="name">UNMERGABLE_ARGS</span> = <span class="name">UNMERGABLE_ARGS</span> =
<input id="UNMERGABLE_ARGS-view-value" class="view-value-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1"> <input id="UNMERGABLE_ARGS-view-value" class="view-value-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
<label class="view-value-button pdoc-button" for="UNMERGABLE_ARGS-view-value"></label><span class="default_value">{&#39;kind&#39;, &#39;offset&#39;, &#39;settings&#39;, &#39;locks&#39;, &#39;match&#39;, &#39;with&#39;, &#39;into&#39;, &#39;distribute&#39;, &#39;cluster&#39;, &#39;format&#39;, &#39;laterals&#39;, &#39;limit&#39;, &#39;group&#39;, &#39;sample&#39;, &#39;sort&#39;, &#39;windows&#39;, &#39;pivots&#39;, &#39;having&#39;, &#39;distinct&#39;, &#39;qualify&#39;}</span> <label class="view-value-button pdoc-button" for="UNMERGABLE_ARGS-view-value"></label><span class="default_value">{&#39;distinct&#39;, &#39;locks&#39;, &#39;laterals&#39;, &#39;pivots&#39;, &#39;limit&#39;, &#39;distribute&#39;, &#39;into&#39;, &#39;kind&#39;, &#39;sort&#39;, &#39;match&#39;, &#39;cluster&#39;, &#39;format&#39;, &#39;sample&#39;, &#39;settings&#39;, &#39;windows&#39;, &#39;qualify&#39;, &#39;having&#39;, &#39;with&#39;, &#39;offset&#39;, &#39;group&#39;}</span>
</div> </div>

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -65,95 +65,97 @@
</span><span id="L-7"><a href="#L-7"><span class="linenos"> 7</span></a><span class="kn">from</span> <span class="nn">sqlglot.optimizer.scope</span> <span class="kn">import</span> <span class="n">Scope</span><span class="p">,</span> <span class="n">traverse_scope</span> </span><span id="L-7"><a href="#L-7"><span class="linenos"> 7</span></a><span class="kn">from</span> <span class="nn">sqlglot.optimizer.scope</span> <span class="kn">import</span> <span class="n">Scope</span><span class="p">,</span> <span class="n">traverse_scope</span>
</span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</span></a><span class="kn">from</span> <span class="nn">sqlglot.schema</span> <span class="kn">import</span> <span class="n">Schema</span> </span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</span></a><span class="kn">from</span> <span class="nn">sqlglot.schema</span> <span class="kn">import</span> <span class="n">Schema</span>
</span><span id="L-9"><a href="#L-9"><span class="linenos"> 9</span></a> </span><span id="L-9"><a href="#L-9"><span class="linenos"> 9</span></a>
</span><span id="L-10"><a href="#L-10"><span class="linenos">10</span></a> </span><span id="L-10"><a href="#L-10"><span class="linenos"> 10</span></a>
</span><span id="L-11"><a href="#L-11"><span class="linenos">11</span></a><span class="k">def</span> <span class="nf">qualify_tables</span><span class="p">(</span> </span><span id="L-11"><a href="#L-11"><span class="linenos"> 11</span></a><span class="k">def</span> <span class="nf">qualify_tables</span><span class="p">(</span>
</span><span id="L-12"><a href="#L-12"><span class="linenos">12</span></a> <span class="n">expression</span><span class="p">:</span> <span class="n">E</span><span class="p">,</span> </span><span id="L-12"><a href="#L-12"><span class="linenos"> 12</span></a> <span class="n">expression</span><span class="p">:</span> <span class="n">E</span><span class="p">,</span>
</span><span id="L-13"><a href="#L-13"><span class="linenos">13</span></a> <span class="n">db</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> </span><span id="L-13"><a href="#L-13"><span class="linenos"> 13</span></a> <span class="n">db</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="L-14"><a href="#L-14"><span class="linenos">14</span></a> <span class="n">catalog</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> </span><span id="L-14"><a href="#L-14"><span class="linenos"> 14</span></a> <span class="n">catalog</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="L-15"><a href="#L-15"><span class="linenos">15</span></a> <span class="n">schema</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">Schema</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> </span><span id="L-15"><a href="#L-15"><span class="linenos"> 15</span></a> <span class="n">schema</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">Schema</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="L-16"><a href="#L-16"><span class="linenos">16</span></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">E</span><span class="p">:</span> </span><span id="L-16"><a href="#L-16"><span class="linenos"> 16</span></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">E</span><span class="p">:</span>
</span><span id="L-17"><a href="#L-17"><span class="linenos">17</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span> </span><span id="L-17"><a href="#L-17"><span class="linenos"> 17</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-18"><a href="#L-18"><span class="linenos">18</span></a><span class="sd"> Rewrite sqlglot AST to have fully qualified tables. Join constructs such as</span> </span><span id="L-18"><a href="#L-18"><span class="linenos"> 18</span></a><span class="sd"> Rewrite sqlglot AST to have fully qualified tables. Join constructs such as</span>
</span><span id="L-19"><a href="#L-19"><span class="linenos">19</span></a><span class="sd"> (t1 JOIN t2) AS t will be expanded into (SELECT * FROM t1 AS t1, t2 AS t2) AS t.</span> </span><span id="L-19"><a href="#L-19"><span class="linenos"> 19</span></a><span class="sd"> (t1 JOIN t2) AS t will be expanded into (SELECT * FROM t1 AS t1, t2 AS t2) AS t.</span>
</span><span id="L-20"><a href="#L-20"><span class="linenos">20</span></a> </span><span id="L-20"><a href="#L-20"><span class="linenos"> 20</span></a>
</span><span id="L-21"><a href="#L-21"><span class="linenos">21</span></a><span class="sd"> Examples:</span> </span><span id="L-21"><a href="#L-21"><span class="linenos"> 21</span></a><span class="sd"> Examples:</span>
</span><span id="L-22"><a href="#L-22"><span class="linenos">22</span></a><span class="sd"> &gt;&gt;&gt; import sqlglot</span> </span><span id="L-22"><a href="#L-22"><span class="linenos"> 22</span></a><span class="sd"> &gt;&gt;&gt; import sqlglot</span>
</span><span id="L-23"><a href="#L-23"><span class="linenos">23</span></a><span class="sd"> &gt;&gt;&gt; expression = sqlglot.parse_one(&quot;SELECT 1 FROM tbl&quot;)</span> </span><span id="L-23"><a href="#L-23"><span class="linenos"> 23</span></a><span class="sd"> &gt;&gt;&gt; expression = sqlglot.parse_one(&quot;SELECT 1 FROM tbl&quot;)</span>
</span><span id="L-24"><a href="#L-24"><span class="linenos">24</span></a><span class="sd"> &gt;&gt;&gt; qualify_tables(expression, db=&quot;db&quot;).sql()</span> </span><span id="L-24"><a href="#L-24"><span class="linenos"> 24</span></a><span class="sd"> &gt;&gt;&gt; qualify_tables(expression, db=&quot;db&quot;).sql()</span>
</span><span id="L-25"><a href="#L-25"><span class="linenos">25</span></a><span class="sd"> &#39;SELECT 1 FROM db.tbl AS tbl&#39;</span> </span><span id="L-25"><a href="#L-25"><span class="linenos"> 25</span></a><span class="sd"> &#39;SELECT 1 FROM db.tbl AS tbl&#39;</span>
</span><span id="L-26"><a href="#L-26"><span class="linenos">26</span></a><span class="sd"> &gt;&gt;&gt;</span> </span><span id="L-26"><a href="#L-26"><span class="linenos"> 26</span></a><span class="sd"> &gt;&gt;&gt;</span>
</span><span id="L-27"><a href="#L-27"><span class="linenos">27</span></a><span class="sd"> &gt;&gt;&gt; expression = sqlglot.parse_one(&quot;SELECT 1 FROM (t1 JOIN t2) AS t&quot;)</span> </span><span id="L-27"><a href="#L-27"><span class="linenos"> 27</span></a><span class="sd"> &gt;&gt;&gt; expression = sqlglot.parse_one(&quot;SELECT 1 FROM (t1 JOIN t2) AS t&quot;)</span>
</span><span id="L-28"><a href="#L-28"><span class="linenos">28</span></a><span class="sd"> &gt;&gt;&gt; qualify_tables(expression).sql()</span> </span><span id="L-28"><a href="#L-28"><span class="linenos"> 28</span></a><span class="sd"> &gt;&gt;&gt; qualify_tables(expression).sql()</span>
</span><span id="L-29"><a href="#L-29"><span class="linenos">29</span></a><span class="sd"> &#39;SELECT 1 FROM (SELECT * FROM t1 AS t1, t2 AS t2) AS t&#39;</span> </span><span id="L-29"><a href="#L-29"><span class="linenos"> 29</span></a><span class="sd"> &#39;SELECT 1 FROM (SELECT * FROM t1 AS t1, t2 AS t2) AS t&#39;</span>
</span><span id="L-30"><a href="#L-30"><span class="linenos">30</span></a> </span><span id="L-30"><a href="#L-30"><span class="linenos"> 30</span></a>
</span><span id="L-31"><a href="#L-31"><span class="linenos">31</span></a><span class="sd"> Args:</span> </span><span id="L-31"><a href="#L-31"><span class="linenos"> 31</span></a><span class="sd"> Args:</span>
</span><span id="L-32"><a href="#L-32"><span class="linenos">32</span></a><span class="sd"> expression: Expression to qualify</span> </span><span id="L-32"><a href="#L-32"><span class="linenos"> 32</span></a><span class="sd"> expression: Expression to qualify</span>
</span><span id="L-33"><a href="#L-33"><span class="linenos">33</span></a><span class="sd"> db: Database name</span> </span><span id="L-33"><a href="#L-33"><span class="linenos"> 33</span></a><span class="sd"> db: Database name</span>
</span><span id="L-34"><a href="#L-34"><span class="linenos">34</span></a><span class="sd"> catalog: Catalog name</span> </span><span id="L-34"><a href="#L-34"><span class="linenos"> 34</span></a><span class="sd"> catalog: Catalog name</span>
</span><span id="L-35"><a href="#L-35"><span class="linenos">35</span></a><span class="sd"> schema: A schema to populate</span> </span><span id="L-35"><a href="#L-35"><span class="linenos"> 35</span></a><span class="sd"> schema: A schema to populate</span>
</span><span id="L-36"><a href="#L-36"><span class="linenos">36</span></a> </span><span id="L-36"><a href="#L-36"><span class="linenos"> 36</span></a>
</span><span id="L-37"><a href="#L-37"><span class="linenos">37</span></a><span class="sd"> Returns:</span> </span><span id="L-37"><a href="#L-37"><span class="linenos"> 37</span></a><span class="sd"> Returns:</span>
</span><span id="L-38"><a href="#L-38"><span class="linenos">38</span></a><span class="sd"> The qualified expression.</span> </span><span id="L-38"><a href="#L-38"><span class="linenos"> 38</span></a><span class="sd"> The qualified expression.</span>
</span><span id="L-39"><a href="#L-39"><span class="linenos">39</span></a><span class="sd"> &quot;&quot;&quot;</span> </span><span id="L-39"><a href="#L-39"><span class="linenos"> 39</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-40"><a href="#L-40"><span class="linenos">40</span></a> <span class="n">next_alias_name</span> <span class="o">=</span> <span class="n">name_sequence</span><span class="p">(</span><span class="s2">&quot;_q_&quot;</span><span class="p">)</span> </span><span id="L-40"><a href="#L-40"><span class="linenos"> 40</span></a> <span class="n">next_alias_name</span> <span class="o">=</span> <span class="n">name_sequence</span><span class="p">(</span><span class="s2">&quot;_q_&quot;</span><span class="p">)</span>
</span><span id="L-41"><a href="#L-41"><span class="linenos">41</span></a> </span><span id="L-41"><a href="#L-41"><span class="linenos"> 41</span></a>
</span><span id="L-42"><a href="#L-42"><span class="linenos">42</span></a> <span class="k">for</span> <span class="n">scope</span> <span class="ow">in</span> <span class="n">traverse_scope</span><span class="p">(</span><span class="n">expression</span><span class="p">):</span> </span><span id="L-42"><a href="#L-42"><span class="linenos"> 42</span></a> <span class="k">for</span> <span class="n">scope</span> <span class="ow">in</span> <span class="n">traverse_scope</span><span class="p">(</span><span class="n">expression</span><span class="p">):</span>
</span><span id="L-43"><a href="#L-43"><span class="linenos">43</span></a> <span class="k">for</span> <span class="n">derived_table</span> <span class="ow">in</span> <span class="n">itertools</span><span class="o">.</span><span class="n">chain</span><span class="p">(</span><span class="n">scope</span><span class="o">.</span><span class="n">ctes</span><span class="p">,</span> <span class="n">scope</span><span class="o">.</span><span class="n">derived_tables</span><span class="p">):</span> </span><span id="L-43"><a href="#L-43"><span class="linenos"> 43</span></a> <span class="k">for</span> <span class="n">derived_table</span> <span class="ow">in</span> <span class="n">itertools</span><span class="o">.</span><span class="n">chain</span><span class="p">(</span><span class="n">scope</span><span class="o">.</span><span class="n">ctes</span><span class="p">,</span> <span class="n">scope</span><span class="o">.</span><span class="n">derived_tables</span><span class="p">):</span>
</span><span id="L-44"><a href="#L-44"><span class="linenos">44</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">derived_table</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Subquery</span><span class="p">):</span> </span><span id="L-44"><a href="#L-44"><span class="linenos"> 44</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">derived_table</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Subquery</span><span class="p">):</span>
</span><span id="L-45"><a href="#L-45"><span class="linenos">45</span></a> <span class="n">unnested</span> <span class="o">=</span> <span class="n">derived_table</span><span class="o">.</span><span class="n">unnest</span><span class="p">()</span> </span><span id="L-45"><a href="#L-45"><span class="linenos"> 45</span></a> <span class="n">unnested</span> <span class="o">=</span> <span class="n">derived_table</span><span class="o">.</span><span class="n">unnest</span><span class="p">()</span>
</span><span id="L-46"><a href="#L-46"><span class="linenos">46</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">unnested</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Table</span><span class="p">):</span> </span><span id="L-46"><a href="#L-46"><span class="linenos"> 46</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">unnested</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Table</span><span class="p">):</span>
</span><span id="L-47"><a href="#L-47"><span class="linenos">47</span></a> <span class="n">joins</span> <span class="o">=</span> <span class="n">unnested</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">&quot;joins&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span> </span><span id="L-47"><a href="#L-47"><span class="linenos"> 47</span></a> <span class="n">joins</span> <span class="o">=</span> <span class="n">unnested</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">&quot;joins&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
</span><span id="L-48"><a href="#L-48"><span class="linenos">48</span></a> <span class="n">derived_table</span><span class="o">.</span><span class="n">this</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">select</span><span class="p">(</span><span class="s2">&quot;*&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">from_</span><span class="p">(</span><span class="n">unnested</span><span class="o">.</span><span class="n">copy</span><span class="p">(),</span> <span class="n">copy</span><span class="o">=</span><span class="kc">False</span><span class="p">))</span> </span><span id="L-48"><a href="#L-48"><span class="linenos"> 48</span></a> <span class="n">derived_table</span><span class="o">.</span><span class="n">this</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">select</span><span class="p">(</span><span class="s2">&quot;*&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">from_</span><span class="p">(</span><span class="n">unnested</span><span class="o">.</span><span class="n">copy</span><span class="p">(),</span> <span class="n">copy</span><span class="o">=</span><span class="kc">False</span><span class="p">))</span>
</span><span id="L-49"><a href="#L-49"><span class="linenos">49</span></a> <span class="n">derived_table</span><span class="o">.</span><span class="n">this</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;joins&quot;</span><span class="p">,</span> <span class="n">joins</span><span class="p">)</span> </span><span id="L-49"><a href="#L-49"><span class="linenos"> 49</span></a> <span class="n">derived_table</span><span class="o">.</span><span class="n">this</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;joins&quot;</span><span class="p">,</span> <span class="n">joins</span><span class="p">)</span>
</span><span id="L-50"><a href="#L-50"><span class="linenos">50</span></a> </span><span id="L-50"><a href="#L-50"><span class="linenos"> 50</span></a>
</span><span id="L-51"><a href="#L-51"><span class="linenos">51</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">derived_table</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;alias&quot;</span><span class="p">):</span> </span><span id="L-51"><a href="#L-51"><span class="linenos"> 51</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">derived_table</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;alias&quot;</span><span class="p">):</span>
</span><span id="L-52"><a href="#L-52"><span class="linenos">52</span></a> <span class="n">alias_</span> <span class="o">=</span> <span class="n">next_alias_name</span><span class="p">()</span> </span><span id="L-52"><a href="#L-52"><span class="linenos"> 52</span></a> <span class="n">alias_</span> <span class="o">=</span> <span class="n">next_alias_name</span><span class="p">()</span>
</span><span id="L-53"><a href="#L-53"><span class="linenos">53</span></a> <span class="n">derived_table</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;alias&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">TableAlias</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">alias_</span><span class="p">)))</span> </span><span id="L-53"><a href="#L-53"><span class="linenos"> 53</span></a> <span class="n">derived_table</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;alias&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">TableAlias</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">alias_</span><span class="p">)))</span>
</span><span id="L-54"><a href="#L-54"><span class="linenos">54</span></a> <span class="n">scope</span><span class="o">.</span><span class="n">rename_source</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="n">alias_</span><span class="p">)</span> </span><span id="L-54"><a href="#L-54"><span class="linenos"> 54</span></a> <span class="n">scope</span><span class="o">.</span><span class="n">rename_source</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="n">alias_</span><span class="p">)</span>
</span><span id="L-55"><a href="#L-55"><span class="linenos">55</span></a> </span><span id="L-55"><a href="#L-55"><span class="linenos"> 55</span></a>
</span><span id="L-56"><a href="#L-56"><span class="linenos">56</span></a> <span class="n">pivots</span> <span class="o">=</span> <span class="n">derived_table</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;pivots&quot;</span><span class="p">)</span> </span><span id="L-56"><a href="#L-56"><span class="linenos"> 56</span></a> <span class="n">pivots</span> <span class="o">=</span> <span class="n">derived_table</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;pivots&quot;</span><span class="p">)</span>
</span><span id="L-57"><a href="#L-57"><span class="linenos">57</span></a> <span class="k">if</span> <span class="n">pivots</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">pivots</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">alias</span><span class="p">:</span> </span><span id="L-57"><a href="#L-57"><span class="linenos"> 57</span></a> <span class="k">if</span> <span class="n">pivots</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">pivots</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">alias</span><span class="p">:</span>
</span><span id="L-58"><a href="#L-58"><span class="linenos">58</span></a> <span class="n">pivots</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;alias&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">TableAlias</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">next_alias_name</span><span class="p">())))</span> </span><span id="L-58"><a href="#L-58"><span class="linenos"> 58</span></a> <span class="n">pivots</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;alias&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">TableAlias</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">next_alias_name</span><span class="p">())))</span>
</span><span id="L-59"><a href="#L-59"><span class="linenos">59</span></a> </span><span id="L-59"><a href="#L-59"><span class="linenos"> 59</span></a>
</span><span id="L-60"><a href="#L-60"><span class="linenos">60</span></a> <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">source</span> <span class="ow">in</span> <span class="n">scope</span><span class="o">.</span><span class="n">sources</span><span class="o">.</span><span class="n">items</span><span class="p">():</span> </span><span id="L-60"><a href="#L-60"><span class="linenos"> 60</span></a> <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">source</span> <span class="ow">in</span> <span class="n">scope</span><span class="o">.</span><span class="n">sources</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
</span><span id="L-61"><a href="#L-61"><span class="linenos">61</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">source</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Table</span><span class="p">):</span> </span><span id="L-61"><a href="#L-61"><span class="linenos"> 61</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">source</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Table</span><span class="p">):</span>
</span><span id="L-62"><a href="#L-62"><span class="linenos">62</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">source</span><span class="o">.</span><span class="n">this</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Identifier</span><span class="p">):</span> </span><span id="L-62"><a href="#L-62"><span class="linenos"> 62</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">source</span><span class="o">.</span><span class="n">this</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Identifier</span><span class="p">):</span>
</span><span id="L-63"><a href="#L-63"><span class="linenos">63</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">source</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;db&quot;</span><span class="p">):</span> </span><span id="L-63"><a href="#L-63"><span class="linenos"> 63</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">source</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;db&quot;</span><span class="p">):</span>
</span><span id="L-64"><a href="#L-64"><span class="linenos">64</span></a> <span class="n">source</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;db&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">db</span><span class="p">))</span> </span><span id="L-64"><a href="#L-64"><span class="linenos"> 64</span></a> <span class="n">source</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;db&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">db</span><span class="p">))</span>
</span><span id="L-65"><a href="#L-65"><span class="linenos">65</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">source</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;catalog&quot;</span><span class="p">):</span> </span><span id="L-65"><a href="#L-65"><span class="linenos"> 65</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">source</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;catalog&quot;</span><span class="p">):</span>
</span><span id="L-66"><a href="#L-66"><span class="linenos">66</span></a> <span class="n">source</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;catalog&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">catalog</span><span class="p">))</span> </span><span id="L-66"><a href="#L-66"><span class="linenos"> 66</span></a> <span class="n">source</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;catalog&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">catalog</span><span class="p">))</span>
</span><span id="L-67"><a href="#L-67"><span class="linenos">67</span></a> </span><span id="L-67"><a href="#L-67"><span class="linenos"> 67</span></a>
</span><span id="L-68"><a href="#L-68"><span class="linenos">68</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">source</span><span class="o">.</span><span class="n">alias</span><span class="p">:</span> </span><span id="L-68"><a href="#L-68"><span class="linenos"> 68</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">source</span><span class="o">.</span><span class="n">alias</span><span class="p">:</span>
</span><span id="L-69"><a href="#L-69"><span class="linenos">69</span></a> <span class="c1"># Mutates the source by attaching an alias to it</span> </span><span id="L-69"><a href="#L-69"><span class="linenos"> 69</span></a> <span class="c1"># Mutates the source by attaching an alias to it</span>
</span><span id="L-70"><a href="#L-70"><span class="linenos">70</span></a> <span class="n">alias</span><span class="p">(</span><span class="n">source</span><span class="p">,</span> <span class="n">name</span> <span class="ow">or</span> <span class="n">source</span><span class="o">.</span><span class="n">name</span> <span class="ow">or</span> <span class="n">next_alias_name</span><span class="p">(),</span> <span class="n">copy</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">table</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> </span><span id="L-70"><a href="#L-70"><span class="linenos"> 70</span></a> <span class="n">alias</span><span class="p">(</span><span class="n">source</span><span class="p">,</span> <span class="n">name</span> <span class="ow">or</span> <span class="n">source</span><span class="o">.</span><span class="n">name</span> <span class="ow">or</span> <span class="n">next_alias_name</span><span class="p">(),</span> <span class="n">copy</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">table</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="L-71"><a href="#L-71"><span class="linenos">71</span></a> </span><span id="L-71"><a href="#L-71"><span class="linenos"> 71</span></a>
</span><span id="L-72"><a href="#L-72"><span class="linenos">72</span></a> <span class="n">pivots</span> <span class="o">=</span> <span class="n">source</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;pivots&quot;</span><span class="p">)</span> </span><span id="L-72"><a href="#L-72"><span class="linenos"> 72</span></a> <span class="n">pivots</span> <span class="o">=</span> <span class="n">source</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;pivots&quot;</span><span class="p">)</span>
</span><span id="L-73"><a href="#L-73"><span class="linenos">73</span></a> <span class="k">if</span> <span class="n">pivots</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">pivots</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">alias</span><span class="p">:</span> </span><span id="L-73"><a href="#L-73"><span class="linenos"> 73</span></a> <span class="k">if</span> <span class="n">pivots</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">pivots</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">alias</span><span class="p">:</span>
</span><span id="L-74"><a href="#L-74"><span class="linenos">74</span></a> <span class="n">pivots</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">set</span><span class="p">(</span> </span><span id="L-74"><a href="#L-74"><span class="linenos"> 74</span></a> <span class="n">pivots</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">set</span><span class="p">(</span>
</span><span id="L-75"><a href="#L-75"><span class="linenos">75</span></a> <span class="s2">&quot;alias&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">TableAlias</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">next_alias_name</span><span class="p">()))</span> </span><span id="L-75"><a href="#L-75"><span class="linenos"> 75</span></a> <span class="s2">&quot;alias&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">TableAlias</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">next_alias_name</span><span class="p">()))</span>
</span><span id="L-76"><a href="#L-76"><span class="linenos">76</span></a> <span class="p">)</span> </span><span id="L-76"><a href="#L-76"><span class="linenos"> 76</span></a> <span class="p">)</span>
</span><span id="L-77"><a href="#L-77"><span class="linenos">77</span></a> </span><span id="L-77"><a href="#L-77"><span class="linenos"> 77</span></a>
</span><span id="L-78"><a href="#L-78"><span class="linenos">78</span></a> <span class="k">if</span> <span class="n">schema</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">source</span><span class="o">.</span><span class="n">this</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">ReadCSV</span><span class="p">):</span> </span><span id="L-78"><a href="#L-78"><span class="linenos"> 78</span></a> <span class="k">if</span> <span class="n">schema</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">source</span><span class="o">.</span><span class="n">this</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">ReadCSV</span><span class="p">):</span>
</span><span id="L-79"><a href="#L-79"><span class="linenos">79</span></a> <span class="k">with</span> <span class="n">csv_reader</span><span class="p">(</span><span class="n">source</span><span class="o">.</span><span class="n">this</span><span class="p">)</span> <span class="k">as</span> <span class="n">reader</span><span class="p">:</span> </span><span id="L-79"><a href="#L-79"><span class="linenos"> 79</span></a> <span class="k">with</span> <span class="n">csv_reader</span><span class="p">(</span><span class="n">source</span><span class="o">.</span><span class="n">this</span><span class="p">)</span> <span class="k">as</span> <span class="n">reader</span><span class="p">:</span>
</span><span id="L-80"><a href="#L-80"><span class="linenos">80</span></a> <span class="n">header</span> <span class="o">=</span> <span class="nb">next</span><span class="p">(</span><span class="n">reader</span><span class="p">)</span> </span><span id="L-80"><a href="#L-80"><span class="linenos"> 80</span></a> <span class="n">header</span> <span class="o">=</span> <span class="nb">next</span><span class="p">(</span><span class="n">reader</span><span class="p">)</span>
</span><span id="L-81"><a href="#L-81"><span class="linenos">81</span></a> <span class="n">columns</span> <span class="o">=</span> <span class="nb">next</span><span class="p">(</span><span class="n">reader</span><span class="p">)</span> </span><span id="L-81"><a href="#L-81"><span class="linenos"> 81</span></a> <span class="n">columns</span> <span class="o">=</span> <span class="nb">next</span><span class="p">(</span><span class="n">reader</span><span class="p">)</span>
</span><span id="L-82"><a href="#L-82"><span class="linenos">82</span></a> <span class="n">schema</span><span class="o">.</span><span class="n">add_table</span><span class="p">(</span> </span><span id="L-82"><a href="#L-82"><span class="linenos"> 82</span></a> <span class="n">schema</span><span class="o">.</span><span class="n">add_table</span><span class="p">(</span>
</span><span id="L-83"><a href="#L-83"><span class="linenos">83</span></a> <span class="n">source</span><span class="p">,</span> <span class="p">{</span><span class="n">k</span><span class="p">:</span> <span class="nb">type</span><span class="p">(</span><span class="n">v</span><span class="p">)</span><span class="o">.</span><span class="vm">__name__</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">header</span><span class="p">,</span> <span class="n">columns</span><span class="p">)}</span> </span><span id="L-83"><a href="#L-83"><span class="linenos"> 83</span></a> <span class="n">source</span><span class="p">,</span>
</span><span id="L-84"><a href="#L-84"><span class="linenos">84</span></a> <span class="p">)</span> </span><span id="L-84"><a href="#L-84"><span class="linenos"> 84</span></a> <span class="p">{</span><span class="n">k</span><span class="p">:</span> <span class="nb">type</span><span class="p">(</span><span class="n">v</span><span class="p">)</span><span class="o">.</span><span class="vm">__name__</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">header</span><span class="p">,</span> <span class="n">columns</span><span class="p">)},</span>
</span><span id="L-85"><a href="#L-85"><span class="linenos">85</span></a> <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">source</span><span class="p">,</span> <span class="n">Scope</span><span class="p">)</span> <span class="ow">and</span> <span class="n">source</span><span class="o">.</span><span class="n">is_udtf</span><span class="p">:</span> </span><span id="L-85"><a href="#L-85"><span class="linenos"> 85</span></a> <span class="n">match_depth</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
</span><span id="L-86"><a href="#L-86"><span class="linenos">86</span></a> <span class="n">udtf</span> <span class="o">=</span> <span class="n">source</span><span class="o">.</span><span class="n">expression</span> </span><span id="L-86"><a href="#L-86"><span class="linenos"> 86</span></a> <span class="p">)</span>
</span><span id="L-87"><a href="#L-87"><span class="linenos">87</span></a> <span class="n">table_alias</span> <span class="o">=</span> <span class="n">udtf</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;alias&quot;</span><span class="p">)</span> <span class="ow">or</span> <span class="n">exp</span><span class="o">.</span><span class="n">TableAlias</span><span class="p">(</span> </span><span id="L-87"><a href="#L-87"><span class="linenos"> 87</span></a> <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">source</span><span class="p">,</span> <span class="n">Scope</span><span class="p">)</span> <span class="ow">and</span> <span class="n">source</span><span class="o">.</span><span class="n">is_udtf</span><span class="p">:</span>
</span><span id="L-88"><a href="#L-88"><span class="linenos">88</span></a> <span class="n">this</span><span class="o">=</span><span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">next_alias_name</span><span class="p">())</span> </span><span id="L-88"><a href="#L-88"><span class="linenos"> 88</span></a> <span class="n">udtf</span> <span class="o">=</span> <span class="n">source</span><span class="o">.</span><span class="n">expression</span>
</span><span id="L-89"><a href="#L-89"><span class="linenos">89</span></a> <span class="p">)</span> </span><span id="L-89"><a href="#L-89"><span class="linenos"> 89</span></a> <span class="n">table_alias</span> <span class="o">=</span> <span class="n">udtf</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;alias&quot;</span><span class="p">)</span> <span class="ow">or</span> <span class="n">exp</span><span class="o">.</span><span class="n">TableAlias</span><span class="p">(</span>
</span><span id="L-90"><a href="#L-90"><span class="linenos">90</span></a> <span class="n">udtf</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;alias&quot;</span><span class="p">,</span> <span class="n">table_alias</span><span class="p">)</span> </span><span id="L-90"><a href="#L-90"><span class="linenos"> 90</span></a> <span class="n">this</span><span class="o">=</span><span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">next_alias_name</span><span class="p">())</span>
</span><span id="L-91"><a href="#L-91"><span class="linenos">91</span></a> </span><span id="L-91"><a href="#L-91"><span class="linenos"> 91</span></a> <span class="p">)</span>
</span><span id="L-92"><a href="#L-92"><span class="linenos">92</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">table_alias</span><span class="o">.</span><span class="n">name</span><span class="p">:</span> </span><span id="L-92"><a href="#L-92"><span class="linenos"> 92</span></a> <span class="n">udtf</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;alias&quot;</span><span class="p">,</span> <span class="n">table_alias</span><span class="p">)</span>
</span><span id="L-93"><a href="#L-93"><span class="linenos">93</span></a> <span class="n">table_alias</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;this&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">next_alias_name</span><span class="p">()))</span> </span><span id="L-93"><a href="#L-93"><span class="linenos"> 93</span></a>
</span><span id="L-94"><a href="#L-94"><span class="linenos">94</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">udtf</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Values</span><span class="p">)</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">table_alias</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span> </span><span id="L-94"><a href="#L-94"><span class="linenos"> 94</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">table_alias</span><span class="o">.</span><span class="n">name</span><span class="p">:</span>
</span><span id="L-95"><a href="#L-95"><span class="linenos">95</span></a> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">e</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">udtf</span><span class="o">.</span><span class="n">expressions</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">expressions</span><span class="p">):</span> </span><span id="L-95"><a href="#L-95"><span class="linenos"> 95</span></a> <span class="n">table_alias</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;this&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">next_alias_name</span><span class="p">()))</span>
</span><span id="L-96"><a href="#L-96"><span class="linenos">96</span></a> <span class="n">table_alias</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;columns&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;_col_</span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">))</span> </span><span id="L-96"><a href="#L-96"><span class="linenos"> 96</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">udtf</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Values</span><span class="p">)</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">table_alias</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span>
</span><span id="L-97"><a href="#L-97"><span class="linenos">97</span></a> </span><span id="L-97"><a href="#L-97"><span class="linenos"> 97</span></a> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">e</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">udtf</span><span class="o">.</span><span class="n">expressions</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">expressions</span><span class="p">):</span>
</span><span id="L-98"><a href="#L-98"><span class="linenos">98</span></a> <span class="k">return</span> <span class="n">expression</span> </span><span id="L-98"><a href="#L-98"><span class="linenos"> 98</span></a> <span class="n">table_alias</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;columns&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;_col_</span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">))</span>
</span><span id="L-99"><a href="#L-99"><span class="linenos"> 99</span></a>
</span><span id="L-100"><a href="#L-100"><span class="linenos">100</span></a> <span class="k">return</span> <span class="n">expression</span>
</span></pre></div> </span></pre></div>
@ -169,94 +171,96 @@
</div> </div>
<a class="headerlink" href="#qualify_tables"></a> <a class="headerlink" href="#qualify_tables"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="qualify_tables-12"><a href="#qualify_tables-12"><span class="linenos">12</span></a><span class="k">def</span> <span class="nf">qualify_tables</span><span class="p">(</span> <div class="pdoc-code codehilite"><pre><span></span><span id="qualify_tables-12"><a href="#qualify_tables-12"><span class="linenos"> 12</span></a><span class="k">def</span> <span class="nf">qualify_tables</span><span class="p">(</span>
</span><span id="qualify_tables-13"><a href="#qualify_tables-13"><span class="linenos">13</span></a> <span class="n">expression</span><span class="p">:</span> <span class="n">E</span><span class="p">,</span> </span><span id="qualify_tables-13"><a href="#qualify_tables-13"><span class="linenos"> 13</span></a> <span class="n">expression</span><span class="p">:</span> <span class="n">E</span><span class="p">,</span>
</span><span id="qualify_tables-14"><a href="#qualify_tables-14"><span class="linenos">14</span></a> <span class="n">db</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> </span><span id="qualify_tables-14"><a href="#qualify_tables-14"><span class="linenos"> 14</span></a> <span class="n">db</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="qualify_tables-15"><a href="#qualify_tables-15"><span class="linenos">15</span></a> <span class="n">catalog</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> </span><span id="qualify_tables-15"><a href="#qualify_tables-15"><span class="linenos"> 15</span></a> <span class="n">catalog</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="qualify_tables-16"><a href="#qualify_tables-16"><span class="linenos">16</span></a> <span class="n">schema</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">Schema</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> </span><span id="qualify_tables-16"><a href="#qualify_tables-16"><span class="linenos"> 16</span></a> <span class="n">schema</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">Schema</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="qualify_tables-17"><a href="#qualify_tables-17"><span class="linenos">17</span></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">E</span><span class="p">:</span> </span><span id="qualify_tables-17"><a href="#qualify_tables-17"><span class="linenos"> 17</span></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">E</span><span class="p">:</span>
</span><span id="qualify_tables-18"><a href="#qualify_tables-18"><span class="linenos">18</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span> </span><span id="qualify_tables-18"><a href="#qualify_tables-18"><span class="linenos"> 18</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="qualify_tables-19"><a href="#qualify_tables-19"><span class="linenos">19</span></a><span class="sd"> Rewrite sqlglot AST to have fully qualified tables. Join constructs such as</span> </span><span id="qualify_tables-19"><a href="#qualify_tables-19"><span class="linenos"> 19</span></a><span class="sd"> Rewrite sqlglot AST to have fully qualified tables. Join constructs such as</span>
</span><span id="qualify_tables-20"><a href="#qualify_tables-20"><span class="linenos">20</span></a><span class="sd"> (t1 JOIN t2) AS t will be expanded into (SELECT * FROM t1 AS t1, t2 AS t2) AS t.</span> </span><span id="qualify_tables-20"><a href="#qualify_tables-20"><span class="linenos"> 20</span></a><span class="sd"> (t1 JOIN t2) AS t will be expanded into (SELECT * FROM t1 AS t1, t2 AS t2) AS t.</span>
</span><span id="qualify_tables-21"><a href="#qualify_tables-21"><span class="linenos">21</span></a> </span><span id="qualify_tables-21"><a href="#qualify_tables-21"><span class="linenos"> 21</span></a>
</span><span id="qualify_tables-22"><a href="#qualify_tables-22"><span class="linenos">22</span></a><span class="sd"> Examples:</span> </span><span id="qualify_tables-22"><a href="#qualify_tables-22"><span class="linenos"> 22</span></a><span class="sd"> Examples:</span>
</span><span id="qualify_tables-23"><a href="#qualify_tables-23"><span class="linenos">23</span></a><span class="sd"> &gt;&gt;&gt; import sqlglot</span> </span><span id="qualify_tables-23"><a href="#qualify_tables-23"><span class="linenos"> 23</span></a><span class="sd"> &gt;&gt;&gt; import sqlglot</span>
</span><span id="qualify_tables-24"><a href="#qualify_tables-24"><span class="linenos">24</span></a><span class="sd"> &gt;&gt;&gt; expression = sqlglot.parse_one(&quot;SELECT 1 FROM tbl&quot;)</span> </span><span id="qualify_tables-24"><a href="#qualify_tables-24"><span class="linenos"> 24</span></a><span class="sd"> &gt;&gt;&gt; expression = sqlglot.parse_one(&quot;SELECT 1 FROM tbl&quot;)</span>
</span><span id="qualify_tables-25"><a href="#qualify_tables-25"><span class="linenos">25</span></a><span class="sd"> &gt;&gt;&gt; qualify_tables(expression, db=&quot;db&quot;).sql()</span> </span><span id="qualify_tables-25"><a href="#qualify_tables-25"><span class="linenos"> 25</span></a><span class="sd"> &gt;&gt;&gt; qualify_tables(expression, db=&quot;db&quot;).sql()</span>
</span><span id="qualify_tables-26"><a href="#qualify_tables-26"><span class="linenos">26</span></a><span class="sd"> &#39;SELECT 1 FROM db.tbl AS tbl&#39;</span> </span><span id="qualify_tables-26"><a href="#qualify_tables-26"><span class="linenos"> 26</span></a><span class="sd"> &#39;SELECT 1 FROM db.tbl AS tbl&#39;</span>
</span><span id="qualify_tables-27"><a href="#qualify_tables-27"><span class="linenos">27</span></a><span class="sd"> &gt;&gt;&gt;</span> </span><span id="qualify_tables-27"><a href="#qualify_tables-27"><span class="linenos"> 27</span></a><span class="sd"> &gt;&gt;&gt;</span>
</span><span id="qualify_tables-28"><a href="#qualify_tables-28"><span class="linenos">28</span></a><span class="sd"> &gt;&gt;&gt; expression = sqlglot.parse_one(&quot;SELECT 1 FROM (t1 JOIN t2) AS t&quot;)</span> </span><span id="qualify_tables-28"><a href="#qualify_tables-28"><span class="linenos"> 28</span></a><span class="sd"> &gt;&gt;&gt; expression = sqlglot.parse_one(&quot;SELECT 1 FROM (t1 JOIN t2) AS t&quot;)</span>
</span><span id="qualify_tables-29"><a href="#qualify_tables-29"><span class="linenos">29</span></a><span class="sd"> &gt;&gt;&gt; qualify_tables(expression).sql()</span> </span><span id="qualify_tables-29"><a href="#qualify_tables-29"><span class="linenos"> 29</span></a><span class="sd"> &gt;&gt;&gt; qualify_tables(expression).sql()</span>
</span><span id="qualify_tables-30"><a href="#qualify_tables-30"><span class="linenos">30</span></a><span class="sd"> &#39;SELECT 1 FROM (SELECT * FROM t1 AS t1, t2 AS t2) AS t&#39;</span> </span><span id="qualify_tables-30"><a href="#qualify_tables-30"><span class="linenos"> 30</span></a><span class="sd"> &#39;SELECT 1 FROM (SELECT * FROM t1 AS t1, t2 AS t2) AS t&#39;</span>
</span><span id="qualify_tables-31"><a href="#qualify_tables-31"><span class="linenos">31</span></a> </span><span id="qualify_tables-31"><a href="#qualify_tables-31"><span class="linenos"> 31</span></a>
</span><span id="qualify_tables-32"><a href="#qualify_tables-32"><span class="linenos">32</span></a><span class="sd"> Args:</span> </span><span id="qualify_tables-32"><a href="#qualify_tables-32"><span class="linenos"> 32</span></a><span class="sd"> Args:</span>
</span><span id="qualify_tables-33"><a href="#qualify_tables-33"><span class="linenos">33</span></a><span class="sd"> expression: Expression to qualify</span> </span><span id="qualify_tables-33"><a href="#qualify_tables-33"><span class="linenos"> 33</span></a><span class="sd"> expression: Expression to qualify</span>
</span><span id="qualify_tables-34"><a href="#qualify_tables-34"><span class="linenos">34</span></a><span class="sd"> db: Database name</span> </span><span id="qualify_tables-34"><a href="#qualify_tables-34"><span class="linenos"> 34</span></a><span class="sd"> db: Database name</span>
</span><span id="qualify_tables-35"><a href="#qualify_tables-35"><span class="linenos">35</span></a><span class="sd"> catalog: Catalog name</span> </span><span id="qualify_tables-35"><a href="#qualify_tables-35"><span class="linenos"> 35</span></a><span class="sd"> catalog: Catalog name</span>
</span><span id="qualify_tables-36"><a href="#qualify_tables-36"><span class="linenos">36</span></a><span class="sd"> schema: A schema to populate</span> </span><span id="qualify_tables-36"><a href="#qualify_tables-36"><span class="linenos"> 36</span></a><span class="sd"> schema: A schema to populate</span>
</span><span id="qualify_tables-37"><a href="#qualify_tables-37"><span class="linenos">37</span></a> </span><span id="qualify_tables-37"><a href="#qualify_tables-37"><span class="linenos"> 37</span></a>
</span><span id="qualify_tables-38"><a href="#qualify_tables-38"><span class="linenos">38</span></a><span class="sd"> Returns:</span> </span><span id="qualify_tables-38"><a href="#qualify_tables-38"><span class="linenos"> 38</span></a><span class="sd"> Returns:</span>
</span><span id="qualify_tables-39"><a href="#qualify_tables-39"><span class="linenos">39</span></a><span class="sd"> The qualified expression.</span> </span><span id="qualify_tables-39"><a href="#qualify_tables-39"><span class="linenos"> 39</span></a><span class="sd"> The qualified expression.</span>
</span><span id="qualify_tables-40"><a href="#qualify_tables-40"><span class="linenos">40</span></a><span class="sd"> &quot;&quot;&quot;</span> </span><span id="qualify_tables-40"><a href="#qualify_tables-40"><span class="linenos"> 40</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="qualify_tables-41"><a href="#qualify_tables-41"><span class="linenos">41</span></a> <span class="n">next_alias_name</span> <span class="o">=</span> <span class="n">name_sequence</span><span class="p">(</span><span class="s2">&quot;_q_&quot;</span><span class="p">)</span> </span><span id="qualify_tables-41"><a href="#qualify_tables-41"><span class="linenos"> 41</span></a> <span class="n">next_alias_name</span> <span class="o">=</span> <span class="n">name_sequence</span><span class="p">(</span><span class="s2">&quot;_q_&quot;</span><span class="p">)</span>
</span><span id="qualify_tables-42"><a href="#qualify_tables-42"><span class="linenos">42</span></a> </span><span id="qualify_tables-42"><a href="#qualify_tables-42"><span class="linenos"> 42</span></a>
</span><span id="qualify_tables-43"><a href="#qualify_tables-43"><span class="linenos">43</span></a> <span class="k">for</span> <span class="n">scope</span> <span class="ow">in</span> <span class="n">traverse_scope</span><span class="p">(</span><span class="n">expression</span><span class="p">):</span> </span><span id="qualify_tables-43"><a href="#qualify_tables-43"><span class="linenos"> 43</span></a> <span class="k">for</span> <span class="n">scope</span> <span class="ow">in</span> <span class="n">traverse_scope</span><span class="p">(</span><span class="n">expression</span><span class="p">):</span>
</span><span id="qualify_tables-44"><a href="#qualify_tables-44"><span class="linenos">44</span></a> <span class="k">for</span> <span class="n">derived_table</span> <span class="ow">in</span> <span class="n">itertools</span><span class="o">.</span><span class="n">chain</span><span class="p">(</span><span class="n">scope</span><span class="o">.</span><span class="n">ctes</span><span class="p">,</span> <span class="n">scope</span><span class="o">.</span><span class="n">derived_tables</span><span class="p">):</span> </span><span id="qualify_tables-44"><a href="#qualify_tables-44"><span class="linenos"> 44</span></a> <span class="k">for</span> <span class="n">derived_table</span> <span class="ow">in</span> <span class="n">itertools</span><span class="o">.</span><span class="n">chain</span><span class="p">(</span><span class="n">scope</span><span class="o">.</span><span class="n">ctes</span><span class="p">,</span> <span class="n">scope</span><span class="o">.</span><span class="n">derived_tables</span><span class="p">):</span>
</span><span id="qualify_tables-45"><a href="#qualify_tables-45"><span class="linenos">45</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">derived_table</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Subquery</span><span class="p">):</span> </span><span id="qualify_tables-45"><a href="#qualify_tables-45"><span class="linenos"> 45</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">derived_table</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Subquery</span><span class="p">):</span>
</span><span id="qualify_tables-46"><a href="#qualify_tables-46"><span class="linenos">46</span></a> <span class="n">unnested</span> <span class="o">=</span> <span class="n">derived_table</span><span class="o">.</span><span class="n">unnest</span><span class="p">()</span> </span><span id="qualify_tables-46"><a href="#qualify_tables-46"><span class="linenos"> 46</span></a> <span class="n">unnested</span> <span class="o">=</span> <span class="n">derived_table</span><span class="o">.</span><span class="n">unnest</span><span class="p">()</span>
</span><span id="qualify_tables-47"><a href="#qualify_tables-47"><span class="linenos">47</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">unnested</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Table</span><span class="p">):</span> </span><span id="qualify_tables-47"><a href="#qualify_tables-47"><span class="linenos"> 47</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">unnested</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Table</span><span class="p">):</span>
</span><span id="qualify_tables-48"><a href="#qualify_tables-48"><span class="linenos">48</span></a> <span class="n">joins</span> <span class="o">=</span> <span class="n">unnested</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">&quot;joins&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span> </span><span id="qualify_tables-48"><a href="#qualify_tables-48"><span class="linenos"> 48</span></a> <span class="n">joins</span> <span class="o">=</span> <span class="n">unnested</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">&quot;joins&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
</span><span id="qualify_tables-49"><a href="#qualify_tables-49"><span class="linenos">49</span></a> <span class="n">derived_table</span><span class="o">.</span><span class="n">this</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">select</span><span class="p">(</span><span class="s2">&quot;*&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">from_</span><span class="p">(</span><span class="n">unnested</span><span class="o">.</span><span class="n">copy</span><span class="p">(),</span> <span class="n">copy</span><span class="o">=</span><span class="kc">False</span><span class="p">))</span> </span><span id="qualify_tables-49"><a href="#qualify_tables-49"><span class="linenos"> 49</span></a> <span class="n">derived_table</span><span class="o">.</span><span class="n">this</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">select</span><span class="p">(</span><span class="s2">&quot;*&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">from_</span><span class="p">(</span><span class="n">unnested</span><span class="o">.</span><span class="n">copy</span><span class="p">(),</span> <span class="n">copy</span><span class="o">=</span><span class="kc">False</span><span class="p">))</span>
</span><span id="qualify_tables-50"><a href="#qualify_tables-50"><span class="linenos">50</span></a> <span class="n">derived_table</span><span class="o">.</span><span class="n">this</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;joins&quot;</span><span class="p">,</span> <span class="n">joins</span><span class="p">)</span> </span><span id="qualify_tables-50"><a href="#qualify_tables-50"><span class="linenos"> 50</span></a> <span class="n">derived_table</span><span class="o">.</span><span class="n">this</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;joins&quot;</span><span class="p">,</span> <span class="n">joins</span><span class="p">)</span>
</span><span id="qualify_tables-51"><a href="#qualify_tables-51"><span class="linenos">51</span></a> </span><span id="qualify_tables-51"><a href="#qualify_tables-51"><span class="linenos"> 51</span></a>
</span><span id="qualify_tables-52"><a href="#qualify_tables-52"><span class="linenos">52</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">derived_table</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;alias&quot;</span><span class="p">):</span> </span><span id="qualify_tables-52"><a href="#qualify_tables-52"><span class="linenos"> 52</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">derived_table</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;alias&quot;</span><span class="p">):</span>
</span><span id="qualify_tables-53"><a href="#qualify_tables-53"><span class="linenos">53</span></a> <span class="n">alias_</span> <span class="o">=</span> <span class="n">next_alias_name</span><span class="p">()</span> </span><span id="qualify_tables-53"><a href="#qualify_tables-53"><span class="linenos"> 53</span></a> <span class="n">alias_</span> <span class="o">=</span> <span class="n">next_alias_name</span><span class="p">()</span>
</span><span id="qualify_tables-54"><a href="#qualify_tables-54"><span class="linenos">54</span></a> <span class="n">derived_table</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;alias&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">TableAlias</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">alias_</span><span class="p">)))</span> </span><span id="qualify_tables-54"><a href="#qualify_tables-54"><span class="linenos"> 54</span></a> <span class="n">derived_table</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;alias&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">TableAlias</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">alias_</span><span class="p">)))</span>
</span><span id="qualify_tables-55"><a href="#qualify_tables-55"><span class="linenos">55</span></a> <span class="n">scope</span><span class="o">.</span><span class="n">rename_source</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="n">alias_</span><span class="p">)</span> </span><span id="qualify_tables-55"><a href="#qualify_tables-55"><span class="linenos"> 55</span></a> <span class="n">scope</span><span class="o">.</span><span class="n">rename_source</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="n">alias_</span><span class="p">)</span>
</span><span id="qualify_tables-56"><a href="#qualify_tables-56"><span class="linenos">56</span></a> </span><span id="qualify_tables-56"><a href="#qualify_tables-56"><span class="linenos"> 56</span></a>
</span><span id="qualify_tables-57"><a href="#qualify_tables-57"><span class="linenos">57</span></a> <span class="n">pivots</span> <span class="o">=</span> <span class="n">derived_table</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;pivots&quot;</span><span class="p">)</span> </span><span id="qualify_tables-57"><a href="#qualify_tables-57"><span class="linenos"> 57</span></a> <span class="n">pivots</span> <span class="o">=</span> <span class="n">derived_table</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;pivots&quot;</span><span class="p">)</span>
</span><span id="qualify_tables-58"><a href="#qualify_tables-58"><span class="linenos">58</span></a> <span class="k">if</span> <span class="n">pivots</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">pivots</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">alias</span><span class="p">:</span> </span><span id="qualify_tables-58"><a href="#qualify_tables-58"><span class="linenos"> 58</span></a> <span class="k">if</span> <span class="n">pivots</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">pivots</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">alias</span><span class="p">:</span>
</span><span id="qualify_tables-59"><a href="#qualify_tables-59"><span class="linenos">59</span></a> <span class="n">pivots</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;alias&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">TableAlias</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">next_alias_name</span><span class="p">())))</span> </span><span id="qualify_tables-59"><a href="#qualify_tables-59"><span class="linenos"> 59</span></a> <span class="n">pivots</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;alias&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">TableAlias</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">next_alias_name</span><span class="p">())))</span>
</span><span id="qualify_tables-60"><a href="#qualify_tables-60"><span class="linenos">60</span></a> </span><span id="qualify_tables-60"><a href="#qualify_tables-60"><span class="linenos"> 60</span></a>
</span><span id="qualify_tables-61"><a href="#qualify_tables-61"><span class="linenos">61</span></a> <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">source</span> <span class="ow">in</span> <span class="n">scope</span><span class="o">.</span><span class="n">sources</span><span class="o">.</span><span class="n">items</span><span class="p">():</span> </span><span id="qualify_tables-61"><a href="#qualify_tables-61"><span class="linenos"> 61</span></a> <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">source</span> <span class="ow">in</span> <span class="n">scope</span><span class="o">.</span><span class="n">sources</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
</span><span id="qualify_tables-62"><a href="#qualify_tables-62"><span class="linenos">62</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">source</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Table</span><span class="p">):</span> </span><span id="qualify_tables-62"><a href="#qualify_tables-62"><span class="linenos"> 62</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">source</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Table</span><span class="p">):</span>
</span><span id="qualify_tables-63"><a href="#qualify_tables-63"><span class="linenos">63</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">source</span><span class="o">.</span><span class="n">this</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Identifier</span><span class="p">):</span> </span><span id="qualify_tables-63"><a href="#qualify_tables-63"><span class="linenos"> 63</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">source</span><span class="o">.</span><span class="n">this</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Identifier</span><span class="p">):</span>
</span><span id="qualify_tables-64"><a href="#qualify_tables-64"><span class="linenos">64</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">source</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;db&quot;</span><span class="p">):</span> </span><span id="qualify_tables-64"><a href="#qualify_tables-64"><span class="linenos"> 64</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">source</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;db&quot;</span><span class="p">):</span>
</span><span id="qualify_tables-65"><a href="#qualify_tables-65"><span class="linenos">65</span></a> <span class="n">source</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;db&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">db</span><span class="p">))</span> </span><span id="qualify_tables-65"><a href="#qualify_tables-65"><span class="linenos"> 65</span></a> <span class="n">source</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;db&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">db</span><span class="p">))</span>
</span><span id="qualify_tables-66"><a href="#qualify_tables-66"><span class="linenos">66</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">source</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;catalog&quot;</span><span class="p">):</span> </span><span id="qualify_tables-66"><a href="#qualify_tables-66"><span class="linenos"> 66</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">source</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;catalog&quot;</span><span class="p">):</span>
</span><span id="qualify_tables-67"><a href="#qualify_tables-67"><span class="linenos">67</span></a> <span class="n">source</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;catalog&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">catalog</span><span class="p">))</span> </span><span id="qualify_tables-67"><a href="#qualify_tables-67"><span class="linenos"> 67</span></a> <span class="n">source</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;catalog&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">catalog</span><span class="p">))</span>
</span><span id="qualify_tables-68"><a href="#qualify_tables-68"><span class="linenos">68</span></a> </span><span id="qualify_tables-68"><a href="#qualify_tables-68"><span class="linenos"> 68</span></a>
</span><span id="qualify_tables-69"><a href="#qualify_tables-69"><span class="linenos">69</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">source</span><span class="o">.</span><span class="n">alias</span><span class="p">:</span> </span><span id="qualify_tables-69"><a href="#qualify_tables-69"><span class="linenos"> 69</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">source</span><span class="o">.</span><span class="n">alias</span><span class="p">:</span>
</span><span id="qualify_tables-70"><a href="#qualify_tables-70"><span class="linenos">70</span></a> <span class="c1"># Mutates the source by attaching an alias to it</span> </span><span id="qualify_tables-70"><a href="#qualify_tables-70"><span class="linenos"> 70</span></a> <span class="c1"># Mutates the source by attaching an alias to it</span>
</span><span id="qualify_tables-71"><a href="#qualify_tables-71"><span class="linenos">71</span></a> <span class="n">alias</span><span class="p">(</span><span class="n">source</span><span class="p">,</span> <span class="n">name</span> <span class="ow">or</span> <span class="n">source</span><span class="o">.</span><span class="n">name</span> <span class="ow">or</span> <span class="n">next_alias_name</span><span class="p">(),</span> <span class="n">copy</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">table</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> </span><span id="qualify_tables-71"><a href="#qualify_tables-71"><span class="linenos"> 71</span></a> <span class="n">alias</span><span class="p">(</span><span class="n">source</span><span class="p">,</span> <span class="n">name</span> <span class="ow">or</span> <span class="n">source</span><span class="o">.</span><span class="n">name</span> <span class="ow">or</span> <span class="n">next_alias_name</span><span class="p">(),</span> <span class="n">copy</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">table</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="qualify_tables-72"><a href="#qualify_tables-72"><span class="linenos">72</span></a> </span><span id="qualify_tables-72"><a href="#qualify_tables-72"><span class="linenos"> 72</span></a>
</span><span id="qualify_tables-73"><a href="#qualify_tables-73"><span class="linenos">73</span></a> <span class="n">pivots</span> <span class="o">=</span> <span class="n">source</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;pivots&quot;</span><span class="p">)</span> </span><span id="qualify_tables-73"><a href="#qualify_tables-73"><span class="linenos"> 73</span></a> <span class="n">pivots</span> <span class="o">=</span> <span class="n">source</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;pivots&quot;</span><span class="p">)</span>
</span><span id="qualify_tables-74"><a href="#qualify_tables-74"><span class="linenos">74</span></a> <span class="k">if</span> <span class="n">pivots</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">pivots</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">alias</span><span class="p">:</span> </span><span id="qualify_tables-74"><a href="#qualify_tables-74"><span class="linenos"> 74</span></a> <span class="k">if</span> <span class="n">pivots</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">pivots</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">alias</span><span class="p">:</span>
</span><span id="qualify_tables-75"><a href="#qualify_tables-75"><span class="linenos">75</span></a> <span class="n">pivots</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">set</span><span class="p">(</span> </span><span id="qualify_tables-75"><a href="#qualify_tables-75"><span class="linenos"> 75</span></a> <span class="n">pivots</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">set</span><span class="p">(</span>
</span><span id="qualify_tables-76"><a href="#qualify_tables-76"><span class="linenos">76</span></a> <span class="s2">&quot;alias&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">TableAlias</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">next_alias_name</span><span class="p">()))</span> </span><span id="qualify_tables-76"><a href="#qualify_tables-76"><span class="linenos"> 76</span></a> <span class="s2">&quot;alias&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">TableAlias</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">next_alias_name</span><span class="p">()))</span>
</span><span id="qualify_tables-77"><a href="#qualify_tables-77"><span class="linenos">77</span></a> <span class="p">)</span> </span><span id="qualify_tables-77"><a href="#qualify_tables-77"><span class="linenos"> 77</span></a> <span class="p">)</span>
</span><span id="qualify_tables-78"><a href="#qualify_tables-78"><span class="linenos">78</span></a> </span><span id="qualify_tables-78"><a href="#qualify_tables-78"><span class="linenos"> 78</span></a>
</span><span id="qualify_tables-79"><a href="#qualify_tables-79"><span class="linenos">79</span></a> <span class="k">if</span> <span class="n">schema</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">source</span><span class="o">.</span><span class="n">this</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">ReadCSV</span><span class="p">):</span> </span><span id="qualify_tables-79"><a href="#qualify_tables-79"><span class="linenos"> 79</span></a> <span class="k">if</span> <span class="n">schema</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">source</span><span class="o">.</span><span class="n">this</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">ReadCSV</span><span class="p">):</span>
</span><span id="qualify_tables-80"><a href="#qualify_tables-80"><span class="linenos">80</span></a> <span class="k">with</span> <span class="n">csv_reader</span><span class="p">(</span><span class="n">source</span><span class="o">.</span><span class="n">this</span><span class="p">)</span> <span class="k">as</span> <span class="n">reader</span><span class="p">:</span> </span><span id="qualify_tables-80"><a href="#qualify_tables-80"><span class="linenos"> 80</span></a> <span class="k">with</span> <span class="n">csv_reader</span><span class="p">(</span><span class="n">source</span><span class="o">.</span><span class="n">this</span><span class="p">)</span> <span class="k">as</span> <span class="n">reader</span><span class="p">:</span>
</span><span id="qualify_tables-81"><a href="#qualify_tables-81"><span class="linenos">81</span></a> <span class="n">header</span> <span class="o">=</span> <span class="nb">next</span><span class="p">(</span><span class="n">reader</span><span class="p">)</span> </span><span id="qualify_tables-81"><a href="#qualify_tables-81"><span class="linenos"> 81</span></a> <span class="n">header</span> <span class="o">=</span> <span class="nb">next</span><span class="p">(</span><span class="n">reader</span><span class="p">)</span>
</span><span id="qualify_tables-82"><a href="#qualify_tables-82"><span class="linenos">82</span></a> <span class="n">columns</span> <span class="o">=</span> <span class="nb">next</span><span class="p">(</span><span class="n">reader</span><span class="p">)</span> </span><span id="qualify_tables-82"><a href="#qualify_tables-82"><span class="linenos"> 82</span></a> <span class="n">columns</span> <span class="o">=</span> <span class="nb">next</span><span class="p">(</span><span class="n">reader</span><span class="p">)</span>
</span><span id="qualify_tables-83"><a href="#qualify_tables-83"><span class="linenos">83</span></a> <span class="n">schema</span><span class="o">.</span><span class="n">add_table</span><span class="p">(</span> </span><span id="qualify_tables-83"><a href="#qualify_tables-83"><span class="linenos"> 83</span></a> <span class="n">schema</span><span class="o">.</span><span class="n">add_table</span><span class="p">(</span>
</span><span id="qualify_tables-84"><a href="#qualify_tables-84"><span class="linenos">84</span></a> <span class="n">source</span><span class="p">,</span> <span class="p">{</span><span class="n">k</span><span class="p">:</span> <span class="nb">type</span><span class="p">(</span><span class="n">v</span><span class="p">)</span><span class="o">.</span><span class="vm">__name__</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">header</span><span class="p">,</span> <span class="n">columns</span><span class="p">)}</span> </span><span id="qualify_tables-84"><a href="#qualify_tables-84"><span class="linenos"> 84</span></a> <span class="n">source</span><span class="p">,</span>
</span><span id="qualify_tables-85"><a href="#qualify_tables-85"><span class="linenos">85</span></a> <span class="p">)</span> </span><span id="qualify_tables-85"><a href="#qualify_tables-85"><span class="linenos"> 85</span></a> <span class="p">{</span><span class="n">k</span><span class="p">:</span> <span class="nb">type</span><span class="p">(</span><span class="n">v</span><span class="p">)</span><span class="o">.</span><span class="vm">__name__</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">header</span><span class="p">,</span> <span class="n">columns</span><span class="p">)},</span>
</span><span id="qualify_tables-86"><a href="#qualify_tables-86"><span class="linenos">86</span></a> <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">source</span><span class="p">,</span> <span class="n">Scope</span><span class="p">)</span> <span class="ow">and</span> <span class="n">source</span><span class="o">.</span><span class="n">is_udtf</span><span class="p">:</span> </span><span id="qualify_tables-86"><a href="#qualify_tables-86"><span class="linenos"> 86</span></a> <span class="n">match_depth</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
</span><span id="qualify_tables-87"><a href="#qualify_tables-87"><span class="linenos">87</span></a> <span class="n">udtf</span> <span class="o">=</span> <span class="n">source</span><span class="o">.</span><span class="n">expression</span> </span><span id="qualify_tables-87"><a href="#qualify_tables-87"><span class="linenos"> 87</span></a> <span class="p">)</span>
</span><span id="qualify_tables-88"><a href="#qualify_tables-88"><span class="linenos">88</span></a> <span class="n">table_alias</span> <span class="o">=</span> <span class="n">udtf</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;alias&quot;</span><span class="p">)</span> <span class="ow">or</span> <span class="n">exp</span><span class="o">.</span><span class="n">TableAlias</span><span class="p">(</span> </span><span id="qualify_tables-88"><a href="#qualify_tables-88"><span class="linenos"> 88</span></a> <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">source</span><span class="p">,</span> <span class="n">Scope</span><span class="p">)</span> <span class="ow">and</span> <span class="n">source</span><span class="o">.</span><span class="n">is_udtf</span><span class="p">:</span>
</span><span id="qualify_tables-89"><a href="#qualify_tables-89"><span class="linenos">89</span></a> <span class="n">this</span><span class="o">=</span><span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">next_alias_name</span><span class="p">())</span> </span><span id="qualify_tables-89"><a href="#qualify_tables-89"><span class="linenos"> 89</span></a> <span class="n">udtf</span> <span class="o">=</span> <span class="n">source</span><span class="o">.</span><span class="n">expression</span>
</span><span id="qualify_tables-90"><a href="#qualify_tables-90"><span class="linenos">90</span></a> <span class="p">)</span> </span><span id="qualify_tables-90"><a href="#qualify_tables-90"><span class="linenos"> 90</span></a> <span class="n">table_alias</span> <span class="o">=</span> <span class="n">udtf</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;alias&quot;</span><span class="p">)</span> <span class="ow">or</span> <span class="n">exp</span><span class="o">.</span><span class="n">TableAlias</span><span class="p">(</span>
</span><span id="qualify_tables-91"><a href="#qualify_tables-91"><span class="linenos">91</span></a> <span class="n">udtf</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;alias&quot;</span><span class="p">,</span> <span class="n">table_alias</span><span class="p">)</span> </span><span id="qualify_tables-91"><a href="#qualify_tables-91"><span class="linenos"> 91</span></a> <span class="n">this</span><span class="o">=</span><span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">next_alias_name</span><span class="p">())</span>
</span><span id="qualify_tables-92"><a href="#qualify_tables-92"><span class="linenos">92</span></a> </span><span id="qualify_tables-92"><a href="#qualify_tables-92"><span class="linenos"> 92</span></a> <span class="p">)</span>
</span><span id="qualify_tables-93"><a href="#qualify_tables-93"><span class="linenos">93</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">table_alias</span><span class="o">.</span><span class="n">name</span><span class="p">:</span> </span><span id="qualify_tables-93"><a href="#qualify_tables-93"><span class="linenos"> 93</span></a> <span class="n">udtf</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;alias&quot;</span><span class="p">,</span> <span class="n">table_alias</span><span class="p">)</span>
</span><span id="qualify_tables-94"><a href="#qualify_tables-94"><span class="linenos">94</span></a> <span class="n">table_alias</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;this&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">next_alias_name</span><span class="p">()))</span> </span><span id="qualify_tables-94"><a href="#qualify_tables-94"><span class="linenos"> 94</span></a>
</span><span id="qualify_tables-95"><a href="#qualify_tables-95"><span class="linenos">95</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">udtf</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Values</span><span class="p">)</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">table_alias</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span> </span><span id="qualify_tables-95"><a href="#qualify_tables-95"><span class="linenos"> 95</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">table_alias</span><span class="o">.</span><span class="n">name</span><span class="p">:</span>
</span><span id="qualify_tables-96"><a href="#qualify_tables-96"><span class="linenos">96</span></a> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">e</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">udtf</span><span class="o">.</span><span class="n">expressions</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">expressions</span><span class="p">):</span> </span><span id="qualify_tables-96"><a href="#qualify_tables-96"><span class="linenos"> 96</span></a> <span class="n">table_alias</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&quot;this&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="n">next_alias_name</span><span class="p">()))</span>
</span><span id="qualify_tables-97"><a href="#qualify_tables-97"><span class="linenos">97</span></a> <span class="n">table_alias</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;columns&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;_col_</span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">))</span> </span><span id="qualify_tables-97"><a href="#qualify_tables-97"><span class="linenos"> 97</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">udtf</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Values</span><span class="p">)</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">table_alias</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span>
</span><span id="qualify_tables-98"><a href="#qualify_tables-98"><span class="linenos">98</span></a> </span><span id="qualify_tables-98"><a href="#qualify_tables-98"><span class="linenos"> 98</span></a> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">e</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">udtf</span><span class="o">.</span><span class="n">expressions</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">expressions</span><span class="p">):</span>
</span><span id="qualify_tables-99"><a href="#qualify_tables-99"><span class="linenos">99</span></a> <span class="k">return</span> <span class="n">expression</span> </span><span id="qualify_tables-99"><a href="#qualify_tables-99"><span class="linenos"> 99</span></a> <span class="n">table_alias</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;columns&quot;</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">to_identifier</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;_col_</span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">))</span>
</span><span id="qualify_tables-100"><a href="#qualify_tables-100"><span class="linenos">100</span></a>
</span><span id="qualify_tables-101"><a href="#qualify_tables-101"><span class="linenos">101</span></a> <span class="k">return</span> <span class="n">expression</span>
</span></pre></div> </span></pre></div>

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -67,19 +67,22 @@ schema = MappingSchema()
"""The default schema used by SQLGlot (e.g. in the optimizer).""" """The default schema used by SQLGlot (e.g. in the optimizer)."""
def parse(sql: str, read: DialectType = None, **opts) -> t.List[t.Optional[Expression]]: def parse(
sql: str, read: DialectType = None, dialect: DialectType = None, **opts
) -> t.List[t.Optional[Expression]]:
""" """
Parses the given SQL string into a collection of syntax trees, one per parsed SQL statement. Parses the given SQL string into a collection of syntax trees, one per parsed SQL statement.
Args: Args:
sql: the SQL code string to parse. sql: the SQL code string to parse.
read: the SQL dialect to apply during parsing (eg. "spark", "hive", "presto", "mysql"). read: the SQL dialect to apply during parsing (eg. "spark", "hive", "presto", "mysql").
dialect: the SQL dialect (alias for read).
**opts: other `sqlglot.parser.Parser` options. **opts: other `sqlglot.parser.Parser` options.
Returns: Returns:
The resulting syntax tree collection. The resulting syntax tree collection.
""" """
dialect = Dialect.get_or_raise(read)() dialect = Dialect.get_or_raise(read or dialect)()
return dialect.parse(sql, **opts) return dialect.parse(sql, **opts)

View file

@ -386,7 +386,7 @@ def input_file_name() -> Column:
def isnan(col: ColumnOrName) -> Column: def isnan(col: ColumnOrName) -> Column:
return Column.invoke_anonymous_function(col, "ISNAN") return Column.invoke_expression_over_column(col, expression.IsNan)
def isnull(col: ColumnOrName) -> Column: def isnull(col: ColumnOrName) -> Column:

View file

@ -211,6 +211,10 @@ class BigQuery(Dialect):
"TZH": "%z", "TZH": "%z",
} }
# The _PARTITIONTIME and _PARTITIONDATE pseudo-columns are not returned by a SELECT * statement
# https://cloud.google.com/bigquery/docs/querying-partitioned-tables#query_an_ingestion-time_partitioned_table
PSEUDOCOLUMNS = {"_PARTITIONTIME", "_PARTITIONDATE"}
@classmethod @classmethod
def normalize_identifier(cls, expression: E) -> E: def normalize_identifier(cls, expression: E) -> E:
# In BigQuery, CTEs aren't case-sensitive, but table names are (by default, at least). # In BigQuery, CTEs aren't case-sensitive, but table names are (by default, at least).

View file

@ -380,7 +380,7 @@ class ClickHouse(Dialect):
] ]
def parameterizedagg_sql(self, expression: exp.Anonymous) -> str: def parameterizedagg_sql(self, expression: exp.Anonymous) -> str:
params = self.expressions(expression, "params", flat=True) params = self.expressions(expression, key="params", flat=True)
return self.func(expression.name, *expression.expressions) + f"({params})" return self.func(expression.name, *expression.expressions) + f"({params})"
def placeholder_sql(self, expression: exp.Placeholder) -> str: def placeholder_sql(self, expression: exp.Placeholder) -> str:

View file

@ -5,6 +5,7 @@ from enum import Enum
from sqlglot import exp from sqlglot import exp
from sqlglot._typing import E from sqlglot._typing import E
from sqlglot.errors import ParseError
from sqlglot.generator import Generator from sqlglot.generator import Generator
from sqlglot.helper import flatten, seq_get from sqlglot.helper import flatten, seq_get
from sqlglot.parser import Parser from sqlglot.parser import Parser
@ -168,6 +169,10 @@ class Dialect(metaclass=_Dialect):
# special syntax cast(x as date format 'yyyy') defaults to time_mapping # special syntax cast(x as date format 'yyyy') defaults to time_mapping
FORMAT_MAPPING: t.Dict[str, str] = {} FORMAT_MAPPING: t.Dict[str, str] = {}
# Columns that are auto-generated by the engine corresponding to this dialect
# Such columns may be excluded from SELECT * queries, for example
PSEUDOCOLUMNS: t.Set[str] = set()
# Autofilled # Autofilled
tokenizer_class = Tokenizer tokenizer_class = Tokenizer
parser_class = Parser parser_class = Parser
@ -497,6 +502,10 @@ def parse_date_delta_with_interval(
return None return None
interval = args[1] interval = args[1]
if not isinstance(interval, exp.Interval):
raise ParseError(f"INTERVAL expression expected but got '{interval}'")
expression = interval.this expression = interval.this
if expression and expression.is_string: if expression and expression.is_string:
expression = exp.Literal.number(expression.this) expression = exp.Literal.number(expression.this)
@ -555,11 +564,11 @@ def right_to_substring_sql(self: Generator, expression: exp.Left) -> str:
def timestrtotime_sql(self: Generator, expression: exp.TimeStrToTime) -> str: def timestrtotime_sql(self: Generator, expression: exp.TimeStrToTime) -> str:
return f"CAST({self.sql(expression, 'this')} AS TIMESTAMP)" return self.sql(exp.cast(expression.this, "timestamp"))
def datestrtodate_sql(self: Generator, expression: exp.DateStrToDate) -> str: def datestrtodate_sql(self: Generator, expression: exp.DateStrToDate) -> str:
return f"CAST({self.sql(expression, 'this')} AS DATE)" return self.sql(exp.cast(expression.this, "date"))
def min_or_least(self: Generator, expression: exp.Min) -> str: def min_or_least(self: Generator, expression: exp.Min) -> str:
@ -608,8 +617,9 @@ def ts_or_ds_to_date_sql(dialect: str) -> t.Callable:
_dialect = Dialect.get_or_raise(dialect) _dialect = Dialect.get_or_raise(dialect)
time_format = self.format_time(expression) time_format = self.format_time(expression)
if time_format and time_format not in (_dialect.TIME_FORMAT, _dialect.DATE_FORMAT): if time_format and time_format not in (_dialect.TIME_FORMAT, _dialect.DATE_FORMAT):
return f"CAST({str_to_time_sql(self, expression)} AS DATE)" return self.sql(exp.cast(str_to_time_sql(self, expression), "date"))
return f"CAST({self.sql(expression, 'this')} AS DATE)"
return self.sql(exp.cast(self.sql(expression, "this"), "date"))
return _ts_or_ds_to_date_sql return _ts_or_ds_to_date_sql
@ -664,5 +674,15 @@ def pivot_column_names(aggregations: t.List[exp.Expression], dialect: DialectTyp
return names return names
def simplify_literal(expression: E, copy: bool = True) -> E:
if not isinstance(expression.expression, exp.Literal):
from sqlglot.optimizer.simplify import simplify
expression = exp.maybe_copy(expression, copy)
simplify(expression.expression)
return expression
def binary_from_function(expr_type: t.Type[B]) -> t.Callable[[t.List], B]: def binary_from_function(expr_type: t.Type[B]) -> t.Callable[[t.List], B]:
return lambda args: expr_type(this=seq_get(args, 0), expression=seq_get(args, 1)) return lambda args: expr_type(this=seq_get(args, 0), expression=seq_get(args, 1))

View file

@ -359,14 +359,16 @@ class Hive(Dialect):
TABLE_HINTS = False TABLE_HINTS = False
QUERY_HINTS = False QUERY_HINTS = False
INDEX_ON = "ON TABLE" INDEX_ON = "ON TABLE"
EXTRACT_ALLOWS_QUOTES = False
TYPE_MAPPING = { TYPE_MAPPING = {
**generator.Generator.TYPE_MAPPING, **generator.Generator.TYPE_MAPPING,
exp.DataType.Type.TEXT: "STRING",
exp.DataType.Type.DATETIME: "TIMESTAMP",
exp.DataType.Type.VARBINARY: "BINARY",
exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP",
exp.DataType.Type.BIT: "BOOLEAN", exp.DataType.Type.BIT: "BOOLEAN",
exp.DataType.Type.DATETIME: "TIMESTAMP",
exp.DataType.Type.TEXT: "STRING",
exp.DataType.Type.TIME: "TIMESTAMP",
exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP",
exp.DataType.Type.VARBINARY: "BINARY",
} }
TRANSFORMS = { TRANSFORMS = {
@ -396,6 +398,7 @@ class Hive(Dialect):
exp.FromBase64: rename_func("UNBASE64"), exp.FromBase64: rename_func("UNBASE64"),
exp.If: if_sql, exp.If: if_sql,
exp.ILike: no_ilike_sql, exp.ILike: no_ilike_sql,
exp.IsNan: rename_func("ISNAN"),
exp.JSONExtract: rename_func("GET_JSON_OBJECT"), exp.JSONExtract: rename_func("GET_JSON_OBJECT"),
exp.JSONExtractScalar: rename_func("GET_JSON_OBJECT"), exp.JSONExtractScalar: rename_func("GET_JSON_OBJECT"),
exp.JSONFormat: _json_format_sql, exp.JSONFormat: _json_format_sql,

View file

@ -18,6 +18,7 @@ from sqlglot.dialects.dialect import (
no_trycast_sql, no_trycast_sql,
parse_date_delta_with_interval, parse_date_delta_with_interval,
rename_func, rename_func,
simplify_literal,
strposition_to_locate_sql, strposition_to_locate_sql,
) )
from sqlglot.helper import seq_get from sqlglot.helper import seq_get
@ -303,6 +304,22 @@ class MySQL(Dialect):
"NAMES": lambda self: self._parse_set_item_names(), "NAMES": lambda self: self._parse_set_item_names(),
} }
CONSTRAINT_PARSERS = {
**parser.Parser.CONSTRAINT_PARSERS,
"FULLTEXT": lambda self: self._parse_index_constraint(kind="FULLTEXT"),
"INDEX": lambda self: self._parse_index_constraint(),
"KEY": lambda self: self._parse_index_constraint(),
"SPATIAL": lambda self: self._parse_index_constraint(kind="SPATIAL"),
}
SCHEMA_UNNAMED_CONSTRAINTS = {
*parser.Parser.SCHEMA_UNNAMED_CONSTRAINTS,
"FULLTEXT",
"INDEX",
"KEY",
"SPATIAL",
}
PROFILE_TYPES = { PROFILE_TYPES = {
"ALL", "ALL",
"BLOCK IO", "BLOCK IO",
@ -327,6 +344,57 @@ class MySQL(Dialect):
LOG_DEFAULTS_TO_LN = True LOG_DEFAULTS_TO_LN = True
def _parse_index_constraint(
self, kind: t.Optional[str] = None
) -> exp.IndexColumnConstraint:
if kind:
self._match_texts({"INDEX", "KEY"})
this = self._parse_id_var(any_token=False)
type_ = self._match(TokenType.USING) and self._advance_any() and self._prev.text
schema = self._parse_schema()
options = []
while True:
if self._match_text_seq("KEY_BLOCK_SIZE"):
self._match(TokenType.EQ)
opt = exp.IndexConstraintOption(key_block_size=self._parse_number())
elif self._match(TokenType.USING):
opt = exp.IndexConstraintOption(using=self._advance_any() and self._prev.text)
elif self._match_text_seq("WITH", "PARSER"):
opt = exp.IndexConstraintOption(parser=self._parse_var(any_token=True))
elif self._match(TokenType.COMMENT):
opt = exp.IndexConstraintOption(comment=self._parse_string())
elif self._match_text_seq("VISIBLE"):
opt = exp.IndexConstraintOption(visible=True)
elif self._match_text_seq("INVISIBLE"):
opt = exp.IndexConstraintOption(visible=False)
elif self._match_text_seq("ENGINE_ATTRIBUTE"):
self._match(TokenType.EQ)
opt = exp.IndexConstraintOption(engine_attr=self._parse_string())
elif self._match_text_seq("ENGINE_ATTRIBUTE"):
self._match(TokenType.EQ)
opt = exp.IndexConstraintOption(engine_attr=self._parse_string())
elif self._match_text_seq("SECONDARY_ENGINE_ATTRIBUTE"):
self._match(TokenType.EQ)
opt = exp.IndexConstraintOption(secondary_engine_attr=self._parse_string())
else:
opt = None
if not opt:
break
options.append(opt)
return self.expression(
exp.IndexColumnConstraint,
this=this,
schema=schema,
kind=kind,
type=type_,
options=options,
)
def _parse_show_mysql( def _parse_show_mysql(
self, self,
this: str, this: str,
@ -454,6 +522,7 @@ class MySQL(Dialect):
exp.StrToTime: _str_to_date_sql, exp.StrToTime: _str_to_date_sql,
exp.TableSample: no_tablesample_sql, exp.TableSample: no_tablesample_sql,
exp.TimeStrToUnix: rename_func("UNIX_TIMESTAMP"), exp.TimeStrToUnix: rename_func("UNIX_TIMESTAMP"),
exp.TimeStrToTime: lambda self, e: self.sql(exp.cast(e.this, "datetime")),
exp.TimeToStr: lambda self, e: self.func("DATE_FORMAT", e.this, self.format_time(e)), exp.TimeToStr: lambda self, e: self.func("DATE_FORMAT", e.this, self.format_time(e)),
exp.Trim: _trim_sql, exp.Trim: _trim_sql,
exp.TryCast: no_trycast_sql, exp.TryCast: no_trycast_sql,
@ -485,6 +554,16 @@ class MySQL(Dialect):
exp.DataType.Type.VARCHAR: "CHAR", exp.DataType.Type.VARCHAR: "CHAR",
} }
def limit_sql(self, expression: exp.Limit, top: bool = False) -> str:
# MySQL requires simple literal values for its LIMIT clause.
expression = simplify_literal(expression)
return super().limit_sql(expression, top=top)
def offset_sql(self, expression: exp.Offset) -> str:
# MySQL requires simple literal values for its OFFSET clause.
expression = simplify_literal(expression)
return super().offset_sql(expression)
def xor_sql(self, expression: exp.Xor) -> str: def xor_sql(self, expression: exp.Xor) -> str:
if expression.expressions: if expression.expressions:
return self.expressions(expression, sep=" XOR ") return self.expressions(expression, sep=" XOR ")

View file

@ -30,6 +30,9 @@ def _parse_xml_table(self: parser.Parser) -> exp.XMLTable:
class Oracle(Dialect): class Oracle(Dialect):
ALIAS_POST_TABLESAMPLE = True ALIAS_POST_TABLESAMPLE = True
# See section 8: https://docs.oracle.com/cd/A97630_01/server.920/a96540/sql_elements9a.htm
RESOLVES_IDENTIFIERS_AS_UPPERCASE = True
# https://docs.oracle.com/database/121/SQLRF/sql_elements004.htm#SQLRF00212 # https://docs.oracle.com/database/121/SQLRF/sql_elements004.htm#SQLRF00212
# https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes # https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
TIME_MAPPING = { TIME_MAPPING = {

View file

@ -17,6 +17,7 @@ from sqlglot.dialects.dialect import (
no_tablesample_sql, no_tablesample_sql,
no_trycast_sql, no_trycast_sql,
rename_func, rename_func,
simplify_literal,
str_position_sql, str_position_sql,
timestamptrunc_sql, timestamptrunc_sql,
timestrtotime_sql, timestrtotime_sql,
@ -39,16 +40,13 @@ DATE_DIFF_FACTOR = {
def _date_add_sql(kind: str) -> t.Callable[[generator.Generator, exp.DateAdd | exp.DateSub], str]: def _date_add_sql(kind: str) -> t.Callable[[generator.Generator, exp.DateAdd | exp.DateSub], str]:
def func(self: generator.Generator, expression: exp.DateAdd | exp.DateSub) -> str: def func(self: generator.Generator, expression: exp.DateAdd | exp.DateSub) -> str:
from sqlglot.optimizer.simplify import simplify
this = self.sql(expression, "this") this = self.sql(expression, "this")
unit = expression.args.get("unit") unit = expression.args.get("unit")
expression = simplify(expression.args["expression"])
expression = simplify_literal(expression.copy(), copy=False).expression
if not isinstance(expression, exp.Literal): if not isinstance(expression, exp.Literal):
self.unsupported("Cannot add non literal") self.unsupported("Cannot add non literal")
expression = expression.copy()
expression.args["is_string"] = True expression.args["is_string"] = True
return f"{this} {kind} {self.sql(exp.Interval(this=expression, unit=unit))}" return f"{this} {kind} {self.sql(exp.Interval(this=expression, unit=unit))}"

View file

@ -192,6 +192,8 @@ class Presto(Dialect):
"START": TokenType.BEGIN, "START": TokenType.BEGIN,
"MATCH_RECOGNIZE": TokenType.MATCH_RECOGNIZE, "MATCH_RECOGNIZE": TokenType.MATCH_RECOGNIZE,
"ROW": TokenType.STRUCT, "ROW": TokenType.STRUCT,
"IPADDRESS": TokenType.IPADDRESS,
"IPPREFIX": TokenType.IPPREFIX,
} }
class Parser(parser.Parser): class Parser(parser.Parser):

View file

@ -3,6 +3,7 @@ from __future__ import annotations
import typing as t import typing as t
from sqlglot import exp from sqlglot import exp
from sqlglot.dialects.dialect import rename_func
from sqlglot.dialects.spark2 import Spark2 from sqlglot.dialects.spark2 import Spark2
from sqlglot.helper import seq_get from sqlglot.helper import seq_get
@ -47,7 +48,11 @@ class Spark(Spark2):
exp.DataType.Type.SMALLMONEY: "DECIMAL(6, 4)", exp.DataType.Type.SMALLMONEY: "DECIMAL(6, 4)",
exp.DataType.Type.UNIQUEIDENTIFIER: "STRING", exp.DataType.Type.UNIQUEIDENTIFIER: "STRING",
} }
TRANSFORMS = Spark2.Generator.TRANSFORMS.copy()
TRANSFORMS = {
**Spark2.Generator.TRANSFORMS,
exp.StartsWith: rename_func("STARTSWITH"),
}
TRANSFORMS.pop(exp.DateDiff) TRANSFORMS.pop(exp.DateDiff)
TRANSFORMS.pop(exp.Group) TRANSFORMS.pop(exp.Group)

View file

@ -19,9 +19,13 @@ def _create_sql(self: Hive.Generator, e: exp.Create) -> str:
kind = e.args["kind"] kind = e.args["kind"]
properties = e.args.get("properties") properties = e.args.get("properties")
if kind.upper() == "TABLE" and any( if (
kind.upper() == "TABLE"
and e.expression
and any(
isinstance(prop, exp.TemporaryProperty) isinstance(prop, exp.TemporaryProperty)
for prop in (properties.expressions if properties else []) for prop in (properties.expressions if properties else [])
)
): ):
return f"CREATE TEMPORARY VIEW {self.sql(e, 'this')} AS {self.sql(e, 'expression')}" return f"CREATE TEMPORARY VIEW {self.sql(e, 'this')} AS {self.sql(e, 'expression')}"
return create_with_partitions_sql(self, e) return create_with_partitions_sql(self, e)

View file

@ -33,8 +33,10 @@ class Teradata(Dialect):
**tokens.Tokenizer.KEYWORDS, **tokens.Tokenizer.KEYWORDS,
"^=": TokenType.NEQ, "^=": TokenType.NEQ,
"BYTEINT": TokenType.SMALLINT, "BYTEINT": TokenType.SMALLINT,
"COLLECT": TokenType.COMMAND,
"GE": TokenType.GTE, "GE": TokenType.GTE,
"GT": TokenType.GT, "GT": TokenType.GT,
"HELP": TokenType.COMMAND,
"INS": TokenType.INSERT, "INS": TokenType.INSERT,
"LE": TokenType.LTE, "LE": TokenType.LTE,
"LT": TokenType.LT, "LT": TokenType.LT,

View file

@ -1,5 +1,6 @@
from __future__ import annotations from __future__ import annotations
import datetime
import re import re
import typing as t import typing as t
@ -10,6 +11,7 @@ from sqlglot.dialects.dialect import (
min_or_least, min_or_least,
parse_date_delta, parse_date_delta,
rename_func, rename_func,
timestrtotime_sql,
) )
from sqlglot.expressions import DataType from sqlglot.expressions import DataType
from sqlglot.helper import seq_get from sqlglot.helper import seq_get
@ -52,6 +54,8 @@ DATE_FMT_RE = re.compile("([dD]{1,2})|([mM]{1,2})|([yY]{1,4})|([hH]{1,2})|([sS]{
# N = Numeric, C=Currency # N = Numeric, C=Currency
TRANSPILE_SAFE_NUMBER_FMT = {"N", "C"} TRANSPILE_SAFE_NUMBER_FMT = {"N", "C"}
DEFAULT_START_DATE = datetime.date(1900, 1, 1)
def _format_time_lambda( def _format_time_lambda(
exp_class: t.Type[E], full_format_mapping: t.Optional[bool] = None exp_class: t.Type[E], full_format_mapping: t.Optional[bool] = None
@ -166,6 +170,34 @@ def _string_agg_sql(self: generator.Generator, expression: exp.GroupConcat) -> s
return f"STRING_AGG({self.format_args(this, separator)}){order}" return f"STRING_AGG({self.format_args(this, separator)}){order}"
def _parse_date_delta(
exp_class: t.Type[E], unit_mapping: t.Optional[t.Dict[str, str]] = None
) -> t.Callable[[t.List], E]:
def inner_func(args: t.List) -> E:
unit = seq_get(args, 0)
if unit and unit_mapping:
unit = exp.var(unit_mapping.get(unit.name.lower(), unit.name))
start_date = seq_get(args, 1)
if start_date and start_date.is_number:
# Numeric types are valid DATETIME values
if start_date.is_int:
adds = DEFAULT_START_DATE + datetime.timedelta(days=int(start_date.this))
start_date = exp.Literal.string(adds.strftime("%F"))
else:
# We currently don't handle float values, i.e. they're not converted to equivalent DATETIMEs.
# This is not a problem when generating T-SQL code, it is when transpiling to other dialects.
return exp_class(this=seq_get(args, 2), expression=start_date, unit=unit)
return exp_class(
this=exp.TimeStrToTime(this=seq_get(args, 2)),
expression=exp.TimeStrToTime(this=start_date),
unit=unit,
)
return inner_func
class TSQL(Dialect): class TSQL(Dialect):
RESOLVES_IDENTIFIERS_AS_UPPERCASE = None RESOLVES_IDENTIFIERS_AS_UPPERCASE = None
NULL_ORDERING = "nulls_are_small" NULL_ORDERING = "nulls_are_small"
@ -298,7 +330,6 @@ class TSQL(Dialect):
"SMALLDATETIME": TokenType.DATETIME, "SMALLDATETIME": TokenType.DATETIME,
"SMALLMONEY": TokenType.SMALLMONEY, "SMALLMONEY": TokenType.SMALLMONEY,
"SQL_VARIANT": TokenType.VARIANT, "SQL_VARIANT": TokenType.VARIANT,
"TIME": TokenType.TIMESTAMP,
"TOP": TokenType.TOP, "TOP": TokenType.TOP,
"UNIQUEIDENTIFIER": TokenType.UNIQUEIDENTIFIER, "UNIQUEIDENTIFIER": TokenType.UNIQUEIDENTIFIER,
"VARCHAR(MAX)": TokenType.TEXT, "VARCHAR(MAX)": TokenType.TEXT,
@ -307,10 +338,6 @@ class TSQL(Dialect):
"SYSTEM_USER": TokenType.CURRENT_USER, "SYSTEM_USER": TokenType.CURRENT_USER,
} }
# TSQL allows @, # to appear as a variable/identifier prefix
SINGLE_TOKENS = tokens.Tokenizer.SINGLE_TOKENS.copy()
SINGLE_TOKENS.pop("#")
class Parser(parser.Parser): class Parser(parser.Parser):
FUNCTIONS = { FUNCTIONS = {
**parser.Parser.FUNCTIONS, **parser.Parser.FUNCTIONS,
@ -320,7 +347,7 @@ class TSQL(Dialect):
position=seq_get(args, 2), position=seq_get(args, 2),
), ),
"DATEADD": parse_date_delta(exp.DateAdd, unit_mapping=DATE_DELTA_INTERVAL), "DATEADD": parse_date_delta(exp.DateAdd, unit_mapping=DATE_DELTA_INTERVAL),
"DATEDIFF": parse_date_delta(exp.DateDiff, unit_mapping=DATE_DELTA_INTERVAL), "DATEDIFF": _parse_date_delta(exp.DateDiff, unit_mapping=DATE_DELTA_INTERVAL),
"DATENAME": _format_time_lambda(exp.TimeToStr, full_format_mapping=True), "DATENAME": _format_time_lambda(exp.TimeToStr, full_format_mapping=True),
"DATEPART": _format_time_lambda(exp.TimeToStr), "DATEPART": _format_time_lambda(exp.TimeToStr),
"EOMONTH": _parse_eomonth, "EOMONTH": _parse_eomonth,
@ -518,6 +545,36 @@ class TSQL(Dialect):
expressions = self._parse_csv(self._parse_function_parameter) expressions = self._parse_csv(self._parse_function_parameter)
return self.expression(exp.UserDefinedFunction, this=this, expressions=expressions) return self.expression(exp.UserDefinedFunction, this=this, expressions=expressions)
def _parse_id_var(
self,
any_token: bool = True,
tokens: t.Optional[t.Collection[TokenType]] = None,
) -> t.Optional[exp.Expression]:
is_temporary = self._match(TokenType.HASH)
is_global = is_temporary and self._match(TokenType.HASH)
this = super()._parse_id_var(any_token=any_token, tokens=tokens)
if this:
if is_global:
this.set("global", True)
elif is_temporary:
this.set("temporary", True)
return this
def _parse_create(self) -> exp.Create | exp.Command:
create = super()._parse_create()
if isinstance(create, exp.Create):
table = create.this.this if isinstance(create.this, exp.Schema) else create.this
if isinstance(table, exp.Table) and table.this.args.get("temporary"):
if not create.args.get("properties"):
create.set("properties", exp.Properties(expressions=[]))
create.args["properties"].append("expressions", exp.TemporaryProperty())
return create
class Generator(generator.Generator): class Generator(generator.Generator):
LOCKING_READS_SUPPORTED = True LOCKING_READS_SUPPORTED = True
LIMIT_IS_TOP = True LIMIT_IS_TOP = True
@ -526,9 +583,11 @@ class TSQL(Dialect):
TYPE_MAPPING = { TYPE_MAPPING = {
**generator.Generator.TYPE_MAPPING, **generator.Generator.TYPE_MAPPING,
exp.DataType.Type.INT: "INTEGER",
exp.DataType.Type.DECIMAL: "NUMERIC", exp.DataType.Type.DECIMAL: "NUMERIC",
exp.DataType.Type.DATETIME: "DATETIME2", exp.DataType.Type.DATETIME: "DATETIME2",
exp.DataType.Type.INT: "INTEGER",
exp.DataType.Type.TIMESTAMP: "DATETIME2",
exp.DataType.Type.TIMESTAMPTZ: "DATETIMEOFFSET",
exp.DataType.Type.VARIANT: "SQL_VARIANT", exp.DataType.Type.VARIANT: "SQL_VARIANT",
} }
@ -552,6 +611,8 @@ class TSQL(Dialect):
exp.Literal.string(f"SHA2_{e.args.get('length', 256)}"), exp.Literal.string(f"SHA2_{e.args.get('length', 256)}"),
e.this, e.this,
), ),
exp.TemporaryProperty: lambda self, e: "",
exp.TimeStrToTime: timestrtotime_sql,
exp.TimeToStr: _format_sql, exp.TimeToStr: _format_sql,
} }
@ -564,6 +625,22 @@ class TSQL(Dialect):
LIMIT_FETCH = "FETCH" LIMIT_FETCH = "FETCH"
def createable_sql(
self,
expression: exp.Create,
locations: dict[exp.Properties.Location, list[exp.Property]],
) -> str:
sql = self.sql(expression, "this")
properties = expression.args.get("properties")
if sql[:1] != "#" and any(
isinstance(prop, exp.TemporaryProperty)
for prop in (properties.expressions if properties else [])
):
sql = f"#{sql}"
return sql
def offset_sql(self, expression: exp.Offset) -> str: def offset_sql(self, expression: exp.Offset) -> str:
return f"{super().offset_sql(expression)} ROWS" return f"{super().offset_sql(expression)} ROWS"
@ -616,3 +693,13 @@ class TSQL(Dialect):
this = self.sql(expression, "this") this = self.sql(expression, "this")
this = f" {this}" if this else "" this = f" {this}" if this else ""
return f"ROLLBACK TRANSACTION{this}" return f"ROLLBACK TRANSACTION{this}"
def identifier_sql(self, expression: exp.Identifier) -> str:
identifier = super().identifier_sql(expression)
if expression.args.get("global"):
identifier = f"##{identifier}"
elif expression.args.get("temporary"):
identifier = f"#{identifier}"
return identifier

View file

@ -67,8 +67,9 @@ class Expression(metaclass=_Expression):
uses to refer to it. uses to refer to it.
comments: a list of comments that are associated with a given expression. This is used in comments: a list of comments that are associated with a given expression. This is used in
order to preserve comments when transpiling SQL code. order to preserve comments when transpiling SQL code.
_type: the `sqlglot.expressions.DataType` type of an expression. This is inferred by the type: the `sqlglot.expressions.DataType` type of an expression. This is inferred by the
optimizer, in order to enable some transformations that require type information. optimizer, in order to enable some transformations that require type information.
meta: a dictionary that can be used to store useful metadata for a given expression.
Example: Example:
>>> class Foo(Expression): >>> class Foo(Expression):
@ -767,7 +768,7 @@ class Condition(Expression):
**opts, **opts,
) -> In: ) -> In:
return In( return In(
this=_maybe_copy(self, copy), this=maybe_copy(self, copy),
expressions=[convert(e, copy=copy) for e in expressions], expressions=[convert(e, copy=copy) for e in expressions],
query=maybe_parse(query, copy=copy, **opts) if query else None, query=maybe_parse(query, copy=copy, **opts) if query else None,
unnest=Unnest( unnest=Unnest(
@ -781,7 +782,7 @@ class Condition(Expression):
def between(self, low: t.Any, high: t.Any, copy: bool = True, **opts) -> Between: def between(self, low: t.Any, high: t.Any, copy: bool = True, **opts) -> Between:
return Between( return Between(
this=_maybe_copy(self, copy), this=maybe_copy(self, copy),
low=convert(low, copy=copy, **opts), low=convert(low, copy=copy, **opts),
high=convert(high, copy=copy, **opts), high=convert(high, copy=copy, **opts),
) )
@ -990,7 +991,28 @@ class Uncache(Expression):
arg_types = {"this": True, "exists": False} arg_types = {"this": True, "exists": False}
class Create(Expression): class DDL(Expression):
@property
def ctes(self):
with_ = self.args.get("with")
if not with_:
return []
return with_.expressions
@property
def named_selects(self) -> t.List[str]:
if isinstance(self.expression, Subqueryable):
return self.expression.named_selects
return []
@property
def selects(self) -> t.List[Expression]:
if isinstance(self.expression, Subqueryable):
return self.expression.selects
return []
class Create(DDL):
arg_types = { arg_types = {
"with": False, "with": False,
"this": True, "this": True,
@ -1206,6 +1228,19 @@ class MergeTreeTTL(Expression):
} }
# https://dev.mysql.com/doc/refman/8.0/en/create-table.html
class IndexConstraintOption(Expression):
arg_types = {
"key_block_size": False,
"using": False,
"parser": False,
"comment": False,
"visible": False,
"engine_attr": False,
"secondary_engine_attr": False,
}
class ColumnConstraint(Expression): class ColumnConstraint(Expression):
arg_types = {"this": False, "kind": True} arg_types = {"this": False, "kind": True}
@ -1272,6 +1307,11 @@ class GeneratedAsIdentityColumnConstraint(ColumnConstraintKind):
} }
# https://dev.mysql.com/doc/refman/8.0/en/create-table.html
class IndexColumnConstraint(ColumnConstraintKind):
arg_types = {"this": False, "schema": True, "kind": False, "type": False, "options": False}
class InlineLengthColumnConstraint(ColumnConstraintKind): class InlineLengthColumnConstraint(ColumnConstraintKind):
pass pass
@ -1496,7 +1536,7 @@ class JoinHint(Expression):
class Identifier(Expression): class Identifier(Expression):
arg_types = {"this": True, "quoted": False} arg_types = {"this": True, "quoted": False, "global": False, "temporary": False}
@property @property
def quoted(self) -> bool: def quoted(self) -> bool:
@ -1525,7 +1565,7 @@ class Index(Expression):
} }
class Insert(Expression): class Insert(DDL):
arg_types = { arg_types = {
"with": False, "with": False,
"this": True, "this": True,
@ -1892,6 +1932,10 @@ class EngineProperty(Property):
arg_types = {"this": True} arg_types = {"this": True}
class HeapProperty(Property):
arg_types = {}
class ToTableProperty(Property): class ToTableProperty(Property):
arg_types = {"this": True} arg_types = {"this": True}
@ -2182,7 +2226,7 @@ class Tuple(Expression):
**opts, **opts,
) -> In: ) -> In:
return In( return In(
this=_maybe_copy(self, copy), this=maybe_copy(self, copy),
expressions=[convert(e, copy=copy) for e in expressions], expressions=[convert(e, copy=copy) for e in expressions],
query=maybe_parse(query, copy=copy, **opts) if query else None, query=maybe_parse(query, copy=copy, **opts) if query else None,
unnest=Unnest( unnest=Unnest(
@ -2212,7 +2256,7 @@ class Subqueryable(Unionable):
Returns: Returns:
Alias: the subquery Alias: the subquery
""" """
instance = _maybe_copy(self, copy) instance = maybe_copy(self, copy)
if not isinstance(alias, Expression): if not isinstance(alias, Expression):
alias = TableAlias(this=to_identifier(alias)) if alias else None alias = TableAlias(this=to_identifier(alias)) if alias else None
@ -2865,7 +2909,7 @@ class Select(Subqueryable):
self, self,
expression: ExpOrStr, expression: ExpOrStr,
on: t.Optional[ExpOrStr] = None, on: t.Optional[ExpOrStr] = None,
using: t.Optional[ExpOrStr | t.List[ExpOrStr]] = None, using: t.Optional[ExpOrStr | t.Collection[ExpOrStr]] = None,
append: bool = True, append: bool = True,
join_type: t.Optional[str] = None, join_type: t.Optional[str] = None,
join_alias: t.Optional[Identifier | str] = None, join_alias: t.Optional[Identifier | str] = None,
@ -2943,6 +2987,7 @@ class Select(Subqueryable):
arg="using", arg="using",
append=append, append=append,
copy=copy, copy=copy,
into=Identifier,
**opts, **opts,
) )
@ -3092,7 +3137,7 @@ class Select(Subqueryable):
Returns: Returns:
Select: the modified expression. Select: the modified expression.
""" """
instance = _maybe_copy(self, copy) instance = maybe_copy(self, copy)
on = Tuple(expressions=[maybe_parse(on, copy=copy) for on in ons if on]) if ons else None on = Tuple(expressions=[maybe_parse(on, copy=copy) for on in ons if on]) if ons else None
instance.set("distinct", Distinct(on=on) if distinct else None) instance.set("distinct", Distinct(on=on) if distinct else None)
return instance return instance
@ -3123,7 +3168,7 @@ class Select(Subqueryable):
Returns: Returns:
The new Create expression. The new Create expression.
""" """
instance = _maybe_copy(self, copy) instance = maybe_copy(self, copy)
table_expression = maybe_parse( table_expression = maybe_parse(
table, table,
into=Table, into=Table,
@ -3159,7 +3204,7 @@ class Select(Subqueryable):
Returns: Returns:
The modified expression. The modified expression.
""" """
inst = _maybe_copy(self, copy) inst = maybe_copy(self, copy)
inst.set("locks", [Lock(update=update)]) inst.set("locks", [Lock(update=update)])
return inst return inst
@ -3181,7 +3226,7 @@ class Select(Subqueryable):
Returns: Returns:
The modified expression. The modified expression.
""" """
inst = _maybe_copy(self, copy) inst = maybe_copy(self, copy)
inst.set( inst.set(
"hint", Hint(expressions=[maybe_parse(h, copy=copy, dialect=dialect) for h in hints]) "hint", Hint(expressions=[maybe_parse(h, copy=copy, dialect=dialect) for h in hints])
) )
@ -3376,6 +3421,8 @@ class DataType(Expression):
HSTORE = auto() HSTORE = auto()
IMAGE = auto() IMAGE = auto()
INET = auto() INET = auto()
IPADDRESS = auto()
IPPREFIX = auto()
INT = auto() INT = auto()
INT128 = auto() INT128 = auto()
INT256 = auto() INT256 = auto()
@ -3987,7 +4034,7 @@ class Case(Func):
arg_types = {"this": False, "ifs": True, "default": False} arg_types = {"this": False, "ifs": True, "default": False}
def when(self, condition: ExpOrStr, then: ExpOrStr, copy: bool = True, **opts) -> Case: def when(self, condition: ExpOrStr, then: ExpOrStr, copy: bool = True, **opts) -> Case:
instance = _maybe_copy(self, copy) instance = maybe_copy(self, copy)
instance.append( instance.append(
"ifs", "ifs",
If( If(
@ -3998,7 +4045,7 @@ class Case(Func):
return instance return instance
def else_(self, condition: ExpOrStr, copy: bool = True, **opts) -> Case: def else_(self, condition: ExpOrStr, copy: bool = True, **opts) -> Case:
instance = _maybe_copy(self, copy) instance = maybe_copy(self, copy)
instance.set("default", maybe_parse(condition, copy=copy, **opts)) instance.set("default", maybe_parse(condition, copy=copy, **opts))
return instance return instance
@ -4263,6 +4310,10 @@ class Initcap(Func):
arg_types = {"this": True, "expression": False} arg_types = {"this": True, "expression": False}
class IsNan(Func):
_sql_names = ["IS_NAN", "ISNAN"]
class JSONKeyValue(Expression): class JSONKeyValue(Expression):
arg_types = {"this": True, "expression": True} arg_types = {"this": True, "expression": True}
@ -4549,6 +4600,11 @@ class StandardHash(Func):
arg_types = {"this": True, "expression": False} arg_types = {"this": True, "expression": False}
class StartsWith(Func):
_sql_names = ["STARTS_WITH", "STARTSWITH"]
arg_types = {"this": True, "expression": True}
class StrPosition(Func): class StrPosition(Func):
arg_types = { arg_types = {
"this": True, "this": True,
@ -4804,7 +4860,7 @@ def maybe_parse(
return sqlglot.parse_one(sql, read=dialect, into=into, **opts) return sqlglot.parse_one(sql, read=dialect, into=into, **opts)
def _maybe_copy(instance: E, copy: bool = True) -> E: def maybe_copy(instance: E, copy: bool = True) -> E:
return instance.copy() if copy else instance return instance.copy() if copy else instance
@ -4824,7 +4880,7 @@ def _apply_builder(
): ):
if _is_wrong_expression(expression, into): if _is_wrong_expression(expression, into):
expression = into(this=expression) expression = into(this=expression)
instance = _maybe_copy(instance, copy) instance = maybe_copy(instance, copy)
expression = maybe_parse( expression = maybe_parse(
sql_or_expression=expression, sql_or_expression=expression,
prefix=prefix, prefix=prefix,
@ -4848,7 +4904,7 @@ def _apply_child_list_builder(
properties=None, properties=None,
**opts, **opts,
): ):
instance = _maybe_copy(instance, copy) instance = maybe_copy(instance, copy)
parsed = [] parsed = []
for expression in expressions: for expression in expressions:
if expression is not None: if expression is not None:
@ -4887,7 +4943,7 @@ def _apply_list_builder(
dialect=None, dialect=None,
**opts, **opts,
): ):
inst = _maybe_copy(instance, copy) inst = maybe_copy(instance, copy)
expressions = [ expressions = [
maybe_parse( maybe_parse(
@ -4923,7 +4979,7 @@ def _apply_conjunction_builder(
if not expressions: if not expressions:
return instance return instance
inst = _maybe_copy(instance, copy) inst = maybe_copy(instance, copy)
existing = inst.args.get(arg) existing = inst.args.get(arg)
if append and existing is not None: if append and existing is not None:
@ -5398,7 +5454,7 @@ def to_identifier(name, quoted=None, copy=True):
return None return None
if isinstance(name, Identifier): if isinstance(name, Identifier):
identifier = _maybe_copy(name, copy) identifier = maybe_copy(name, copy)
elif isinstance(name, str): elif isinstance(name, str):
identifier = Identifier( identifier = Identifier(
this=name, this=name,
@ -5735,7 +5791,7 @@ def convert(value: t.Any, copy: bool = False) -> Expression:
Expression: the equivalent expression object. Expression: the equivalent expression object.
""" """
if isinstance(value, Expression): if isinstance(value, Expression):
return _maybe_copy(value, copy) return maybe_copy(value, copy)
if isinstance(value, str): if isinstance(value, str):
return Literal.string(value) return Literal.string(value)
if isinstance(value, bool): if isinstance(value, bool):

View file

@ -68,6 +68,7 @@ class Generator:
exp.EncodeColumnConstraint: lambda self, e: f"ENCODE {self.sql(e, 'this')}", exp.EncodeColumnConstraint: lambda self, e: f"ENCODE {self.sql(e, 'this')}",
exp.ExecuteAsProperty: lambda self, e: self.naked_property(e), exp.ExecuteAsProperty: lambda self, e: self.naked_property(e),
exp.ExternalProperty: lambda self, e: "EXTERNAL", exp.ExternalProperty: lambda self, e: "EXTERNAL",
exp.HeapProperty: lambda self, e: "HEAP",
exp.InlineLengthColumnConstraint: lambda self, e: f"INLINE LENGTH {self.sql(e, 'this')}", exp.InlineLengthColumnConstraint: lambda self, e: f"INLINE LENGTH {self.sql(e, 'this')}",
exp.LanguageProperty: lambda self, e: self.naked_property(e), exp.LanguageProperty: lambda self, e: self.naked_property(e),
exp.LocationProperty: lambda self, e: self.naked_property(e), exp.LocationProperty: lambda self, e: self.naked_property(e),
@ -161,6 +162,9 @@ class Generator:
# Whether or not to generate the (+) suffix for columns used in old-style join conditions # Whether or not to generate the (+) suffix for columns used in old-style join conditions
COLUMN_JOIN_MARKS_SUPPORTED = False COLUMN_JOIN_MARKS_SUPPORTED = False
# Whether or not to generate an unquoted value for EXTRACT's date part argument
EXTRACT_ALLOWS_QUOTES = True
# https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax # https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax
SELECT_KINDS: t.Tuple[str, ...] = ("STRUCT", "VALUE") SELECT_KINDS: t.Tuple[str, ...] = ("STRUCT", "VALUE")
@ -224,6 +228,7 @@ class Generator:
exp.FallbackProperty: exp.Properties.Location.POST_NAME, exp.FallbackProperty: exp.Properties.Location.POST_NAME,
exp.FileFormatProperty: exp.Properties.Location.POST_WITH, exp.FileFormatProperty: exp.Properties.Location.POST_WITH,
exp.FreespaceProperty: exp.Properties.Location.POST_NAME, exp.FreespaceProperty: exp.Properties.Location.POST_NAME,
exp.HeapProperty: exp.Properties.Location.POST_WITH,
exp.IsolatedLoadingProperty: exp.Properties.Location.POST_NAME, exp.IsolatedLoadingProperty: exp.Properties.Location.POST_NAME,
exp.JournalProperty: exp.Properties.Location.POST_NAME, exp.JournalProperty: exp.Properties.Location.POST_NAME,
exp.LanguageProperty: exp.Properties.Location.POST_SCHEMA, exp.LanguageProperty: exp.Properties.Location.POST_SCHEMA,
@ -265,9 +270,12 @@ class Generator:
# Expressions whose comments are separated from them for better formatting # Expressions whose comments are separated from them for better formatting
WITH_SEPARATED_COMMENTS: t.Tuple[t.Type[exp.Expression], ...] = ( WITH_SEPARATED_COMMENTS: t.Tuple[t.Type[exp.Expression], ...] = (
exp.Delete,
exp.Drop, exp.Drop,
exp.From, exp.From,
exp.Insert,
exp.Select, exp.Select,
exp.Update,
exp.Where, exp.Where,
exp.With, exp.With,
) )
@ -985,6 +993,7 @@ class Generator:
) -> str: ) -> str:
if properties.expressions: if properties.expressions:
expressions = self.expressions(properties, sep=sep, indent=False) expressions = self.expressions(properties, sep=sep, indent=False)
if expressions:
expressions = self.wrap(expressions) if wrapped else expressions expressions = self.wrap(expressions) if wrapped else expressions
return f"{prefix}{' ' if prefix and prefix != ' ' else ''}{expressions}{suffix}" return f"{prefix}{' ' if prefix and prefix != ' ' else ''}{expressions}{suffix}"
return "" return ""
@ -1905,7 +1914,7 @@ class Generator:
return f"NEXT VALUE FOR {self.sql(expression, 'this')}{order}" return f"NEXT VALUE FOR {self.sql(expression, 'this')}{order}"
def extract_sql(self, expression: exp.Extract) -> str: def extract_sql(self, expression: exp.Extract) -> str:
this = self.sql(expression, "this") this = self.sql(expression, "this") if self.EXTRACT_ALLOWS_QUOTES else expression.this.name
expression_sql = self.sql(expression, "expression") expression_sql = self.sql(expression, "expression")
return f"EXTRACT({this} FROM {expression_sql})" return f"EXTRACT({this} FROM {expression_sql})"
@ -2370,7 +2379,12 @@ class Generator:
elif arg_value is not None: elif arg_value is not None:
args.append(arg_value) args.append(arg_value)
return self.func(expression.sql_name(), *args) if self.normalize_functions:
name = expression.sql_name()
else:
name = (expression._meta and expression.meta.get("name")) or expression.sql_name()
return self.func(name, *args)
def func( def func(
self, self,
@ -2412,7 +2426,7 @@ class Generator:
return "" return ""
if flat: if flat:
return sep.join(self.sql(e) for e in expressions) return sep.join(sql for sql in (self.sql(e) for e in expressions) if sql)
num_sqls = len(expressions) num_sqls = len(expressions)
@ -2423,6 +2437,9 @@ class Generator:
result_sqls = [] result_sqls = []
for i, e in enumerate(expressions): for i, e in enumerate(expressions):
sql = self.sql(e, comment=False) sql = self.sql(e, comment=False)
if not sql:
continue
comments = self.maybe_comment("", e) if isinstance(e, exp.Expression) else "" comments = self.maybe_comment("", e) if isinstance(e, exp.Expression) else ""
if self.pretty: if self.pretty:
@ -2562,6 +2579,51 @@ class Generator:
record_reader = f" RECORDREADER {record_reader}" if record_reader else "" record_reader = f" RECORDREADER {record_reader}" if record_reader else ""
return f"{transform}{row_format_before}{record_writer}{using}{schema}{row_format_after}{record_reader}" return f"{transform}{row_format_before}{record_writer}{using}{schema}{row_format_after}{record_reader}"
def indexconstraintoption_sql(self, expression: exp.IndexConstraintOption) -> str:
key_block_size = self.sql(expression, "key_block_size")
if key_block_size:
return f"KEY_BLOCK_SIZE = {key_block_size}"
using = self.sql(expression, "using")
if using:
return f"USING {using}"
parser = self.sql(expression, "parser")
if parser:
return f"WITH PARSER {parser}"
comment = self.sql(expression, "comment")
if comment:
return f"COMMENT {comment}"
visible = expression.args.get("visible")
if visible is not None:
return "VISIBLE" if visible else "INVISIBLE"
engine_attr = self.sql(expression, "engine_attr")
if engine_attr:
return f"ENGINE_ATTRIBUTE = {engine_attr}"
secondary_engine_attr = self.sql(expression, "secondary_engine_attr")
if secondary_engine_attr:
return f"SECONDARY_ENGINE_ATTRIBUTE = {secondary_engine_attr}"
self.unsupported("Unsupported index constraint option.")
return ""
def indexcolumnconstraint_sql(self, expression: exp.IndexColumnConstraint) -> str:
kind = self.sql(expression, "kind")
kind = f"{kind} INDEX" if kind else "INDEX"
this = self.sql(expression, "this")
this = f" {this}" if this else ""
type_ = self.sql(expression, "type")
type_ = f" USING {type_}" if type_ else ""
schema = self.sql(expression, "schema")
schema = f" {schema}" if schema else ""
options = self.expressions(expression, key="options", sep=" ")
options = f" {options}" if options else ""
return f"{kind}{this}{type_}{schema}{options}"
def cached_generator( def cached_generator(
cache: t.Optional[t.Dict[int, str]] = None cache: t.Optional[t.Dict[int, str]] = None

View file

@ -136,8 +136,10 @@ def _eliminate_union(scope, existing_ctes, taken):
def _eliminate_derived_table(scope, existing_ctes, taken): def _eliminate_derived_table(scope, existing_ctes, taken):
# This ensures we don't drop the "pivot" arg from a pivoted subquery # This makes sure that we don't:
if scope.parent.pivots: # - drop the "pivot" arg from a pivoted subquery
# - eliminate a lateral correlated subquery
if scope.parent.pivots or isinstance(scope.parent.expression, exp.Lateral):
return None return None
parent = scope.expression.parent parent = scope.expression.parent

View file

@ -1,8 +1,23 @@
from __future__ import annotations
import typing as t
from sqlglot import exp
from sqlglot._typing import E from sqlglot._typing import E
from sqlglot.dialects.dialect import Dialect, DialectType from sqlglot.dialects.dialect import Dialect, DialectType
@t.overload
def normalize_identifiers(expression: E, dialect: DialectType = None) -> E: def normalize_identifiers(expression: E, dialect: DialectType = None) -> E:
...
@t.overload
def normalize_identifiers(expression: str, dialect: DialectType = None) -> exp.Expression:
...
def normalize_identifiers(expression, dialect=None):
""" """
Normalize all unquoted identifiers to either lower or upper case, depending Normalize all unquoted identifiers to either lower or upper case, depending
on the dialect. This essentially makes those identifiers case-insensitive. on the dialect. This essentially makes those identifiers case-insensitive.
@ -16,6 +31,8 @@ def normalize_identifiers(expression: E, dialect: DialectType = None) -> E:
>>> expression = sqlglot.parse_one('SELECT Bar.A AS A FROM "Foo".Bar') >>> expression = sqlglot.parse_one('SELECT Bar.A AS A FROM "Foo".Bar')
>>> normalize_identifiers(expression).sql() >>> normalize_identifiers(expression).sql()
'SELECT bar.a AS a FROM "Foo".bar' 'SELECT bar.a AS a FROM "Foo".bar'
>>> normalize_identifiers("foo", dialect="snowflake").sql(dialect="snowflake")
'FOO'
Args: Args:
expression: The expression to transform. expression: The expression to transform.
@ -24,4 +41,5 @@ def normalize_identifiers(expression: E, dialect: DialectType = None) -> E:
Returns: Returns:
The transformed expression. The transformed expression.
""" """
expression = exp.maybe_parse(expression, dialect=dialect)
return expression.transform(Dialect.get_or_raise(dialect).normalize_identifier, copy=False) return expression.transform(Dialect.get_or_raise(dialect).normalize_identifier, copy=False)

View file

@ -39,6 +39,7 @@ def qualify_columns(
""" """
schema = ensure_schema(schema) schema = ensure_schema(schema)
infer_schema = schema.empty if infer_schema is None else infer_schema infer_schema = schema.empty if infer_schema is None else infer_schema
pseudocolumns = Dialect.get_or_raise(schema.dialect).PSEUDOCOLUMNS
for scope in traverse_scope(expression): for scope in traverse_scope(expression):
resolver = Resolver(scope, schema, infer_schema=infer_schema) resolver = Resolver(scope, schema, infer_schema=infer_schema)
@ -55,7 +56,7 @@ def qualify_columns(
_expand_alias_refs(scope, resolver) _expand_alias_refs(scope, resolver)
if not isinstance(scope.expression, exp.UDTF): if not isinstance(scope.expression, exp.UDTF):
_expand_stars(scope, resolver, using_column_tables) _expand_stars(scope, resolver, using_column_tables, pseudocolumns)
_qualify_outputs(scope) _qualify_outputs(scope)
_expand_group_by(scope) _expand_group_by(scope)
_expand_order_by(scope, resolver) _expand_order_by(scope, resolver)
@ -326,7 +327,10 @@ def _qualify_columns(scope: Scope, resolver: Resolver) -> None:
def _expand_stars( def _expand_stars(
scope: Scope, resolver: Resolver, using_column_tables: t.Dict[str, t.Any] scope: Scope,
resolver: Resolver,
using_column_tables: t.Dict[str, t.Any],
pseudocolumns: t.Set[str],
) -> None: ) -> None:
"""Expand stars to lists of column selections""" """Expand stars to lists of column selections"""
@ -367,14 +371,8 @@ def _expand_stars(
columns = resolver.get_source_columns(table, only_visible=True) columns = resolver.get_source_columns(table, only_visible=True)
# The _PARTITIONTIME and _PARTITIONDATE pseudo-columns are not returned by a SELECT * statement if pseudocolumns:
# https://cloud.google.com/bigquery/docs/querying-partitioned-tables#query_an_ingestion-time_partitioned_table columns = [name for name in columns if name.upper() not in pseudocolumns]
if resolver.schema.dialect == "bigquery":
columns = [
name
for name in columns
if name.upper() not in ("_PARTITIONTIME", "_PARTITIONDATE")
]
if columns and "*" not in columns: if columns and "*" not in columns:
if pivot and has_pivoted_source and pivot_columns and pivot_output_columns: if pivot and has_pivoted_source and pivot_columns and pivot_output_columns:

View file

@ -80,7 +80,9 @@ def qualify_tables(
header = next(reader) header = next(reader)
columns = next(reader) columns = next(reader)
schema.add_table( schema.add_table(
source, {k: type(v).__name__ for k, v in zip(header, columns)} source,
{k: type(v).__name__ for k, v in zip(header, columns)},
match_depth=False,
) )
elif isinstance(source, Scope) and source.is_udtf: elif isinstance(source, Scope) and source.is_udtf:
udtf = source.expression udtf = source.expression

View file

@ -435,7 +435,10 @@ class Scope:
@property @property
def is_correlated_subquery(self): def is_correlated_subquery(self):
"""Determine if this scope is a correlated subquery""" """Determine if this scope is a correlated subquery"""
return bool(self.is_subquery and self.external_columns) return bool(
(self.is_subquery or (self.parent and isinstance(self.parent.expression, exp.Lateral)))
and self.external_columns
)
def rename_source(self, old_name, new_name): def rename_source(self, old_name, new_name):
"""Rename a source in this scope""" """Rename a source in this scope"""
@ -486,7 +489,7 @@ class Scope:
def traverse_scope(expression: exp.Expression) -> t.List[Scope]: def traverse_scope(expression: exp.Expression) -> t.List[Scope]:
""" """
Traverse an expression by it's "scopes". Traverse an expression by its "scopes".
"Scope" represents the current context of a Select statement. "Scope" represents the current context of a Select statement.
@ -509,10 +512,13 @@ def traverse_scope(expression: exp.Expression) -> t.List[Scope]:
Returns: Returns:
list[Scope]: scope instances list[Scope]: scope instances
""" """
if not isinstance(expression, exp.Unionable): if isinstance(expression, exp.Unionable) or (
return [] isinstance(expression, exp.DDL) and isinstance(expression.expression, exp.Subqueryable)
):
return list(_traverse_scope(Scope(expression))) return list(_traverse_scope(Scope(expression)))
return []
def build_scope(expression: exp.Expression) -> t.Optional[Scope]: def build_scope(expression: exp.Expression) -> t.Optional[Scope]:
""" """
@ -539,7 +545,9 @@ def _traverse_scope(scope):
elif isinstance(scope.expression, exp.Table): elif isinstance(scope.expression, exp.Table):
yield from _traverse_tables(scope) yield from _traverse_tables(scope)
elif isinstance(scope.expression, exp.UDTF): elif isinstance(scope.expression, exp.UDTF):
pass yield from _traverse_udtfs(scope)
elif isinstance(scope.expression, exp.DDL):
yield from _traverse_ddl(scope)
else: else:
logger.warning( logger.warning(
"Cannot traverse scope %s with type '%s'", scope.expression, type(scope.expression) "Cannot traverse scope %s with type '%s'", scope.expression, type(scope.expression)
@ -576,10 +584,10 @@ def _traverse_ctes(scope):
for cte in scope.ctes: for cte in scope.ctes:
recursive_scope = None recursive_scope = None
# if the scope is a recursive cte, it must be in the form of # if the scope is a recursive cte, it must be in the form of base_case UNION recursive.
# base_case UNION recursive. thus the recursive scope is the first # thus the recursive scope is the first section of the union.
# section of the union. with_ = scope.expression.args.get("with")
if scope.expression.args["with"].recursive: if with_ and with_.recursive:
union = cte.this union = cte.this
if isinstance(union, exp.Union): if isinstance(union, exp.Union):
@ -692,8 +700,7 @@ def _traverse_tables(scope):
# This shouldn't be a problem once qualify_columns runs, as it adds aliases on everything. # This shouldn't be a problem once qualify_columns runs, as it adds aliases on everything.
# Until then, this means that only a single, unaliased derived table is allowed (rather, # Until then, this means that only a single, unaliased derived table is allowed (rather,
# the latest one wins. # the latest one wins.
alias = expression.alias sources[expression.alias] = child_scope
sources[alias] = child_scope
# append the final child_scope yielded # append the final child_scope yielded
scopes.append(child_scope) scopes.append(child_scope)
@ -711,6 +718,47 @@ def _traverse_subqueries(scope):
scope.subquery_scopes.append(top) scope.subquery_scopes.append(top)
def _traverse_udtfs(scope):
if isinstance(scope.expression, exp.Unnest):
expressions = scope.expression.expressions
elif isinstance(scope.expression, exp.Lateral):
expressions = [scope.expression.this]
else:
expressions = []
sources = {}
for expression in expressions:
if isinstance(expression, exp.Subquery) and _is_derived_table(expression):
top = None
for child_scope in _traverse_scope(
scope.branch(
expression,
scope_type=ScopeType.DERIVED_TABLE,
outer_column_list=expression.alias_column_names,
)
):
yield child_scope
top = child_scope
sources[expression.alias] = child_scope
scope.derived_table_scopes.append(top)
scope.table_scopes.append(top)
scope.sources.update(sources)
def _traverse_ddl(scope):
yield from _traverse_ctes(scope)
query_scope = scope.branch(
scope.expression.expression, scope_type=ScopeType.DERIVED_TABLE, chain_sources=scope.sources
)
query_scope._collect()
query_scope._ctes = scope.ctes + query_scope._ctes
yield from _traverse_scope(query_scope)
def walk_in_scope(expression, bfs=True): def walk_in_scope(expression, bfs=True):
""" """
Returns a generator object which visits all nodes in the syntrax tree, stopping at Returns a generator object which visits all nodes in the syntrax tree, stopping at

View file

@ -46,20 +46,24 @@ def unnest(select, parent_select, next_alias_name):
if not predicate or parent_select is not predicate.parent_select: if not predicate or parent_select is not predicate.parent_select:
return return
# this subquery returns a scalar and can just be converted to a cross join # This subquery returns a scalar and can just be converted to a cross join
if not isinstance(predicate, (exp.In, exp.Any)): if not isinstance(predicate, (exp.In, exp.Any)):
having = predicate.find_ancestor(exp.Having)
column = exp.column(select.selects[0].alias_or_name, alias) column = exp.column(select.selects[0].alias_or_name, alias)
if having and having.parent_select is parent_select:
column = exp.Max(this=column)
_replace(select.parent, column)
parent_select.join( clause = predicate.find_ancestor(exp.Having, exp.Where, exp.Join)
select, clause_parent_select = clause.parent_select if clause else None
join_type="CROSS",
join_alias=alias, if (isinstance(clause, exp.Having) and clause_parent_select is parent_select) or (
copy=False, (not clause or clause_parent_select is not parent_select)
and (
parent_select.args.get("group")
or any(projection.find(exp.AggFunc) for projection in parent_select.selects)
) )
):
column = exp.Max(this=column)
_replace(select.parent, column)
parent_select.join(select, join_type="CROSS", join_alias=alias, copy=False)
return return
if select.find(exp.Limit, exp.Offset): if select.find(exp.Limit, exp.Offset):

View file

@ -185,6 +185,8 @@ class Parser(metaclass=_Parser):
TokenType.VARIANT, TokenType.VARIANT,
TokenType.OBJECT, TokenType.OBJECT,
TokenType.INET, TokenType.INET,
TokenType.IPADDRESS,
TokenType.IPPREFIX,
TokenType.ENUM, TokenType.ENUM,
*NESTED_TYPE_TOKENS, *NESTED_TYPE_TOKENS,
} }
@ -603,6 +605,7 @@ class Parser(metaclass=_Parser):
"FALLBACK": lambda self, **kwargs: self._parse_fallback(**kwargs), "FALLBACK": lambda self, **kwargs: self._parse_fallback(**kwargs),
"FORMAT": lambda self: self._parse_property_assignment(exp.FileFormatProperty), "FORMAT": lambda self: self._parse_property_assignment(exp.FileFormatProperty),
"FREESPACE": lambda self: self._parse_freespace(), "FREESPACE": lambda self: self._parse_freespace(),
"HEAP": lambda self: self.expression(exp.HeapProperty),
"IMMUTABLE": lambda self: self.expression( "IMMUTABLE": lambda self: self.expression(
exp.StabilityProperty, this=exp.Literal.string("IMMUTABLE") exp.StabilityProperty, this=exp.Literal.string("IMMUTABLE")
), ),
@ -832,6 +835,7 @@ class Parser(metaclass=_Parser):
UNNEST_COLUMN_ONLY: bool = False UNNEST_COLUMN_ONLY: bool = False
ALIAS_POST_TABLESAMPLE: bool = False ALIAS_POST_TABLESAMPLE: bool = False
STRICT_STRING_CONCAT = False STRICT_STRING_CONCAT = False
NORMALIZE_FUNCTIONS = "upper"
NULL_ORDERING: str = "nulls_are_small" NULL_ORDERING: str = "nulls_are_small"
SHOW_TRIE: t.Dict = {} SHOW_TRIE: t.Dict = {}
SET_TRIE: t.Dict = {} SET_TRIE: t.Dict = {}
@ -1187,7 +1191,7 @@ class Parser(metaclass=_Parser):
exists = self._parse_exists(not_=True) exists = self._parse_exists(not_=True)
this = None this = None
expression = None expression: t.Optional[exp.Expression] = None
indexes = None indexes = None
no_schema_binding = None no_schema_binding = None
begin = None begin = None
@ -1207,6 +1211,10 @@ class Parser(metaclass=_Parser):
extend_props(self._parse_properties()) extend_props(self._parse_properties())
self._match(TokenType.ALIAS) self._match(TokenType.ALIAS)
if self._match(TokenType.COMMAND):
expression = self._parse_as_command(self._prev)
else:
begin = self._match(TokenType.BEGIN) begin = self._match(TokenType.BEGIN)
return_ = self._match_text_seq("RETURN") return_ = self._match_text_seq("RETURN")
expression = self._parse_statement() expression = self._parse_statement()
@ -1692,6 +1700,7 @@ class Parser(metaclass=_Parser):
return self.expression(exp.Describe, this=this, kind=kind) return self.expression(exp.Describe, this=this, kind=kind)
def _parse_insert(self) -> exp.Insert: def _parse_insert(self) -> exp.Insert:
comments = ensure_list(self._prev_comments)
overwrite = self._match(TokenType.OVERWRITE) overwrite = self._match(TokenType.OVERWRITE)
ignore = self._match(TokenType.IGNORE) ignore = self._match(TokenType.IGNORE)
local = self._match_text_seq("LOCAL") local = self._match_text_seq("LOCAL")
@ -1709,6 +1718,7 @@ class Parser(metaclass=_Parser):
alternative = self._match_texts(self.INSERT_ALTERNATIVES) and self._prev.text alternative = self._match_texts(self.INSERT_ALTERNATIVES) and self._prev.text
self._match(TokenType.INTO) self._match(TokenType.INTO)
comments += ensure_list(self._prev_comments)
self._match(TokenType.TABLE) self._match(TokenType.TABLE)
this = self._parse_table(schema=True) this = self._parse_table(schema=True)
@ -1716,6 +1726,7 @@ class Parser(metaclass=_Parser):
return self.expression( return self.expression(
exp.Insert, exp.Insert,
comments=comments,
this=this, this=this,
exists=self._parse_exists(), exists=self._parse_exists(),
partition=self._parse_partition(), partition=self._parse_partition(),
@ -1840,6 +1851,7 @@ class Parser(metaclass=_Parser):
# This handles MySQL's "Multiple-Table Syntax" # This handles MySQL's "Multiple-Table Syntax"
# https://dev.mysql.com/doc/refman/8.0/en/delete.html # https://dev.mysql.com/doc/refman/8.0/en/delete.html
tables = None tables = None
comments = self._prev_comments
if not self._match(TokenType.FROM, advance=False): if not self._match(TokenType.FROM, advance=False):
tables = self._parse_csv(self._parse_table) or None tables = self._parse_csv(self._parse_table) or None
@ -1847,6 +1859,7 @@ class Parser(metaclass=_Parser):
return self.expression( return self.expression(
exp.Delete, exp.Delete,
comments=comments,
tables=tables, tables=tables,
this=self._match(TokenType.FROM) and self._parse_table(joins=True), this=self._match(TokenType.FROM) and self._parse_table(joins=True),
using=self._match(TokenType.USING) and self._parse_table(joins=True), using=self._match(TokenType.USING) and self._parse_table(joins=True),
@ -1856,11 +1869,13 @@ class Parser(metaclass=_Parser):
) )
def _parse_update(self) -> exp.Update: def _parse_update(self) -> exp.Update:
comments = self._prev_comments
this = self._parse_table(alias_tokens=self.UPDATE_ALIAS_TOKENS) this = self._parse_table(alias_tokens=self.UPDATE_ALIAS_TOKENS)
expressions = self._match(TokenType.SET) and self._parse_csv(self._parse_equality) expressions = self._match(TokenType.SET) and self._parse_csv(self._parse_equality)
returning = self._parse_returning() returning = self._parse_returning()
return self.expression( return self.expression(
exp.Update, exp.Update,
comments=comments,
**{ # type: ignore **{ # type: ignore
"this": this, "this": this,
"expressions": expressions, "expressions": expressions,
@ -2235,7 +2250,12 @@ class Parser(metaclass=_Parser):
return None return None
if not this: if not this:
this = self._parse_function() or self._parse_id_var(any_token=False) this = (
self._parse_unnest()
or self._parse_function()
or self._parse_id_var(any_token=False)
)
while self._match(TokenType.DOT): while self._match(TokenType.DOT):
this = exp.Dot( this = exp.Dot(
this=this, this=this,
@ -3341,7 +3361,10 @@ class Parser(metaclass=_Parser):
args = self._parse_csv(lambda: self._parse_lambda(alias=alias)) args = self._parse_csv(lambda: self._parse_lambda(alias=alias))
if function and not anonymous: if function and not anonymous:
this = self.validate_expression(function(args), args) func = self.validate_expression(function(args), args)
if not self.NORMALIZE_FUNCTIONS:
func.meta["name"] = this
this = func
else: else:
this = self.expression(exp.Anonymous, this=this, expressions=args) this = self.expression(exp.Anonymous, this=this, expressions=args)
@ -3842,13 +3865,11 @@ class Parser(metaclass=_Parser):
args = self._parse_csv(self._parse_conjunction) args = self._parse_csv(self._parse_conjunction)
index = self._index index = self._index
if not self._match(TokenType.R_PAREN): if not self._match(TokenType.R_PAREN) and args:
# postgres: STRING_AGG([DISTINCT] expression, separator [ORDER BY expression1 {ASC | DESC} [, ...]]) # postgres: STRING_AGG([DISTINCT] expression, separator [ORDER BY expression1 {ASC | DESC} [, ...]])
return self.expression( # bigquery: STRING_AGG([DISTINCT] expression [, separator] [ORDER BY key [{ASC | DESC}] [, ... ]] [LIMIT n])
exp.GroupConcat, args[-1] = self._parse_limit(this=self._parse_order(this=args[-1]))
this=seq_get(args, 0), return self.expression(exp.GroupConcat, this=args[0], separator=seq_get(args, 1))
separator=self._parse_order(this=seq_get(args, 1)),
)
# Checks if we can parse an order clause: WITHIN GROUP (ORDER BY <order_by_expression_list> [ASC | DESC]). # Checks if we can parse an order clause: WITHIN GROUP (ORDER BY <order_by_expression_list> [ASC | DESC]).
# This is done "manually", instead of letting _parse_window parse it into an exp.WithinGroup node, so that # This is done "manually", instead of letting _parse_window parse it into an exp.WithinGroup node, so that
@ -4172,7 +4193,7 @@ class Parser(metaclass=_Parser):
self._match_r_paren() self._match_r_paren()
return self.expression( window = self.expression(
exp.Window, exp.Window,
this=this, this=this,
partition_by=partition, partition_by=partition,
@ -4183,6 +4204,12 @@ class Parser(metaclass=_Parser):
first=first, first=first,
) )
# This covers Oracle's FIRST/LAST syntax: aggregate KEEP (...) OVER (...)
if self._match_set(self.WINDOW_BEFORE_PAREN_TOKENS, advance=False):
return self._parse_window(window, alias=alias)
return window
def _parse_window_spec(self) -> t.Dict[str, t.Optional[str | exp.Expression]]: def _parse_window_spec(self) -> t.Dict[str, t.Optional[str | exp.Expression]]:
self._match(TokenType.BETWEEN) self._match(TokenType.BETWEEN)
@ -4276,19 +4303,19 @@ class Parser(metaclass=_Parser):
def _parse_null(self) -> t.Optional[exp.Expression]: def _parse_null(self) -> t.Optional[exp.Expression]:
if self._match(TokenType.NULL): if self._match(TokenType.NULL):
return self.PRIMARY_PARSERS[TokenType.NULL](self, self._prev) return self.PRIMARY_PARSERS[TokenType.NULL](self, self._prev)
return None return self._parse_placeholder()
def _parse_boolean(self) -> t.Optional[exp.Expression]: def _parse_boolean(self) -> t.Optional[exp.Expression]:
if self._match(TokenType.TRUE): if self._match(TokenType.TRUE):
return self.PRIMARY_PARSERS[TokenType.TRUE](self, self._prev) return self.PRIMARY_PARSERS[TokenType.TRUE](self, self._prev)
if self._match(TokenType.FALSE): if self._match(TokenType.FALSE):
return self.PRIMARY_PARSERS[TokenType.FALSE](self, self._prev) return self.PRIMARY_PARSERS[TokenType.FALSE](self, self._prev)
return None return self._parse_placeholder()
def _parse_star(self) -> t.Optional[exp.Expression]: def _parse_star(self) -> t.Optional[exp.Expression]:
if self._match(TokenType.STAR): if self._match(TokenType.STAR):
return self.PRIMARY_PARSERS[TokenType.STAR](self, self._prev) return self.PRIMARY_PARSERS[TokenType.STAR](self, self._prev)
return None return self._parse_placeholder()
def _parse_parameter(self) -> exp.Parameter: def _parse_parameter(self) -> exp.Parameter:
wrapped = self._match(TokenType.L_BRACE) wrapped = self._match(TokenType.L_BRACE)

View file

@ -31,14 +31,19 @@ class Schema(abc.ABC):
table: exp.Table | str, table: exp.Table | str,
column_mapping: t.Optional[ColumnMapping] = None, column_mapping: t.Optional[ColumnMapping] = None,
dialect: DialectType = None, dialect: DialectType = None,
normalize: t.Optional[bool] = None,
match_depth: bool = True,
) -> None: ) -> None:
""" """
Register or update a table. Some implementing classes may require column information to also be provided. Register or update a table. Some implementing classes may require column information to also be provided.
The added table must have the necessary number of qualifiers in its path to match the schema's nesting level.
Args: Args:
table: the `Table` expression instance or string representing the table. table: the `Table` expression instance or string representing the table.
column_mapping: a column mapping that describes the structure of the table. column_mapping: a column mapping that describes the structure of the table.
dialect: the SQL dialect that will be used to parse `table` if it's a string. dialect: the SQL dialect that will be used to parse `table` if it's a string.
normalize: whether to normalize identifiers according to the dialect of interest.
match_depth: whether to enforce that the table must match the schema's depth or not.
""" """
@abc.abstractmethod @abc.abstractmethod
@ -47,6 +52,7 @@ class Schema(abc.ABC):
table: exp.Table | str, table: exp.Table | str,
only_visible: bool = False, only_visible: bool = False,
dialect: DialectType = None, dialect: DialectType = None,
normalize: t.Optional[bool] = None,
) -> t.List[str]: ) -> t.List[str]:
""" """
Get the column names for a table. Get the column names for a table.
@ -55,6 +61,7 @@ class Schema(abc.ABC):
table: the `Table` expression instance. table: the `Table` expression instance.
only_visible: whether to include invisible columns. only_visible: whether to include invisible columns.
dialect: the SQL dialect that will be used to parse `table` if it's a string. dialect: the SQL dialect that will be used to parse `table` if it's a string.
normalize: whether to normalize identifiers according to the dialect of interest.
Returns: Returns:
The list of column names. The list of column names.
@ -66,6 +73,7 @@ class Schema(abc.ABC):
table: exp.Table | str, table: exp.Table | str,
column: exp.Column, column: exp.Column,
dialect: DialectType = None, dialect: DialectType = None,
normalize: t.Optional[bool] = None,
) -> exp.DataType: ) -> exp.DataType:
""" """
Get the `sqlglot.exp.DataType` type of a column in the schema. Get the `sqlglot.exp.DataType` type of a column in the schema.
@ -74,6 +82,7 @@ class Schema(abc.ABC):
table: the source table. table: the source table.
column: the target column. column: the target column.
dialect: the SQL dialect that will be used to parse `table` if it's a string. dialect: the SQL dialect that will be used to parse `table` if it's a string.
normalize: whether to normalize identifiers according to the dialect of interest.
Returns: Returns:
The resulting column type. The resulting column type.
@ -99,7 +108,7 @@ class AbstractMappingSchema(t.Generic[T]):
) -> None: ) -> None:
self.mapping = mapping or {} self.mapping = mapping or {}
self.mapping_trie = new_trie( self.mapping_trie = new_trie(
tuple(reversed(t)) for t in flatten_schema(self.mapping, depth=self._depth()) tuple(reversed(t)) for t in flatten_schema(self.mapping, depth=self.depth())
) )
self._supported_table_args: t.Tuple[str, ...] = tuple() self._supported_table_args: t.Tuple[str, ...] = tuple()
@ -107,13 +116,13 @@ class AbstractMappingSchema(t.Generic[T]):
def empty(self) -> bool: def empty(self) -> bool:
return not self.mapping return not self.mapping
def _depth(self) -> int: def depth(self) -> int:
return dict_depth(self.mapping) return dict_depth(self.mapping)
@property @property
def supported_table_args(self) -> t.Tuple[str, ...]: def supported_table_args(self) -> t.Tuple[str, ...]:
if not self._supported_table_args and self.mapping: if not self._supported_table_args and self.mapping:
depth = self._depth() depth = self.depth()
if not depth: # None if not depth: # None
self._supported_table_args = tuple() self._supported_table_args = tuple()
@ -191,6 +200,7 @@ class MappingSchema(AbstractMappingSchema[t.Dict[str, str]], Schema):
self.visible = visible or {} self.visible = visible or {}
self.normalize = normalize self.normalize = normalize
self._type_mapping_cache: t.Dict[str, exp.DataType] = {} self._type_mapping_cache: t.Dict[str, exp.DataType] = {}
self._depth = 0
super().__init__(self._normalize(schema or {})) super().__init__(self._normalize(schema or {}))
@ -200,6 +210,7 @@ class MappingSchema(AbstractMappingSchema[t.Dict[str, str]], Schema):
schema=mapping_schema.mapping, schema=mapping_schema.mapping,
visible=mapping_schema.visible, visible=mapping_schema.visible,
dialect=mapping_schema.dialect, dialect=mapping_schema.dialect,
normalize=mapping_schema.normalize,
) )
def copy(self, **kwargs) -> MappingSchema: def copy(self, **kwargs) -> MappingSchema:
@ -208,6 +219,7 @@ class MappingSchema(AbstractMappingSchema[t.Dict[str, str]], Schema):
"schema": self.mapping.copy(), "schema": self.mapping.copy(),
"visible": self.visible.copy(), "visible": self.visible.copy(),
"dialect": self.dialect, "dialect": self.dialect,
"normalize": self.normalize,
**kwargs, **kwargs,
} }
) )
@ -217,19 +229,30 @@ class MappingSchema(AbstractMappingSchema[t.Dict[str, str]], Schema):
table: exp.Table | str, table: exp.Table | str,
column_mapping: t.Optional[ColumnMapping] = None, column_mapping: t.Optional[ColumnMapping] = None,
dialect: DialectType = None, dialect: DialectType = None,
normalize: t.Optional[bool] = None,
match_depth: bool = True,
) -> None: ) -> None:
""" """
Register or update a table. Updates are only performed if a new column mapping is provided. Register or update a table. Updates are only performed if a new column mapping is provided.
The added table must have the necessary number of qualifiers in its path to match the schema's nesting level.
Args: Args:
table: the `Table` expression instance or string representing the table. table: the `Table` expression instance or string representing the table.
column_mapping: a column mapping that describes the structure of the table. column_mapping: a column mapping that describes the structure of the table.
dialect: the SQL dialect that will be used to parse `table` if it's a string. dialect: the SQL dialect that will be used to parse `table` if it's a string.
normalize: whether to normalize identifiers according to the dialect of interest.
match_depth: whether to enforce that the table must match the schema's depth or not.
""" """
normalized_table = self._normalize_table(table, dialect=dialect) normalized_table = self._normalize_table(table, dialect=dialect, normalize=normalize)
if match_depth and not self.empty and len(normalized_table.parts) != self.depth():
raise SchemaError(
f"Table {normalized_table.sql(dialect=self.dialect)} must match the "
f"schema's nesting level: {self.depth()}."
)
normalized_column_mapping = { normalized_column_mapping = {
self._normalize_name(key, dialect=dialect): value self._normalize_name(key, dialect=dialect, normalize=normalize): value
for key, value in ensure_column_mapping(column_mapping).items() for key, value in ensure_column_mapping(column_mapping).items()
} }
@ -247,8 +270,9 @@ class MappingSchema(AbstractMappingSchema[t.Dict[str, str]], Schema):
table: exp.Table | str, table: exp.Table | str,
only_visible: bool = False, only_visible: bool = False,
dialect: DialectType = None, dialect: DialectType = None,
normalize: t.Optional[bool] = None,
) -> t.List[str]: ) -> t.List[str]:
normalized_table = self._normalize_table(table, dialect=dialect) normalized_table = self._normalize_table(table, dialect=dialect, normalize=normalize)
schema = self.find(normalized_table) schema = self.find(normalized_table)
if schema is None: if schema is None:
@ -265,11 +289,12 @@ class MappingSchema(AbstractMappingSchema[t.Dict[str, str]], Schema):
table: exp.Table | str, table: exp.Table | str,
column: exp.Column, column: exp.Column,
dialect: DialectType = None, dialect: DialectType = None,
normalize: t.Optional[bool] = None,
) -> exp.DataType: ) -> exp.DataType:
normalized_table = self._normalize_table(table, dialect=dialect) normalized_table = self._normalize_table(table, dialect=dialect, normalize=normalize)
normalized_column_name = self._normalize_name( normalized_column_name = self._normalize_name(
column if isinstance(column, str) else column.this, dialect=dialect column if isinstance(column, str) else column.this, dialect=dialect, normalize=normalize
) )
table_schema = self.find(normalized_table, raise_on_missing=False) table_schema = self.find(normalized_table, raise_on_missing=False)
@ -293,12 +318,16 @@ class MappingSchema(AbstractMappingSchema[t.Dict[str, str]], Schema):
Returns: Returns:
The normalized schema mapping. The normalized schema mapping.
""" """
normalized_mapping: t.Dict = {}
flattened_schema = flatten_schema(schema, depth=dict_depth(schema) - 1) flattened_schema = flatten_schema(schema, depth=dict_depth(schema) - 1)
normalized_mapping: t.Dict = {}
for keys in flattened_schema: for keys in flattened_schema:
columns = nested_get(schema, *zip(keys, keys)) columns = nested_get(schema, *zip(keys, keys))
assert columns is not None
if not isinstance(columns, dict):
raise SchemaError(
f"Table {'.'.join(keys[:-1])} must match the schema's nesting level: {len(flattened_schema[0])}."
)
normalized_keys = [ normalized_keys = [
self._normalize_name(key, dialect=self.dialect, is_table=True) for key in keys self._normalize_name(key, dialect=self.dialect, is_table=True) for key in keys
@ -312,7 +341,12 @@ class MappingSchema(AbstractMappingSchema[t.Dict[str, str]], Schema):
return normalized_mapping return normalized_mapping
def _normalize_table(self, table: exp.Table | str, dialect: DialectType = None) -> exp.Table: def _normalize_table(
self,
table: exp.Table | str,
dialect: DialectType = None,
normalize: t.Optional[bool] = None,
) -> exp.Table:
normalized_table = exp.maybe_parse( normalized_table = exp.maybe_parse(
table, into=exp.Table, dialect=dialect or self.dialect, copy=True table, into=exp.Table, dialect=dialect or self.dialect, copy=True
) )
@ -322,15 +356,24 @@ class MappingSchema(AbstractMappingSchema[t.Dict[str, str]], Schema):
if isinstance(value, (str, exp.Identifier)): if isinstance(value, (str, exp.Identifier)):
normalized_table.set( normalized_table.set(
arg, arg,
exp.to_identifier(self._normalize_name(value, dialect=dialect, is_table=True)), exp.to_identifier(
self._normalize_name(
value, dialect=dialect, is_table=True, normalize=normalize
)
),
) )
return normalized_table return normalized_table
def _normalize_name( def _normalize_name(
self, name: str | exp.Identifier, dialect: DialectType = None, is_table: bool = False self,
name: str | exp.Identifier,
dialect: DialectType = None,
is_table: bool = False,
normalize: t.Optional[bool] = None,
) -> str: ) -> str:
dialect = dialect or self.dialect dialect = dialect or self.dialect
normalize = self.normalize if normalize is None else normalize
try: try:
identifier = sqlglot.maybe_parse(name, dialect=dialect, into=exp.Identifier) identifier = sqlglot.maybe_parse(name, dialect=dialect, into=exp.Identifier)
@ -338,16 +381,18 @@ class MappingSchema(AbstractMappingSchema[t.Dict[str, str]], Schema):
return name if isinstance(name, str) else name.name return name if isinstance(name, str) else name.name
name = identifier.name name = identifier.name
if not self.normalize: if not normalize:
return name return name
# This can be useful for normalize_identifier # This can be useful for normalize_identifier
identifier.meta["is_table"] = is_table identifier.meta["is_table"] = is_table
return Dialect.get_or_raise(dialect).normalize_identifier(identifier).name return Dialect.get_or_raise(dialect).normalize_identifier(identifier).name
def _depth(self) -> int: def depth(self) -> int:
if not self.empty and not self._depth:
# The columns themselves are a mapping, but we don't want to include those # The columns themselves are a mapping, but we don't want to include those
return super()._depth() - 1 self._depth = super().depth() - 1
return self._depth
def _to_data_type(self, schema_type: str, dialect: DialectType = None) -> exp.DataType: def _to_data_type(self, schema_type: str, dialect: DialectType = None) -> exp.DataType:
""" """

View file

@ -147,6 +147,8 @@ class TokenType(AutoName):
VARIANT = auto() VARIANT = auto()
OBJECT = auto() OBJECT = auto()
INET = auto() INET = auto()
IPADDRESS = auto()
IPPREFIX = auto()
ENUM = auto() ENUM = auto()
# keywords # keywords

View file

@ -100,7 +100,8 @@ def eliminate_qualify(expression: exp.Expression) -> exp.Expression:
outer_selects = exp.select(*[select.alias_or_name for select in expression.selects]) outer_selects = exp.select(*[select.alias_or_name for select in expression.selects])
qualify_filters = expression.args["qualify"].pop().this qualify_filters = expression.args["qualify"].pop().this
for expr in qualify_filters.find_all((exp.Window, exp.Column)): select_candidates = exp.Window if expression.is_star else (exp.Window, exp.Column)
for expr in qualify_filters.find_all(select_candidates):
if isinstance(expr, exp.Window): if isinstance(expr, exp.Window):
alias = find_new_name(expression.named_selects, "_w") alias = find_new_name(expression.named_selects, "_w")
expression.select(exp.alias_(expr, alias), copy=False) expression.select(exp.alias_(expr, alias), copy=False)

View file

@ -29,6 +29,10 @@ class TestBigQuery(Validator):
with self.assertRaises(ParseError): with self.assertRaises(ParseError):
transpile("SELECT * FROM UNNEST(x) AS x(y)", read="bigquery") transpile("SELECT * FROM UNNEST(x) AS x(y)", read="bigquery")
with self.assertRaises(ParseError):
transpile("DATE_ADD(x, day)", read="bigquery")
self.validate_identity("STRING_AGG(DISTINCT a ORDER BY b DESC, c DESC LIMIT 10)")
self.validate_identity("SELECT PARSE_TIMESTAMP('%c', 'Thu Dec 25 07:30:00 2008', 'UTC')") self.validate_identity("SELECT PARSE_TIMESTAMP('%c', 'Thu Dec 25 07:30:00 2008', 'UTC')")
self.validate_identity("SELECT ANY_VALUE(fruit HAVING MAX sold) FROM fruits") self.validate_identity("SELECT ANY_VALUE(fruit HAVING MAX sold) FROM fruits")
self.validate_identity("SELECT ANY_VALUE(fruit HAVING MIN sold) FROM fruits") self.validate_identity("SELECT ANY_VALUE(fruit HAVING MIN sold) FROM fruits")
@ -389,7 +393,7 @@ class TestBigQuery(Validator):
}, },
) )
self.validate_all( self.validate_all(
"current_timestamp", "CURRENT_TIMESTAMP",
write={ write={
"bigquery": "CURRENT_TIMESTAMP()", "bigquery": "CURRENT_TIMESTAMP()",
"duckdb": "CURRENT_TIMESTAMP", "duckdb": "CURRENT_TIMESTAMP",
@ -400,7 +404,7 @@ class TestBigQuery(Validator):
}, },
) )
self.validate_all( self.validate_all(
"current_timestamp()", "CURRENT_TIMESTAMP()",
write={ write={
"bigquery": "CURRENT_TIMESTAMP()", "bigquery": "CURRENT_TIMESTAMP()",
"duckdb": "CURRENT_TIMESTAMP", "duckdb": "CURRENT_TIMESTAMP",

View file

@ -6,6 +6,12 @@ class TestClickhouse(Validator):
dialect = "clickhouse" dialect = "clickhouse"
def test_clickhouse(self): def test_clickhouse(self):
expr = parse_one("count(x)")
self.assertEqual(expr.sql(dialect="clickhouse"), "COUNT(x)")
self.assertIsNone(expr._meta)
self.validate_identity("SELECT isNaN(1.0)")
self.validate_identity("SELECT startsWith('Spider-Man', 'Spi')")
self.validate_identity("SELECT xor(TRUE, FALSE)") self.validate_identity("SELECT xor(TRUE, FALSE)")
self.validate_identity("ATTACH DATABASE DEFAULT ENGINE = ORDINARY") self.validate_identity("ATTACH DATABASE DEFAULT ENGINE = ORDINARY")
self.validate_identity("CAST(['hello'], 'Array(Enum8(''hello'' = 1))')") self.validate_identity("CAST(['hello'], 'Array(Enum8(''hello'' = 1))')")
@ -162,7 +168,7 @@ class TestClickhouse(Validator):
ORDER BY loyalty ASC ORDER BY loyalty ASC
""", """,
write={ write={
"clickhouse": "SELECT loyalty, COUNT() FROM hits LEFT SEMI JOIN users USING (UserID)" "clickhouse": "SELECT loyalty, count() FROM hits LEFT SEMI JOIN users USING (UserID)"
+ " GROUP BY loyalty ORDER BY loyalty" + " GROUP BY loyalty ORDER BY loyalty"
}, },
) )
@ -247,7 +253,7 @@ class TestClickhouse(Validator):
for data_type in data_types: for data_type in data_types:
self.validate_all( self.validate_all(
f"pow(2, 32)::{data_type}", f"pow(2, 32)::{data_type}",
write={"clickhouse": f"CAST(POWER(2, 32) AS {data_type})"}, write={"clickhouse": f"CAST(pow(2, 32) AS {data_type})"},
) )
def test_ddl(self): def test_ddl(self):
@ -304,8 +310,8 @@ GROUP BY
id, id,
toStartOfDay(timestamp) toStartOfDay(timestamp)
SET SET
max_hits = MAX(max_hits), max_hits = max(max_hits),
sum_hits = SUM(sum_hits)""", sum_hits = sum(sum_hits)""",
}, },
pretty=True, pretty=True,
) )
@ -447,8 +453,8 @@ GROUP BY
k1, k1,
k2 k2
SET SET
x = MAX(x), x = max(x),
y = MIN(y)""", y = min(y)""",
}, },
pretty=True, pretty=True,
) )

View file

@ -66,7 +66,7 @@ class TestDrill(Validator):
write={ write={
"drill": "SELECT * FROM (SELECT education_level, salary, marital_status, " "drill": "SELECT * FROM (SELECT education_level, salary, marital_status, "
"EXTRACT(year FROM age(birth_date)) AS age FROM cp.`employee.json`) " "EXTRACT(year FROM age(birth_date)) AS age FROM cp.`employee.json`) "
"PIVOT(AVG(salary) AS avg_salary, AVG(age) AS avg_age FOR marital_status " "PIVOT(avg(salary) AS avg_salary, avg(age) AS avg_age FOR marital_status "
"IN ('M' AS married, 'S' AS single))" "IN ('M' AS married, 'S' AS single))"
}, },
) )

View file

@ -9,6 +9,12 @@ class TestMySQL(Validator):
self.validate_identity("CREATE TABLE foo (id BIGINT)") self.validate_identity("CREATE TABLE foo (id BIGINT)")
self.validate_identity("UPDATE items SET items.price = 0 WHERE items.id >= 5 LIMIT 10") self.validate_identity("UPDATE items SET items.price = 0 WHERE items.id >= 5 LIMIT 10")
self.validate_identity("DELETE FROM t WHERE a <= 10 LIMIT 10") self.validate_identity("DELETE FROM t WHERE a <= 10 LIMIT 10")
self.validate_identity("CREATE TABLE foo (a BIGINT, INDEX USING BTREE (b))")
self.validate_identity("CREATE TABLE foo (a BIGINT, FULLTEXT INDEX (b))")
self.validate_identity("CREATE TABLE foo (a BIGINT, SPATIAL INDEX (b))")
self.validate_identity(
"CREATE TABLE foo (a BIGINT, INDEX b USING HASH (c) COMMENT 'd' VISIBLE ENGINE_ATTRIBUTE = 'e' WITH PARSER foo)"
)
self.validate_identity( self.validate_identity(
"DELETE t1 FROM t1 LEFT JOIN t2 ON t1.id = t2.id WHERE t2.id IS NULL" "DELETE t1 FROM t1 LEFT JOIN t2 ON t1.id = t2.id WHERE t2.id IS NULL"
) )
@ -67,6 +73,12 @@ class TestMySQL(Validator):
"mysql": "CREATE TABLE `foo` (`id` CHAR(36) NOT NULL DEFAULT (UUID()), PRIMARY KEY (`id`), UNIQUE `id` (`id`))", "mysql": "CREATE TABLE `foo` (`id` CHAR(36) NOT NULL DEFAULT (UUID()), PRIMARY KEY (`id`), UNIQUE `id` (`id`))",
}, },
) )
self.validate_all(
"CREATE TABLE IF NOT EXISTS industry_info (a BIGINT(20) NOT NULL AUTO_INCREMENT, b BIGINT(20) NOT NULL, c VARCHAR(1000), PRIMARY KEY (a), UNIQUE KEY d (b), KEY e (b))",
write={
"mysql": "CREATE TABLE IF NOT EXISTS industry_info (a BIGINT(20) NOT NULL AUTO_INCREMENT, b BIGINT(20) NOT NULL, c VARCHAR(1000), PRIMARY KEY (a), UNIQUE d (b), INDEX e (b))",
},
)
def test_identity(self): def test_identity(self):
self.validate_identity("SELECT 1 XOR 0") self.validate_identity("SELECT 1 XOR 0")
@ -436,6 +448,13 @@ class TestMySQL(Validator):
self.validate_identity("TIME_STR_TO_UNIX(x)", "UNIX_TIMESTAMP(x)") self.validate_identity("TIME_STR_TO_UNIX(x)", "UNIX_TIMESTAMP(x)")
def test_mysql(self): def test_mysql(self):
self.validate_all(
"SELECT * FROM test LIMIT 0 + 1, 0 + 1",
write={
"mysql": "SELECT * FROM test LIMIT 1 OFFSET 1",
"postgres": "SELECT * FROM test LIMIT 0 + 1 OFFSET 0 + 1",
},
)
self.validate_all( self.validate_all(
"CAST(x AS TEXT)", "CAST(x AS TEXT)",
write={ write={
@ -448,6 +467,7 @@ class TestMySQL(Validator):
self.validate_all("CAST(x AS SIGNED INTEGER)", write={"mysql": "CAST(x AS SIGNED)"}) self.validate_all("CAST(x AS SIGNED INTEGER)", write={"mysql": "CAST(x AS SIGNED)"})
self.validate_all("CAST(x AS UNSIGNED)", write={"mysql": "CAST(x AS UNSIGNED)"}) self.validate_all("CAST(x AS UNSIGNED)", write={"mysql": "CAST(x AS UNSIGNED)"})
self.validate_all("CAST(x AS UNSIGNED INTEGER)", write={"mysql": "CAST(x AS UNSIGNED)"}) self.validate_all("CAST(x AS UNSIGNED INTEGER)", write={"mysql": "CAST(x AS UNSIGNED)"})
self.validate_all("TIME_STR_TO_TIME(x)", write={"mysql": "CAST(x AS DATETIME)"})
self.validate_all( self.validate_all(
"""SELECT 17 MEMBER OF('[23, "abc", 17, "ab", 10]')""", """SELECT 17 MEMBER OF('[23, "abc", 17, "ab", 10]')""",
write={ write={

View file

@ -23,6 +23,11 @@ class TestOracle(Validator):
self.validate_identity( self.validate_identity(
"SELECT MIN(column_name) KEEP (DENSE_RANK FIRST ORDER BY column_name DESC) FROM table_name" "SELECT MIN(column_name) KEEP (DENSE_RANK FIRST ORDER BY column_name DESC) FROM table_name"
) )
self.validate_identity(
"SELECT last_name, department_id, salary, MIN(salary) KEEP (DENSE_RANK FIRST ORDER BY commission_pct) "
'OVER (PARTITION BY department_id) AS "Worst", MAX(salary) KEEP (DENSE_RANK LAST ORDER BY commission_pct) '
'OVER (PARTITION BY department_id) AS "Best" FROM employees ORDER BY department_id, salary, last_name'
)
self.validate_all( self.validate_all(
"NVL(NULL, 1)", "NVL(NULL, 1)",

View file

@ -122,6 +122,10 @@ class TestPostgres(Validator):
) )
def test_postgres(self): def test_postgres(self):
expr = parse_one("SELECT * FROM r CROSS JOIN LATERAL UNNEST(ARRAY[1]) AS s(location)")
unnest = expr.args["joins"][0].this.this
unnest.assert_is(exp.Unnest)
self.validate_identity("CAST(x AS MONEY)") self.validate_identity("CAST(x AS MONEY)")
self.validate_identity("CAST(x AS INT4RANGE)") self.validate_identity("CAST(x AS INT4RANGE)")
self.validate_identity("CAST(x AS INT4MULTIRANGE)") self.validate_identity("CAST(x AS INT4MULTIRANGE)")
@ -414,7 +418,7 @@ class TestPostgres(Validator):
}, },
) )
self.validate_all( self.validate_all(
"SELECT * FROM r CROSS JOIN LATERAL unnest(array(1)) AS s(location)", "SELECT * FROM r CROSS JOIN LATERAL UNNEST(ARRAY[1]) AS s(location)",
write={ write={
"postgres": "SELECT * FROM r CROSS JOIN LATERAL UNNEST(ARRAY[1]) AS s(location)", "postgres": "SELECT * FROM r CROSS JOIN LATERAL UNNEST(ARRAY[1]) AS s(location)",
}, },

View file

@ -109,6 +109,8 @@ class TestPresto(Validator):
"spark": "CAST(x AS TIMESTAMP)", "spark": "CAST(x AS TIMESTAMP)",
}, },
) )
self.validate_identity("CAST(x AS IPADDRESS)")
self.validate_identity("CAST(x AS IPPREFIX)")
def test_regex(self): def test_regex(self):
self.validate_all( self.validate_all(
@ -459,6 +461,25 @@ class TestPresto(Validator):
self.validate_identity("START TRANSACTION ISOLATION LEVEL REPEATABLE READ") self.validate_identity("START TRANSACTION ISOLATION LEVEL REPEATABLE READ")
self.validate_identity("APPROX_PERCENTILE(a, b, c, d)") self.validate_identity("APPROX_PERCENTILE(a, b, c, d)")
self.validate_all(
"STARTS_WITH('abc', 'a')",
read={"spark": "STARTSWITH('abc', 'a')"},
write={
"presto": "STARTS_WITH('abc', 'a')",
"spark": "STARTSWITH('abc', 'a')",
},
)
self.validate_all(
"IS_NAN(x)",
read={
"spark": "ISNAN(x)",
},
write={
"presto": "IS_NAN(x)",
"spark": "ISNAN(x)",
"spark2": "ISNAN(x)",
},
)
self.validate_all("VALUES 1, 2, 3", write={"presto": "VALUES (1), (2), (3)"}) self.validate_all("VALUES 1, 2, 3", write={"presto": "VALUES (1), (2), (3)"})
self.validate_all("INTERVAL '1 day'", write={"trino": "INTERVAL '1' day"}) self.validate_all("INTERVAL '1 day'", write={"trino": "INTERVAL '1' day"})
self.validate_all("(5 * INTERVAL '7' day)", read={"": "INTERVAL '5' week"}) self.validate_all("(5 * INTERVAL '7' day)", read={"": "INTERVAL '5' week"})

View file

@ -44,6 +44,14 @@ class TestSnowflake(Validator):
self.validate_all("CAST(x AS CHAR VARYING)", write={"snowflake": "CAST(x AS VARCHAR)"}) self.validate_all("CAST(x AS CHAR VARYING)", write={"snowflake": "CAST(x AS VARCHAR)"})
self.validate_all("CAST(x AS CHARACTER VARYING)", write={"snowflake": "CAST(x AS VARCHAR)"}) self.validate_all("CAST(x AS CHARACTER VARYING)", write={"snowflake": "CAST(x AS VARCHAR)"})
self.validate_all("CAST(x AS NCHAR VARYING)", write={"snowflake": "CAST(x AS VARCHAR)"}) self.validate_all("CAST(x AS NCHAR VARYING)", write={"snowflake": "CAST(x AS VARCHAR)"})
self.validate_all(
"SELECT DATE_PART('year', TIMESTAMP '2020-01-01')",
write={
"hive": "SELECT EXTRACT(year FROM CAST('2020-01-01' AS TIMESTAMP))",
"snowflake": "SELECT DATE_PART('year', CAST('2020-01-01' AS TIMESTAMPNTZ))",
"spark": "SELECT EXTRACT(year FROM CAST('2020-01-01' AS TIMESTAMP))",
},
)
self.validate_all( self.validate_all(
"SELECT * FROM (VALUES (0) foo(bar))", "SELECT * FROM (VALUES (0) foo(bar))",
write={"snowflake": "SELECT * FROM (VALUES (0)) AS foo(bar)"}, write={"snowflake": "SELECT * FROM (VALUES (0)) AS foo(bar)"},

View file

@ -22,6 +22,13 @@ class TestTeradata(Validator):
}, },
) )
def test_statistics(self):
self.validate_identity("COLLECT STATISTICS ON tbl INDEX(col)")
self.validate_identity("COLLECT STATS ON tbl COLUMNS(col)")
self.validate_identity("COLLECT STATS COLUMNS(col) ON tbl")
self.validate_identity("HELP STATISTICS personel.employee")
self.validate_identity("HELP STATISTICS personnel.employee FROM my_qcd")
def test_create(self): def test_create(self):
self.validate_identity("CREATE TABLE x (y INT) PRIMARY INDEX (y) PARTITION BY y INDEX (y)") self.validate_identity("CREATE TABLE x (y INT) PRIMARY INDEX (y) PARTITION BY y INDEX (y)")
self.validate_identity("CREATE TABLE x (y INT) PARTITION BY y INDEX (y)") self.validate_identity("CREATE TABLE x (y INT) PARTITION BY y INDEX (y)")

View file

@ -336,7 +336,7 @@ class TestTSQL(Validator):
"CAST(x as TIME(4))", "CAST(x as TIME(4))",
write={ write={
"spark": "CAST(x AS TIMESTAMP)", "spark": "CAST(x AS TIMESTAMP)",
"tsql": "CAST(x AS TIMESTAMP(4))", "tsql": "CAST(x AS TIME(4))",
}, },
) )
@ -352,7 +352,7 @@ class TestTSQL(Validator):
"CAST(x as DATETIMEOFFSET)", "CAST(x as DATETIMEOFFSET)",
write={ write={
"spark": "CAST(x AS TIMESTAMP)", "spark": "CAST(x AS TIMESTAMP)",
"tsql": "CAST(x AS TIMESTAMPTZ)", "tsql": "CAST(x AS DATETIMEOFFSET)",
}, },
) )
@ -393,7 +393,30 @@ class TestTSQL(Validator):
self.validate_all( self.validate_all(
"CREATE TABLE #mytemp (a INTEGER, b CHAR(2), c TIME(4), d FLOAT(24))", "CREATE TABLE #mytemp (a INTEGER, b CHAR(2), c TIME(4), d FLOAT(24))",
write={ write={
"tsql": "CREATE TABLE #mytemp (a INTEGER, b CHAR(2), c TIMESTAMP(4), d FLOAT(24))" "spark": "CREATE TEMPORARY TABLE mytemp (a INT, b CHAR(2), c TIMESTAMP, d FLOAT)",
"tsql": "CREATE TABLE #mytemp (a INTEGER, b CHAR(2), c TIME(4), d FLOAT(24))",
},
)
self.validate_all(
"CREATE TABLE #mytemptable (a INTEGER)",
read={
"duckdb": "CREATE TEMPORARY TABLE mytemptable (a INT)",
},
write={
"tsql": "CREATE TABLE #mytemptable (a INTEGER)",
"snowflake": "CREATE TEMPORARY TABLE mytemptable (a INT)",
"duckdb": "CREATE TEMPORARY TABLE mytemptable (a INT)",
"oracle": "CREATE TEMPORARY TABLE mytemptable (a NUMBER)",
},
)
self.validate_all(
"CREATE TABLE #mytemptable AS SELECT a FROM Source_Table",
write={
"duckdb": "CREATE TEMPORARY TABLE mytemptable AS SELECT a FROM Source_Table",
"oracle": "CREATE TEMPORARY TABLE mytemptable AS SELECT a FROM Source_Table",
"snowflake": "CREATE TEMPORARY TABLE mytemptable AS SELECT a FROM Source_Table",
"spark": "CREATE TEMPORARY VIEW mytemptable AS SELECT a FROM Source_Table",
"tsql": "CREATE TABLE #mytemptable AS SELECT a FROM Source_Table",
}, },
) )
@ -535,6 +558,30 @@ WHERE
for expr, expected_sql in zip(parse(sql, read="tsql"), expected_sqls): for expr, expected_sql in zip(parse(sql, read="tsql"), expected_sqls):
self.assertEqual(expr.sql(dialect="tsql"), expected_sql) self.assertEqual(expr.sql(dialect="tsql"), expected_sql)
sql = """
CREATE PROC [dbo].[transform_proc] AS
DECLARE @CurrentDate VARCHAR(20);
SET @CurrentDate = CONVERT(VARCHAR(20), GETDATE(), 120);
CREATE TABLE [target_schema].[target_table]
WITH (DISTRIBUTION = REPLICATE, HEAP)
AS
SELECT
@CurrentDate AS DWCreatedDate
FROM source_schema.sourcetable;
"""
expected_sqls = [
'CREATE PROC "dbo"."transform_proc" AS DECLARE @CurrentDate VARCHAR(20)',
"SET @CurrentDate = CAST(FORMAT(GETDATE(), 'yyyy-MM-dd HH:mm:ss') AS VARCHAR(20))",
'CREATE TABLE "target_schema"."target_table" WITH (DISTRIBUTION=REPLICATE, HEAP) AS SELECT @CurrentDate AS DWCreatedDate FROM source_schema.sourcetable',
]
for expr, expected_sql in zip(parse(sql, read="tsql"), expected_sqls):
self.assertEqual(expr.sql(dialect="tsql"), expected_sql)
def test_charindex(self): def test_charindex(self):
self.validate_all( self.validate_all(
"CHARINDEX(x, y, 9)", "CHARINDEX(x, y, 9)",
@ -795,31 +842,50 @@ WHERE
) )
def test_date_diff(self): def test_date_diff(self):
self.validate_identity("SELECT DATEDIFF(year, '2020/01/01', '2021/01/01')") self.validate_identity("SELECT DATEDIFF(hour, 1.5, '2021-01-01')")
self.validate_identity(
"SELECT DATEDIFF(year, '2020-01-01', '2021-01-01')",
"SELECT DATEDIFF(year, CAST('2020-01-01' AS DATETIME2), CAST('2021-01-01' AS DATETIME2))",
)
self.validate_all( self.validate_all(
"SELECT DATEDIFF(year, '2020/01/01', '2021/01/01')", "SELECT DATEDIFF(quarter, 0, '2021-01-01')",
write={ write={
"tsql": "SELECT DATEDIFF(year, '2020/01/01', '2021/01/01')", "tsql": "SELECT DATEDIFF(quarter, CAST('1900-01-01' AS DATETIME2), CAST('2021-01-01' AS DATETIME2))",
"spark": "SELECT DATEDIFF(year, '2020/01/01', '2021/01/01')", "spark": "SELECT DATEDIFF(quarter, CAST('1900-01-01' AS TIMESTAMP), CAST('2021-01-01' AS TIMESTAMP))",
"spark2": "SELECT MONTHS_BETWEEN('2021/01/01', '2020/01/01') / 12", "duckdb": "SELECT DATE_DIFF('quarter', CAST('1900-01-01' AS TIMESTAMP), CAST('2021-01-01' AS TIMESTAMP))",
}, },
) )
self.validate_all( self.validate_all(
"SELECT DATEDIFF(mm, 'start','end')", "SELECT DATEDIFF(day, 1, '2021-01-01')",
write={ write={
"databricks": "SELECT DATEDIFF(month, 'start', 'end')", "tsql": "SELECT DATEDIFF(day, CAST('1900-01-02' AS DATETIME2), CAST('2021-01-01' AS DATETIME2))",
"spark2": "SELECT MONTHS_BETWEEN('end', 'start')", "spark": "SELECT DATEDIFF(day, CAST('1900-01-02' AS TIMESTAMP), CAST('2021-01-01' AS TIMESTAMP))",
"tsql": "SELECT DATEDIFF(month, 'start', 'end')", "duckdb": "SELECT DATE_DIFF('day', CAST('1900-01-02' AS TIMESTAMP), CAST('2021-01-01' AS TIMESTAMP))",
},
)
self.validate_all(
"SELECT DATEDIFF(year, '2020/01/01', '2021/01/01')",
write={
"tsql": "SELECT DATEDIFF(year, CAST('2020/01/01' AS DATETIME2), CAST('2021/01/01' AS DATETIME2))",
"spark": "SELECT DATEDIFF(year, CAST('2020/01/01' AS TIMESTAMP), CAST('2021/01/01' AS TIMESTAMP))",
"spark2": "SELECT MONTHS_BETWEEN(CAST('2021/01/01' AS TIMESTAMP), CAST('2020/01/01' AS TIMESTAMP)) / 12",
},
)
self.validate_all(
"SELECT DATEDIFF(mm, 'start', 'end')",
write={
"databricks": "SELECT DATEDIFF(month, CAST('start' AS TIMESTAMP), CAST('end' AS TIMESTAMP))",
"spark2": "SELECT MONTHS_BETWEEN(CAST('end' AS TIMESTAMP), CAST('start' AS TIMESTAMP))",
"tsql": "SELECT DATEDIFF(month, CAST('start' AS DATETIME2), CAST('end' AS DATETIME2))",
}, },
) )
self.validate_all( self.validate_all(
"SELECT DATEDIFF(quarter, 'start', 'end')", "SELECT DATEDIFF(quarter, 'start', 'end')",
write={ write={
"databricks": "SELECT DATEDIFF(quarter, 'start', 'end')", "databricks": "SELECT DATEDIFF(quarter, CAST('start' AS TIMESTAMP), CAST('end' AS TIMESTAMP))",
"spark": "SELECT DATEDIFF(quarter, 'start', 'end')", "spark": "SELECT DATEDIFF(quarter, CAST('start' AS TIMESTAMP), CAST('end' AS TIMESTAMP))",
"spark2": "SELECT MONTHS_BETWEEN('end', 'start') / 3", "spark2": "SELECT MONTHS_BETWEEN(CAST('end' AS TIMESTAMP), CAST('start' AS TIMESTAMP)) / 3",
"tsql": "SELECT DATEDIFF(quarter, 'start', 'end')", "tsql": "SELECT DATEDIFF(quarter, CAST('start' AS DATETIME2), CAST('end' AS DATETIME2))",
}, },
) )
@ -943,8 +1009,15 @@ WHERE
expr = parse_one("#x", read="tsql") expr = parse_one("#x", read="tsql")
self.assertIsInstance(expr, exp.Column) self.assertIsInstance(expr, exp.Column)
self.assertIsInstance(expr.this, exp.Identifier) self.assertIsInstance(expr.this, exp.Identifier)
self.assertTrue(expr.this.args.get("temporary"))
self.assertEqual(expr.sql("tsql"), "#x") self.assertEqual(expr.sql("tsql"), "#x")
expr = parse_one("##x", read="tsql")
self.assertIsInstance(expr, exp.Column)
self.assertIsInstance(expr.this, exp.Identifier)
self.assertTrue(expr.this.args.get("global"))
self.assertEqual(expr.sql("tsql"), "##x")
expr = parse_one("@x", read="tsql") expr = parse_one("@x", read="tsql")
self.assertIsInstance(expr, exp.Parameter) self.assertIsInstance(expr, exp.Parameter)
self.assertIsInstance(expr.this, exp.Var) self.assertIsInstance(expr.this, exp.Var)
@ -955,6 +1028,24 @@ WHERE
self.assertIsInstance(table.this, exp.Parameter) self.assertIsInstance(table.this, exp.Parameter)
self.assertIsInstance(table.this.this, exp.Var) self.assertIsInstance(table.this.this, exp.Var)
def test_temp_table(self):
self.validate_all(
"SELECT * FROM #mytemptable",
write={
"duckdb": "SELECT * FROM mytemptable",
"spark": "SELECT * FROM mytemptable",
"tsql": "SELECT * FROM #mytemptable",
},
)
self.validate_all(
"SELECT * FROM ##mytemptable",
write={
"duckdb": "SELECT * FROM mytemptable",
"spark": "SELECT * FROM mytemptable",
"tsql": "SELECT * FROM ##mytemptable",
},
)
def test_system_time(self): def test_system_time(self):
self.validate_all( self.validate_all(
"SELECT [x] FROM [a].[b] FOR SYSTEM_TIME AS OF 'foo'", "SELECT [x] FROM [a].[b] FOR SYSTEM_TIME AS OF 'foo'",

View file

@ -730,6 +730,7 @@ WITH a AS (SELECT * FROM b) DELETE FROM a
WITH a AS (SELECT * FROM b) CACHE TABLE a WITH a AS (SELECT * FROM b) CACHE TABLE a
SELECT ? AS ? FROM x WHERE b BETWEEN ? AND ? GROUP BY ?, 1 LIMIT ? SELECT ? AS ? FROM x WHERE b BETWEEN ? AND ? GROUP BY ?, 1 LIMIT ?
SELECT :hello, ? FROM x LIMIT :my_limit SELECT :hello, ? FROM x LIMIT :my_limit
SELECT a FROM b WHERE c IS ?
SELECT * FROM x OFFSET @skip FETCH NEXT @take ROWS ONLY SELECT * FROM x OFFSET @skip FETCH NEXT @take ROWS ONLY
WITH a AS ((SELECT b.foo AS foo, b.bar AS bar FROM b) UNION ALL (SELECT c.foo AS foo, c.bar AS bar FROM c)) SELECT * FROM a WITH a AS ((SELECT b.foo AS foo, b.bar AS bar FROM b) UNION ALL (SELECT c.foo AS foo, c.bar AS bar FROM c)) SELECT * FROM a
WITH a AS ((SELECT 1 AS b) UNION ALL (SELECT 1 AS b)) SELECT * FROM a WITH a AS ((SELECT 1 AS b) UNION ALL (SELECT 1 AS b)) SELECT * FROM a
@ -848,3 +849,6 @@ SELECT * FROM current_date
SELECT * FROM schema.current_date SELECT * FROM schema.current_date
SELECT /*+ SOME_HINT(foo) */ 1 SELECT /*+ SOME_HINT(foo) */ 1
SELECT * FROM (tbl1 CROSS JOIN (SELECT * FROM tbl2) AS t1) SELECT * FROM (tbl1 CROSS JOIN (SELECT * FROM tbl2) AS t1)
/* comment1 */ INSERT INTO x /* comment2 */ VALUES (1, 2, 3)
/* comment1 */ UPDATE tbl /* comment2 */ SET x = 2 WHERE x < 2
/* comment1 */ DELETE FROM x /* comment2 */ WHERE y > 1

View file

@ -1,3 +1,10 @@
foo;
foo;
# dialect: snowflake
foo + "bar".baz;
FOO + "bar".BAZ;
SELECT a FROM x; SELECT a FROM x;
SELECT a FROM x; SELECT a FROM x;

View file

@ -638,7 +638,7 @@ SELECT
FROM "users" AS "u" FROM "users" AS "u"
CROSS JOIN LATERAL ( CROSS JOIN LATERAL (
SELECT SELECT
"l"."log_date" "l"."log_date" AS "log_date"
FROM "logs" AS "l" FROM "logs" AS "l"
WHERE WHERE
"l"."log_date" <= 100 AND "l"."user_id" = "u"."user_id" "l"."log_date" <= 100 AND "l"."user_id" = "u"."user_id"
@ -890,3 +890,20 @@ FROM (
JOIN "y" AS "y" JOIN "y" AS "y"
ON "x"."a" = "y"."c" ON "x"."a" = "y"."c"
); );
# title: replace scalar subquery, wrap resulting column in a MAX
SELECT a, SUM(c) / (SELECT SUM(c) FROM y) * 100 AS foo FROM y INNER JOIN x ON y.b = x.b GROUP BY a;
WITH "_u_0" AS (
SELECT
SUM("y"."c") AS "_col_0"
FROM "y" AS "y"
)
SELECT
"x"."a" AS "a",
SUM("y"."c") / MAX("_u_0"."_col_0") * 100 AS "foo"
FROM "y" AS "y"
CROSS JOIN "_u_0" AS "_u_0"
JOIN "x" AS "x"
ON "y"."b" = "x"."b"
GROUP BY
"x"."a";

View file

@ -93,6 +93,16 @@ SELECT 2 AS "2" FROM x AS x GROUP BY 1;
SELECT 'a' AS a FROM x GROUP BY 1; SELECT 'a' AS a FROM x GROUP BY 1;
SELECT 'a' AS a FROM x AS x GROUP BY 1; SELECT 'a' AS a FROM x AS x GROUP BY 1;
# execute: false
# dialect: oracle
SELECT t."col" FROM tbl t;
SELECT T."col" AS "col" FROM TBL T;
# execute: false
# dialect: oracle
WITH base AS (SELECT x.dummy AS COL_1 FROM dual x) SELECT b."COL_1" FROM base b;
WITH BASE AS (SELECT X.DUMMY AS COL_1 FROM DUAL X) SELECT B.COL_1 AS COL_1 FROM BASE B;
# execute: false # execute: false
-- this query seems to be invalid in postgres and duckdb but valid in bigquery -- this query seems to be invalid in postgres and duckdb but valid in bigquery
SELECT 2 a FROM x GROUP BY 1 HAVING a > 1; SELECT 2 a FROM x GROUP BY 1 HAVING a > 1;

View file

@ -0,0 +1,35 @@
# title: Create with CTE
WITH cte AS (SELECT b FROM y) CREATE TABLE s AS SELECT * FROM cte;
WITH cte AS (SELECT y.b AS b FROM y AS y) CREATE TABLE s AS SELECT cte.b AS b FROM cte;
# title: Create without CTE
CREATE TABLE foo AS SELECT a FROM tbl;
CREATE TABLE foo AS SELECT tbl.a AS a FROM tbl AS tbl;
# title: Create with complex CTE with derived table
WITH cte AS (SELECT a FROM (SELECT a from x)) CREATE TABLE s AS SELECT * FROM cte;
WITH cte AS (SELECT _q_0.a AS a FROM (SELECT x.a AS a FROM x AS x) AS _q_0) CREATE TABLE s AS SELECT cte.a AS a FROM cte;
# title: Create wtih multiple CTEs
WITH cte1 AS (SELECT b FROM y), cte2 AS (SELECT b FROM cte1) CREATE TABLE s AS SELECT * FROM cte2;
WITH cte1 AS (SELECT y.b AS b FROM y AS y), cte2 AS (SELECT cte1.b AS b FROM cte1) CREATE TABLE s AS SELECT cte2.b AS b FROM cte2;
# title: Create with multiple CTEs, selecting only from the first CTE (unnecessary code)
WITH cte1 AS (SELECT b FROM y), cte2 AS (SELECT b FROM cte1) CREATE TABLE s AS SELECT * FROM cte1;
WITH cte1 AS (SELECT y.b AS b FROM y AS y), cte2 AS (SELECT cte1.b AS b FROM cte1) CREATE TABLE s AS SELECT cte1.b AS b FROM cte1;
# title: Create with multiple derived tables
CREATE TABLE s AS SELECT * FROM (SELECT b FROM (SELECT b FROM y));
CREATE TABLE s AS SELECT _q_1.b AS b FROM (SELECT _q_0.b AS b FROM (SELECT y.b AS b FROM y AS y) AS _q_0) AS _q_1;
# title: Create with a CTE and a derived table
WITH cte AS (SELECT b FROM y) CREATE TABLE s AS SELECT * FROM (SELECT b FROM (SELECT b FROM cte));
WITH cte AS (SELECT y.b AS b FROM y AS y) CREATE TABLE s AS SELECT _q_1.b AS b FROM (SELECT _q_0.b AS b FROM (SELECT cte.b AS b FROM cte) AS _q_0) AS _q_1;
# title: Insert with CTE
WITH cte AS (SELECT b FROM y) INSERT INTO s SELECT * FROM cte;
WITH cte AS (SELECT y.b AS b FROM y AS y) INSERT INTO s SELECT cte.b AS b FROM cte;
# title: Insert without CTE
INSERT INTO foo SELECT a FROM tbl;
INSERT INTO foo SELECT tbl.a AS a FROM tbl AS tbl;

View file

@ -1449,11 +1449,31 @@ WITH "_u_0" AS (
"store_sales"."ss_quantity" <= 80 AND "store_sales"."ss_quantity" >= 61 "store_sales"."ss_quantity" <= 80 AND "store_sales"."ss_quantity" >= 61
) )
SELECT SELECT
CASE WHEN "_u_0"."_col_0" > 3672 THEN "_u_1"."_col_0" ELSE "_u_2"."_col_0" END AS "bucket1", CASE
CASE WHEN "_u_3"."_col_0" > 3392 THEN "_u_4"."_col_0" ELSE "_u_5"."_col_0" END AS "bucket2", WHEN MAX("_u_0"."_col_0") > 3672
CASE WHEN "_u_6"."_col_0" > 32784 THEN "_u_7"."_col_0" ELSE "_u_8"."_col_0" END AS "bucket3", THEN MAX("_u_1"."_col_0")
CASE WHEN "_u_9"."_col_0" > 26032 THEN "_u_10"."_col_0" ELSE "_u_11"."_col_0" END AS "bucket4", ELSE MAX("_u_2"."_col_0")
CASE WHEN "_u_12"."_col_0" > 23982 THEN "_u_13"."_col_0" ELSE "_u_14"."_col_0" END AS "bucket5" END AS "bucket1",
CASE
WHEN MAX("_u_3"."_col_0") > 3392
THEN MAX("_u_4"."_col_0")
ELSE MAX("_u_5"."_col_0")
END AS "bucket2",
CASE
WHEN MAX("_u_6"."_col_0") > 32784
THEN MAX("_u_7"."_col_0")
ELSE MAX("_u_8"."_col_0")
END AS "bucket3",
CASE
WHEN MAX("_u_9"."_col_0") > 26032
THEN MAX("_u_10"."_col_0")
ELSE MAX("_u_11"."_col_0")
END AS "bucket4",
CASE
WHEN MAX("_u_12"."_col_0") > 23982
THEN MAX("_u_13"."_col_0")
ELSE MAX("_u_14"."_col_0")
END AS "bucket5"
FROM "reason" AS "reason" FROM "reason" AS "reason"
CROSS JOIN "_u_0" AS "_u_0" CROSS JOIN "_u_0" AS "_u_0"
CROSS JOIN "_u_1" AS "_u_1" CROSS JOIN "_u_1" AS "_u_1"

View file

@ -242,7 +242,10 @@ class TestOptimizer(unittest.TestCase):
"CREATE FUNCTION `udfs`.`myTest`(`x` FLOAT64) AS (1)", "CREATE FUNCTION `udfs`.`myTest`(`x` FLOAT64) AS (1)",
) )
self.check_file("qualify_columns", qualify_columns, execute=True, schema=self.schema) self.check_file(
"qualify_columns", qualify_columns, execute=True, schema=self.schema, set_dialect=True
)
self.check_file("qualify_columns_ddl", qualify_columns, schema=self.schema)
def test_qualify_columns__with_invisible(self): def test_qualify_columns__with_invisible(self):
schema = MappingSchema(self.schema, {"x": {"a"}, "y": {"b"}, "z": {"b"}}) schema = MappingSchema(self.schema, {"x": {"a"}, "y": {"b"}, "z": {"b"}})
@ -448,6 +451,23 @@ FROM READ_CSV('tests/fixtures/optimizer/tpc-h/nation.csv.gz', 'delimiter', '|')
) )
self.assertEqual(set(scopes[3].sources), {""}) self.assertEqual(set(scopes[3].sources), {""})
inner_query = "SELECT bar FROM baz"
for udtf in (f"UNNEST(({inner_query}))", f"LATERAL ({inner_query})"):
sql = f"SELECT a FROM foo CROSS JOIN {udtf}"
expression = parse_one(sql)
for scopes in traverse_scope(expression), list(build_scope(expression).traverse()):
self.assertEqual(len(scopes), 3)
self.assertEqual(scopes[0].expression.sql(), inner_query)
self.assertEqual(set(scopes[0].sources), {"baz"})
self.assertEqual(scopes[1].expression.sql(), udtf)
self.assertEqual(set(scopes[1].sources), {"", "foo"}) # foo is a lateral source
self.assertEqual(scopes[2].expression.sql(), f"SELECT a FROM foo CROSS JOIN {udtf}")
self.assertEqual(set(scopes[2].sources), {"", "foo"})
@patch("sqlglot.optimizer.scope.logger") @patch("sqlglot.optimizer.scope.logger")
def test_scope_warning(self, logger): def test_scope_warning(self, logger):
self.assertEqual(len(traverse_scope(parse_one("WITH q AS (@y) SELECT * FROM q"))), 1) self.assertEqual(len(traverse_scope(parse_one("WITH q AS (@y) SELECT * FROM q"))), 1)

View file

@ -253,7 +253,7 @@ class TestParser(unittest.TestCase):
self.assertIsInstance(parse_one("INTERVAL '1' DAY").args["unit"], exp.Var) self.assertIsInstance(parse_one("INTERVAL '1' DAY").args["unit"], exp.Var)
self.assertEqual(parse_one("SELECT @JOIN, @'foo'").sql(), "SELECT @JOIN, @'foo'") self.assertEqual(parse_one("SELECT @JOIN, @'foo'").sql(), "SELECT @JOIN, @'foo'")
def test_comments(self): def test_comments_select(self):
expression = parse_one( expression = parse_one(
""" """
--comment1.1 --comment1.1
@ -277,6 +277,120 @@ class TestParser(unittest.TestCase):
self.assertEqual(expression.expressions[4].comments, [""]) self.assertEqual(expression.expressions[4].comments, [""])
self.assertEqual(expression.expressions[5].comments, [" space"]) self.assertEqual(expression.expressions[5].comments, [" space"])
def test_comments_select_cte(self):
expression = parse_one(
"""
/*comment1.1*/
/*comment1.2*/
WITH a AS (SELECT 1)
SELECT /*comment2*/
a.*
FROM /*comment3*/
a
"""
)
self.assertEqual(expression.comments, ["comment2"])
self.assertEqual(expression.args.get("from").comments, ["comment3"])
self.assertEqual(expression.args.get("with").comments, ["comment1.1", "comment1.2"])
def test_comments_insert(self):
expression = parse_one(
"""
--comment1.1
--comment1.2
INSERT INTO /*comment1.3*/
x /*comment2*/
VALUES /*comment3*/
(1, 'a', 2.0)
"""
)
self.assertEqual(expression.comments, ["comment1.1", "comment1.2", "comment1.3"])
self.assertEqual(expression.this.comments, ["comment2"])
def test_comments_insert_cte(self):
expression = parse_one(
"""
/*comment1.1*/
/*comment1.2*/
WITH a AS (SELECT 1)
INSERT INTO /*comment2*/
b /*comment3*/
SELECT * FROM a
"""
)
self.assertEqual(expression.comments, ["comment2"])
self.assertEqual(expression.this.comments, ["comment3"])
self.assertEqual(expression.args.get("with").comments, ["comment1.1", "comment1.2"])
def test_comments_update(self):
expression = parse_one(
"""
--comment1.1
--comment1.2
UPDATE /*comment1.3*/
tbl /*comment2*/
SET /*comment3*/
x = 2
WHERE /*comment4*/
x <> 2
"""
)
self.assertEqual(expression.comments, ["comment1.1", "comment1.2", "comment1.3"])
self.assertEqual(expression.this.comments, ["comment2"])
self.assertEqual(expression.args.get("where").comments, ["comment4"])
def test_comments_update_cte(self):
expression = parse_one(
"""
/*comment1.1*/
/*comment1.2*/
WITH a AS (SELECT * FROM b)
UPDATE /*comment2*/
a /*comment3*/
SET col = 1
"""
)
self.assertEqual(expression.comments, ["comment2"])
self.assertEqual(expression.this.comments, ["comment3"])
self.assertEqual(expression.args.get("with").comments, ["comment1.1", "comment1.2"])
def test_comments_delete(self):
expression = parse_one(
"""
--comment1.1
--comment1.2
DELETE /*comment1.3*/
FROM /*comment2*/
x /*comment3*/
WHERE /*comment4*/
y > 1
"""
)
self.assertEqual(expression.comments, ["comment1.1", "comment1.2", "comment1.3"])
self.assertEqual(expression.this.comments, ["comment3"])
self.assertEqual(expression.args.get("where").comments, ["comment4"])
def test_comments_delete_cte(self):
expression = parse_one(
"""
/*comment1.1*/
/*comment1.2*/
WITH a AS (SELECT * FROM b)
--comment2
DELETE FROM a /*comment3*/
"""
)
self.assertEqual(expression.comments, ["comment2"])
self.assertEqual(expression.this.comments, ["comment3"])
self.assertEqual(expression.args.get("with").comments, ["comment1.1", "comment1.2"])
def test_type_literals(self): def test_type_literals(self):
self.assertEqual(parse_one("int 1"), parse_one("CAST(1 AS INT)")) self.assertEqual(parse_one("int 1"), parse_one("CAST(1 AS INT)"))
self.assertEqual(parse_one("int.5"), parse_one("CAST(0.5 AS INT)")) self.assertEqual(parse_one("int.5"), parse_one("CAST(0.5 AS INT)"))
@ -528,7 +642,7 @@ class TestParser(unittest.TestCase):
now = time.time() now = time.time()
query = parse_one( query = parse_one(
""" """
select * SELECT *
FROM a FROM a
LEFT JOIN b ON a.id = b.id LEFT JOIN b ON a.id = b.id
LEFT JOIN b ON a.id = b.id LEFT JOIN b ON a.id = b.id

View file

@ -238,3 +238,37 @@ class TestSchema(unittest.TestCase):
schema = MappingSchema(schema={"Foo": {"`BaR`": "int"}}, dialect="bigquery") schema = MappingSchema(schema={"Foo": {"`BaR`": "int"}}, dialect="bigquery")
self.assertEqual(schema.column_names("Foo"), ["bar"]) self.assertEqual(schema.column_names("Foo"), ["bar"])
self.assertEqual(schema.column_names("foo"), []) self.assertEqual(schema.column_names("foo"), [])
# Check that the schema's normalization setting can be overridden
schema = MappingSchema(schema={"X": {"y": "int"}}, normalize=False, dialect="snowflake")
self.assertEqual(schema.column_names("x", normalize=True), ["y"])
def test_same_number_of_qualifiers(self):
schema = MappingSchema({"x": {"y": {"c1": "int"}}})
with self.assertRaises(SchemaError) as ctx:
schema.add_table("z", {"c2": "int"})
self.assertEqual(
str(ctx.exception),
"Table z must match the schema's nesting level: 2.",
)
schema = MappingSchema()
schema.add_table("x.y", {"c1": "int"})
with self.assertRaises(SchemaError) as ctx:
schema.add_table("z", {"c2": "int"})
self.assertEqual(
str(ctx.exception),
"Table z must match the schema's nesting level: 2.",
)
with self.assertRaises(SchemaError) as ctx:
MappingSchema({"x": {"y": {"c1": "int"}}, "z": {"c2": "int"}})
self.assertEqual(
str(ctx.exception),
"Table z must match the schema's nesting level: 2.",
)

View file

@ -99,7 +99,7 @@ class TestTransforms(unittest.TestCase):
self.validate( self.validate(
eliminate_qualify, eliminate_qualify,
"SELECT * FROM qt QUALIFY ROW_NUMBER() OVER (PARTITION BY p ORDER BY o) = 1", "SELECT * FROM qt QUALIFY ROW_NUMBER() OVER (PARTITION BY p ORDER BY o) = 1",
"SELECT * FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY p ORDER BY o) AS _w, p, o FROM qt) AS _t WHERE _w = 1", "SELECT * FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY p ORDER BY o) AS _w FROM qt) AS _t WHERE _w = 1",
) )
self.validate( self.validate(
eliminate_qualify, eliminate_qualify,