1
0
Fork 0

Adding upstream version 21.0.1.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-13 21:20:19 +01:00
parent 07f4660f31
commit 91f2cef5f0
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
115 changed files with 66603 additions and 60920 deletions

View file

@ -1,28 +1,27 @@
repos:
- repo: local
hooks:
- id: autoflake
name: autoflake
entry: autoflake -i -r
language: system
types: [ python ]
- id: ruff
name: ruff
description: "Run 'ruff' for extremely fast Python linting"
entry: ruff check
--force-exclude --fix
--ignore E721
--ignore E741
language: python
types_or: [python, pyi]
require_serial: true
additional_dependencies: []
files: ^(sqlglot/|tests/|setup.py)
- id: isort
args: [--combine-as]
name: isort
entry: isort
language: system
types: [ python ]
files: ^(sqlglot/|tests/|setup.py)
- id: ruff-format
name: ruff-format
description: "Run 'ruff format' for extremely fast Python formatting"
entry: ruff format
--force-exclude
--line-length 100
language: python
types_or: [python, pyi]
require_serial: true
- id: black
name: black
entry: black --line-length 100
language: system
types: [ python ]
require_serial: true
files: ^(sqlglot/|tests/|setup.py)
- id: mypy
name: mypy
entry: mypy sqlglot tests

View file

@ -1,6 +1,88 @@
Changelog
=========
## [v21.0.0] - 2024-02-07
### :boom: BREAKING CHANGES
- due to [`b4e8868`](https://github.com/tobymao/sqlglot/commit/b4e886877ecfbafdd64c515c765c3c54764bd987) - improve transpilation of JSON paths across dialects *(PR [#2883](https://github.com/tobymao/sqlglot/pull/2883) by [@georgesittas](https://github.com/georgesittas))*:
improve transpilation of JSON paths across dialects (#2883)
- due to [`aa388ea`](https://github.com/tobymao/sqlglot/commit/aa388ea64404a26550dbb0734f4d3e35111f9e2c) - ignore nulls closes [#2896](https://github.com/tobymao/sqlglot/pull/2896) *(PR [#2898](https://github.com/tobymao/sqlglot/pull/2898) by [@tobymao](https://github.com/tobymao))*:
ignore nulls closes #2896 (#2898)
- due to [`617a8c0`](https://github.com/tobymao/sqlglot/commit/617a8c0dfc5e9f2716f7827381af0db2e135059e) - timestamp diff for mysql and databricks *(commit by [@tobymao](https://github.com/tobymao))*:
timestamp diff for mysql and databricks
- due to [`b00b393`](https://github.com/tobymao/sqlglot/commit/b00b393d853ae05a3fce4ef78d7673edbcabf67d) - use raise instead of assert for assert_is *(commit by [@tobymao](https://github.com/tobymao))*:
use raise instead of assert for assert_is
- due to [`326aa31`](https://github.com/tobymao/sqlglot/commit/326aa31e32e511f4e40d3a5a7b1d599b5e2c1307) - deprecate case where transforms can be plain strs *(PR [#2919](https://github.com/tobymao/sqlglot/pull/2919) by [@georgesittas](https://github.com/georgesittas))*:
deprecate case where transforms can be plain strs (#2919)
### :sparkles: New Features
- [`fb450f0`](https://github.com/tobymao/sqlglot/commit/fb450f0263ecd6b7c9d0f49d84441327d50b9d83) - add tsql right left auto casting closes [#2899](https://github.com/tobymao/sqlglot/pull/2899) *(commit by [@tobymao](https://github.com/tobymao))*
- [`617a8c0`](https://github.com/tobymao/sqlglot/commit/617a8c0dfc5e9f2716f7827381af0db2e135059e) - timestamp diff for mysql and databricks *(commit by [@tobymao](https://github.com/tobymao))*
- [`3fa92ca`](https://github.com/tobymao/sqlglot/commit/3fa92cac285cbb2bd9d8b5724dadb77be7e12731) - **redshift**: parse GETDATE *(PR [#2904](https://github.com/tobymao/sqlglot/pull/2904) by [@erickpeirson](https://github.com/erickpeirson))*
- [`d262139`](https://github.com/tobymao/sqlglot/commit/d26213998b27fa9b6a66b6d21ab5a3a15f65635e) - **snowflake**: implement parsing logic for SHOW TABLES *(PR [#2913](https://github.com/tobymao/sqlglot/pull/2913) by [@tekumara](https://github.com/tekumara))*
- [`838e780`](https://github.com/tobymao/sqlglot/commit/838e7800c32ad16074efef6a188ebd89083a9717) - improve transpilation of CREATE TABLE LIKE statement *(PR [#2923](https://github.com/tobymao/sqlglot/pull/2923) by [@georgesittas](https://github.com/georgesittas))*
- :arrow_lower_right: *addresses issue [#2922](https://github.com/tobymao/sqlglot/issues/2922) opened by [@tharwan](https://github.com/tharwan)*
- [`cbbad1f`](https://github.com/tobymao/sqlglot/commit/cbbad1fc40b6b2ca837ddb0f798b1802ad4063da) - improve transpilation of JSON path wildcards *(PR [#2924](https://github.com/tobymao/sqlglot/pull/2924) by [@georgesittas](https://github.com/georgesittas))*
### :bug: Bug Fixes
- [`aa388ea`](https://github.com/tobymao/sqlglot/commit/aa388ea64404a26550dbb0734f4d3e35111f9e2c) - ignore nulls closes [#2896](https://github.com/tobymao/sqlglot/pull/2896) *(PR [#2898](https://github.com/tobymao/sqlglot/pull/2898) by [@tobymao](https://github.com/tobymao))*
- [`b00b393`](https://github.com/tobymao/sqlglot/commit/b00b393d853ae05a3fce4ef78d7673edbcabf67d) - use raise instead of assert for assert_is *(commit by [@tobymao](https://github.com/tobymao))*
- [`ab97246`](https://github.com/tobymao/sqlglot/commit/ab972462b1c545b4a60bb88cb40cdb98cb64e360) - array overlaps closes [#2903](https://github.com/tobymao/sqlglot/pull/2903) *(commit by [@tobymao](https://github.com/tobymao))*
- [`f3bdcb0`](https://github.com/tobymao/sqlglot/commit/f3bdcb087bb993289c4a1a5d2de54155ae2d2681) - **duckdb**: fix JSON pointer path parsing, reduce warning noise *(PR [#2911](https://github.com/tobymao/sqlglot/pull/2911) by [@georgesittas](https://github.com/georgesittas))*
- [`072264f`](https://github.com/tobymao/sqlglot/commit/072264f8af25737050f7becd27af5a9331bde896) - **mysql**: SHOW SCHEMAS *(PR [#2916](https://github.com/tobymao/sqlglot/pull/2916) by [@barakalon](https://github.com/barakalon))*
- [`15fdff2`](https://github.com/tobymao/sqlglot/commit/15fdff2df3363ab8d3595e7eeb8baee65e525733) - **optimizer**: don't remove NOT parenthesis *(PR [#2917](https://github.com/tobymao/sqlglot/pull/2917) by [@barakalon](https://github.com/barakalon))*
- [`d20d826`](https://github.com/tobymao/sqlglot/commit/d20d826e9cc4a9b0d636a9b56b5547cd906a5903) - have table exclude this if schema target *(PR [#2921](https://github.com/tobymao/sqlglot/pull/2921) by [@eakmanrq](https://github.com/eakmanrq))*
### :recycle: Refactors
- [`b4e8868`](https://github.com/tobymao/sqlglot/commit/b4e886877ecfbafdd64c515c765c3c54764bd987) - improve transpilation of JSON paths across dialects *(PR [#2883](https://github.com/tobymao/sqlglot/pull/2883) by [@georgesittas](https://github.com/georgesittas))*
- :arrow_lower_right: *addresses issue [#2839](https://github.com/tobymao/sqlglot/issues/2839) opened by [@FlaviovLeal](https://github.com/FlaviovLeal)*
- [`9481f94`](https://github.com/tobymao/sqlglot/commit/9481f946b068e43d99c9aaae6e1c59abf384eeac) - several JSON path improvements *(PR [#2914](https://github.com/tobymao/sqlglot/pull/2914) by [@georgesittas](https://github.com/georgesittas))*
- [`326aa31`](https://github.com/tobymao/sqlglot/commit/326aa31e32e511f4e40d3a5a7b1d599b5e2c1307) - deprecate case where transforms can be plain strs *(PR [#2919](https://github.com/tobymao/sqlglot/pull/2919) by [@georgesittas](https://github.com/georgesittas))*
- [`15582f4`](https://github.com/tobymao/sqlglot/commit/15582f40bd18da3fa7adbe454b401ef8d31a131e) - move JSON path generation logic in Generator *(PR [#2920](https://github.com/tobymao/sqlglot/pull/2920) by [@georgesittas](https://github.com/georgesittas))*
### :wrench: Chores
- [`afb4f9b`](https://github.com/tobymao/sqlglot/commit/afb4f9bfe074200e60b5a870267fe21aa04a87c5) - switch to ruff *(commit by [@tobymao](https://github.com/tobymao))*
- [`f9fdf7b`](https://github.com/tobymao/sqlglot/commit/f9fdf7b3bb25aa7e830b70600728bb35ee1e4ff7) - switch to ruff *(PR [#2912](https://github.com/tobymao/sqlglot/pull/2912) by [@tobymao](https://github.com/tobymao))*
- [`71c33fa`](https://github.com/tobymao/sqlglot/commit/71c33fa13b9c416ae50acb10a9b08dcfcfd35f92) - pandas warning *(commit by [@tobymao](https://github.com/tobymao))*
## [v20.11.0] - 2024-01-29
### :boom: BREAKING CHANGES
- due to [`eb8b40a`](https://github.com/tobymao/sqlglot/commit/eb8b40aade54eec8b34a808dda95420dcf7a7e13) - deprecate NULL, TRUE, FALSE constant expressions *(PR [#2884](https://github.com/tobymao/sqlglot/pull/2884) by [@georgesittas](https://github.com/georgesittas))*:
deprecate NULL, TRUE, FALSE constant expressions (#2884)
### :sparkles: New Features
- [`3a8ed85`](https://github.com/tobymao/sqlglot/commit/3a8ed8573d5562110b312586ae6fca22038e5d05) - add alter table alter comment closes [#2889](https://github.com/tobymao/sqlglot/pull/2889) *(commit by [@tobymao](https://github.com/tobymao))*
### :bug: Bug Fixes
- [`dc2d7d7`](https://github.com/tobymao/sqlglot/commit/dc2d7d7dd4253fe6b247d534bd92327f186e9aa8) - **tsql**: len text transpilation closes [#2885](https://github.com/tobymao/sqlglot/pull/2885) *(commit by [@tobymao](https://github.com/tobymao))*
- [`ad50f47`](https://github.com/tobymao/sqlglot/commit/ad50f479c47d5b4990f1b41272c69079a453cf21) - type imports *(PR [#2886](https://github.com/tobymao/sqlglot/pull/2886) by [@tobymao](https://github.com/tobymao))*
- [`e4fb7f6`](https://github.com/tobymao/sqlglot/commit/e4fb7f6e1b8ab15ceb5acc6a93256c849c738740) - union should return union *(commit by [@tobymao](https://github.com/tobymao))*
- [`8f795ea`](https://github.com/tobymao/sqlglot/commit/8f795ea00164b69acba093c3684ab54b62138e8e) - don't expand star except/replace refs *(commit by [@tobymao](https://github.com/tobymao))*
- [`218121c`](https://github.com/tobymao/sqlglot/commit/218121c274656a1b252143a7d0fc2d73407115ca) - alter table cluster by closes [#2887](https://github.com/tobymao/sqlglot/pull/2887) *(commit by [@tobymao](https://github.com/tobymao))*
- [`5cec283`](https://github.com/tobymao/sqlglot/commit/5cec2839f8ed8477821bf766025f4b5de0621fe2) - bigquery script if statement closes [#2888](https://github.com/tobymao/sqlglot/pull/2888) *(commit by [@tobymao](https://github.com/tobymao))*
- [`5fc7791`](https://github.com/tobymao/sqlglot/commit/5fc7791a4d19d704c0d4fafe8924cf8f76fcb867) - all view column options without types closes [#2891](https://github.com/tobymao/sqlglot/pull/2891) *(commit by [@tobymao](https://github.com/tobymao))*
- [`102304e`](https://github.com/tobymao/sqlglot/commit/102304e28f2ed7126840789837ed797a75bae44e) - **postgres**: generate CurrentUser without parentheses closes [#2893](https://github.com/tobymao/sqlglot/pull/2893) *(commit by [@georgesittas](https://github.com/georgesittas))*
- [`43902db`](https://github.com/tobymao/sqlglot/commit/43902db25706a2434fe7e9ba39addd1c31c2aa64) - error level ignore comments closes [#2895](https://github.com/tobymao/sqlglot/pull/2895) *(commit by [@tobymao](https://github.com/tobymao))*
### :wrench: Chores
- [`eb8b40a`](https://github.com/tobymao/sqlglot/commit/eb8b40aade54eec8b34a808dda95420dcf7a7e13) - deprecate NULL, TRUE, FALSE constant expressions *(PR [#2884](https://github.com/tobymao/sqlglot/pull/2884) by [@georgesittas](https://github.com/georgesittas))*
- [`29cddd5`](https://github.com/tobymao/sqlglot/commit/29cddd5c3f5401033197d47e7544cedd91b8046c) - change warning message *(commit by [@tobymao](https://github.com/tobymao))*
- [`9eac93e`](https://github.com/tobymao/sqlglot/commit/9eac93e0acd5ae8b034045759fc48937586cbc2e) - upgrade black *(commit by [@tobymao](https://github.com/tobymao))*
- [`4f3fac7`](https://github.com/tobymao/sqlglot/commit/4f3fac7815e0d8206c80f1f255336ab630503d4d) - cleanup command parsing and warnings *(commit by [@tobymao](https://github.com/tobymao))*
## [v20.10.0] - 2024-01-24
### :boom: BREAKING CHANGES
- due to [`1f5fc39`](https://github.com/tobymao/sqlglot/commit/1f5fc39c10b92b94bd94afa5fd038fdb9afeb4b4) - jsonpath parsing *(PR [#2867](https://github.com/tobymao/sqlglot/pull/2867) by [@tobymao](https://github.com/tobymao))*:
@ -2486,3 +2568,5 @@ Changelog
[v20.8.0]: https://github.com/tobymao/sqlglot/compare/v20.7.1...v20.8.0
[v20.9.0]: https://github.com/tobymao/sqlglot/compare/v20.8.0...v20.9.0
[v20.10.0]: https://github.com/tobymao/sqlglot/compare/v20.9.0...v20.10.0
[v20.11.0]: https://github.com/tobymao/sqlglot/compare/v20.10.0...v20.11.0
[v21.0.0]: https://github.com/tobymao/sqlglot/compare/v20.11.0...v21.0.0

View file

@ -2,15 +2,14 @@ import collections.abc
# moz_sql_parser 3.10 compatibility
collections.Iterable = collections.abc.Iterable
import gc
import timeit
import numpy as np
#import sqlfluff
#import moz_sql_parser
#import sqloxide
#import sqlparse
# import sqlfluff
# import moz_sql_parser
# import sqloxide
# import sqlparse
import sqltree
import sqlglot
@ -170,7 +169,7 @@ def sqlglotrs_parse(sql):
def sqltree_parse(sql):
sqltree.api.sqltree(sql.replace('"', '`').replace("''", '"'))
sqltree.api.sqltree(sql.replace('"', "`").replace("''", '"'))
def sqlparse_parse(sql):
@ -206,11 +205,11 @@ def diff(row, column):
libs = [
"sqlglot",
"sqlglotrs",
#"sqlfluff",
# "sqlfluff",
"sqltree",
#"sqlparse",
#"moz_sql_parser",
#"sqloxide",
# "sqlparse",
# "moz_sql_parser",
# "sqloxide",
]
table = []
@ -231,10 +230,12 @@ lines = [border(column.rjust(width) for column, width in widths.items())]
lines.append(border(str("-" * width) for width in widths.values()))
for i, row in enumerate(table):
lines.append(border(
(str(row[column])[0:7] + diff(row, column)).rjust(width)[0 : width]
for column, width in widths.items()
))
lines.append(
border(
(str(row[column])[0:7] + diff(row, column)).rjust(width)[0:width]
for column, width in widths.items()
)
)
for line in lines:
print(line)

File diff suppressed because one or more lines are too long

View file

@ -707,170 +707,171 @@ make check # Full test suite &amp; linter checks
<label class="view-source-button" for="mod-sqlglot-view-source"><span>View Source</span></label>
<div class="pdoc-code codehilite"><pre><span></span><span id="L-1"><a href="#L-1"><span class="linenos"> 1</span></a><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-2"><a href="#L-2"><span class="linenos"> 2</span></a><span class="sd">.. include:: ../README.md</span>
</span><span id="L-3"><a href="#L-3"><span class="linenos"> 3</span></a>
</span><span id="L-4"><a href="#L-4"><span class="linenos"> 4</span></a><span class="sd">----</span>
</span><span id="L-5"><a href="#L-5"><span class="linenos"> 5</span></a><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-6"><a href="#L-6"><span class="linenos"> 6</span></a>
</span><span id="L-7"><a href="#L-7"><span class="linenos"> 7</span></a><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">annotations</span>
</span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</span></a>
</span><span id="L-9"><a href="#L-9"><span class="linenos"> 9</span></a><span class="kn">import</span> <span class="nn">logging</span>
</span><span id="L-10"><a href="#L-10"><span class="linenos"> 10</span></a><span class="kn">import</span> <span class="nn">typing</span> <span class="k">as</span> <span class="nn">t</span>
</span><span id="L-11"><a href="#L-11"><span class="linenos"> 11</span></a>
</span><span id="L-12"><a href="#L-12"><span class="linenos"> 12</span></a><span class="kn">from</span> <span class="nn">sqlglot</span> <span class="kn">import</span> <span class="n">expressions</span> <span class="k">as</span> <span class="n">exp</span>
</span><span id="L-13"><a href="#L-13"><span class="linenos"> 13</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.dialect</span> <span class="kn">import</span> <span class="n">Dialect</span> <span class="k">as</span> <span class="n">Dialect</span><span class="p">,</span> <span class="n">Dialects</span> <span class="k">as</span> <span class="n">Dialects</span>
</span><span id="L-14"><a href="#L-14"><span class="linenos"> 14</span></a><span class="kn">from</span> <span class="nn">sqlglot.diff</span> <span class="kn">import</span> <span class="n">diff</span> <span class="k">as</span> <span class="n">diff</span>
</span><span id="L-15"><a href="#L-15"><span class="linenos"> 15</span></a><span class="kn">from</span> <span class="nn">sqlglot.errors</span> <span class="kn">import</span> <span class="p">(</span>
</span><span id="L-16"><a href="#L-16"><span class="linenos"> 16</span></a> <span class="n">ErrorLevel</span> <span class="k">as</span> <span class="n">ErrorLevel</span><span class="p">,</span>
</span><span id="L-17"><a href="#L-17"><span class="linenos"> 17</span></a> <span class="n">ParseError</span> <span class="k">as</span> <span class="n">ParseError</span><span class="p">,</span>
</span><span id="L-18"><a href="#L-18"><span class="linenos"> 18</span></a> <span class="n">TokenError</span> <span class="k">as</span> <span class="n">TokenError</span><span class="p">,</span>
</span><span id="L-19"><a href="#L-19"><span class="linenos"> 19</span></a> <span class="n">UnsupportedError</span> <span class="k">as</span> <span class="n">UnsupportedError</span><span class="p">,</span>
</span><span id="L-20"><a href="#L-20"><span class="linenos"> 20</span></a><span class="p">)</span>
</span><span id="L-21"><a href="#L-21"><span class="linenos"> 21</span></a><span class="kn">from</span> <span class="nn">sqlglot.expressions</span> <span class="kn">import</span> <span class="p">(</span>
</span><span id="L-22"><a href="#L-22"><span class="linenos"> 22</span></a> <span class="n">Expression</span> <span class="k">as</span> <span class="n">Expression</span><span class="p">,</span>
</span><span id="L-23"><a href="#L-23"><span class="linenos"> 23</span></a> <span class="n">alias_</span> <span class="k">as</span> <span class="n">alias</span><span class="p">,</span>
</span><span id="L-24"><a href="#L-24"><span class="linenos"> 24</span></a> <span class="n">and_</span> <span class="k">as</span> <span class="n">and_</span><span class="p">,</span>
</span><span id="L-25"><a href="#L-25"><span class="linenos"> 25</span></a> <span class="n">case</span> <span class="k">as</span> <span class="n">case</span><span class="p">,</span>
</span><span id="L-26"><a href="#L-26"><span class="linenos"> 26</span></a> <span class="n">cast</span> <span class="k">as</span> <span class="n">cast</span><span class="p">,</span>
</span><span id="L-27"><a href="#L-27"><span class="linenos"> 27</span></a> <span class="n">column</span> <span class="k">as</span> <span class="n">column</span><span class="p">,</span>
</span><span id="L-28"><a href="#L-28"><span class="linenos"> 28</span></a> <span class="n">condition</span> <span class="k">as</span> <span class="n">condition</span><span class="p">,</span>
</span><span id="L-29"><a href="#L-29"><span class="linenos"> 29</span></a> <span class="n">except_</span> <span class="k">as</span> <span class="n">except_</span><span class="p">,</span>
</span><span id="L-30"><a href="#L-30"><span class="linenos"> 30</span></a> <span class="n">from_</span> <span class="k">as</span> <span class="n">from_</span><span class="p">,</span>
</span><span id="L-31"><a href="#L-31"><span class="linenos"> 31</span></a> <span class="n">func</span> <span class="k">as</span> <span class="n">func</span><span class="p">,</span>
</span><span id="L-32"><a href="#L-32"><span class="linenos"> 32</span></a> <span class="n">intersect</span> <span class="k">as</span> <span class="n">intersect</span><span class="p">,</span>
</span><span id="L-33"><a href="#L-33"><span class="linenos"> 33</span></a> <span class="n">maybe_parse</span> <span class="k">as</span> <span class="n">maybe_parse</span><span class="p">,</span>
</span><span id="L-34"><a href="#L-34"><span class="linenos"> 34</span></a> <span class="n">not_</span> <span class="k">as</span> <span class="n">not_</span><span class="p">,</span>
</span><span id="L-35"><a href="#L-35"><span class="linenos"> 35</span></a> <span class="n">or_</span> <span class="k">as</span> <span class="n">or_</span><span class="p">,</span>
</span><span id="L-36"><a href="#L-36"><span class="linenos"> 36</span></a> <span class="n">select</span> <span class="k">as</span> <span class="n">select</span><span class="p">,</span>
</span><span id="L-37"><a href="#L-37"><span class="linenos"> 37</span></a> <span class="n">subquery</span> <span class="k">as</span> <span class="n">subquery</span><span class="p">,</span>
</span><span id="L-38"><a href="#L-38"><span class="linenos"> 38</span></a> <span class="n">table_</span> <span class="k">as</span> <span class="n">table</span><span class="p">,</span>
</span><span id="L-39"><a href="#L-39"><span class="linenos"> 39</span></a> <span class="n">to_column</span> <span class="k">as</span> <span class="n">to_column</span><span class="p">,</span>
</span><span id="L-40"><a href="#L-40"><span class="linenos"> 40</span></a> <span class="n">to_identifier</span> <span class="k">as</span> <span class="n">to_identifier</span><span class="p">,</span>
</span><span id="L-41"><a href="#L-41"><span class="linenos"> 41</span></a> <span class="n">to_table</span> <span class="k">as</span> <span class="n">to_table</span><span class="p">,</span>
</span><span id="L-42"><a href="#L-42"><span class="linenos"> 42</span></a> <span class="n">union</span> <span class="k">as</span> <span class="n">union</span><span class="p">,</span>
</span><span id="L-43"><a href="#L-43"><span class="linenos"> 43</span></a><span class="p">)</span>
</span><span id="L-44"><a href="#L-44"><span class="linenos"> 44</span></a><span class="kn">from</span> <span class="nn">sqlglot.generator</span> <span class="kn">import</span> <span class="n">Generator</span> <span class="k">as</span> <span class="n">Generator</span>
</span><span id="L-45"><a href="#L-45"><span class="linenos"> 45</span></a><span class="kn">from</span> <span class="nn">sqlglot.parser</span> <span class="kn">import</span> <span class="n">Parser</span> <span class="k">as</span> <span class="n">Parser</span>
</span><span id="L-46"><a href="#L-46"><span class="linenos"> 46</span></a><span class="kn">from</span> <span class="nn">sqlglot.schema</span> <span class="kn">import</span> <span class="n">MappingSchema</span> <span class="k">as</span> <span class="n">MappingSchema</span><span class="p">,</span> <span class="n">Schema</span> <span class="k">as</span> <span class="n">Schema</span>
</span><span id="L-47"><a href="#L-47"><span class="linenos"> 47</span></a><span class="kn">from</span> <span class="nn">sqlglot.tokens</span> <span class="kn">import</span> <span class="n">Tokenizer</span> <span class="k">as</span> <span class="n">Tokenizer</span><span class="p">,</span> <span class="n">TokenType</span> <span class="k">as</span> <span class="n">TokenType</span>
</span><span id="L-48"><a href="#L-48"><span class="linenos"> 48</span></a>
</span><span id="L-49"><a href="#L-49"><span class="linenos"> 49</span></a><span class="k">if</span> <span class="n">t</span><span class="o">.</span><span class="n">TYPE_CHECKING</span><span class="p">:</span>
</span><span id="L-50"><a href="#L-50"><span class="linenos"> 50</span></a> <span class="kn">from</span> <span class="nn">sqlglot._typing</span> <span class="kn">import</span> <span class="n">E</span>
</span><span id="L-51"><a href="#L-51"><span class="linenos"> 51</span></a> <span class="kn">from</span> <span class="nn">sqlglot.dialects.dialect</span> <span class="kn">import</span> <span class="n">DialectType</span> <span class="k">as</span> <span class="n">DialectType</span>
</span><span id="L-52"><a href="#L-52"><span class="linenos"> 52</span></a>
</span><span id="L-53"><a href="#L-53"><span class="linenos"> 53</span></a><span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s2">&quot;sqlglot&quot;</span><span class="p">)</span>
</span><span id="L-54"><a href="#L-54"><span class="linenos"> 54</span></a>
<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"># ruff: noqa: F401</span>
</span><span id="L-2"><a href="#L-2"><span class="linenos"> 2</span></a><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-3"><a href="#L-3"><span class="linenos"> 3</span></a><span class="sd">.. include:: ../README.md</span>
</span><span id="L-4"><a href="#L-4"><span class="linenos"> 4</span></a>
</span><span id="L-5"><a href="#L-5"><span class="linenos"> 5</span></a><span class="sd">----</span>
</span><span id="L-6"><a href="#L-6"><span class="linenos"> 6</span></a><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-7"><a href="#L-7"><span class="linenos"> 7</span></a>
</span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</span></a><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">annotations</span>
</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 class="kn">import</span> <span class="nn">logging</span>
</span><span id="L-11"><a href="#L-11"><span class="linenos"> 11</span></a><span class="kn">import</span> <span class="nn">typing</span> <span class="k">as</span> <span class="nn">t</span>
</span><span id="L-12"><a href="#L-12"><span class="linenos"> 12</span></a>
</span><span id="L-13"><a href="#L-13"><span class="linenos"> 13</span></a><span class="kn">from</span> <span class="nn">sqlglot</span> <span class="kn">import</span> <span class="n">expressions</span> <span class="k">as</span> <span class="n">exp</span>
</span><span id="L-14"><a href="#L-14"><span class="linenos"> 14</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.dialect</span> <span class="kn">import</span> <span class="n">Dialect</span> <span class="k">as</span> <span class="n">Dialect</span><span class="p">,</span> <span class="n">Dialects</span> <span class="k">as</span> <span class="n">Dialects</span>
</span><span id="L-15"><a href="#L-15"><span class="linenos"> 15</span></a><span class="kn">from</span> <span class="nn">sqlglot.diff</span> <span class="kn">import</span> <span class="n">diff</span> <span class="k">as</span> <span class="n">diff</span>
</span><span id="L-16"><a href="#L-16"><span class="linenos"> 16</span></a><span class="kn">from</span> <span class="nn">sqlglot.errors</span> <span class="kn">import</span> <span class="p">(</span>
</span><span id="L-17"><a href="#L-17"><span class="linenos"> 17</span></a> <span class="n">ErrorLevel</span> <span class="k">as</span> <span class="n">ErrorLevel</span><span class="p">,</span>
</span><span id="L-18"><a href="#L-18"><span class="linenos"> 18</span></a> <span class="n">ParseError</span> <span class="k">as</span> <span class="n">ParseError</span><span class="p">,</span>
</span><span id="L-19"><a href="#L-19"><span class="linenos"> 19</span></a> <span class="n">TokenError</span> <span class="k">as</span> <span class="n">TokenError</span><span class="p">,</span>
</span><span id="L-20"><a href="#L-20"><span class="linenos"> 20</span></a> <span class="n">UnsupportedError</span> <span class="k">as</span> <span class="n">UnsupportedError</span><span class="p">,</span>
</span><span id="L-21"><a href="#L-21"><span class="linenos"> 21</span></a><span class="p">)</span>
</span><span id="L-22"><a href="#L-22"><span class="linenos"> 22</span></a><span class="kn">from</span> <span class="nn">sqlglot.expressions</span> <span class="kn">import</span> <span class="p">(</span>
</span><span id="L-23"><a href="#L-23"><span class="linenos"> 23</span></a> <span class="n">Expression</span> <span class="k">as</span> <span class="n">Expression</span><span class="p">,</span>
</span><span id="L-24"><a href="#L-24"><span class="linenos"> 24</span></a> <span class="n">alias_</span> <span class="k">as</span> <span class="n">alias</span><span class="p">,</span>
</span><span id="L-25"><a href="#L-25"><span class="linenos"> 25</span></a> <span class="n">and_</span> <span class="k">as</span> <span class="n">and_</span><span class="p">,</span>
</span><span id="L-26"><a href="#L-26"><span class="linenos"> 26</span></a> <span class="n">case</span> <span class="k">as</span> <span class="n">case</span><span class="p">,</span>
</span><span id="L-27"><a href="#L-27"><span class="linenos"> 27</span></a> <span class="n">cast</span> <span class="k">as</span> <span class="n">cast</span><span class="p">,</span>
</span><span id="L-28"><a href="#L-28"><span class="linenos"> 28</span></a> <span class="n">column</span> <span class="k">as</span> <span class="n">column</span><span class="p">,</span>
</span><span id="L-29"><a href="#L-29"><span class="linenos"> 29</span></a> <span class="n">condition</span> <span class="k">as</span> <span class="n">condition</span><span class="p">,</span>
</span><span id="L-30"><a href="#L-30"><span class="linenos"> 30</span></a> <span class="n">except_</span> <span class="k">as</span> <span class="n">except_</span><span class="p">,</span>
</span><span id="L-31"><a href="#L-31"><span class="linenos"> 31</span></a> <span class="n">from_</span> <span class="k">as</span> <span class="n">from_</span><span class="p">,</span>
</span><span id="L-32"><a href="#L-32"><span class="linenos"> 32</span></a> <span class="n">func</span> <span class="k">as</span> <span class="n">func</span><span class="p">,</span>
</span><span id="L-33"><a href="#L-33"><span class="linenos"> 33</span></a> <span class="n">intersect</span> <span class="k">as</span> <span class="n">intersect</span><span class="p">,</span>
</span><span id="L-34"><a href="#L-34"><span class="linenos"> 34</span></a> <span class="n">maybe_parse</span> <span class="k">as</span> <span class="n">maybe_parse</span><span class="p">,</span>
</span><span id="L-35"><a href="#L-35"><span class="linenos"> 35</span></a> <span class="n">not_</span> <span class="k">as</span> <span class="n">not_</span><span class="p">,</span>
</span><span id="L-36"><a href="#L-36"><span class="linenos"> 36</span></a> <span class="n">or_</span> <span class="k">as</span> <span class="n">or_</span><span class="p">,</span>
</span><span id="L-37"><a href="#L-37"><span class="linenos"> 37</span></a> <span class="n">select</span> <span class="k">as</span> <span class="n">select</span><span class="p">,</span>
</span><span id="L-38"><a href="#L-38"><span class="linenos"> 38</span></a> <span class="n">subquery</span> <span class="k">as</span> <span class="n">subquery</span><span class="p">,</span>
</span><span id="L-39"><a href="#L-39"><span class="linenos"> 39</span></a> <span class="n">table_</span> <span class="k">as</span> <span class="n">table</span><span class="p">,</span>
</span><span id="L-40"><a href="#L-40"><span class="linenos"> 40</span></a> <span class="n">to_column</span> <span class="k">as</span> <span class="n">to_column</span><span class="p">,</span>
</span><span id="L-41"><a href="#L-41"><span class="linenos"> 41</span></a> <span class="n">to_identifier</span> <span class="k">as</span> <span class="n">to_identifier</span><span class="p">,</span>
</span><span id="L-42"><a href="#L-42"><span class="linenos"> 42</span></a> <span class="n">to_table</span> <span class="k">as</span> <span class="n">to_table</span><span class="p">,</span>
</span><span id="L-43"><a href="#L-43"><span class="linenos"> 43</span></a> <span class="n">union</span> <span class="k">as</span> <span class="n">union</span><span class="p">,</span>
</span><span id="L-44"><a href="#L-44"><span class="linenos"> 44</span></a><span class="p">)</span>
</span><span id="L-45"><a href="#L-45"><span class="linenos"> 45</span></a><span class="kn">from</span> <span class="nn">sqlglot.generator</span> <span class="kn">import</span> <span class="n">Generator</span> <span class="k">as</span> <span class="n">Generator</span>
</span><span id="L-46"><a href="#L-46"><span class="linenos"> 46</span></a><span class="kn">from</span> <span class="nn">sqlglot.parser</span> <span class="kn">import</span> <span class="n">Parser</span> <span class="k">as</span> <span class="n">Parser</span>
</span><span id="L-47"><a href="#L-47"><span class="linenos"> 47</span></a><span class="kn">from</span> <span class="nn">sqlglot.schema</span> <span class="kn">import</span> <span class="n">MappingSchema</span> <span class="k">as</span> <span class="n">MappingSchema</span><span class="p">,</span> <span class="n">Schema</span> <span class="k">as</span> <span class="n">Schema</span>
</span><span id="L-48"><a href="#L-48"><span class="linenos"> 48</span></a><span class="kn">from</span> <span class="nn">sqlglot.tokens</span> <span class="kn">import</span> <span class="n">Tokenizer</span> <span class="k">as</span> <span class="n">Tokenizer</span><span class="p">,</span> <span class="n">TokenType</span> <span class="k">as</span> <span class="n">TokenType</span>
</span><span id="L-49"><a href="#L-49"><span class="linenos"> 49</span></a>
</span><span id="L-50"><a href="#L-50"><span class="linenos"> 50</span></a><span class="k">if</span> <span class="n">t</span><span class="o">.</span><span class="n">TYPE_CHECKING</span><span class="p">:</span>
</span><span id="L-51"><a href="#L-51"><span class="linenos"> 51</span></a> <span class="kn">from</span> <span class="nn">sqlglot._typing</span> <span class="kn">import</span> <span class="n">E</span>
</span><span id="L-52"><a href="#L-52"><span class="linenos"> 52</span></a> <span class="kn">from</span> <span class="nn">sqlglot.dialects.dialect</span> <span class="kn">import</span> <span class="n">DialectType</span> <span class="k">as</span> <span class="n">DialectType</span>
</span><span id="L-53"><a href="#L-53"><span class="linenos"> 53</span></a>
</span><span id="L-54"><a href="#L-54"><span class="linenos"> 54</span></a><span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s2">&quot;sqlglot&quot;</span><span class="p">)</span>
</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="k">try</span><span class="p">:</span>
</span><span id="L-57"><a href="#L-57"><span class="linenos"> 57</span></a> <span class="kn">from</span> <span class="nn">sqlglot._version</span> <span class="kn">import</span> <span class="n">__version__</span><span class="p">,</span> <span class="n">__version_tuple__</span>
</span><span id="L-58"><a href="#L-58"><span class="linenos"> 58</span></a><span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
</span><span id="L-59"><a href="#L-59"><span class="linenos"> 59</span></a> <span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span>
</span><span id="L-60"><a href="#L-60"><span class="linenos"> 60</span></a> <span class="s2">&quot;Unable to set __version__, run `pip install -e .` or `python setup.py develop` first.&quot;</span>
</span><span id="L-61"><a href="#L-61"><span class="linenos"> 61</span></a> <span class="p">)</span>
</span><span id="L-62"><a href="#L-62"><span class="linenos"> 62</span></a>
</span><span id="L-56"><a href="#L-56"><span class="linenos"> 56</span></a>
</span><span id="L-57"><a href="#L-57"><span class="linenos"> 57</span></a><span class="k">try</span><span class="p">:</span>
</span><span id="L-58"><a href="#L-58"><span class="linenos"> 58</span></a> <span class="kn">from</span> <span class="nn">sqlglot._version</span> <span class="kn">import</span> <span class="n">__version__</span><span class="p">,</span> <span class="n">__version_tuple__</span>
</span><span id="L-59"><a href="#L-59"><span class="linenos"> 59</span></a><span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
</span><span id="L-60"><a href="#L-60"><span class="linenos"> 60</span></a> <span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span>
</span><span id="L-61"><a href="#L-61"><span class="linenos"> 61</span></a> <span class="s2">&quot;Unable to set __version__, run `pip install -e .` or `python setup.py develop` first.&quot;</span>
</span><span id="L-62"><a href="#L-62"><span class="linenos"> 62</span></a> <span class="p">)</span>
</span><span id="L-63"><a href="#L-63"><span class="linenos"> 63</span></a>
</span><span id="L-64"><a href="#L-64"><span class="linenos"> 64</span></a><span class="n">pretty</span> <span class="o">=</span> <span class="kc">False</span>
</span><span id="L-65"><a href="#L-65"><span class="linenos"> 65</span></a><span class="sd">&quot;&quot;&quot;Whether to format generated SQL by default.&quot;&quot;&quot;</span>
</span><span id="L-66"><a href="#L-66"><span class="linenos"> 66</span></a>
</span><span id="L-67"><a href="#L-67"><span class="linenos"> 67</span></a><span class="n">schema</span> <span class="o">=</span> <span class="n">MappingSchema</span><span class="p">()</span>
</span><span id="L-68"><a href="#L-68"><span class="linenos"> 68</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-69"><a href="#L-69"><span class="linenos"> 69</span></a>
</span><span id="L-64"><a href="#L-64"><span class="linenos"> 64</span></a>
</span><span id="L-65"><a href="#L-65"><span class="linenos"> 65</span></a><span class="n">pretty</span> <span class="o">=</span> <span class="kc">False</span>
</span><span id="L-66"><a href="#L-66"><span class="linenos"> 66</span></a><span class="sd">&quot;&quot;&quot;Whether to format generated SQL by default.&quot;&quot;&quot;</span>
</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="n">schema</span> <span class="o">=</span> <span class="n">MappingSchema</span><span class="p">()</span>
</span><span id="L-69"><a href="#L-69"><span class="linenos"> 69</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-70"><a href="#L-70"><span class="linenos"> 70</span></a>
</span><span id="L-71"><a href="#L-71"><span class="linenos"> 71</span></a><span class="k">def</span> <span class="nf">parse</span><span class="p">(</span>
</span><span id="L-72"><a href="#L-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="L-73"><a href="#L-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="L-74"><a href="#L-74"><span class="linenos"> 74</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-75"><a href="#L-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="L-76"><a href="#L-76"><span class="linenos"> 76</span></a>
</span><span id="L-77"><a href="#L-77"><span class="linenos"> 77</span></a><span class="sd"> Args:</span>
</span><span id="L-78"><a href="#L-78"><span class="linenos"> 78</span></a><span class="sd"> sql: the SQL code string to parse.</span>
</span><span id="L-79"><a href="#L-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="L-80"><a href="#L-80"><span class="linenos"> 80</span></a><span class="sd"> dialect: the SQL dialect (alias for read).</span>
</span><span id="L-81"><a href="#L-81"><span class="linenos"> 81</span></a><span class="sd"> **opts: other `sqlglot.parser.Parser` options.</span>
</span><span id="L-82"><a href="#L-82"><span class="linenos"> 82</span></a>
</span><span id="L-83"><a href="#L-83"><span class="linenos"> 83</span></a><span class="sd"> Returns:</span>
</span><span id="L-84"><a href="#L-84"><span class="linenos"> 84</span></a><span class="sd"> The resulting syntax tree collection.</span>
</span><span id="L-85"><a href="#L-85"><span class="linenos"> 85</span></a><span class="sd"> &quot;&quot;&quot;</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">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 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><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="k">def</span> <span class="nf">parse</span><span class="p">(</span>
</span><span id="L-73"><a href="#L-73"><span class="linenos"> 73</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-74"><a href="#L-74"><span class="linenos"> 74</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-75"><a href="#L-75"><span class="linenos"> 75</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-76"><a href="#L-76"><span class="linenos"> 76</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-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="sd"> Args:</span>
</span><span id="L-79"><a href="#L-79"><span class="linenos"> 79</span></a><span class="sd"> sql: the SQL code string to parse.</span>
</span><span id="L-80"><a href="#L-80"><span class="linenos"> 80</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-81"><a href="#L-81"><span class="linenos"> 81</span></a><span class="sd"> dialect: the SQL dialect (alias for read).</span>
</span><span id="L-82"><a href="#L-82"><span class="linenos"> 82</span></a><span class="sd"> **opts: other `sqlglot.parser.Parser` options.</span>
</span><span id="L-83"><a href="#L-83"><span class="linenos"> 83</span></a>
</span><span id="L-84"><a href="#L-84"><span class="linenos"> 84</span></a><span class="sd"> Returns:</span>
</span><span id="L-85"><a href="#L-85"><span class="linenos"> 85</span></a><span class="sd"> The resulting syntax tree collection.</span>
</span><span id="L-86"><a href="#L-86"><span class="linenos"> 86</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-87"><a href="#L-87"><span class="linenos"> 87</span></a> <span class="k">return</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 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-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 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 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="o">...</span>
</span><span id="L-92"><a href="#L-92"><span class="linenos"> 92</span></a>
</span><span id="L-89"><a href="#L-89"><span class="linenos"> 89</span></a>
</span><span id="L-90"><a href="#L-90"><span class="linenos"> 90</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="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-92"><a href="#L-92"><span class="linenos"> 92</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 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 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="o">...</span>
</span><span id="L-97"><a href="#L-97"><span class="linenos"> 97</span></a>
</span><span id="L-94"><a href="#L-94"><span class="linenos"> 94</span></a>
</span><span id="L-95"><a href="#L-95"><span class="linenos"> 95</span></a><span class="nd">@t</span><span class="o">.</span><span class="n">overload</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 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-97"><a href="#L-97"><span class="linenos"> 97</span></a> <span class="o">...</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="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">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="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="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="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="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 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="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"> 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><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"> 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"> 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 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"> 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"> **opts: other `sqlglot.parser.Parser` options.</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 class="sd"> Returns:</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 class="sd"> &quot;&quot;&quot;</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">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><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 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">else</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><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">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-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 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">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><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">def</span> <span class="nf">parse_one</span><span class="p">(</span>
</span><span id="L-101"><a href="#L-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="L-102"><a href="#L-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="L-103"><a href="#L-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="L-104"><a href="#L-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="L-105"><a href="#L-105"><span class="linenos">105</span></a> <span class="o">**</span><span class="n">opts</span><span class="p">,</span>
</span><span id="L-106"><a href="#L-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="L-107"><a href="#L-107"><span class="linenos">107</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-108"><a href="#L-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="L-109"><a href="#L-109"><span class="linenos">109</span></a>
</span><span id="L-110"><a href="#L-110"><span class="linenos">110</span></a><span class="sd"> Args:</span>
</span><span id="L-111"><a href="#L-111"><span class="linenos">111</span></a><span class="sd"> sql: the SQL code string to parse.</span>
</span><span id="L-112"><a href="#L-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="L-113"><a href="#L-113"><span class="linenos">113</span></a><span class="sd"> dialect: the SQL dialect (alias for read)</span>
</span><span id="L-114"><a href="#L-114"><span class="linenos">114</span></a><span class="sd"> into: the SQLGlot Expression to parse into.</span>
</span><span id="L-115"><a href="#L-115"><span class="linenos">115</span></a><span class="sd"> **opts: other `sqlglot.parser.Parser` options.</span>
</span><span id="L-116"><a href="#L-116"><span class="linenos">116</span></a>
</span><span id="L-117"><a href="#L-117"><span class="linenos">117</span></a><span class="sd"> Returns:</span>
</span><span id="L-118"><a href="#L-118"><span class="linenos">118</span></a><span class="sd"> The syntax tree for the first parsed statement.</span>
</span><span id="L-119"><a href="#L-119"><span class="linenos">119</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-120"><a href="#L-120"><span class="linenos">120</span></a>
</span><span id="L-121"><a href="#L-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="L-122"><a href="#L-122"><span class="linenos">122</span></a>
</span><span id="L-123"><a href="#L-123"><span class="linenos">123</span></a> <span class="k">if</span> <span class="n">into</span><span class="p">:</span>
</span><span id="L-124"><a href="#L-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="L-125"><a href="#L-125"><span class="linenos">125</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-126"><a href="#L-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="L-127"><a href="#L-127"><span class="linenos">127</span></a>
</span><span id="L-128"><a href="#L-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="L-129"><a href="#L-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="L-130"><a href="#L-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="L-131"><a href="#L-131"><span class="linenos">131</span></a> <span class="k">return</span> <span class="n">expression</span>
</span><span id="L-132"><a href="#L-132"><span class="linenos">132</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-133"><a href="#L-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><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="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">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">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="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="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="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="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="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 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"> 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"> 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><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"> 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"> 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"> 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"> 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 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"> 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"> **opts: other `sqlglot.generator.Generator` options.</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="sd"> Returns:</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="sd"> &quot;&quot;&quot;</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="n">write</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">write</span><span class="p">)</span>
</span><span id="L-161"><a href="#L-161"><span class="linenos">161</span></a> <span class="k">return</span> <span class="p">[</span>
</span><span id="L-162"><a href="#L-162"><span class="linenos">162</span></a> <span class="n">write</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="n">copy</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span> <span class="k">if</span> <span class="n">expression</span> <span class="k">else</span> <span class="s2">&quot;&quot;</span>
</span><span id="L-163"><a href="#L-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="L-164"><a href="#L-164"><span class="linenos">164</span></a> <span class="p">]</span>
</span><span id="L-135"><a href="#L-135"><span class="linenos">135</span></a>
</span><span id="L-136"><a href="#L-136"><span class="linenos">136</span></a><span class="k">def</span> <span class="nf">transpile</span><span class="p">(</span>
</span><span id="L-137"><a href="#L-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="L-138"><a href="#L-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="L-139"><a href="#L-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="L-140"><a href="#L-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="L-141"><a href="#L-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="L-142"><a href="#L-142"><span class="linenos">142</span></a> <span class="o">**</span><span class="n">opts</span><span class="p">,</span>
</span><span id="L-143"><a href="#L-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="L-144"><a href="#L-144"><span class="linenos">144</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-145"><a href="#L-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="L-146"><a href="#L-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="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 class="sd"> Args:</span>
</span><span id="L-149"><a href="#L-149"><span class="linenos">149</span></a><span class="sd"> sql: the SQL code string to transpile.</span>
</span><span id="L-150"><a href="#L-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="L-151"><a href="#L-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="L-152"><a href="#L-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="L-153"><a href="#L-153"><span class="linenos">153</span></a><span class="sd"> the source and the target dialect.</span>
</span><span id="L-154"><a href="#L-154"><span class="linenos">154</span></a><span class="sd"> error_level: the desired error level of the parser.</span>
</span><span id="L-155"><a href="#L-155"><span class="linenos">155</span></a><span class="sd"> **opts: other `sqlglot.generator.Generator` options.</span>
</span><span id="L-156"><a href="#L-156"><span class="linenos">156</span></a>
</span><span id="L-157"><a href="#L-157"><span class="linenos">157</span></a><span class="sd"> Returns:</span>
</span><span id="L-158"><a href="#L-158"><span class="linenos">158</span></a><span class="sd"> The list of transpiled SQL statements.</span>
</span><span id="L-159"><a href="#L-159"><span class="linenos">159</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-160"><a href="#L-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="L-161"><a href="#L-161"><span class="linenos">161</span></a> <span class="n">write</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">write</span><span class="p">)</span>
</span><span id="L-162"><a href="#L-162"><span class="linenos">162</span></a> <span class="k">return</span> <span class="p">[</span>
</span><span id="L-163"><a href="#L-163"><span class="linenos">163</span></a> <span class="n">write</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="n">copy</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span> <span class="k">if</span> <span class="n">expression</span> <span class="k">else</span> <span class="s2">&quot;&quot;</span>
</span><span id="L-164"><a href="#L-164"><span class="linenos">164</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-165"><a href="#L-165"><span class="linenos">165</span></a> <span class="p">]</span>
</span></pre></div>
@ -926,22 +927,22 @@ make check # Full test suite &amp; linter checks
</div>
<a class="headerlink" href="#parse"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="parse-72"><a href="#parse-72"><span class="linenos">72</span></a><span class="k">def</span> <span class="nf">parse</span><span class="p">(</span>
</span><span id="parse-73"><a href="#parse-73"><span class="linenos">73</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-74"><a href="#parse-74"><span class="linenos">74</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-75"><a href="#parse-75"><span class="linenos">75</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="parse-76"><a href="#parse-76"><span class="linenos">76</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-77"><a href="#parse-77"><span class="linenos">77</span></a>
</span><span id="parse-78"><a href="#parse-78"><span class="linenos">78</span></a><span class="sd"> Args:</span>
</span><span id="parse-79"><a href="#parse-79"><span class="linenos">79</span></a><span class="sd"> sql: the SQL code string to parse.</span>
</span><span id="parse-80"><a href="#parse-80"><span class="linenos">80</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-81"><a href="#parse-81"><span class="linenos">81</span></a><span class="sd"> dialect: the SQL dialect (alias for read).</span>
</span><span id="parse-82"><a href="#parse-82"><span class="linenos">82</span></a><span class="sd"> **opts: other `sqlglot.parser.Parser` options.</span>
</span><span id="parse-83"><a href="#parse-83"><span class="linenos">83</span></a>
</span><span id="parse-84"><a href="#parse-84"><span class="linenos">84</span></a><span class="sd"> Returns:</span>
</span><span id="parse-85"><a href="#parse-85"><span class="linenos">85</span></a><span class="sd"> The resulting syntax tree collection.</span>
</span><span id="parse-86"><a href="#parse-86"><span class="linenos">86</span></a><span class="sd"> &quot;&quot;&quot;</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">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 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>
<div class="pdoc-code codehilite"><pre><span></span><span id="parse-73"><a href="#parse-73"><span class="linenos">73</span></a><span class="k">def</span> <span class="nf">parse</span><span class="p">(</span>
</span><span id="parse-74"><a href="#parse-74"><span class="linenos">74</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-75"><a href="#parse-75"><span class="linenos">75</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-76"><a href="#parse-76"><span class="linenos">76</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="parse-77"><a href="#parse-77"><span class="linenos">77</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-78"><a href="#parse-78"><span class="linenos">78</span></a>
</span><span id="parse-79"><a href="#parse-79"><span class="linenos">79</span></a><span class="sd"> Args:</span>
</span><span id="parse-80"><a href="#parse-80"><span class="linenos">80</span></a><span class="sd"> sql: the SQL code string to parse.</span>
</span><span id="parse-81"><a href="#parse-81"><span class="linenos">81</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-82"><a href="#parse-82"><span class="linenos">82</span></a><span class="sd"> dialect: the SQL dialect (alias for read).</span>
</span><span id="parse-83"><a href="#parse-83"><span class="linenos">83</span></a><span class="sd"> **opts: other `sqlglot.parser.Parser` options.</span>
</span><span id="parse-84"><a href="#parse-84"><span class="linenos">84</span></a>
</span><span id="parse-85"><a href="#parse-85"><span class="linenos">85</span></a><span class="sd"> Returns:</span>
</span><span id="parse-86"><a href="#parse-86"><span class="linenos">86</span></a><span class="sd"> The resulting syntax tree collection.</span>
</span><span id="parse-87"><a href="#parse-87"><span class="linenos">87</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="parse-88"><a href="#parse-88"><span class="linenos">88</span></a> <span class="k">return</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 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>
@ -976,40 +977,40 @@ make check # Full test suite &amp; linter checks
</div>
<a class="headerlink" href="#parse_one"></a>
<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-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-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-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-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-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-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-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-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-109"><a href="#parse_one-109"><span class="linenos">109</span></a>
</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-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-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-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-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-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-116"><a href="#parse_one-116"><span class="linenos">116</span></a>
</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-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-119"><a href="#parse_one-119"><span class="linenos">119</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="parse_one-120"><a href="#parse_one-120"><span class="linenos">120</span></a>
</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-122"><a href="#parse_one-122"><span class="linenos">122</span></a>
</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-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-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-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-127"><a href="#parse_one-127"><span class="linenos">127</span></a>
</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-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-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>
<div class="pdoc-code codehilite"><pre><span></span><span id="parse_one-101"><a href="#parse_one-101"><span class="linenos">101</span></a><span class="k">def</span> <span class="nf">parse_one</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">sql</span><span class="p">:</span> <span class="nb">str</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">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-104"><a href="#parse_one-104"><span class="linenos">104</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-105"><a href="#parse_one-105"><span class="linenos">105</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-106"><a href="#parse_one-106"><span class="linenos">106</span></a> <span class="o">**</span><span class="n">opts</span><span class="p">,</span>
</span><span id="parse_one-107"><a href="#parse_one-107"><span class="linenos">107</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-108"><a href="#parse_one-108"><span class="linenos">108</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="parse_one-109"><a href="#parse_one-109"><span class="linenos">109</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-110"><a href="#parse_one-110"><span class="linenos">110</span></a>
</span><span id="parse_one-111"><a href="#parse_one-111"><span class="linenos">111</span></a><span class="sd"> Args:</span>
</span><span id="parse_one-112"><a href="#parse_one-112"><span class="linenos">112</span></a><span class="sd"> sql: the SQL code string to parse.</span>
</span><span id="parse_one-113"><a href="#parse_one-113"><span class="linenos">113</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-114"><a href="#parse_one-114"><span class="linenos">114</span></a><span class="sd"> dialect: the SQL dialect (alias for read)</span>
</span><span id="parse_one-115"><a href="#parse_one-115"><span class="linenos">115</span></a><span class="sd"> into: the SQLGlot Expression to parse into.</span>
</span><span id="parse_one-116"><a href="#parse_one-116"><span class="linenos">116</span></a><span class="sd"> **opts: other `sqlglot.parser.Parser` options.</span>
</span><span id="parse_one-117"><a href="#parse_one-117"><span class="linenos">117</span></a>
</span><span id="parse_one-118"><a href="#parse_one-118"><span class="linenos">118</span></a><span class="sd"> Returns:</span>
</span><span id="parse_one-119"><a href="#parse_one-119"><span class="linenos">119</span></a><span class="sd"> The syntax tree for the first parsed statement.</span>
</span><span id="parse_one-120"><a href="#parse_one-120"><span class="linenos">120</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="parse_one-121"><a href="#parse_one-121"><span class="linenos">121</span></a>
</span><span id="parse_one-122"><a href="#parse_one-122"><span class="linenos">122</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-123"><a href="#parse_one-123"><span class="linenos">123</span></a>
</span><span id="parse_one-124"><a href="#parse_one-124"><span class="linenos">124</span></a> <span class="k">if</span> <span class="n">into</span><span class="p">:</span>
</span><span id="parse_one-125"><a href="#parse_one-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_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-126"><a href="#parse_one-126"><span class="linenos">126</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="parse_one-127"><a href="#parse_one-127"><span class="linenos">127</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-128"><a href="#parse_one-128"><span class="linenos">128</span></a>
</span><span id="parse_one-129"><a href="#parse_one-129"><span class="linenos">129</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-130"><a href="#parse_one-130"><span class="linenos">130</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-131"><a href="#parse_one-131"><span class="linenos">131</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-132"><a href="#parse_one-132"><span class="linenos">132</span></a> <span class="k">return</span> <span class="n">expression</span>
</span><span id="parse_one-133"><a href="#parse_one-133"><span class="linenos">133</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="parse_one-134"><a href="#parse_one-134"><span class="linenos">134</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>
@ -1045,36 +1046,36 @@ make check # Full test suite &amp; linter checks
</div>
<a class="headerlink" href="#transpile"></a>
<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-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-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-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-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-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-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-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-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-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-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-147"><a href="#transpile-147"><span class="linenos">147</span></a>
</span><span id="transpile-148"><a href="#transpile-148"><span class="linenos">148</span></a><span class="sd"> Args:</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-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-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-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-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-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-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-156"><a href="#transpile-156"><span class="linenos">156</span></a>
</span><span id="transpile-157"><a href="#transpile-157"><span class="linenos">157</span></a><span class="sd"> Returns:</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-159"><a href="#transpile-159"><span class="linenos">159</span></a><span class="sd"> &quot;&quot;&quot;</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-161"><a href="#transpile-161"><span class="linenos">161</span></a> <span class="n">write</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">write</span><span class="p">)</span>
</span><span id="transpile-162"><a href="#transpile-162"><span class="linenos">162</span></a> <span class="k">return</span> <span class="p">[</span>
</span><span id="transpile-163"><a href="#transpile-163"><span class="linenos">163</span></a> <span class="n">write</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="n">copy</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span> <span class="k">if</span> <span class="n">expression</span> <span class="k">else</span> <span class="s2">&quot;&quot;</span>
</span><span id="transpile-164"><a href="#transpile-164"><span class="linenos">164</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-165"><a href="#transpile-165"><span class="linenos">165</span></a> <span class="p">]</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="transpile-137"><a href="#transpile-137"><span class="linenos">137</span></a><span class="k">def</span> <span class="nf">transpile</span><span class="p">(</span>
</span><span id="transpile-138"><a href="#transpile-138"><span class="linenos">138</span></a> <span class="n">sql</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span>
</span><span id="transpile-139"><a href="#transpile-139"><span class="linenos">139</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-140"><a href="#transpile-140"><span class="linenos">140</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-141"><a href="#transpile-141"><span class="linenos">141</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-142"><a href="#transpile-142"><span class="linenos">142</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-143"><a href="#transpile-143"><span class="linenos">143</span></a> <span class="o">**</span><span class="n">opts</span><span class="p">,</span>
</span><span id="transpile-144"><a href="#transpile-144"><span class="linenos">144</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-145"><a href="#transpile-145"><span class="linenos">145</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="transpile-146"><a href="#transpile-146"><span class="linenos">146</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-147"><a href="#transpile-147"><span class="linenos">147</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-148"><a href="#transpile-148"><span class="linenos">148</span></a>
</span><span id="transpile-149"><a href="#transpile-149"><span class="linenos">149</span></a><span class="sd"> Args:</span>
</span><span id="transpile-150"><a href="#transpile-150"><span class="linenos">150</span></a><span class="sd"> sql: the SQL code string to transpile.</span>
</span><span id="transpile-151"><a href="#transpile-151"><span class="linenos">151</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-152"><a href="#transpile-152"><span class="linenos">152</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-153"><a href="#transpile-153"><span class="linenos">153</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-154"><a href="#transpile-154"><span class="linenos">154</span></a><span class="sd"> the source and the target dialect.</span>
</span><span id="transpile-155"><a href="#transpile-155"><span class="linenos">155</span></a><span class="sd"> error_level: the desired error level of the parser.</span>
</span><span id="transpile-156"><a href="#transpile-156"><span class="linenos">156</span></a><span class="sd"> **opts: other `sqlglot.generator.Generator` options.</span>
</span><span id="transpile-157"><a href="#transpile-157"><span class="linenos">157</span></a>
</span><span id="transpile-158"><a href="#transpile-158"><span class="linenos">158</span></a><span class="sd"> Returns:</span>
</span><span id="transpile-159"><a href="#transpile-159"><span class="linenos">159</span></a><span class="sd"> The list of transpiled SQL statements.</span>
</span><span id="transpile-160"><a href="#transpile-160"><span class="linenos">160</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="transpile-161"><a href="#transpile-161"><span class="linenos">161</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-162"><a href="#transpile-162"><span class="linenos">162</span></a> <span class="n">write</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">write</span><span class="p">)</span>
</span><span id="transpile-163"><a href="#transpile-163"><span class="linenos">163</span></a> <span class="k">return</span> <span class="p">[</span>
</span><span id="transpile-164"><a href="#transpile-164"><span class="linenos">164</span></a> <span class="n">write</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="n">copy</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span> <span class="k">if</span> <span class="n">expression</span> <span class="k">else</span> <span class="s2">&quot;&quot;</span>
</span><span id="transpile-165"><a href="#transpile-165"><span class="linenos">165</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-166"><a href="#transpile-166"><span class="linenos">166</span></a> <span class="p">]</span>
</span></pre></div>

View file

@ -57,17 +57,18 @@
</span><span id="L-2"><a href="#L-2"><span class="linenos"> 2</span></a>
</span><span id="L-3"><a href="#L-3"><span class="linenos"> 3</span></a><span class="kn">import</span> <span class="nn">typing</span> <span class="k">as</span> <span class="nn">t</span>
</span><span id="L-4"><a href="#L-4"><span class="linenos"> 4</span></a>
</span><span id="L-5"><a href="#L-5"><span class="linenos"> 5</span></a><span class="kn">from</span> <span class="nn">typing_extensions</span> <span class="kn">import</span> <span class="n">Literal</span> <span class="k">as</span> <span class="n">Lit</span> <span class="c1"># noqa</span>
</span><span id="L-5"><a href="#L-5"><span class="linenos"> 5</span></a><span class="kn">import</span> <span class="nn">sqlglot</span>
</span><span id="L-6"><a href="#L-6"><span class="linenos"> 6</span></a>
</span><span id="L-7"><a href="#L-7"><span class="linenos"> 7</span></a><span class="kn">import</span> <span class="nn">sqlglot</span>
</span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</span></a>
</span><span id="L-9"><a href="#L-9"><span class="linenos"> 9</span></a><span class="c1"># A little hack for backwards compatibility with Python 3.7.</span>
</span><span id="L-10"><a href="#L-10"><span class="linenos">10</span></a><span class="c1"># For example, we might want a TypeVar for objects that support comparison e.g. SupportsRichComparisonT from typeshed.</span>
</span><span id="L-11"><a href="#L-11"><span class="linenos">11</span></a><span class="c1"># But Python 3.7 doesn&#39;t support Protocols, so we&#39;d also need typing_extensions, which we don&#39;t want as a dependency.</span>
</span><span id="L-12"><a href="#L-12"><span class="linenos">12</span></a><span class="n">A</span> <span class="o">=</span> <span class="n">t</span><span class="o">.</span><span class="n">TypeVar</span><span class="p">(</span><span class="s2">&quot;A&quot;</span><span class="p">,</span> <span class="n">bound</span><span class="o">=</span><span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">)</span>
</span><span id="L-13"><a href="#L-13"><span class="linenos">13</span></a>
</span><span id="L-14"><a href="#L-14"><span class="linenos">14</span></a><span class="n">E</span> <span class="o">=</span> <span class="n">t</span><span class="o">.</span><span class="n">TypeVar</span><span class="p">(</span><span class="s2">&quot;E&quot;</span><span class="p">,</span> <span class="n">bound</span><span class="o">=</span><span class="s2">&quot;sqlglot.exp.Expression&quot;</span><span class="p">)</span>
</span><span id="L-15"><a href="#L-15"><span class="linenos">15</span></a><span class="n">T</span> <span class="o">=</span> <span class="n">t</span><span class="o">.</span><span class="n">TypeVar</span><span class="p">(</span><span class="s2">&quot;T&quot;</span><span class="p">)</span>
</span><span id="L-7"><a href="#L-7"><span class="linenos"> 7</span></a><span class="k">if</span> <span class="n">t</span><span class="o">.</span><span class="n">TYPE_CHECKING</span><span class="p">:</span>
</span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</span></a> <span class="kn">from</span> <span class="nn">typing_extensions</span> <span class="kn">import</span> <span class="n">Literal</span> <span class="k">as</span> <span class="n">Lit</span> <span class="c1"># noqa</span>
</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 class="c1"># A little hack for backwards compatibility with Python 3.7.</span>
</span><span id="L-11"><a href="#L-11"><span class="linenos">11</span></a><span class="c1"># For example, we might want a TypeVar for objects that support comparison e.g. SupportsRichComparisonT from typeshed.</span>
</span><span id="L-12"><a href="#L-12"><span class="linenos">12</span></a><span class="c1"># But Python 3.7 doesn&#39;t support Protocols, so we&#39;d also need typing_extensions, which we don&#39;t want as a dependency.</span>
</span><span id="L-13"><a href="#L-13"><span class="linenos">13</span></a><span class="n">A</span> <span class="o">=</span> <span class="n">t</span><span class="o">.</span><span class="n">TypeVar</span><span class="p">(</span><span class="s2">&quot;A&quot;</span><span class="p">,</span> <span class="n">bound</span><span class="o">=</span><span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">)</span>
</span><span id="L-14"><a href="#L-14"><span class="linenos">14</span></a><span class="n">B</span> <span class="o">=</span> <span class="n">t</span><span class="o">.</span><span class="n">TypeVar</span><span class="p">(</span><span class="s2">&quot;B&quot;</span><span class="p">,</span> <span class="n">bound</span><span class="o">=</span><span class="s2">&quot;sqlglot.exp.Binary&quot;</span><span class="p">)</span>
</span><span id="L-15"><a href="#L-15"><span class="linenos">15</span></a><span class="n">E</span> <span class="o">=</span> <span class="n">t</span><span class="o">.</span><span class="n">TypeVar</span><span class="p">(</span><span class="s2">&quot;E&quot;</span><span class="p">,</span> <span class="n">bound</span><span class="o">=</span><span class="s2">&quot;sqlglot.exp.Expression&quot;</span><span class="p">)</span>
</span><span id="L-16"><a href="#L-16"><span class="linenos">16</span></a><span class="n">T</span> <span class="o">=</span> <span class="n">t</span><span class="o">.</span><span class="n">TypeVar</span><span class="p">(</span><span class="s2">&quot;T&quot;</span><span class="p">)</span>
</span></pre></div>

View file

@ -76,8 +76,8 @@
</span><span id="L-12"><a href="#L-12"><span class="linenos">12</span></a><span class="n">__version_tuple__</span><span class="p">:</span> <span class="n">VERSION_TUPLE</span>
</span><span id="L-13"><a href="#L-13"><span class="linenos">13</span></a><span class="n">version_tuple</span><span class="p">:</span> <span class="n">VERSION_TUPLE</span>
</span><span id="L-14"><a href="#L-14"><span class="linenos">14</span></a>
</span><span id="L-15"><a href="#L-15"><span class="linenos">15</span></a><span class="n">__version__</span> <span class="o">=</span> <span class="n">version</span> <span class="o">=</span> <span class="s1">&#39;20.10.0&#39;</span>
</span><span id="L-16"><a href="#L-16"><span class="linenos">16</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">20</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
</span><span id="L-15"><a href="#L-15"><span class="linenos">15</span></a><span class="n">__version__</span> <span class="o">=</span> <span class="n">version</span> <span class="o">=</span> <span class="s1">&#39;21.0.0&#39;</span>
</span><span id="L-16"><a href="#L-16"><span class="linenos">16</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">21</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
</span></pre></div>
@ -97,7 +97,7 @@
<section id="version">
<div class="attr variable">
<span class="name">version</span><span class="annotation">: str</span> =
<span class="default_value">&#39;20.10.0&#39;</span>
<span class="default_value">&#39;21.0.0&#39;</span>
</div>
@ -109,7 +109,7 @@
<section id="version_tuple">
<div class="attr variable">
<span class="name">version_tuple</span><span class="annotation">: object</span> =
<span class="default_value">(20, 10, 0)</span>
<span class="default_value">(21, 0, 0)</span>
</div>

File diff suppressed because it is too large Load diff

View file

@ -76,7 +76,7 @@
<p>While there is a SQL standard, most SQL engines support a variation of that standard. This makes it difficult
to write portable SQL code. SQLGlot bridges all the different variations, called "dialects", with an extensible
SQL transpilation framework. </p>
SQL transpilation framework.</p>
<p>The base <code><a href="dialects/dialect.html#Dialect">sqlglot.dialects.dialect.Dialect</a></code> class implements a generic dialect that aims to be as universal as possible.</p>
@ -138,90 +138,91 @@ dialect implementations in order to understand how their various components can
<label class="view-source-button" for="mod-dialects-view-source"><span>View Source</span></label>
<div class="pdoc-code codehilite"><pre><span></span><span id="L-1"><a href="#L-1"><span class="linenos"> 1</span></a><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-2"><a href="#L-2"><span class="linenos"> 2</span></a><span class="sd">## Dialects</span>
</span><span id="L-3"><a href="#L-3"><span class="linenos"> 3</span></a>
</span><span id="L-4"><a href="#L-4"><span class="linenos"> 4</span></a><span class="sd">While there is a SQL standard, most SQL engines support a variation of that standard. This makes it difficult</span>
</span><span id="L-5"><a href="#L-5"><span class="linenos"> 5</span></a><span class="sd">to write portable SQL code. SQLGlot bridges all the different variations, called &quot;dialects&quot;, with an extensible</span>
</span><span id="L-6"><a href="#L-6"><span class="linenos"> 6</span></a><span class="sd">SQL transpilation framework. </span>
</span><span id="L-7"><a href="#L-7"><span class="linenos"> 7</span></a>
</span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</span></a><span class="sd">The base `sqlglot.dialects.dialect.Dialect` class implements a generic dialect that aims to be as universal as possible.</span>
</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 class="sd">Each SQL variation has its own `Dialect` subclass, extending the corresponding `Tokenizer`, `Parser` and `Generator`</span>
</span><span id="L-11"><a href="#L-11"><span class="linenos">11</span></a><span class="sd">classes as needed.</span>
</span><span id="L-12"><a href="#L-12"><span class="linenos">12</span></a>
</span><span id="L-13"><a href="#L-13"><span class="linenos">13</span></a><span class="sd">### Implementing a custom Dialect</span>
</span><span id="L-14"><a href="#L-14"><span class="linenos">14</span></a>
</span><span id="L-15"><a href="#L-15"><span class="linenos">15</span></a><span class="sd">Creating a new SQL dialect may seem complicated at first, but it is actually quite simple in SQLGlot:</span>
</span><span id="L-16"><a href="#L-16"><span class="linenos">16</span></a>
</span><span id="L-17"><a href="#L-17"><span class="linenos">17</span></a><span class="sd">```python</span>
</span><span id="L-18"><a href="#L-18"><span class="linenos">18</span></a><span class="sd">from sqlglot import exp</span>
</span><span id="L-19"><a href="#L-19"><span class="linenos">19</span></a><span class="sd">from sqlglot.dialects.dialect import Dialect</span>
</span><span id="L-20"><a href="#L-20"><span class="linenos">20</span></a><span class="sd">from sqlglot.generator import Generator</span>
</span><span id="L-21"><a href="#L-21"><span class="linenos">21</span></a><span class="sd">from sqlglot.tokens import Tokenizer, TokenType</span>
</span><span id="L-22"><a href="#L-22"><span class="linenos">22</span></a>
<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"># ruff: noqa: F401</span>
</span><span id="L-2"><a href="#L-2"><span class="linenos"> 2</span></a><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-3"><a href="#L-3"><span class="linenos"> 3</span></a><span class="sd">## Dialects</span>
</span><span id="L-4"><a href="#L-4"><span class="linenos"> 4</span></a>
</span><span id="L-5"><a href="#L-5"><span class="linenos"> 5</span></a><span class="sd">While there is a SQL standard, most SQL engines support a variation of that standard. This makes it difficult</span>
</span><span id="L-6"><a href="#L-6"><span class="linenos"> 6</span></a><span class="sd">to write portable SQL code. SQLGlot bridges all the different variations, called &quot;dialects&quot;, with an extensible</span>
</span><span id="L-7"><a href="#L-7"><span class="linenos"> 7</span></a><span class="sd">SQL transpilation framework.</span>
</span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</span></a>
</span><span id="L-9"><a href="#L-9"><span class="linenos"> 9</span></a><span class="sd">The base `sqlglot.dialects.dialect.Dialect` class implements a generic dialect that aims to be as universal as possible.</span>
</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="sd">Each SQL variation has its own `Dialect` subclass, extending the corresponding `Tokenizer`, `Parser` and `Generator`</span>
</span><span id="L-12"><a href="#L-12"><span class="linenos">12</span></a><span class="sd">classes as needed.</span>
</span><span id="L-13"><a href="#L-13"><span class="linenos">13</span></a>
</span><span id="L-14"><a href="#L-14"><span class="linenos">14</span></a><span class="sd">### Implementing a custom Dialect</span>
</span><span id="L-15"><a href="#L-15"><span class="linenos">15</span></a>
</span><span id="L-16"><a href="#L-16"><span class="linenos">16</span></a><span class="sd">Creating a new SQL dialect may seem complicated at first, but it is actually quite simple in SQLGlot:</span>
</span><span id="L-17"><a href="#L-17"><span class="linenos">17</span></a>
</span><span id="L-18"><a href="#L-18"><span class="linenos">18</span></a><span class="sd">```python</span>
</span><span id="L-19"><a href="#L-19"><span class="linenos">19</span></a><span class="sd">from sqlglot import exp</span>
</span><span id="L-20"><a href="#L-20"><span class="linenos">20</span></a><span class="sd">from sqlglot.dialects.dialect import Dialect</span>
</span><span id="L-21"><a href="#L-21"><span class="linenos">21</span></a><span class="sd">from sqlglot.generator import Generator</span>
</span><span id="L-22"><a href="#L-22"><span class="linenos">22</span></a><span class="sd">from sqlglot.tokens import Tokenizer, TokenType</span>
</span><span id="L-23"><a href="#L-23"><span class="linenos">23</span></a>
</span><span id="L-24"><a href="#L-24"><span class="linenos">24</span></a><span class="sd">class Custom(Dialect):</span>
</span><span id="L-25"><a href="#L-25"><span class="linenos">25</span></a><span class="sd"> class Tokenizer(Tokenizer):</span>
</span><span id="L-26"><a href="#L-26"><span class="linenos">26</span></a><span class="sd"> QUOTES = [&quot;&#39;&quot;, &#39;&quot;&#39;] # Strings can be delimited by either single or double quotes</span>
</span><span id="L-27"><a href="#L-27"><span class="linenos">27</span></a><span class="sd"> IDENTIFIERS = [&quot;`&quot;] # Identifiers can be delimited by backticks</span>
</span><span id="L-28"><a href="#L-28"><span class="linenos">28</span></a>
</span><span id="L-29"><a href="#L-29"><span class="linenos">29</span></a><span class="sd"> # Associates certain meaningful words with tokens that capture their intent</span>
</span><span id="L-30"><a href="#L-30"><span class="linenos">30</span></a><span class="sd"> KEYWORDS = {</span>
</span><span id="L-31"><a href="#L-31"><span class="linenos">31</span></a><span class="sd"> **Tokenizer.KEYWORDS,</span>
</span><span id="L-32"><a href="#L-32"><span class="linenos">32</span></a><span class="sd"> &quot;INT64&quot;: TokenType.BIGINT,</span>
</span><span id="L-33"><a href="#L-33"><span class="linenos">33</span></a><span class="sd"> &quot;FLOAT64&quot;: TokenType.DOUBLE,</span>
</span><span id="L-34"><a href="#L-34"><span class="linenos">34</span></a><span class="sd"> }</span>
</span><span id="L-35"><a href="#L-35"><span class="linenos">35</span></a>
</span><span id="L-36"><a href="#L-36"><span class="linenos">36</span></a><span class="sd"> class Generator(Generator):</span>
</span><span id="L-37"><a href="#L-37"><span class="linenos">37</span></a><span class="sd"> # Specifies how AST nodes, i.e. subclasses of exp.Expression, should be converted into SQL</span>
</span><span id="L-38"><a href="#L-38"><span class="linenos">38</span></a><span class="sd"> TRANSFORMS = {</span>
</span><span id="L-39"><a href="#L-39"><span class="linenos">39</span></a><span class="sd"> exp.Array: lambda self, e: f&quot;[{self.expressions(e)}]&quot;,</span>
</span><span id="L-40"><a href="#L-40"><span class="linenos">40</span></a><span class="sd"> }</span>
</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="sd"> # Specifies how AST nodes representing data types should be converted into SQL</span>
</span><span id="L-43"><a href="#L-43"><span class="linenos">43</span></a><span class="sd"> TYPE_MAPPING = {</span>
</span><span id="L-44"><a href="#L-44"><span class="linenos">44</span></a><span class="sd"> exp.DataType.Type.TINYINT: &quot;INT64&quot;,</span>
</span><span id="L-45"><a href="#L-45"><span class="linenos">45</span></a><span class="sd"> exp.DataType.Type.SMALLINT: &quot;INT64&quot;,</span>
</span><span id="L-46"><a href="#L-46"><span class="linenos">46</span></a><span class="sd"> exp.DataType.Type.INT: &quot;INT64&quot;,</span>
</span><span id="L-47"><a href="#L-47"><span class="linenos">47</span></a><span class="sd"> exp.DataType.Type.BIGINT: &quot;INT64&quot;,</span>
</span><span id="L-48"><a href="#L-48"><span class="linenos">48</span></a><span class="sd"> exp.DataType.Type.DECIMAL: &quot;NUMERIC&quot;,</span>
</span><span id="L-49"><a href="#L-49"><span class="linenos">49</span></a><span class="sd"> exp.DataType.Type.FLOAT: &quot;FLOAT64&quot;,</span>
</span><span id="L-50"><a href="#L-50"><span class="linenos">50</span></a><span class="sd"> exp.DataType.Type.DOUBLE: &quot;FLOAT64&quot;,</span>
</span><span id="L-51"><a href="#L-51"><span class="linenos">51</span></a><span class="sd"> exp.DataType.Type.BOOLEAN: &quot;BOOL&quot;,</span>
</span><span id="L-52"><a href="#L-52"><span class="linenos">52</span></a><span class="sd"> exp.DataType.Type.TEXT: &quot;STRING&quot;,</span>
</span><span id="L-53"><a href="#L-53"><span class="linenos">53</span></a><span class="sd"> }</span>
</span><span id="L-54"><a href="#L-54"><span class="linenos">54</span></a><span class="sd">```</span>
</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="sd">The above example demonstrates how certain parts of the base `Dialect` class can be overridden to match a different</span>
</span><span id="L-57"><a href="#L-57"><span class="linenos">57</span></a><span class="sd">specification. Even though it is a fairly realistic starting point, we strongly encourage the reader to study existing</span>
</span><span id="L-58"><a href="#L-58"><span class="linenos">58</span></a><span class="sd">dialect implementations in order to understand how their various components can be modified, depending on the use-case.</span>
</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="sd">----</span>
</span><span id="L-61"><a href="#L-61"><span class="linenos">61</span></a><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-62"><a href="#L-62"><span class="linenos">62</span></a>
</span><span id="L-63"><a href="#L-63"><span class="linenos">63</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.bigquery</span> <span class="kn">import</span> <span class="n">BigQuery</span>
</span><span id="L-64"><a href="#L-64"><span class="linenos">64</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.clickhouse</span> <span class="kn">import</span> <span class="n">ClickHouse</span>
</span><span id="L-65"><a href="#L-65"><span class="linenos">65</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.databricks</span> <span class="kn">import</span> <span class="n">Databricks</span>
</span><span id="L-66"><a href="#L-66"><span class="linenos">66</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.dialect</span> <span class="kn">import</span> <span class="n">Dialect</span><span class="p">,</span> <span class="n">Dialects</span>
</span><span id="L-67"><a href="#L-67"><span class="linenos">67</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.doris</span> <span class="kn">import</span> <span class="n">Doris</span>
</span><span id="L-68"><a href="#L-68"><span class="linenos">68</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.drill</span> <span class="kn">import</span> <span class="n">Drill</span>
</span><span id="L-69"><a href="#L-69"><span class="linenos">69</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.duckdb</span> <span class="kn">import</span> <span class="n">DuckDB</span>
</span><span id="L-70"><a href="#L-70"><span class="linenos">70</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.hive</span> <span class="kn">import</span> <span class="n">Hive</span>
</span><span id="L-71"><a href="#L-71"><span class="linenos">71</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.mysql</span> <span class="kn">import</span> <span class="n">MySQL</span>
</span><span id="L-72"><a href="#L-72"><span class="linenos">72</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.oracle</span> <span class="kn">import</span> <span class="n">Oracle</span>
</span><span id="L-73"><a href="#L-73"><span class="linenos">73</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.postgres</span> <span class="kn">import</span> <span class="n">Postgres</span>
</span><span id="L-74"><a href="#L-74"><span class="linenos">74</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.presto</span> <span class="kn">import</span> <span class="n">Presto</span>
</span><span id="L-75"><a href="#L-75"><span class="linenos">75</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.redshift</span> <span class="kn">import</span> <span class="n">Redshift</span>
</span><span id="L-76"><a href="#L-76"><span class="linenos">76</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.snowflake</span> <span class="kn">import</span> <span class="n">Snowflake</span>
</span><span id="L-77"><a href="#L-77"><span class="linenos">77</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.spark</span> <span class="kn">import</span> <span class="n">Spark</span>
</span><span id="L-78"><a href="#L-78"><span class="linenos">78</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.spark2</span> <span class="kn">import</span> <span class="n">Spark2</span>
</span><span id="L-79"><a href="#L-79"><span class="linenos">79</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.sqlite</span> <span class="kn">import</span> <span class="n">SQLite</span>
</span><span id="L-80"><a href="#L-80"><span class="linenos">80</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.starrocks</span> <span class="kn">import</span> <span class="n">StarRocks</span>
</span><span id="L-81"><a href="#L-81"><span class="linenos">81</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.tableau</span> <span class="kn">import</span> <span class="n">Tableau</span>
</span><span id="L-82"><a href="#L-82"><span class="linenos">82</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.teradata</span> <span class="kn">import</span> <span class="n">Teradata</span>
</span><span id="L-83"><a href="#L-83"><span class="linenos">83</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.trino</span> <span class="kn">import</span> <span class="n">Trino</span>
</span><span id="L-84"><a href="#L-84"><span class="linenos">84</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.tsql</span> <span class="kn">import</span> <span class="n">TSQL</span>
</span><span id="L-24"><a href="#L-24"><span class="linenos">24</span></a>
</span><span id="L-25"><a href="#L-25"><span class="linenos">25</span></a><span class="sd">class Custom(Dialect):</span>
</span><span id="L-26"><a href="#L-26"><span class="linenos">26</span></a><span class="sd"> class Tokenizer(Tokenizer):</span>
</span><span id="L-27"><a href="#L-27"><span class="linenos">27</span></a><span class="sd"> QUOTES = [&quot;&#39;&quot;, &#39;&quot;&#39;] # Strings can be delimited by either single or double quotes</span>
</span><span id="L-28"><a href="#L-28"><span class="linenos">28</span></a><span class="sd"> IDENTIFIERS = [&quot;`&quot;] # Identifiers can be delimited by backticks</span>
</span><span id="L-29"><a href="#L-29"><span class="linenos">29</span></a>
</span><span id="L-30"><a href="#L-30"><span class="linenos">30</span></a><span class="sd"> # Associates certain meaningful words with tokens that capture their intent</span>
</span><span id="L-31"><a href="#L-31"><span class="linenos">31</span></a><span class="sd"> KEYWORDS = {</span>
</span><span id="L-32"><a href="#L-32"><span class="linenos">32</span></a><span class="sd"> **Tokenizer.KEYWORDS,</span>
</span><span id="L-33"><a href="#L-33"><span class="linenos">33</span></a><span class="sd"> &quot;INT64&quot;: TokenType.BIGINT,</span>
</span><span id="L-34"><a href="#L-34"><span class="linenos">34</span></a><span class="sd"> &quot;FLOAT64&quot;: TokenType.DOUBLE,</span>
</span><span id="L-35"><a href="#L-35"><span class="linenos">35</span></a><span class="sd"> }</span>
</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"> class Generator(Generator):</span>
</span><span id="L-38"><a href="#L-38"><span class="linenos">38</span></a><span class="sd"> # Specifies how AST nodes, i.e. subclasses of exp.Expression, should be converted into SQL</span>
</span><span id="L-39"><a href="#L-39"><span class="linenos">39</span></a><span class="sd"> TRANSFORMS = {</span>
</span><span id="L-40"><a href="#L-40"><span class="linenos">40</span></a><span class="sd"> exp.Array: lambda self, e: f&quot;[{self.expressions(e)}]&quot;,</span>
</span><span id="L-41"><a href="#L-41"><span class="linenos">41</span></a><span class="sd"> }</span>
</span><span id="L-42"><a href="#L-42"><span class="linenos">42</span></a>
</span><span id="L-43"><a href="#L-43"><span class="linenos">43</span></a><span class="sd"> # Specifies how AST nodes representing data types should be converted into SQL</span>
</span><span id="L-44"><a href="#L-44"><span class="linenos">44</span></a><span class="sd"> TYPE_MAPPING = {</span>
</span><span id="L-45"><a href="#L-45"><span class="linenos">45</span></a><span class="sd"> exp.DataType.Type.TINYINT: &quot;INT64&quot;,</span>
</span><span id="L-46"><a href="#L-46"><span class="linenos">46</span></a><span class="sd"> exp.DataType.Type.SMALLINT: &quot;INT64&quot;,</span>
</span><span id="L-47"><a href="#L-47"><span class="linenos">47</span></a><span class="sd"> exp.DataType.Type.INT: &quot;INT64&quot;,</span>
</span><span id="L-48"><a href="#L-48"><span class="linenos">48</span></a><span class="sd"> exp.DataType.Type.BIGINT: &quot;INT64&quot;,</span>
</span><span id="L-49"><a href="#L-49"><span class="linenos">49</span></a><span class="sd"> exp.DataType.Type.DECIMAL: &quot;NUMERIC&quot;,</span>
</span><span id="L-50"><a href="#L-50"><span class="linenos">50</span></a><span class="sd"> exp.DataType.Type.FLOAT: &quot;FLOAT64&quot;,</span>
</span><span id="L-51"><a href="#L-51"><span class="linenos">51</span></a><span class="sd"> exp.DataType.Type.DOUBLE: &quot;FLOAT64&quot;,</span>
</span><span id="L-52"><a href="#L-52"><span class="linenos">52</span></a><span class="sd"> exp.DataType.Type.BOOLEAN: &quot;BOOL&quot;,</span>
</span><span id="L-53"><a href="#L-53"><span class="linenos">53</span></a><span class="sd"> exp.DataType.Type.TEXT: &quot;STRING&quot;,</span>
</span><span id="L-54"><a href="#L-54"><span class="linenos">54</span></a><span class="sd"> }</span>
</span><span id="L-55"><a href="#L-55"><span class="linenos">55</span></a><span class="sd">```</span>
</span><span id="L-56"><a href="#L-56"><span class="linenos">56</span></a>
</span><span id="L-57"><a href="#L-57"><span class="linenos">57</span></a><span class="sd">The above example demonstrates how certain parts of the base `Dialect` class can be overridden to match a different</span>
</span><span id="L-58"><a href="#L-58"><span class="linenos">58</span></a><span class="sd">specification. Even though it is a fairly realistic starting point, we strongly encourage the reader to study existing</span>
</span><span id="L-59"><a href="#L-59"><span class="linenos">59</span></a><span class="sd">dialect implementations in order to understand how their various components can be modified, depending on the use-case.</span>
</span><span id="L-60"><a href="#L-60"><span class="linenos">60</span></a>
</span><span id="L-61"><a href="#L-61"><span class="linenos">61</span></a><span class="sd">----</span>
</span><span id="L-62"><a href="#L-62"><span class="linenos">62</span></a><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-63"><a href="#L-63"><span class="linenos">63</span></a>
</span><span id="L-64"><a href="#L-64"><span class="linenos">64</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.bigquery</span> <span class="kn">import</span> <span class="n">BigQuery</span>
</span><span id="L-65"><a href="#L-65"><span class="linenos">65</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.clickhouse</span> <span class="kn">import</span> <span class="n">ClickHouse</span>
</span><span id="L-66"><a href="#L-66"><span class="linenos">66</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.databricks</span> <span class="kn">import</span> <span class="n">Databricks</span>
</span><span id="L-67"><a href="#L-67"><span class="linenos">67</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.dialect</span> <span class="kn">import</span> <span class="n">Dialect</span><span class="p">,</span> <span class="n">Dialects</span>
</span><span id="L-68"><a href="#L-68"><span class="linenos">68</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.doris</span> <span class="kn">import</span> <span class="n">Doris</span>
</span><span id="L-69"><a href="#L-69"><span class="linenos">69</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.drill</span> <span class="kn">import</span> <span class="n">Drill</span>
</span><span id="L-70"><a href="#L-70"><span class="linenos">70</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.duckdb</span> <span class="kn">import</span> <span class="n">DuckDB</span>
</span><span id="L-71"><a href="#L-71"><span class="linenos">71</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.hive</span> <span class="kn">import</span> <span class="n">Hive</span>
</span><span id="L-72"><a href="#L-72"><span class="linenos">72</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.mysql</span> <span class="kn">import</span> <span class="n">MySQL</span>
</span><span id="L-73"><a href="#L-73"><span class="linenos">73</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.oracle</span> <span class="kn">import</span> <span class="n">Oracle</span>
</span><span id="L-74"><a href="#L-74"><span class="linenos">74</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.postgres</span> <span class="kn">import</span> <span class="n">Postgres</span>
</span><span id="L-75"><a href="#L-75"><span class="linenos">75</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.presto</span> <span class="kn">import</span> <span class="n">Presto</span>
</span><span id="L-76"><a href="#L-76"><span class="linenos">76</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.redshift</span> <span class="kn">import</span> <span class="n">Redshift</span>
</span><span id="L-77"><a href="#L-77"><span class="linenos">77</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.snowflake</span> <span class="kn">import</span> <span class="n">Snowflake</span>
</span><span id="L-78"><a href="#L-78"><span class="linenos">78</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.spark</span> <span class="kn">import</span> <span class="n">Spark</span>
</span><span id="L-79"><a href="#L-79"><span class="linenos">79</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.spark2</span> <span class="kn">import</span> <span class="n">Spark2</span>
</span><span id="L-80"><a href="#L-80"><span class="linenos">80</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.sqlite</span> <span class="kn">import</span> <span class="n">SQLite</span>
</span><span id="L-81"><a href="#L-81"><span class="linenos">81</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.starrocks</span> <span class="kn">import</span> <span class="n">StarRocks</span>
</span><span id="L-82"><a href="#L-82"><span class="linenos">82</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.tableau</span> <span class="kn">import</span> <span class="n">Tableau</span>
</span><span id="L-83"><a href="#L-83"><span class="linenos">83</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.teradata</span> <span class="kn">import</span> <span class="n">Teradata</span>
</span><span id="L-84"><a href="#L-84"><span class="linenos">84</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.trino</span> <span class="kn">import</span> <span class="n">Trino</span>
</span><span id="L-85"><a href="#L-85"><span class="linenos">85</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.tsql</span> <span class="kn">import</span> <span class="n">TSQL</span>
</span></pre></div>

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

@ -347,86 +347,84 @@
</span><span id="L-10"><a href="#L-10"><span class="linenos">10</span></a><span class="kn">import</span> <span class="nn">time</span>
</span><span id="L-11"><a href="#L-11"><span class="linenos">11</span></a><span class="kn">import</span> <span class="nn">typing</span> <span class="k">as</span> <span class="nn">t</span>
</span><span id="L-12"><a href="#L-12"><span class="linenos">12</span></a>
</span><span id="L-13"><a href="#L-13"><span class="linenos">13</span></a><span class="kn">from</span> <span class="nn">sqlglot</span> <span class="kn">import</span> <span class="n">maybe_parse</span>
</span><span id="L-14"><a href="#L-14"><span class="linenos">14</span></a><span class="kn">from</span> <span class="nn">sqlglot.errors</span> <span class="kn">import</span> <span class="n">ExecuteError</span>
</span><span id="L-15"><a href="#L-15"><span class="linenos">15</span></a><span class="kn">from</span> <span class="nn">sqlglot.executor.python</span> <span class="kn">import</span> <span class="n">PythonExecutor</span>
</span><span id="L-16"><a href="#L-16"><span class="linenos">16</span></a><span class="kn">from</span> <span class="nn">sqlglot.executor.table</span> <span class="kn">import</span> <span class="n">Table</span><span class="p">,</span> <span class="n">ensure_tables</span>
</span><span id="L-17"><a href="#L-17"><span class="linenos">17</span></a><span class="kn">from</span> <span class="nn">sqlglot.helper</span> <span class="kn">import</span> <span class="n">dict_depth</span>
</span><span id="L-18"><a href="#L-18"><span class="linenos">18</span></a><span class="kn">from</span> <span class="nn">sqlglot.optimizer</span> <span class="kn">import</span> <span class="n">optimize</span>
</span><span id="L-19"><a href="#L-19"><span class="linenos">19</span></a><span class="kn">from</span> <span class="nn">sqlglot.planner</span> <span class="kn">import</span> <span class="n">Plan</span>
</span><span id="L-20"><a href="#L-20"><span class="linenos">20</span></a><span class="kn">from</span> <span class="nn">sqlglot.schema</span> <span class="kn">import</span> <span class="n">ensure_schema</span><span class="p">,</span> <span class="n">flatten_schema</span><span class="p">,</span> <span class="n">nested_get</span><span class="p">,</span> <span class="n">nested_set</span>
</span><span id="L-21"><a href="#L-21"><span class="linenos">21</span></a>
</span><span id="L-22"><a href="#L-22"><span class="linenos">22</span></a><span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s2">&quot;sqlglot&quot;</span><span class="p">)</span>
</span><span id="L-23"><a href="#L-23"><span class="linenos">23</span></a>
</span><span id="L-24"><a href="#L-24"><span class="linenos">24</span></a><span class="k">if</span> <span class="n">t</span><span class="o">.</span><span class="n">TYPE_CHECKING</span><span class="p">:</span>
</span><span id="L-25"><a href="#L-25"><span class="linenos">25</span></a> <span class="kn">from</span> <span class="nn">sqlglot.dialects.dialect</span> <span class="kn">import</span> <span class="n">DialectType</span>
</span><span id="L-26"><a href="#L-26"><span class="linenos">26</span></a> <span class="kn">from</span> <span class="nn">sqlglot.executor.table</span> <span class="kn">import</span> <span class="n">Tables</span>
</span><span id="L-27"><a href="#L-27"><span class="linenos">27</span></a> <span class="kn">from</span> <span class="nn">sqlglot.expressions</span> <span class="kn">import</span> <span class="n">Expression</span>
</span><span id="L-28"><a href="#L-28"><span class="linenos">28</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-29"><a href="#L-29"><span class="linenos">29</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="n">PYTHON_TYPE_TO_SQLGLOT</span> <span class="o">=</span> <span class="p">{</span>
</span><span id="L-32"><a href="#L-32"><span class="linenos">32</span></a> <span class="s2">&quot;dict&quot;</span><span class="p">:</span> <span class="s2">&quot;MAP&quot;</span><span class="p">,</span>
</span><span id="L-33"><a href="#L-33"><span class="linenos">33</span></a><span class="p">}</span>
</span><span id="L-34"><a href="#L-34"><span class="linenos">34</span></a>
</span><span id="L-35"><a href="#L-35"><span class="linenos">35</span></a>
</span><span id="L-36"><a href="#L-36"><span class="linenos">36</span></a><span class="k">def</span> <span class="nf">execute</span><span class="p">(</span>
</span><span id="L-37"><a href="#L-37"><span class="linenos">37</span></a> <span class="n">sql</span><span class="p">:</span> <span class="nb">str</span> <span class="o">|</span> <span class="n">Expression</span><span class="p">,</span>
</span><span id="L-38"><a href="#L-38"><span class="linenos">38</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">t</span><span class="o">.</span><span class="n">Dict</span> <span class="o">|</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-39"><a href="#L-39"><span class="linenos">39</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-40"><a href="#L-40"><span class="linenos">40</span></a> <span class="n">tables</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">t</span><span class="o">.</span><span class="n">Dict</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="L-41"><a href="#L-41"><span class="linenos">41</span></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Table</span><span class="p">:</span>
</span><span id="L-42"><a href="#L-42"><span class="linenos">42</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-43"><a href="#L-43"><span class="linenos">43</span></a><span class="sd"> Run a sql query against data.</span>
</span><span id="L-44"><a href="#L-44"><span class="linenos">44</span></a>
</span><span id="L-45"><a href="#L-45"><span class="linenos">45</span></a><span class="sd"> Args:</span>
</span><span id="L-46"><a href="#L-46"><span class="linenos">46</span></a><span class="sd"> sql: a sql statement.</span>
</span><span id="L-47"><a href="#L-47"><span class="linenos">47</span></a><span class="sd"> schema: database schema.</span>
</span><span id="L-48"><a href="#L-48"><span class="linenos">48</span></a><span class="sd"> This can either be an instance of `Schema` or a mapping in one of the following forms:</span>
</span><span id="L-49"><a href="#L-49"><span class="linenos">49</span></a><span class="sd"> 1. {table: {col: type}}</span>
</span><span id="L-50"><a href="#L-50"><span class="linenos">50</span></a><span class="sd"> 2. {db: {table: {col: type}}}</span>
</span><span id="L-51"><a href="#L-51"><span class="linenos">51</span></a><span class="sd"> 3. {catalog: {db: {table: {col: type}}}}</span>
</span><span id="L-52"><a href="#L-52"><span class="linenos">52</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-53"><a href="#L-53"><span class="linenos">53</span></a><span class="sd"> tables: additional tables to register.</span>
</span><span id="L-54"><a href="#L-54"><span class="linenos">54</span></a>
</span><span id="L-55"><a href="#L-55"><span class="linenos">55</span></a><span class="sd"> Returns:</span>
</span><span id="L-56"><a href="#L-56"><span class="linenos">56</span></a><span class="sd"> Simple columnar data structure.</span>
</span><span id="L-57"><a href="#L-57"><span class="linenos">57</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-58"><a href="#L-58"><span class="linenos">58</span></a> <span class="n">tables_</span> <span class="o">=</span> <span class="n">ensure_tables</span><span class="p">(</span><span class="n">tables</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">read</span><span class="p">)</span>
</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">if</span> <span class="ow">not</span> <span class="n">schema</span><span class="p">:</span>
</span><span id="L-61"><a href="#L-61"><span class="linenos">61</span></a> <span class="n">schema</span> <span class="o">=</span> <span class="p">{}</span>
</span><span id="L-62"><a href="#L-62"><span class="linenos">62</span></a> <span class="n">flattened_tables</span> <span class="o">=</span> <span class="n">flatten_schema</span><span class="p">(</span><span class="n">tables_</span><span class="o">.</span><span class="n">mapping</span><span class="p">,</span> <span class="n">depth</span><span class="o">=</span><span class="n">dict_depth</span><span class="p">(</span><span class="n">tables_</span><span class="o">.</span><span class="n">mapping</span><span class="p">))</span>
</span><span id="L-63"><a href="#L-63"><span class="linenos">63</span></a>
</span><span id="L-64"><a href="#L-64"><span class="linenos">64</span></a> <span class="k">for</span> <span class="n">keys</span> <span class="ow">in</span> <span class="n">flattened_tables</span><span class="p">:</span>
</span><span id="L-65"><a href="#L-65"><span class="linenos">65</span></a> <span class="n">table</span> <span class="o">=</span> <span class="n">nested_get</span><span class="p">(</span><span class="n">tables_</span><span class="o">.</span><span class="n">mapping</span><span class="p">,</span> <span class="o">*</span><span class="nb">zip</span><span class="p">(</span><span class="n">keys</span><span class="p">,</span> <span class="n">keys</span><span class="p">))</span>
</span><span id="L-66"><a href="#L-66"><span class="linenos">66</span></a> <span class="k">assert</span> <span class="n">table</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
</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">for</span> <span class="n">column</span> <span class="ow">in</span> <span class="n">table</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span>
</span><span id="L-69"><a href="#L-69"><span class="linenos">69</span></a> <span class="n">py_type</span> <span class="o">=</span> <span class="nb">type</span><span class="p">(</span><span class="n">table</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">column</span><span class="p">])</span><span class="o">.</span><span class="vm">__name__</span>
</span><span id="L-70"><a href="#L-70"><span class="linenos">70</span></a> <span class="n">nested_set</span><span class="p">(</span><span class="n">schema</span><span class="p">,</span> <span class="p">[</span><span class="o">*</span><span class="n">keys</span><span class="p">,</span> <span class="n">column</span><span class="p">],</span> <span class="n">PYTHON_TYPE_TO_SQLGLOT</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">py_type</span><span class="p">)</span> <span class="ow">or</span> <span class="n">py_type</span><span class="p">)</span>
</span><span id="L-13"><a href="#L-13"><span class="linenos">13</span></a><span class="kn">from</span> <span class="nn">sqlglot.errors</span> <span class="kn">import</span> <span class="n">ExecuteError</span>
</span><span id="L-14"><a href="#L-14"><span class="linenos">14</span></a><span class="kn">from</span> <span class="nn">sqlglot.executor.python</span> <span class="kn">import</span> <span class="n">PythonExecutor</span>
</span><span id="L-15"><a href="#L-15"><span class="linenos">15</span></a><span class="kn">from</span> <span class="nn">sqlglot.executor.table</span> <span class="kn">import</span> <span class="n">Table</span><span class="p">,</span> <span class="n">ensure_tables</span>
</span><span id="L-16"><a href="#L-16"><span class="linenos">16</span></a><span class="kn">from</span> <span class="nn">sqlglot.helper</span> <span class="kn">import</span> <span class="n">dict_depth</span>
</span><span id="L-17"><a href="#L-17"><span class="linenos">17</span></a><span class="kn">from</span> <span class="nn">sqlglot.optimizer</span> <span class="kn">import</span> <span class="n">optimize</span>
</span><span id="L-18"><a href="#L-18"><span class="linenos">18</span></a><span class="kn">from</span> <span class="nn">sqlglot.planner</span> <span class="kn">import</span> <span class="n">Plan</span>
</span><span id="L-19"><a href="#L-19"><span class="linenos">19</span></a><span class="kn">from</span> <span class="nn">sqlglot.schema</span> <span class="kn">import</span> <span class="n">ensure_schema</span><span class="p">,</span> <span class="n">flatten_schema</span><span class="p">,</span> <span class="n">nested_get</span><span class="p">,</span> <span class="n">nested_set</span>
</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="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s2">&quot;sqlglot&quot;</span><span class="p">)</span>
</span><span id="L-22"><a href="#L-22"><span class="linenos">22</span></a>
</span><span id="L-23"><a href="#L-23"><span class="linenos">23</span></a><span class="k">if</span> <span class="n">t</span><span class="o">.</span><span class="n">TYPE_CHECKING</span><span class="p">:</span>
</span><span id="L-24"><a href="#L-24"><span class="linenos">24</span></a> <span class="kn">from</span> <span class="nn">sqlglot.dialects.dialect</span> <span class="kn">import</span> <span class="n">DialectType</span>
</span><span id="L-25"><a href="#L-25"><span class="linenos">25</span></a> <span class="kn">from</span> <span class="nn">sqlglot.expressions</span> <span class="kn">import</span> <span class="n">Expression</span>
</span><span id="L-26"><a href="#L-26"><span class="linenos">26</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-27"><a href="#L-27"><span class="linenos">27</span></a>
</span><span id="L-28"><a href="#L-28"><span class="linenos">28</span></a>
</span><span id="L-29"><a href="#L-29"><span class="linenos">29</span></a><span class="n">PYTHON_TYPE_TO_SQLGLOT</span> <span class="o">=</span> <span class="p">{</span>
</span><span id="L-30"><a href="#L-30"><span class="linenos">30</span></a> <span class="s2">&quot;dict&quot;</span><span class="p">:</span> <span class="s2">&quot;MAP&quot;</span><span class="p">,</span>
</span><span id="L-31"><a href="#L-31"><span class="linenos">31</span></a><span class="p">}</span>
</span><span id="L-32"><a href="#L-32"><span class="linenos">32</span></a>
</span><span id="L-33"><a href="#L-33"><span class="linenos">33</span></a>
</span><span id="L-34"><a href="#L-34"><span class="linenos">34</span></a><span class="k">def</span> <span class="nf">execute</span><span class="p">(</span>
</span><span id="L-35"><a href="#L-35"><span class="linenos">35</span></a> <span class="n">sql</span><span class="p">:</span> <span class="nb">str</span> <span class="o">|</span> <span class="n">Expression</span><span class="p">,</span>
</span><span id="L-36"><a href="#L-36"><span class="linenos">36</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">t</span><span class="o">.</span><span class="n">Dict</span> <span class="o">|</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-37"><a href="#L-37"><span class="linenos">37</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-38"><a href="#L-38"><span class="linenos">38</span></a> <span class="n">tables</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">t</span><span class="o">.</span><span class="n">Dict</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="L-39"><a href="#L-39"><span class="linenos">39</span></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Table</span><span class="p">:</span>
</span><span id="L-40"><a href="#L-40"><span class="linenos">40</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-41"><a href="#L-41"><span class="linenos">41</span></a><span class="sd"> Run a sql query against data.</span>
</span><span id="L-42"><a href="#L-42"><span class="linenos">42</span></a>
</span><span id="L-43"><a href="#L-43"><span class="linenos">43</span></a><span class="sd"> Args:</span>
</span><span id="L-44"><a href="#L-44"><span class="linenos">44</span></a><span class="sd"> sql: a sql statement.</span>
</span><span id="L-45"><a href="#L-45"><span class="linenos">45</span></a><span class="sd"> schema: database schema.</span>
</span><span id="L-46"><a href="#L-46"><span class="linenos">46</span></a><span class="sd"> This can either be an instance of `Schema` or a mapping in one of the following forms:</span>
</span><span id="L-47"><a href="#L-47"><span class="linenos">47</span></a><span class="sd"> 1. {table: {col: type}}</span>
</span><span id="L-48"><a href="#L-48"><span class="linenos">48</span></a><span class="sd"> 2. {db: {table: {col: type}}}</span>
</span><span id="L-49"><a href="#L-49"><span class="linenos">49</span></a><span class="sd"> 3. {catalog: {db: {table: {col: type}}}}</span>
</span><span id="L-50"><a href="#L-50"><span class="linenos">50</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-51"><a href="#L-51"><span class="linenos">51</span></a><span class="sd"> tables: additional tables to register.</span>
</span><span id="L-52"><a href="#L-52"><span class="linenos">52</span></a>
</span><span id="L-53"><a href="#L-53"><span class="linenos">53</span></a><span class="sd"> Returns:</span>
</span><span id="L-54"><a href="#L-54"><span class="linenos">54</span></a><span class="sd"> Simple columnar data structure.</span>
</span><span id="L-55"><a href="#L-55"><span class="linenos">55</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-56"><a href="#L-56"><span class="linenos">56</span></a> <span class="n">tables_</span> <span class="o">=</span> <span class="n">ensure_tables</span><span class="p">(</span><span class="n">tables</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">read</span><span class="p">)</span>
</span><span id="L-57"><a href="#L-57"><span class="linenos">57</span></a>
</span><span id="L-58"><a href="#L-58"><span class="linenos">58</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">schema</span><span class="p">:</span>
</span><span id="L-59"><a href="#L-59"><span class="linenos">59</span></a> <span class="n">schema</span> <span class="o">=</span> <span class="p">{}</span>
</span><span id="L-60"><a href="#L-60"><span class="linenos">60</span></a> <span class="n">flattened_tables</span> <span class="o">=</span> <span class="n">flatten_schema</span><span class="p">(</span><span class="n">tables_</span><span class="o">.</span><span class="n">mapping</span><span class="p">,</span> <span class="n">depth</span><span class="o">=</span><span class="n">dict_depth</span><span class="p">(</span><span class="n">tables_</span><span class="o">.</span><span class="n">mapping</span><span class="p">))</span>
</span><span id="L-61"><a href="#L-61"><span class="linenos">61</span></a>
</span><span id="L-62"><a href="#L-62"><span class="linenos">62</span></a> <span class="k">for</span> <span class="n">keys</span> <span class="ow">in</span> <span class="n">flattened_tables</span><span class="p">:</span>
</span><span id="L-63"><a href="#L-63"><span class="linenos">63</span></a> <span class="n">table</span> <span class="o">=</span> <span class="n">nested_get</span><span class="p">(</span><span class="n">tables_</span><span class="o">.</span><span class="n">mapping</span><span class="p">,</span> <span class="o">*</span><span class="nb">zip</span><span class="p">(</span><span class="n">keys</span><span class="p">,</span> <span class="n">keys</span><span class="p">))</span>
</span><span id="L-64"><a href="#L-64"><span class="linenos">64</span></a> <span class="k">assert</span> <span class="n">table</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
</span><span id="L-65"><a href="#L-65"><span class="linenos">65</span></a>
</span><span id="L-66"><a href="#L-66"><span class="linenos">66</span></a> <span class="k">for</span> <span class="n">column</span> <span class="ow">in</span> <span class="n">table</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span>
</span><span id="L-67"><a href="#L-67"><span class="linenos">67</span></a> <span class="n">py_type</span> <span class="o">=</span> <span class="nb">type</span><span class="p">(</span><span class="n">table</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">column</span><span class="p">])</span><span class="o">.</span><span class="vm">__name__</span>
</span><span id="L-68"><a href="#L-68"><span class="linenos">68</span></a> <span class="n">nested_set</span><span class="p">(</span><span class="n">schema</span><span class="p">,</span> <span class="p">[</span><span class="o">*</span><span class="n">keys</span><span class="p">,</span> <span class="n">column</span><span class="p">],</span> <span class="n">PYTHON_TYPE_TO_SQLGLOT</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">py_type</span><span class="p">)</span> <span class="ow">or</span> <span class="n">py_type</span><span class="p">)</span>
</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="n">schema</span> <span class="o">=</span> <span class="n">ensure_schema</span><span class="p">(</span><span class="n">schema</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">read</span><span class="p">)</span>
</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">schema</span> <span class="o">=</span> <span class="n">ensure_schema</span><span class="p">(</span><span class="n">schema</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">read</span><span class="p">)</span>
</span><span id="L-73"><a href="#L-73"><span class="linenos">73</span></a>
</span><span id="L-74"><a href="#L-74"><span class="linenos">74</span></a> <span class="k">if</span> <span class="n">tables_</span><span class="o">.</span><span class="n">supported_table_args</span> <span class="ow">and</span> <span class="n">tables_</span><span class="o">.</span><span class="n">supported_table_args</span> <span class="o">!=</span> <span class="n">schema</span><span class="o">.</span><span class="n">supported_table_args</span><span class="p">:</span>
</span><span id="L-75"><a href="#L-75"><span class="linenos">75</span></a> <span class="k">raise</span> <span class="n">ExecuteError</span><span class="p">(</span><span class="s2">&quot;Tables must support the same table args as schema&quot;</span><span class="p">)</span>
</span><span id="L-76"><a href="#L-76"><span class="linenos">76</span></a>
</span><span id="L-77"><a href="#L-77"><span class="linenos">77</span></a> <span class="n">now</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>
</span><span id="L-78"><a href="#L-78"><span class="linenos">78</span></a> <span class="n">expression</span> <span class="o">=</span> <span class="n">optimize</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="n">schema</span><span class="p">,</span> <span class="n">leave_tables_isolated</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">read</span><span class="p">)</span>
</span><span id="L-79"><a href="#L-79"><span class="linenos">79</span></a>
</span><span id="L-80"><a href="#L-80"><span class="linenos">80</span></a> <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">&quot;Optimization finished: </span><span class="si">%f</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">now</span><span class="p">)</span>
</span><span id="L-81"><a href="#L-81"><span class="linenos">81</span></a> <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">&quot;Optimized SQL: </span><span class="si">%s</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">expression</span><span class="o">.</span><span class="n">sql</span><span class="p">(</span><span class="n">pretty</span><span class="o">=</span><span class="kc">True</span><span class="p">))</span>
</span><span id="L-72"><a href="#L-72"><span class="linenos">72</span></a> <span class="k">if</span> <span class="n">tables_</span><span class="o">.</span><span class="n">supported_table_args</span> <span class="ow">and</span> <span class="n">tables_</span><span class="o">.</span><span class="n">supported_table_args</span> <span class="o">!=</span> <span class="n">schema</span><span class="o">.</span><span class="n">supported_table_args</span><span class="p">:</span>
</span><span id="L-73"><a href="#L-73"><span class="linenos">73</span></a> <span class="k">raise</span> <span class="n">ExecuteError</span><span class="p">(</span><span class="s2">&quot;Tables must support the same table args as schema&quot;</span><span class="p">)</span>
</span><span id="L-74"><a href="#L-74"><span class="linenos">74</span></a>
</span><span id="L-75"><a href="#L-75"><span class="linenos">75</span></a> <span class="n">now</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>
</span><span id="L-76"><a href="#L-76"><span class="linenos">76</span></a> <span class="n">expression</span> <span class="o">=</span> <span class="n">optimize</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="n">schema</span><span class="p">,</span> <span class="n">leave_tables_isolated</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">read</span><span class="p">)</span>
</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="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">&quot;Optimization finished: </span><span class="si">%f</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">now</span><span class="p">)</span>
</span><span id="L-79"><a href="#L-79"><span class="linenos">79</span></a> <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">&quot;Optimized SQL: </span><span class="si">%s</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">expression</span><span class="o">.</span><span class="n">sql</span><span class="p">(</span><span class="n">pretty</span><span class="o">=</span><span class="kc">True</span><span class="p">))</span>
</span><span id="L-80"><a href="#L-80"><span class="linenos">80</span></a>
</span><span id="L-81"><a href="#L-81"><span class="linenos">81</span></a> <span class="n">plan</span> <span class="o">=</span> <span class="n">Plan</span><span class="p">(</span><span class="n">expression</span><span class="p">)</span>
</span><span id="L-82"><a href="#L-82"><span class="linenos">82</span></a>
</span><span id="L-83"><a href="#L-83"><span class="linenos">83</span></a> <span class="n">plan</span> <span class="o">=</span> <span class="n">Plan</span><span class="p">(</span><span class="n">expression</span><span class="p">)</span>
</span><span id="L-83"><a href="#L-83"><span class="linenos">83</span></a> <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">&quot;Logical Plan: </span><span class="si">%s</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">plan</span><span class="p">)</span>
</span><span id="L-84"><a href="#L-84"><span class="linenos">84</span></a>
</span><span id="L-85"><a href="#L-85"><span class="linenos">85</span></a> <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">&quot;Logical Plan: </span><span class="si">%s</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">plan</span><span class="p">)</span>
</span><span id="L-86"><a href="#L-86"><span class="linenos">86</span></a>
</span><span id="L-87"><a href="#L-87"><span class="linenos">87</span></a> <span class="n">now</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>
</span><span id="L-88"><a href="#L-88"><span class="linenos">88</span></a> <span class="n">result</span> <span class="o">=</span> <span class="n">PythonExecutor</span><span class="p">(</span><span class="n">tables</span><span class="o">=</span><span class="n">tables_</span><span class="p">)</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">plan</span><span class="p">)</span>
</span><span id="L-85"><a href="#L-85"><span class="linenos">85</span></a> <span class="n">now</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>
</span><span id="L-86"><a href="#L-86"><span class="linenos">86</span></a> <span class="n">result</span> <span class="o">=</span> <span class="n">PythonExecutor</span><span class="p">(</span><span class="n">tables</span><span class="o">=</span><span class="n">tables_</span><span class="p">)</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">plan</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="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">&quot;Query finished: </span><span class="si">%f</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">now</span><span class="p">)</span>
</span><span id="L-89"><a href="#L-89"><span class="linenos">89</span></a>
</span><span id="L-90"><a href="#L-90"><span class="linenos">90</span></a> <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">&quot;Query finished: </span><span class="si">%f</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">now</span><span class="p">)</span>
</span><span id="L-91"><a href="#L-91"><span class="linenos">91</span></a>
</span><span id="L-92"><a href="#L-92"><span class="linenos">92</span></a> <span class="k">return</span> <span class="n">result</span>
</span><span id="L-90"><a href="#L-90"><span class="linenos">90</span></a> <span class="k">return</span> <span class="n">result</span>
</span></pre></div>
@ -466,63 +464,63 @@
</div>
<a class="headerlink" href="#execute"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="execute-37"><a href="#execute-37"><span class="linenos">37</span></a><span class="k">def</span> <span class="nf">execute</span><span class="p">(</span>
</span><span id="execute-38"><a href="#execute-38"><span class="linenos">38</span></a> <span class="n">sql</span><span class="p">:</span> <span class="nb">str</span> <span class="o">|</span> <span class="n">Expression</span><span class="p">,</span>
</span><span id="execute-39"><a href="#execute-39"><span class="linenos">39</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">t</span><span class="o">.</span><span class="n">Dict</span> <span class="o">|</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="execute-40"><a href="#execute-40"><span class="linenos">40</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="execute-41"><a href="#execute-41"><span class="linenos">41</span></a> <span class="n">tables</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">t</span><span class="o">.</span><span class="n">Dict</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="execute-42"><a href="#execute-42"><span class="linenos">42</span></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Table</span><span class="p">:</span>
</span><span id="execute-43"><a href="#execute-43"><span class="linenos">43</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="execute-44"><a href="#execute-44"><span class="linenos">44</span></a><span class="sd"> Run a sql query against data.</span>
</span><span id="execute-45"><a href="#execute-45"><span class="linenos">45</span></a>
</span><span id="execute-46"><a href="#execute-46"><span class="linenos">46</span></a><span class="sd"> Args:</span>
</span><span id="execute-47"><a href="#execute-47"><span class="linenos">47</span></a><span class="sd"> sql: a sql statement.</span>
</span><span id="execute-48"><a href="#execute-48"><span class="linenos">48</span></a><span class="sd"> schema: database schema.</span>
</span><span id="execute-49"><a href="#execute-49"><span class="linenos">49</span></a><span class="sd"> This can either be an instance of `Schema` or a mapping in one of the following forms:</span>
</span><span id="execute-50"><a href="#execute-50"><span class="linenos">50</span></a><span class="sd"> 1. {table: {col: type}}</span>
</span><span id="execute-51"><a href="#execute-51"><span class="linenos">51</span></a><span class="sd"> 2. {db: {table: {col: type}}}</span>
</span><span id="execute-52"><a href="#execute-52"><span class="linenos">52</span></a><span class="sd"> 3. {catalog: {db: {table: {col: type}}}}</span>
</span><span id="execute-53"><a href="#execute-53"><span class="linenos">53</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="execute-54"><a href="#execute-54"><span class="linenos">54</span></a><span class="sd"> tables: additional tables to register.</span>
</span><span id="execute-55"><a href="#execute-55"><span class="linenos">55</span></a>
</span><span id="execute-56"><a href="#execute-56"><span class="linenos">56</span></a><span class="sd"> Returns:</span>
</span><span id="execute-57"><a href="#execute-57"><span class="linenos">57</span></a><span class="sd"> Simple columnar data structure.</span>
</span><span id="execute-58"><a href="#execute-58"><span class="linenos">58</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="execute-59"><a href="#execute-59"><span class="linenos">59</span></a> <span class="n">tables_</span> <span class="o">=</span> <span class="n">ensure_tables</span><span class="p">(</span><span class="n">tables</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">read</span><span class="p">)</span>
</span><span id="execute-60"><a href="#execute-60"><span class="linenos">60</span></a>
</span><span id="execute-61"><a href="#execute-61"><span class="linenos">61</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">schema</span><span class="p">:</span>
</span><span id="execute-62"><a href="#execute-62"><span class="linenos">62</span></a> <span class="n">schema</span> <span class="o">=</span> <span class="p">{}</span>
</span><span id="execute-63"><a href="#execute-63"><span class="linenos">63</span></a> <span class="n">flattened_tables</span> <span class="o">=</span> <span class="n">flatten_schema</span><span class="p">(</span><span class="n">tables_</span><span class="o">.</span><span class="n">mapping</span><span class="p">,</span> <span class="n">depth</span><span class="o">=</span><span class="n">dict_depth</span><span class="p">(</span><span class="n">tables_</span><span class="o">.</span><span class="n">mapping</span><span class="p">))</span>
</span><span id="execute-64"><a href="#execute-64"><span class="linenos">64</span></a>
</span><span id="execute-65"><a href="#execute-65"><span class="linenos">65</span></a> <span class="k">for</span> <span class="n">keys</span> <span class="ow">in</span> <span class="n">flattened_tables</span><span class="p">:</span>
</span><span id="execute-66"><a href="#execute-66"><span class="linenos">66</span></a> <span class="n">table</span> <span class="o">=</span> <span class="n">nested_get</span><span class="p">(</span><span class="n">tables_</span><span class="o">.</span><span class="n">mapping</span><span class="p">,</span> <span class="o">*</span><span class="nb">zip</span><span class="p">(</span><span class="n">keys</span><span class="p">,</span> <span class="n">keys</span><span class="p">))</span>
</span><span id="execute-67"><a href="#execute-67"><span class="linenos">67</span></a> <span class="k">assert</span> <span class="n">table</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
</span><span id="execute-68"><a href="#execute-68"><span class="linenos">68</span></a>
</span><span id="execute-69"><a href="#execute-69"><span class="linenos">69</span></a> <span class="k">for</span> <span class="n">column</span> <span class="ow">in</span> <span class="n">table</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span>
</span><span id="execute-70"><a href="#execute-70"><span class="linenos">70</span></a> <span class="n">py_type</span> <span class="o">=</span> <span class="nb">type</span><span class="p">(</span><span class="n">table</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">column</span><span class="p">])</span><span class="o">.</span><span class="vm">__name__</span>
</span><span id="execute-71"><a href="#execute-71"><span class="linenos">71</span></a> <span class="n">nested_set</span><span class="p">(</span><span class="n">schema</span><span class="p">,</span> <span class="p">[</span><span class="o">*</span><span class="n">keys</span><span class="p">,</span> <span class="n">column</span><span class="p">],</span> <span class="n">PYTHON_TYPE_TO_SQLGLOT</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">py_type</span><span class="p">)</span> <span class="ow">or</span> <span class="n">py_type</span><span class="p">)</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="execute-35"><a href="#execute-35"><span class="linenos">35</span></a><span class="k">def</span> <span class="nf">execute</span><span class="p">(</span>
</span><span id="execute-36"><a href="#execute-36"><span class="linenos">36</span></a> <span class="n">sql</span><span class="p">:</span> <span class="nb">str</span> <span class="o">|</span> <span class="n">Expression</span><span class="p">,</span>
</span><span id="execute-37"><a href="#execute-37"><span class="linenos">37</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">t</span><span class="o">.</span><span class="n">Dict</span> <span class="o">|</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="execute-38"><a href="#execute-38"><span class="linenos">38</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="execute-39"><a href="#execute-39"><span class="linenos">39</span></a> <span class="n">tables</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">t</span><span class="o">.</span><span class="n">Dict</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="execute-40"><a href="#execute-40"><span class="linenos">40</span></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Table</span><span class="p">:</span>
</span><span id="execute-41"><a href="#execute-41"><span class="linenos">41</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="execute-42"><a href="#execute-42"><span class="linenos">42</span></a><span class="sd"> Run a sql query against data.</span>
</span><span id="execute-43"><a href="#execute-43"><span class="linenos">43</span></a>
</span><span id="execute-44"><a href="#execute-44"><span class="linenos">44</span></a><span class="sd"> Args:</span>
</span><span id="execute-45"><a href="#execute-45"><span class="linenos">45</span></a><span class="sd"> sql: a sql statement.</span>
</span><span id="execute-46"><a href="#execute-46"><span class="linenos">46</span></a><span class="sd"> schema: database schema.</span>
</span><span id="execute-47"><a href="#execute-47"><span class="linenos">47</span></a><span class="sd"> This can either be an instance of `Schema` or a mapping in one of the following forms:</span>
</span><span id="execute-48"><a href="#execute-48"><span class="linenos">48</span></a><span class="sd"> 1. {table: {col: type}}</span>
</span><span id="execute-49"><a href="#execute-49"><span class="linenos">49</span></a><span class="sd"> 2. {db: {table: {col: type}}}</span>
</span><span id="execute-50"><a href="#execute-50"><span class="linenos">50</span></a><span class="sd"> 3. {catalog: {db: {table: {col: type}}}}</span>
</span><span id="execute-51"><a href="#execute-51"><span class="linenos">51</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="execute-52"><a href="#execute-52"><span class="linenos">52</span></a><span class="sd"> tables: additional tables to register.</span>
</span><span id="execute-53"><a href="#execute-53"><span class="linenos">53</span></a>
</span><span id="execute-54"><a href="#execute-54"><span class="linenos">54</span></a><span class="sd"> Returns:</span>
</span><span id="execute-55"><a href="#execute-55"><span class="linenos">55</span></a><span class="sd"> Simple columnar data structure.</span>
</span><span id="execute-56"><a href="#execute-56"><span class="linenos">56</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="execute-57"><a href="#execute-57"><span class="linenos">57</span></a> <span class="n">tables_</span> <span class="o">=</span> <span class="n">ensure_tables</span><span class="p">(</span><span class="n">tables</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">read</span><span class="p">)</span>
</span><span id="execute-58"><a href="#execute-58"><span class="linenos">58</span></a>
</span><span id="execute-59"><a href="#execute-59"><span class="linenos">59</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">schema</span><span class="p">:</span>
</span><span id="execute-60"><a href="#execute-60"><span class="linenos">60</span></a> <span class="n">schema</span> <span class="o">=</span> <span class="p">{}</span>
</span><span id="execute-61"><a href="#execute-61"><span class="linenos">61</span></a> <span class="n">flattened_tables</span> <span class="o">=</span> <span class="n">flatten_schema</span><span class="p">(</span><span class="n">tables_</span><span class="o">.</span><span class="n">mapping</span><span class="p">,</span> <span class="n">depth</span><span class="o">=</span><span class="n">dict_depth</span><span class="p">(</span><span class="n">tables_</span><span class="o">.</span><span class="n">mapping</span><span class="p">))</span>
</span><span id="execute-62"><a href="#execute-62"><span class="linenos">62</span></a>
</span><span id="execute-63"><a href="#execute-63"><span class="linenos">63</span></a> <span class="k">for</span> <span class="n">keys</span> <span class="ow">in</span> <span class="n">flattened_tables</span><span class="p">:</span>
</span><span id="execute-64"><a href="#execute-64"><span class="linenos">64</span></a> <span class="n">table</span> <span class="o">=</span> <span class="n">nested_get</span><span class="p">(</span><span class="n">tables_</span><span class="o">.</span><span class="n">mapping</span><span class="p">,</span> <span class="o">*</span><span class="nb">zip</span><span class="p">(</span><span class="n">keys</span><span class="p">,</span> <span class="n">keys</span><span class="p">))</span>
</span><span id="execute-65"><a href="#execute-65"><span class="linenos">65</span></a> <span class="k">assert</span> <span class="n">table</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
</span><span id="execute-66"><a href="#execute-66"><span class="linenos">66</span></a>
</span><span id="execute-67"><a href="#execute-67"><span class="linenos">67</span></a> <span class="k">for</span> <span class="n">column</span> <span class="ow">in</span> <span class="n">table</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span>
</span><span id="execute-68"><a href="#execute-68"><span class="linenos">68</span></a> <span class="n">py_type</span> <span class="o">=</span> <span class="nb">type</span><span class="p">(</span><span class="n">table</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">column</span><span class="p">])</span><span class="o">.</span><span class="vm">__name__</span>
</span><span id="execute-69"><a href="#execute-69"><span class="linenos">69</span></a> <span class="n">nested_set</span><span class="p">(</span><span class="n">schema</span><span class="p">,</span> <span class="p">[</span><span class="o">*</span><span class="n">keys</span><span class="p">,</span> <span class="n">column</span><span class="p">],</span> <span class="n">PYTHON_TYPE_TO_SQLGLOT</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">py_type</span><span class="p">)</span> <span class="ow">or</span> <span class="n">py_type</span><span class="p">)</span>
</span><span id="execute-70"><a href="#execute-70"><span class="linenos">70</span></a>
</span><span id="execute-71"><a href="#execute-71"><span class="linenos">71</span></a> <span class="n">schema</span> <span class="o">=</span> <span class="n">ensure_schema</span><span class="p">(</span><span class="n">schema</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">read</span><span class="p">)</span>
</span><span id="execute-72"><a href="#execute-72"><span class="linenos">72</span></a>
</span><span id="execute-73"><a href="#execute-73"><span class="linenos">73</span></a> <span class="n">schema</span> <span class="o">=</span> <span class="n">ensure_schema</span><span class="p">(</span><span class="n">schema</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">read</span><span class="p">)</span>
</span><span id="execute-74"><a href="#execute-74"><span class="linenos">74</span></a>
</span><span id="execute-75"><a href="#execute-75"><span class="linenos">75</span></a> <span class="k">if</span> <span class="n">tables_</span><span class="o">.</span><span class="n">supported_table_args</span> <span class="ow">and</span> <span class="n">tables_</span><span class="o">.</span><span class="n">supported_table_args</span> <span class="o">!=</span> <span class="n">schema</span><span class="o">.</span><span class="n">supported_table_args</span><span class="p">:</span>
</span><span id="execute-76"><a href="#execute-76"><span class="linenos">76</span></a> <span class="k">raise</span> <span class="n">ExecuteError</span><span class="p">(</span><span class="s2">&quot;Tables must support the same table args as schema&quot;</span><span class="p">)</span>
</span><span id="execute-77"><a href="#execute-77"><span class="linenos">77</span></a>
</span><span id="execute-78"><a href="#execute-78"><span class="linenos">78</span></a> <span class="n">now</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>
</span><span id="execute-79"><a href="#execute-79"><span class="linenos">79</span></a> <span class="n">expression</span> <span class="o">=</span> <span class="n">optimize</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="n">schema</span><span class="p">,</span> <span class="n">leave_tables_isolated</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">read</span><span class="p">)</span>
</span><span id="execute-80"><a href="#execute-80"><span class="linenos">80</span></a>
</span><span id="execute-81"><a href="#execute-81"><span class="linenos">81</span></a> <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">&quot;Optimization finished: </span><span class="si">%f</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">now</span><span class="p">)</span>
</span><span id="execute-82"><a href="#execute-82"><span class="linenos">82</span></a> <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">&quot;Optimized SQL: </span><span class="si">%s</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">expression</span><span class="o">.</span><span class="n">sql</span><span class="p">(</span><span class="n">pretty</span><span class="o">=</span><span class="kc">True</span><span class="p">))</span>
</span><span id="execute-73"><a href="#execute-73"><span class="linenos">73</span></a> <span class="k">if</span> <span class="n">tables_</span><span class="o">.</span><span class="n">supported_table_args</span> <span class="ow">and</span> <span class="n">tables_</span><span class="o">.</span><span class="n">supported_table_args</span> <span class="o">!=</span> <span class="n">schema</span><span class="o">.</span><span class="n">supported_table_args</span><span class="p">:</span>
</span><span id="execute-74"><a href="#execute-74"><span class="linenos">74</span></a> <span class="k">raise</span> <span class="n">ExecuteError</span><span class="p">(</span><span class="s2">&quot;Tables must support the same table args as schema&quot;</span><span class="p">)</span>
</span><span id="execute-75"><a href="#execute-75"><span class="linenos">75</span></a>
</span><span id="execute-76"><a href="#execute-76"><span class="linenos">76</span></a> <span class="n">now</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>
</span><span id="execute-77"><a href="#execute-77"><span class="linenos">77</span></a> <span class="n">expression</span> <span class="o">=</span> <span class="n">optimize</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="n">schema</span><span class="p">,</span> <span class="n">leave_tables_isolated</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">read</span><span class="p">)</span>
</span><span id="execute-78"><a href="#execute-78"><span class="linenos">78</span></a>
</span><span id="execute-79"><a href="#execute-79"><span class="linenos">79</span></a> <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">&quot;Optimization finished: </span><span class="si">%f</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">now</span><span class="p">)</span>
</span><span id="execute-80"><a href="#execute-80"><span class="linenos">80</span></a> <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">&quot;Optimized SQL: </span><span class="si">%s</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">expression</span><span class="o">.</span><span class="n">sql</span><span class="p">(</span><span class="n">pretty</span><span class="o">=</span><span class="kc">True</span><span class="p">))</span>
</span><span id="execute-81"><a href="#execute-81"><span class="linenos">81</span></a>
</span><span id="execute-82"><a href="#execute-82"><span class="linenos">82</span></a> <span class="n">plan</span> <span class="o">=</span> <span class="n">Plan</span><span class="p">(</span><span class="n">expression</span><span class="p">)</span>
</span><span id="execute-83"><a href="#execute-83"><span class="linenos">83</span></a>
</span><span id="execute-84"><a href="#execute-84"><span class="linenos">84</span></a> <span class="n">plan</span> <span class="o">=</span> <span class="n">Plan</span><span class="p">(</span><span class="n">expression</span><span class="p">)</span>
</span><span id="execute-84"><a href="#execute-84"><span class="linenos">84</span></a> <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">&quot;Logical Plan: </span><span class="si">%s</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">plan</span><span class="p">)</span>
</span><span id="execute-85"><a href="#execute-85"><span class="linenos">85</span></a>
</span><span id="execute-86"><a href="#execute-86"><span class="linenos">86</span></a> <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">&quot;Logical Plan: </span><span class="si">%s</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">plan</span><span class="p">)</span>
</span><span id="execute-87"><a href="#execute-87"><span class="linenos">87</span></a>
</span><span id="execute-88"><a href="#execute-88"><span class="linenos">88</span></a> <span class="n">now</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>
</span><span id="execute-89"><a href="#execute-89"><span class="linenos">89</span></a> <span class="n">result</span> <span class="o">=</span> <span class="n">PythonExecutor</span><span class="p">(</span><span class="n">tables</span><span class="o">=</span><span class="n">tables_</span><span class="p">)</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">plan</span><span class="p">)</span>
</span><span id="execute-86"><a href="#execute-86"><span class="linenos">86</span></a> <span class="n">now</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>
</span><span id="execute-87"><a href="#execute-87"><span class="linenos">87</span></a> <span class="n">result</span> <span class="o">=</span> <span class="n">PythonExecutor</span><span class="p">(</span><span class="n">tables</span><span class="o">=</span><span class="n">tables_</span><span class="p">)</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">plan</span><span class="p">)</span>
</span><span id="execute-88"><a href="#execute-88"><span class="linenos">88</span></a>
</span><span id="execute-89"><a href="#execute-89"><span class="linenos">89</span></a> <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">&quot;Query finished: </span><span class="si">%f</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">now</span><span class="p">)</span>
</span><span id="execute-90"><a href="#execute-90"><span class="linenos">90</span></a>
</span><span id="execute-91"><a href="#execute-91"><span class="linenos">91</span></a> <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">&quot;Query finished: </span><span class="si">%f</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">now</span><span class="p">)</span>
</span><span id="execute-92"><a href="#execute-92"><span class="linenos">92</span></a>
</span><span id="execute-93"><a href="#execute-93"><span class="linenos">93</span></a> <span class="k">return</span> <span class="n">result</span>
</span><span id="execute-91"><a href="#execute-91"><span class="linenos">91</span></a> <span class="k">return</span> <span class="n">result</span>
</span></pre></div>

View file

@ -153,9 +153,9 @@
</span><span id="L-44"><a href="#L-44"><span class="linenos"> 44</span></a>
</span><span id="L-45"><a href="#L-45"><span class="linenos"> 45</span></a> <span class="k">for</span> <span class="n">other</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">tables</span><span class="o">.</span><span class="n">values</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="bp">self</span><span class="o">.</span><span class="n">_table</span><span class="o">.</span><span class="n">columns</span> <span class="o">!=</span> <span class="n">other</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span>
</span><span id="L-47"><a href="#L-47"><span class="linenos"> 47</span></a> <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Columns are different.&quot;</span><span class="p">)</span>
</span><span id="L-47"><a href="#L-47"><span class="linenos"> 47</span></a> <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s2">&quot;Columns are different.&quot;</span><span class="p">)</span>
</span><span id="L-48"><a href="#L-48"><span class="linenos"> 48</span></a> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_table</span><span class="o">.</span><span class="n">rows</span><span class="p">)</span> <span class="o">!=</span> <span class="nb">len</span><span class="p">(</span><span class="n">other</span><span class="o">.</span><span class="n">rows</span><span class="p">):</span>
</span><span id="L-49"><a href="#L-49"><span class="linenos"> 49</span></a> <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Rows are different.&quot;</span><span class="p">)</span>
</span><span id="L-49"><a href="#L-49"><span class="linenos"> 49</span></a> <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s2">&quot;Rows are different.&quot;</span><span class="p">)</span>
</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">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_table</span>
</span><span id="L-52"><a href="#L-52"><span class="linenos"> 52</span></a>
@ -259,9 +259,9 @@
</span><span id="Context-45"><a href="#Context-45"><span class="linenos"> 45</span></a>
</span><span id="Context-46"><a href="#Context-46"><span class="linenos"> 46</span></a> <span class="k">for</span> <span class="n">other</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">tables</span><span class="o">.</span><span class="n">values</span><span class="p">():</span>
</span><span id="Context-47"><a href="#Context-47"><span class="linenos"> 47</span></a> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_table</span><span class="o">.</span><span class="n">columns</span> <span class="o">!=</span> <span class="n">other</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span>
</span><span id="Context-48"><a href="#Context-48"><span class="linenos"> 48</span></a> <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Columns are different.&quot;</span><span class="p">)</span>
</span><span id="Context-48"><a href="#Context-48"><span class="linenos"> 48</span></a> <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s2">&quot;Columns are different.&quot;</span><span class="p">)</span>
</span><span id="Context-49"><a href="#Context-49"><span class="linenos"> 49</span></a> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_table</span><span class="o">.</span><span class="n">rows</span><span class="p">)</span> <span class="o">!=</span> <span class="nb">len</span><span class="p">(</span><span class="n">other</span><span class="o">.</span><span class="n">rows</span><span class="p">):</span>
</span><span id="Context-50"><a href="#Context-50"><span class="linenos"> 50</span></a> <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Rows are different.&quot;</span><span class="p">)</span>
</span><span id="Context-50"><a href="#Context-50"><span class="linenos"> 50</span></a> <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s2">&quot;Rows are different.&quot;</span><span class="p">)</span>
</span><span id="Context-51"><a href="#Context-51"><span class="linenos"> 51</span></a>
</span><span id="Context-52"><a href="#Context-52"><span class="linenos"> 52</span></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_table</span>
</span><span id="Context-53"><a href="#Context-53"><span class="linenos"> 53</span></a>
@ -456,9 +456,9 @@ evaluation of aggregation functions.</p>
</span><span id="Context.table-45"><a href="#Context.table-45"><span class="linenos">45</span></a>
</span><span id="Context.table-46"><a href="#Context.table-46"><span class="linenos">46</span></a> <span class="k">for</span> <span class="n">other</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">tables</span><span class="o">.</span><span class="n">values</span><span class="p">():</span>
</span><span id="Context.table-47"><a href="#Context.table-47"><span class="linenos">47</span></a> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_table</span><span class="o">.</span><span class="n">columns</span> <span class="o">!=</span> <span class="n">other</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span>
</span><span id="Context.table-48"><a href="#Context.table-48"><span class="linenos">48</span></a> <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Columns are different.&quot;</span><span class="p">)</span>
</span><span id="Context.table-48"><a href="#Context.table-48"><span class="linenos">48</span></a> <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s2">&quot;Columns are different.&quot;</span><span class="p">)</span>
</span><span id="Context.table-49"><a href="#Context.table-49"><span class="linenos">49</span></a> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_table</span><span class="o">.</span><span class="n">rows</span><span class="p">)</span> <span class="o">!=</span> <span class="nb">len</span><span class="p">(</span><span class="n">other</span><span class="o">.</span><span class="n">rows</span><span class="p">):</span>
</span><span id="Context.table-50"><a href="#Context.table-50"><span class="linenos">50</span></a> <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Rows are different.&quot;</span><span class="p">)</span>
</span><span id="Context.table-50"><a href="#Context.table-50"><span class="linenos">50</span></a> <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s2">&quot;Rows are different.&quot;</span><span class="p">)</span>
</span><span id="Context.table-51"><a href="#Context.table-51"><span class="linenos">51</span></a>
</span><span id="Context.table-52"><a href="#Context.table-52"><span class="linenos">52</span></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_table</span>
</span></pre></div>

View file

@ -66,6 +66,9 @@
<li>
<a class="function" href="#arrayjoin">arrayjoin</a>
</li>
<li>
<a class="function" href="#jsonextract">jsonextract</a>
</li>
<li>
<a class="variable" href="#ENV">ENV</a>
</li>
@ -100,7 +103,7 @@
</span><span id="L-6"><a href="#L-6"><span class="linenos"> 6</span></a>
</span><span id="L-7"><a href="#L-7"><span class="linenos"> 7</span></a><span class="kn">from</span> <span class="nn">sqlglot</span> <span class="kn">import</span> <span class="n">exp</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.generator</span> <span class="kn">import</span> <span class="n">Generator</span>
</span><span id="L-9"><a href="#L-9"><span class="linenos"> 9</span></a><span class="kn">from</span> <span class="nn">sqlglot.helper</span> <span class="kn">import</span> <span class="n">PYTHON_VERSION</span>
</span><span id="L-9"><a href="#L-9"><span class="linenos"> 9</span></a><span class="kn">from</span> <span class="nn">sqlglot.helper</span> <span class="kn">import</span> <span class="n">PYTHON_VERSION</span><span class="p">,</span> <span class="n">is_int</span><span class="p">,</span> <span class="n">seq_get</span>
</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><span id="L-12"><a href="#L-12"><span class="linenos"> 12</span></a><span class="k">class</span> <span class="nc">reverse_key</span><span class="p">:</span>
@ -237,79 +240,95 @@
</span><span id="L-143"><a href="#L-143"><span class="linenos">143</span></a> <span class="k">return</span> <span class="n">expression</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="p">(</span><span class="n">x</span> <span class="k">if</span> <span class="n">x</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">null</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">this</span><span class="p">)</span> <span class="k">if</span> <span class="n">x</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</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-146"><a href="#L-146"><span class="linenos">146</span></a><span class="n">ENV</span> <span class="o">=</span> <span class="p">{</span>
</span><span id="L-147"><a href="#L-147"><span class="linenos">147</span></a> <span class="s2">&quot;exp&quot;</span><span class="p">:</span> <span class="n">exp</span><span class="p">,</span>
</span><span id="L-148"><a href="#L-148"><span class="linenos">148</span></a> <span class="c1"># aggs</span>
</span><span id="L-149"><a href="#L-149"><span class="linenos">149</span></a> <span class="s2">&quot;ARRAYAGG&quot;</span><span class="p">:</span> <span class="nb">list</span><span class="p">,</span>
</span><span id="L-150"><a href="#L-150"><span class="linenos">150</span></a> <span class="s2">&quot;ARRAYUNIQUEAGG&quot;</span><span class="p">:</span> <span class="n">filter_nulls</span><span class="p">(</span><span class="k">lambda</span> <span class="n">acc</span><span class="p">:</span> <span class="nb">list</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">acc</span><span class="p">))),</span>
</span><span id="L-151"><a href="#L-151"><span class="linenos">151</span></a> <span class="s2">&quot;AVG&quot;</span><span class="p">:</span> <span class="n">filter_nulls</span><span class="p">(</span><span class="n">statistics</span><span class="o">.</span><span class="n">fmean</span> <span class="k">if</span> <span class="n">PYTHON_VERSION</span> <span class="o">&gt;=</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">8</span><span class="p">)</span> <span class="k">else</span> <span class="n">statistics</span><span class="o">.</span><span class="n">mean</span><span class="p">),</span> <span class="c1"># type: ignore</span>
</span><span id="L-152"><a href="#L-152"><span class="linenos">152</span></a> <span class="s2">&quot;COUNT&quot;</span><span class="p">:</span> <span class="n">filter_nulls</span><span class="p">(</span><span class="k">lambda</span> <span class="n">acc</span><span class="p">:</span> <span class="nb">sum</span><span class="p">(</span><span class="mi">1</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="n">acc</span><span class="p">),</span> <span class="kc">False</span><span class="p">),</span>
</span><span id="L-153"><a href="#L-153"><span class="linenos">153</span></a> <span class="s2">&quot;MAX&quot;</span><span class="p">:</span> <span class="n">filter_nulls</span><span class="p">(</span><span class="nb">max</span><span class="p">),</span>
</span><span id="L-154"><a href="#L-154"><span class="linenos">154</span></a> <span class="s2">&quot;MIN&quot;</span><span class="p">:</span> <span class="n">filter_nulls</span><span class="p">(</span><span class="nb">min</span><span class="p">),</span>
</span><span id="L-155"><a href="#L-155"><span class="linenos">155</span></a> <span class="s2">&quot;SUM&quot;</span><span class="p">:</span> <span class="n">filter_nulls</span><span class="p">(</span><span class="nb">sum</span><span class="p">),</span>
</span><span id="L-156"><a href="#L-156"><span class="linenos">156</span></a> <span class="c1"># scalar functions</span>
</span><span id="L-157"><a href="#L-157"><span class="linenos">157</span></a> <span class="s2">&quot;ABS&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">:</span> <span class="nb">abs</span><span class="p">(</span><span class="n">this</span><span class="p">)),</span>
</span><span id="L-158"><a href="#L-158"><span class="linenos">158</span></a> <span class="s2">&quot;ADD&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">e</span><span class="p">,</span> <span class="n">this</span><span class="p">:</span> <span class="n">e</span> <span class="o">+</span> <span class="n">this</span><span class="p">),</span>
</span><span id="L-159"><a href="#L-159"><span class="linenos">159</span></a> <span class="s2">&quot;ARRAYANY&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">arr</span><span class="p">,</span> <span class="n">func</span><span class="p">:</span> <span class="nb">any</span><span class="p">(</span><span class="n">func</span><span class="p">(</span><span class="n">e</span><span class="p">)</span> <span class="k">for</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">arr</span><span class="p">)),</span>
</span><span id="L-160"><a href="#L-160"><span class="linenos">160</span></a> <span class="s2">&quot;ARRAYJOIN&quot;</span><span class="p">:</span> <span class="n">arrayjoin</span><span class="p">,</span>
</span><span id="L-161"><a href="#L-161"><span class="linenos">161</span></a> <span class="s2">&quot;BETWEEN&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">low</span><span class="p">,</span> <span class="n">high</span><span class="p">:</span> <span class="n">low</span> <span class="o">&lt;=</span> <span class="n">this</span> <span class="ow">and</span> <span class="n">this</span> <span class="o">&lt;=</span> <span class="n">high</span><span class="p">),</span>
</span><span id="L-162"><a href="#L-162"><span class="linenos">162</span></a> <span class="s2">&quot;BITWISEAND&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span> <span class="o">&amp;</span> <span class="n">e</span><span class="p">),</span>
</span><span id="L-163"><a href="#L-163"><span class="linenos">163</span></a> <span class="s2">&quot;BITWISELEFTSHIFT&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span> <span class="o">&lt;&lt;</span> <span class="n">e</span><span class="p">),</span>
</span><span id="L-164"><a href="#L-164"><span class="linenos">164</span></a> <span class="s2">&quot;BITWISEOR&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span> <span class="o">|</span> <span class="n">e</span><span class="p">),</span>
</span><span id="L-165"><a href="#L-165"><span class="linenos">165</span></a> <span class="s2">&quot;BITWISERIGHTSHIFT&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span> <span class="o">&gt;&gt;</span> <span class="n">e</span><span class="p">),</span>
</span><span id="L-166"><a href="#L-166"><span class="linenos">166</span></a> <span class="s2">&quot;BITWISEXOR&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span> <span class="o">^</span> <span class="n">e</span><span class="p">),</span>
</span><span id="L-167"><a href="#L-167"><span class="linenos">167</span></a> <span class="s2">&quot;CAST&quot;</span><span class="p">:</span> <span class="n">cast</span><span class="p">,</span>
</span><span id="L-168"><a href="#L-168"><span class="linenos">168</span></a> <span class="s2">&quot;COALESCE&quot;</span><span class="p">:</span> <span class="k">lambda</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="nb">next</span><span class="p">((</span><span class="n">a</span> <span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">args</span> <span class="k">if</span> <span class="n">a</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">),</span> <span class="kc">None</span><span class="p">),</span>
</span><span id="L-169"><a href="#L-169"><span class="linenos">169</span></a> <span class="s2">&quot;CONCAT&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="s2">&quot;&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">args</span><span class="p">)),</span>
</span><span id="L-170"><a href="#L-170"><span class="linenos">170</span></a> <span class="s2">&quot;SAFECONCAT&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="s2">&quot;&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">arg</span><span class="p">)</span> <span class="k">for</span> <span class="n">arg</span> <span class="ow">in</span> <span class="n">args</span><span class="p">)),</span>
</span><span id="L-171"><a href="#L-171"><span class="linenos">171</span></a> <span class="s2">&quot;CONCATWS&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">this</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">args</span><span class="p">)),</span>
</span><span id="L-172"><a href="#L-172"><span class="linenos">172</span></a> <span class="s2">&quot;DATEDIFF&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="o">*</span><span class="n">_</span><span class="p">:</span> <span class="p">(</span><span class="n">this</span> <span class="o">-</span> <span class="n">expression</span><span class="p">)</span><span class="o">.</span><span class="n">days</span><span class="p">),</span>
</span><span id="L-173"><a href="#L-173"><span class="linenos">173</span></a> <span class="s2">&quot;DATESTRTODATE&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">arg</span><span class="p">:</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">fromisoformat</span><span class="p">(</span><span class="n">arg</span><span class="p">)),</span>
</span><span id="L-174"><a href="#L-174"><span class="linenos">174</span></a> <span class="s2">&quot;DIV&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">e</span><span class="p">,</span> <span class="n">this</span><span class="p">:</span> <span class="n">e</span> <span class="o">/</span> <span class="n">this</span><span class="p">),</span>
</span><span id="L-175"><a href="#L-175"><span class="linenos">175</span></a> <span class="s2">&quot;DOT&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">e</span><span class="p">,</span> <span class="n">this</span><span class="p">:</span> <span class="n">e</span><span class="p">[</span><span class="n">this</span><span class="p">]),</span>
</span><span id="L-176"><a href="#L-176"><span class="linenos">176</span></a> <span class="s2">&quot;EQ&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span> <span class="o">==</span> <span class="n">e</span><span class="p">),</span>
</span><span id="L-177"><a href="#L-177"><span class="linenos">177</span></a> <span class="s2">&quot;EXTRACT&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">this</span><span class="p">)),</span>
</span><span id="L-178"><a href="#L-178"><span class="linenos">178</span></a> <span class="s2">&quot;GETPATH&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">e</span><span class="p">)),</span>
</span><span id="L-179"><a href="#L-179"><span class="linenos">179</span></a> <span class="s2">&quot;GT&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span> <span class="o">&gt;</span> <span class="n">e</span><span class="p">),</span>
</span><span id="L-180"><a href="#L-180"><span class="linenos">180</span></a> <span class="s2">&quot;GTE&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span> <span class="o">&gt;=</span> <span class="n">e</span><span class="p">),</span>
</span><span id="L-181"><a href="#L-181"><span class="linenos">181</span></a> <span class="s2">&quot;IF&quot;</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">predicate</span><span class="p">,</span> <span class="n">true</span><span class="p">,</span> <span class="n">false</span><span class="p">:</span> <span class="n">true</span> <span class="k">if</span> <span class="n">predicate</span> <span class="k">else</span> <span class="n">false</span><span class="p">,</span>
</span><span id="L-182"><a href="#L-182"><span class="linenos">182</span></a> <span class="s2">&quot;INTDIV&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">e</span><span class="p">,</span> <span class="n">this</span><span class="p">:</span> <span class="n">e</span> <span class="o">//</span> <span class="n">this</span><span class="p">),</span>
</span><span id="L-183"><a href="#L-183"><span class="linenos">183</span></a> <span class="s2">&quot;INTERVAL&quot;</span><span class="p">:</span> <span class="n">interval</span><span class="p">,</span>
</span><span id="L-184"><a href="#L-184"><span class="linenos">184</span></a> <span class="s2">&quot;LEFT&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span><span class="p">[:</span><span class="n">e</span><span class="p">]),</span>
</span><span id="L-185"><a href="#L-185"><span class="linenos">185</span></a> <span class="s2">&quot;LIKE&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span>
</span><span id="L-186"><a href="#L-186"><span class="linenos">186</span></a> <span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="nb">bool</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">e</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">&quot;_&quot;</span><span class="p">,</span> <span class="s2">&quot;.&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">&quot;%&quot;</span><span class="p">,</span> <span class="s2">&quot;.*&quot;</span><span class="p">),</span> <span class="n">this</span><span class="p">))</span>
</span><span id="L-187"><a href="#L-187"><span class="linenos">187</span></a> <span class="p">),</span>
</span><span id="L-188"><a href="#L-188"><span class="linenos">188</span></a> <span class="s2">&quot;LOWER&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">arg</span><span class="p">:</span> <span class="n">arg</span><span class="o">.</span><span class="n">lower</span><span class="p">()),</span>
</span><span id="L-189"><a href="#L-189"><span class="linenos">189</span></a> <span class="s2">&quot;LT&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span> <span class="o">&lt;</span> <span class="n">e</span><span class="p">),</span>
</span><span id="L-190"><a href="#L-190"><span class="linenos">190</span></a> <span class="s2">&quot;LTE&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span> <span class="o">&lt;=</span> <span class="n">e</span><span class="p">),</span>
</span><span id="L-191"><a href="#L-191"><span class="linenos">191</span></a> <span class="s2">&quot;MAP&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="nb">dict</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">))),</span> <span class="c1"># type: ignore</span>
</span><span id="L-192"><a href="#L-192"><span class="linenos">192</span></a> <span class="s2">&quot;MOD&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">e</span><span class="p">,</span> <span class="n">this</span><span class="p">:</span> <span class="n">e</span> <span class="o">%</span> <span class="n">this</span><span class="p">),</span>
</span><span id="L-193"><a href="#L-193"><span class="linenos">193</span></a> <span class="s2">&quot;MUL&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">e</span><span class="p">,</span> <span class="n">this</span><span class="p">:</span> <span class="n">e</span> <span class="o">*</span> <span class="n">this</span><span class="p">),</span>
</span><span id="L-194"><a href="#L-194"><span class="linenos">194</span></a> <span class="s2">&quot;NEQ&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span> <span class="o">!=</span> <span class="n">e</span><span class="p">),</span>
</span><span id="L-195"><a href="#L-195"><span class="linenos">195</span></a> <span class="s2">&quot;ORD&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="nb">ord</span><span class="p">),</span>
</span><span id="L-196"><a href="#L-196"><span class="linenos">196</span></a> <span class="s2">&quot;ORDERED&quot;</span><span class="p">:</span> <span class="n">ordered</span><span class="p">,</span>
</span><span id="L-197"><a href="#L-197"><span class="linenos">197</span></a> <span class="s2">&quot;POW&quot;</span><span class="p">:</span> <span class="nb">pow</span><span class="p">,</span>
</span><span id="L-198"><a href="#L-198"><span class="linenos">198</span></a> <span class="s2">&quot;RIGHT&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span><span class="p">[</span><span class="o">-</span><span class="n">e</span><span class="p">:]),</span>
</span><span id="L-199"><a href="#L-199"><span class="linenos">199</span></a> <span class="s2">&quot;STRPOSITION&quot;</span><span class="p">:</span> <span class="n">str_position</span><span class="p">,</span>
</span><span id="L-200"><a href="#L-200"><span class="linenos">200</span></a> <span class="s2">&quot;SUB&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">e</span><span class="p">,</span> <span class="n">this</span><span class="p">:</span> <span class="n">e</span> <span class="o">-</span> <span class="n">this</span><span class="p">),</span>
</span><span id="L-201"><a href="#L-201"><span class="linenos">201</span></a> <span class="s2">&quot;SUBSTRING&quot;</span><span class="p">:</span> <span class="n">substring</span><span class="p">,</span>
</span><span id="L-202"><a href="#L-202"><span class="linenos">202</span></a> <span class="s2">&quot;TIMESTRTOTIME&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">arg</span><span class="p">:</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">fromisoformat</span><span class="p">(</span><span class="n">arg</span><span class="p">)),</span>
</span><span id="L-203"><a href="#L-203"><span class="linenos">203</span></a> <span class="s2">&quot;UPPER&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">arg</span><span class="p">:</span> <span class="n">arg</span><span class="o">.</span><span class="n">upper</span><span class="p">()),</span>
</span><span id="L-204"><a href="#L-204"><span class="linenos">204</span></a> <span class="s2">&quot;YEAR&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">arg</span><span class="p">:</span> <span class="n">arg</span><span class="o">.</span><span class="n">year</span><span class="p">),</span>
</span><span id="L-205"><a href="#L-205"><span class="linenos">205</span></a> <span class="s2">&quot;MONTH&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">arg</span><span class="p">:</span> <span class="n">arg</span><span class="o">.</span><span class="n">month</span><span class="p">),</span>
</span><span id="L-206"><a href="#L-206"><span class="linenos">206</span></a> <span class="s2">&quot;DAY&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">arg</span><span class="p">:</span> <span class="n">arg</span><span class="o">.</span><span class="n">day</span><span class="p">),</span>
</span><span id="L-207"><a href="#L-207"><span class="linenos">207</span></a> <span class="s2">&quot;CURRENTDATETIME&quot;</span><span class="p">:</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">,</span>
</span><span id="L-208"><a href="#L-208"><span class="linenos">208</span></a> <span class="s2">&quot;CURRENTTIMESTAMP&quot;</span><span class="p">:</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">,</span>
</span><span id="L-209"><a href="#L-209"><span class="linenos">209</span></a> <span class="s2">&quot;CURRENTTIME&quot;</span><span class="p">:</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">,</span>
</span><span id="L-210"><a href="#L-210"><span class="linenos">210</span></a> <span class="s2">&quot;CURRENTDATE&quot;</span><span class="p">:</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">today</span><span class="p">,</span>
</span><span id="L-211"><a href="#L-211"><span class="linenos">211</span></a> <span class="s2">&quot;STRFTIME&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">fmt</span><span class="p">,</span> <span class="n">arg</span><span class="p">:</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">fromisoformat</span><span class="p">(</span><span class="n">arg</span><span class="p">)</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="n">fmt</span><span class="p">)),</span>
</span><span id="L-212"><a href="#L-212"><span class="linenos">212</span></a> <span class="s2">&quot;TRIM&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="o">=</span><span class="kc">None</span><span class="p">:</span> <span class="n">this</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="n">e</span><span class="p">)),</span>
</span><span id="L-213"><a href="#L-213"><span class="linenos">213</span></a> <span class="s2">&quot;STRUCT&quot;</span><span class="p">:</span> <span class="k">lambda</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="p">{</span>
</span><span id="L-214"><a href="#L-214"><span class="linenos">214</span></a> <span class="n">args</span><span class="p">[</span><span class="n">x</span><span class="p">]:</span> <span class="n">args</span><span class="p">[</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
</span><span id="L-215"><a href="#L-215"><span class="linenos">215</span></a> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">args</span><span class="p">),</span> <span class="mi">2</span><span class="p">)</span>
</span><span id="L-216"><a href="#L-216"><span class="linenos">216</span></a> <span class="k">if</span> <span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">args</span><span class="p">[</span><span class="n">x</span><span class="p">]</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">)</span>
</span><span id="L-217"><a href="#L-217"><span class="linenos">217</span></a> <span class="p">},</span>
</span><span id="L-218"><a href="#L-218"><span class="linenos">218</span></a><span class="p">}</span>
</span><span id="L-146"><a href="#L-146"><span class="linenos">146</span></a><span class="nd">@null_if_any</span><span class="p">(</span><span class="s2">&quot;this&quot;</span><span class="p">,</span> <span class="s2">&quot;expression&quot;</span><span class="p">)</span>
</span><span id="L-147"><a href="#L-147"><span class="linenos">147</span></a><span class="k">def</span> <span class="nf">jsonextract</span><span class="p">(</span><span class="n">this</span><span class="p">,</span> <span class="n">expression</span><span class="p">):</span>
</span><span id="L-148"><a href="#L-148"><span class="linenos">148</span></a> <span class="k">for</span> <span class="n">path_segment</span> <span class="ow">in</span> <span class="n">expression</span><span class="p">:</span>
</span><span id="L-149"><a href="#L-149"><span class="linenos">149</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">this</span><span class="p">,</span> <span class="nb">dict</span><span class="p">):</span>
</span><span id="L-150"><a href="#L-150"><span class="linenos">150</span></a> <span class="n">this</span> <span class="o">=</span> <span class="n">this</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">path_segment</span><span class="p">)</span>
</span><span id="L-151"><a href="#L-151"><span class="linenos">151</span></a> <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">this</span><span class="p">,</span> <span class="nb">list</span><span class="p">)</span> <span class="ow">and</span> <span class="n">is_int</span><span class="p">(</span><span class="n">path_segment</span><span class="p">):</span>
</span><span id="L-152"><a href="#L-152"><span class="linenos">152</span></a> <span class="n">this</span> <span class="o">=</span> <span class="n">seq_get</span><span class="p">(</span><span class="n">this</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">path_segment</span><span class="p">))</span>
</span><span id="L-153"><a href="#L-153"><span class="linenos">153</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-154"><a href="#L-154"><span class="linenos">154</span></a> <span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Unable to extract value for </span><span class="si">{</span><span class="n">this</span><span class="si">}</span><span class="s2"> at </span><span class="si">{</span><span class="n">path_segment</span><span class="si">}</span><span class="s2">.&quot;</span><span class="p">)</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="k">if</span> <span class="n">this</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="L-157"><a href="#L-157"><span class="linenos">157</span></a> <span class="k">break</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">return</span> <span class="n">this</span>
</span><span id="L-160"><a href="#L-160"><span class="linenos">160</span></a>
</span><span id="L-161"><a href="#L-161"><span class="linenos">161</span></a>
</span><span id="L-162"><a href="#L-162"><span class="linenos">162</span></a><span class="n">ENV</span> <span class="o">=</span> <span class="p">{</span>
</span><span id="L-163"><a href="#L-163"><span class="linenos">163</span></a> <span class="s2">&quot;exp&quot;</span><span class="p">:</span> <span class="n">exp</span><span class="p">,</span>
</span><span id="L-164"><a href="#L-164"><span class="linenos">164</span></a> <span class="c1"># aggs</span>
</span><span id="L-165"><a href="#L-165"><span class="linenos">165</span></a> <span class="s2">&quot;ARRAYAGG&quot;</span><span class="p">:</span> <span class="nb">list</span><span class="p">,</span>
</span><span id="L-166"><a href="#L-166"><span class="linenos">166</span></a> <span class="s2">&quot;ARRAYUNIQUEAGG&quot;</span><span class="p">:</span> <span class="n">filter_nulls</span><span class="p">(</span><span class="k">lambda</span> <span class="n">acc</span><span class="p">:</span> <span class="nb">list</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">acc</span><span class="p">))),</span>
</span><span id="L-167"><a href="#L-167"><span class="linenos">167</span></a> <span class="s2">&quot;AVG&quot;</span><span class="p">:</span> <span class="n">filter_nulls</span><span class="p">(</span><span class="n">statistics</span><span class="o">.</span><span class="n">fmean</span> <span class="k">if</span> <span class="n">PYTHON_VERSION</span> <span class="o">&gt;=</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">8</span><span class="p">)</span> <span class="k">else</span> <span class="n">statistics</span><span class="o">.</span><span class="n">mean</span><span class="p">),</span> <span class="c1"># type: ignore</span>
</span><span id="L-168"><a href="#L-168"><span class="linenos">168</span></a> <span class="s2">&quot;COUNT&quot;</span><span class="p">:</span> <span class="n">filter_nulls</span><span class="p">(</span><span class="k">lambda</span> <span class="n">acc</span><span class="p">:</span> <span class="nb">sum</span><span class="p">(</span><span class="mi">1</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="n">acc</span><span class="p">),</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="s2">&quot;MAX&quot;</span><span class="p">:</span> <span class="n">filter_nulls</span><span class="p">(</span><span class="nb">max</span><span class="p">),</span>
</span><span id="L-170"><a href="#L-170"><span class="linenos">170</span></a> <span class="s2">&quot;MIN&quot;</span><span class="p">:</span> <span class="n">filter_nulls</span><span class="p">(</span><span class="nb">min</span><span class="p">),</span>
</span><span id="L-171"><a href="#L-171"><span class="linenos">171</span></a> <span class="s2">&quot;SUM&quot;</span><span class="p">:</span> <span class="n">filter_nulls</span><span class="p">(</span><span class="nb">sum</span><span class="p">),</span>
</span><span id="L-172"><a href="#L-172"><span class="linenos">172</span></a> <span class="c1"># scalar functions</span>
</span><span id="L-173"><a href="#L-173"><span class="linenos">173</span></a> <span class="s2">&quot;ABS&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">:</span> <span class="nb">abs</span><span class="p">(</span><span class="n">this</span><span class="p">)),</span>
</span><span id="L-174"><a href="#L-174"><span class="linenos">174</span></a> <span class="s2">&quot;ADD&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">e</span><span class="p">,</span> <span class="n">this</span><span class="p">:</span> <span class="n">e</span> <span class="o">+</span> <span class="n">this</span><span class="p">),</span>
</span><span id="L-175"><a href="#L-175"><span class="linenos">175</span></a> <span class="s2">&quot;ARRAYANY&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">arr</span><span class="p">,</span> <span class="n">func</span><span class="p">:</span> <span class="nb">any</span><span class="p">(</span><span class="n">func</span><span class="p">(</span><span class="n">e</span><span class="p">)</span> <span class="k">for</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">arr</span><span class="p">)),</span>
</span><span id="L-176"><a href="#L-176"><span class="linenos">176</span></a> <span class="s2">&quot;ARRAYJOIN&quot;</span><span class="p">:</span> <span class="n">arrayjoin</span><span class="p">,</span>
</span><span id="L-177"><a href="#L-177"><span class="linenos">177</span></a> <span class="s2">&quot;BETWEEN&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">low</span><span class="p">,</span> <span class="n">high</span><span class="p">:</span> <span class="n">low</span> <span class="o">&lt;=</span> <span class="n">this</span> <span class="ow">and</span> <span class="n">this</span> <span class="o">&lt;=</span> <span class="n">high</span><span class="p">),</span>
</span><span id="L-178"><a href="#L-178"><span class="linenos">178</span></a> <span class="s2">&quot;BITWISEAND&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span> <span class="o">&amp;</span> <span class="n">e</span><span class="p">),</span>
</span><span id="L-179"><a href="#L-179"><span class="linenos">179</span></a> <span class="s2">&quot;BITWISELEFTSHIFT&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span> <span class="o">&lt;&lt;</span> <span class="n">e</span><span class="p">),</span>
</span><span id="L-180"><a href="#L-180"><span class="linenos">180</span></a> <span class="s2">&quot;BITWISEOR&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span> <span class="o">|</span> <span class="n">e</span><span class="p">),</span>
</span><span id="L-181"><a href="#L-181"><span class="linenos">181</span></a> <span class="s2">&quot;BITWISERIGHTSHIFT&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span> <span class="o">&gt;&gt;</span> <span class="n">e</span><span class="p">),</span>
</span><span id="L-182"><a href="#L-182"><span class="linenos">182</span></a> <span class="s2">&quot;BITWISEXOR&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span> <span class="o">^</span> <span class="n">e</span><span class="p">),</span>
</span><span id="L-183"><a href="#L-183"><span class="linenos">183</span></a> <span class="s2">&quot;CAST&quot;</span><span class="p">:</span> <span class="n">cast</span><span class="p">,</span>
</span><span id="L-184"><a href="#L-184"><span class="linenos">184</span></a> <span class="s2">&quot;COALESCE&quot;</span><span class="p">:</span> <span class="k">lambda</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="nb">next</span><span class="p">((</span><span class="n">a</span> <span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">args</span> <span class="k">if</span> <span class="n">a</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">),</span> <span class="kc">None</span><span class="p">),</span>
</span><span id="L-185"><a href="#L-185"><span class="linenos">185</span></a> <span class="s2">&quot;CONCAT&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="s2">&quot;&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">args</span><span class="p">)),</span>
</span><span id="L-186"><a href="#L-186"><span class="linenos">186</span></a> <span class="s2">&quot;SAFECONCAT&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="s2">&quot;&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">arg</span><span class="p">)</span> <span class="k">for</span> <span class="n">arg</span> <span class="ow">in</span> <span class="n">args</span><span class="p">)),</span>
</span><span id="L-187"><a href="#L-187"><span class="linenos">187</span></a> <span class="s2">&quot;CONCATWS&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">this</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">args</span><span class="p">)),</span>
</span><span id="L-188"><a href="#L-188"><span class="linenos">188</span></a> <span class="s2">&quot;DATEDIFF&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="o">*</span><span class="n">_</span><span class="p">:</span> <span class="p">(</span><span class="n">this</span> <span class="o">-</span> <span class="n">expression</span><span class="p">)</span><span class="o">.</span><span class="n">days</span><span class="p">),</span>
</span><span id="L-189"><a href="#L-189"><span class="linenos">189</span></a> <span class="s2">&quot;DATESTRTODATE&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">arg</span><span class="p">:</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">fromisoformat</span><span class="p">(</span><span class="n">arg</span><span class="p">)),</span>
</span><span id="L-190"><a href="#L-190"><span class="linenos">190</span></a> <span class="s2">&quot;DIV&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">e</span><span class="p">,</span> <span class="n">this</span><span class="p">:</span> <span class="n">e</span> <span class="o">/</span> <span class="n">this</span><span class="p">),</span>
</span><span id="L-191"><a href="#L-191"><span class="linenos">191</span></a> <span class="s2">&quot;DOT&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">e</span><span class="p">,</span> <span class="n">this</span><span class="p">:</span> <span class="n">e</span><span class="p">[</span><span class="n">this</span><span class="p">]),</span>
</span><span id="L-192"><a href="#L-192"><span class="linenos">192</span></a> <span class="s2">&quot;EQ&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span> <span class="o">==</span> <span class="n">e</span><span class="p">),</span>
</span><span id="L-193"><a href="#L-193"><span class="linenos">193</span></a> <span class="s2">&quot;EXTRACT&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">this</span><span class="p">)),</span>
</span><span id="L-194"><a href="#L-194"><span class="linenos">194</span></a> <span class="s2">&quot;GT&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span> <span class="o">&gt;</span> <span class="n">e</span><span class="p">),</span>
</span><span id="L-195"><a href="#L-195"><span class="linenos">195</span></a> <span class="s2">&quot;GTE&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span> <span class="o">&gt;=</span> <span class="n">e</span><span class="p">),</span>
</span><span id="L-196"><a href="#L-196"><span class="linenos">196</span></a> <span class="s2">&quot;IF&quot;</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">predicate</span><span class="p">,</span> <span class="n">true</span><span class="p">,</span> <span class="n">false</span><span class="p">:</span> <span class="n">true</span> <span class="k">if</span> <span class="n">predicate</span> <span class="k">else</span> <span class="n">false</span><span class="p">,</span>
</span><span id="L-197"><a href="#L-197"><span class="linenos">197</span></a> <span class="s2">&quot;INTDIV&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">e</span><span class="p">,</span> <span class="n">this</span><span class="p">:</span> <span class="n">e</span> <span class="o">//</span> <span class="n">this</span><span class="p">),</span>
</span><span id="L-198"><a href="#L-198"><span class="linenos">198</span></a> <span class="s2">&quot;INTERVAL&quot;</span><span class="p">:</span> <span class="n">interval</span><span class="p">,</span>
</span><span id="L-199"><a href="#L-199"><span class="linenos">199</span></a> <span class="s2">&quot;JSONEXTRACT&quot;</span><span class="p">:</span> <span class="n">jsonextract</span><span class="p">,</span>
</span><span id="L-200"><a href="#L-200"><span class="linenos">200</span></a> <span class="s2">&quot;LEFT&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span><span class="p">[:</span><span class="n">e</span><span class="p">]),</span>
</span><span id="L-201"><a href="#L-201"><span class="linenos">201</span></a> <span class="s2">&quot;LIKE&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span>
</span><span id="L-202"><a href="#L-202"><span class="linenos">202</span></a> <span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="nb">bool</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">e</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">&quot;_&quot;</span><span class="p">,</span> <span class="s2">&quot;.&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">&quot;%&quot;</span><span class="p">,</span> <span class="s2">&quot;.*&quot;</span><span class="p">),</span> <span class="n">this</span><span class="p">))</span>
</span><span id="L-203"><a href="#L-203"><span class="linenos">203</span></a> <span class="p">),</span>
</span><span id="L-204"><a href="#L-204"><span class="linenos">204</span></a> <span class="s2">&quot;LOWER&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">arg</span><span class="p">:</span> <span class="n">arg</span><span class="o">.</span><span class="n">lower</span><span class="p">()),</span>
</span><span id="L-205"><a href="#L-205"><span class="linenos">205</span></a> <span class="s2">&quot;LT&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span> <span class="o">&lt;</span> <span class="n">e</span><span class="p">),</span>
</span><span id="L-206"><a href="#L-206"><span class="linenos">206</span></a> <span class="s2">&quot;LTE&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span> <span class="o">&lt;=</span> <span class="n">e</span><span class="p">),</span>
</span><span id="L-207"><a href="#L-207"><span class="linenos">207</span></a> <span class="s2">&quot;MAP&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="nb">dict</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">))),</span> <span class="c1"># type: ignore</span>
</span><span id="L-208"><a href="#L-208"><span class="linenos">208</span></a> <span class="s2">&quot;MOD&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">e</span><span class="p">,</span> <span class="n">this</span><span class="p">:</span> <span class="n">e</span> <span class="o">%</span> <span class="n">this</span><span class="p">),</span>
</span><span id="L-209"><a href="#L-209"><span class="linenos">209</span></a> <span class="s2">&quot;MUL&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">e</span><span class="p">,</span> <span class="n">this</span><span class="p">:</span> <span class="n">e</span> <span class="o">*</span> <span class="n">this</span><span class="p">),</span>
</span><span id="L-210"><a href="#L-210"><span class="linenos">210</span></a> <span class="s2">&quot;NEQ&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span> <span class="o">!=</span> <span class="n">e</span><span class="p">),</span>
</span><span id="L-211"><a href="#L-211"><span class="linenos">211</span></a> <span class="s2">&quot;ORD&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="nb">ord</span><span class="p">),</span>
</span><span id="L-212"><a href="#L-212"><span class="linenos">212</span></a> <span class="s2">&quot;ORDERED&quot;</span><span class="p">:</span> <span class="n">ordered</span><span class="p">,</span>
</span><span id="L-213"><a href="#L-213"><span class="linenos">213</span></a> <span class="s2">&quot;POW&quot;</span><span class="p">:</span> <span class="nb">pow</span><span class="p">,</span>
</span><span id="L-214"><a href="#L-214"><span class="linenos">214</span></a> <span class="s2">&quot;RIGHT&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="n">this</span><span class="p">[</span><span class="o">-</span><span class="n">e</span><span class="p">:]),</span>
</span><span id="L-215"><a href="#L-215"><span class="linenos">215</span></a> <span class="s2">&quot;STRPOSITION&quot;</span><span class="p">:</span> <span class="n">str_position</span><span class="p">,</span>
</span><span id="L-216"><a href="#L-216"><span class="linenos">216</span></a> <span class="s2">&quot;SUB&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">e</span><span class="p">,</span> <span class="n">this</span><span class="p">:</span> <span class="n">e</span> <span class="o">-</span> <span class="n">this</span><span class="p">),</span>
</span><span id="L-217"><a href="#L-217"><span class="linenos">217</span></a> <span class="s2">&quot;SUBSTRING&quot;</span><span class="p">:</span> <span class="n">substring</span><span class="p">,</span>
</span><span id="L-218"><a href="#L-218"><span class="linenos">218</span></a> <span class="s2">&quot;TIMESTRTOTIME&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">arg</span><span class="p">:</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">fromisoformat</span><span class="p">(</span><span class="n">arg</span><span class="p">)),</span>
</span><span id="L-219"><a href="#L-219"><span class="linenos">219</span></a> <span class="s2">&quot;UPPER&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">arg</span><span class="p">:</span> <span class="n">arg</span><span class="o">.</span><span class="n">upper</span><span class="p">()),</span>
</span><span id="L-220"><a href="#L-220"><span class="linenos">220</span></a> <span class="s2">&quot;YEAR&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">arg</span><span class="p">:</span> <span class="n">arg</span><span class="o">.</span><span class="n">year</span><span class="p">),</span>
</span><span id="L-221"><a href="#L-221"><span class="linenos">221</span></a> <span class="s2">&quot;MONTH&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">arg</span><span class="p">:</span> <span class="n">arg</span><span class="o">.</span><span class="n">month</span><span class="p">),</span>
</span><span id="L-222"><a href="#L-222"><span class="linenos">222</span></a> <span class="s2">&quot;DAY&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">arg</span><span class="p">:</span> <span class="n">arg</span><span class="o">.</span><span class="n">day</span><span class="p">),</span>
</span><span id="L-223"><a href="#L-223"><span class="linenos">223</span></a> <span class="s2">&quot;CURRENTDATETIME&quot;</span><span class="p">:</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">,</span>
</span><span id="L-224"><a href="#L-224"><span class="linenos">224</span></a> <span class="s2">&quot;CURRENTTIMESTAMP&quot;</span><span class="p">:</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">,</span>
</span><span id="L-225"><a href="#L-225"><span class="linenos">225</span></a> <span class="s2">&quot;CURRENTTIME&quot;</span><span class="p">:</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">,</span>
</span><span id="L-226"><a href="#L-226"><span class="linenos">226</span></a> <span class="s2">&quot;CURRENTDATE&quot;</span><span class="p">:</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">today</span><span class="p">,</span>
</span><span id="L-227"><a href="#L-227"><span class="linenos">227</span></a> <span class="s2">&quot;STRFTIME&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">fmt</span><span class="p">,</span> <span class="n">arg</span><span class="p">:</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">fromisoformat</span><span class="p">(</span><span class="n">arg</span><span class="p">)</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="n">fmt</span><span class="p">)),</span>
</span><span id="L-228"><a href="#L-228"><span class="linenos">228</span></a> <span class="s2">&quot;TRIM&quot;</span><span class="p">:</span> <span class="n">null_if_any</span><span class="p">(</span><span class="k">lambda</span> <span class="n">this</span><span class="p">,</span> <span class="n">e</span><span class="o">=</span><span class="kc">None</span><span class="p">:</span> <span class="n">this</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="n">e</span><span class="p">)),</span>
</span><span id="L-229"><a href="#L-229"><span class="linenos">229</span></a> <span class="s2">&quot;STRUCT&quot;</span><span class="p">:</span> <span class="k">lambda</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="p">{</span>
</span><span id="L-230"><a href="#L-230"><span class="linenos">230</span></a> <span class="n">args</span><span class="p">[</span><span class="n">x</span><span class="p">]:</span> <span class="n">args</span><span class="p">[</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
</span><span id="L-231"><a href="#L-231"><span class="linenos">231</span></a> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">args</span><span class="p">),</span> <span class="mi">2</span><span class="p">)</span>
</span><span id="L-232"><a href="#L-232"><span class="linenos">232</span></a> <span class="k">if</span> <span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">args</span><span class="p">[</span><span class="n">x</span><span class="p">]</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">)</span>
</span><span id="L-233"><a href="#L-233"><span class="linenos">233</span></a> <span class="p">},</span>
</span><span id="L-234"><a href="#L-234"><span class="linenos">234</span></a><span class="p">}</span>
</span></pre></div>
@ -626,12 +645,44 @@ def foo(a, b): ...
</section>
<section id="jsonextract">
<input id="jsonextract-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
<div class="attr function">
<div class="decorator">@null_if_any(&#39;this&#39;, &#39;expression&#39;)</div>
<span class="def">def</span>
<span class="name">jsonextract</span><span class="signature pdoc-code condensed">(<span class="param"><span class="n">this</span>, </span><span class="param"><span class="n">expression</span></span><span class="return-annotation">):</span></span>
<label class="view-source-button" for="jsonextract-view-source"><span>View Source</span></label>
</div>
<a class="headerlink" href="#jsonextract"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="jsonextract-147"><a href="#jsonextract-147"><span class="linenos">147</span></a><span class="nd">@null_if_any</span><span class="p">(</span><span class="s2">&quot;this&quot;</span><span class="p">,</span> <span class="s2">&quot;expression&quot;</span><span class="p">)</span>
</span><span id="jsonextract-148"><a href="#jsonextract-148"><span class="linenos">148</span></a><span class="k">def</span> <span class="nf">jsonextract</span><span class="p">(</span><span class="n">this</span><span class="p">,</span> <span class="n">expression</span><span class="p">):</span>
</span><span id="jsonextract-149"><a href="#jsonextract-149"><span class="linenos">149</span></a> <span class="k">for</span> <span class="n">path_segment</span> <span class="ow">in</span> <span class="n">expression</span><span class="p">:</span>
</span><span id="jsonextract-150"><a href="#jsonextract-150"><span class="linenos">150</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">this</span><span class="p">,</span> <span class="nb">dict</span><span class="p">):</span>
</span><span id="jsonextract-151"><a href="#jsonextract-151"><span class="linenos">151</span></a> <span class="n">this</span> <span class="o">=</span> <span class="n">this</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">path_segment</span><span class="p">)</span>
</span><span id="jsonextract-152"><a href="#jsonextract-152"><span class="linenos">152</span></a> <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">this</span><span class="p">,</span> <span class="nb">list</span><span class="p">)</span> <span class="ow">and</span> <span class="n">is_int</span><span class="p">(</span><span class="n">path_segment</span><span class="p">):</span>
</span><span id="jsonextract-153"><a href="#jsonextract-153"><span class="linenos">153</span></a> <span class="n">this</span> <span class="o">=</span> <span class="n">seq_get</span><span class="p">(</span><span class="n">this</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">path_segment</span><span class="p">))</span>
</span><span id="jsonextract-154"><a href="#jsonextract-154"><span class="linenos">154</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="jsonextract-155"><a href="#jsonextract-155"><span class="linenos">155</span></a> <span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Unable to extract value for </span><span class="si">{</span><span class="n">this</span><span class="si">}</span><span class="s2"> at </span><span class="si">{</span><span class="n">path_segment</span><span class="si">}</span><span class="s2">.&quot;</span><span class="p">)</span>
</span><span id="jsonextract-156"><a href="#jsonextract-156"><span class="linenos">156</span></a>
</span><span id="jsonextract-157"><a href="#jsonextract-157"><span class="linenos">157</span></a> <span class="k">if</span> <span class="n">this</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="jsonextract-158"><a href="#jsonextract-158"><span class="linenos">158</span></a> <span class="k">break</span>
</span><span id="jsonextract-159"><a href="#jsonextract-159"><span class="linenos">159</span></a>
</span><span id="jsonextract-160"><a href="#jsonextract-160"><span class="linenos">160</span></a> <span class="k">return</span> <span class="n">this</span>
</span></pre></div>
</section>
<section id="ENV">
<div class="attr variable">
<span class="name">ENV</span> =
<input id="ENV-view-value" class="view-value-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
<label class="view-value-button pdoc-button" for="ENV-view-value"></label><span class="default_value">{&#39;exp&#39;: &lt;module &#39;<a href="../expressions.html">sqlglot.expressions</a>&#39; from &#39;/home/runner/work/sqlglot/sqlglot/sqlglot/expressions.py&#39;&gt;, &#39;ARRAYAGG&#39;: &lt;class &#39;list&#39;&gt;, &#39;ARRAYUNIQUEAGG&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;AVG&#39;: &lt;function fmean&gt;, &#39;COUNT&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;MAX&#39;: &lt;function max&gt;, &#39;MIN&#39;: &lt;function min&gt;, &#39;SUM&#39;: &lt;function sum&gt;, &#39;ABS&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;ADD&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;ARRAYANY&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;ARRAYJOIN&#39;: &lt;function arrayjoin&gt;, &#39;BETWEEN&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;BITWISEAND&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;BITWISELEFTSHIFT&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;BITWISEOR&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;BITWISERIGHTSHIFT&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;BITWISEXOR&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;CAST&#39;: &lt;function cast&gt;, &#39;COALESCE&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;CONCAT&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;SAFECONCAT&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;CONCATWS&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;DATEDIFF&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;DATESTRTODATE&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;DIV&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;DOT&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;EQ&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;EXTRACT&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;GETPATH&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;GT&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;GTE&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;IF&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;INTDIV&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;INTERVAL&#39;: &lt;function interval&gt;, &#39;LEFT&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;LIKE&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;LOWER&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;LT&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;LTE&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;MAP&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;MOD&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;MUL&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;NEQ&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;ORD&#39;: &lt;function ord&gt;, &#39;ORDERED&#39;: &lt;function ordered&gt;, &#39;POW&#39;: &lt;built-in function pow&gt;, &#39;RIGHT&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;STRPOSITION&#39;: &lt;function str_position&gt;, &#39;SUB&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;SUBSTRING&#39;: &lt;function substring&gt;, &#39;TIMESTRTOTIME&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;UPPER&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;YEAR&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;MONTH&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;DAY&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;CURRENTDATETIME&#39;: &lt;built-in method now of type object&gt;, &#39;CURRENTTIMESTAMP&#39;: &lt;built-in method now of type object&gt;, &#39;CURRENTTIME&#39;: &lt;built-in method now of type object&gt;, &#39;CURRENTDATE&#39;: &lt;built-in method today of type object&gt;, &#39;STRFTIME&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;TRIM&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;STRUCT&#39;: &lt;function &lt;lambda&gt;&gt;}</span>
<label class="view-value-button pdoc-button" for="ENV-view-value"></label><span class="default_value">{&#39;exp&#39;: &lt;module &#39;<a href="../expressions.html">sqlglot.expressions</a>&#39; from &#39;/home/runner/work/sqlglot/sqlglot/sqlglot/expressions.py&#39;&gt;, &#39;ARRAYAGG&#39;: &lt;class &#39;list&#39;&gt;, &#39;ARRAYUNIQUEAGG&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;AVG&#39;: &lt;function fmean&gt;, &#39;COUNT&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;MAX&#39;: &lt;function max&gt;, &#39;MIN&#39;: &lt;function min&gt;, &#39;SUM&#39;: &lt;function sum&gt;, &#39;ABS&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;ADD&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;ARRAYANY&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;ARRAYJOIN&#39;: &lt;function arrayjoin&gt;, &#39;BETWEEN&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;BITWISEAND&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;BITWISELEFTSHIFT&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;BITWISEOR&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;BITWISERIGHTSHIFT&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;BITWISEXOR&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;CAST&#39;: &lt;function cast&gt;, &#39;COALESCE&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;CONCAT&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;SAFECONCAT&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;CONCATWS&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;DATEDIFF&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;DATESTRTODATE&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;DIV&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;DOT&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;EQ&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;EXTRACT&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;GT&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;GTE&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;IF&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;INTDIV&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;INTERVAL&#39;: &lt;function interval&gt;, &#39;JSONEXTRACT&#39;: &lt;function jsonextract&gt;, &#39;LEFT&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;LIKE&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;LOWER&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;LT&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;LTE&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;MAP&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;MOD&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;MUL&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;NEQ&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;ORD&#39;: &lt;function ord&gt;, &#39;ORDERED&#39;: &lt;function ordered&gt;, &#39;POW&#39;: &lt;built-in function pow&gt;, &#39;RIGHT&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;STRPOSITION&#39;: &lt;function str_position&gt;, &#39;SUB&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;SUBSTRING&#39;: &lt;function substring&gt;, &#39;TIMESTRTOTIME&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;UPPER&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;YEAR&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;MONTH&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;DAY&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;CURRENTDATETIME&#39;: &lt;built-in method now of type object&gt;, &#39;CURRENTTIMESTAMP&#39;: &lt;built-in method now of type object&gt;, &#39;CURRENTTIME&#39;: &lt;built-in method now of type object&gt;, &#39;CURRENTDATE&#39;: &lt;built-in method today of type object&gt;, &#39;STRFTIME&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;TRIM&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;STRUCT&#39;: &lt;function &lt;lambda&gt;&gt;}</span>
</div>

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

@ -87,6 +87,9 @@
<li>
<a class="function" href="#find_new_name">find_new_name</a>
</li>
<li>
<a class="function" href="#is_int">is_int</a>
</li>
<li>
<a class="function" href="#name_sequence">name_sequence</a>
</li>
@ -384,7 +387,7 @@
</span><span id="L-236"><a href="#L-236"><span class="linenos">236</span></a>
</span><span id="L-237"><a href="#L-237"><span class="linenos">237</span></a> <span class="k">for</span> <span class="n">node</span><span class="p">,</span> <span class="n">deps</span> <span class="ow">in</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">dag</span><span class="o">.</span><span class="n">items</span><span class="p">()):</span>
</span><span id="L-238"><a href="#L-238"><span class="linenos">238</span></a> <span class="k">for</span> <span class="n">dep</span> <span class="ow">in</span> <span class="n">deps</span><span class="p">:</span>
</span><span id="L-239"><a href="#L-239"><span class="linenos">239</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">dep</span> <span class="ow">in</span> <span class="n">dag</span><span class="p">:</span>
</span><span id="L-239"><a href="#L-239"><span class="linenos">239</span></a> <span class="k">if</span> <span class="n">dep</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">dag</span><span class="p">:</span>
</span><span id="L-240"><a href="#L-240"><span class="linenos">240</span></a> <span class="n">dag</span><span class="p">[</span><span class="n">dep</span><span class="p">]</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
</span><span id="L-241"><a href="#L-241"><span class="linenos">241</span></a>
</span><span id="L-242"><a href="#L-242"><span class="linenos">242</span></a> <span class="k">while</span> <span class="n">dag</span><span class="p">:</span>
@ -468,174 +471,182 @@
</span><span id="L-320"><a href="#L-320"><span class="linenos">320</span></a> <span class="k">return</span> <span class="n">new</span>
</span><span id="L-321"><a href="#L-321"><span class="linenos">321</span></a>
</span><span id="L-322"><a href="#L-322"><span class="linenos">322</span></a>
</span><span id="L-323"><a href="#L-323"><span class="linenos">323</span></a><span class="k">def</span> <span class="nf">name_sequence</span><span class="p">(</span><span class="n">prefix</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Callable</span><span class="p">[[],</span> <span class="nb">str</span><span class="p">]:</span>
</span><span id="L-324"><a href="#L-324"><span class="linenos">324</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;Returns a name generator given a prefix (e.g. a0, a1, a2, ... if the prefix is &quot;a&quot;).&quot;&quot;&quot;</span>
</span><span id="L-325"><a href="#L-325"><span class="linenos">325</span></a> <span class="n">sequence</span> <span class="o">=</span> <span class="n">count</span><span class="p">()</span>
</span><span id="L-326"><a href="#L-326"><span class="linenos">326</span></a> <span class="k">return</span> <span class="k">lambda</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">prefix</span><span class="si">}{</span><span class="nb">next</span><span class="p">(</span><span class="n">sequence</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span>
</span><span id="L-327"><a href="#L-327"><span class="linenos">327</span></a>
</span><span id="L-328"><a href="#L-328"><span class="linenos">328</span></a>
</span><span id="L-329"><a href="#L-329"><span class="linenos">329</span></a><span class="k">def</span> <span class="nf">object_to_dict</span><span class="p">(</span><span class="n">obj</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Dict</span><span class="p">:</span>
</span><span id="L-330"><a href="#L-330"><span class="linenos">330</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;Returns a dictionary created from an object&#39;s attributes.&quot;&quot;&quot;</span>
</span><span id="L-331"><a href="#L-331"><span class="linenos">331</span></a> <span class="k">return</span> <span class="p">{</span>
</span><span id="L-332"><a href="#L-332"><span class="linenos">332</span></a> <span class="o">**</span><span class="p">{</span><span class="n">k</span><span class="p">:</span> <span class="n">v</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span> <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="s2">&quot;copy&quot;</span><span class="p">)</span> <span class="k">else</span> <span class="n">copy</span><span class="p">(</span><span class="n">v</span><span class="p">)</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">vars</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span><span class="o">.</span><span class="n">items</span><span class="p">()},</span>
</span><span id="L-333"><a href="#L-333"><span class="linenos">333</span></a> <span class="o">**</span><span class="n">kwargs</span><span class="p">,</span>
</span><span id="L-334"><a href="#L-334"><span class="linenos">334</span></a> <span class="p">}</span>
</span><span id="L-323"><a href="#L-323"><span class="linenos">323</span></a><span class="k">def</span> <span class="nf">is_int</span><span class="p">(</span><span class="n">text</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
</span><span id="L-324"><a href="#L-324"><span class="linenos">324</span></a> <span class="k">try</span><span class="p">:</span>
</span><span id="L-325"><a href="#L-325"><span class="linenos">325</span></a> <span class="nb">int</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
</span><span id="L-326"><a href="#L-326"><span class="linenos">326</span></a> <span class="k">return</span> <span class="kc">True</span>
</span><span id="L-327"><a href="#L-327"><span class="linenos">327</span></a> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
</span><span id="L-328"><a href="#L-328"><span class="linenos">328</span></a> <span class="k">return</span> <span class="kc">False</span>
</span><span id="L-329"><a href="#L-329"><span class="linenos">329</span></a>
</span><span id="L-330"><a href="#L-330"><span class="linenos">330</span></a>
</span><span id="L-331"><a href="#L-331"><span class="linenos">331</span></a><span class="k">def</span> <span class="nf">name_sequence</span><span class="p">(</span><span class="n">prefix</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Callable</span><span class="p">[[],</span> <span class="nb">str</span><span class="p">]:</span>
</span><span id="L-332"><a href="#L-332"><span class="linenos">332</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;Returns a name generator given a prefix (e.g. a0, a1, a2, ... if the prefix is &quot;a&quot;).&quot;&quot;&quot;</span>
</span><span id="L-333"><a href="#L-333"><span class="linenos">333</span></a> <span class="n">sequence</span> <span class="o">=</span> <span class="n">count</span><span class="p">()</span>
</span><span id="L-334"><a href="#L-334"><span class="linenos">334</span></a> <span class="k">return</span> <span class="k">lambda</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">prefix</span><span class="si">}{</span><span class="nb">next</span><span class="p">(</span><span class="n">sequence</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span>
</span><span id="L-335"><a href="#L-335"><span class="linenos">335</span></a>
</span><span id="L-336"><a href="#L-336"><span class="linenos">336</span></a>
</span><span id="L-337"><a href="#L-337"><span class="linenos">337</span></a><span class="k">def</span> <span class="nf">split_num_words</span><span class="p">(</span>
</span><span id="L-338"><a href="#L-338"><span class="linenos">338</span></a> <span class="n">value</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">sep</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">min_num_words</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">fill_from_start</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">True</span>
</span><span id="L-339"><a href="#L-339"><span class="linenos">339</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="nb">str</span><span class="p">]]:</span>
</span><span id="L-340"><a href="#L-340"><span class="linenos">340</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-341"><a href="#L-341"><span class="linenos">341</span></a><span class="sd"> Perform a split on a value and return N words as a result with `None` used for words that don&#39;t exist.</span>
</span><span id="L-342"><a href="#L-342"><span class="linenos">342</span></a>
</span><span id="L-343"><a href="#L-343"><span class="linenos">343</span></a><span class="sd"> Args:</span>
</span><span id="L-344"><a href="#L-344"><span class="linenos">344</span></a><span class="sd"> value: The value to be split.</span>
</span><span id="L-345"><a href="#L-345"><span class="linenos">345</span></a><span class="sd"> sep: The value to use to split on.</span>
</span><span id="L-346"><a href="#L-346"><span class="linenos">346</span></a><span class="sd"> min_num_words: The minimum number of words that are going to be in the result.</span>
</span><span id="L-347"><a href="#L-347"><span class="linenos">347</span></a><span class="sd"> fill_from_start: Indicates that if `None` values should be inserted at the start or end of the list.</span>
</span><span id="L-348"><a href="#L-348"><span class="linenos">348</span></a>
</span><span id="L-349"><a href="#L-349"><span class="linenos">349</span></a><span class="sd"> Examples:</span>
</span><span id="L-350"><a href="#L-350"><span class="linenos">350</span></a><span class="sd"> &gt;&gt;&gt; split_num_words(&quot;db.table&quot;, &quot;.&quot;, 3)</span>
</span><span id="L-351"><a href="#L-351"><span class="linenos">351</span></a><span class="sd"> [None, &#39;db&#39;, &#39;table&#39;]</span>
</span><span id="L-352"><a href="#L-352"><span class="linenos">352</span></a><span class="sd"> &gt;&gt;&gt; split_num_words(&quot;db.table&quot;, &quot;.&quot;, 3, fill_from_start=False)</span>
</span><span id="L-353"><a href="#L-353"><span class="linenos">353</span></a><span class="sd"> [&#39;db&#39;, &#39;table&#39;, None]</span>
</span><span id="L-354"><a href="#L-354"><span class="linenos">354</span></a><span class="sd"> &gt;&gt;&gt; split_num_words(&quot;db.table&quot;, &quot;.&quot;, 1)</span>
</span><span id="L-355"><a href="#L-355"><span class="linenos">355</span></a><span class="sd"> [&#39;db&#39;, &#39;table&#39;]</span>
</span><span id="L-337"><a href="#L-337"><span class="linenos">337</span></a><span class="k">def</span> <span class="nf">object_to_dict</span><span class="p">(</span><span class="n">obj</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Dict</span><span class="p">:</span>
</span><span id="L-338"><a href="#L-338"><span class="linenos">338</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;Returns a dictionary created from an object&#39;s attributes.&quot;&quot;&quot;</span>
</span><span id="L-339"><a href="#L-339"><span class="linenos">339</span></a> <span class="k">return</span> <span class="p">{</span>
</span><span id="L-340"><a href="#L-340"><span class="linenos">340</span></a> <span class="o">**</span><span class="p">{</span><span class="n">k</span><span class="p">:</span> <span class="n">v</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span> <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="s2">&quot;copy&quot;</span><span class="p">)</span> <span class="k">else</span> <span class="n">copy</span><span class="p">(</span><span class="n">v</span><span class="p">)</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">vars</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span><span class="o">.</span><span class="n">items</span><span class="p">()},</span>
</span><span id="L-341"><a href="#L-341"><span class="linenos">341</span></a> <span class="o">**</span><span class="n">kwargs</span><span class="p">,</span>
</span><span id="L-342"><a href="#L-342"><span class="linenos">342</span></a> <span class="p">}</span>
</span><span id="L-343"><a href="#L-343"><span class="linenos">343</span></a>
</span><span id="L-344"><a href="#L-344"><span class="linenos">344</span></a>
</span><span id="L-345"><a href="#L-345"><span class="linenos">345</span></a><span class="k">def</span> <span class="nf">split_num_words</span><span class="p">(</span>
</span><span id="L-346"><a href="#L-346"><span class="linenos">346</span></a> <span class="n">value</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">sep</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">min_num_words</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">fill_from_start</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">True</span>
</span><span id="L-347"><a href="#L-347"><span class="linenos">347</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="nb">str</span><span class="p">]]:</span>
</span><span id="L-348"><a href="#L-348"><span class="linenos">348</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-349"><a href="#L-349"><span class="linenos">349</span></a><span class="sd"> Perform a split on a value and return N words as a result with `None` used for words that don&#39;t exist.</span>
</span><span id="L-350"><a href="#L-350"><span class="linenos">350</span></a>
</span><span id="L-351"><a href="#L-351"><span class="linenos">351</span></a><span class="sd"> Args:</span>
</span><span id="L-352"><a href="#L-352"><span class="linenos">352</span></a><span class="sd"> value: The value to be split.</span>
</span><span id="L-353"><a href="#L-353"><span class="linenos">353</span></a><span class="sd"> sep: The value to use to split on.</span>
</span><span id="L-354"><a href="#L-354"><span class="linenos">354</span></a><span class="sd"> min_num_words: The minimum number of words that are going to be in the result.</span>
</span><span id="L-355"><a href="#L-355"><span class="linenos">355</span></a><span class="sd"> fill_from_start: Indicates that if `None` values should be inserted at the start or end of the list.</span>
</span><span id="L-356"><a href="#L-356"><span class="linenos">356</span></a>
</span><span id="L-357"><a href="#L-357"><span class="linenos">357</span></a><span class="sd"> Returns:</span>
</span><span id="L-358"><a href="#L-358"><span class="linenos">358</span></a><span class="sd"> The list of words returned by `split`, possibly augmented by a number of `None` values.</span>
</span><span id="L-359"><a href="#L-359"><span class="linenos">359</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-360"><a href="#L-360"><span class="linenos">360</span></a> <span class="n">words</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">sep</span><span class="p">)</span>
</span><span id="L-361"><a href="#L-361"><span class="linenos">361</span></a> <span class="k">if</span> <span class="n">fill_from_start</span><span class="p">:</span>
</span><span id="L-362"><a href="#L-362"><span class="linenos">362</span></a> <span class="k">return</span> <span class="p">[</span><span class="kc">None</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">min_num_words</span> <span class="o">-</span> <span class="nb">len</span><span class="p">(</span><span class="n">words</span><span class="p">))</span> <span class="o">+</span> <span class="n">words</span>
</span><span id="L-363"><a href="#L-363"><span class="linenos">363</span></a> <span class="k">return</span> <span class="n">words</span> <span class="o">+</span> <span class="p">[</span><span class="kc">None</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">min_num_words</span> <span class="o">-</span> <span class="nb">len</span><span class="p">(</span><span class="n">words</span><span class="p">))</span>
</span><span id="L-357"><a href="#L-357"><span class="linenos">357</span></a><span class="sd"> Examples:</span>
</span><span id="L-358"><a href="#L-358"><span class="linenos">358</span></a><span class="sd"> &gt;&gt;&gt; split_num_words(&quot;db.table&quot;, &quot;.&quot;, 3)</span>
</span><span id="L-359"><a href="#L-359"><span class="linenos">359</span></a><span class="sd"> [None, &#39;db&#39;, &#39;table&#39;]</span>
</span><span id="L-360"><a href="#L-360"><span class="linenos">360</span></a><span class="sd"> &gt;&gt;&gt; split_num_words(&quot;db.table&quot;, &quot;.&quot;, 3, fill_from_start=False)</span>
</span><span id="L-361"><a href="#L-361"><span class="linenos">361</span></a><span class="sd"> [&#39;db&#39;, &#39;table&#39;, None]</span>
</span><span id="L-362"><a href="#L-362"><span class="linenos">362</span></a><span class="sd"> &gt;&gt;&gt; split_num_words(&quot;db.table&quot;, &quot;.&quot;, 1)</span>
</span><span id="L-363"><a href="#L-363"><span class="linenos">363</span></a><span class="sd"> [&#39;db&#39;, &#39;table&#39;]</span>
</span><span id="L-364"><a href="#L-364"><span class="linenos">364</span></a>
</span><span id="L-365"><a href="#L-365"><span class="linenos">365</span></a>
</span><span id="L-366"><a href="#L-366"><span class="linenos">366</span></a><span class="k">def</span> <span class="nf">is_iterable</span><span class="p">(</span><span class="n">value</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
</span><span id="L-367"><a href="#L-367"><span class="linenos">367</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-368"><a href="#L-368"><span class="linenos">368</span></a><span class="sd"> Checks if the value is an iterable, excluding the types `str` and `bytes`.</span>
</span><span id="L-369"><a href="#L-369"><span class="linenos">369</span></a>
</span><span id="L-370"><a href="#L-370"><span class="linenos">370</span></a><span class="sd"> Examples:</span>
</span><span id="L-371"><a href="#L-371"><span class="linenos">371</span></a><span class="sd"> &gt;&gt;&gt; is_iterable([1,2])</span>
</span><span id="L-372"><a href="#L-372"><span class="linenos">372</span></a><span class="sd"> True</span>
</span><span id="L-373"><a href="#L-373"><span class="linenos">373</span></a><span class="sd"> &gt;&gt;&gt; is_iterable(&quot;test&quot;)</span>
</span><span id="L-374"><a href="#L-374"><span class="linenos">374</span></a><span class="sd"> False</span>
</span><span id="L-375"><a href="#L-375"><span class="linenos">375</span></a>
</span><span id="L-376"><a href="#L-376"><span class="linenos">376</span></a><span class="sd"> Args:</span>
</span><span id="L-377"><a href="#L-377"><span class="linenos">377</span></a><span class="sd"> value: The value to check if it is an iterable.</span>
</span><span id="L-378"><a href="#L-378"><span class="linenos">378</span></a>
</span><span id="L-379"><a href="#L-379"><span class="linenos">379</span></a><span class="sd"> Returns:</span>
</span><span id="L-380"><a href="#L-380"><span class="linenos">380</span></a><span class="sd"> A `bool` value indicating if it is an iterable.</span>
</span><span id="L-381"><a href="#L-381"><span class="linenos">381</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-382"><a href="#L-382"><span class="linenos">382</span></a> <span class="kn">from</span> <span class="nn">sqlglot</span> <span class="kn">import</span> <span class="n">Expression</span>
</span><span id="L-365"><a href="#L-365"><span class="linenos">365</span></a><span class="sd"> Returns:</span>
</span><span id="L-366"><a href="#L-366"><span class="linenos">366</span></a><span class="sd"> The list of words returned by `split`, possibly augmented by a number of `None` values.</span>
</span><span id="L-367"><a href="#L-367"><span class="linenos">367</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-368"><a href="#L-368"><span class="linenos">368</span></a> <span class="n">words</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">sep</span><span class="p">)</span>
</span><span id="L-369"><a href="#L-369"><span class="linenos">369</span></a> <span class="k">if</span> <span class="n">fill_from_start</span><span class="p">:</span>
</span><span id="L-370"><a href="#L-370"><span class="linenos">370</span></a> <span class="k">return</span> <span class="p">[</span><span class="kc">None</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">min_num_words</span> <span class="o">-</span> <span class="nb">len</span><span class="p">(</span><span class="n">words</span><span class="p">))</span> <span class="o">+</span> <span class="n">words</span>
</span><span id="L-371"><a href="#L-371"><span class="linenos">371</span></a> <span class="k">return</span> <span class="n">words</span> <span class="o">+</span> <span class="p">[</span><span class="kc">None</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">min_num_words</span> <span class="o">-</span> <span class="nb">len</span><span class="p">(</span><span class="n">words</span><span class="p">))</span>
</span><span id="L-372"><a href="#L-372"><span class="linenos">372</span></a>
</span><span id="L-373"><a href="#L-373"><span class="linenos">373</span></a>
</span><span id="L-374"><a href="#L-374"><span class="linenos">374</span></a><span class="k">def</span> <span class="nf">is_iterable</span><span class="p">(</span><span class="n">value</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
</span><span id="L-375"><a href="#L-375"><span class="linenos">375</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-376"><a href="#L-376"><span class="linenos">376</span></a><span class="sd"> Checks if the value is an iterable, excluding the types `str` and `bytes`.</span>
</span><span id="L-377"><a href="#L-377"><span class="linenos">377</span></a>
</span><span id="L-378"><a href="#L-378"><span class="linenos">378</span></a><span class="sd"> Examples:</span>
</span><span id="L-379"><a href="#L-379"><span class="linenos">379</span></a><span class="sd"> &gt;&gt;&gt; is_iterable([1,2])</span>
</span><span id="L-380"><a href="#L-380"><span class="linenos">380</span></a><span class="sd"> True</span>
</span><span id="L-381"><a href="#L-381"><span class="linenos">381</span></a><span class="sd"> &gt;&gt;&gt; is_iterable(&quot;test&quot;)</span>
</span><span id="L-382"><a href="#L-382"><span class="linenos">382</span></a><span class="sd"> False</span>
</span><span id="L-383"><a href="#L-383"><span class="linenos">383</span></a>
</span><span id="L-384"><a href="#L-384"><span class="linenos">384</span></a> <span class="k">return</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="s2">&quot;__iter__&quot;</span><span class="p">)</span> <span class="ow">and</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">,</span> <span class="n">Expression</span><span class="p">))</span>
</span><span id="L-385"><a href="#L-385"><span class="linenos">385</span></a>
</span><span id="L-384"><a href="#L-384"><span class="linenos">384</span></a><span class="sd"> Args:</span>
</span><span id="L-385"><a href="#L-385"><span class="linenos">385</span></a><span class="sd"> value: The value to check if it is an iterable.</span>
</span><span id="L-386"><a href="#L-386"><span class="linenos">386</span></a>
</span><span id="L-387"><a href="#L-387"><span class="linenos">387</span></a><span class="k">def</span> <span class="nf">flatten</span><span class="p">(</span><span class="n">values</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Iterable</span><span class="p">[</span><span class="n">t</span><span class="o">.</span><span class="n">Iterable</span><span class="p">[</span><span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">]</span> <span class="o">|</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Iterator</span><span class="p">[</span><span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">]:</span>
</span><span id="L-388"><a href="#L-388"><span class="linenos">388</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-389"><a href="#L-389"><span class="linenos">389</span></a><span class="sd"> Flattens an iterable that can contain both iterable and non-iterable elements. Objects of</span>
</span><span id="L-390"><a href="#L-390"><span class="linenos">390</span></a><span class="sd"> type `str` and `bytes` are not regarded as iterables.</span>
</span><span id="L-387"><a href="#L-387"><span class="linenos">387</span></a><span class="sd"> Returns:</span>
</span><span id="L-388"><a href="#L-388"><span class="linenos">388</span></a><span class="sd"> A `bool` value indicating if it is an iterable.</span>
</span><span id="L-389"><a href="#L-389"><span class="linenos">389</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-390"><a href="#L-390"><span class="linenos">390</span></a> <span class="kn">from</span> <span class="nn">sqlglot</span> <span class="kn">import</span> <span class="n">Expression</span>
</span><span id="L-391"><a href="#L-391"><span class="linenos">391</span></a>
</span><span id="L-392"><a href="#L-392"><span class="linenos">392</span></a><span class="sd"> Examples:</span>
</span><span id="L-393"><a href="#L-393"><span class="linenos">393</span></a><span class="sd"> &gt;&gt;&gt; list(flatten([[1, 2], 3, {4}, (5, &quot;bla&quot;)]))</span>
</span><span id="L-394"><a href="#L-394"><span class="linenos">394</span></a><span class="sd"> [1, 2, 3, 4, 5, &#39;bla&#39;]</span>
</span><span id="L-395"><a href="#L-395"><span class="linenos">395</span></a><span class="sd"> &gt;&gt;&gt; list(flatten([1, 2, 3]))</span>
</span><span id="L-396"><a href="#L-396"><span class="linenos">396</span></a><span class="sd"> [1, 2, 3]</span>
</span><span id="L-397"><a href="#L-397"><span class="linenos">397</span></a>
</span><span id="L-398"><a href="#L-398"><span class="linenos">398</span></a><span class="sd"> Args:</span>
</span><span id="L-399"><a href="#L-399"><span class="linenos">399</span></a><span class="sd"> values: The value to be flattened.</span>
</span><span id="L-400"><a href="#L-400"><span class="linenos">400</span></a>
</span><span id="L-401"><a href="#L-401"><span class="linenos">401</span></a><span class="sd"> Yields:</span>
</span><span id="L-402"><a href="#L-402"><span class="linenos">402</span></a><span class="sd"> Non-iterable elements in `values`.</span>
</span><span id="L-403"><a href="#L-403"><span class="linenos">403</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-404"><a href="#L-404"><span class="linenos">404</span></a> <span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">values</span><span class="p">:</span>
</span><span id="L-405"><a href="#L-405"><span class="linenos">405</span></a> <span class="k">if</span> <span class="n">is_iterable</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
</span><span id="L-406"><a href="#L-406"><span class="linenos">406</span></a> <span class="k">yield from</span> <span class="n">flatten</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
</span><span id="L-407"><a href="#L-407"><span class="linenos">407</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-408"><a href="#L-408"><span class="linenos">408</span></a> <span class="k">yield</span> <span class="n">value</span>
</span><span id="L-409"><a href="#L-409"><span class="linenos">409</span></a>
</span><span id="L-410"><a href="#L-410"><span class="linenos">410</span></a>
</span><span id="L-411"><a href="#L-411"><span class="linenos">411</span></a><span class="k">def</span> <span class="nf">dict_depth</span><span class="p">(</span><span class="n">d</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Dict</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span><span id="L-412"><a href="#L-412"><span class="linenos">412</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-413"><a href="#L-413"><span class="linenos">413</span></a><span class="sd"> Get the nesting depth of a dictionary.</span>
</span><span id="L-414"><a href="#L-414"><span class="linenos">414</span></a>
</span><span id="L-415"><a href="#L-415"><span class="linenos">415</span></a><span class="sd"> Example:</span>
</span><span id="L-416"><a href="#L-416"><span class="linenos">416</span></a><span class="sd"> &gt;&gt;&gt; dict_depth(None)</span>
</span><span id="L-417"><a href="#L-417"><span class="linenos">417</span></a><span class="sd"> 0</span>
</span><span id="L-418"><a href="#L-418"><span class="linenos">418</span></a><span class="sd"> &gt;&gt;&gt; dict_depth({})</span>
</span><span id="L-419"><a href="#L-419"><span class="linenos">419</span></a><span class="sd"> 1</span>
</span><span id="L-420"><a href="#L-420"><span class="linenos">420</span></a><span class="sd"> &gt;&gt;&gt; dict_depth({&quot;a&quot;: &quot;b&quot;})</span>
</span><span id="L-421"><a href="#L-421"><span class="linenos">421</span></a><span class="sd"> 1</span>
</span><span id="L-422"><a href="#L-422"><span class="linenos">422</span></a><span class="sd"> &gt;&gt;&gt; dict_depth({&quot;a&quot;: {}})</span>
</span><span id="L-423"><a href="#L-423"><span class="linenos">423</span></a><span class="sd"> 2</span>
</span><span id="L-424"><a href="#L-424"><span class="linenos">424</span></a><span class="sd"> &gt;&gt;&gt; dict_depth({&quot;a&quot;: {&quot;b&quot;: {}}})</span>
</span><span id="L-425"><a href="#L-425"><span class="linenos">425</span></a><span class="sd"> 3</span>
</span><span id="L-426"><a href="#L-426"><span class="linenos">426</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-427"><a href="#L-427"><span class="linenos">427</span></a> <span class="k">try</span><span class="p">:</span>
</span><span id="L-428"><a href="#L-428"><span class="linenos">428</span></a> <span class="k">return</span> <span class="mi">1</span> <span class="o">+</span> <span class="n">dict_depth</span><span class="p">(</span><span class="nb">next</span><span class="p">(</span><span class="nb">iter</span><span class="p">(</span><span class="n">d</span><span class="o">.</span><span class="n">values</span><span class="p">())))</span>
</span><span id="L-429"><a href="#L-429"><span class="linenos">429</span></a> <span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
</span><span id="L-430"><a href="#L-430"><span class="linenos">430</span></a> <span class="c1"># d doesn&#39;t have attribute &quot;values&quot;</span>
</span><span id="L-431"><a href="#L-431"><span class="linenos">431</span></a> <span class="k">return</span> <span class="mi">0</span>
</span><span id="L-432"><a href="#L-432"><span class="linenos">432</span></a> <span class="k">except</span> <span class="ne">StopIteration</span><span class="p">:</span>
</span><span id="L-433"><a href="#L-433"><span class="linenos">433</span></a> <span class="c1"># d.values() returns an empty sequence</span>
</span><span id="L-434"><a href="#L-434"><span class="linenos">434</span></a> <span class="k">return</span> <span class="mi">1</span>
</span><span id="L-435"><a href="#L-435"><span class="linenos">435</span></a>
</span><span id="L-436"><a href="#L-436"><span class="linenos">436</span></a>
</span><span id="L-437"><a href="#L-437"><span class="linenos">437</span></a><span class="k">def</span> <span class="nf">first</span><span class="p">(</span><span class="n">it</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Iterable</span><span class="p">[</span><span class="n">T</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">T</span><span class="p">:</span>
</span><span id="L-438"><a href="#L-438"><span class="linenos">438</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;Returns the first element from an iterable (useful for sets).&quot;&quot;&quot;</span>
</span><span id="L-439"><a href="#L-439"><span class="linenos">439</span></a> <span class="k">return</span> <span class="nb">next</span><span class="p">(</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">it</span><span class="p">)</span>
</span><span id="L-440"><a href="#L-440"><span class="linenos">440</span></a>
</span><span id="L-441"><a href="#L-441"><span class="linenos">441</span></a>
</span><span id="L-442"><a href="#L-442"><span class="linenos">442</span></a><span class="k">def</span> <span class="nf">merge_ranges</span><span class="p">(</span><span class="n">ranges</span><span class="p">:</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">Tuple</span><span class="p">[</span><span class="n">A</span><span class="p">,</span> <span class="n">A</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">Tuple</span><span class="p">[</span><span class="n">A</span><span class="p">,</span> <span class="n">A</span><span class="p">]]:</span>
</span><span id="L-443"><a href="#L-443"><span class="linenos">443</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-444"><a href="#L-444"><span class="linenos">444</span></a><span class="sd"> Merges a sequence of ranges, represented as tuples (low, high) whose values</span>
</span><span id="L-445"><a href="#L-445"><span class="linenos">445</span></a><span class="sd"> belong to some totally-ordered set.</span>
</span><span id="L-446"><a href="#L-446"><span class="linenos">446</span></a>
</span><span id="L-447"><a href="#L-447"><span class="linenos">447</span></a><span class="sd"> Example:</span>
</span><span id="L-448"><a href="#L-448"><span class="linenos">448</span></a><span class="sd"> &gt;&gt;&gt; merge_ranges([(1, 3), (2, 6)])</span>
</span><span id="L-449"><a href="#L-449"><span class="linenos">449</span></a><span class="sd"> [(1, 6)]</span>
</span><span id="L-450"><a href="#L-450"><span class="linenos">450</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-451"><a href="#L-451"><span class="linenos">451</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">ranges</span><span class="p">:</span>
</span><span id="L-452"><a href="#L-452"><span class="linenos">452</span></a> <span class="k">return</span> <span class="p">[]</span>
</span><span id="L-453"><a href="#L-453"><span class="linenos">453</span></a>
</span><span id="L-454"><a href="#L-454"><span class="linenos">454</span></a> <span class="n">ranges</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">ranges</span><span class="p">)</span>
</span><span id="L-455"><a href="#L-455"><span class="linenos">455</span></a>
</span><span id="L-456"><a href="#L-456"><span class="linenos">456</span></a> <span class="n">merged</span> <span class="o">=</span> <span class="p">[</span><span class="n">ranges</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span>
</span><span id="L-457"><a href="#L-457"><span class="linenos">457</span></a>
</span><span id="L-458"><a href="#L-458"><span class="linenos">458</span></a> <span class="k">for</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="ow">in</span> <span class="n">ranges</span><span class="p">[</span><span class="mi">1</span><span class="p">:]:</span>
</span><span id="L-459"><a href="#L-459"><span class="linenos">459</span></a> <span class="n">last_start</span><span class="p">,</span> <span class="n">last_end</span> <span class="o">=</span> <span class="n">merged</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
</span><span id="L-460"><a href="#L-460"><span class="linenos">460</span></a>
</span><span id="L-461"><a href="#L-461"><span class="linenos">461</span></a> <span class="k">if</span> <span class="n">start</span> <span class="o">&lt;=</span> <span class="n">last_end</span><span class="p">:</span>
</span><span id="L-462"><a href="#L-462"><span class="linenos">462</span></a> <span class="n">merged</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">last_start</span><span class="p">,</span> <span class="nb">max</span><span class="p">(</span><span class="n">last_end</span><span class="p">,</span> <span class="n">end</span><span class="p">))</span>
</span><span id="L-463"><a href="#L-463"><span class="linenos">463</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-464"><a href="#L-464"><span class="linenos">464</span></a> <span class="n">merged</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">))</span>
</span><span id="L-392"><a href="#L-392"><span class="linenos">392</span></a> <span class="k">return</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="s2">&quot;__iter__&quot;</span><span class="p">)</span> <span class="ow">and</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">,</span> <span class="n">Expression</span><span class="p">))</span>
</span><span id="L-393"><a href="#L-393"><span class="linenos">393</span></a>
</span><span id="L-394"><a href="#L-394"><span class="linenos">394</span></a>
</span><span id="L-395"><a href="#L-395"><span class="linenos">395</span></a><span class="k">def</span> <span class="nf">flatten</span><span class="p">(</span><span class="n">values</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Iterable</span><span class="p">[</span><span class="n">t</span><span class="o">.</span><span class="n">Iterable</span><span class="p">[</span><span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">]</span> <span class="o">|</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Iterator</span><span class="p">[</span><span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">]:</span>
</span><span id="L-396"><a href="#L-396"><span class="linenos">396</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-397"><a href="#L-397"><span class="linenos">397</span></a><span class="sd"> Flattens an iterable that can contain both iterable and non-iterable elements. Objects of</span>
</span><span id="L-398"><a href="#L-398"><span class="linenos">398</span></a><span class="sd"> type `str` and `bytes` are not regarded as iterables.</span>
</span><span id="L-399"><a href="#L-399"><span class="linenos">399</span></a>
</span><span id="L-400"><a href="#L-400"><span class="linenos">400</span></a><span class="sd"> Examples:</span>
</span><span id="L-401"><a href="#L-401"><span class="linenos">401</span></a><span class="sd"> &gt;&gt;&gt; list(flatten([[1, 2], 3, {4}, (5, &quot;bla&quot;)]))</span>
</span><span id="L-402"><a href="#L-402"><span class="linenos">402</span></a><span class="sd"> [1, 2, 3, 4, 5, &#39;bla&#39;]</span>
</span><span id="L-403"><a href="#L-403"><span class="linenos">403</span></a><span class="sd"> &gt;&gt;&gt; list(flatten([1, 2, 3]))</span>
</span><span id="L-404"><a href="#L-404"><span class="linenos">404</span></a><span class="sd"> [1, 2, 3]</span>
</span><span id="L-405"><a href="#L-405"><span class="linenos">405</span></a>
</span><span id="L-406"><a href="#L-406"><span class="linenos">406</span></a><span class="sd"> Args:</span>
</span><span id="L-407"><a href="#L-407"><span class="linenos">407</span></a><span class="sd"> values: The value to be flattened.</span>
</span><span id="L-408"><a href="#L-408"><span class="linenos">408</span></a>
</span><span id="L-409"><a href="#L-409"><span class="linenos">409</span></a><span class="sd"> Yields:</span>
</span><span id="L-410"><a href="#L-410"><span class="linenos">410</span></a><span class="sd"> Non-iterable elements in `values`.</span>
</span><span id="L-411"><a href="#L-411"><span class="linenos">411</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-412"><a href="#L-412"><span class="linenos">412</span></a> <span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">values</span><span class="p">:</span>
</span><span id="L-413"><a href="#L-413"><span class="linenos">413</span></a> <span class="k">if</span> <span class="n">is_iterable</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
</span><span id="L-414"><a href="#L-414"><span class="linenos">414</span></a> <span class="k">yield from</span> <span class="n">flatten</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
</span><span id="L-415"><a href="#L-415"><span class="linenos">415</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-416"><a href="#L-416"><span class="linenos">416</span></a> <span class="k">yield</span> <span class="n">value</span>
</span><span id="L-417"><a href="#L-417"><span class="linenos">417</span></a>
</span><span id="L-418"><a href="#L-418"><span class="linenos">418</span></a>
</span><span id="L-419"><a href="#L-419"><span class="linenos">419</span></a><span class="k">def</span> <span class="nf">dict_depth</span><span class="p">(</span><span class="n">d</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Dict</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span><span id="L-420"><a href="#L-420"><span class="linenos">420</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-421"><a href="#L-421"><span class="linenos">421</span></a><span class="sd"> Get the nesting depth of a dictionary.</span>
</span><span id="L-422"><a href="#L-422"><span class="linenos">422</span></a>
</span><span id="L-423"><a href="#L-423"><span class="linenos">423</span></a><span class="sd"> Example:</span>
</span><span id="L-424"><a href="#L-424"><span class="linenos">424</span></a><span class="sd"> &gt;&gt;&gt; dict_depth(None)</span>
</span><span id="L-425"><a href="#L-425"><span class="linenos">425</span></a><span class="sd"> 0</span>
</span><span id="L-426"><a href="#L-426"><span class="linenos">426</span></a><span class="sd"> &gt;&gt;&gt; dict_depth({})</span>
</span><span id="L-427"><a href="#L-427"><span class="linenos">427</span></a><span class="sd"> 1</span>
</span><span id="L-428"><a href="#L-428"><span class="linenos">428</span></a><span class="sd"> &gt;&gt;&gt; dict_depth({&quot;a&quot;: &quot;b&quot;})</span>
</span><span id="L-429"><a href="#L-429"><span class="linenos">429</span></a><span class="sd"> 1</span>
</span><span id="L-430"><a href="#L-430"><span class="linenos">430</span></a><span class="sd"> &gt;&gt;&gt; dict_depth({&quot;a&quot;: {}})</span>
</span><span id="L-431"><a href="#L-431"><span class="linenos">431</span></a><span class="sd"> 2</span>
</span><span id="L-432"><a href="#L-432"><span class="linenos">432</span></a><span class="sd"> &gt;&gt;&gt; dict_depth({&quot;a&quot;: {&quot;b&quot;: {}}})</span>
</span><span id="L-433"><a href="#L-433"><span class="linenos">433</span></a><span class="sd"> 3</span>
</span><span id="L-434"><a href="#L-434"><span class="linenos">434</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-435"><a href="#L-435"><span class="linenos">435</span></a> <span class="k">try</span><span class="p">:</span>
</span><span id="L-436"><a href="#L-436"><span class="linenos">436</span></a> <span class="k">return</span> <span class="mi">1</span> <span class="o">+</span> <span class="n">dict_depth</span><span class="p">(</span><span class="nb">next</span><span class="p">(</span><span class="nb">iter</span><span class="p">(</span><span class="n">d</span><span class="o">.</span><span class="n">values</span><span class="p">())))</span>
</span><span id="L-437"><a href="#L-437"><span class="linenos">437</span></a> <span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
</span><span id="L-438"><a href="#L-438"><span class="linenos">438</span></a> <span class="c1"># d doesn&#39;t have attribute &quot;values&quot;</span>
</span><span id="L-439"><a href="#L-439"><span class="linenos">439</span></a> <span class="k">return</span> <span class="mi">0</span>
</span><span id="L-440"><a href="#L-440"><span class="linenos">440</span></a> <span class="k">except</span> <span class="ne">StopIteration</span><span class="p">:</span>
</span><span id="L-441"><a href="#L-441"><span class="linenos">441</span></a> <span class="c1"># d.values() returns an empty sequence</span>
</span><span id="L-442"><a href="#L-442"><span class="linenos">442</span></a> <span class="k">return</span> <span class="mi">1</span>
</span><span id="L-443"><a href="#L-443"><span class="linenos">443</span></a>
</span><span id="L-444"><a href="#L-444"><span class="linenos">444</span></a>
</span><span id="L-445"><a href="#L-445"><span class="linenos">445</span></a><span class="k">def</span> <span class="nf">first</span><span class="p">(</span><span class="n">it</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Iterable</span><span class="p">[</span><span class="n">T</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">T</span><span class="p">:</span>
</span><span id="L-446"><a href="#L-446"><span class="linenos">446</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;Returns the first element from an iterable (useful for sets).&quot;&quot;&quot;</span>
</span><span id="L-447"><a href="#L-447"><span class="linenos">447</span></a> <span class="k">return</span> <span class="nb">next</span><span class="p">(</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">it</span><span class="p">)</span>
</span><span id="L-448"><a href="#L-448"><span class="linenos">448</span></a>
</span><span id="L-449"><a href="#L-449"><span class="linenos">449</span></a>
</span><span id="L-450"><a href="#L-450"><span class="linenos">450</span></a><span class="k">def</span> <span class="nf">merge_ranges</span><span class="p">(</span><span class="n">ranges</span><span class="p">:</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">Tuple</span><span class="p">[</span><span class="n">A</span><span class="p">,</span> <span class="n">A</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">Tuple</span><span class="p">[</span><span class="n">A</span><span class="p">,</span> <span class="n">A</span><span class="p">]]:</span>
</span><span id="L-451"><a href="#L-451"><span class="linenos">451</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-452"><a href="#L-452"><span class="linenos">452</span></a><span class="sd"> Merges a sequence of ranges, represented as tuples (low, high) whose values</span>
</span><span id="L-453"><a href="#L-453"><span class="linenos">453</span></a><span class="sd"> belong to some totally-ordered set.</span>
</span><span id="L-454"><a href="#L-454"><span class="linenos">454</span></a>
</span><span id="L-455"><a href="#L-455"><span class="linenos">455</span></a><span class="sd"> Example:</span>
</span><span id="L-456"><a href="#L-456"><span class="linenos">456</span></a><span class="sd"> &gt;&gt;&gt; merge_ranges([(1, 3), (2, 6)])</span>
</span><span id="L-457"><a href="#L-457"><span class="linenos">457</span></a><span class="sd"> [(1, 6)]</span>
</span><span id="L-458"><a href="#L-458"><span class="linenos">458</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-459"><a href="#L-459"><span class="linenos">459</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">ranges</span><span class="p">:</span>
</span><span id="L-460"><a href="#L-460"><span class="linenos">460</span></a> <span class="k">return</span> <span class="p">[]</span>
</span><span id="L-461"><a href="#L-461"><span class="linenos">461</span></a>
</span><span id="L-462"><a href="#L-462"><span class="linenos">462</span></a> <span class="n">ranges</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">ranges</span><span class="p">)</span>
</span><span id="L-463"><a href="#L-463"><span class="linenos">463</span></a>
</span><span id="L-464"><a href="#L-464"><span class="linenos">464</span></a> <span class="n">merged</span> <span class="o">=</span> <span class="p">[</span><span class="n">ranges</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span>
</span><span id="L-465"><a href="#L-465"><span class="linenos">465</span></a>
</span><span id="L-466"><a href="#L-466"><span class="linenos">466</span></a> <span class="k">return</span> <span class="n">merged</span>
</span><span id="L-467"><a href="#L-467"><span class="linenos">467</span></a>
</span><span id="L-466"><a href="#L-466"><span class="linenos">466</span></a> <span class="k">for</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="ow">in</span> <span class="n">ranges</span><span class="p">[</span><span class="mi">1</span><span class="p">:]:</span>
</span><span id="L-467"><a href="#L-467"><span class="linenos">467</span></a> <span class="n">last_start</span><span class="p">,</span> <span class="n">last_end</span> <span class="o">=</span> <span class="n">merged</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
</span><span id="L-468"><a href="#L-468"><span class="linenos">468</span></a>
</span><span id="L-469"><a href="#L-469"><span class="linenos">469</span></a><span class="k">def</span> <span class="nf">is_iso_date</span><span class="p">(</span><span class="n">text</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
</span><span id="L-470"><a href="#L-470"><span class="linenos">470</span></a> <span class="k">try</span><span class="p">:</span>
</span><span id="L-471"><a href="#L-471"><span class="linenos">471</span></a> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">fromisoformat</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
</span><span id="L-472"><a href="#L-472"><span class="linenos">472</span></a> <span class="k">return</span> <span class="kc">True</span>
</span><span id="L-473"><a href="#L-473"><span class="linenos">473</span></a> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
</span><span id="L-474"><a href="#L-474"><span class="linenos">474</span></a> <span class="k">return</span> <span class="kc">False</span>
</span><span id="L-469"><a href="#L-469"><span class="linenos">469</span></a> <span class="k">if</span> <span class="n">start</span> <span class="o">&lt;=</span> <span class="n">last_end</span><span class="p">:</span>
</span><span id="L-470"><a href="#L-470"><span class="linenos">470</span></a> <span class="n">merged</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">last_start</span><span class="p">,</span> <span class="nb">max</span><span class="p">(</span><span class="n">last_end</span><span class="p">,</span> <span class="n">end</span><span class="p">))</span>
</span><span id="L-471"><a href="#L-471"><span class="linenos">471</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-472"><a href="#L-472"><span class="linenos">472</span></a> <span class="n">merged</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">))</span>
</span><span id="L-473"><a href="#L-473"><span class="linenos">473</span></a>
</span><span id="L-474"><a href="#L-474"><span class="linenos">474</span></a> <span class="k">return</span> <span class="n">merged</span>
</span><span id="L-475"><a href="#L-475"><span class="linenos">475</span></a>
</span><span id="L-476"><a href="#L-476"><span class="linenos">476</span></a>
</span><span id="L-477"><a href="#L-477"><span class="linenos">477</span></a><span class="k">def</span> <span class="nf">is_iso_datetime</span><span class="p">(</span><span class="n">text</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
</span><span id="L-477"><a href="#L-477"><span class="linenos">477</span></a><span class="k">def</span> <span class="nf">is_iso_date</span><span class="p">(</span><span class="n">text</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
</span><span id="L-478"><a href="#L-478"><span class="linenos">478</span></a> <span class="k">try</span><span class="p">:</span>
</span><span id="L-479"><a href="#L-479"><span class="linenos">479</span></a> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">fromisoformat</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
</span><span id="L-479"><a href="#L-479"><span class="linenos">479</span></a> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">fromisoformat</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
</span><span id="L-480"><a href="#L-480"><span class="linenos">480</span></a> <span class="k">return</span> <span class="kc">True</span>
</span><span id="L-481"><a href="#L-481"><span class="linenos">481</span></a> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
</span><span id="L-482"><a href="#L-482"><span class="linenos">482</span></a> <span class="k">return</span> <span class="kc">False</span>
</span><span id="L-483"><a href="#L-483"><span class="linenos">483</span></a>
</span><span id="L-484"><a href="#L-484"><span class="linenos">484</span></a>
</span><span id="L-485"><a href="#L-485"><span class="linenos">485</span></a><span class="c1"># Interval units that operate on date components</span>
</span><span id="L-486"><a href="#L-486"><span class="linenos">486</span></a><span class="n">DATE_UNITS</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;day&quot;</span><span class="p">,</span> <span class="s2">&quot;week&quot;</span><span class="p">,</span> <span class="s2">&quot;month&quot;</span><span class="p">,</span> <span class="s2">&quot;quarter&quot;</span><span class="p">,</span> <span class="s2">&quot;year&quot;</span><span class="p">,</span> <span class="s2">&quot;year_month&quot;</span><span class="p">}</span>
</span><span id="L-487"><a href="#L-487"><span class="linenos">487</span></a>
</span><span id="L-488"><a href="#L-488"><span class="linenos">488</span></a>
</span><span id="L-489"><a href="#L-489"><span class="linenos">489</span></a><span class="k">def</span> <span class="nf">is_date_unit</span><span class="p">(</span><span class="n">expression</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">Expression</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
</span><span id="L-490"><a href="#L-490"><span class="linenos">490</span></a> <span class="k">return</span> <span class="n">expression</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">expression</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="ow">in</span> <span class="n">DATE_UNITS</span>
</span><span id="L-485"><a href="#L-485"><span class="linenos">485</span></a><span class="k">def</span> <span class="nf">is_iso_datetime</span><span class="p">(</span><span class="n">text</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
</span><span id="L-486"><a href="#L-486"><span class="linenos">486</span></a> <span class="k">try</span><span class="p">:</span>
</span><span id="L-487"><a href="#L-487"><span class="linenos">487</span></a> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">fromisoformat</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
</span><span id="L-488"><a href="#L-488"><span class="linenos">488</span></a> <span class="k">return</span> <span class="kc">True</span>
</span><span id="L-489"><a href="#L-489"><span class="linenos">489</span></a> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
</span><span id="L-490"><a href="#L-490"><span class="linenos">490</span></a> <span class="k">return</span> <span class="kc">False</span>
</span><span id="L-491"><a href="#L-491"><span class="linenos">491</span></a>
</span><span id="L-492"><a href="#L-492"><span class="linenos">492</span></a>
</span><span id="L-493"><a href="#L-493"><span class="linenos">493</span></a><span class="c1"># Interval units that operate on date components</span>
</span><span id="L-494"><a href="#L-494"><span class="linenos">494</span></a><span class="n">DATE_UNITS</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;day&quot;</span><span class="p">,</span> <span class="s2">&quot;week&quot;</span><span class="p">,</span> <span class="s2">&quot;month&quot;</span><span class="p">,</span> <span class="s2">&quot;quarter&quot;</span><span class="p">,</span> <span class="s2">&quot;year&quot;</span><span class="p">,</span> <span class="s2">&quot;year_month&quot;</span><span class="p">}</span>
</span><span id="L-495"><a href="#L-495"><span class="linenos">495</span></a>
</span><span id="L-496"><a href="#L-496"><span class="linenos">496</span></a>
</span><span id="L-497"><a href="#L-497"><span class="linenos">497</span></a><span class="k">def</span> <span class="nf">is_date_unit</span><span class="p">(</span><span class="n">expression</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">Expression</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
</span><span id="L-498"><a href="#L-498"><span class="linenos">498</span></a> <span class="k">return</span> <span class="n">expression</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">expression</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="ow">in</span> <span class="n">DATE_UNITS</span>
</span></pre></div>
@ -1157,7 +1168,7 @@ of the corresponding enum's identifier (e.g. FOO.value results in "FOO").</p>
</span><span id="tsort-237"><a href="#tsort-237"><span class="linenos">237</span></a>
</span><span id="tsort-238"><a href="#tsort-238"><span class="linenos">238</span></a> <span class="k">for</span> <span class="n">node</span><span class="p">,</span> <span class="n">deps</span> <span class="ow">in</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">dag</span><span class="o">.</span><span class="n">items</span><span class="p">()):</span>
</span><span id="tsort-239"><a href="#tsort-239"><span class="linenos">239</span></a> <span class="k">for</span> <span class="n">dep</span> <span class="ow">in</span> <span class="n">deps</span><span class="p">:</span>
</span><span id="tsort-240"><a href="#tsort-240"><span class="linenos">240</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">dep</span> <span class="ow">in</span> <span class="n">dag</span><span class="p">:</span>
</span><span id="tsort-240"><a href="#tsort-240"><span class="linenos">240</span></a> <span class="k">if</span> <span class="n">dep</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">dag</span><span class="p">:</span>
</span><span id="tsort-241"><a href="#tsort-241"><span class="linenos">241</span></a> <span class="n">dag</span><span class="p">[</span><span class="n">dep</span><span class="p">]</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
</span><span id="tsort-242"><a href="#tsort-242"><span class="linenos">242</span></a>
</span><span id="tsort-243"><a href="#tsort-243"><span class="linenos">243</span></a> <span class="k">while</span> <span class="n">dag</span><span class="p">:</span>
@ -1335,6 +1346,29 @@ of the corresponding enum's identifier (e.g. FOO.value results in "FOO").</p>
</div>
</section>
<section id="is_int">
<input id="is_int-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
<div class="attr function">
<span class="def">def</span>
<span class="name">is_int</span><span class="signature pdoc-code condensed">(<span class="param"><span class="n">text</span><span class="p">:</span> <span class="nb">str</span></span><span class="return-annotation">) -> <span class="nb">bool</span>:</span></span>
<label class="view-source-button" for="is_int-view-source"><span>View Source</span></label>
</div>
<a class="headerlink" href="#is_int"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="is_int-324"><a href="#is_int-324"><span class="linenos">324</span></a><span class="k">def</span> <span class="nf">is_int</span><span class="p">(</span><span class="n">text</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
</span><span id="is_int-325"><a href="#is_int-325"><span class="linenos">325</span></a> <span class="k">try</span><span class="p">:</span>
</span><span id="is_int-326"><a href="#is_int-326"><span class="linenos">326</span></a> <span class="nb">int</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
</span><span id="is_int-327"><a href="#is_int-327"><span class="linenos">327</span></a> <span class="k">return</span> <span class="kc">True</span>
</span><span id="is_int-328"><a href="#is_int-328"><span class="linenos">328</span></a> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
</span><span id="is_int-329"><a href="#is_int-329"><span class="linenos">329</span></a> <span class="k">return</span> <span class="kc">False</span>
</span></pre></div>
</section>
<section id="name_sequence">
<input id="name_sequence-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
@ -1347,10 +1381,10 @@ of the corresponding enum's identifier (e.g. FOO.value results in "FOO").</p>
</div>
<a class="headerlink" href="#name_sequence"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="name_sequence-324"><a href="#name_sequence-324"><span class="linenos">324</span></a><span class="k">def</span> <span class="nf">name_sequence</span><span class="p">(</span><span class="n">prefix</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Callable</span><span class="p">[[],</span> <span class="nb">str</span><span class="p">]:</span>
</span><span id="name_sequence-325"><a href="#name_sequence-325"><span class="linenos">325</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;Returns a name generator given a prefix (e.g. a0, a1, a2, ... if the prefix is &quot;a&quot;).&quot;&quot;&quot;</span>
</span><span id="name_sequence-326"><a href="#name_sequence-326"><span class="linenos">326</span></a> <span class="n">sequence</span> <span class="o">=</span> <span class="n">count</span><span class="p">()</span>
</span><span id="name_sequence-327"><a href="#name_sequence-327"><span class="linenos">327</span></a> <span class="k">return</span> <span class="k">lambda</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">prefix</span><span class="si">}{</span><span class="nb">next</span><span class="p">(</span><span class="n">sequence</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="name_sequence-332"><a href="#name_sequence-332"><span class="linenos">332</span></a><span class="k">def</span> <span class="nf">name_sequence</span><span class="p">(</span><span class="n">prefix</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Callable</span><span class="p">[[],</span> <span class="nb">str</span><span class="p">]:</span>
</span><span id="name_sequence-333"><a href="#name_sequence-333"><span class="linenos">333</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;Returns a name generator given a prefix (e.g. a0, a1, a2, ... if the prefix is &quot;a&quot;).&quot;&quot;&quot;</span>
</span><span id="name_sequence-334"><a href="#name_sequence-334"><span class="linenos">334</span></a> <span class="n">sequence</span> <span class="o">=</span> <span class="n">count</span><span class="p">()</span>
</span><span id="name_sequence-335"><a href="#name_sequence-335"><span class="linenos">335</span></a> <span class="k">return</span> <span class="k">lambda</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">prefix</span><span class="si">}{</span><span class="nb">next</span><span class="p">(</span><span class="n">sequence</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span>
</span></pre></div>
@ -1370,12 +1404,12 @@ of the corresponding enum's identifier (e.g. FOO.value results in "FOO").</p>
</div>
<a class="headerlink" href="#object_to_dict"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="object_to_dict-330"><a href="#object_to_dict-330"><span class="linenos">330</span></a><span class="k">def</span> <span class="nf">object_to_dict</span><span class="p">(</span><span class="n">obj</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Dict</span><span class="p">:</span>
</span><span id="object_to_dict-331"><a href="#object_to_dict-331"><span class="linenos">331</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;Returns a dictionary created from an object&#39;s attributes.&quot;&quot;&quot;</span>
</span><span id="object_to_dict-332"><a href="#object_to_dict-332"><span class="linenos">332</span></a> <span class="k">return</span> <span class="p">{</span>
</span><span id="object_to_dict-333"><a href="#object_to_dict-333"><span class="linenos">333</span></a> <span class="o">**</span><span class="p">{</span><span class="n">k</span><span class="p">:</span> <span class="n">v</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span> <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="s2">&quot;copy&quot;</span><span class="p">)</span> <span class="k">else</span> <span class="n">copy</span><span class="p">(</span><span class="n">v</span><span class="p">)</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">vars</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span><span class="o">.</span><span class="n">items</span><span class="p">()},</span>
</span><span id="object_to_dict-334"><a href="#object_to_dict-334"><span class="linenos">334</span></a> <span class="o">**</span><span class="n">kwargs</span><span class="p">,</span>
</span><span id="object_to_dict-335"><a href="#object_to_dict-335"><span class="linenos">335</span></a> <span class="p">}</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="object_to_dict-338"><a href="#object_to_dict-338"><span class="linenos">338</span></a><span class="k">def</span> <span class="nf">object_to_dict</span><span class="p">(</span><span class="n">obj</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Dict</span><span class="p">:</span>
</span><span id="object_to_dict-339"><a href="#object_to_dict-339"><span class="linenos">339</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;Returns a dictionary created from an object&#39;s attributes.&quot;&quot;&quot;</span>
</span><span id="object_to_dict-340"><a href="#object_to_dict-340"><span class="linenos">340</span></a> <span class="k">return</span> <span class="p">{</span>
</span><span id="object_to_dict-341"><a href="#object_to_dict-341"><span class="linenos">341</span></a> <span class="o">**</span><span class="p">{</span><span class="n">k</span><span class="p">:</span> <span class="n">v</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span> <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="s2">&quot;copy&quot;</span><span class="p">)</span> <span class="k">else</span> <span class="n">copy</span><span class="p">(</span><span class="n">v</span><span class="p">)</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">vars</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span><span class="o">.</span><span class="n">items</span><span class="p">()},</span>
</span><span id="object_to_dict-342"><a href="#object_to_dict-342"><span class="linenos">342</span></a> <span class="o">**</span><span class="n">kwargs</span><span class="p">,</span>
</span><span id="object_to_dict-343"><a href="#object_to_dict-343"><span class="linenos">343</span></a> <span class="p">}</span>
</span></pre></div>
@ -1395,33 +1429,33 @@ of the corresponding enum's identifier (e.g. FOO.value results in "FOO").</p>
</div>
<a class="headerlink" href="#split_num_words"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="split_num_words-338"><a href="#split_num_words-338"><span class="linenos">338</span></a><span class="k">def</span> <span class="nf">split_num_words</span><span class="p">(</span>
</span><span id="split_num_words-339"><a href="#split_num_words-339"><span class="linenos">339</span></a> <span class="n">value</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">sep</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">min_num_words</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">fill_from_start</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">True</span>
</span><span id="split_num_words-340"><a href="#split_num_words-340"><span class="linenos">340</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="nb">str</span><span class="p">]]:</span>
</span><span id="split_num_words-341"><a href="#split_num_words-341"><span class="linenos">341</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="split_num_words-342"><a href="#split_num_words-342"><span class="linenos">342</span></a><span class="sd"> Perform a split on a value and return N words as a result with `None` used for words that don&#39;t exist.</span>
</span><span id="split_num_words-343"><a href="#split_num_words-343"><span class="linenos">343</span></a>
</span><span id="split_num_words-344"><a href="#split_num_words-344"><span class="linenos">344</span></a><span class="sd"> Args:</span>
</span><span id="split_num_words-345"><a href="#split_num_words-345"><span class="linenos">345</span></a><span class="sd"> value: The value to be split.</span>
</span><span id="split_num_words-346"><a href="#split_num_words-346"><span class="linenos">346</span></a><span class="sd"> sep: The value to use to split on.</span>
</span><span id="split_num_words-347"><a href="#split_num_words-347"><span class="linenos">347</span></a><span class="sd"> min_num_words: The minimum number of words that are going to be in the result.</span>
</span><span id="split_num_words-348"><a href="#split_num_words-348"><span class="linenos">348</span></a><span class="sd"> fill_from_start: Indicates that if `None` values should be inserted at the start or end of the list.</span>
</span><span id="split_num_words-349"><a href="#split_num_words-349"><span class="linenos">349</span></a>
</span><span id="split_num_words-350"><a href="#split_num_words-350"><span class="linenos">350</span></a><span class="sd"> Examples:</span>
</span><span id="split_num_words-351"><a href="#split_num_words-351"><span class="linenos">351</span></a><span class="sd"> &gt;&gt;&gt; split_num_words(&quot;db.table&quot;, &quot;.&quot;, 3)</span>
</span><span id="split_num_words-352"><a href="#split_num_words-352"><span class="linenos">352</span></a><span class="sd"> [None, &#39;db&#39;, &#39;table&#39;]</span>
</span><span id="split_num_words-353"><a href="#split_num_words-353"><span class="linenos">353</span></a><span class="sd"> &gt;&gt;&gt; split_num_words(&quot;db.table&quot;, &quot;.&quot;, 3, fill_from_start=False)</span>
</span><span id="split_num_words-354"><a href="#split_num_words-354"><span class="linenos">354</span></a><span class="sd"> [&#39;db&#39;, &#39;table&#39;, None]</span>
</span><span id="split_num_words-355"><a href="#split_num_words-355"><span class="linenos">355</span></a><span class="sd"> &gt;&gt;&gt; split_num_words(&quot;db.table&quot;, &quot;.&quot;, 1)</span>
</span><span id="split_num_words-356"><a href="#split_num_words-356"><span class="linenos">356</span></a><span class="sd"> [&#39;db&#39;, &#39;table&#39;]</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="split_num_words-346"><a href="#split_num_words-346"><span class="linenos">346</span></a><span class="k">def</span> <span class="nf">split_num_words</span><span class="p">(</span>
</span><span id="split_num_words-347"><a href="#split_num_words-347"><span class="linenos">347</span></a> <span class="n">value</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">sep</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">min_num_words</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">fill_from_start</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">True</span>
</span><span id="split_num_words-348"><a href="#split_num_words-348"><span class="linenos">348</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="nb">str</span><span class="p">]]:</span>
</span><span id="split_num_words-349"><a href="#split_num_words-349"><span class="linenos">349</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="split_num_words-350"><a href="#split_num_words-350"><span class="linenos">350</span></a><span class="sd"> Perform a split on a value and return N words as a result with `None` used for words that don&#39;t exist.</span>
</span><span id="split_num_words-351"><a href="#split_num_words-351"><span class="linenos">351</span></a>
</span><span id="split_num_words-352"><a href="#split_num_words-352"><span class="linenos">352</span></a><span class="sd"> Args:</span>
</span><span id="split_num_words-353"><a href="#split_num_words-353"><span class="linenos">353</span></a><span class="sd"> value: The value to be split.</span>
</span><span id="split_num_words-354"><a href="#split_num_words-354"><span class="linenos">354</span></a><span class="sd"> sep: The value to use to split on.</span>
</span><span id="split_num_words-355"><a href="#split_num_words-355"><span class="linenos">355</span></a><span class="sd"> min_num_words: The minimum number of words that are going to be in the result.</span>
</span><span id="split_num_words-356"><a href="#split_num_words-356"><span class="linenos">356</span></a><span class="sd"> fill_from_start: Indicates that if `None` values should be inserted at the start or end of the list.</span>
</span><span id="split_num_words-357"><a href="#split_num_words-357"><span class="linenos">357</span></a>
</span><span id="split_num_words-358"><a href="#split_num_words-358"><span class="linenos">358</span></a><span class="sd"> Returns:</span>
</span><span id="split_num_words-359"><a href="#split_num_words-359"><span class="linenos">359</span></a><span class="sd"> The list of words returned by `split`, possibly augmented by a number of `None` values.</span>
</span><span id="split_num_words-360"><a href="#split_num_words-360"><span class="linenos">360</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="split_num_words-361"><a href="#split_num_words-361"><span class="linenos">361</span></a> <span class="n">words</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">sep</span><span class="p">)</span>
</span><span id="split_num_words-362"><a href="#split_num_words-362"><span class="linenos">362</span></a> <span class="k">if</span> <span class="n">fill_from_start</span><span class="p">:</span>
</span><span id="split_num_words-363"><a href="#split_num_words-363"><span class="linenos">363</span></a> <span class="k">return</span> <span class="p">[</span><span class="kc">None</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">min_num_words</span> <span class="o">-</span> <span class="nb">len</span><span class="p">(</span><span class="n">words</span><span class="p">))</span> <span class="o">+</span> <span class="n">words</span>
</span><span id="split_num_words-364"><a href="#split_num_words-364"><span class="linenos">364</span></a> <span class="k">return</span> <span class="n">words</span> <span class="o">+</span> <span class="p">[</span><span class="kc">None</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">min_num_words</span> <span class="o">-</span> <span class="nb">len</span><span class="p">(</span><span class="n">words</span><span class="p">))</span>
</span><span id="split_num_words-358"><a href="#split_num_words-358"><span class="linenos">358</span></a><span class="sd"> Examples:</span>
</span><span id="split_num_words-359"><a href="#split_num_words-359"><span class="linenos">359</span></a><span class="sd"> &gt;&gt;&gt; split_num_words(&quot;db.table&quot;, &quot;.&quot;, 3)</span>
</span><span id="split_num_words-360"><a href="#split_num_words-360"><span class="linenos">360</span></a><span class="sd"> [None, &#39;db&#39;, &#39;table&#39;]</span>
</span><span id="split_num_words-361"><a href="#split_num_words-361"><span class="linenos">361</span></a><span class="sd"> &gt;&gt;&gt; split_num_words(&quot;db.table&quot;, &quot;.&quot;, 3, fill_from_start=False)</span>
</span><span id="split_num_words-362"><a href="#split_num_words-362"><span class="linenos">362</span></a><span class="sd"> [&#39;db&#39;, &#39;table&#39;, None]</span>
</span><span id="split_num_words-363"><a href="#split_num_words-363"><span class="linenos">363</span></a><span class="sd"> &gt;&gt;&gt; split_num_words(&quot;db.table&quot;, &quot;.&quot;, 1)</span>
</span><span id="split_num_words-364"><a href="#split_num_words-364"><span class="linenos">364</span></a><span class="sd"> [&#39;db&#39;, &#39;table&#39;]</span>
</span><span id="split_num_words-365"><a href="#split_num_words-365"><span class="linenos">365</span></a>
</span><span id="split_num_words-366"><a href="#split_num_words-366"><span class="linenos">366</span></a><span class="sd"> Returns:</span>
</span><span id="split_num_words-367"><a href="#split_num_words-367"><span class="linenos">367</span></a><span class="sd"> The list of words returned by `split`, possibly augmented by a number of `None` values.</span>
</span><span id="split_num_words-368"><a href="#split_num_words-368"><span class="linenos">368</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="split_num_words-369"><a href="#split_num_words-369"><span class="linenos">369</span></a> <span class="n">words</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">sep</span><span class="p">)</span>
</span><span id="split_num_words-370"><a href="#split_num_words-370"><span class="linenos">370</span></a> <span class="k">if</span> <span class="n">fill_from_start</span><span class="p">:</span>
</span><span id="split_num_words-371"><a href="#split_num_words-371"><span class="linenos">371</span></a> <span class="k">return</span> <span class="p">[</span><span class="kc">None</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">min_num_words</span> <span class="o">-</span> <span class="nb">len</span><span class="p">(</span><span class="n">words</span><span class="p">))</span> <span class="o">+</span> <span class="n">words</span>
</span><span id="split_num_words-372"><a href="#split_num_words-372"><span class="linenos">372</span></a> <span class="k">return</span> <span class="n">words</span> <span class="o">+</span> <span class="p">[</span><span class="kc">None</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">min_num_words</span> <span class="o">-</span> <span class="nb">len</span><span class="p">(</span><span class="n">words</span><span class="p">))</span>
</span></pre></div>
@ -1470,25 +1504,25 @@ of the corresponding enum's identifier (e.g. FOO.value results in "FOO").</p>
</div>
<a class="headerlink" href="#is_iterable"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="is_iterable-367"><a href="#is_iterable-367"><span class="linenos">367</span></a><span class="k">def</span> <span class="nf">is_iterable</span><span class="p">(</span><span class="n">value</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
</span><span id="is_iterable-368"><a href="#is_iterable-368"><span class="linenos">368</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="is_iterable-369"><a href="#is_iterable-369"><span class="linenos">369</span></a><span class="sd"> Checks if the value is an iterable, excluding the types `str` and `bytes`.</span>
</span><span id="is_iterable-370"><a href="#is_iterable-370"><span class="linenos">370</span></a>
</span><span id="is_iterable-371"><a href="#is_iterable-371"><span class="linenos">371</span></a><span class="sd"> Examples:</span>
</span><span id="is_iterable-372"><a href="#is_iterable-372"><span class="linenos">372</span></a><span class="sd"> &gt;&gt;&gt; is_iterable([1,2])</span>
</span><span id="is_iterable-373"><a href="#is_iterable-373"><span class="linenos">373</span></a><span class="sd"> True</span>
</span><span id="is_iterable-374"><a href="#is_iterable-374"><span class="linenos">374</span></a><span class="sd"> &gt;&gt;&gt; is_iterable(&quot;test&quot;)</span>
</span><span id="is_iterable-375"><a href="#is_iterable-375"><span class="linenos">375</span></a><span class="sd"> False</span>
</span><span id="is_iterable-376"><a href="#is_iterable-376"><span class="linenos">376</span></a>
</span><span id="is_iterable-377"><a href="#is_iterable-377"><span class="linenos">377</span></a><span class="sd"> Args:</span>
</span><span id="is_iterable-378"><a href="#is_iterable-378"><span class="linenos">378</span></a><span class="sd"> value: The value to check if it is an iterable.</span>
</span><span id="is_iterable-379"><a href="#is_iterable-379"><span class="linenos">379</span></a>
</span><span id="is_iterable-380"><a href="#is_iterable-380"><span class="linenos">380</span></a><span class="sd"> Returns:</span>
</span><span id="is_iterable-381"><a href="#is_iterable-381"><span class="linenos">381</span></a><span class="sd"> A `bool` value indicating if it is an iterable.</span>
</span><span id="is_iterable-382"><a href="#is_iterable-382"><span class="linenos">382</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="is_iterable-383"><a href="#is_iterable-383"><span class="linenos">383</span></a> <span class="kn">from</span> <span class="nn">sqlglot</span> <span class="kn">import</span> <span class="n">Expression</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="is_iterable-375"><a href="#is_iterable-375"><span class="linenos">375</span></a><span class="k">def</span> <span class="nf">is_iterable</span><span class="p">(</span><span class="n">value</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
</span><span id="is_iterable-376"><a href="#is_iterable-376"><span class="linenos">376</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="is_iterable-377"><a href="#is_iterable-377"><span class="linenos">377</span></a><span class="sd"> Checks if the value is an iterable, excluding the types `str` and `bytes`.</span>
</span><span id="is_iterable-378"><a href="#is_iterable-378"><span class="linenos">378</span></a>
</span><span id="is_iterable-379"><a href="#is_iterable-379"><span class="linenos">379</span></a><span class="sd"> Examples:</span>
</span><span id="is_iterable-380"><a href="#is_iterable-380"><span class="linenos">380</span></a><span class="sd"> &gt;&gt;&gt; is_iterable([1,2])</span>
</span><span id="is_iterable-381"><a href="#is_iterable-381"><span class="linenos">381</span></a><span class="sd"> True</span>
</span><span id="is_iterable-382"><a href="#is_iterable-382"><span class="linenos">382</span></a><span class="sd"> &gt;&gt;&gt; is_iterable(&quot;test&quot;)</span>
</span><span id="is_iterable-383"><a href="#is_iterable-383"><span class="linenos">383</span></a><span class="sd"> False</span>
</span><span id="is_iterable-384"><a href="#is_iterable-384"><span class="linenos">384</span></a>
</span><span id="is_iterable-385"><a href="#is_iterable-385"><span class="linenos">385</span></a> <span class="k">return</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="s2">&quot;__iter__&quot;</span><span class="p">)</span> <span class="ow">and</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">,</span> <span class="n">Expression</span><span class="p">))</span>
</span><span id="is_iterable-385"><a href="#is_iterable-385"><span class="linenos">385</span></a><span class="sd"> Args:</span>
</span><span id="is_iterable-386"><a href="#is_iterable-386"><span class="linenos">386</span></a><span class="sd"> value: The value to check if it is an iterable.</span>
</span><span id="is_iterable-387"><a href="#is_iterable-387"><span class="linenos">387</span></a>
</span><span id="is_iterable-388"><a href="#is_iterable-388"><span class="linenos">388</span></a><span class="sd"> Returns:</span>
</span><span id="is_iterable-389"><a href="#is_iterable-389"><span class="linenos">389</span></a><span class="sd"> A `bool` value indicating if it is an iterable.</span>
</span><span id="is_iterable-390"><a href="#is_iterable-390"><span class="linenos">390</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="is_iterable-391"><a href="#is_iterable-391"><span class="linenos">391</span></a> <span class="kn">from</span> <span class="nn">sqlglot</span> <span class="kn">import</span> <span class="n">Expression</span>
</span><span id="is_iterable-392"><a href="#is_iterable-392"><span class="linenos">392</span></a>
</span><span id="is_iterable-393"><a href="#is_iterable-393"><span class="linenos">393</span></a> <span class="k">return</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="s2">&quot;__iter__&quot;</span><span class="p">)</span> <span class="ow">and</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">,</span> <span class="n">Expression</span><span class="p">))</span>
</span></pre></div>
@ -1532,28 +1566,28 @@ of the corresponding enum's identifier (e.g. FOO.value results in "FOO").</p>
</div>
<a class="headerlink" href="#flatten"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="flatten-388"><a href="#flatten-388"><span class="linenos">388</span></a><span class="k">def</span> <span class="nf">flatten</span><span class="p">(</span><span class="n">values</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Iterable</span><span class="p">[</span><span class="n">t</span><span class="o">.</span><span class="n">Iterable</span><span class="p">[</span><span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">]</span> <span class="o">|</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Iterator</span><span class="p">[</span><span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">]:</span>
</span><span id="flatten-389"><a href="#flatten-389"><span class="linenos">389</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="flatten-390"><a href="#flatten-390"><span class="linenos">390</span></a><span class="sd"> Flattens an iterable that can contain both iterable and non-iterable elements. Objects of</span>
</span><span id="flatten-391"><a href="#flatten-391"><span class="linenos">391</span></a><span class="sd"> type `str` and `bytes` are not regarded as iterables.</span>
</span><span id="flatten-392"><a href="#flatten-392"><span class="linenos">392</span></a>
</span><span id="flatten-393"><a href="#flatten-393"><span class="linenos">393</span></a><span class="sd"> Examples:</span>
</span><span id="flatten-394"><a href="#flatten-394"><span class="linenos">394</span></a><span class="sd"> &gt;&gt;&gt; list(flatten([[1, 2], 3, {4}, (5, &quot;bla&quot;)]))</span>
</span><span id="flatten-395"><a href="#flatten-395"><span class="linenos">395</span></a><span class="sd"> [1, 2, 3, 4, 5, &#39;bla&#39;]</span>
</span><span id="flatten-396"><a href="#flatten-396"><span class="linenos">396</span></a><span class="sd"> &gt;&gt;&gt; list(flatten([1, 2, 3]))</span>
</span><span id="flatten-397"><a href="#flatten-397"><span class="linenos">397</span></a><span class="sd"> [1, 2, 3]</span>
</span><span id="flatten-398"><a href="#flatten-398"><span class="linenos">398</span></a>
</span><span id="flatten-399"><a href="#flatten-399"><span class="linenos">399</span></a><span class="sd"> Args:</span>
</span><span id="flatten-400"><a href="#flatten-400"><span class="linenos">400</span></a><span class="sd"> values: The value to be flattened.</span>
</span><span id="flatten-401"><a href="#flatten-401"><span class="linenos">401</span></a>
</span><span id="flatten-402"><a href="#flatten-402"><span class="linenos">402</span></a><span class="sd"> Yields:</span>
</span><span id="flatten-403"><a href="#flatten-403"><span class="linenos">403</span></a><span class="sd"> Non-iterable elements in `values`.</span>
</span><span id="flatten-404"><a href="#flatten-404"><span class="linenos">404</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="flatten-405"><a href="#flatten-405"><span class="linenos">405</span></a> <span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">values</span><span class="p">:</span>
</span><span id="flatten-406"><a href="#flatten-406"><span class="linenos">406</span></a> <span class="k">if</span> <span class="n">is_iterable</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
</span><span id="flatten-407"><a href="#flatten-407"><span class="linenos">407</span></a> <span class="k">yield from</span> <span class="n">flatten</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
</span><span id="flatten-408"><a href="#flatten-408"><span class="linenos">408</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="flatten-409"><a href="#flatten-409"><span class="linenos">409</span></a> <span class="k">yield</span> <span class="n">value</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="flatten-396"><a href="#flatten-396"><span class="linenos">396</span></a><span class="k">def</span> <span class="nf">flatten</span><span class="p">(</span><span class="n">values</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Iterable</span><span class="p">[</span><span class="n">t</span><span class="o">.</span><span class="n">Iterable</span><span class="p">[</span><span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">]</span> <span class="o">|</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Iterator</span><span class="p">[</span><span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">]:</span>
</span><span id="flatten-397"><a href="#flatten-397"><span class="linenos">397</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="flatten-398"><a href="#flatten-398"><span class="linenos">398</span></a><span class="sd"> Flattens an iterable that can contain both iterable and non-iterable elements. Objects of</span>
</span><span id="flatten-399"><a href="#flatten-399"><span class="linenos">399</span></a><span class="sd"> type `str` and `bytes` are not regarded as iterables.</span>
</span><span id="flatten-400"><a href="#flatten-400"><span class="linenos">400</span></a>
</span><span id="flatten-401"><a href="#flatten-401"><span class="linenos">401</span></a><span class="sd"> Examples:</span>
</span><span id="flatten-402"><a href="#flatten-402"><span class="linenos">402</span></a><span class="sd"> &gt;&gt;&gt; list(flatten([[1, 2], 3, {4}, (5, &quot;bla&quot;)]))</span>
</span><span id="flatten-403"><a href="#flatten-403"><span class="linenos">403</span></a><span class="sd"> [1, 2, 3, 4, 5, &#39;bla&#39;]</span>
</span><span id="flatten-404"><a href="#flatten-404"><span class="linenos">404</span></a><span class="sd"> &gt;&gt;&gt; list(flatten([1, 2, 3]))</span>
</span><span id="flatten-405"><a href="#flatten-405"><span class="linenos">405</span></a><span class="sd"> [1, 2, 3]</span>
</span><span id="flatten-406"><a href="#flatten-406"><span class="linenos">406</span></a>
</span><span id="flatten-407"><a href="#flatten-407"><span class="linenos">407</span></a><span class="sd"> Args:</span>
</span><span id="flatten-408"><a href="#flatten-408"><span class="linenos">408</span></a><span class="sd"> values: The value to be flattened.</span>
</span><span id="flatten-409"><a href="#flatten-409"><span class="linenos">409</span></a>
</span><span id="flatten-410"><a href="#flatten-410"><span class="linenos">410</span></a><span class="sd"> Yields:</span>
</span><span id="flatten-411"><a href="#flatten-411"><span class="linenos">411</span></a><span class="sd"> Non-iterable elements in `values`.</span>
</span><span id="flatten-412"><a href="#flatten-412"><span class="linenos">412</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="flatten-413"><a href="#flatten-413"><span class="linenos">413</span></a> <span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">values</span><span class="p">:</span>
</span><span id="flatten-414"><a href="#flatten-414"><span class="linenos">414</span></a> <span class="k">if</span> <span class="n">is_iterable</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
</span><span id="flatten-415"><a href="#flatten-415"><span class="linenos">415</span></a> <span class="k">yield from</span> <span class="n">flatten</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
</span><span id="flatten-416"><a href="#flatten-416"><span class="linenos">416</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="flatten-417"><a href="#flatten-417"><span class="linenos">417</span></a> <span class="k">yield</span> <span class="n">value</span>
</span></pre></div>
@ -1598,30 +1632,30 @@ type <code>str</code> and <code>bytes</code> are not regarded as iterables.</p>
</div>
<a class="headerlink" href="#dict_depth"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="dict_depth-412"><a href="#dict_depth-412"><span class="linenos">412</span></a><span class="k">def</span> <span class="nf">dict_depth</span><span class="p">(</span><span class="n">d</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Dict</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span><span id="dict_depth-413"><a href="#dict_depth-413"><span class="linenos">413</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="dict_depth-414"><a href="#dict_depth-414"><span class="linenos">414</span></a><span class="sd"> Get the nesting depth of a dictionary.</span>
</span><span id="dict_depth-415"><a href="#dict_depth-415"><span class="linenos">415</span></a>
</span><span id="dict_depth-416"><a href="#dict_depth-416"><span class="linenos">416</span></a><span class="sd"> Example:</span>
</span><span id="dict_depth-417"><a href="#dict_depth-417"><span class="linenos">417</span></a><span class="sd"> &gt;&gt;&gt; dict_depth(None)</span>
</span><span id="dict_depth-418"><a href="#dict_depth-418"><span class="linenos">418</span></a><span class="sd"> 0</span>
</span><span id="dict_depth-419"><a href="#dict_depth-419"><span class="linenos">419</span></a><span class="sd"> &gt;&gt;&gt; dict_depth({})</span>
</span><span id="dict_depth-420"><a href="#dict_depth-420"><span class="linenos">420</span></a><span class="sd"> 1</span>
</span><span id="dict_depth-421"><a href="#dict_depth-421"><span class="linenos">421</span></a><span class="sd"> &gt;&gt;&gt; dict_depth({&quot;a&quot;: &quot;b&quot;})</span>
</span><span id="dict_depth-422"><a href="#dict_depth-422"><span class="linenos">422</span></a><span class="sd"> 1</span>
</span><span id="dict_depth-423"><a href="#dict_depth-423"><span class="linenos">423</span></a><span class="sd"> &gt;&gt;&gt; dict_depth({&quot;a&quot;: {}})</span>
</span><span id="dict_depth-424"><a href="#dict_depth-424"><span class="linenos">424</span></a><span class="sd"> 2</span>
</span><span id="dict_depth-425"><a href="#dict_depth-425"><span class="linenos">425</span></a><span class="sd"> &gt;&gt;&gt; dict_depth({&quot;a&quot;: {&quot;b&quot;: {}}})</span>
</span><span id="dict_depth-426"><a href="#dict_depth-426"><span class="linenos">426</span></a><span class="sd"> 3</span>
</span><span id="dict_depth-427"><a href="#dict_depth-427"><span class="linenos">427</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="dict_depth-428"><a href="#dict_depth-428"><span class="linenos">428</span></a> <span class="k">try</span><span class="p">:</span>
</span><span id="dict_depth-429"><a href="#dict_depth-429"><span class="linenos">429</span></a> <span class="k">return</span> <span class="mi">1</span> <span class="o">+</span> <span class="n">dict_depth</span><span class="p">(</span><span class="nb">next</span><span class="p">(</span><span class="nb">iter</span><span class="p">(</span><span class="n">d</span><span class="o">.</span><span class="n">values</span><span class="p">())))</span>
</span><span id="dict_depth-430"><a href="#dict_depth-430"><span class="linenos">430</span></a> <span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
</span><span id="dict_depth-431"><a href="#dict_depth-431"><span class="linenos">431</span></a> <span class="c1"># d doesn&#39;t have attribute &quot;values&quot;</span>
</span><span id="dict_depth-432"><a href="#dict_depth-432"><span class="linenos">432</span></a> <span class="k">return</span> <span class="mi">0</span>
</span><span id="dict_depth-433"><a href="#dict_depth-433"><span class="linenos">433</span></a> <span class="k">except</span> <span class="ne">StopIteration</span><span class="p">:</span>
</span><span id="dict_depth-434"><a href="#dict_depth-434"><span class="linenos">434</span></a> <span class="c1"># d.values() returns an empty sequence</span>
</span><span id="dict_depth-435"><a href="#dict_depth-435"><span class="linenos">435</span></a> <span class="k">return</span> <span class="mi">1</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="dict_depth-420"><a href="#dict_depth-420"><span class="linenos">420</span></a><span class="k">def</span> <span class="nf">dict_depth</span><span class="p">(</span><span class="n">d</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Dict</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span><span id="dict_depth-421"><a href="#dict_depth-421"><span class="linenos">421</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="dict_depth-422"><a href="#dict_depth-422"><span class="linenos">422</span></a><span class="sd"> Get the nesting depth of a dictionary.</span>
</span><span id="dict_depth-423"><a href="#dict_depth-423"><span class="linenos">423</span></a>
</span><span id="dict_depth-424"><a href="#dict_depth-424"><span class="linenos">424</span></a><span class="sd"> Example:</span>
</span><span id="dict_depth-425"><a href="#dict_depth-425"><span class="linenos">425</span></a><span class="sd"> &gt;&gt;&gt; dict_depth(None)</span>
</span><span id="dict_depth-426"><a href="#dict_depth-426"><span class="linenos">426</span></a><span class="sd"> 0</span>
</span><span id="dict_depth-427"><a href="#dict_depth-427"><span class="linenos">427</span></a><span class="sd"> &gt;&gt;&gt; dict_depth({})</span>
</span><span id="dict_depth-428"><a href="#dict_depth-428"><span class="linenos">428</span></a><span class="sd"> 1</span>
</span><span id="dict_depth-429"><a href="#dict_depth-429"><span class="linenos">429</span></a><span class="sd"> &gt;&gt;&gt; dict_depth({&quot;a&quot;: &quot;b&quot;})</span>
</span><span id="dict_depth-430"><a href="#dict_depth-430"><span class="linenos">430</span></a><span class="sd"> 1</span>
</span><span id="dict_depth-431"><a href="#dict_depth-431"><span class="linenos">431</span></a><span class="sd"> &gt;&gt;&gt; dict_depth({&quot;a&quot;: {}})</span>
</span><span id="dict_depth-432"><a href="#dict_depth-432"><span class="linenos">432</span></a><span class="sd"> 2</span>
</span><span id="dict_depth-433"><a href="#dict_depth-433"><span class="linenos">433</span></a><span class="sd"> &gt;&gt;&gt; dict_depth({&quot;a&quot;: {&quot;b&quot;: {}}})</span>
</span><span id="dict_depth-434"><a href="#dict_depth-434"><span class="linenos">434</span></a><span class="sd"> 3</span>
</span><span id="dict_depth-435"><a href="#dict_depth-435"><span class="linenos">435</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="dict_depth-436"><a href="#dict_depth-436"><span class="linenos">436</span></a> <span class="k">try</span><span class="p">:</span>
</span><span id="dict_depth-437"><a href="#dict_depth-437"><span class="linenos">437</span></a> <span class="k">return</span> <span class="mi">1</span> <span class="o">+</span> <span class="n">dict_depth</span><span class="p">(</span><span class="nb">next</span><span class="p">(</span><span class="nb">iter</span><span class="p">(</span><span class="n">d</span><span class="o">.</span><span class="n">values</span><span class="p">())))</span>
</span><span id="dict_depth-438"><a href="#dict_depth-438"><span class="linenos">438</span></a> <span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
</span><span id="dict_depth-439"><a href="#dict_depth-439"><span class="linenos">439</span></a> <span class="c1"># d doesn&#39;t have attribute &quot;values&quot;</span>
</span><span id="dict_depth-440"><a href="#dict_depth-440"><span class="linenos">440</span></a> <span class="k">return</span> <span class="mi">0</span>
</span><span id="dict_depth-441"><a href="#dict_depth-441"><span class="linenos">441</span></a> <span class="k">except</span> <span class="ne">StopIteration</span><span class="p">:</span>
</span><span id="dict_depth-442"><a href="#dict_depth-442"><span class="linenos">442</span></a> <span class="c1"># d.values() returns an empty sequence</span>
</span><span id="dict_depth-443"><a href="#dict_depth-443"><span class="linenos">443</span></a> <span class="k">return</span> <span class="mi">1</span>
</span></pre></div>
@ -1659,9 +1693,9 @@ type <code>str</code> and <code>bytes</code> are not regarded as iterables.</p>
</div>
<a class="headerlink" href="#first"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="first-438"><a href="#first-438"><span class="linenos">438</span></a><span class="k">def</span> <span class="nf">first</span><span class="p">(</span><span class="n">it</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Iterable</span><span class="p">[</span><span class="n">T</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">T</span><span class="p">:</span>
</span><span id="first-439"><a href="#first-439"><span class="linenos">439</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;Returns the first element from an iterable (useful for sets).&quot;&quot;&quot;</span>
</span><span id="first-440"><a href="#first-440"><span class="linenos">440</span></a> <span class="k">return</span> <span class="nb">next</span><span class="p">(</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">it</span><span class="p">)</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="first-446"><a href="#first-446"><span class="linenos">446</span></a><span class="k">def</span> <span class="nf">first</span><span class="p">(</span><span class="n">it</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Iterable</span><span class="p">[</span><span class="n">T</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">T</span><span class="p">:</span>
</span><span id="first-447"><a href="#first-447"><span class="linenos">447</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;Returns the first element from an iterable (useful for sets).&quot;&quot;&quot;</span>
</span><span id="first-448"><a href="#first-448"><span class="linenos">448</span></a> <span class="k">return</span> <span class="nb">next</span><span class="p">(</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">it</span><span class="p">)</span>
</span></pre></div>
@ -1681,31 +1715,31 @@ type <code>str</code> and <code>bytes</code> are not regarded as iterables.</p>
</div>
<a class="headerlink" href="#merge_ranges"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="merge_ranges-443"><a href="#merge_ranges-443"><span class="linenos">443</span></a><span class="k">def</span> <span class="nf">merge_ranges</span><span class="p">(</span><span class="n">ranges</span><span class="p">:</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">Tuple</span><span class="p">[</span><span class="n">A</span><span class="p">,</span> <span class="n">A</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">Tuple</span><span class="p">[</span><span class="n">A</span><span class="p">,</span> <span class="n">A</span><span class="p">]]:</span>
</span><span id="merge_ranges-444"><a href="#merge_ranges-444"><span class="linenos">444</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="merge_ranges-445"><a href="#merge_ranges-445"><span class="linenos">445</span></a><span class="sd"> Merges a sequence of ranges, represented as tuples (low, high) whose values</span>
</span><span id="merge_ranges-446"><a href="#merge_ranges-446"><span class="linenos">446</span></a><span class="sd"> belong to some totally-ordered set.</span>
</span><span id="merge_ranges-447"><a href="#merge_ranges-447"><span class="linenos">447</span></a>
</span><span id="merge_ranges-448"><a href="#merge_ranges-448"><span class="linenos">448</span></a><span class="sd"> Example:</span>
</span><span id="merge_ranges-449"><a href="#merge_ranges-449"><span class="linenos">449</span></a><span class="sd"> &gt;&gt;&gt; merge_ranges([(1, 3), (2, 6)])</span>
</span><span id="merge_ranges-450"><a href="#merge_ranges-450"><span class="linenos">450</span></a><span class="sd"> [(1, 6)]</span>
</span><span id="merge_ranges-451"><a href="#merge_ranges-451"><span class="linenos">451</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="merge_ranges-452"><a href="#merge_ranges-452"><span class="linenos">452</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">ranges</span><span class="p">:</span>
</span><span id="merge_ranges-453"><a href="#merge_ranges-453"><span class="linenos">453</span></a> <span class="k">return</span> <span class="p">[]</span>
</span><span id="merge_ranges-454"><a href="#merge_ranges-454"><span class="linenos">454</span></a>
</span><span id="merge_ranges-455"><a href="#merge_ranges-455"><span class="linenos">455</span></a> <span class="n">ranges</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">ranges</span><span class="p">)</span>
</span><span id="merge_ranges-456"><a href="#merge_ranges-456"><span class="linenos">456</span></a>
</span><span id="merge_ranges-457"><a href="#merge_ranges-457"><span class="linenos">457</span></a> <span class="n">merged</span> <span class="o">=</span> <span class="p">[</span><span class="n">ranges</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span>
</span><span id="merge_ranges-458"><a href="#merge_ranges-458"><span class="linenos">458</span></a>
</span><span id="merge_ranges-459"><a href="#merge_ranges-459"><span class="linenos">459</span></a> <span class="k">for</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="ow">in</span> <span class="n">ranges</span><span class="p">[</span><span class="mi">1</span><span class="p">:]:</span>
</span><span id="merge_ranges-460"><a href="#merge_ranges-460"><span class="linenos">460</span></a> <span class="n">last_start</span><span class="p">,</span> <span class="n">last_end</span> <span class="o">=</span> <span class="n">merged</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
</span><span id="merge_ranges-461"><a href="#merge_ranges-461"><span class="linenos">461</span></a>
</span><span id="merge_ranges-462"><a href="#merge_ranges-462"><span class="linenos">462</span></a> <span class="k">if</span> <span class="n">start</span> <span class="o">&lt;=</span> <span class="n">last_end</span><span class="p">:</span>
</span><span id="merge_ranges-463"><a href="#merge_ranges-463"><span class="linenos">463</span></a> <span class="n">merged</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">last_start</span><span class="p">,</span> <span class="nb">max</span><span class="p">(</span><span class="n">last_end</span><span class="p">,</span> <span class="n">end</span><span class="p">))</span>
</span><span id="merge_ranges-464"><a href="#merge_ranges-464"><span class="linenos">464</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="merge_ranges-465"><a href="#merge_ranges-465"><span class="linenos">465</span></a> <span class="n">merged</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">))</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="merge_ranges-451"><a href="#merge_ranges-451"><span class="linenos">451</span></a><span class="k">def</span> <span class="nf">merge_ranges</span><span class="p">(</span><span class="n">ranges</span><span class="p">:</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">Tuple</span><span class="p">[</span><span class="n">A</span><span class="p">,</span> <span class="n">A</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">Tuple</span><span class="p">[</span><span class="n">A</span><span class="p">,</span> <span class="n">A</span><span class="p">]]:</span>
</span><span id="merge_ranges-452"><a href="#merge_ranges-452"><span class="linenos">452</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="merge_ranges-453"><a href="#merge_ranges-453"><span class="linenos">453</span></a><span class="sd"> Merges a sequence of ranges, represented as tuples (low, high) whose values</span>
</span><span id="merge_ranges-454"><a href="#merge_ranges-454"><span class="linenos">454</span></a><span class="sd"> belong to some totally-ordered set.</span>
</span><span id="merge_ranges-455"><a href="#merge_ranges-455"><span class="linenos">455</span></a>
</span><span id="merge_ranges-456"><a href="#merge_ranges-456"><span class="linenos">456</span></a><span class="sd"> Example:</span>
</span><span id="merge_ranges-457"><a href="#merge_ranges-457"><span class="linenos">457</span></a><span class="sd"> &gt;&gt;&gt; merge_ranges([(1, 3), (2, 6)])</span>
</span><span id="merge_ranges-458"><a href="#merge_ranges-458"><span class="linenos">458</span></a><span class="sd"> [(1, 6)]</span>
</span><span id="merge_ranges-459"><a href="#merge_ranges-459"><span class="linenos">459</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="merge_ranges-460"><a href="#merge_ranges-460"><span class="linenos">460</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">ranges</span><span class="p">:</span>
</span><span id="merge_ranges-461"><a href="#merge_ranges-461"><span class="linenos">461</span></a> <span class="k">return</span> <span class="p">[]</span>
</span><span id="merge_ranges-462"><a href="#merge_ranges-462"><span class="linenos">462</span></a>
</span><span id="merge_ranges-463"><a href="#merge_ranges-463"><span class="linenos">463</span></a> <span class="n">ranges</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">ranges</span><span class="p">)</span>
</span><span id="merge_ranges-464"><a href="#merge_ranges-464"><span class="linenos">464</span></a>
</span><span id="merge_ranges-465"><a href="#merge_ranges-465"><span class="linenos">465</span></a> <span class="n">merged</span> <span class="o">=</span> <span class="p">[</span><span class="n">ranges</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span>
</span><span id="merge_ranges-466"><a href="#merge_ranges-466"><span class="linenos">466</span></a>
</span><span id="merge_ranges-467"><a href="#merge_ranges-467"><span class="linenos">467</span></a> <span class="k">return</span> <span class="n">merged</span>
</span><span id="merge_ranges-467"><a href="#merge_ranges-467"><span class="linenos">467</span></a> <span class="k">for</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="ow">in</span> <span class="n">ranges</span><span class="p">[</span><span class="mi">1</span><span class="p">:]:</span>
</span><span id="merge_ranges-468"><a href="#merge_ranges-468"><span class="linenos">468</span></a> <span class="n">last_start</span><span class="p">,</span> <span class="n">last_end</span> <span class="o">=</span> <span class="n">merged</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
</span><span id="merge_ranges-469"><a href="#merge_ranges-469"><span class="linenos">469</span></a>
</span><span id="merge_ranges-470"><a href="#merge_ranges-470"><span class="linenos">470</span></a> <span class="k">if</span> <span class="n">start</span> <span class="o">&lt;=</span> <span class="n">last_end</span><span class="p">:</span>
</span><span id="merge_ranges-471"><a href="#merge_ranges-471"><span class="linenos">471</span></a> <span class="n">merged</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">last_start</span><span class="p">,</span> <span class="nb">max</span><span class="p">(</span><span class="n">last_end</span><span class="p">,</span> <span class="n">end</span><span class="p">))</span>
</span><span id="merge_ranges-472"><a href="#merge_ranges-472"><span class="linenos">472</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="merge_ranges-473"><a href="#merge_ranges-473"><span class="linenos">473</span></a> <span class="n">merged</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">))</span>
</span><span id="merge_ranges-474"><a href="#merge_ranges-474"><span class="linenos">474</span></a>
</span><span id="merge_ranges-475"><a href="#merge_ranges-475"><span class="linenos">475</span></a> <span class="k">return</span> <span class="n">merged</span>
</span></pre></div>
@ -1736,12 +1770,12 @@ belong to some totally-ordered set.</p>
</div>
<a class="headerlink" href="#is_iso_date"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="is_iso_date-470"><a href="#is_iso_date-470"><span class="linenos">470</span></a><span class="k">def</span> <span class="nf">is_iso_date</span><span class="p">(</span><span class="n">text</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
</span><span id="is_iso_date-471"><a href="#is_iso_date-471"><span class="linenos">471</span></a> <span class="k">try</span><span class="p">:</span>
</span><span id="is_iso_date-472"><a href="#is_iso_date-472"><span class="linenos">472</span></a> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">fromisoformat</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
</span><span id="is_iso_date-473"><a href="#is_iso_date-473"><span class="linenos">473</span></a> <span class="k">return</span> <span class="kc">True</span>
</span><span id="is_iso_date-474"><a href="#is_iso_date-474"><span class="linenos">474</span></a> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
</span><span id="is_iso_date-475"><a href="#is_iso_date-475"><span class="linenos">475</span></a> <span class="k">return</span> <span class="kc">False</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="is_iso_date-478"><a href="#is_iso_date-478"><span class="linenos">478</span></a><span class="k">def</span> <span class="nf">is_iso_date</span><span class="p">(</span><span class="n">text</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
</span><span id="is_iso_date-479"><a href="#is_iso_date-479"><span class="linenos">479</span></a> <span class="k">try</span><span class="p">:</span>
</span><span id="is_iso_date-480"><a href="#is_iso_date-480"><span class="linenos">480</span></a> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">fromisoformat</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
</span><span id="is_iso_date-481"><a href="#is_iso_date-481"><span class="linenos">481</span></a> <span class="k">return</span> <span class="kc">True</span>
</span><span id="is_iso_date-482"><a href="#is_iso_date-482"><span class="linenos">482</span></a> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
</span><span id="is_iso_date-483"><a href="#is_iso_date-483"><span class="linenos">483</span></a> <span class="k">return</span> <span class="kc">False</span>
</span></pre></div>
@ -1759,12 +1793,12 @@ belong to some totally-ordered set.</p>
</div>
<a class="headerlink" href="#is_iso_datetime"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="is_iso_datetime-478"><a href="#is_iso_datetime-478"><span class="linenos">478</span></a><span class="k">def</span> <span class="nf">is_iso_datetime</span><span class="p">(</span><span class="n">text</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
</span><span id="is_iso_datetime-479"><a href="#is_iso_datetime-479"><span class="linenos">479</span></a> <span class="k">try</span><span class="p">:</span>
</span><span id="is_iso_datetime-480"><a href="#is_iso_datetime-480"><span class="linenos">480</span></a> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">fromisoformat</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
</span><span id="is_iso_datetime-481"><a href="#is_iso_datetime-481"><span class="linenos">481</span></a> <span class="k">return</span> <span class="kc">True</span>
</span><span id="is_iso_datetime-482"><a href="#is_iso_datetime-482"><span class="linenos">482</span></a> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
</span><span id="is_iso_datetime-483"><a href="#is_iso_datetime-483"><span class="linenos">483</span></a> <span class="k">return</span> <span class="kc">False</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="is_iso_datetime-486"><a href="#is_iso_datetime-486"><span class="linenos">486</span></a><span class="k">def</span> <span class="nf">is_iso_datetime</span><span class="p">(</span><span class="n">text</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
</span><span id="is_iso_datetime-487"><a href="#is_iso_datetime-487"><span class="linenos">487</span></a> <span class="k">try</span><span class="p">:</span>
</span><span id="is_iso_datetime-488"><a href="#is_iso_datetime-488"><span class="linenos">488</span></a> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">fromisoformat</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
</span><span id="is_iso_datetime-489"><a href="#is_iso_datetime-489"><span class="linenos">489</span></a> <span class="k">return</span> <span class="kc">True</span>
</span><span id="is_iso_datetime-490"><a href="#is_iso_datetime-490"><span class="linenos">490</span></a> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
</span><span id="is_iso_datetime-491"><a href="#is_iso_datetime-491"><span class="linenos">491</span></a> <span class="k">return</span> <span class="kc">False</span>
</span></pre></div>
@ -1774,7 +1808,7 @@ belong to some totally-ordered set.</p>
<section id="DATE_UNITS">
<div class="attr variable">
<span class="name">DATE_UNITS</span> =
<span class="default_value">{&#39;year_month&#39;, &#39;quarter&#39;, &#39;day&#39;, &#39;year&#39;, &#39;week&#39;, &#39;month&#39;}</span>
<span class="default_value">{&#39;year_month&#39;, &#39;quarter&#39;, &#39;day&#39;, &#39;week&#39;, &#39;year&#39;, &#39;month&#39;}</span>
</div>
@ -1794,8 +1828,8 @@ belong to some totally-ordered set.</p>
</div>
<a class="headerlink" href="#is_date_unit"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="is_date_unit-490"><a href="#is_date_unit-490"><span class="linenos">490</span></a><span class="k">def</span> <span class="nf">is_date_unit</span><span class="p">(</span><span class="n">expression</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">Expression</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
</span><span id="is_date_unit-491"><a href="#is_date_unit-491"><span class="linenos">491</span></a> <span class="k">return</span> <span class="n">expression</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">expression</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="ow">in</span> <span class="n">DATE_UNITS</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="is_date_unit-498"><a href="#is_date_unit-498"><span class="linenos">498</span></a><span class="k">def</span> <span class="nf">is_date_unit</span><span class="p">(</span><span class="n">expression</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">Expression</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
</span><span id="is_date_unit-499"><a href="#is_date_unit-499"><span class="linenos">499</span></a> <span class="k">return</span> <span class="n">expression</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">expression</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="ow">in</span> <span class="n">DATE_UNITS</span>
</span></pre></div>

View file

@ -48,17 +48,14 @@
</ul>
</li>
<li>
<a class="variable" href="#JSONPathNode">JSONPathNode</a>
</li>
<li>
<a class="function" href="#parse">parse</a>
</li>
<li>
<a class="variable" href="#MAPPING">MAPPING</a>
<a class="variable" href="#JSON_PATH_PART_TRANSFORMS">JSON_PATH_PART_TRANSFORMS</a>
</li>
<li>
<a class="function" href="#generate">generate</a>
<a class="variable" href="#ALL_JSON_PATH_PARTS">ALL_JSON_PATH_PARTS</a>
</li>
</ul>
@ -87,8 +84,8 @@
</span><span id="L-2"><a href="#L-2"><span class="linenos"> 2</span></a>
</span><span id="L-3"><a href="#L-3"><span class="linenos"> 3</span></a><span class="kn">import</span> <span class="nn">typing</span> <span class="k">as</span> <span class="nn">t</span>
</span><span id="L-4"><a href="#L-4"><span class="linenos"> 4</span></a>
</span><span id="L-5"><a href="#L-5"><span class="linenos"> 5</span></a><span class="kn">from</span> <span class="nn">sqlglot.errors</span> <span class="kn">import</span> <span class="n">ParseError</span>
</span><span id="L-6"><a href="#L-6"><span class="linenos"> 6</span></a><span class="kn">from</span> <span class="nn">sqlglot.expressions</span> <span class="kn">import</span> <span class="n">SAFE_IDENTIFIER_RE</span>
</span><span id="L-5"><a href="#L-5"><span class="linenos"> 5</span></a><span class="kn">import</span> <span class="nn">sqlglot.expressions</span> <span class="k">as</span> <span class="nn">exp</span>
</span><span id="L-6"><a href="#L-6"><span class="linenos"> 6</span></a><span class="kn">from</span> <span class="nn">sqlglot.errors</span> <span class="kn">import</span> <span class="n">ParseError</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.tokens</span> <span class="kn">import</span> <span class="n">Token</span><span class="p">,</span> <span class="n">Tokenizer</span><span class="p">,</span> <span class="n">TokenType</span>
</span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</span></a>
</span><span id="L-9"><a href="#L-9"><span class="linenos"> 9</span></a><span class="k">if</span> <span class="n">t</span><span class="o">.</span><span class="n">TYPE_CHECKING</span><span class="p">:</span>
@ -121,183 +118,165 @@
</span><span id="L-36"><a href="#L-36"><span class="linenos"> 36</span></a> <span class="n">STRING_ESCAPES</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;</span><span class="se">\\</span><span class="s2">&quot;</span><span class="p">]</span>
</span><span id="L-37"><a href="#L-37"><span class="linenos"> 37</span></a>
</span><span id="L-38"><a href="#L-38"><span class="linenos"> 38</span></a>
</span><span id="L-39"><a href="#L-39"><span class="linenos"> 39</span></a><span class="n">JSONPathNode</span> <span class="o">=</span> <span class="n">t</span><span class="o">.</span><span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">]</span>
</span><span id="L-40"><a href="#L-40"><span class="linenos"> 40</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">def</span> <span class="nf">_node</span><span class="p">(</span><span class="n">kind</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">value</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">JSONPathNode</span><span class="p">:</span>
</span><span id="L-43"><a href="#L-43"><span class="linenos"> 43</span></a> <span class="n">node</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;kind&quot;</span><span class="p">:</span> <span class="n">kind</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">}</span>
</span><span id="L-44"><a href="#L-44"><span class="linenos"> 44</span></a>
</span><span id="L-45"><a href="#L-45"><span class="linenos"> 45</span></a> <span class="k">if</span> <span class="n">value</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="L-46"><a href="#L-46"><span class="linenos"> 46</span></a> <span class="n">node</span><span class="p">[</span><span class="s2">&quot;value&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
</span><span id="L-47"><a href="#L-47"><span class="linenos"> 47</span></a>
</span><span id="L-48"><a href="#L-48"><span class="linenos"> 48</span></a> <span class="k">return</span> <span class="n">node</span>
</span><span id="L-49"><a href="#L-49"><span class="linenos"> 49</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">def</span> <span class="nf">parse</span><span class="p">(</span><span class="n">path</span><span class="p">:</span> <span class="nb">str</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">JSONPathNode</span><span class="p">]:</span>
</span><span id="L-52"><a href="#L-52"><span class="linenos"> 52</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;Takes in a JSONPath string and converts into a list of nodes.&quot;&quot;&quot;</span>
</span><span id="L-53"><a href="#L-53"><span class="linenos"> 53</span></a> <span class="n">tokens</span> <span class="o">=</span> <span class="n">JSONPathTokenizer</span><span class="p">()</span><span class="o">.</span><span class="n">tokenize</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
</span><span id="L-54"><a href="#L-54"><span class="linenos"> 54</span></a> <span class="n">size</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">tokens</span><span class="p">)</span>
</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">i</span> <span class="o">=</span> <span class="mi">0</span>
</span><span id="L-57"><a href="#L-57"><span class="linenos"> 57</span></a>
</span><span id="L-58"><a href="#L-58"><span class="linenos"> 58</span></a> <span class="k">def</span> <span class="nf">_curr</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">TokenType</span><span class="p">]:</span>
</span><span id="L-59"><a href="#L-59"><span class="linenos"> 59</span></a> <span class="k">return</span> <span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">token_type</span> <span class="k">if</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">size</span> <span class="k">else</span> <span class="kc">None</span>
</span><span id="L-60"><a href="#L-60"><span class="linenos"> 60</span></a>
</span><span id="L-61"><a href="#L-61"><span class="linenos"> 61</span></a> <span class="k">def</span> <span class="nf">_prev</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">Token</span><span class="p">:</span>
</span><span id="L-62"><a href="#L-62"><span class="linenos"> 62</span></a> <span class="k">return</span> <span class="n">tokens</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
</span><span id="L-39"><a href="#L-39"><span class="linenos"> 39</span></a><span class="k">def</span> <span class="nf">parse</span><span class="p">(</span><span class="n">path</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPath</span><span class="p">:</span>
</span><span id="L-40"><a href="#L-40"><span class="linenos"> 40</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;Takes in a JSON path string and parses it into a JSONPath expression.&quot;&quot;&quot;</span>
</span><span id="L-41"><a href="#L-41"><span class="linenos"> 41</span></a> <span class="n">tokens</span> <span class="o">=</span> <span class="n">JSONPathTokenizer</span><span class="p">()</span><span class="o">.</span><span class="n">tokenize</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
</span><span id="L-42"><a href="#L-42"><span class="linenos"> 42</span></a> <span class="n">size</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">tokens</span><span class="p">)</span>
</span><span id="L-43"><a href="#L-43"><span class="linenos"> 43</span></a>
</span><span id="L-44"><a href="#L-44"><span class="linenos"> 44</span></a> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
</span><span id="L-45"><a href="#L-45"><span class="linenos"> 45</span></a>
</span><span id="L-46"><a href="#L-46"><span class="linenos"> 46</span></a> <span class="k">def</span> <span class="nf">_curr</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">TokenType</span><span class="p">]:</span>
</span><span id="L-47"><a href="#L-47"><span class="linenos"> 47</span></a> <span class="k">return</span> <span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">token_type</span> <span class="k">if</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">size</span> <span class="k">else</span> <span class="kc">None</span>
</span><span id="L-48"><a href="#L-48"><span class="linenos"> 48</span></a>
</span><span id="L-49"><a href="#L-49"><span class="linenos"> 49</span></a> <span class="k">def</span> <span class="nf">_prev</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">Token</span><span class="p">:</span>
</span><span id="L-50"><a href="#L-50"><span class="linenos"> 50</span></a> <span class="k">return</span> <span class="n">tokens</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
</span><span id="L-51"><a href="#L-51"><span class="linenos"> 51</span></a>
</span><span id="L-52"><a href="#L-52"><span class="linenos"> 52</span></a> <span class="k">def</span> <span class="nf">_advance</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">Token</span><span class="p">:</span>
</span><span id="L-53"><a href="#L-53"><span class="linenos"> 53</span></a> <span class="k">nonlocal</span> <span class="n">i</span>
</span><span id="L-54"><a href="#L-54"><span class="linenos"> 54</span></a> <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
</span><span id="L-55"><a href="#L-55"><span class="linenos"> 55</span></a> <span class="k">return</span> <span class="n">_prev</span><span class="p">()</span>
</span><span id="L-56"><a href="#L-56"><span class="linenos"> 56</span></a>
</span><span id="L-57"><a href="#L-57"><span class="linenos"> 57</span></a> <span class="k">def</span> <span class="nf">_error</span><span class="p">(</span><span class="n">msg</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span><span id="L-58"><a href="#L-58"><span class="linenos"> 58</span></a> <span class="k">return</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">msg</span><span class="si">}</span><span class="s2"> at index </span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">: </span><span class="si">{</span><span class="n">path</span><span class="si">}</span><span class="s2">&quot;</span>
</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="nd">@t</span><span class="o">.</span><span class="n">overload</span>
</span><span id="L-61"><a href="#L-61"><span class="linenos"> 61</span></a> <span class="k">def</span> <span class="nf">_match</span><span class="p">(</span><span class="n">token_type</span><span class="p">:</span> <span class="n">TokenType</span><span class="p">,</span> <span class="n">raise_unmatched</span><span class="p">:</span> <span class="n">Lit</span><span class="p">[</span><span class="kc">True</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Token</span><span class="p">:</span>
</span><span id="L-62"><a href="#L-62"><span class="linenos"> 62</span></a> <span class="k">pass</span>
</span><span id="L-63"><a href="#L-63"><span class="linenos"> 63</span></a>
</span><span id="L-64"><a href="#L-64"><span class="linenos"> 64</span></a> <span class="k">def</span> <span class="nf">_advance</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">Token</span><span class="p">:</span>
</span><span id="L-65"><a href="#L-65"><span class="linenos"> 65</span></a> <span class="k">nonlocal</span> <span class="n">i</span>
</span><span id="L-66"><a href="#L-66"><span class="linenos"> 66</span></a> <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
</span><span id="L-67"><a href="#L-67"><span class="linenos"> 67</span></a> <span class="k">return</span> <span class="n">_prev</span><span class="p">()</span>
</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 class="k">def</span> <span class="nf">_error</span><span class="p">(</span><span class="n">msg</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span><span id="L-70"><a href="#L-70"><span class="linenos"> 70</span></a> <span class="k">return</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">msg</span><span class="si">}</span><span class="s2"> at index </span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">: </span><span class="si">{</span><span class="n">path</span><span class="si">}</span><span class="s2">&quot;</span>
</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="nd">@t</span><span class="o">.</span><span class="n">overload</span>
</span><span id="L-73"><a href="#L-73"><span class="linenos"> 73</span></a> <span class="k">def</span> <span class="nf">_match</span><span class="p">(</span><span class="n">token_type</span><span class="p">:</span> <span class="n">TokenType</span><span class="p">,</span> <span class="n">raise_unmatched</span><span class="p">:</span> <span class="n">Lit</span><span class="p">[</span><span class="kc">True</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Token</span><span class="p">:</span>
</span><span id="L-74"><a href="#L-74"><span class="linenos"> 74</span></a> <span class="k">pass</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="nd">@t</span><span class="o">.</span><span class="n">overload</span>
</span><span id="L-77"><a href="#L-77"><span class="linenos"> 77</span></a> <span class="k">def</span> <span class="nf">_match</span><span class="p">(</span><span class="n">token_type</span><span class="p">:</span> <span class="n">TokenType</span><span class="p">,</span> <span class="n">raise_unmatched</span><span class="p">:</span> <span class="n">Lit</span><span class="p">[</span><span class="kc">False</span><span class="p">]</span> <span class="o">=</span> <span class="kc">False</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">Token</span><span class="p">]:</span>
</span><span id="L-78"><a href="#L-78"><span class="linenos"> 78</span></a> <span class="k">pass</span>
</span><span id="L-79"><a href="#L-79"><span class="linenos"> 79</span></a>
</span><span id="L-80"><a href="#L-80"><span class="linenos"> 80</span></a> <span class="k">def</span> <span class="nf">_match</span><span class="p">(</span><span class="n">token_type</span><span class="p">,</span> <span class="n">raise_unmatched</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
</span><span id="L-81"><a href="#L-81"><span class="linenos"> 81</span></a> <span class="k">if</span> <span class="n">_curr</span><span class="p">()</span> <span class="o">==</span> <span class="n">token_type</span><span class="p">:</span>
</span><span id="L-82"><a href="#L-82"><span class="linenos"> 82</span></a> <span class="k">return</span> <span class="n">_advance</span><span class="p">()</span>
</span><span id="L-83"><a href="#L-83"><span class="linenos"> 83</span></a> <span class="k">if</span> <span class="n">raise_unmatched</span><span class="p">:</span>
</span><span id="L-84"><a href="#L-84"><span class="linenos"> 84</span></a> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="n">_error</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Expected </span><span class="si">{</span><span class="n">token_type</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">))</span>
</span><span id="L-85"><a href="#L-85"><span class="linenos"> 85</span></a> <span class="k">return</span> <span class="kc">None</span>
</span><span id="L-86"><a href="#L-86"><span class="linenos"> 86</span></a>
</span><span id="L-87"><a href="#L-87"><span class="linenos"> 87</span></a> <span class="k">def</span> <span class="nf">_parse_literal</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">:</span>
</span><span id="L-88"><a href="#L-88"><span class="linenos"> 88</span></a> <span class="n">token</span> <span class="o">=</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">STRING</span><span class="p">)</span> <span class="ow">or</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">IDENTIFIER</span><span class="p">)</span>
</span><span id="L-89"><a href="#L-89"><span class="linenos"> 89</span></a> <span class="k">if</span> <span class="n">token</span><span class="p">:</span>
</span><span id="L-90"><a href="#L-90"><span class="linenos"> 90</span></a> <span class="k">return</span> <span class="n">token</span><span class="o">.</span><span class="n">text</span>
</span><span id="L-91"><a href="#L-91"><span class="linenos"> 91</span></a> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">STAR</span><span class="p">):</span>
</span><span id="L-92"><a href="#L-92"><span class="linenos"> 92</span></a> <span class="k">return</span> <span class="n">_node</span><span class="p">(</span><span class="s2">&quot;wildcard&quot;</span><span class="p">)</span>
</span><span id="L-93"><a href="#L-93"><span class="linenos"> 93</span></a> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">PLACEHOLDER</span><span class="p">)</span> <span class="ow">or</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">L_PAREN</span><span class="p">):</span>
</span><span id="L-94"><a href="#L-94"><span class="linenos"> 94</span></a> <span class="n">script</span> <span class="o">=</span> <span class="n">_prev</span><span class="p">()</span><span class="o">.</span><span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;(&quot;</span>
</span><span id="L-95"><a href="#L-95"><span class="linenos"> 95</span></a> <span class="n">start</span> <span class="o">=</span> <span class="n">i</span>
</span><span id="L-64"><a href="#L-64"><span class="linenos"> 64</span></a> <span class="nd">@t</span><span class="o">.</span><span class="n">overload</span>
</span><span id="L-65"><a href="#L-65"><span class="linenos"> 65</span></a> <span class="k">def</span> <span class="nf">_match</span><span class="p">(</span><span class="n">token_type</span><span class="p">:</span> <span class="n">TokenType</span><span class="p">,</span> <span class="n">raise_unmatched</span><span class="p">:</span> <span class="n">Lit</span><span class="p">[</span><span class="kc">False</span><span class="p">]</span> <span class="o">=</span> <span class="kc">False</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">Token</span><span class="p">]:</span>
</span><span id="L-66"><a href="#L-66"><span class="linenos"> 66</span></a> <span class="k">pass</span>
</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">def</span> <span class="nf">_match</span><span class="p">(</span><span class="n">token_type</span><span class="p">,</span> <span class="n">raise_unmatched</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
</span><span id="L-69"><a href="#L-69"><span class="linenos"> 69</span></a> <span class="k">if</span> <span class="n">_curr</span><span class="p">()</span> <span class="o">==</span> <span class="n">token_type</span><span class="p">:</span>
</span><span id="L-70"><a href="#L-70"><span class="linenos"> 70</span></a> <span class="k">return</span> <span class="n">_advance</span><span class="p">()</span>
</span><span id="L-71"><a href="#L-71"><span class="linenos"> 71</span></a> <span class="k">if</span> <span class="n">raise_unmatched</span><span class="p">:</span>
</span><span id="L-72"><a href="#L-72"><span class="linenos"> 72</span></a> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="n">_error</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Expected </span><span class="si">{</span><span class="n">token_type</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">))</span>
</span><span id="L-73"><a href="#L-73"><span class="linenos"> 73</span></a> <span class="k">return</span> <span class="kc">None</span>
</span><span id="L-74"><a href="#L-74"><span class="linenos"> 74</span></a>
</span><span id="L-75"><a href="#L-75"><span class="linenos"> 75</span></a> <span class="k">def</span> <span class="nf">_parse_literal</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">:</span>
</span><span id="L-76"><a href="#L-76"><span class="linenos"> 76</span></a> <span class="n">token</span> <span class="o">=</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">STRING</span><span class="p">)</span> <span class="ow">or</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">IDENTIFIER</span><span class="p">)</span>
</span><span id="L-77"><a href="#L-77"><span class="linenos"> 77</span></a> <span class="k">if</span> <span class="n">token</span><span class="p">:</span>
</span><span id="L-78"><a href="#L-78"><span class="linenos"> 78</span></a> <span class="k">return</span> <span class="n">token</span><span class="o">.</span><span class="n">text</span>
</span><span id="L-79"><a href="#L-79"><span class="linenos"> 79</span></a> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">STAR</span><span class="p">):</span>
</span><span id="L-80"><a href="#L-80"><span class="linenos"> 80</span></a> <span class="k">return</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathWildcard</span><span class="p">()</span>
</span><span id="L-81"><a href="#L-81"><span class="linenos"> 81</span></a> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">PLACEHOLDER</span><span class="p">)</span> <span class="ow">or</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">L_PAREN</span><span class="p">):</span>
</span><span id="L-82"><a href="#L-82"><span class="linenos"> 82</span></a> <span class="n">script</span> <span class="o">=</span> <span class="n">_prev</span><span class="p">()</span><span class="o">.</span><span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;(&quot;</span>
</span><span id="L-83"><a href="#L-83"><span class="linenos"> 83</span></a> <span class="n">start</span> <span class="o">=</span> <span class="n">i</span>
</span><span id="L-84"><a href="#L-84"><span class="linenos"> 84</span></a>
</span><span id="L-85"><a href="#L-85"><span class="linenos"> 85</span></a> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
</span><span id="L-86"><a href="#L-86"><span class="linenos"> 86</span></a> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">L_BRACKET</span><span class="p">):</span>
</span><span id="L-87"><a href="#L-87"><span class="linenos"> 87</span></a> <span class="n">_parse_bracket</span><span class="p">()</span> <span class="c1"># nested call which we can throw away</span>
</span><span id="L-88"><a href="#L-88"><span class="linenos"> 88</span></a> <span class="k">if</span> <span class="n">_curr</span><span class="p">()</span> <span class="ow">in</span> <span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">R_BRACKET</span><span class="p">,</span> <span class="kc">None</span><span class="p">):</span>
</span><span id="L-89"><a href="#L-89"><span class="linenos"> 89</span></a> <span class="k">break</span>
</span><span id="L-90"><a href="#L-90"><span class="linenos"> 90</span></a> <span class="n">_advance</span><span class="p">()</span>
</span><span id="L-91"><a href="#L-91"><span class="linenos"> 91</span></a>
</span><span id="L-92"><a href="#L-92"><span class="linenos"> 92</span></a> <span class="n">expr_type</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathScript</span> <span class="k">if</span> <span class="n">script</span> <span class="k">else</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathFilter</span>
</span><span id="L-93"><a href="#L-93"><span class="linenos"> 93</span></a> <span class="k">return</span> <span class="n">expr_type</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">path</span><span class="p">[</span><span class="n">tokens</span><span class="p">[</span><span class="n">start</span><span class="p">]</span><span class="o">.</span><span class="n">start</span> <span class="p">:</span> <span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">end</span><span class="p">])</span>
</span><span id="L-94"><a href="#L-94"><span class="linenos"> 94</span></a>
</span><span id="L-95"><a href="#L-95"><span class="linenos"> 95</span></a> <span class="n">number</span> <span class="o">=</span> <span class="s2">&quot;-&quot;</span> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">DASH</span><span class="p">)</span> <span class="k">else</span> <span class="s2">&quot;&quot;</span>
</span><span id="L-96"><a href="#L-96"><span class="linenos"> 96</span></a>
</span><span id="L-97"><a href="#L-97"><span class="linenos"> 97</span></a> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
</span><span id="L-98"><a href="#L-98"><span class="linenos"> 98</span></a> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">L_BRACKET</span><span class="p">):</span>
</span><span id="L-99"><a href="#L-99"><span class="linenos"> 99</span></a> <span class="n">_parse_bracket</span><span class="p">()</span> <span class="c1"># nested call which we can throw away</span>
</span><span id="L-100"><a href="#L-100"><span class="linenos">100</span></a> <span class="k">if</span> <span class="n">_curr</span><span class="p">()</span> <span class="ow">in</span> <span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">R_BRACKET</span><span class="p">,</span> <span class="kc">None</span><span class="p">):</span>
</span><span id="L-101"><a href="#L-101"><span class="linenos">101</span></a> <span class="k">break</span>
</span><span id="L-102"><a href="#L-102"><span class="linenos">102</span></a> <span class="n">_advance</span><span class="p">()</span>
</span><span id="L-103"><a href="#L-103"><span class="linenos">103</span></a> <span class="k">return</span> <span class="n">_node</span><span class="p">(</span>
</span><span id="L-104"><a href="#L-104"><span class="linenos">104</span></a> <span class="s2">&quot;script&quot;</span> <span class="k">if</span> <span class="n">script</span> <span class="k">else</span> <span class="s2">&quot;filter&quot;</span><span class="p">,</span> <span class="n">path</span><span class="p">[</span><span class="n">tokens</span><span class="p">[</span><span class="n">start</span><span class="p">]</span><span class="o">.</span><span class="n">start</span> <span class="p">:</span> <span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">end</span><span class="p">]</span>
</span><span id="L-105"><a href="#L-105"><span class="linenos">105</span></a> <span class="p">)</span>
</span><span id="L-106"><a href="#L-106"><span class="linenos">106</span></a>
</span><span id="L-107"><a href="#L-107"><span class="linenos">107</span></a> <span class="n">number</span> <span class="o">=</span> <span class="s2">&quot;-&quot;</span> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">DASH</span><span class="p">)</span> <span class="k">else</span> <span class="s2">&quot;&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="n">token</span> <span class="o">=</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">NUMBER</span><span class="p">)</span>
</span><span id="L-110"><a href="#L-110"><span class="linenos">110</span></a> <span class="k">if</span> <span class="n">token</span><span class="p">:</span>
</span><span id="L-111"><a href="#L-111"><span class="linenos">111</span></a> <span class="n">number</span> <span class="o">+=</span> <span class="n">token</span><span class="o">.</span><span class="n">text</span>
</span><span id="L-112"><a href="#L-112"><span class="linenos">112</span></a>
</span><span id="L-113"><a href="#L-113"><span class="linenos">113</span></a> <span class="k">if</span> <span class="n">number</span><span class="p">:</span>
</span><span id="L-114"><a href="#L-114"><span class="linenos">114</span></a> <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">number</span><span class="p">)</span>
</span><span id="L-115"><a href="#L-115"><span class="linenos">115</span></a> <span class="k">return</span> <span class="kc">False</span>
</span><span id="L-116"><a href="#L-116"><span class="linenos">116</span></a>
</span><span id="L-117"><a href="#L-117"><span class="linenos">117</span></a> <span class="k">def</span> <span class="nf">_parse_slice</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">:</span>
</span><span id="L-118"><a href="#L-118"><span class="linenos">118</span></a> <span class="n">start</span> <span class="o">=</span> <span class="n">_parse_literal</span><span class="p">()</span>
</span><span id="L-119"><a href="#L-119"><span class="linenos">119</span></a> <span class="n">end</span> <span class="o">=</span> <span class="n">_parse_literal</span><span class="p">()</span> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">COLON</span><span class="p">)</span> <span class="k">else</span> <span class="kc">None</span>
</span><span id="L-120"><a href="#L-120"><span class="linenos">120</span></a> <span class="n">step</span> <span class="o">=</span> <span class="n">_parse_literal</span><span class="p">()</span> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">COLON</span><span class="p">)</span> <span class="k">else</span> <span class="kc">None</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="k">if</span> <span class="n">end</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">step</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="L-123"><a href="#L-123"><span class="linenos">123</span></a> <span class="k">return</span> <span class="n">start</span>
</span><span id="L-124"><a href="#L-124"><span class="linenos">124</span></a> <span class="k">return</span> <span class="n">_node</span><span class="p">(</span><span class="s2">&quot;slice&quot;</span><span class="p">,</span> <span class="n">start</span><span class="o">=</span><span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="n">end</span><span class="p">,</span> <span class="n">step</span><span class="o">=</span><span class="n">step</span><span class="p">)</span>
</span><span id="L-125"><a href="#L-125"><span class="linenos">125</span></a>
</span><span id="L-126"><a href="#L-126"><span class="linenos">126</span></a> <span class="k">def</span> <span class="nf">_parse_bracket</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">JSONPathNode</span><span class="p">:</span>
</span><span id="L-127"><a href="#L-127"><span class="linenos">127</span></a> <span class="n">literal</span> <span class="o">=</span> <span class="n">_parse_slice</span><span class="p">()</span>
</span><span id="L-128"><a href="#L-128"><span class="linenos">128</span></a>
</span><span id="L-129"><a href="#L-129"><span class="linenos">129</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">literal</span><span class="p">,</span> <span class="nb">str</span><span class="p">)</span> <span class="ow">or</span> <span class="n">literal</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">False</span><span class="p">:</span>
</span><span id="L-130"><a href="#L-130"><span class="linenos">130</span></a> <span class="n">indexes</span> <span class="o">=</span> <span class="p">[</span><span class="n">literal</span><span class="p">]</span>
</span><span id="L-131"><a href="#L-131"><span class="linenos">131</span></a> <span class="k">while</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">COMMA</span><span class="p">):</span>
</span><span id="L-132"><a href="#L-132"><span class="linenos">132</span></a> <span class="n">literal</span> <span class="o">=</span> <span class="n">_parse_slice</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="k">if</span> <span class="n">literal</span><span class="p">:</span>
</span><span id="L-135"><a href="#L-135"><span class="linenos">135</span></a> <span class="n">indexes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">literal</span><span class="p">)</span>
</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 class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">indexes</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
</span><span id="L-138"><a href="#L-138"><span class="linenos">138</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">literal</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">node</span> <span class="o">=</span> <span class="n">_node</span><span class="p">(</span><span class="s2">&quot;key&quot;</span><span class="p">,</span> <span class="n">indexes</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
</span><span id="L-140"><a href="#L-140"><span class="linenos">140</span></a> <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">literal</span><span class="p">,</span> <span class="nb">dict</span><span class="p">)</span> <span class="ow">and</span> <span class="n">literal</span><span class="p">[</span><span class="s2">&quot;kind&quot;</span><span class="p">]</span> <span class="ow">in</span> <span class="p">(</span><span class="s2">&quot;script&quot;</span><span class="p">,</span> <span class="s2">&quot;filter&quot;</span><span class="p">):</span>
</span><span id="L-141"><a href="#L-141"><span class="linenos">141</span></a> <span class="n">node</span> <span class="o">=</span> <span class="n">_node</span><span class="p">(</span><span class="s2">&quot;selector&quot;</span><span class="p">,</span> <span class="n">indexes</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
</span><span id="L-142"><a href="#L-142"><span class="linenos">142</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-143"><a href="#L-143"><span class="linenos">143</span></a> <span class="n">node</span> <span class="o">=</span> <span class="n">_node</span><span class="p">(</span><span class="s2">&quot;subscript&quot;</span><span class="p">,</span> <span class="n">indexes</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
</span><span id="L-144"><a href="#L-144"><span class="linenos">144</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-145"><a href="#L-145"><span class="linenos">145</span></a> <span class="n">node</span> <span class="o">=</span> <span class="n">_node</span><span class="p">(</span><span class="s2">&quot;union&quot;</span><span class="p">,</span> <span class="n">indexes</span><span class="p">)</span>
</span><span id="L-146"><a href="#L-146"><span class="linenos">146</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-147"><a href="#L-147"><span class="linenos">147</span></a> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="n">_error</span><span class="p">(</span><span class="s2">&quot;Cannot have empty segment&quot;</span><span class="p">))</span>
</span><span id="L-148"><a href="#L-148"><span class="linenos">148</span></a>
</span><span id="L-149"><a href="#L-149"><span class="linenos">149</span></a> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">R_BRACKET</span><span class="p">,</span> <span class="n">raise_unmatched</span><span class="o">=</span><span class="kc">True</span><span class="p">)</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 class="k">return</span> <span class="n">node</span>
</span><span id="L-152"><a href="#L-152"><span class="linenos">152</span></a>
</span><span id="L-153"><a href="#L-153"><span class="linenos">153</span></a> <span class="n">nodes</span> <span class="o">=</span> <span class="p">[]</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="k">while</span> <span class="n">_curr</span><span class="p">():</span>
</span><span id="L-156"><a href="#L-156"><span class="linenos">156</span></a> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">DOLLAR</span><span class="p">):</span>
</span><span id="L-157"><a href="#L-157"><span class="linenos">157</span></a> <span class="n">nodes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">_node</span><span class="p">(</span><span class="s2">&quot;root&quot;</span><span class="p">))</span>
</span><span id="L-158"><a href="#L-158"><span class="linenos">158</span></a> <span class="k">elif</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">DOT</span><span class="p">):</span>
</span><span id="L-159"><a href="#L-159"><span class="linenos">159</span></a> <span class="n">recursive</span> <span class="o">=</span> <span class="n">_prev</span><span class="p">()</span><span class="o">.</span><span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;..&quot;</span>
</span><span id="L-160"><a href="#L-160"><span class="linenos">160</span></a> <span class="n">value</span> <span class="o">=</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">VAR</span><span class="p">)</span> <span class="ow">or</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">STAR</span><span class="p">)</span>
</span><span id="L-161"><a href="#L-161"><span class="linenos">161</span></a> <span class="n">nodes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
</span><span id="L-162"><a href="#L-162"><span class="linenos">162</span></a> <span class="n">_node</span><span class="p">(</span><span class="s2">&quot;recursive&quot;</span> <span class="k">if</span> <span class="n">recursive</span> <span class="k">else</span> <span class="s2">&quot;child&quot;</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="n">value</span><span class="o">.</span><span class="n">text</span> <span class="k">if</span> <span class="n">value</span> <span class="k">else</span> <span class="kc">None</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><span id="L-164"><a href="#L-164"><span class="linenos">164</span></a> <span class="k">elif</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">L_BRACKET</span><span class="p">):</span>
</span><span id="L-165"><a href="#L-165"><span class="linenos">165</span></a> <span class="n">nodes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">_parse_bracket</span><span class="p">())</span>
</span><span id="L-166"><a href="#L-166"><span class="linenos">166</span></a> <span class="k">elif</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">VAR</span><span class="p">):</span>
</span><span id="L-167"><a href="#L-167"><span class="linenos">167</span></a> <span class="n">nodes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">_node</span><span class="p">(</span><span class="s2">&quot;key&quot;</span><span class="p">,</span> <span class="n">_prev</span><span class="p">()</span><span class="o">.</span><span class="n">text</span><span class="p">))</span>
</span><span id="L-168"><a href="#L-168"><span class="linenos">168</span></a> <span class="k">elif</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">STAR</span><span class="p">):</span>
</span><span id="L-169"><a href="#L-169"><span class="linenos">169</span></a> <span class="n">nodes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">_node</span><span class="p">(</span><span class="s2">&quot;wildcard&quot;</span><span class="p">))</span>
</span><span id="L-170"><a href="#L-170"><span class="linenos">170</span></a> <span class="k">elif</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">PARAMETER</span><span class="p">):</span>
</span><span id="L-171"><a href="#L-171"><span class="linenos">171</span></a> <span class="n">nodes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">_node</span><span class="p">(</span><span class="s2">&quot;current&quot;</span><span class="p">))</span>
</span><span id="L-172"><a href="#L-172"><span class="linenos">172</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-173"><a href="#L-173"><span class="linenos">173</span></a> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="n">_error</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Unexpected </span><span class="si">{</span><span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">token_type</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">))</span>
</span><span id="L-174"><a href="#L-174"><span class="linenos">174</span></a>
</span><span id="L-175"><a href="#L-175"><span class="linenos">175</span></a> <span class="k">return</span> <span class="n">nodes</span>
</span><span id="L-176"><a href="#L-176"><span class="linenos">176</span></a>
</span><span id="L-97"><a href="#L-97"><span class="linenos"> 97</span></a> <span class="n">token</span> <span class="o">=</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">NUMBER</span><span class="p">)</span>
</span><span id="L-98"><a href="#L-98"><span class="linenos"> 98</span></a> <span class="k">if</span> <span class="n">token</span><span class="p">:</span>
</span><span id="L-99"><a href="#L-99"><span class="linenos"> 99</span></a> <span class="n">number</span> <span class="o">+=</span> <span class="n">token</span><span class="o">.</span><span class="n">text</span>
</span><span id="L-100"><a href="#L-100"><span class="linenos">100</span></a>
</span><span id="L-101"><a href="#L-101"><span class="linenos">101</span></a> <span class="k">if</span> <span class="n">number</span><span class="p">:</span>
</span><span id="L-102"><a href="#L-102"><span class="linenos">102</span></a> <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">number</span><span class="p">)</span>
</span><span id="L-103"><a href="#L-103"><span class="linenos">103</span></a>
</span><span id="L-104"><a href="#L-104"><span class="linenos">104</span></a> <span class="k">return</span> <span class="kc">False</span>
</span><span id="L-105"><a href="#L-105"><span class="linenos">105</span></a>
</span><span id="L-106"><a href="#L-106"><span class="linenos">106</span></a> <span class="k">def</span> <span class="nf">_parse_slice</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">:</span>
</span><span id="L-107"><a href="#L-107"><span class="linenos">107</span></a> <span class="n">start</span> <span class="o">=</span> <span class="n">_parse_literal</span><span class="p">()</span>
</span><span id="L-108"><a href="#L-108"><span class="linenos">108</span></a> <span class="n">end</span> <span class="o">=</span> <span class="n">_parse_literal</span><span class="p">()</span> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">COLON</span><span class="p">)</span> <span class="k">else</span> <span class="kc">None</span>
</span><span id="L-109"><a href="#L-109"><span class="linenos">109</span></a> <span class="n">step</span> <span class="o">=</span> <span class="n">_parse_literal</span><span class="p">()</span> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">COLON</span><span class="p">)</span> <span class="k">else</span> <span class="kc">None</span>
</span><span id="L-110"><a href="#L-110"><span class="linenos">110</span></a>
</span><span id="L-111"><a href="#L-111"><span class="linenos">111</span></a> <span class="k">if</span> <span class="n">end</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">step</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="L-112"><a href="#L-112"><span class="linenos">112</span></a> <span class="k">return</span> <span class="n">start</span>
</span><span id="L-113"><a href="#L-113"><span class="linenos">113</span></a>
</span><span id="L-114"><a href="#L-114"><span class="linenos">114</span></a> <span class="k">return</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathSlice</span><span class="p">(</span><span class="n">start</span><span class="o">=</span><span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="n">end</span><span class="p">,</span> <span class="n">step</span><span class="o">=</span><span class="n">step</span><span class="p">)</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 class="k">def</span> <span class="nf">_parse_bracket</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathPart</span><span class="p">:</span>
</span><span id="L-117"><a href="#L-117"><span class="linenos">117</span></a> <span class="n">literal</span> <span class="o">=</span> <span class="n">_parse_slice</span><span class="p">()</span>
</span><span id="L-118"><a href="#L-118"><span class="linenos">118</span></a>
</span><span id="L-119"><a href="#L-119"><span class="linenos">119</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">literal</span><span class="p">,</span> <span class="nb">str</span><span class="p">)</span> <span class="ow">or</span> <span class="n">literal</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">False</span><span class="p">:</span>
</span><span id="L-120"><a href="#L-120"><span class="linenos">120</span></a> <span class="n">indexes</span> <span class="o">=</span> <span class="p">[</span><span class="n">literal</span><span class="p">]</span>
</span><span id="L-121"><a href="#L-121"><span class="linenos">121</span></a> <span class="k">while</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">COMMA</span><span class="p">):</span>
</span><span id="L-122"><a href="#L-122"><span class="linenos">122</span></a> <span class="n">literal</span> <span class="o">=</span> <span class="n">_parse_slice</span><span class="p">()</span>
</span><span id="L-123"><a href="#L-123"><span class="linenos">123</span></a>
</span><span id="L-124"><a href="#L-124"><span class="linenos">124</span></a> <span class="k">if</span> <span class="n">literal</span><span class="p">:</span>
</span><span id="L-125"><a href="#L-125"><span class="linenos">125</span></a> <span class="n">indexes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">literal</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">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">indexes</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</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="nb">isinstance</span><span class="p">(</span><span class="n">literal</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
</span><span id="L-129"><a href="#L-129"><span class="linenos">129</span></a> <span class="n">node</span><span class="p">:</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathPart</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathKey</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">indexes</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
</span><span id="L-130"><a href="#L-130"><span class="linenos">130</span></a> <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">literal</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathPart</span><span class="p">)</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span>
</span><span id="L-131"><a href="#L-131"><span class="linenos">131</span></a> <span class="n">literal</span><span class="p">,</span> <span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">JSONPathScript</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathFilter</span><span class="p">)</span>
</span><span id="L-132"><a href="#L-132"><span class="linenos">132</span></a> <span class="p">):</span>
</span><span id="L-133"><a href="#L-133"><span class="linenos">133</span></a> <span class="n">node</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathSelector</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">indexes</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
</span><span id="L-134"><a href="#L-134"><span class="linenos">134</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-135"><a href="#L-135"><span class="linenos">135</span></a> <span class="n">node</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathSubscript</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">indexes</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
</span><span id="L-136"><a href="#L-136"><span class="linenos">136</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-137"><a href="#L-137"><span class="linenos">137</span></a> <span class="n">node</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathUnion</span><span class="p">(</span><span class="n">expressions</span><span class="o">=</span><span class="n">indexes</span><span class="p">)</span>
</span><span id="L-138"><a href="#L-138"><span class="linenos">138</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-139"><a href="#L-139"><span class="linenos">139</span></a> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="n">_error</span><span class="p">(</span><span class="s2">&quot;Cannot have empty segment&quot;</span><span class="p">))</span>
</span><span id="L-140"><a href="#L-140"><span class="linenos">140</span></a>
</span><span id="L-141"><a href="#L-141"><span class="linenos">141</span></a> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">R_BRACKET</span><span class="p">,</span> <span class="n">raise_unmatched</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="L-142"><a href="#L-142"><span class="linenos">142</span></a>
</span><span id="L-143"><a href="#L-143"><span class="linenos">143</span></a> <span class="k">return</span> <span class="n">node</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 class="c1"># We canonicalize the JSON path AST so that it always starts with a</span>
</span><span id="L-146"><a href="#L-146"><span class="linenos">146</span></a> <span class="c1"># &quot;root&quot; element, so paths like &quot;field&quot; will be generated as &quot;$.field&quot;</span>
</span><span id="L-147"><a href="#L-147"><span class="linenos">147</span></a> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">DOLLAR</span><span class="p">)</span>
</span><span id="L-148"><a href="#L-148"><span class="linenos">148</span></a> <span class="n">expressions</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">List</span><span class="p">[</span><span class="n">exp</span><span class="o">.</span><span class="n">JSONPathPart</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">exp</span><span class="o">.</span><span class="n">JSONPathRoot</span><span class="p">()]</span>
</span><span id="L-149"><a href="#L-149"><span class="linenos">149</span></a>
</span><span id="L-150"><a href="#L-150"><span class="linenos">150</span></a> <span class="k">while</span> <span class="n">_curr</span><span class="p">():</span>
</span><span id="L-151"><a href="#L-151"><span class="linenos">151</span></a> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">DOT</span><span class="p">)</span> <span class="ow">or</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">COLON</span><span class="p">):</span>
</span><span id="L-152"><a href="#L-152"><span class="linenos">152</span></a> <span class="n">recursive</span> <span class="o">=</span> <span class="n">_prev</span><span class="p">()</span><span class="o">.</span><span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;..&quot;</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="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">VAR</span><span class="p">)</span> <span class="ow">or</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">IDENTIFIER</span><span class="p">):</span>
</span><span id="L-155"><a href="#L-155"><span class="linenos">155</span></a> <span class="n">value</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="o">|</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathWildcard</span><span class="p">]</span> <span class="o">=</span> <span class="n">_prev</span><span class="p">()</span><span class="o">.</span><span class="n">text</span>
</span><span id="L-156"><a href="#L-156"><span class="linenos">156</span></a> <span class="k">elif</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">STAR</span><span class="p">):</span>
</span><span id="L-157"><a href="#L-157"><span class="linenos">157</span></a> <span class="n">value</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathWildcard</span><span class="p">()</span>
</span><span id="L-158"><a href="#L-158"><span class="linenos">158</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-159"><a href="#L-159"><span class="linenos">159</span></a> <span class="n">value</span> <span class="o">=</span> <span class="kc">None</span>
</span><span id="L-160"><a href="#L-160"><span class="linenos">160</span></a>
</span><span id="L-161"><a href="#L-161"><span class="linenos">161</span></a> <span class="k">if</span> <span class="n">recursive</span><span class="p">:</span>
</span><span id="L-162"><a href="#L-162"><span class="linenos">162</span></a> <span class="n">expressions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">JSONPathRecursive</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">value</span><span class="p">))</span>
</span><span id="L-163"><a href="#L-163"><span class="linenos">163</span></a> <span class="k">elif</span> <span class="n">value</span><span class="p">:</span>
</span><span id="L-164"><a href="#L-164"><span class="linenos">164</span></a> <span class="n">expressions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">JSONPathKey</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">value</span><span class="p">))</span>
</span><span id="L-165"><a href="#L-165"><span class="linenos">165</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-166"><a href="#L-166"><span class="linenos">166</span></a> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="n">_error</span><span class="p">(</span><span class="s2">&quot;Expected key name or * after DOT&quot;</span><span class="p">))</span>
</span><span id="L-167"><a href="#L-167"><span class="linenos">167</span></a> <span class="k">elif</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">L_BRACKET</span><span class="p">):</span>
</span><span id="L-168"><a href="#L-168"><span class="linenos">168</span></a> <span class="n">expressions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">_parse_bracket</span><span class="p">())</span>
</span><span id="L-169"><a href="#L-169"><span class="linenos">169</span></a> <span class="k">elif</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">VAR</span><span class="p">)</span> <span class="ow">or</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">IDENTIFIER</span><span class="p">):</span>
</span><span id="L-170"><a href="#L-170"><span class="linenos">170</span></a> <span class="n">expressions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">JSONPathKey</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">_prev</span><span class="p">()</span><span class="o">.</span><span class="n">text</span><span class="p">))</span>
</span><span id="L-171"><a href="#L-171"><span class="linenos">171</span></a> <span class="k">elif</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">STAR</span><span class="p">):</span>
</span><span id="L-172"><a href="#L-172"><span class="linenos">172</span></a> <span class="n">expressions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">JSONPathWildcard</span><span class="p">())</span>
</span><span id="L-173"><a href="#L-173"><span class="linenos">173</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-174"><a href="#L-174"><span class="linenos">174</span></a> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="n">_error</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Unexpected </span><span class="si">{</span><span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">token_type</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">))</span>
</span><span id="L-175"><a href="#L-175"><span class="linenos">175</span></a>
</span><span id="L-176"><a href="#L-176"><span class="linenos">176</span></a> <span class="k">return</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPath</span><span class="p">(</span><span class="n">expressions</span><span class="o">=</span><span class="n">expressions</span><span class="p">)</span>
</span><span id="L-177"><a href="#L-177"><span class="linenos">177</span></a>
</span><span id="L-178"><a href="#L-178"><span class="linenos">178</span></a><span class="n">MAPPING</span> <span class="o">=</span> <span class="p">{</span>
</span><span id="L-179"><a href="#L-179"><span class="linenos">179</span></a> <span class="s2">&quot;child&quot;</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&quot;.</span><span class="si">{</span><span class="n">n</span><span class="p">[</span><span class="s1">&#39;value&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2">&quot;</span> <span class="k">if</span> <span class="n">n</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;value&quot;</span><span class="p">)</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="k">else</span> <span class="s2">&quot;&quot;</span><span class="p">,</span>
</span><span id="L-180"><a href="#L-180"><span class="linenos">180</span></a> <span class="s2">&quot;filter&quot;</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&quot;?</span><span class="si">{</span><span class="n">n</span><span class="p">[</span><span class="s1">&#39;value&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">,</span>
</span><span id="L-181"><a href="#L-181"><span class="linenos">181</span></a> <span class="s2">&quot;key&quot;</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&quot;.</span><span class="si">{</span><span class="n">n</span><span class="p">[</span><span class="s1">&#39;value&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2">&quot;</span>
</span><span id="L-182"><a href="#L-182"><span class="linenos">182</span></a> <span class="k">if</span> <span class="n">SAFE_IDENTIFIER_RE</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">n</span><span class="p">[</span><span class="s2">&quot;value&quot;</span><span class="p">])</span>
</span><span id="L-183"><a href="#L-183"><span class="linenos">183</span></a> <span class="k">else</span> <span class="sa">f</span><span class="s1">&#39;[</span><span class="si">{</span><span class="n">generate</span><span class="p">([</span><span class="n">n</span><span class="p">[</span><span class="s2">&quot;value&quot;</span><span class="p">]])</span><span class="si">}</span><span class="s1">]&#39;</span><span class="p">,</span>
</span><span id="L-184"><a href="#L-184"><span class="linenos">184</span></a> <span class="s2">&quot;recursive&quot;</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&quot;..</span><span class="si">{</span><span class="n">n</span><span class="p">[</span><span class="s1">&#39;value&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2">&quot;</span> <span class="k">if</span> <span class="n">n</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;value&quot;</span><span class="p">)</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="k">else</span> <span class="s2">&quot;..&quot;</span><span class="p">,</span>
</span><span id="L-185"><a href="#L-185"><span class="linenos">185</span></a> <span class="s2">&quot;root&quot;</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">_</span><span class="p">:</span> <span class="s2">&quot;$&quot;</span><span class="p">,</span>
</span><span id="L-186"><a href="#L-186"><span class="linenos">186</span></a> <span class="s2">&quot;script&quot;</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&quot;(</span><span class="si">{</span><span class="n">n</span><span class="p">[</span><span class="s1">&#39;value&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">,</span>
</span><span id="L-187"><a href="#L-187"><span class="linenos">187</span></a> <span class="s2">&quot;slice&quot;</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="s2">&quot;:&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span>
</span><span id="L-188"><a href="#L-188"><span class="linenos">188</span></a> <span class="s2">&quot;&quot;</span> <span class="k">if</span> <span class="n">p</span> <span class="ow">is</span> <span class="kc">False</span> <span class="k">else</span> <span class="n">generate</span><span class="p">([</span><span class="n">p</span><span class="p">])</span>
</span><span id="L-189"><a href="#L-189"><span class="linenos">189</span></a> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="p">[</span><span class="n">n</span><span class="p">[</span><span class="s2">&quot;start&quot;</span><span class="p">],</span> <span class="n">n</span><span class="p">[</span><span class="s2">&quot;end&quot;</span><span class="p">],</span> <span class="n">n</span><span class="p">[</span><span class="s2">&quot;step&quot;</span><span class="p">]]</span>
</span><span id="L-190"><a href="#L-190"><span class="linenos">190</span></a> <span class="k">if</span> <span class="n">p</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
</span><span id="L-191"><a href="#L-191"><span class="linenos">191</span></a> <span class="p">),</span>
</span><span id="L-192"><a href="#L-192"><span class="linenos">192</span></a> <span class="s2">&quot;selector&quot;</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&quot;[</span><span class="si">{</span><span class="n">generate</span><span class="p">([</span><span class="n">n</span><span class="p">[</span><span class="s1">&#39;value&#39;</span><span class="p">]])</span><span class="si">}</span><span class="s2">]&quot;</span><span class="p">,</span>
</span><span id="L-193"><a href="#L-193"><span class="linenos">193</span></a> <span class="s2">&quot;subscript&quot;</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&quot;[</span><span class="si">{</span><span class="n">generate</span><span class="p">([</span><span class="n">n</span><span class="p">[</span><span class="s1">&#39;value&#39;</span><span class="p">]])</span><span class="si">}</span><span class="s2">]&quot;</span><span class="p">,</span>
</span><span id="L-194"><a href="#L-194"><span class="linenos">194</span></a> <span class="s2">&quot;union&quot;</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&quot;[</span><span class="si">{</span><span class="s1">&#39;,&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">generate</span><span class="p">([</span><span class="n">p</span><span class="p">])</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">n</span><span class="p">[</span><span class="s1">&#39;value&#39;</span><span class="p">])</span><span class="si">}</span><span class="s2">]&quot;</span><span class="p">,</span>
</span><span id="L-195"><a href="#L-195"><span class="linenos">195</span></a> <span class="s2">&quot;wildcard&quot;</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">_</span><span class="p">:</span> <span class="s2">&quot;*&quot;</span><span class="p">,</span>
</span><span id="L-196"><a href="#L-196"><span class="linenos">196</span></a><span class="p">}</span>
</span><span id="L-197"><a href="#L-197"><span class="linenos">197</span></a>
</span><span id="L-198"><a href="#L-198"><span class="linenos">198</span></a>
</span><span id="L-199"><a href="#L-199"><span class="linenos">199</span></a><span class="k">def</span> <span class="nf">generate</span><span class="p">(</span>
</span><span id="L-200"><a href="#L-200"><span class="linenos">200</span></a> <span class="n">nodes</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">List</span><span class="p">[</span><span class="n">JSONPathNode</span><span class="p">],</span>
</span><span id="L-201"><a href="#L-201"><span class="linenos">201</span></a> <span class="n">mapping</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">t</span><span class="o">.</span><span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">t</span><span class="o">.</span><span class="n">Callable</span><span class="p">[[</span><span class="n">JSONPathNode</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-202"><a href="#L-202"><span class="linenos">202</span></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span><span id="L-203"><a href="#L-203"><span class="linenos">203</span></a> <span class="n">mapping</span> <span class="o">=</span> <span class="n">MAPPING</span> <span class="k">if</span> <span class="n">mapping</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">mapping</span>
</span><span id="L-204"><a href="#L-204"><span class="linenos">204</span></a> <span class="n">path</span> <span class="o">=</span> <span class="p">[]</span>
</span><span id="L-205"><a href="#L-205"><span class="linenos">205</span></a>
</span><span id="L-206"><a href="#L-206"><span class="linenos">206</span></a> <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="n">nodes</span><span class="p">:</span>
</span><span id="L-207"><a href="#L-207"><span class="linenos">207</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="nb">dict</span><span class="p">):</span>
</span><span id="L-208"><a href="#L-208"><span class="linenos">208</span></a> <span class="n">path</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">mapping</span><span class="p">[</span><span class="n">node</span><span class="p">[</span><span class="s2">&quot;kind&quot;</span><span class="p">]](</span><span class="n">node</span><span class="p">))</span>
</span><span id="L-209"><a href="#L-209"><span class="linenos">209</span></a> <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
</span><span id="L-210"><a href="#L-210"><span class="linenos">210</span></a> <span class="n">escaped</span> <span class="o">=</span> <span class="n">node</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">&#39;&quot;&#39;</span><span class="p">,</span> <span class="s1">&#39;</span><span class="se">\\</span><span class="s1">&quot;&#39;</span><span class="p">)</span>
</span><span id="L-211"><a href="#L-211"><span class="linenos">211</span></a> <span class="n">path</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;&quot;</span><span class="si">{</span><span class="n">escaped</span><span class="si">}</span><span class="s1">&quot;&#39;</span><span class="p">)</span>
</span><span id="L-212"><a href="#L-212"><span class="linenos">212</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-213"><a href="#L-213"><span class="linenos">213</span></a> <span class="n">path</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">node</span><span class="p">))</span>
</span><span id="L-214"><a href="#L-214"><span class="linenos">214</span></a>
</span><span id="L-215"><a href="#L-215"><span class="linenos">215</span></a> <span class="k">return</span> <span class="s2">&quot;&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
</span><span id="L-178"><a href="#L-178"><span class="linenos">178</span></a>
</span><span id="L-179"><a href="#L-179"><span class="linenos">179</span></a><span class="n">JSON_PATH_PART_TRANSFORMS</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Dict</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">exp</span><span class="o">.</span><span class="n">Expression</span><span class="p">],</span> <span class="n">t</span><span class="o">.</span><span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="nb">str</span><span class="p">]]</span> <span class="o">=</span> <span class="p">{</span>
</span><span id="L-180"><a href="#L-180"><span class="linenos">180</span></a> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathFilter</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">_</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&quot;?</span><span class="si">{</span><span class="n">e</span><span class="o">.</span><span class="n">this</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">,</span>
</span><span id="L-181"><a href="#L-181"><span class="linenos">181</span></a> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathKey</span><span class="p">:</span> <span class="k">lambda</span> <span class="bp">self</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_jsonpathkey_sql</span><span class="p">(</span><span class="n">e</span><span class="p">),</span>
</span><span id="L-182"><a href="#L-182"><span class="linenos">182</span></a> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathRecursive</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">_</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&quot;..</span><span class="si">{</span><span class="n">e</span><span class="o">.</span><span class="n">this</span><span class="w"> </span><span class="ow">or</span><span class="w"> </span><span class="s1">&#39;&#39;</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">,</span>
</span><span id="L-183"><a href="#L-183"><span class="linenos">183</span></a> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathRoot</span><span class="p">:</span> <span class="k">lambda</span> <span class="o">*</span><span class="n">_</span><span class="p">:</span> <span class="s2">&quot;$&quot;</span><span class="p">,</span>
</span><span id="L-184"><a href="#L-184"><span class="linenos">184</span></a> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathScript</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">_</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&quot;(</span><span class="si">{</span><span class="n">e</span><span class="o">.</span><span class="n">this</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">,</span>
</span><span id="L-185"><a href="#L-185"><span class="linenos">185</span></a> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathSelector</span><span class="p">:</span> <span class="k">lambda</span> <span class="bp">self</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&quot;[</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">json_path_part</span><span class="p">(</span><span class="n">e</span><span class="o">.</span><span class="n">this</span><span class="p">)</span><span class="si">}</span><span class="s2">]&quot;</span><span class="p">,</span>
</span><span id="L-186"><a href="#L-186"><span class="linenos">186</span></a> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathSlice</span><span class="p">:</span> <span class="k">lambda</span> <span class="bp">self</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="s2">&quot;:&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span>
</span><span id="L-187"><a href="#L-187"><span class="linenos">187</span></a> <span class="s2">&quot;&quot;</span> <span class="k">if</span> <span class="n">p</span> <span class="ow">is</span> <span class="kc">False</span> <span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">json_path_part</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
</span><span id="L-188"><a href="#L-188"><span class="linenos">188</span></a> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="p">[</span><span class="n">e</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;start&quot;</span><span class="p">),</span> <span class="n">e</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;end&quot;</span><span class="p">),</span> <span class="n">e</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;step&quot;</span><span class="p">)]</span>
</span><span id="L-189"><a href="#L-189"><span class="linenos">189</span></a> <span class="k">if</span> <span class="n">p</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
</span><span id="L-190"><a href="#L-190"><span class="linenos">190</span></a> <span class="p">),</span>
</span><span id="L-191"><a href="#L-191"><span class="linenos">191</span></a> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathSubscript</span><span class="p">:</span> <span class="k">lambda</span> <span class="bp">self</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_jsonpathsubscript_sql</span><span class="p">(</span><span class="n">e</span><span class="p">),</span>
</span><span id="L-192"><a href="#L-192"><span class="linenos">192</span></a> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathUnion</span><span class="p">:</span> <span class="k">lambda</span> <span class="bp">self</span><span class="p">,</span>
</span><span id="L-193"><a href="#L-193"><span class="linenos">193</span></a> <span class="n">e</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&quot;[</span><span class="si">{</span><span class="s1">&#39;,&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">json_path_part</span><span class="p">(</span><span class="n">p</span><span class="p">)</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">e</span><span class="o">.</span><span class="n">expressions</span><span class="p">)</span><span class="si">}</span><span class="s2">]&quot;</span><span class="p">,</span>
</span><span id="L-194"><a href="#L-194"><span class="linenos">194</span></a> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathWildcard</span><span class="p">:</span> <span class="k">lambda</span> <span class="o">*</span><span class="n">_</span><span class="p">:</span> <span class="s2">&quot;*&quot;</span><span class="p">,</span>
</span><span id="L-195"><a href="#L-195"><span class="linenos">195</span></a><span class="p">}</span>
</span><span id="L-196"><a href="#L-196"><span class="linenos">196</span></a>
</span><span id="L-197"><a href="#L-197"><span class="linenos">197</span></a><span class="n">ALL_JSON_PATH_PARTS</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span><span class="n">JSON_PATH_PART_TRANSFORMS</span><span class="p">)</span>
</span></pre></div>
@ -422,206 +401,186 @@
</div>
</dl>
</div>
</section>
<section id="JSONPathNode">
<div class="attr variable">
<span class="name">JSONPathNode</span> =
<span class="default_value">typing.Dict[str, typing.Any]</span>
</div>
<a class="headerlink" href="#JSONPathNode"></a>
</section>
<section id="parse">
<input id="parse-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
<div class="attr function">
<span class="def">def</span>
<span class="name">parse</span><span class="signature pdoc-code condensed">(<span class="param"><span class="n">path</span><span class="p">:</span> <span class="nb">str</span></span><span class="return-annotation">) -> <span class="n">List</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="n">Any</span><span class="p">]]</span>:</span></span>
<span class="name">parse</span><span class="signature pdoc-code condensed">(<span class="param"><span class="n">path</span><span class="p">:</span> <span class="nb">str</span></span><span class="return-annotation">) -> <span class="n"><a href="expressions.html#JSONPath">sqlglot.expressions.JSONPath</a></span>:</span></span>
<label class="view-source-button" for="parse-view-source"><span>View Source</span></label>
</div>
<a class="headerlink" href="#parse"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="parse-52"><a href="#parse-52"><span class="linenos"> 52</span></a><span class="k">def</span> <span class="nf">parse</span><span class="p">(</span><span class="n">path</span><span class="p">:</span> <span class="nb">str</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">JSONPathNode</span><span class="p">]:</span>
</span><span id="parse-53"><a href="#parse-53"><span class="linenos"> 53</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;Takes in a JSONPath string and converts into a list of nodes.&quot;&quot;&quot;</span>
</span><span id="parse-54"><a href="#parse-54"><span class="linenos"> 54</span></a> <span class="n">tokens</span> <span class="o">=</span> <span class="n">JSONPathTokenizer</span><span class="p">()</span><span class="o">.</span><span class="n">tokenize</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
</span><span id="parse-55"><a href="#parse-55"><span class="linenos"> 55</span></a> <span class="n">size</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">tokens</span><span class="p">)</span>
</span><span id="parse-56"><a href="#parse-56"><span class="linenos"> 56</span></a>
</span><span id="parse-57"><a href="#parse-57"><span class="linenos"> 57</span></a> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
</span><span id="parse-58"><a href="#parse-58"><span class="linenos"> 58</span></a>
</span><span id="parse-59"><a href="#parse-59"><span class="linenos"> 59</span></a> <span class="k">def</span> <span class="nf">_curr</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">TokenType</span><span class="p">]:</span>
</span><span id="parse-60"><a href="#parse-60"><span class="linenos"> 60</span></a> <span class="k">return</span> <span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">token_type</span> <span class="k">if</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">size</span> <span class="k">else</span> <span class="kc">None</span>
</span><span id="parse-61"><a href="#parse-61"><span class="linenos"> 61</span></a>
</span><span id="parse-62"><a href="#parse-62"><span class="linenos"> 62</span></a> <span class="k">def</span> <span class="nf">_prev</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">Token</span><span class="p">:</span>
</span><span id="parse-63"><a href="#parse-63"><span class="linenos"> 63</span></a> <span class="k">return</span> <span class="n">tokens</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="parse-40"><a href="#parse-40"><span class="linenos"> 40</span></a><span class="k">def</span> <span class="nf">parse</span><span class="p">(</span><span class="n">path</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPath</span><span class="p">:</span>
</span><span id="parse-41"><a href="#parse-41"><span class="linenos"> 41</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;Takes in a JSON path string and parses it into a JSONPath expression.&quot;&quot;&quot;</span>
</span><span id="parse-42"><a href="#parse-42"><span class="linenos"> 42</span></a> <span class="n">tokens</span> <span class="o">=</span> <span class="n">JSONPathTokenizer</span><span class="p">()</span><span class="o">.</span><span class="n">tokenize</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
</span><span id="parse-43"><a href="#parse-43"><span class="linenos"> 43</span></a> <span class="n">size</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">tokens</span><span class="p">)</span>
</span><span id="parse-44"><a href="#parse-44"><span class="linenos"> 44</span></a>
</span><span id="parse-45"><a href="#parse-45"><span class="linenos"> 45</span></a> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
</span><span id="parse-46"><a href="#parse-46"><span class="linenos"> 46</span></a>
</span><span id="parse-47"><a href="#parse-47"><span class="linenos"> 47</span></a> <span class="k">def</span> <span class="nf">_curr</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">TokenType</span><span class="p">]:</span>
</span><span id="parse-48"><a href="#parse-48"><span class="linenos"> 48</span></a> <span class="k">return</span> <span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">token_type</span> <span class="k">if</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">size</span> <span class="k">else</span> <span class="kc">None</span>
</span><span id="parse-49"><a href="#parse-49"><span class="linenos"> 49</span></a>
</span><span id="parse-50"><a href="#parse-50"><span class="linenos"> 50</span></a> <span class="k">def</span> <span class="nf">_prev</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">Token</span><span class="p">:</span>
</span><span id="parse-51"><a href="#parse-51"><span class="linenos"> 51</span></a> <span class="k">return</span> <span class="n">tokens</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
</span><span id="parse-52"><a href="#parse-52"><span class="linenos"> 52</span></a>
</span><span id="parse-53"><a href="#parse-53"><span class="linenos"> 53</span></a> <span class="k">def</span> <span class="nf">_advance</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">Token</span><span class="p">:</span>
</span><span id="parse-54"><a href="#parse-54"><span class="linenos"> 54</span></a> <span class="k">nonlocal</span> <span class="n">i</span>
</span><span id="parse-55"><a href="#parse-55"><span class="linenos"> 55</span></a> <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
</span><span id="parse-56"><a href="#parse-56"><span class="linenos"> 56</span></a> <span class="k">return</span> <span class="n">_prev</span><span class="p">()</span>
</span><span id="parse-57"><a href="#parse-57"><span class="linenos"> 57</span></a>
</span><span id="parse-58"><a href="#parse-58"><span class="linenos"> 58</span></a> <span class="k">def</span> <span class="nf">_error</span><span class="p">(</span><span class="n">msg</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span><span id="parse-59"><a href="#parse-59"><span class="linenos"> 59</span></a> <span class="k">return</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">msg</span><span class="si">}</span><span class="s2"> at index </span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">: </span><span class="si">{</span><span class="n">path</span><span class="si">}</span><span class="s2">&quot;</span>
</span><span id="parse-60"><a href="#parse-60"><span class="linenos"> 60</span></a>
</span><span id="parse-61"><a href="#parse-61"><span class="linenos"> 61</span></a> <span class="nd">@t</span><span class="o">.</span><span class="n">overload</span>
</span><span id="parse-62"><a href="#parse-62"><span class="linenos"> 62</span></a> <span class="k">def</span> <span class="nf">_match</span><span class="p">(</span><span class="n">token_type</span><span class="p">:</span> <span class="n">TokenType</span><span class="p">,</span> <span class="n">raise_unmatched</span><span class="p">:</span> <span class="n">Lit</span><span class="p">[</span><span class="kc">True</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Token</span><span class="p">:</span>
</span><span id="parse-63"><a href="#parse-63"><span class="linenos"> 63</span></a> <span class="k">pass</span>
</span><span id="parse-64"><a href="#parse-64"><span class="linenos"> 64</span></a>
</span><span id="parse-65"><a href="#parse-65"><span class="linenos"> 65</span></a> <span class="k">def</span> <span class="nf">_advance</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">Token</span><span class="p">:</span>
</span><span id="parse-66"><a href="#parse-66"><span class="linenos"> 66</span></a> <span class="k">nonlocal</span> <span class="n">i</span>
</span><span id="parse-67"><a href="#parse-67"><span class="linenos"> 67</span></a> <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
</span><span id="parse-68"><a href="#parse-68"><span class="linenos"> 68</span></a> <span class="k">return</span> <span class="n">_prev</span><span class="p">()</span>
</span><span id="parse-69"><a href="#parse-69"><span class="linenos"> 69</span></a>
</span><span id="parse-70"><a href="#parse-70"><span class="linenos"> 70</span></a> <span class="k">def</span> <span class="nf">_error</span><span class="p">(</span><span class="n">msg</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span><span id="parse-71"><a href="#parse-71"><span class="linenos"> 71</span></a> <span class="k">return</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">msg</span><span class="si">}</span><span class="s2"> at index </span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">: </span><span class="si">{</span><span class="n">path</span><span class="si">}</span><span class="s2">&quot;</span>
</span><span id="parse-72"><a href="#parse-72"><span class="linenos"> 72</span></a>
</span><span id="parse-73"><a href="#parse-73"><span class="linenos"> 73</span></a> <span class="nd">@t</span><span class="o">.</span><span class="n">overload</span>
</span><span id="parse-74"><a href="#parse-74"><span class="linenos"> 74</span></a> <span class="k">def</span> <span class="nf">_match</span><span class="p">(</span><span class="n">token_type</span><span class="p">:</span> <span class="n">TokenType</span><span class="p">,</span> <span class="n">raise_unmatched</span><span class="p">:</span> <span class="n">Lit</span><span class="p">[</span><span class="kc">True</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Token</span><span class="p">:</span>
</span><span id="parse-75"><a href="#parse-75"><span class="linenos"> 75</span></a> <span class="k">pass</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="nd">@t</span><span class="o">.</span><span class="n">overload</span>
</span><span id="parse-78"><a href="#parse-78"><span class="linenos"> 78</span></a> <span class="k">def</span> <span class="nf">_match</span><span class="p">(</span><span class="n">token_type</span><span class="p">:</span> <span class="n">TokenType</span><span class="p">,</span> <span class="n">raise_unmatched</span><span class="p">:</span> <span class="n">Lit</span><span class="p">[</span><span class="kc">False</span><span class="p">]</span> <span class="o">=</span> <span class="kc">False</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">Token</span><span class="p">]:</span>
</span><span id="parse-79"><a href="#parse-79"><span class="linenos"> 79</span></a> <span class="k">pass</span>
</span><span id="parse-80"><a href="#parse-80"><span class="linenos"> 80</span></a>
</span><span id="parse-81"><a href="#parse-81"><span class="linenos"> 81</span></a> <span class="k">def</span> <span class="nf">_match</span><span class="p">(</span><span class="n">token_type</span><span class="p">,</span> <span class="n">raise_unmatched</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
</span><span id="parse-82"><a href="#parse-82"><span class="linenos"> 82</span></a> <span class="k">if</span> <span class="n">_curr</span><span class="p">()</span> <span class="o">==</span> <span class="n">token_type</span><span class="p">:</span>
</span><span id="parse-83"><a href="#parse-83"><span class="linenos"> 83</span></a> <span class="k">return</span> <span class="n">_advance</span><span class="p">()</span>
</span><span id="parse-84"><a href="#parse-84"><span class="linenos"> 84</span></a> <span class="k">if</span> <span class="n">raise_unmatched</span><span class="p">:</span>
</span><span id="parse-85"><a href="#parse-85"><span class="linenos"> 85</span></a> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="n">_error</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Expected </span><span class="si">{</span><span class="n">token_type</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">))</span>
</span><span id="parse-86"><a href="#parse-86"><span class="linenos"> 86</span></a> <span class="k">return</span> <span class="kc">None</span>
</span><span id="parse-87"><a href="#parse-87"><span class="linenos"> 87</span></a>
</span><span id="parse-88"><a href="#parse-88"><span class="linenos"> 88</span></a> <span class="k">def</span> <span class="nf">_parse_literal</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">:</span>
</span><span id="parse-89"><a href="#parse-89"><span class="linenos"> 89</span></a> <span class="n">token</span> <span class="o">=</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">STRING</span><span class="p">)</span> <span class="ow">or</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">IDENTIFIER</span><span class="p">)</span>
</span><span id="parse-90"><a href="#parse-90"><span class="linenos"> 90</span></a> <span class="k">if</span> <span class="n">token</span><span class="p">:</span>
</span><span id="parse-91"><a href="#parse-91"><span class="linenos"> 91</span></a> <span class="k">return</span> <span class="n">token</span><span class="o">.</span><span class="n">text</span>
</span><span id="parse-92"><a href="#parse-92"><span class="linenos"> 92</span></a> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">STAR</span><span class="p">):</span>
</span><span id="parse-93"><a href="#parse-93"><span class="linenos"> 93</span></a> <span class="k">return</span> <span class="n">_node</span><span class="p">(</span><span class="s2">&quot;wildcard&quot;</span><span class="p">)</span>
</span><span id="parse-94"><a href="#parse-94"><span class="linenos"> 94</span></a> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">PLACEHOLDER</span><span class="p">)</span> <span class="ow">or</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">L_PAREN</span><span class="p">):</span>
</span><span id="parse-95"><a href="#parse-95"><span class="linenos"> 95</span></a> <span class="n">script</span> <span class="o">=</span> <span class="n">_prev</span><span class="p">()</span><span class="o">.</span><span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;(&quot;</span>
</span><span id="parse-96"><a href="#parse-96"><span class="linenos"> 96</span></a> <span class="n">start</span> <span class="o">=</span> <span class="n">i</span>
</span><span id="parse-65"><a href="#parse-65"><span class="linenos"> 65</span></a> <span class="nd">@t</span><span class="o">.</span><span class="n">overload</span>
</span><span id="parse-66"><a href="#parse-66"><span class="linenos"> 66</span></a> <span class="k">def</span> <span class="nf">_match</span><span class="p">(</span><span class="n">token_type</span><span class="p">:</span> <span class="n">TokenType</span><span class="p">,</span> <span class="n">raise_unmatched</span><span class="p">:</span> <span class="n">Lit</span><span class="p">[</span><span class="kc">False</span><span class="p">]</span> <span class="o">=</span> <span class="kc">False</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">Token</span><span class="p">]:</span>
</span><span id="parse-67"><a href="#parse-67"><span class="linenos"> 67</span></a> <span class="k">pass</span>
</span><span id="parse-68"><a href="#parse-68"><span class="linenos"> 68</span></a>
</span><span id="parse-69"><a href="#parse-69"><span class="linenos"> 69</span></a> <span class="k">def</span> <span class="nf">_match</span><span class="p">(</span><span class="n">token_type</span><span class="p">,</span> <span class="n">raise_unmatched</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
</span><span id="parse-70"><a href="#parse-70"><span class="linenos"> 70</span></a> <span class="k">if</span> <span class="n">_curr</span><span class="p">()</span> <span class="o">==</span> <span class="n">token_type</span><span class="p">:</span>
</span><span id="parse-71"><a href="#parse-71"><span class="linenos"> 71</span></a> <span class="k">return</span> <span class="n">_advance</span><span class="p">()</span>
</span><span id="parse-72"><a href="#parse-72"><span class="linenos"> 72</span></a> <span class="k">if</span> <span class="n">raise_unmatched</span><span class="p">:</span>
</span><span id="parse-73"><a href="#parse-73"><span class="linenos"> 73</span></a> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="n">_error</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Expected </span><span class="si">{</span><span class="n">token_type</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">))</span>
</span><span id="parse-74"><a href="#parse-74"><span class="linenos"> 74</span></a> <span class="k">return</span> <span class="kc">None</span>
</span><span id="parse-75"><a href="#parse-75"><span class="linenos"> 75</span></a>
</span><span id="parse-76"><a href="#parse-76"><span class="linenos"> 76</span></a> <span class="k">def</span> <span class="nf">_parse_literal</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">:</span>
</span><span id="parse-77"><a href="#parse-77"><span class="linenos"> 77</span></a> <span class="n">token</span> <span class="o">=</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">STRING</span><span class="p">)</span> <span class="ow">or</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">IDENTIFIER</span><span class="p">)</span>
</span><span id="parse-78"><a href="#parse-78"><span class="linenos"> 78</span></a> <span class="k">if</span> <span class="n">token</span><span class="p">:</span>
</span><span id="parse-79"><a href="#parse-79"><span class="linenos"> 79</span></a> <span class="k">return</span> <span class="n">token</span><span class="o">.</span><span class="n">text</span>
</span><span id="parse-80"><a href="#parse-80"><span class="linenos"> 80</span></a> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">STAR</span><span class="p">):</span>
</span><span id="parse-81"><a href="#parse-81"><span class="linenos"> 81</span></a> <span class="k">return</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathWildcard</span><span class="p">()</span>
</span><span id="parse-82"><a href="#parse-82"><span class="linenos"> 82</span></a> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">PLACEHOLDER</span><span class="p">)</span> <span class="ow">or</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">L_PAREN</span><span class="p">):</span>
</span><span id="parse-83"><a href="#parse-83"><span class="linenos"> 83</span></a> <span class="n">script</span> <span class="o">=</span> <span class="n">_prev</span><span class="p">()</span><span class="o">.</span><span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;(&quot;</span>
</span><span id="parse-84"><a href="#parse-84"><span class="linenos"> 84</span></a> <span class="n">start</span> <span class="o">=</span> <span class="n">i</span>
</span><span id="parse-85"><a href="#parse-85"><span class="linenos"> 85</span></a>
</span><span id="parse-86"><a href="#parse-86"><span class="linenos"> 86</span></a> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
</span><span id="parse-87"><a href="#parse-87"><span class="linenos"> 87</span></a> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">L_BRACKET</span><span class="p">):</span>
</span><span id="parse-88"><a href="#parse-88"><span class="linenos"> 88</span></a> <span class="n">_parse_bracket</span><span class="p">()</span> <span class="c1"># nested call which we can throw away</span>
</span><span id="parse-89"><a href="#parse-89"><span class="linenos"> 89</span></a> <span class="k">if</span> <span class="n">_curr</span><span class="p">()</span> <span class="ow">in</span> <span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">R_BRACKET</span><span class="p">,</span> <span class="kc">None</span><span class="p">):</span>
</span><span id="parse-90"><a href="#parse-90"><span class="linenos"> 90</span></a> <span class="k">break</span>
</span><span id="parse-91"><a href="#parse-91"><span class="linenos"> 91</span></a> <span class="n">_advance</span><span class="p">()</span>
</span><span id="parse-92"><a href="#parse-92"><span class="linenos"> 92</span></a>
</span><span id="parse-93"><a href="#parse-93"><span class="linenos"> 93</span></a> <span class="n">expr_type</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathScript</span> <span class="k">if</span> <span class="n">script</span> <span class="k">else</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathFilter</span>
</span><span id="parse-94"><a href="#parse-94"><span class="linenos"> 94</span></a> <span class="k">return</span> <span class="n">expr_type</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">path</span><span class="p">[</span><span class="n">tokens</span><span class="p">[</span><span class="n">start</span><span class="p">]</span><span class="o">.</span><span class="n">start</span> <span class="p">:</span> <span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">end</span><span class="p">])</span>
</span><span id="parse-95"><a href="#parse-95"><span class="linenos"> 95</span></a>
</span><span id="parse-96"><a href="#parse-96"><span class="linenos"> 96</span></a> <span class="n">number</span> <span class="o">=</span> <span class="s2">&quot;-&quot;</span> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">DASH</span><span class="p">)</span> <span class="k">else</span> <span class="s2">&quot;&quot;</span>
</span><span id="parse-97"><a href="#parse-97"><span class="linenos"> 97</span></a>
</span><span id="parse-98"><a href="#parse-98"><span class="linenos"> 98</span></a> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
</span><span id="parse-99"><a href="#parse-99"><span class="linenos"> 99</span></a> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">L_BRACKET</span><span class="p">):</span>
</span><span id="parse-100"><a href="#parse-100"><span class="linenos">100</span></a> <span class="n">_parse_bracket</span><span class="p">()</span> <span class="c1"># nested call which we can throw away</span>
</span><span id="parse-101"><a href="#parse-101"><span class="linenos">101</span></a> <span class="k">if</span> <span class="n">_curr</span><span class="p">()</span> <span class="ow">in</span> <span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">R_BRACKET</span><span class="p">,</span> <span class="kc">None</span><span class="p">):</span>
</span><span id="parse-102"><a href="#parse-102"><span class="linenos">102</span></a> <span class="k">break</span>
</span><span id="parse-103"><a href="#parse-103"><span class="linenos">103</span></a> <span class="n">_advance</span><span class="p">()</span>
</span><span id="parse-104"><a href="#parse-104"><span class="linenos">104</span></a> <span class="k">return</span> <span class="n">_node</span><span class="p">(</span>
</span><span id="parse-105"><a href="#parse-105"><span class="linenos">105</span></a> <span class="s2">&quot;script&quot;</span> <span class="k">if</span> <span class="n">script</span> <span class="k">else</span> <span class="s2">&quot;filter&quot;</span><span class="p">,</span> <span class="n">path</span><span class="p">[</span><span class="n">tokens</span><span class="p">[</span><span class="n">start</span><span class="p">]</span><span class="o">.</span><span class="n">start</span> <span class="p">:</span> <span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">end</span><span class="p">]</span>
</span><span id="parse-106"><a href="#parse-106"><span class="linenos">106</span></a> <span class="p">)</span>
</span><span id="parse-107"><a href="#parse-107"><span class="linenos">107</span></a>
</span><span id="parse-108"><a href="#parse-108"><span class="linenos">108</span></a> <span class="n">number</span> <span class="o">=</span> <span class="s2">&quot;-&quot;</span> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">DASH</span><span class="p">)</span> <span class="k">else</span> <span class="s2">&quot;&quot;</span>
</span><span id="parse-109"><a href="#parse-109"><span class="linenos">109</span></a>
</span><span id="parse-110"><a href="#parse-110"><span class="linenos">110</span></a> <span class="n">token</span> <span class="o">=</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">NUMBER</span><span class="p">)</span>
</span><span id="parse-111"><a href="#parse-111"><span class="linenos">111</span></a> <span class="k">if</span> <span class="n">token</span><span class="p">:</span>
</span><span id="parse-112"><a href="#parse-112"><span class="linenos">112</span></a> <span class="n">number</span> <span class="o">+=</span> <span class="n">token</span><span class="o">.</span><span class="n">text</span>
</span><span id="parse-113"><a href="#parse-113"><span class="linenos">113</span></a>
</span><span id="parse-114"><a href="#parse-114"><span class="linenos">114</span></a> <span class="k">if</span> <span class="n">number</span><span class="p">:</span>
</span><span id="parse-115"><a href="#parse-115"><span class="linenos">115</span></a> <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">number</span><span class="p">)</span>
</span><span id="parse-116"><a href="#parse-116"><span class="linenos">116</span></a> <span class="k">return</span> <span class="kc">False</span>
</span><span id="parse-117"><a href="#parse-117"><span class="linenos">117</span></a>
</span><span id="parse-118"><a href="#parse-118"><span class="linenos">118</span></a> <span class="k">def</span> <span class="nf">_parse_slice</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">:</span>
</span><span id="parse-119"><a href="#parse-119"><span class="linenos">119</span></a> <span class="n">start</span> <span class="o">=</span> <span class="n">_parse_literal</span><span class="p">()</span>
</span><span id="parse-120"><a href="#parse-120"><span class="linenos">120</span></a> <span class="n">end</span> <span class="o">=</span> <span class="n">_parse_literal</span><span class="p">()</span> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">COLON</span><span class="p">)</span> <span class="k">else</span> <span class="kc">None</span>
</span><span id="parse-121"><a href="#parse-121"><span class="linenos">121</span></a> <span class="n">step</span> <span class="o">=</span> <span class="n">_parse_literal</span><span class="p">()</span> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">COLON</span><span class="p">)</span> <span class="k">else</span> <span class="kc">None</span>
</span><span id="parse-122"><a href="#parse-122"><span class="linenos">122</span></a>
</span><span id="parse-123"><a href="#parse-123"><span class="linenos">123</span></a> <span class="k">if</span> <span class="n">end</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">step</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="parse-124"><a href="#parse-124"><span class="linenos">124</span></a> <span class="k">return</span> <span class="n">start</span>
</span><span id="parse-125"><a href="#parse-125"><span class="linenos">125</span></a> <span class="k">return</span> <span class="n">_node</span><span class="p">(</span><span class="s2">&quot;slice&quot;</span><span class="p">,</span> <span class="n">start</span><span class="o">=</span><span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="n">end</span><span class="p">,</span> <span class="n">step</span><span class="o">=</span><span class="n">step</span><span class="p">)</span>
</span><span id="parse-126"><a href="#parse-126"><span class="linenos">126</span></a>
</span><span id="parse-127"><a href="#parse-127"><span class="linenos">127</span></a> <span class="k">def</span> <span class="nf">_parse_bracket</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">JSONPathNode</span><span class="p">:</span>
</span><span id="parse-128"><a href="#parse-128"><span class="linenos">128</span></a> <span class="n">literal</span> <span class="o">=</span> <span class="n">_parse_slice</span><span class="p">()</span>
</span><span id="parse-129"><a href="#parse-129"><span class="linenos">129</span></a>
</span><span id="parse-130"><a href="#parse-130"><span class="linenos">130</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">literal</span><span class="p">,</span> <span class="nb">str</span><span class="p">)</span> <span class="ow">or</span> <span class="n">literal</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">False</span><span class="p">:</span>
</span><span id="parse-131"><a href="#parse-131"><span class="linenos">131</span></a> <span class="n">indexes</span> <span class="o">=</span> <span class="p">[</span><span class="n">literal</span><span class="p">]</span>
</span><span id="parse-132"><a href="#parse-132"><span class="linenos">132</span></a> <span class="k">while</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">COMMA</span><span class="p">):</span>
</span><span id="parse-133"><a href="#parse-133"><span class="linenos">133</span></a> <span class="n">literal</span> <span class="o">=</span> <span class="n">_parse_slice</span><span class="p">()</span>
</span><span id="parse-134"><a href="#parse-134"><span class="linenos">134</span></a>
</span><span id="parse-135"><a href="#parse-135"><span class="linenos">135</span></a> <span class="k">if</span> <span class="n">literal</span><span class="p">:</span>
</span><span id="parse-136"><a href="#parse-136"><span class="linenos">136</span></a> <span class="n">indexes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">literal</span><span class="p">)</span>
</span><span id="parse-137"><a href="#parse-137"><span class="linenos">137</span></a>
</span><span id="parse-138"><a href="#parse-138"><span class="linenos">138</span></a> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">indexes</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
</span><span id="parse-139"><a href="#parse-139"><span class="linenos">139</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">literal</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
</span><span id="parse-140"><a href="#parse-140"><span class="linenos">140</span></a> <span class="n">node</span> <span class="o">=</span> <span class="n">_node</span><span class="p">(</span><span class="s2">&quot;key&quot;</span><span class="p">,</span> <span class="n">indexes</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
</span><span id="parse-141"><a href="#parse-141"><span class="linenos">141</span></a> <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">literal</span><span class="p">,</span> <span class="nb">dict</span><span class="p">)</span> <span class="ow">and</span> <span class="n">literal</span><span class="p">[</span><span class="s2">&quot;kind&quot;</span><span class="p">]</span> <span class="ow">in</span> <span class="p">(</span><span class="s2">&quot;script&quot;</span><span class="p">,</span> <span class="s2">&quot;filter&quot;</span><span class="p">):</span>
</span><span id="parse-142"><a href="#parse-142"><span class="linenos">142</span></a> <span class="n">node</span> <span class="o">=</span> <span class="n">_node</span><span class="p">(</span><span class="s2">&quot;selector&quot;</span><span class="p">,</span> <span class="n">indexes</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
</span><span id="parse-143"><a href="#parse-143"><span class="linenos">143</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="parse-144"><a href="#parse-144"><span class="linenos">144</span></a> <span class="n">node</span> <span class="o">=</span> <span class="n">_node</span><span class="p">(</span><span class="s2">&quot;subscript&quot;</span><span class="p">,</span> <span class="n">indexes</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
</span><span id="parse-145"><a href="#parse-145"><span class="linenos">145</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="parse-146"><a href="#parse-146"><span class="linenos">146</span></a> <span class="n">node</span> <span class="o">=</span> <span class="n">_node</span><span class="p">(</span><span class="s2">&quot;union&quot;</span><span class="p">,</span> <span class="n">indexes</span><span class="p">)</span>
</span><span id="parse-147"><a href="#parse-147"><span class="linenos">147</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="parse-148"><a href="#parse-148"><span class="linenos">148</span></a> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="n">_error</span><span class="p">(</span><span class="s2">&quot;Cannot have empty segment&quot;</span><span class="p">))</span>
</span><span id="parse-149"><a href="#parse-149"><span class="linenos">149</span></a>
</span><span id="parse-150"><a href="#parse-150"><span class="linenos">150</span></a> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">R_BRACKET</span><span class="p">,</span> <span class="n">raise_unmatched</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="parse-151"><a href="#parse-151"><span class="linenos">151</span></a>
</span><span id="parse-152"><a href="#parse-152"><span class="linenos">152</span></a> <span class="k">return</span> <span class="n">node</span>
</span><span id="parse-153"><a href="#parse-153"><span class="linenos">153</span></a>
</span><span id="parse-154"><a href="#parse-154"><span class="linenos">154</span></a> <span class="n">nodes</span> <span class="o">=</span> <span class="p">[]</span>
</span><span id="parse-155"><a href="#parse-155"><span class="linenos">155</span></a>
</span><span id="parse-156"><a href="#parse-156"><span class="linenos">156</span></a> <span class="k">while</span> <span class="n">_curr</span><span class="p">():</span>
</span><span id="parse-157"><a href="#parse-157"><span class="linenos">157</span></a> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">DOLLAR</span><span class="p">):</span>
</span><span id="parse-158"><a href="#parse-158"><span class="linenos">158</span></a> <span class="n">nodes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">_node</span><span class="p">(</span><span class="s2">&quot;root&quot;</span><span class="p">))</span>
</span><span id="parse-159"><a href="#parse-159"><span class="linenos">159</span></a> <span class="k">elif</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">DOT</span><span class="p">):</span>
</span><span id="parse-160"><a href="#parse-160"><span class="linenos">160</span></a> <span class="n">recursive</span> <span class="o">=</span> <span class="n">_prev</span><span class="p">()</span><span class="o">.</span><span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;..&quot;</span>
</span><span id="parse-161"><a href="#parse-161"><span class="linenos">161</span></a> <span class="n">value</span> <span class="o">=</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">VAR</span><span class="p">)</span> <span class="ow">or</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">STAR</span><span class="p">)</span>
</span><span id="parse-162"><a href="#parse-162"><span class="linenos">162</span></a> <span class="n">nodes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
</span><span id="parse-163"><a href="#parse-163"><span class="linenos">163</span></a> <span class="n">_node</span><span class="p">(</span><span class="s2">&quot;recursive&quot;</span> <span class="k">if</span> <span class="n">recursive</span> <span class="k">else</span> <span class="s2">&quot;child&quot;</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="n">value</span><span class="o">.</span><span class="n">text</span> <span class="k">if</span> <span class="n">value</span> <span class="k">else</span> <span class="kc">None</span><span class="p">)</span>
</span><span id="parse-164"><a href="#parse-164"><span class="linenos">164</span></a> <span class="p">)</span>
</span><span id="parse-165"><a href="#parse-165"><span class="linenos">165</span></a> <span class="k">elif</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">L_BRACKET</span><span class="p">):</span>
</span><span id="parse-166"><a href="#parse-166"><span class="linenos">166</span></a> <span class="n">nodes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">_parse_bracket</span><span class="p">())</span>
</span><span id="parse-167"><a href="#parse-167"><span class="linenos">167</span></a> <span class="k">elif</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">VAR</span><span class="p">):</span>
</span><span id="parse-168"><a href="#parse-168"><span class="linenos">168</span></a> <span class="n">nodes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">_node</span><span class="p">(</span><span class="s2">&quot;key&quot;</span><span class="p">,</span> <span class="n">_prev</span><span class="p">()</span><span class="o">.</span><span class="n">text</span><span class="p">))</span>
</span><span id="parse-169"><a href="#parse-169"><span class="linenos">169</span></a> <span class="k">elif</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">STAR</span><span class="p">):</span>
</span><span id="parse-170"><a href="#parse-170"><span class="linenos">170</span></a> <span class="n">nodes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">_node</span><span class="p">(</span><span class="s2">&quot;wildcard&quot;</span><span class="p">))</span>
</span><span id="parse-171"><a href="#parse-171"><span class="linenos">171</span></a> <span class="k">elif</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">PARAMETER</span><span class="p">):</span>
</span><span id="parse-172"><a href="#parse-172"><span class="linenos">172</span></a> <span class="n">nodes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">_node</span><span class="p">(</span><span class="s2">&quot;current&quot;</span><span class="p">))</span>
</span><span id="parse-173"><a href="#parse-173"><span class="linenos">173</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="parse-174"><a href="#parse-174"><span class="linenos">174</span></a> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="n">_error</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Unexpected </span><span class="si">{</span><span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">token_type</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">))</span>
</span><span id="parse-175"><a href="#parse-175"><span class="linenos">175</span></a>
</span><span id="parse-176"><a href="#parse-176"><span class="linenos">176</span></a> <span class="k">return</span> <span class="n">nodes</span>
</span><span id="parse-98"><a href="#parse-98"><span class="linenos"> 98</span></a> <span class="n">token</span> <span class="o">=</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">NUMBER</span><span class="p">)</span>
</span><span id="parse-99"><a href="#parse-99"><span class="linenos"> 99</span></a> <span class="k">if</span> <span class="n">token</span><span class="p">:</span>
</span><span id="parse-100"><a href="#parse-100"><span class="linenos">100</span></a> <span class="n">number</span> <span class="o">+=</span> <span class="n">token</span><span class="o">.</span><span class="n">text</span>
</span><span id="parse-101"><a href="#parse-101"><span class="linenos">101</span></a>
</span><span id="parse-102"><a href="#parse-102"><span class="linenos">102</span></a> <span class="k">if</span> <span class="n">number</span><span class="p">:</span>
</span><span id="parse-103"><a href="#parse-103"><span class="linenos">103</span></a> <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">number</span><span class="p">)</span>
</span><span id="parse-104"><a href="#parse-104"><span class="linenos">104</span></a>
</span><span id="parse-105"><a href="#parse-105"><span class="linenos">105</span></a> <span class="k">return</span> <span class="kc">False</span>
</span><span id="parse-106"><a href="#parse-106"><span class="linenos">106</span></a>
</span><span id="parse-107"><a href="#parse-107"><span class="linenos">107</span></a> <span class="k">def</span> <span class="nf">_parse_slice</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">t</span><span class="o">.</span><span class="n">Any</span><span class="p">:</span>
</span><span id="parse-108"><a href="#parse-108"><span class="linenos">108</span></a> <span class="n">start</span> <span class="o">=</span> <span class="n">_parse_literal</span><span class="p">()</span>
</span><span id="parse-109"><a href="#parse-109"><span class="linenos">109</span></a> <span class="n">end</span> <span class="o">=</span> <span class="n">_parse_literal</span><span class="p">()</span> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">COLON</span><span class="p">)</span> <span class="k">else</span> <span class="kc">None</span>
</span><span id="parse-110"><a href="#parse-110"><span class="linenos">110</span></a> <span class="n">step</span> <span class="o">=</span> <span class="n">_parse_literal</span><span class="p">()</span> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">COLON</span><span class="p">)</span> <span class="k">else</span> <span class="kc">None</span>
</span><span id="parse-111"><a href="#parse-111"><span class="linenos">111</span></a>
</span><span id="parse-112"><a href="#parse-112"><span class="linenos">112</span></a> <span class="k">if</span> <span class="n">end</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">step</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="parse-113"><a href="#parse-113"><span class="linenos">113</span></a> <span class="k">return</span> <span class="n">start</span>
</span><span id="parse-114"><a href="#parse-114"><span class="linenos">114</span></a>
</span><span id="parse-115"><a href="#parse-115"><span class="linenos">115</span></a> <span class="k">return</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathSlice</span><span class="p">(</span><span class="n">start</span><span class="o">=</span><span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="n">end</span><span class="p">,</span> <span class="n">step</span><span class="o">=</span><span class="n">step</span><span class="p">)</span>
</span><span id="parse-116"><a href="#parse-116"><span class="linenos">116</span></a>
</span><span id="parse-117"><a href="#parse-117"><span class="linenos">117</span></a> <span class="k">def</span> <span class="nf">_parse_bracket</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathPart</span><span class="p">:</span>
</span><span id="parse-118"><a href="#parse-118"><span class="linenos">118</span></a> <span class="n">literal</span> <span class="o">=</span> <span class="n">_parse_slice</span><span class="p">()</span>
</span><span id="parse-119"><a href="#parse-119"><span class="linenos">119</span></a>
</span><span id="parse-120"><a href="#parse-120"><span class="linenos">120</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">literal</span><span class="p">,</span> <span class="nb">str</span><span class="p">)</span> <span class="ow">or</span> <span class="n">literal</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">False</span><span class="p">:</span>
</span><span id="parse-121"><a href="#parse-121"><span class="linenos">121</span></a> <span class="n">indexes</span> <span class="o">=</span> <span class="p">[</span><span class="n">literal</span><span class="p">]</span>
</span><span id="parse-122"><a href="#parse-122"><span class="linenos">122</span></a> <span class="k">while</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">COMMA</span><span class="p">):</span>
</span><span id="parse-123"><a href="#parse-123"><span class="linenos">123</span></a> <span class="n">literal</span> <span class="o">=</span> <span class="n">_parse_slice</span><span class="p">()</span>
</span><span id="parse-124"><a href="#parse-124"><span class="linenos">124</span></a>
</span><span id="parse-125"><a href="#parse-125"><span class="linenos">125</span></a> <span class="k">if</span> <span class="n">literal</span><span class="p">:</span>
</span><span id="parse-126"><a href="#parse-126"><span class="linenos">126</span></a> <span class="n">indexes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">literal</span><span class="p">)</span>
</span><span id="parse-127"><a href="#parse-127"><span class="linenos">127</span></a>
</span><span id="parse-128"><a href="#parse-128"><span class="linenos">128</span></a> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">indexes</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
</span><span id="parse-129"><a href="#parse-129"><span class="linenos">129</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">literal</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
</span><span id="parse-130"><a href="#parse-130"><span class="linenos">130</span></a> <span class="n">node</span><span class="p">:</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathPart</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathKey</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">indexes</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
</span><span id="parse-131"><a href="#parse-131"><span class="linenos">131</span></a> <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">literal</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathPart</span><span class="p">)</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span>
</span><span id="parse-132"><a href="#parse-132"><span class="linenos">132</span></a> <span class="n">literal</span><span class="p">,</span> <span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">JSONPathScript</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathFilter</span><span class="p">)</span>
</span><span id="parse-133"><a href="#parse-133"><span class="linenos">133</span></a> <span class="p">):</span>
</span><span id="parse-134"><a href="#parse-134"><span class="linenos">134</span></a> <span class="n">node</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathSelector</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">indexes</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
</span><span id="parse-135"><a href="#parse-135"><span class="linenos">135</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="parse-136"><a href="#parse-136"><span class="linenos">136</span></a> <span class="n">node</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathSubscript</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">indexes</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
</span><span id="parse-137"><a href="#parse-137"><span class="linenos">137</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="parse-138"><a href="#parse-138"><span class="linenos">138</span></a> <span class="n">node</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathUnion</span><span class="p">(</span><span class="n">expressions</span><span class="o">=</span><span class="n">indexes</span><span class="p">)</span>
</span><span id="parse-139"><a href="#parse-139"><span class="linenos">139</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="parse-140"><a href="#parse-140"><span class="linenos">140</span></a> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="n">_error</span><span class="p">(</span><span class="s2">&quot;Cannot have empty segment&quot;</span><span class="p">))</span>
</span><span id="parse-141"><a href="#parse-141"><span class="linenos">141</span></a>
</span><span id="parse-142"><a href="#parse-142"><span class="linenos">142</span></a> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">R_BRACKET</span><span class="p">,</span> <span class="n">raise_unmatched</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="parse-143"><a href="#parse-143"><span class="linenos">143</span></a>
</span><span id="parse-144"><a href="#parse-144"><span class="linenos">144</span></a> <span class="k">return</span> <span class="n">node</span>
</span><span id="parse-145"><a href="#parse-145"><span class="linenos">145</span></a>
</span><span id="parse-146"><a href="#parse-146"><span class="linenos">146</span></a> <span class="c1"># We canonicalize the JSON path AST so that it always starts with a</span>
</span><span id="parse-147"><a href="#parse-147"><span class="linenos">147</span></a> <span class="c1"># &quot;root&quot; element, so paths like &quot;field&quot; will be generated as &quot;$.field&quot;</span>
</span><span id="parse-148"><a href="#parse-148"><span class="linenos">148</span></a> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">DOLLAR</span><span class="p">)</span>
</span><span id="parse-149"><a href="#parse-149"><span class="linenos">149</span></a> <span class="n">expressions</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">List</span><span class="p">[</span><span class="n">exp</span><span class="o">.</span><span class="n">JSONPathPart</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">exp</span><span class="o">.</span><span class="n">JSONPathRoot</span><span class="p">()]</span>
</span><span id="parse-150"><a href="#parse-150"><span class="linenos">150</span></a>
</span><span id="parse-151"><a href="#parse-151"><span class="linenos">151</span></a> <span class="k">while</span> <span class="n">_curr</span><span class="p">():</span>
</span><span id="parse-152"><a href="#parse-152"><span class="linenos">152</span></a> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">DOT</span><span class="p">)</span> <span class="ow">or</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">COLON</span><span class="p">):</span>
</span><span id="parse-153"><a href="#parse-153"><span class="linenos">153</span></a> <span class="n">recursive</span> <span class="o">=</span> <span class="n">_prev</span><span class="p">()</span><span class="o">.</span><span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;..&quot;</span>
</span><span id="parse-154"><a href="#parse-154"><span class="linenos">154</span></a>
</span><span id="parse-155"><a href="#parse-155"><span class="linenos">155</span></a> <span class="k">if</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">VAR</span><span class="p">)</span> <span class="ow">or</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">IDENTIFIER</span><span class="p">):</span>
</span><span id="parse-156"><a href="#parse-156"><span class="linenos">156</span></a> <span class="n">value</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="o">|</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathWildcard</span><span class="p">]</span> <span class="o">=</span> <span class="n">_prev</span><span class="p">()</span><span class="o">.</span><span class="n">text</span>
</span><span id="parse-157"><a href="#parse-157"><span class="linenos">157</span></a> <span class="k">elif</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">STAR</span><span class="p">):</span>
</span><span id="parse-158"><a href="#parse-158"><span class="linenos">158</span></a> <span class="n">value</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPathWildcard</span><span class="p">()</span>
</span><span id="parse-159"><a href="#parse-159"><span class="linenos">159</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="parse-160"><a href="#parse-160"><span class="linenos">160</span></a> <span class="n">value</span> <span class="o">=</span> <span class="kc">None</span>
</span><span id="parse-161"><a href="#parse-161"><span class="linenos">161</span></a>
</span><span id="parse-162"><a href="#parse-162"><span class="linenos">162</span></a> <span class="k">if</span> <span class="n">recursive</span><span class="p">:</span>
</span><span id="parse-163"><a href="#parse-163"><span class="linenos">163</span></a> <span class="n">expressions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">JSONPathRecursive</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">value</span><span class="p">))</span>
</span><span id="parse-164"><a href="#parse-164"><span class="linenos">164</span></a> <span class="k">elif</span> <span class="n">value</span><span class="p">:</span>
</span><span id="parse-165"><a href="#parse-165"><span class="linenos">165</span></a> <span class="n">expressions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">JSONPathKey</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">value</span><span class="p">))</span>
</span><span id="parse-166"><a href="#parse-166"><span class="linenos">166</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="parse-167"><a href="#parse-167"><span class="linenos">167</span></a> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="n">_error</span><span class="p">(</span><span class="s2">&quot;Expected key name or * after DOT&quot;</span><span class="p">))</span>
</span><span id="parse-168"><a href="#parse-168"><span class="linenos">168</span></a> <span class="k">elif</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">L_BRACKET</span><span class="p">):</span>
</span><span id="parse-169"><a href="#parse-169"><span class="linenos">169</span></a> <span class="n">expressions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">_parse_bracket</span><span class="p">())</span>
</span><span id="parse-170"><a href="#parse-170"><span class="linenos">170</span></a> <span class="k">elif</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">VAR</span><span class="p">)</span> <span class="ow">or</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">IDENTIFIER</span><span class="p">):</span>
</span><span id="parse-171"><a href="#parse-171"><span class="linenos">171</span></a> <span class="n">expressions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">JSONPathKey</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">_prev</span><span class="p">()</span><span class="o">.</span><span class="n">text</span><span class="p">))</span>
</span><span id="parse-172"><a href="#parse-172"><span class="linenos">172</span></a> <span class="k">elif</span> <span class="n">_match</span><span class="p">(</span><span class="n">TokenType</span><span class="o">.</span><span class="n">STAR</span><span class="p">):</span>
</span><span id="parse-173"><a href="#parse-173"><span class="linenos">173</span></a> <span class="n">expressions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">JSONPathWildcard</span><span class="p">())</span>
</span><span id="parse-174"><a href="#parse-174"><span class="linenos">174</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="parse-175"><a href="#parse-175"><span class="linenos">175</span></a> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="n">_error</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Unexpected </span><span class="si">{</span><span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">token_type</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">))</span>
</span><span id="parse-176"><a href="#parse-176"><span class="linenos">176</span></a>
</span><span id="parse-177"><a href="#parse-177"><span class="linenos">177</span></a> <span class="k">return</span> <span class="n">exp</span><span class="o">.</span><span class="n">JSONPath</span><span class="p">(</span><span class="n">expressions</span><span class="o">=</span><span class="n">expressions</span><span class="p">)</span>
</span></pre></div>
<div class="docstring"><p>Takes in a JSONPath string and converts into a list of nodes.</p>
<div class="docstring"><p>Takes in a JSON path string and parses it into a JSONPath expression.</p>
</div>
</section>
<section id="MAPPING">
<section id="JSON_PATH_PART_TRANSFORMS">
<div class="attr variable">
<span class="name">MAPPING</span> =
<input id="MAPPING-view-value" class="view-value-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
<label class="view-value-button pdoc-button" for="MAPPING-view-value"></label><span class="default_value">{&#39;child&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;filter&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;key&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;recursive&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;root&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;script&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;slice&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;selector&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;subscript&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;union&#39;: &lt;function &lt;lambda&gt;&gt;, &#39;wildcard&#39;: &lt;function &lt;lambda&gt;&gt;}</span>
<span class="name">JSON_PATH_PART_TRANSFORMS</span><span class="annotation">: Dict[Type[<a href="expressions.html#Expression">sqlglot.expressions.Expression</a>], Callable[..., str]]</span> =
<input id="JSON_PATH_PART_TRANSFORMS-view-value" class="view-value-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
<label class="view-value-button pdoc-button" for="JSON_PATH_PART_TRANSFORMS-view-value"></label><span class="default_value">{&lt;class &#39;<a href="expressions.html#JSONPathFilter">sqlglot.expressions.JSONPathFilter</a>&#39;&gt;: &lt;function &lt;lambda&gt;&gt;, &lt;class &#39;<a href="expressions.html#JSONPathKey">sqlglot.expressions.JSONPathKey</a>&#39;&gt;: &lt;function &lt;lambda&gt;&gt;, &lt;class &#39;<a href="expressions.html#JSONPathRecursive">sqlglot.expressions.JSONPathRecursive</a>&#39;&gt;: &lt;function &lt;lambda&gt;&gt;, &lt;class &#39;<a href="expressions.html#JSONPathRoot">sqlglot.expressions.JSONPathRoot</a>&#39;&gt;: &lt;function &lt;lambda&gt;&gt;, &lt;class &#39;<a href="expressions.html#JSONPathScript">sqlglot.expressions.JSONPathScript</a>&#39;&gt;: &lt;function &lt;lambda&gt;&gt;, &lt;class &#39;<a href="expressions.html#JSONPathSelector">sqlglot.expressions.JSONPathSelector</a>&#39;&gt;: &lt;function &lt;lambda&gt;&gt;, &lt;class &#39;<a href="expressions.html#JSONPathSlice">sqlglot.expressions.JSONPathSlice</a>&#39;&gt;: &lt;function &lt;lambda&gt;&gt;, &lt;class &#39;<a href="expressions.html#JSONPathSubscript">sqlglot.expressions.JSONPathSubscript</a>&#39;&gt;: &lt;function &lt;lambda&gt;&gt;, &lt;class &#39;<a href="expressions.html#JSONPathUnion">sqlglot.expressions.JSONPathUnion</a>&#39;&gt;: &lt;function &lt;lambda&gt;&gt;, &lt;class &#39;<a href="expressions.html#JSONPathWildcard">sqlglot.expressions.JSONPathWildcard</a>&#39;&gt;: &lt;function &lt;lambda&gt;&gt;}</span>
</div>
<a class="headerlink" href="#MAPPING"></a>
<a class="headerlink" href="#JSON_PATH_PART_TRANSFORMS"></a>
</section>
<section id="generate">
<input id="generate-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
<div class="attr function">
<section id="ALL_JSON_PATH_PARTS">
<div class="attr variable">
<span class="name">ALL_JSON_PATH_PARTS</span> =
<input id="ALL_JSON_PATH_PARTS-view-value" class="view-value-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
<label class="view-value-button pdoc-button" for="ALL_JSON_PATH_PARTS-view-value"></label><span class="default_value">{&lt;class &#39;<a href="expressions.html#JSONPathScript">sqlglot.expressions.JSONPathScript</a>&#39;&gt;, &lt;class &#39;<a href="expressions.html#JSONPathRoot">sqlglot.expressions.JSONPathRoot</a>&#39;&gt;, &lt;class &#39;<a href="expressions.html#JSONPathRecursive">sqlglot.expressions.JSONPathRecursive</a>&#39;&gt;, &lt;class &#39;<a href="expressions.html#JSONPathKey">sqlglot.expressions.JSONPathKey</a>&#39;&gt;, &lt;class &#39;<a href="expressions.html#JSONPathWildcard">sqlglot.expressions.JSONPathWildcard</a>&#39;&gt;, &lt;class &#39;<a href="expressions.html#JSONPathFilter">sqlglot.expressions.JSONPathFilter</a>&#39;&gt;, &lt;class &#39;<a href="expressions.html#JSONPathUnion">sqlglot.expressions.JSONPathUnion</a>&#39;&gt;, &lt;class &#39;<a href="expressions.html#JSONPathSubscript">sqlglot.expressions.JSONPathSubscript</a>&#39;&gt;, &lt;class &#39;<a href="expressions.html#JSONPathSelector">sqlglot.expressions.JSONPathSelector</a>&#39;&gt;, &lt;class &#39;<a href="expressions.html#JSONPathSlice">sqlglot.expressions.JSONPathSlice</a>&#39;&gt;}</span>
<span class="def">def</span>
<span class="name">generate</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="n">nodes</span><span class="p">:</span> <span class="n">List</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="n">Any</span><span class="p">]]</span>,</span><span class="param"> <span class="n">mapping</span><span class="p">:</span> <span class="n">Optional</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="n">Callable</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="n">Any</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="return-annotation">) -> <span class="nb">str</span>:</span></span>
<label class="view-source-button" for="generate-view-source"><span>View Source</span></label>
</div>
<a class="headerlink" href="#generate"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="generate-200"><a href="#generate-200"><span class="linenos">200</span></a><span class="k">def</span> <span class="nf">generate</span><span class="p">(</span>
</span><span id="generate-201"><a href="#generate-201"><span class="linenos">201</span></a> <span class="n">nodes</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">List</span><span class="p">[</span><span class="n">JSONPathNode</span><span class="p">],</span>
</span><span id="generate-202"><a href="#generate-202"><span class="linenos">202</span></a> <span class="n">mapping</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">t</span><span class="o">.</span><span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">t</span><span class="o">.</span><span class="n">Callable</span><span class="p">[[</span><span class="n">JSONPathNode</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="generate-203"><a href="#generate-203"><span class="linenos">203</span></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span><span id="generate-204"><a href="#generate-204"><span class="linenos">204</span></a> <span class="n">mapping</span> <span class="o">=</span> <span class="n">MAPPING</span> <span class="k">if</span> <span class="n">mapping</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">mapping</span>
</span><span id="generate-205"><a href="#generate-205"><span class="linenos">205</span></a> <span class="n">path</span> <span class="o">=</span> <span class="p">[]</span>
</span><span id="generate-206"><a href="#generate-206"><span class="linenos">206</span></a>
</span><span id="generate-207"><a href="#generate-207"><span class="linenos">207</span></a> <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="n">nodes</span><span class="p">:</span>
</span><span id="generate-208"><a href="#generate-208"><span class="linenos">208</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="nb">dict</span><span class="p">):</span>
</span><span id="generate-209"><a href="#generate-209"><span class="linenos">209</span></a> <span class="n">path</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">mapping</span><span class="p">[</span><span class="n">node</span><span class="p">[</span><span class="s2">&quot;kind&quot;</span><span class="p">]](</span><span class="n">node</span><span class="p">))</span>
</span><span id="generate-210"><a href="#generate-210"><span class="linenos">210</span></a> <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
</span><span id="generate-211"><a href="#generate-211"><span class="linenos">211</span></a> <span class="n">escaped</span> <span class="o">=</span> <span class="n">node</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">&#39;&quot;&#39;</span><span class="p">,</span> <span class="s1">&#39;</span><span class="se">\\</span><span class="s1">&quot;&#39;</span><span class="p">)</span>
</span><span id="generate-212"><a href="#generate-212"><span class="linenos">212</span></a> <span class="n">path</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;&quot;</span><span class="si">{</span><span class="n">escaped</span><span class="si">}</span><span class="s1">&quot;&#39;</span><span class="p">)</span>
</span><span id="generate-213"><a href="#generate-213"><span class="linenos">213</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="generate-214"><a href="#generate-214"><span class="linenos">214</span></a> <span class="n">path</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">node</span><span class="p">))</span>
</span><span id="generate-215"><a href="#generate-215"><span class="linenos">215</span></a>
</span><span id="generate-216"><a href="#generate-216"><span class="linenos">216</span></a> <span class="k">return</span> <span class="s2">&quot;&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
</span></pre></div>
<a class="headerlink" href="#ALL_JSON_PATH_PARTS"></a>

View file

@ -150,9 +150,9 @@
</span><span id="L-41"><a href="#L-41"><span class="linenos"> 41</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-42"><a href="#L-42"><span class="linenos"> 42</span></a> <span class="n">label</span> <span class="o">=</span> <span class="n">node</span><span class="o">.</span><span class="n">expression</span><span class="o">.</span><span class="n">sql</span><span class="p">(</span><span class="n">pretty</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">dialect</span><span class="p">)</span>
</span><span id="L-43"><a href="#L-43"><span class="linenos"> 43</span></a> <span class="n">source</span> <span class="o">=</span> <span class="n">node</span><span class="o">.</span><span class="n">source</span><span class="o">.</span><span class="n">transform</span><span class="p">(</span>
</span><span id="L-44"><a href="#L-44"><span class="linenos"> 44</span></a> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">exp</span><span class="o">.</span><span class="n">Tag</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">n</span><span class="p">,</span> <span class="n">prefix</span><span class="o">=</span><span class="s2">&quot;&lt;b&gt;&quot;</span><span class="p">,</span> <span class="n">postfix</span><span class="o">=</span><span class="s2">&quot;&lt;/b&gt;&quot;</span><span class="p">)</span>
</span><span id="L-45"><a href="#L-45"><span class="linenos"> 45</span></a> <span class="k">if</span> <span class="n">n</span> <span class="ow">is</span> <span class="n">node</span><span class="o">.</span><span class="n">expression</span>
</span><span id="L-46"><a href="#L-46"><span class="linenos"> 46</span></a> <span class="k">else</span> <span class="n">n</span><span class="p">,</span>
</span><span id="L-44"><a href="#L-44"><span class="linenos"> 44</span></a> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="p">(</span>
</span><span id="L-45"><a href="#L-45"><span class="linenos"> 45</span></a> <span class="n">exp</span><span class="o">.</span><span class="n">Tag</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">n</span><span class="p">,</span> <span class="n">prefix</span><span class="o">=</span><span class="s2">&quot;&lt;b&gt;&quot;</span><span class="p">,</span> <span class="n">postfix</span><span class="o">=</span><span class="s2">&quot;&lt;/b&gt;&quot;</span><span class="p">)</span> <span class="k">if</span> <span class="n">n</span> <span class="ow">is</span> <span class="n">node</span><span class="o">.</span><span class="n">expression</span> <span class="k">else</span> <span class="n">n</span>
</span><span id="L-46"><a href="#L-46"><span class="linenos"> 46</span></a> <span class="p">),</span>
</span><span id="L-47"><a href="#L-47"><span class="linenos"> 47</span></a> <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="p">)</span><span class="o">.</span><span class="n">sql</span><span class="p">(</span><span class="n">pretty</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">dialect</span><span class="p">)</span>
</span><span id="L-49"><a href="#L-49"><span class="linenos"> 49</span></a> <span class="n">title</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;&lt;pre&gt;</span><span class="si">{</span><span class="n">source</span><span class="si">}</span><span class="s2">&lt;/pre&gt;&quot;</span>
@ -453,9 +453,9 @@
</span><span id="Node-42"><a href="#Node-42"><span class="linenos">42</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="Node-43"><a href="#Node-43"><span class="linenos">43</span></a> <span class="n">label</span> <span class="o">=</span> <span class="n">node</span><span class="o">.</span><span class="n">expression</span><span class="o">.</span><span class="n">sql</span><span class="p">(</span><span class="n">pretty</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">dialect</span><span class="p">)</span>
</span><span id="Node-44"><a href="#Node-44"><span class="linenos">44</span></a> <span class="n">source</span> <span class="o">=</span> <span class="n">node</span><span class="o">.</span><span class="n">source</span><span class="o">.</span><span class="n">transform</span><span class="p">(</span>
</span><span id="Node-45"><a href="#Node-45"><span class="linenos">45</span></a> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">exp</span><span class="o">.</span><span class="n">Tag</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">n</span><span class="p">,</span> <span class="n">prefix</span><span class="o">=</span><span class="s2">&quot;&lt;b&gt;&quot;</span><span class="p">,</span> <span class="n">postfix</span><span class="o">=</span><span class="s2">&quot;&lt;/b&gt;&quot;</span><span class="p">)</span>
</span><span id="Node-46"><a href="#Node-46"><span class="linenos">46</span></a> <span class="k">if</span> <span class="n">n</span> <span class="ow">is</span> <span class="n">node</span><span class="o">.</span><span class="n">expression</span>
</span><span id="Node-47"><a href="#Node-47"><span class="linenos">47</span></a> <span class="k">else</span> <span class="n">n</span><span class="p">,</span>
</span><span id="Node-45"><a href="#Node-45"><span class="linenos">45</span></a> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="p">(</span>
</span><span id="Node-46"><a href="#Node-46"><span class="linenos">46</span></a> <span class="n">exp</span><span class="o">.</span><span class="n">Tag</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">n</span><span class="p">,</span> <span class="n">prefix</span><span class="o">=</span><span class="s2">&quot;&lt;b&gt;&quot;</span><span class="p">,</span> <span class="n">postfix</span><span class="o">=</span><span class="s2">&quot;&lt;/b&gt;&quot;</span><span class="p">)</span> <span class="k">if</span> <span class="n">n</span> <span class="ow">is</span> <span class="n">node</span><span class="o">.</span><span class="n">expression</span> <span class="k">else</span> <span class="n">n</span>
</span><span id="Node-47"><a href="#Node-47"><span class="linenos">47</span></a> <span class="p">),</span>
</span><span id="Node-48"><a href="#Node-48"><span class="linenos">48</span></a> <span class="n">copy</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
</span><span id="Node-49"><a href="#Node-49"><span class="linenos">49</span></a> <span class="p">)</span><span class="o">.</span><span class="n">sql</span><span class="p">(</span><span class="n">pretty</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">dialect</span><span class="p">)</span>
</span><span id="Node-50"><a href="#Node-50"><span class="linenos">50</span></a> <span class="n">title</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;&lt;pre&gt;</span><span class="si">{</span><span class="n">source</span><span class="si">}</span><span class="s2">&lt;/pre&gt;&quot;</span>
@ -594,9 +594,9 @@
</span><span id="Node.to_html-42"><a href="#Node.to_html-42"><span class="linenos">42</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="Node.to_html-43"><a href="#Node.to_html-43"><span class="linenos">43</span></a> <span class="n">label</span> <span class="o">=</span> <span class="n">node</span><span class="o">.</span><span class="n">expression</span><span class="o">.</span><span class="n">sql</span><span class="p">(</span><span class="n">pretty</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">dialect</span><span class="p">)</span>
</span><span id="Node.to_html-44"><a href="#Node.to_html-44"><span class="linenos">44</span></a> <span class="n">source</span> <span class="o">=</span> <span class="n">node</span><span class="o">.</span><span class="n">source</span><span class="o">.</span><span class="n">transform</span><span class="p">(</span>
</span><span id="Node.to_html-45"><a href="#Node.to_html-45"><span class="linenos">45</span></a> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">exp</span><span class="o">.</span><span class="n">Tag</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">n</span><span class="p">,</span> <span class="n">prefix</span><span class="o">=</span><span class="s2">&quot;&lt;b&gt;&quot;</span><span class="p">,</span> <span class="n">postfix</span><span class="o">=</span><span class="s2">&quot;&lt;/b&gt;&quot;</span><span class="p">)</span>
</span><span id="Node.to_html-46"><a href="#Node.to_html-46"><span class="linenos">46</span></a> <span class="k">if</span> <span class="n">n</span> <span class="ow">is</span> <span class="n">node</span><span class="o">.</span><span class="n">expression</span>
</span><span id="Node.to_html-47"><a href="#Node.to_html-47"><span class="linenos">47</span></a> <span class="k">else</span> <span class="n">n</span><span class="p">,</span>
</span><span id="Node.to_html-45"><a href="#Node.to_html-45"><span class="linenos">45</span></a> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="p">(</span>
</span><span id="Node.to_html-46"><a href="#Node.to_html-46"><span class="linenos">46</span></a> <span class="n">exp</span><span class="o">.</span><span class="n">Tag</span><span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="n">n</span><span class="p">,</span> <span class="n">prefix</span><span class="o">=</span><span class="s2">&quot;&lt;b&gt;&quot;</span><span class="p">,</span> <span class="n">postfix</span><span class="o">=</span><span class="s2">&quot;&lt;/b&gt;&quot;</span><span class="p">)</span> <span class="k">if</span> <span class="n">n</span> <span class="ow">is</span> <span class="n">node</span><span class="o">.</span><span class="n">expression</span> <span class="k">else</span> <span class="n">n</span>
</span><span id="Node.to_html-47"><a href="#Node.to_html-47"><span class="linenos">47</span></a> <span class="p">),</span>
</span><span id="Node.to_html-48"><a href="#Node.to_html-48"><span class="linenos">48</span></a> <span class="n">copy</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
</span><span id="Node.to_html-49"><a href="#Node.to_html-49"><span class="linenos">49</span></a> <span class="p">)</span><span class="o">.</span><span class="n">sql</span><span class="p">(</span><span class="n">pretty</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">dialect</span><span class="p">)</span>
</span><span id="Node.to_html-50"><a href="#Node.to_html-50"><span class="linenos">50</span></a> <span class="n">title</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;&lt;pre&gt;</span><span class="si">{</span><span class="n">source</span><span class="si">}</span><span class="s2">&lt;/pre&gt;&quot;</span>

View file

@ -71,15 +71,17 @@
<label class="view-source-button" for="mod-optimizer-view-source"><span>View Source</span></label>
<div class="pdoc-code codehilite"><pre><span></span><span id="L-1"><a href="#L-1"><span class="linenos">1</span></a><span class="kn">from</span> <span class="nn">sqlglot.optimizer.optimizer</span> <span class="kn">import</span> <span class="n">RULES</span><span class="p">,</span> <span class="n">optimize</span>
</span><span id="L-2"><a href="#L-2"><span class="linenos">2</span></a><span class="kn">from</span> <span class="nn">sqlglot.optimizer.scope</span> <span class="kn">import</span> <span class="p">(</span>
</span><span id="L-3"><a href="#L-3"><span class="linenos">3</span></a> <span class="n">Scope</span><span class="p">,</span>
</span><span id="L-4"><a href="#L-4"><span class="linenos">4</span></a> <span class="n">build_scope</span><span class="p">,</span>
</span><span id="L-5"><a href="#L-5"><span class="linenos">5</span></a> <span class="n">find_all_in_scope</span><span class="p">,</span>
</span><span id="L-6"><a href="#L-6"><span class="linenos">6</span></a> <span class="n">find_in_scope</span><span class="p">,</span>
</span><span id="L-7"><a href="#L-7"><span class="linenos">7</span></a> <span class="n">traverse_scope</span><span class="p">,</span>
</span><span id="L-8"><a href="#L-8"><span class="linenos">8</span></a> <span class="n">walk_in_scope</span><span class="p">,</span>
</span><span id="L-9"><a href="#L-9"><span class="linenos">9</span></a><span class="p">)</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"># ruff: noqa: F401</span>
</span><span id="L-2"><a href="#L-2"><span class="linenos"> 2</span></a>
</span><span id="L-3"><a href="#L-3"><span class="linenos"> 3</span></a><span class="kn">from</span> <span class="nn">sqlglot.optimizer.optimizer</span> <span class="kn">import</span> <span class="n">RULES</span><span class="p">,</span> <span class="n">optimize</span>
</span><span id="L-4"><a href="#L-4"><span class="linenos"> 4</span></a><span class="kn">from</span> <span class="nn">sqlglot.optimizer.scope</span> <span class="kn">import</span> <span class="p">(</span>
</span><span id="L-5"><a href="#L-5"><span class="linenos"> 5</span></a> <span class="n">Scope</span><span class="p">,</span>
</span><span id="L-6"><a href="#L-6"><span class="linenos"> 6</span></a> <span class="n">build_scope</span><span class="p">,</span>
</span><span id="L-7"><a href="#L-7"><span class="linenos"> 7</span></a> <span class="n">find_all_in_scope</span><span class="p">,</span>
</span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</span></a> <span class="n">find_in_scope</span><span class="p">,</span>
</span><span id="L-9"><a href="#L-9"><span class="linenos"> 9</span></a> <span class="n">traverse_scope</span><span class="p">,</span>
</span><span id="L-10"><a href="#L-10"><span class="linenos">10</span></a> <span class="n">walk_in_scope</span><span class="p">,</span>
</span><span id="L-11"><a href="#L-11"><span class="linenos">11</span></a><span class="p">)</span>
</span></pre></div>

File diff suppressed because one or more lines are too long

View file

@ -585,7 +585,7 @@ queries if it would result in multiple table selects in a single query:</p>
<div class="attr variable">
<span class="name">UNMERGABLE_ARGS</span> =
<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;qualify&#39;, &#39;offset&#39;, &#39;locks&#39;, &#39;group&#39;, &#39;with&#39;, &#39;limit&#39;, &#39;format&#39;, &#39;distinct&#39;, &#39;sample&#39;, &#39;laterals&#39;, &#39;cluster&#39;, &#39;settings&#39;, &#39;pivots&#39;, &#39;connect&#39;, &#39;distribute&#39;, &#39;match&#39;, &#39;having&#39;, &#39;into&#39;, &#39;windows&#39;, &#39;sort&#39;}</span>
<label class="view-value-button pdoc-button" for="UNMERGABLE_ARGS-view-value"></label><span class="default_value">{&#39;distribute&#39;, &#39;settings&#39;, &#39;windows&#39;, &#39;format&#39;, &#39;group&#39;, &#39;having&#39;, &#39;limit&#39;, &#39;laterals&#39;, &#39;with&#39;, &#39;offset&#39;, &#39;into&#39;, &#39;cluster&#39;, &#39;locks&#39;, &#39;distinct&#39;, &#39;match&#39;, &#39;connect&#39;, &#39;kind&#39;, &#39;sample&#39;, &#39;qualify&#39;, &#39;sort&#39;, &#39;pivots&#39;}</span>
</div>

View file

@ -61,63 +61,65 @@
</span><span id="L-3"><a href="#L-3"><span class="linenos"> 3</span></a><span class="kn">import</span> <span class="nn">typing</span> <span class="k">as</span> <span class="nn">t</span>
</span><span id="L-4"><a href="#L-4"><span class="linenos"> 4</span></a>
</span><span id="L-5"><a href="#L-5"><span class="linenos"> 5</span></a><span class="kn">from</span> <span class="nn">sqlglot</span> <span class="kn">import</span> <span class="n">exp</span>
</span><span id="L-6"><a href="#L-6"><span class="linenos"> 6</span></a><span class="kn">from</span> <span class="nn">sqlglot._typing</span> <span class="kn">import</span> <span class="n">E</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.dialects.dialect</span> <span class="kn">import</span> <span class="n">Dialect</span><span class="p">,</span> <span class="n">DialectType</span>
</span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</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 class="nd">@t</span><span class="o">.</span><span class="n">overload</span>
</span><span id="L-11"><a href="#L-11"><span class="linenos">11</span></a><span class="k">def</span> <span class="nf">normalize_identifiers</span><span class="p">(</span><span class="n">expression</span><span class="p">:</span> <span class="n">E</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">-&gt;</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="o">...</span>
</span><span id="L-13"><a href="#L-13"><span class="linenos">13</span></a>
</span><span id="L-14"><a href="#L-14"><span class="linenos">14</span></a>
</span><span id="L-15"><a href="#L-15"><span class="linenos">15</span></a><span class="nd">@t</span><span class="o">.</span><span class="n">overload</span>
</span><span id="L-16"><a href="#L-16"><span class="linenos">16</span></a><span class="k">def</span> <span class="nf">normalize_identifiers</span><span class="p">(</span><span class="n">expression</span><span class="p">:</span> <span class="nb">str</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">-&gt;</span> <span class="n">exp</span><span class="o">.</span><span class="n">Identifier</span><span class="p">:</span>
</span><span id="L-17"><a href="#L-17"><span class="linenos">17</span></a> <span class="o">...</span>
</span><span id="L-18"><a href="#L-18"><span class="linenos">18</span></a>
</span><span id="L-19"><a href="#L-19"><span class="linenos">19</span></a>
</span><span id="L-20"><a href="#L-20"><span class="linenos">20</span></a><span class="k">def</span> <span class="nf">normalize_identifiers</span><span class="p">(</span><span class="n">expression</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
</span><span id="L-21"><a href="#L-21"><span class="linenos">21</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-22"><a href="#L-22"><span class="linenos">22</span></a><span class="sd"> Normalize all unquoted identifiers to either lower or upper case, depending</span>
</span><span id="L-23"><a href="#L-23"><span class="linenos">23</span></a><span class="sd"> on the dialect. This essentially makes those identifiers case-insensitive.</span>
</span><span id="L-24"><a href="#L-24"><span class="linenos">24</span></a>
</span><span id="L-25"><a href="#L-25"><span class="linenos">25</span></a><span class="sd"> It&#39;s possible to make this a no-op by adding a special comment next to the</span>
</span><span id="L-26"><a href="#L-26"><span class="linenos">26</span></a><span class="sd"> identifier of interest:</span>
</span><span id="L-27"><a href="#L-27"><span class="linenos">27</span></a>
</span><span id="L-28"><a href="#L-28"><span class="linenos">28</span></a><span class="sd"> SELECT a /* sqlglot.meta case_sensitive */ FROM table</span>
</span><span id="L-6"><a href="#L-6"><span class="linenos"> 6</span></a><span class="kn">from</span> <span class="nn">sqlglot.dialects.dialect</span> <span class="kn">import</span> <span class="n">Dialect</span><span class="p">,</span> <span class="n">DialectType</span>
</span><span id="L-7"><a href="#L-7"><span class="linenos"> 7</span></a>
</span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</span></a><span class="k">if</span> <span class="n">t</span><span class="o">.</span><span class="n">TYPE_CHECKING</span><span class="p">:</span>
</span><span id="L-9"><a href="#L-9"><span class="linenos"> 9</span></a> <span class="kn">from</span> <span class="nn">sqlglot._typing</span> <span class="kn">import</span> <span class="n">E</span>
</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><span id="L-12"><a href="#L-12"><span class="linenos">12</span></a><span class="nd">@t</span><span class="o">.</span><span class="n">overload</span>
</span><span id="L-13"><a href="#L-13"><span class="linenos">13</span></a><span class="k">def</span> <span class="nf">normalize_identifiers</span><span class="p">(</span><span class="n">expression</span><span class="p">:</span> <span class="n">E</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">-&gt;</span> <span class="n">E</span><span class="p">:</span>
</span><span id="L-14"><a href="#L-14"><span class="linenos">14</span></a> <span class="o">...</span>
</span><span id="L-15"><a href="#L-15"><span class="linenos">15</span></a>
</span><span id="L-16"><a href="#L-16"><span class="linenos">16</span></a>
</span><span id="L-17"><a href="#L-17"><span class="linenos">17</span></a><span class="nd">@t</span><span class="o">.</span><span class="n">overload</span>
</span><span id="L-18"><a href="#L-18"><span class="linenos">18</span></a><span class="k">def</span> <span class="nf">normalize_identifiers</span><span class="p">(</span><span class="n">expression</span><span class="p">:</span> <span class="nb">str</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">-&gt;</span> <span class="n">exp</span><span class="o">.</span><span class="n">Identifier</span><span class="p">:</span>
</span><span id="L-19"><a href="#L-19"><span class="linenos">19</span></a> <span class="o">...</span>
</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><span id="L-22"><a href="#L-22"><span class="linenos">22</span></a><span class="k">def</span> <span class="nf">normalize_identifiers</span><span class="p">(</span><span class="n">expression</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
</span><span id="L-23"><a href="#L-23"><span class="linenos">23</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-24"><a href="#L-24"><span class="linenos">24</span></a><span class="sd"> Normalize all unquoted identifiers to either lower or upper case, depending</span>
</span><span id="L-25"><a href="#L-25"><span class="linenos">25</span></a><span class="sd"> on the dialect. This essentially makes those identifiers case-insensitive.</span>
</span><span id="L-26"><a href="#L-26"><span class="linenos">26</span></a>
</span><span id="L-27"><a href="#L-27"><span class="linenos">27</span></a><span class="sd"> It&#39;s possible to make this a no-op by adding a special comment next to the</span>
</span><span id="L-28"><a href="#L-28"><span class="linenos">28</span></a><span class="sd"> identifier of interest:</span>
</span><span id="L-29"><a href="#L-29"><span class="linenos">29</span></a>
</span><span id="L-30"><a href="#L-30"><span class="linenos">30</span></a><span class="sd"> In this example, the identifier `a` will not be normalized.</span>
</span><span id="L-30"><a href="#L-30"><span class="linenos">30</span></a><span class="sd"> SELECT a /* sqlglot.meta case_sensitive */ FROM table</span>
</span><span id="L-31"><a href="#L-31"><span class="linenos">31</span></a>
</span><span id="L-32"><a href="#L-32"><span class="linenos">32</span></a><span class="sd"> Note:</span>
</span><span id="L-33"><a href="#L-33"><span class="linenos">33</span></a><span class="sd"> Some dialects (e.g. BigQuery) treat identifiers as case-insensitive even</span>
</span><span id="L-34"><a href="#L-34"><span class="linenos">34</span></a><span class="sd"> when they&#39;re quoted, so in these cases all identifiers are normalized.</span>
</span><span id="L-35"><a href="#L-35"><span class="linenos">35</span></a>
</span><span id="L-36"><a href="#L-36"><span class="linenos">36</span></a><span class="sd"> Example:</span>
</span><span id="L-37"><a href="#L-37"><span class="linenos">37</span></a><span class="sd"> &gt;&gt;&gt; import sqlglot</span>
</span><span id="L-38"><a href="#L-38"><span class="linenos">38</span></a><span class="sd"> &gt;&gt;&gt; expression = sqlglot.parse_one(&#39;SELECT Bar.A AS A FROM &quot;Foo&quot;.Bar&#39;)</span>
</span><span id="L-39"><a href="#L-39"><span class="linenos">39</span></a><span class="sd"> &gt;&gt;&gt; normalize_identifiers(expression).sql()</span>
</span><span id="L-40"><a href="#L-40"><span class="linenos">40</span></a><span class="sd"> &#39;SELECT bar.a AS a FROM &quot;Foo&quot;.bar&#39;</span>
</span><span id="L-41"><a href="#L-41"><span class="linenos">41</span></a><span class="sd"> &gt;&gt;&gt; normalize_identifiers(&quot;foo&quot;, dialect=&quot;snowflake&quot;).sql(dialect=&quot;snowflake&quot;)</span>
</span><span id="L-42"><a href="#L-42"><span class="linenos">42</span></a><span class="sd"> &#39;FOO&#39;</span>
</span><span id="L-43"><a href="#L-43"><span class="linenos">43</span></a>
</span><span id="L-44"><a href="#L-44"><span class="linenos">44</span></a><span class="sd"> Args:</span>
</span><span id="L-45"><a href="#L-45"><span class="linenos">45</span></a><span class="sd"> expression: The expression to transform.</span>
</span><span id="L-46"><a href="#L-46"><span class="linenos">46</span></a><span class="sd"> dialect: The dialect to use in order to decide how to normalize identifiers.</span>
</span><span id="L-47"><a href="#L-47"><span class="linenos">47</span></a>
</span><span id="L-48"><a href="#L-48"><span class="linenos">48</span></a><span class="sd"> Returns:</span>
</span><span id="L-49"><a href="#L-49"><span class="linenos">49</span></a><span class="sd"> The transformed expression.</span>
</span><span id="L-50"><a href="#L-50"><span class="linenos">50</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-51"><a href="#L-51"><span class="linenos">51</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">dialect</span><span class="p">)</span>
</span><span id="L-52"><a href="#L-52"><span class="linenos">52</span></a>
</span><span id="L-53"><a href="#L-53"><span class="linenos">53</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">expression</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
</span><span id="L-54"><a href="#L-54"><span class="linenos">54</span></a> <span class="n">expression</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">parse_identifier</span><span class="p">(</span><span class="n">expression</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">dialect</span><span class="p">)</span>
</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="k">def</span> <span class="nf">_normalize</span><span class="p">(</span><span class="n">node</span><span class="p">:</span> <span class="n">E</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">E</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="ow">not</span> <span class="n">node</span><span class="o">.</span><span class="n">meta</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;case_sensitive&quot;</span><span class="p">):</span>
</span><span id="L-58"><a href="#L-58"><span class="linenos">58</span></a> <span class="n">exp</span><span class="o">.</span><span class="n">replace_children</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">_normalize</span><span class="p">)</span>
</span><span id="L-59"><a href="#L-59"><span class="linenos">59</span></a> <span class="n">node</span> <span class="o">=</span> <span class="n">dialect</span><span class="o">.</span><span class="n">normalize_identifier</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>
</span><span id="L-60"><a href="#L-60"><span class="linenos">60</span></a> <span class="k">return</span> <span class="n">node</span>
</span><span id="L-61"><a href="#L-61"><span class="linenos">61</span></a>
</span><span id="L-62"><a href="#L-62"><span class="linenos">62</span></a> <span class="k">return</span> <span class="n">_normalize</span><span class="p">(</span><span class="n">expression</span><span class="p">)</span>
</span><span id="L-32"><a href="#L-32"><span class="linenos">32</span></a><span class="sd"> In this example, the identifier `a` will not be normalized.</span>
</span><span id="L-33"><a href="#L-33"><span class="linenos">33</span></a>
</span><span id="L-34"><a href="#L-34"><span class="linenos">34</span></a><span class="sd"> Note:</span>
</span><span id="L-35"><a href="#L-35"><span class="linenos">35</span></a><span class="sd"> Some dialects (e.g. BigQuery) treat identifiers as case-insensitive even</span>
</span><span id="L-36"><a href="#L-36"><span class="linenos">36</span></a><span class="sd"> when they&#39;re quoted, so in these cases all identifiers are normalized.</span>
</span><span id="L-37"><a href="#L-37"><span class="linenos">37</span></a>
</span><span id="L-38"><a href="#L-38"><span class="linenos">38</span></a><span class="sd"> Example:</span>
</span><span id="L-39"><a href="#L-39"><span class="linenos">39</span></a><span class="sd"> &gt;&gt;&gt; import sqlglot</span>
</span><span id="L-40"><a href="#L-40"><span class="linenos">40</span></a><span class="sd"> &gt;&gt;&gt; expression = sqlglot.parse_one(&#39;SELECT Bar.A AS A FROM &quot;Foo&quot;.Bar&#39;)</span>
</span><span id="L-41"><a href="#L-41"><span class="linenos">41</span></a><span class="sd"> &gt;&gt;&gt; normalize_identifiers(expression).sql()</span>
</span><span id="L-42"><a href="#L-42"><span class="linenos">42</span></a><span class="sd"> &#39;SELECT bar.a AS a FROM &quot;Foo&quot;.bar&#39;</span>
</span><span id="L-43"><a href="#L-43"><span class="linenos">43</span></a><span class="sd"> &gt;&gt;&gt; normalize_identifiers(&quot;foo&quot;, dialect=&quot;snowflake&quot;).sql(dialect=&quot;snowflake&quot;)</span>
</span><span id="L-44"><a href="#L-44"><span class="linenos">44</span></a><span class="sd"> &#39;FOO&#39;</span>
</span><span id="L-45"><a href="#L-45"><span class="linenos">45</span></a>
</span><span id="L-46"><a href="#L-46"><span class="linenos">46</span></a><span class="sd"> Args:</span>
</span><span id="L-47"><a href="#L-47"><span class="linenos">47</span></a><span class="sd"> expression: The expression to transform.</span>
</span><span id="L-48"><a href="#L-48"><span class="linenos">48</span></a><span class="sd"> dialect: The dialect to use in order to decide how to normalize identifiers.</span>
</span><span id="L-49"><a href="#L-49"><span class="linenos">49</span></a>
</span><span id="L-50"><a href="#L-50"><span class="linenos">50</span></a><span class="sd"> Returns:</span>
</span><span id="L-51"><a href="#L-51"><span class="linenos">51</span></a><span class="sd"> The transformed expression.</span>
</span><span id="L-52"><a href="#L-52"><span class="linenos">52</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-53"><a href="#L-53"><span class="linenos">53</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">dialect</span><span class="p">)</span>
</span><span id="L-54"><a href="#L-54"><span class="linenos">54</span></a>
</span><span id="L-55"><a href="#L-55"><span class="linenos">55</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">expression</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
</span><span id="L-56"><a href="#L-56"><span class="linenos">56</span></a> <span class="n">expression</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">parse_identifier</span><span class="p">(</span><span class="n">expression</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">dialect</span><span class="p">)</span>
</span><span id="L-57"><a href="#L-57"><span class="linenos">57</span></a>
</span><span id="L-58"><a href="#L-58"><span class="linenos">58</span></a> <span class="k">def</span> <span class="nf">_normalize</span><span class="p">(</span><span class="n">node</span><span class="p">:</span> <span class="n">E</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">E</span><span class="p">:</span>
</span><span id="L-59"><a href="#L-59"><span class="linenos">59</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">node</span><span class="o">.</span><span class="n">meta</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;case_sensitive&quot;</span><span class="p">):</span>
</span><span id="L-60"><a href="#L-60"><span class="linenos">60</span></a> <span class="n">exp</span><span class="o">.</span><span class="n">replace_children</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">_normalize</span><span class="p">)</span>
</span><span id="L-61"><a href="#L-61"><span class="linenos">61</span></a> <span class="n">node</span> <span class="o">=</span> <span class="n">dialect</span><span class="o">.</span><span class="n">normalize_identifier</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>
</span><span id="L-62"><a href="#L-62"><span class="linenos">62</span></a> <span class="k">return</span> <span class="n">node</span>
</span><span id="L-63"><a href="#L-63"><span class="linenos">63</span></a>
</span><span id="L-64"><a href="#L-64"><span class="linenos">64</span></a> <span class="k">return</span> <span class="n">_normalize</span><span class="p">(</span><span class="n">expression</span><span class="p">)</span>
</span></pre></div>
@ -133,49 +135,49 @@
</div>
<a class="headerlink" href="#normalize_identifiers"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="normalize_identifiers-21"><a href="#normalize_identifiers-21"><span class="linenos">21</span></a><span class="k">def</span> <span class="nf">normalize_identifiers</span><span class="p">(</span><span class="n">expression</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
</span><span id="normalize_identifiers-22"><a href="#normalize_identifiers-22"><span class="linenos">22</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="normalize_identifiers-23"><a href="#normalize_identifiers-23"><span class="linenos">23</span></a><span class="sd"> Normalize all unquoted identifiers to either lower or upper case, depending</span>
</span><span id="normalize_identifiers-24"><a href="#normalize_identifiers-24"><span class="linenos">24</span></a><span class="sd"> on the dialect. This essentially makes those identifiers case-insensitive.</span>
</span><span id="normalize_identifiers-25"><a href="#normalize_identifiers-25"><span class="linenos">25</span></a>
</span><span id="normalize_identifiers-26"><a href="#normalize_identifiers-26"><span class="linenos">26</span></a><span class="sd"> It&#39;s possible to make this a no-op by adding a special comment next to the</span>
</span><span id="normalize_identifiers-27"><a href="#normalize_identifiers-27"><span class="linenos">27</span></a><span class="sd"> identifier of interest:</span>
</span><span id="normalize_identifiers-28"><a href="#normalize_identifiers-28"><span class="linenos">28</span></a>
</span><span id="normalize_identifiers-29"><a href="#normalize_identifiers-29"><span class="linenos">29</span></a><span class="sd"> SELECT a /* sqlglot.meta case_sensitive */ FROM table</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="normalize_identifiers-23"><a href="#normalize_identifiers-23"><span class="linenos">23</span></a><span class="k">def</span> <span class="nf">normalize_identifiers</span><span class="p">(</span><span class="n">expression</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
</span><span id="normalize_identifiers-24"><a href="#normalize_identifiers-24"><span class="linenos">24</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="normalize_identifiers-25"><a href="#normalize_identifiers-25"><span class="linenos">25</span></a><span class="sd"> Normalize all unquoted identifiers to either lower or upper case, depending</span>
</span><span id="normalize_identifiers-26"><a href="#normalize_identifiers-26"><span class="linenos">26</span></a><span class="sd"> on the dialect. This essentially makes those identifiers case-insensitive.</span>
</span><span id="normalize_identifiers-27"><a href="#normalize_identifiers-27"><span class="linenos">27</span></a>
</span><span id="normalize_identifiers-28"><a href="#normalize_identifiers-28"><span class="linenos">28</span></a><span class="sd"> It&#39;s possible to make this a no-op by adding a special comment next to the</span>
</span><span id="normalize_identifiers-29"><a href="#normalize_identifiers-29"><span class="linenos">29</span></a><span class="sd"> identifier of interest:</span>
</span><span id="normalize_identifiers-30"><a href="#normalize_identifiers-30"><span class="linenos">30</span></a>
</span><span id="normalize_identifiers-31"><a href="#normalize_identifiers-31"><span class="linenos">31</span></a><span class="sd"> In this example, the identifier `a` will not be normalized.</span>
</span><span id="normalize_identifiers-31"><a href="#normalize_identifiers-31"><span class="linenos">31</span></a><span class="sd"> SELECT a /* sqlglot.meta case_sensitive */ FROM table</span>
</span><span id="normalize_identifiers-32"><a href="#normalize_identifiers-32"><span class="linenos">32</span></a>
</span><span id="normalize_identifiers-33"><a href="#normalize_identifiers-33"><span class="linenos">33</span></a><span class="sd"> Note:</span>
</span><span id="normalize_identifiers-34"><a href="#normalize_identifiers-34"><span class="linenos">34</span></a><span class="sd"> Some dialects (e.g. BigQuery) treat identifiers as case-insensitive even</span>
</span><span id="normalize_identifiers-35"><a href="#normalize_identifiers-35"><span class="linenos">35</span></a><span class="sd"> when they&#39;re quoted, so in these cases all identifiers are normalized.</span>
</span><span id="normalize_identifiers-36"><a href="#normalize_identifiers-36"><span class="linenos">36</span></a>
</span><span id="normalize_identifiers-37"><a href="#normalize_identifiers-37"><span class="linenos">37</span></a><span class="sd"> Example:</span>
</span><span id="normalize_identifiers-38"><a href="#normalize_identifiers-38"><span class="linenos">38</span></a><span class="sd"> &gt;&gt;&gt; import sqlglot</span>
</span><span id="normalize_identifiers-39"><a href="#normalize_identifiers-39"><span class="linenos">39</span></a><span class="sd"> &gt;&gt;&gt; expression = sqlglot.parse_one(&#39;SELECT Bar.A AS A FROM &quot;Foo&quot;.Bar&#39;)</span>
</span><span id="normalize_identifiers-40"><a href="#normalize_identifiers-40"><span class="linenos">40</span></a><span class="sd"> &gt;&gt;&gt; normalize_identifiers(expression).sql()</span>
</span><span id="normalize_identifiers-41"><a href="#normalize_identifiers-41"><span class="linenos">41</span></a><span class="sd"> &#39;SELECT bar.a AS a FROM &quot;Foo&quot;.bar&#39;</span>
</span><span id="normalize_identifiers-42"><a href="#normalize_identifiers-42"><span class="linenos">42</span></a><span class="sd"> &gt;&gt;&gt; normalize_identifiers(&quot;foo&quot;, dialect=&quot;snowflake&quot;).sql(dialect=&quot;snowflake&quot;)</span>
</span><span id="normalize_identifiers-43"><a href="#normalize_identifiers-43"><span class="linenos">43</span></a><span class="sd"> &#39;FOO&#39;</span>
</span><span id="normalize_identifiers-44"><a href="#normalize_identifiers-44"><span class="linenos">44</span></a>
</span><span id="normalize_identifiers-45"><a href="#normalize_identifiers-45"><span class="linenos">45</span></a><span class="sd"> Args:</span>
</span><span id="normalize_identifiers-46"><a href="#normalize_identifiers-46"><span class="linenos">46</span></a><span class="sd"> expression: The expression to transform.</span>
</span><span id="normalize_identifiers-47"><a href="#normalize_identifiers-47"><span class="linenos">47</span></a><span class="sd"> dialect: The dialect to use in order to decide how to normalize identifiers.</span>
</span><span id="normalize_identifiers-48"><a href="#normalize_identifiers-48"><span class="linenos">48</span></a>
</span><span id="normalize_identifiers-49"><a href="#normalize_identifiers-49"><span class="linenos">49</span></a><span class="sd"> Returns:</span>
</span><span id="normalize_identifiers-50"><a href="#normalize_identifiers-50"><span class="linenos">50</span></a><span class="sd"> The transformed expression.</span>
</span><span id="normalize_identifiers-51"><a href="#normalize_identifiers-51"><span class="linenos">51</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="normalize_identifiers-52"><a href="#normalize_identifiers-52"><span class="linenos">52</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">dialect</span><span class="p">)</span>
</span><span id="normalize_identifiers-53"><a href="#normalize_identifiers-53"><span class="linenos">53</span></a>
</span><span id="normalize_identifiers-54"><a href="#normalize_identifiers-54"><span class="linenos">54</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">expression</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
</span><span id="normalize_identifiers-55"><a href="#normalize_identifiers-55"><span class="linenos">55</span></a> <span class="n">expression</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">parse_identifier</span><span class="p">(</span><span class="n">expression</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">dialect</span><span class="p">)</span>
</span><span id="normalize_identifiers-56"><a href="#normalize_identifiers-56"><span class="linenos">56</span></a>
</span><span id="normalize_identifiers-57"><a href="#normalize_identifiers-57"><span class="linenos">57</span></a> <span class="k">def</span> <span class="nf">_normalize</span><span class="p">(</span><span class="n">node</span><span class="p">:</span> <span class="n">E</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">E</span><span class="p">:</span>
</span><span id="normalize_identifiers-58"><a href="#normalize_identifiers-58"><span class="linenos">58</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">node</span><span class="o">.</span><span class="n">meta</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;case_sensitive&quot;</span><span class="p">):</span>
</span><span id="normalize_identifiers-59"><a href="#normalize_identifiers-59"><span class="linenos">59</span></a> <span class="n">exp</span><span class="o">.</span><span class="n">replace_children</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">_normalize</span><span class="p">)</span>
</span><span id="normalize_identifiers-60"><a href="#normalize_identifiers-60"><span class="linenos">60</span></a> <span class="n">node</span> <span class="o">=</span> <span class="n">dialect</span><span class="o">.</span><span class="n">normalize_identifier</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>
</span><span id="normalize_identifiers-61"><a href="#normalize_identifiers-61"><span class="linenos">61</span></a> <span class="k">return</span> <span class="n">node</span>
</span><span id="normalize_identifiers-62"><a href="#normalize_identifiers-62"><span class="linenos">62</span></a>
</span><span id="normalize_identifiers-63"><a href="#normalize_identifiers-63"><span class="linenos">63</span></a> <span class="k">return</span> <span class="n">_normalize</span><span class="p">(</span><span class="n">expression</span><span class="p">)</span>
</span><span id="normalize_identifiers-33"><a href="#normalize_identifiers-33"><span class="linenos">33</span></a><span class="sd"> In this example, the identifier `a` will not be normalized.</span>
</span><span id="normalize_identifiers-34"><a href="#normalize_identifiers-34"><span class="linenos">34</span></a>
</span><span id="normalize_identifiers-35"><a href="#normalize_identifiers-35"><span class="linenos">35</span></a><span class="sd"> Note:</span>
</span><span id="normalize_identifiers-36"><a href="#normalize_identifiers-36"><span class="linenos">36</span></a><span class="sd"> Some dialects (e.g. BigQuery) treat identifiers as case-insensitive even</span>
</span><span id="normalize_identifiers-37"><a href="#normalize_identifiers-37"><span class="linenos">37</span></a><span class="sd"> when they&#39;re quoted, so in these cases all identifiers are normalized.</span>
</span><span id="normalize_identifiers-38"><a href="#normalize_identifiers-38"><span class="linenos">38</span></a>
</span><span id="normalize_identifiers-39"><a href="#normalize_identifiers-39"><span class="linenos">39</span></a><span class="sd"> Example:</span>
</span><span id="normalize_identifiers-40"><a href="#normalize_identifiers-40"><span class="linenos">40</span></a><span class="sd"> &gt;&gt;&gt; import sqlglot</span>
</span><span id="normalize_identifiers-41"><a href="#normalize_identifiers-41"><span class="linenos">41</span></a><span class="sd"> &gt;&gt;&gt; expression = sqlglot.parse_one(&#39;SELECT Bar.A AS A FROM &quot;Foo&quot;.Bar&#39;)</span>
</span><span id="normalize_identifiers-42"><a href="#normalize_identifiers-42"><span class="linenos">42</span></a><span class="sd"> &gt;&gt;&gt; normalize_identifiers(expression).sql()</span>
</span><span id="normalize_identifiers-43"><a href="#normalize_identifiers-43"><span class="linenos">43</span></a><span class="sd"> &#39;SELECT bar.a AS a FROM &quot;Foo&quot;.bar&#39;</span>
</span><span id="normalize_identifiers-44"><a href="#normalize_identifiers-44"><span class="linenos">44</span></a><span class="sd"> &gt;&gt;&gt; normalize_identifiers(&quot;foo&quot;, dialect=&quot;snowflake&quot;).sql(dialect=&quot;snowflake&quot;)</span>
</span><span id="normalize_identifiers-45"><a href="#normalize_identifiers-45"><span class="linenos">45</span></a><span class="sd"> &#39;FOO&#39;</span>
</span><span id="normalize_identifiers-46"><a href="#normalize_identifiers-46"><span class="linenos">46</span></a>
</span><span id="normalize_identifiers-47"><a href="#normalize_identifiers-47"><span class="linenos">47</span></a><span class="sd"> Args:</span>
</span><span id="normalize_identifiers-48"><a href="#normalize_identifiers-48"><span class="linenos">48</span></a><span class="sd"> expression: The expression to transform.</span>
</span><span id="normalize_identifiers-49"><a href="#normalize_identifiers-49"><span class="linenos">49</span></a><span class="sd"> dialect: The dialect to use in order to decide how to normalize identifiers.</span>
</span><span id="normalize_identifiers-50"><a href="#normalize_identifiers-50"><span class="linenos">50</span></a>
</span><span id="normalize_identifiers-51"><a href="#normalize_identifiers-51"><span class="linenos">51</span></a><span class="sd"> Returns:</span>
</span><span id="normalize_identifiers-52"><a href="#normalize_identifiers-52"><span class="linenos">52</span></a><span class="sd"> The transformed expression.</span>
</span><span id="normalize_identifiers-53"><a href="#normalize_identifiers-53"><span class="linenos">53</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="normalize_identifiers-54"><a href="#normalize_identifiers-54"><span class="linenos">54</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">dialect</span><span class="p">)</span>
</span><span id="normalize_identifiers-55"><a href="#normalize_identifiers-55"><span class="linenos">55</span></a>
</span><span id="normalize_identifiers-56"><a href="#normalize_identifiers-56"><span class="linenos">56</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">expression</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
</span><span id="normalize_identifiers-57"><a href="#normalize_identifiers-57"><span class="linenos">57</span></a> <span class="n">expression</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">parse_identifier</span><span class="p">(</span><span class="n">expression</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">dialect</span><span class="p">)</span>
</span><span id="normalize_identifiers-58"><a href="#normalize_identifiers-58"><span class="linenos">58</span></a>
</span><span id="normalize_identifiers-59"><a href="#normalize_identifiers-59"><span class="linenos">59</span></a> <span class="k">def</span> <span class="nf">_normalize</span><span class="p">(</span><span class="n">node</span><span class="p">:</span> <span class="n">E</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">E</span><span class="p">:</span>
</span><span id="normalize_identifiers-60"><a href="#normalize_identifiers-60"><span class="linenos">60</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">node</span><span class="o">.</span><span class="n">meta</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;case_sensitive&quot;</span><span class="p">):</span>
</span><span id="normalize_identifiers-61"><a href="#normalize_identifiers-61"><span class="linenos">61</span></a> <span class="n">exp</span><span class="o">.</span><span class="n">replace_children</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">_normalize</span><span class="p">)</span>
</span><span id="normalize_identifiers-62"><a href="#normalize_identifiers-62"><span class="linenos">62</span></a> <span class="n">node</span> <span class="o">=</span> <span class="n">dialect</span><span class="o">.</span><span class="n">normalize_identifier</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>
</span><span id="normalize_identifiers-63"><a href="#normalize_identifiers-63"><span class="linenos">63</span></a> <span class="k">return</span> <span class="n">node</span>
</span><span id="normalize_identifiers-64"><a href="#normalize_identifiers-64"><span class="linenos">64</span></a>
</span><span id="normalize_identifiers-65"><a href="#normalize_identifiers-65"><span class="linenos">65</span></a> <span class="k">return</span> <span class="n">_normalize</span><span class="p">(</span><span class="n">expression</span><span class="p">)</span>
</span></pre></div>

View file

@ -34,7 +34,7 @@
<a class="variable" href="#SELECT_ALL">SELECT_ALL</a>
</li>
<li>
<a class="function" href="#DEFAULT_SELECTION">DEFAULT_SELECTION</a>
<a class="function" href="#default_selection">default_selection</a>
</li>
<li>
<a class="function" href="#pushdown_projections">pushdown_projections</a>
@ -72,10 +72,10 @@
</span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</span></a><span class="c1"># Sentinel value that means an outer query selecting ALL columns</span>
</span><span id="L-9"><a href="#L-9"><span class="linenos"> 9</span></a><span class="n">SELECT_ALL</span> <span class="o">=</span> <span class="nb">object</span><span class="p">()</span>
</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="c1"># Selection to use if selection list is empty</span>
</span><span id="L-12"><a href="#L-12"><span class="linenos"> 12</span></a><span class="n">DEFAULT_SELECTION</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">is_agg</span><span class="p">:</span> <span class="n">alias</span><span class="p">(</span>
</span><span id="L-13"><a href="#L-13"><span class="linenos"> 13</span></a> <span class="n">exp</span><span class="o">.</span><span class="n">Max</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">Literal</span><span class="o">.</span><span class="n">number</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span> <span class="k">if</span> <span class="n">is_agg</span> <span class="k">else</span> <span class="s2">&quot;1&quot;</span><span class="p">,</span> <span class="s2">&quot;_&quot;</span>
</span><span id="L-14"><a href="#L-14"><span class="linenos"> 14</span></a><span class="p">)</span>
</span><span id="L-11"><a href="#L-11"><span class="linenos"> 11</span></a>
</span><span id="L-12"><a href="#L-12"><span class="linenos"> 12</span></a><span class="c1"># Selection to use if selection list is empty</span>
</span><span id="L-13"><a href="#L-13"><span class="linenos"> 13</span></a><span class="k">def</span> <span class="nf">default_selection</span><span class="p">(</span><span class="n">is_agg</span><span class="p">:</span> <span class="nb">bool</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">exp</span><span class="o">.</span><span class="n">Alias</span><span class="p">:</span>
</span><span id="L-14"><a href="#L-14"><span class="linenos"> 14</span></a> <span class="k">return</span> <span class="n">alias</span><span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">Max</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">Literal</span><span class="o">.</span><span class="n">number</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span> <span class="k">if</span> <span class="n">is_agg</span> <span class="k">else</span> <span class="s2">&quot;1&quot;</span><span class="p">,</span> <span class="s2">&quot;_&quot;</span><span class="p">)</span>
</span><span id="L-15"><a href="#L-15"><span class="linenos"> 15</span></a>
</span><span id="L-16"><a href="#L-16"><span class="linenos"> 16</span></a>
</span><span id="L-17"><a href="#L-17"><span class="linenos"> 17</span></a><span class="k">def</span> <span class="nf">pushdown_projections</span><span class="p">(</span><span class="n">expression</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">remove_unused_selections</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
@ -193,7 +193,7 @@
</span><span id="L-129"><a href="#L-129"><span class="linenos">129</span></a>
</span><span id="L-130"><a href="#L-130"><span class="linenos">130</span></a> <span class="c1"># If there are no remaining selections, just select a single constant</span>
</span><span id="L-131"><a href="#L-131"><span class="linenos">131</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">new_selections</span><span class="p">:</span>
</span><span id="L-132"><a href="#L-132"><span class="linenos">132</span></a> <span class="n">new_selections</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">DEFAULT_SELECTION</span><span class="p">(</span><span class="n">is_agg</span><span class="p">))</span>
</span><span id="L-132"><a href="#L-132"><span class="linenos">132</span></a> <span class="n">new_selections</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">default_selection</span><span class="p">(</span><span class="n">is_agg</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">scope</span><span class="o">.</span><span class="n">expression</span><span class="o">.</span><span class="n">select</span><span class="p">(</span><span class="o">*</span><span class="n">new_selections</span><span class="p">,</span> <span class="n">append</span><span class="o">=</span><span class="kc">False</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-135"><a href="#L-135"><span class="linenos">135</span></a>
@ -215,20 +215,19 @@
</section>
<section id="DEFAULT_SELECTION">
<input id="DEFAULT_SELECTION-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
<section id="default_selection">
<input id="default_selection-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
<div class="attr function">
<span class="def">def</span>
<span class="name">DEFAULT_SELECTION</span><span class="signature pdoc-code condensed">(<span class="param"><span class="n">is_agg</span></span><span class="return-annotation">):</span></span>
<span class="name">default_selection</span><span class="signature pdoc-code condensed">(<span class="param"><span class="n">is_agg</span><span class="p">:</span> <span class="nb">bool</span></span><span class="return-annotation">) -> <span class="n"><a href="../expressions.html#Alias">sqlglot.expressions.Alias</a></span>:</span></span>
<label class="view-source-button" for="DEFAULT_SELECTION-view-source"><span>View Source</span></label>
<label class="view-source-button" for="default_selection-view-source"><span>View Source</span></label>
</div>
<a class="headerlink" href="#DEFAULT_SELECTION"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="DEFAULT_SELECTION-13"><a href="#DEFAULT_SELECTION-13"><span class="linenos">13</span></a><span class="n">DEFAULT_SELECTION</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">is_agg</span><span class="p">:</span> <span class="n">alias</span><span class="p">(</span>
</span><span id="DEFAULT_SELECTION-14"><a href="#DEFAULT_SELECTION-14"><span class="linenos">14</span></a> <span class="n">exp</span><span class="o">.</span><span class="n">Max</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">Literal</span><span class="o">.</span><span class="n">number</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span> <span class="k">if</span> <span class="n">is_agg</span> <span class="k">else</span> <span class="s2">&quot;1&quot;</span><span class="p">,</span> <span class="s2">&quot;_&quot;</span>
</span><span id="DEFAULT_SELECTION-15"><a href="#DEFAULT_SELECTION-15"><span class="linenos">15</span></a><span class="p">)</span>
<a class="headerlink" href="#default_selection"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="default_selection-14"><a href="#default_selection-14"><span class="linenos">14</span></a><span class="k">def</span> <span class="nf">default_selection</span><span class="p">(</span><span class="n">is_agg</span><span class="p">:</span> <span class="nb">bool</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">exp</span><span class="o">.</span><span class="n">Alias</span><span class="p">:</span>
</span><span id="default_selection-15"><a href="#default_selection-15"><span class="linenos">15</span></a> <span class="k">return</span> <span class="n">alias</span><span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">Max</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">Literal</span><span class="o">.</span><span class="n">number</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span> <span class="k">if</span> <span class="n">is_agg</span> <span class="k">else</span> <span class="s2">&quot;1&quot;</span><span class="p">,</span> <span class="s2">&quot;_&quot;</span><span class="p">)</span>
</span></pre></div>

File diff suppressed because it is too large Load diff

View file

@ -62,128 +62,130 @@
</span><span id="L-4"><a href="#L-4"><span class="linenos"> 4</span></a><span class="kn">import</span> <span class="nn">typing</span> <span class="k">as</span> <span class="nn">t</span>
</span><span id="L-5"><a href="#L-5"><span class="linenos"> 5</span></a>
</span><span id="L-6"><a href="#L-6"><span class="linenos"> 6</span></a><span class="kn">from</span> <span class="nn">sqlglot</span> <span class="kn">import</span> <span class="n">alias</span><span class="p">,</span> <span class="n">exp</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._typing</span> <span class="kn">import</span> <span class="n">E</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.dialects.dialect</span> <span class="kn">import</span> <span class="n">DialectType</span>
</span><span id="L-9"><a href="#L-9"><span class="linenos"> 9</span></a><span class="kn">from</span> <span class="nn">sqlglot.helper</span> <span class="kn">import</span> <span class="n">csv_reader</span><span class="p">,</span> <span class="n">name_sequence</span>
</span><span id="L-10"><a href="#L-10"><span class="linenos"> 10</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-11"><a href="#L-11"><span class="linenos"> 11</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-12"><a href="#L-12"><span class="linenos"> 12</span></a>
</span><span id="L-13"><a href="#L-13"><span class="linenos"> 13</span></a>
</span><span id="L-14"><a href="#L-14"><span class="linenos"> 14</span></a><span class="k">def</span> <span class="nf">qualify_tables</span><span class="p">(</span>
</span><span id="L-15"><a href="#L-15"><span class="linenos"> 15</span></a> <span class="n">expression</span><span class="p">:</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="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="o">|</span> <span class="n">exp</span><span class="o">.</span><span class="n">Identifier</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="L-17"><a href="#L-17"><span class="linenos"> 17</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="o">|</span> <span class="n">exp</span><span class="o">.</span><span class="n">Identifier</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="L-18"><a href="#L-18"><span class="linenos"> 18</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-19"><a href="#L-19"><span class="linenos"> 19</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-20"><a href="#L-20"><span class="linenos"> 20</span></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">E</span><span class="p">:</span>
</span><span id="L-21"><a href="#L-21"><span class="linenos"> 21</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-22"><a href="#L-22"><span class="linenos"> 22</span></a><span class="sd"> Rewrite sqlglot AST to have fully qualified tables. Join constructs such as</span>
</span><span id="L-23"><a href="#L-23"><span class="linenos"> 23</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-24"><a href="#L-24"><span class="linenos"> 24</span></a>
</span><span id="L-25"><a href="#L-25"><span class="linenos"> 25</span></a><span class="sd"> Examples:</span>
</span><span id="L-26"><a href="#L-26"><span class="linenos"> 26</span></a><span class="sd"> &gt;&gt;&gt; import sqlglot</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 tbl&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, db=&quot;db&quot;).sql()</span>
</span><span id="L-29"><a href="#L-29"><span class="linenos"> 29</span></a><span class="sd"> &#39;SELECT 1 FROM db.tbl AS tbl&#39;</span>
</span><span id="L-30"><a href="#L-30"><span class="linenos"> 30</span></a><span class="sd"> &gt;&gt;&gt;</span>
</span><span id="L-31"><a href="#L-31"><span class="linenos"> 31</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-32"><a href="#L-32"><span class="linenos"> 32</span></a><span class="sd"> &gt;&gt;&gt; qualify_tables(expression).sql()</span>
</span><span id="L-33"><a href="#L-33"><span class="linenos"> 33</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-34"><a href="#L-34"><span class="linenos"> 34</span></a>
</span><span id="L-35"><a href="#L-35"><span class="linenos"> 35</span></a><span class="sd"> Args:</span>
</span><span id="L-36"><a href="#L-36"><span class="linenos"> 36</span></a><span class="sd"> expression: Expression to qualify</span>
</span><span id="L-37"><a href="#L-37"><span class="linenos"> 37</span></a><span class="sd"> db: Database name</span>
</span><span id="L-38"><a href="#L-38"><span class="linenos"> 38</span></a><span class="sd"> catalog: Catalog name</span>
</span><span id="L-39"><a href="#L-39"><span class="linenos"> 39</span></a><span class="sd"> schema: A schema to populate</span>
</span><span id="L-40"><a href="#L-40"><span class="linenos"> 40</span></a><span class="sd"> dialect: The dialect to parse catalog and schema into.</span>
</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="sd"> Returns:</span>
</span><span id="L-43"><a href="#L-43"><span class="linenos"> 43</span></a><span class="sd"> The qualified expression.</span>
</span><span id="L-44"><a href="#L-44"><span class="linenos"> 44</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-45"><a href="#L-45"><span class="linenos"> 45</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-46"><a href="#L-46"><span class="linenos"> 46</span></a> <span class="n">db</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">parse_identifier</span><span class="p">(</span><span class="n">db</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">dialect</span><span class="p">)</span> <span class="k">if</span> <span class="n">db</span> <span class="k">else</span> <span class="kc">None</span>
</span><span id="L-47"><a href="#L-47"><span class="linenos"> 47</span></a> <span class="n">catalog</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">parse_identifier</span><span class="p">(</span><span class="n">catalog</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">dialect</span><span class="p">)</span> <span class="k">if</span> <span class="n">catalog</span> <span class="k">else</span> <span class="kc">None</span>
</span><span id="L-48"><a href="#L-48"><span class="linenos"> 48</span></a>
</span><span id="L-49"><a href="#L-49"><span class="linenos"> 49</span></a> <span class="k">def</span> <span class="nf">_qualify</span><span class="p">(</span><span class="n">table</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="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="L-50"><a href="#L-50"><span class="linenos"> 50</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">table</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-51"><a href="#L-51"><span class="linenos"> 51</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">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;db&quot;</span><span class="p">):</span>
</span><span id="L-52"><a href="#L-52"><span class="linenos"> 52</span></a> <span class="n">table</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">db</span><span class="p">)</span>
</span><span id="L-53"><a href="#L-53"><span class="linenos"> 53</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">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;catalog&quot;</span><span class="p">)</span> <span class="ow">and</span> <span class="n">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;db&quot;</span><span class="p">):</span>
</span><span id="L-54"><a href="#L-54"><span class="linenos"> 54</span></a> <span class="n">table</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">catalog</span><span class="p">)</span>
</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="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">expression</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Subqueryable</span><span class="p">):</span>
</span><span id="L-57"><a href="#L-57"><span class="linenos"> 57</span></a> <span class="k">for</span> <span class="n">node</span><span class="p">,</span> <span class="o">*</span><span class="n">_</span> <span class="ow">in</span> <span class="n">expression</span><span class="o">.</span><span class="n">walk</span><span class="p">(</span><span class="n">prune</span><span class="o">=</span><span class="k">lambda</span> <span class="n">n</span><span class="p">,</span> <span class="o">*</span><span class="n">_</span><span class="p">:</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Unionable</span><span class="p">)):</span>
</span><span id="L-58"><a href="#L-58"><span class="linenos"> 58</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">node</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-59"><a href="#L-59"><span class="linenos"> 59</span></a> <span class="n">_qualify</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>
</span><span id="L-60"><a href="#L-60"><span class="linenos"> 60</span></a>
</span><span id="L-61"><a href="#L-61"><span class="linenos"> 61</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-62"><a href="#L-62"><span class="linenos"> 62</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-63"><a href="#L-63"><span class="linenos"> 63</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-64"><a href="#L-64"><span class="linenos"> 64</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-65"><a href="#L-65"><span class="linenos"> 65</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-66"><a href="#L-66"><span class="linenos"> 66</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-67"><a href="#L-67"><span class="linenos"> 67</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-68"><a href="#L-68"><span class="linenos"> 68</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-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">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-71"><a href="#L-71"><span class="linenos"> 71</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-72"><a href="#L-72"><span class="linenos"> 72</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-73"><a href="#L-73"><span class="linenos"> 73</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-74"><a href="#L-74"><span class="linenos"> 74</span></a>
</span><span id="L-75"><a href="#L-75"><span class="linenos"> 75</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-76"><a href="#L-76"><span class="linenos"> 76</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-77"><a href="#L-77"><span class="linenos"> 77</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-78"><a href="#L-78"><span class="linenos"> 78</span></a>
</span><span id="L-79"><a href="#L-79"><span class="linenos"> 79</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-80"><a href="#L-80"><span class="linenos"> 80</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-81"><a href="#L-81"><span class="linenos"> 81</span></a> <span class="n">_qualify</span><span class="p">(</span><span class="n">source</span><span class="p">)</span>
</span><span id="L-82"><a href="#L-82"><span class="linenos"> 82</span></a>
</span><span id="L-83"><a href="#L-83"><span class="linenos"> 83</span></a> <span class="n">pivots</span> <span class="o">=</span> <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-84"><a href="#L-84"><span class="linenos"> 84</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-85"><a href="#L-85"><span class="linenos"> 85</span></a> <span class="c1"># Don&#39;t add the pivot&#39;s alias to the pivoted table, use the table&#39;s name instead</span>
</span><span id="L-86"><a href="#L-86"><span class="linenos"> 86</span></a> <span class="k">if</span> <span class="n">pivots</span> <span class="ow">and</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="o">==</span> <span class="n">name</span><span class="p">:</span>
</span><span id="L-87"><a href="#L-87"><span class="linenos"> 87</span></a> <span class="n">name</span> <span class="o">=</span> <span class="n">source</span><span class="o">.</span><span class="n">name</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 class="c1"># Mutates the source by attaching an alias to it</span>
</span><span id="L-90"><a href="#L-90"><span class="linenos"> 90</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-91"><a href="#L-91"><span class="linenos"> 91</span></a>
</span><span id="L-92"><a href="#L-92"><span class="linenos"> 92</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-93"><a href="#L-93"><span class="linenos"> 93</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-94"><a href="#L-94"><span class="linenos"> 94</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-95"><a href="#L-95"><span class="linenos"> 95</span></a> <span class="p">)</span>
</span><span id="L-96"><a href="#L-96"><span class="linenos"> 96</span></a>
</span><span id="L-97"><a href="#L-97"><span class="linenos"> 97</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-98"><a href="#L-98"><span class="linenos"> 98</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-99"><a href="#L-99"><span class="linenos"> 99</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-100"><a href="#L-100"><span class="linenos">100</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-101"><a href="#L-101"><span class="linenos">101</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-102"><a href="#L-102"><span class="linenos">102</span></a> <span class="n">source</span><span class="p">,</span>
</span><span id="L-103"><a href="#L-103"><span class="linenos">103</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-104"><a href="#L-104"><span class="linenos">104</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-105"><a href="#L-105"><span class="linenos">105</span></a> <span class="p">)</span>
</span><span id="L-106"><a href="#L-106"><span class="linenos">106</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-107"><a href="#L-107"><span class="linenos">107</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-108"><a href="#L-108"><span class="linenos">108</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-109"><a href="#L-109"><span class="linenos">109</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-110"><a href="#L-110"><span class="linenos">110</span></a> <span class="p">)</span>
</span><span id="L-111"><a href="#L-111"><span class="linenos">111</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-112"><a href="#L-112"><span class="linenos">112</span></a>
</span><span id="L-113"><a href="#L-113"><span class="linenos">113</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-114"><a href="#L-114"><span class="linenos">114</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-115"><a href="#L-115"><span class="linenos">115</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-116"><a href="#L-116"><span class="linenos">116</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-117"><a href="#L-117"><span class="linenos">117</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-118"><a href="#L-118"><span class="linenos">118</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-119"><a href="#L-119"><span class="linenos">119</span></a> <span class="k">for</span> <span class="n">node</span><span class="p">,</span> <span class="n">parent</span><span class="p">,</span> <span class="n">_</span> <span class="ow">in</span> <span class="n">scope</span><span class="o">.</span><span class="n">walk</span><span class="p">():</span>
</span><span id="L-120"><a href="#L-120"><span class="linenos">120</span></a> <span class="k">if</span> <span class="p">(</span>
</span><span id="L-121"><a href="#L-121"><span class="linenos">121</span></a> <span class="nb">isinstance</span><span class="p">(</span><span class="n">node</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-122"><a href="#L-122"><span class="linenos">122</span></a> <span class="ow">and</span> <span class="ow">not</span> <span class="n">node</span><span class="o">.</span><span class="n">alias</span>
</span><span id="L-123"><a href="#L-123"><span class="linenos">123</span></a> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">parent</span><span class="p">,</span> <span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">From</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Join</span><span class="p">))</span>
</span><span id="L-124"><a href="#L-124"><span class="linenos">124</span></a> <span class="p">):</span>
</span><span id="L-125"><a href="#L-125"><span class="linenos">125</span></a> <span class="c1"># Mutates the table by attaching an alias to it</span>
</span><span id="L-126"><a href="#L-126"><span class="linenos">126</span></a> <span class="n">alias</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">node</span><span class="o">.</span><span class="n">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-127"><a href="#L-127"><span class="linenos">127</span></a>
</span><span id="L-128"><a href="#L-128"><span class="linenos">128</span></a> <span class="k">return</span> <span class="n">expression</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.dialects.dialect</span> <span class="kn">import</span> <span class="n">DialectType</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.helper</span> <span class="kn">import</span> <span class="n">csv_reader</span><span class="p">,</span> <span class="n">name_sequence</span>
</span><span id="L-9"><a href="#L-9"><span class="linenos"> 9</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-10"><a href="#L-10"><span class="linenos"> 10</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-11"><a href="#L-11"><span class="linenos"> 11</span></a>
</span><span id="L-12"><a href="#L-12"><span class="linenos"> 12</span></a><span class="k">if</span> <span class="n">t</span><span class="o">.</span><span class="n">TYPE_CHECKING</span><span class="p">:</span>
</span><span id="L-13"><a href="#L-13"><span class="linenos"> 13</span></a> <span class="kn">from</span> <span class="nn">sqlglot._typing</span> <span class="kn">import</span> <span class="n">E</span>
</span><span id="L-14"><a href="#L-14"><span class="linenos"> 14</span></a>
</span><span id="L-15"><a href="#L-15"><span class="linenos"> 15</span></a>
</span><span id="L-16"><a href="#L-16"><span class="linenos"> 16</span></a><span class="k">def</span> <span class="nf">qualify_tables</span><span class="p">(</span>
</span><span id="L-17"><a href="#L-17"><span class="linenos"> 17</span></a> <span class="n">expression</span><span class="p">:</span> <span class="n">E</span><span class="p">,</span>
</span><span id="L-18"><a href="#L-18"><span class="linenos"> 18</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="o">|</span> <span class="n">exp</span><span class="o">.</span><span class="n">Identifier</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="L-19"><a href="#L-19"><span class="linenos"> 19</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="o">|</span> <span class="n">exp</span><span class="o">.</span><span class="n">Identifier</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="L-20"><a href="#L-20"><span class="linenos"> 20</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-21"><a href="#L-21"><span class="linenos"> 21</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-22"><a href="#L-22"><span class="linenos"> 22</span></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">E</span><span class="p">:</span>
</span><span id="L-23"><a href="#L-23"><span class="linenos"> 23</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-24"><a href="#L-24"><span class="linenos"> 24</span></a><span class="sd"> Rewrite sqlglot AST to have fully qualified tables. Join constructs such as</span>
</span><span id="L-25"><a href="#L-25"><span class="linenos"> 25</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-26"><a href="#L-26"><span class="linenos"> 26</span></a>
</span><span id="L-27"><a href="#L-27"><span class="linenos"> 27</span></a><span class="sd"> Examples:</span>
</span><span id="L-28"><a href="#L-28"><span class="linenos"> 28</span></a><span class="sd"> &gt;&gt;&gt; import sqlglot</span>
</span><span id="L-29"><a href="#L-29"><span class="linenos"> 29</span></a><span class="sd"> &gt;&gt;&gt; expression = sqlglot.parse_one(&quot;SELECT 1 FROM tbl&quot;)</span>
</span><span id="L-30"><a href="#L-30"><span class="linenos"> 30</span></a><span class="sd"> &gt;&gt;&gt; qualify_tables(expression, db=&quot;db&quot;).sql()</span>
</span><span id="L-31"><a href="#L-31"><span class="linenos"> 31</span></a><span class="sd"> &#39;SELECT 1 FROM db.tbl AS tbl&#39;</span>
</span><span id="L-32"><a href="#L-32"><span class="linenos"> 32</span></a><span class="sd"> &gt;&gt;&gt;</span>
</span><span id="L-33"><a href="#L-33"><span class="linenos"> 33</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-34"><a href="#L-34"><span class="linenos"> 34</span></a><span class="sd"> &gt;&gt;&gt; qualify_tables(expression).sql()</span>
</span><span id="L-35"><a href="#L-35"><span class="linenos"> 35</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-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"> Args:</span>
</span><span id="L-38"><a href="#L-38"><span class="linenos"> 38</span></a><span class="sd"> expression: Expression to qualify</span>
</span><span id="L-39"><a href="#L-39"><span class="linenos"> 39</span></a><span class="sd"> db: Database name</span>
</span><span id="L-40"><a href="#L-40"><span class="linenos"> 40</span></a><span class="sd"> catalog: Catalog name</span>
</span><span id="L-41"><a href="#L-41"><span class="linenos"> 41</span></a><span class="sd"> schema: A schema to populate</span>
</span><span id="L-42"><a href="#L-42"><span class="linenos"> 42</span></a><span class="sd"> dialect: The dialect to parse catalog and schema into.</span>
</span><span id="L-43"><a href="#L-43"><span class="linenos"> 43</span></a>
</span><span id="L-44"><a href="#L-44"><span class="linenos"> 44</span></a><span class="sd"> Returns:</span>
</span><span id="L-45"><a href="#L-45"><span class="linenos"> 45</span></a><span class="sd"> The qualified expression.</span>
</span><span id="L-46"><a href="#L-46"><span class="linenos"> 46</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-47"><a href="#L-47"><span class="linenos"> 47</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-48"><a href="#L-48"><span class="linenos"> 48</span></a> <span class="n">db</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">parse_identifier</span><span class="p">(</span><span class="n">db</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">dialect</span><span class="p">)</span> <span class="k">if</span> <span class="n">db</span> <span class="k">else</span> <span class="kc">None</span>
</span><span id="L-49"><a href="#L-49"><span class="linenos"> 49</span></a> <span class="n">catalog</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">parse_identifier</span><span class="p">(</span><span class="n">catalog</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">dialect</span><span class="p">)</span> <span class="k">if</span> <span class="n">catalog</span> <span class="k">else</span> <span class="kc">None</span>
</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">def</span> <span class="nf">_qualify</span><span class="p">(</span><span class="n">table</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="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="L-52"><a href="#L-52"><span class="linenos"> 52</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">table</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-53"><a href="#L-53"><span class="linenos"> 53</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">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;db&quot;</span><span class="p">):</span>
</span><span id="L-54"><a href="#L-54"><span class="linenos"> 54</span></a> <span class="n">table</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">db</span><span class="p">)</span>
</span><span id="L-55"><a href="#L-55"><span class="linenos"> 55</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">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;catalog&quot;</span><span class="p">)</span> <span class="ow">and</span> <span class="n">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;db&quot;</span><span class="p">):</span>
</span><span id="L-56"><a href="#L-56"><span class="linenos"> 56</span></a> <span class="n">table</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">catalog</span><span class="p">)</span>
</span><span id="L-57"><a href="#L-57"><span class="linenos"> 57</span></a>
</span><span id="L-58"><a href="#L-58"><span class="linenos"> 58</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">expression</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Subqueryable</span><span class="p">):</span>
</span><span id="L-59"><a href="#L-59"><span class="linenos"> 59</span></a> <span class="k">for</span> <span class="n">node</span><span class="p">,</span> <span class="o">*</span><span class="n">_</span> <span class="ow">in</span> <span class="n">expression</span><span class="o">.</span><span class="n">walk</span><span class="p">(</span><span class="n">prune</span><span class="o">=</span><span class="k">lambda</span> <span class="n">n</span><span class="p">,</span> <span class="o">*</span><span class="n">_</span><span class="p">:</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Unionable</span><span class="p">)):</span>
</span><span id="L-60"><a href="#L-60"><span class="linenos"> 60</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">node</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="n">_qualify</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>
</span><span id="L-62"><a href="#L-62"><span class="linenos"> 62</span></a>
</span><span id="L-63"><a href="#L-63"><span class="linenos"> 63</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-64"><a href="#L-64"><span class="linenos"> 64</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-65"><a href="#L-65"><span class="linenos"> 65</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-66"><a href="#L-66"><span class="linenos"> 66</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-67"><a href="#L-67"><span class="linenos"> 67</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-68"><a href="#L-68"><span class="linenos"> 68</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-69"><a href="#L-69"><span class="linenos"> 69</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-70"><a href="#L-70"><span class="linenos"> 70</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-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="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-73"><a href="#L-73"><span class="linenos"> 73</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-74"><a href="#L-74"><span class="linenos"> 74</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-75"><a href="#L-75"><span class="linenos"> 75</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-76"><a href="#L-76"><span class="linenos"> 76</span></a>
</span><span id="L-77"><a href="#L-77"><span class="linenos"> 77</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-78"><a href="#L-78"><span class="linenos"> 78</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-79"><a href="#L-79"><span class="linenos"> 79</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-80"><a href="#L-80"><span class="linenos"> 80</span></a>
</span><span id="L-81"><a href="#L-81"><span class="linenos"> 81</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-82"><a href="#L-82"><span class="linenos"> 82</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-83"><a href="#L-83"><span class="linenos"> 83</span></a> <span class="n">_qualify</span><span class="p">(</span><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><span id="L-85"><a href="#L-85"><span class="linenos"> 85</span></a> <span class="n">pivots</span> <span class="o">=</span> <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-86"><a href="#L-86"><span class="linenos"> 86</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-87"><a href="#L-87"><span class="linenos"> 87</span></a> <span class="c1"># Don&#39;t add the pivot&#39;s alias to the pivoted table, use the table&#39;s name instead</span>
</span><span id="L-88"><a href="#L-88"><span class="linenos"> 88</span></a> <span class="k">if</span> <span class="n">pivots</span> <span class="ow">and</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="o">==</span> <span class="n">name</span><span class="p">:</span>
</span><span id="L-89"><a href="#L-89"><span class="linenos"> 89</span></a> <span class="n">name</span> <span class="o">=</span> <span class="n">source</span><span class="o">.</span><span class="n">name</span>
</span><span id="L-90"><a href="#L-90"><span class="linenos"> 90</span></a>
</span><span id="L-91"><a href="#L-91"><span class="linenos"> 91</span></a> <span class="c1"># Mutates the source by attaching an alias to it</span>
</span><span id="L-92"><a href="#L-92"><span class="linenos"> 92</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-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="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-95"><a href="#L-95"><span class="linenos"> 95</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-96"><a href="#L-96"><span class="linenos"> 96</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-97"><a href="#L-97"><span class="linenos"> 97</span></a> <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="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-100"><a href="#L-100"><span class="linenos">100</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-101"><a href="#L-101"><span class="linenos">101</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-102"><a href="#L-102"><span class="linenos">102</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-103"><a href="#L-103"><span class="linenos">103</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-104"><a href="#L-104"><span class="linenos">104</span></a> <span class="n">source</span><span class="p">,</span>
</span><span id="L-105"><a href="#L-105"><span class="linenos">105</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-106"><a href="#L-106"><span class="linenos">106</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-107"><a href="#L-107"><span class="linenos">107</span></a> <span class="p">)</span>
</span><span id="L-108"><a href="#L-108"><span class="linenos">108</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-109"><a href="#L-109"><span class="linenos">109</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-110"><a href="#L-110"><span class="linenos">110</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-111"><a href="#L-111"><span class="linenos">111</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-112"><a href="#L-112"><span class="linenos">112</span></a> <span class="p">)</span>
</span><span id="L-113"><a href="#L-113"><span class="linenos">113</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-114"><a href="#L-114"><span class="linenos">114</span></a>
</span><span id="L-115"><a href="#L-115"><span class="linenos">115</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-116"><a href="#L-116"><span class="linenos">116</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-117"><a href="#L-117"><span class="linenos">117</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-118"><a href="#L-118"><span class="linenos">118</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-119"><a href="#L-119"><span class="linenos">119</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-120"><a href="#L-120"><span class="linenos">120</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 class="k">for</span> <span class="n">node</span><span class="p">,</span> <span class="n">parent</span><span class="p">,</span> <span class="n">_</span> <span class="ow">in</span> <span class="n">scope</span><span class="o">.</span><span class="n">walk</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="p">(</span>
</span><span id="L-123"><a href="#L-123"><span class="linenos">123</span></a> <span class="nb">isinstance</span><span class="p">(</span><span class="n">node</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-124"><a href="#L-124"><span class="linenos">124</span></a> <span class="ow">and</span> <span class="ow">not</span> <span class="n">node</span><span class="o">.</span><span class="n">alias</span>
</span><span id="L-125"><a href="#L-125"><span class="linenos">125</span></a> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">parent</span><span class="p">,</span> <span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">From</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Join</span><span class="p">))</span>
</span><span id="L-126"><a href="#L-126"><span class="linenos">126</span></a> <span class="p">):</span>
</span><span id="L-127"><a href="#L-127"><span class="linenos">127</span></a> <span class="c1"># Mutates the table by attaching an alias to it</span>
</span><span id="L-128"><a href="#L-128"><span class="linenos">128</span></a> <span class="n">alias</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">node</span><span class="o">.</span><span class="n">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-129"><a href="#L-129"><span class="linenos">129</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></pre></div>
@ -199,121 +201,121 @@
</div>
<a class="headerlink" href="#qualify_tables"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="qualify_tables-15"><a href="#qualify_tables-15"><span class="linenos"> 15</span></a><span class="k">def</span> <span class="nf">qualify_tables</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">expression</span><span class="p">:</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="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="o">|</span> <span class="n">exp</span><span class="o">.</span><span class="n">Identifier</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="qualify_tables-18"><a href="#qualify_tables-18"><span class="linenos"> 18</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="o">|</span> <span class="n">exp</span><span class="o">.</span><span class="n">Identifier</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="qualify_tables-19"><a href="#qualify_tables-19"><span class="linenos"> 19</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-20"><a href="#qualify_tables-20"><span class="linenos"> 20</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="qualify_tables-21"><a href="#qualify_tables-21"><span class="linenos"> 21</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-22"><a href="#qualify_tables-22"><span class="linenos"> 22</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="qualify_tables-23"><a href="#qualify_tables-23"><span class="linenos"> 23</span></a><span class="sd"> Rewrite sqlglot AST to have fully qualified tables. Join constructs such as</span>
</span><span id="qualify_tables-24"><a href="#qualify_tables-24"><span class="linenos"> 24</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-25"><a href="#qualify_tables-25"><span class="linenos"> 25</span></a>
</span><span id="qualify_tables-26"><a href="#qualify_tables-26"><span class="linenos"> 26</span></a><span class="sd"> Examples:</span>
</span><span id="qualify_tables-27"><a href="#qualify_tables-27"><span class="linenos"> 27</span></a><span class="sd"> &gt;&gt;&gt; import sqlglot</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 tbl&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, db=&quot;db&quot;).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 db.tbl AS tbl&#39;</span>
</span><span id="qualify_tables-31"><a href="#qualify_tables-31"><span class="linenos"> 31</span></a><span class="sd"> &gt;&gt;&gt;</span>
</span><span id="qualify_tables-32"><a href="#qualify_tables-32"><span class="linenos"> 32</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-33"><a href="#qualify_tables-33"><span class="linenos"> 33</span></a><span class="sd"> &gt;&gt;&gt; qualify_tables(expression).sql()</span>
</span><span id="qualify_tables-34"><a href="#qualify_tables-34"><span class="linenos"> 34</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-35"><a href="#qualify_tables-35"><span class="linenos"> 35</span></a>
</span><span id="qualify_tables-36"><a href="#qualify_tables-36"><span class="linenos"> 36</span></a><span class="sd"> Args:</span>
</span><span id="qualify_tables-37"><a href="#qualify_tables-37"><span class="linenos"> 37</span></a><span class="sd"> expression: Expression to qualify</span>
</span><span id="qualify_tables-38"><a href="#qualify_tables-38"><span class="linenos"> 38</span></a><span class="sd"> db: Database name</span>
</span><span id="qualify_tables-39"><a href="#qualify_tables-39"><span class="linenos"> 39</span></a><span class="sd"> catalog: Catalog name</span>
</span><span id="qualify_tables-40"><a href="#qualify_tables-40"><span class="linenos"> 40</span></a><span class="sd"> schema: A schema to populate</span>
</span><span id="qualify_tables-41"><a href="#qualify_tables-41"><span class="linenos"> 41</span></a><span class="sd"> dialect: The dialect to parse catalog and schema into.</span>
</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="sd"> Returns:</span>
</span><span id="qualify_tables-44"><a href="#qualify_tables-44"><span class="linenos"> 44</span></a><span class="sd"> The qualified expression.</span>
</span><span id="qualify_tables-45"><a href="#qualify_tables-45"><span class="linenos"> 45</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="qualify_tables-46"><a href="#qualify_tables-46"><span class="linenos"> 46</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-47"><a href="#qualify_tables-47"><span class="linenos"> 47</span></a> <span class="n">db</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">parse_identifier</span><span class="p">(</span><span class="n">db</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">dialect</span><span class="p">)</span> <span class="k">if</span> <span class="n">db</span> <span class="k">else</span> <span class="kc">None</span>
</span><span id="qualify_tables-48"><a href="#qualify_tables-48"><span class="linenos"> 48</span></a> <span class="n">catalog</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">parse_identifier</span><span class="p">(</span><span class="n">catalog</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">dialect</span><span class="p">)</span> <span class="k">if</span> <span class="n">catalog</span> <span class="k">else</span> <span class="kc">None</span>
</span><span id="qualify_tables-49"><a href="#qualify_tables-49"><span class="linenos"> 49</span></a>
</span><span id="qualify_tables-50"><a href="#qualify_tables-50"><span class="linenos"> 50</span></a> <span class="k">def</span> <span class="nf">_qualify</span><span class="p">(</span><span class="n">table</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="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="qualify_tables-51"><a href="#qualify_tables-51"><span class="linenos"> 51</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">table</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-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">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;db&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">table</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">db</span><span class="p">)</span>
</span><span id="qualify_tables-54"><a href="#qualify_tables-54"><span class="linenos"> 54</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">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;catalog&quot;</span><span class="p">)</span> <span class="ow">and</span> <span class="n">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;db&quot;</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">table</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">catalog</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-57"><a href="#qualify_tables-57"><span class="linenos"> 57</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">expression</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Subqueryable</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">for</span> <span class="n">node</span><span class="p">,</span> <span class="o">*</span><span class="n">_</span> <span class="ow">in</span> <span class="n">expression</span><span class="o">.</span><span class="n">walk</span><span class="p">(</span><span class="n">prune</span><span class="o">=</span><span class="k">lambda</span> <span class="n">n</span><span class="p">,</span> <span class="o">*</span><span class="n">_</span><span class="p">:</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Unionable</span><span class="p">)):</span>
</span><span id="qualify_tables-59"><a href="#qualify_tables-59"><span class="linenos"> 59</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">node</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-60"><a href="#qualify_tables-60"><span class="linenos"> 60</span></a> <span class="n">_qualify</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>
</span><span id="qualify_tables-61"><a href="#qualify_tables-61"><span class="linenos"> 61</span></a>
</span><span id="qualify_tables-62"><a href="#qualify_tables-62"><span class="linenos"> 62</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-63"><a href="#qualify_tables-63"><span class="linenos"> 63</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-64"><a href="#qualify_tables-64"><span class="linenos"> 64</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-65"><a href="#qualify_tables-65"><span class="linenos"> 65</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-66"><a href="#qualify_tables-66"><span class="linenos"> 66</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-67"><a href="#qualify_tables-67"><span class="linenos"> 67</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-68"><a href="#qualify_tables-68"><span class="linenos"> 68</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-69"><a href="#qualify_tables-69"><span class="linenos"> 69</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-70"><a href="#qualify_tables-70"><span class="linenos"> 70</span></a>
</span><span id="qualify_tables-71"><a href="#qualify_tables-71"><span class="linenos"> 71</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-72"><a href="#qualify_tables-72"><span class="linenos"> 72</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-73"><a href="#qualify_tables-73"><span class="linenos"> 73</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-74"><a href="#qualify_tables-74"><span class="linenos"> 74</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-75"><a href="#qualify_tables-75"><span class="linenos"> 75</span></a>
</span><span id="qualify_tables-76"><a href="#qualify_tables-76"><span class="linenos"> 76</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-77"><a href="#qualify_tables-77"><span class="linenos"> 77</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-78"><a href="#qualify_tables-78"><span class="linenos"> 78</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-79"><a href="#qualify_tables-79"><span class="linenos"> 79</span></a>
</span><span id="qualify_tables-80"><a href="#qualify_tables-80"><span class="linenos"> 80</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-81"><a href="#qualify_tables-81"><span class="linenos"> 81</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-82"><a href="#qualify_tables-82"><span class="linenos"> 82</span></a> <span class="n">_qualify</span><span class="p">(</span><span class="n">source</span><span class="p">)</span>
</span><span id="qualify_tables-83"><a href="#qualify_tables-83"><span class="linenos"> 83</span></a>
</span><span id="qualify_tables-84"><a href="#qualify_tables-84"><span class="linenos"> 84</span></a> <span class="n">pivots</span> <span class="o">=</span> <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-85"><a href="#qualify_tables-85"><span class="linenos"> 85</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-86"><a href="#qualify_tables-86"><span class="linenos"> 86</span></a> <span class="c1"># Don&#39;t add the pivot&#39;s alias to the pivoted table, use the table&#39;s name instead</span>
</span><span id="qualify_tables-87"><a href="#qualify_tables-87"><span class="linenos"> 87</span></a> <span class="k">if</span> <span class="n">pivots</span> <span class="ow">and</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="o">==</span> <span class="n">name</span><span class="p">:</span>
</span><span id="qualify_tables-88"><a href="#qualify_tables-88"><span class="linenos"> 88</span></a> <span class="n">name</span> <span class="o">=</span> <span class="n">source</span><span class="o">.</span><span class="n">name</span>
</span><span id="qualify_tables-89"><a href="#qualify_tables-89"><span class="linenos"> 89</span></a>
</span><span id="qualify_tables-90"><a href="#qualify_tables-90"><span class="linenos"> 90</span></a> <span class="c1"># Mutates the source by attaching an alias to it</span>
</span><span id="qualify_tables-91"><a href="#qualify_tables-91"><span class="linenos"> 91</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-92"><a href="#qualify_tables-92"><span class="linenos"> 92</span></a>
</span><span id="qualify_tables-93"><a href="#qualify_tables-93"><span class="linenos"> 93</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-94"><a href="#qualify_tables-94"><span class="linenos"> 94</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-95"><a href="#qualify_tables-95"><span class="linenos"> 95</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-96"><a href="#qualify_tables-96"><span class="linenos"> 96</span></a> <span class="p">)</span>
</span><span id="qualify_tables-97"><a href="#qualify_tables-97"><span class="linenos"> 97</span></a>
</span><span id="qualify_tables-98"><a href="#qualify_tables-98"><span class="linenos"> 98</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-99"><a href="#qualify_tables-99"><span class="linenos"> 99</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-100"><a href="#qualify_tables-100"><span class="linenos">100</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-101"><a href="#qualify_tables-101"><span class="linenos">101</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-102"><a href="#qualify_tables-102"><span class="linenos">102</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-103"><a href="#qualify_tables-103"><span class="linenos">103</span></a> <span class="n">source</span><span class="p">,</span>
</span><span id="qualify_tables-104"><a href="#qualify_tables-104"><span class="linenos">104</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-105"><a href="#qualify_tables-105"><span class="linenos">105</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-106"><a href="#qualify_tables-106"><span class="linenos">106</span></a> <span class="p">)</span>
</span><span id="qualify_tables-107"><a href="#qualify_tables-107"><span class="linenos">107</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-108"><a href="#qualify_tables-108"><span class="linenos">108</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-109"><a href="#qualify_tables-109"><span class="linenos">109</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-110"><a href="#qualify_tables-110"><span class="linenos">110</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-111"><a href="#qualify_tables-111"><span class="linenos">111</span></a> <span class="p">)</span>
</span><span id="qualify_tables-112"><a href="#qualify_tables-112"><span class="linenos">112</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-113"><a href="#qualify_tables-113"><span class="linenos">113</span></a>
</span><span id="qualify_tables-114"><a href="#qualify_tables-114"><span class="linenos">114</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-115"><a href="#qualify_tables-115"><span class="linenos">115</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-116"><a href="#qualify_tables-116"><span class="linenos">116</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-117"><a href="#qualify_tables-117"><span class="linenos">117</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-118"><a href="#qualify_tables-118"><span class="linenos">118</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-119"><a href="#qualify_tables-119"><span class="linenos">119</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="qualify_tables-120"><a href="#qualify_tables-120"><span class="linenos">120</span></a> <span class="k">for</span> <span class="n">node</span><span class="p">,</span> <span class="n">parent</span><span class="p">,</span> <span class="n">_</span> <span class="ow">in</span> <span class="n">scope</span><span class="o">.</span><span class="n">walk</span><span class="p">():</span>
</span><span id="qualify_tables-121"><a href="#qualify_tables-121"><span class="linenos">121</span></a> <span class="k">if</span> <span class="p">(</span>
</span><span id="qualify_tables-122"><a href="#qualify_tables-122"><span class="linenos">122</span></a> <span class="nb">isinstance</span><span class="p">(</span><span class="n">node</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-123"><a href="#qualify_tables-123"><span class="linenos">123</span></a> <span class="ow">and</span> <span class="ow">not</span> <span class="n">node</span><span class="o">.</span><span class="n">alias</span>
</span><span id="qualify_tables-124"><a href="#qualify_tables-124"><span class="linenos">124</span></a> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">parent</span><span class="p">,</span> <span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">From</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Join</span><span class="p">))</span>
</span><span id="qualify_tables-125"><a href="#qualify_tables-125"><span class="linenos">125</span></a> <span class="p">):</span>
</span><span id="qualify_tables-126"><a href="#qualify_tables-126"><span class="linenos">126</span></a> <span class="c1"># Mutates the table by attaching an alias to it</span>
</span><span id="qualify_tables-127"><a href="#qualify_tables-127"><span class="linenos">127</span></a> <span class="n">alias</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">node</span><span class="o">.</span><span class="n">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-128"><a href="#qualify_tables-128"><span class="linenos">128</span></a>
</span><span id="qualify_tables-129"><a href="#qualify_tables-129"><span class="linenos">129</span></a> <span class="k">return</span> <span class="n">expression</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="qualify_tables-17"><a href="#qualify_tables-17"><span class="linenos"> 17</span></a><span class="k">def</span> <span class="nf">qualify_tables</span><span class="p">(</span>
</span><span id="qualify_tables-18"><a href="#qualify_tables-18"><span class="linenos"> 18</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-19"><a href="#qualify_tables-19"><span class="linenos"> 19</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="o">|</span> <span class="n">exp</span><span class="o">.</span><span class="n">Identifier</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="qualify_tables-20"><a href="#qualify_tables-20"><span class="linenos"> 20</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="o">|</span> <span class="n">exp</span><span class="o">.</span><span class="n">Identifier</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="qualify_tables-21"><a href="#qualify_tables-21"><span class="linenos"> 21</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-22"><a href="#qualify_tables-22"><span class="linenos"> 22</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="qualify_tables-23"><a href="#qualify_tables-23"><span class="linenos"> 23</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-24"><a href="#qualify_tables-24"><span class="linenos"> 24</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="qualify_tables-25"><a href="#qualify_tables-25"><span class="linenos"> 25</span></a><span class="sd"> Rewrite sqlglot AST to have fully qualified tables. Join constructs such as</span>
</span><span id="qualify_tables-26"><a href="#qualify_tables-26"><span class="linenos"> 26</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-27"><a href="#qualify_tables-27"><span class="linenos"> 27</span></a>
</span><span id="qualify_tables-28"><a href="#qualify_tables-28"><span class="linenos"> 28</span></a><span class="sd"> Examples:</span>
</span><span id="qualify_tables-29"><a href="#qualify_tables-29"><span class="linenos"> 29</span></a><span class="sd"> &gt;&gt;&gt; import sqlglot</span>
</span><span id="qualify_tables-30"><a href="#qualify_tables-30"><span class="linenos"> 30</span></a><span class="sd"> &gt;&gt;&gt; expression = sqlglot.parse_one(&quot;SELECT 1 FROM tbl&quot;)</span>
</span><span id="qualify_tables-31"><a href="#qualify_tables-31"><span class="linenos"> 31</span></a><span class="sd"> &gt;&gt;&gt; qualify_tables(expression, db=&quot;db&quot;).sql()</span>
</span><span id="qualify_tables-32"><a href="#qualify_tables-32"><span class="linenos"> 32</span></a><span class="sd"> &#39;SELECT 1 FROM db.tbl AS tbl&#39;</span>
</span><span id="qualify_tables-33"><a href="#qualify_tables-33"><span class="linenos"> 33</span></a><span class="sd"> &gt;&gt;&gt;</span>
</span><span id="qualify_tables-34"><a href="#qualify_tables-34"><span class="linenos"> 34</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-35"><a href="#qualify_tables-35"><span class="linenos"> 35</span></a><span class="sd"> &gt;&gt;&gt; qualify_tables(expression).sql()</span>
</span><span id="qualify_tables-36"><a href="#qualify_tables-36"><span class="linenos"> 36</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-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"> Args:</span>
</span><span id="qualify_tables-39"><a href="#qualify_tables-39"><span class="linenos"> 39</span></a><span class="sd"> expression: Expression to qualify</span>
</span><span id="qualify_tables-40"><a href="#qualify_tables-40"><span class="linenos"> 40</span></a><span class="sd"> db: Database name</span>
</span><span id="qualify_tables-41"><a href="#qualify_tables-41"><span class="linenos"> 41</span></a><span class="sd"> catalog: Catalog name</span>
</span><span id="qualify_tables-42"><a href="#qualify_tables-42"><span class="linenos"> 42</span></a><span class="sd"> schema: A schema to populate</span>
</span><span id="qualify_tables-43"><a href="#qualify_tables-43"><span class="linenos"> 43</span></a><span class="sd"> dialect: The dialect to parse catalog and schema into.</span>
</span><span id="qualify_tables-44"><a href="#qualify_tables-44"><span class="linenos"> 44</span></a>
</span><span id="qualify_tables-45"><a href="#qualify_tables-45"><span class="linenos"> 45</span></a><span class="sd"> Returns:</span>
</span><span id="qualify_tables-46"><a href="#qualify_tables-46"><span class="linenos"> 46</span></a><span class="sd"> The qualified expression.</span>
</span><span id="qualify_tables-47"><a href="#qualify_tables-47"><span class="linenos"> 47</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="qualify_tables-48"><a href="#qualify_tables-48"><span class="linenos"> 48</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-49"><a href="#qualify_tables-49"><span class="linenos"> 49</span></a> <span class="n">db</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">parse_identifier</span><span class="p">(</span><span class="n">db</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">dialect</span><span class="p">)</span> <span class="k">if</span> <span class="n">db</span> <span class="k">else</span> <span class="kc">None</span>
</span><span id="qualify_tables-50"><a href="#qualify_tables-50"><span class="linenos"> 50</span></a> <span class="n">catalog</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">parse_identifier</span><span class="p">(</span><span class="n">catalog</span><span class="p">,</span> <span class="n">dialect</span><span class="o">=</span><span class="n">dialect</span><span class="p">)</span> <span class="k">if</span> <span class="n">catalog</span> <span class="k">else</span> <span class="kc">None</span>
</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">def</span> <span class="nf">_qualify</span><span class="p">(</span><span class="n">table</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="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="qualify_tables-53"><a href="#qualify_tables-53"><span class="linenos"> 53</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">table</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-54"><a href="#qualify_tables-54"><span class="linenos"> 54</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">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;db&quot;</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">table</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">db</span><span class="p">)</span>
</span><span id="qualify_tables-56"><a href="#qualify_tables-56"><span class="linenos"> 56</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">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;catalog&quot;</span><span class="p">)</span> <span class="ow">and</span> <span class="n">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;db&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">table</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">catalog</span><span class="p">)</span>
</span><span id="qualify_tables-58"><a href="#qualify_tables-58"><span class="linenos"> 58</span></a>
</span><span id="qualify_tables-59"><a href="#qualify_tables-59"><span class="linenos"> 59</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">expression</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Subqueryable</span><span class="p">):</span>
</span><span id="qualify_tables-60"><a href="#qualify_tables-60"><span class="linenos"> 60</span></a> <span class="k">for</span> <span class="n">node</span><span class="p">,</span> <span class="o">*</span><span class="n">_</span> <span class="ow">in</span> <span class="n">expression</span><span class="o">.</span><span class="n">walk</span><span class="p">(</span><span class="n">prune</span><span class="o">=</span><span class="k">lambda</span> <span class="n">n</span><span class="p">,</span> <span class="o">*</span><span class="n">_</span><span class="p">:</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Unionable</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">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">node</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="n">_qualify</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>
</span><span id="qualify_tables-63"><a href="#qualify_tables-63"><span class="linenos"> 63</span></a>
</span><span id="qualify_tables-64"><a href="#qualify_tables-64"><span class="linenos"> 64</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-65"><a href="#qualify_tables-65"><span class="linenos"> 65</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-66"><a href="#qualify_tables-66"><span class="linenos"> 66</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-67"><a href="#qualify_tables-67"><span class="linenos"> 67</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-68"><a href="#qualify_tables-68"><span class="linenos"> 68</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-69"><a href="#qualify_tables-69"><span class="linenos"> 69</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-70"><a href="#qualify_tables-70"><span class="linenos"> 70</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-71"><a href="#qualify_tables-71"><span class="linenos"> 71</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-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="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-74"><a href="#qualify_tables-74"><span class="linenos"> 74</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-75"><a href="#qualify_tables-75"><span class="linenos"> 75</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-76"><a href="#qualify_tables-76"><span class="linenos"> 76</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-77"><a href="#qualify_tables-77"><span class="linenos"> 77</span></a>
</span><span id="qualify_tables-78"><a href="#qualify_tables-78"><span class="linenos"> 78</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-79"><a href="#qualify_tables-79"><span class="linenos"> 79</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-80"><a href="#qualify_tables-80"><span class="linenos"> 80</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-81"><a href="#qualify_tables-81"><span class="linenos"> 81</span></a>
</span><span id="qualify_tables-82"><a href="#qualify_tables-82"><span class="linenos"> 82</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-83"><a href="#qualify_tables-83"><span class="linenos"> 83</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-84"><a href="#qualify_tables-84"><span class="linenos"> 84</span></a> <span class="n">_qualify</span><span class="p">(</span><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><span id="qualify_tables-86"><a href="#qualify_tables-86"><span class="linenos"> 86</span></a> <span class="n">pivots</span> <span class="o">=</span> <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-87"><a href="#qualify_tables-87"><span class="linenos"> 87</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-88"><a href="#qualify_tables-88"><span class="linenos"> 88</span></a> <span class="c1"># Don&#39;t add the pivot&#39;s alias to the pivoted table, use the table&#39;s name instead</span>
</span><span id="qualify_tables-89"><a href="#qualify_tables-89"><span class="linenos"> 89</span></a> <span class="k">if</span> <span class="n">pivots</span> <span class="ow">and</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="o">==</span> <span class="n">name</span><span class="p">:</span>
</span><span id="qualify_tables-90"><a href="#qualify_tables-90"><span class="linenos"> 90</span></a> <span class="n">name</span> <span class="o">=</span> <span class="n">source</span><span class="o">.</span><span class="n">name</span>
</span><span id="qualify_tables-91"><a href="#qualify_tables-91"><span class="linenos"> 91</span></a>
</span><span id="qualify_tables-92"><a href="#qualify_tables-92"><span class="linenos"> 92</span></a> <span class="c1"># Mutates the source by attaching an alias to it</span>
</span><span id="qualify_tables-93"><a href="#qualify_tables-93"><span class="linenos"> 93</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-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="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-96"><a href="#qualify_tables-96"><span class="linenos"> 96</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-97"><a href="#qualify_tables-97"><span class="linenos"> 97</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-98"><a href="#qualify_tables-98"><span class="linenos"> 98</span></a> <span class="p">)</span>
</span><span id="qualify_tables-99"><a href="#qualify_tables-99"><span class="linenos"> 99</span></a>
</span><span id="qualify_tables-100"><a href="#qualify_tables-100"><span class="linenos">100</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-101"><a href="#qualify_tables-101"><span class="linenos">101</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-102"><a href="#qualify_tables-102"><span class="linenos">102</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-103"><a href="#qualify_tables-103"><span class="linenos">103</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-104"><a href="#qualify_tables-104"><span class="linenos">104</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-105"><a href="#qualify_tables-105"><span class="linenos">105</span></a> <span class="n">source</span><span class="p">,</span>
</span><span id="qualify_tables-106"><a href="#qualify_tables-106"><span class="linenos">106</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-107"><a href="#qualify_tables-107"><span class="linenos">107</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-108"><a href="#qualify_tables-108"><span class="linenos">108</span></a> <span class="p">)</span>
</span><span id="qualify_tables-109"><a href="#qualify_tables-109"><span class="linenos">109</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-110"><a href="#qualify_tables-110"><span class="linenos">110</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-111"><a href="#qualify_tables-111"><span class="linenos">111</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-112"><a href="#qualify_tables-112"><span class="linenos">112</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-113"><a href="#qualify_tables-113"><span class="linenos">113</span></a> <span class="p">)</span>
</span><span id="qualify_tables-114"><a href="#qualify_tables-114"><span class="linenos">114</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-115"><a href="#qualify_tables-115"><span class="linenos">115</span></a>
</span><span id="qualify_tables-116"><a href="#qualify_tables-116"><span class="linenos">116</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-117"><a href="#qualify_tables-117"><span class="linenos">117</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-118"><a href="#qualify_tables-118"><span class="linenos">118</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-119"><a href="#qualify_tables-119"><span class="linenos">119</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-120"><a href="#qualify_tables-120"><span class="linenos">120</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-121"><a href="#qualify_tables-121"><span class="linenos">121</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="qualify_tables-122"><a href="#qualify_tables-122"><span class="linenos">122</span></a> <span class="k">for</span> <span class="n">node</span><span class="p">,</span> <span class="n">parent</span><span class="p">,</span> <span class="n">_</span> <span class="ow">in</span> <span class="n">scope</span><span class="o">.</span><span class="n">walk</span><span class="p">():</span>
</span><span id="qualify_tables-123"><a href="#qualify_tables-123"><span class="linenos">123</span></a> <span class="k">if</span> <span class="p">(</span>
</span><span id="qualify_tables-124"><a href="#qualify_tables-124"><span class="linenos">124</span></a> <span class="nb">isinstance</span><span class="p">(</span><span class="n">node</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-125"><a href="#qualify_tables-125"><span class="linenos">125</span></a> <span class="ow">and</span> <span class="ow">not</span> <span class="n">node</span><span class="o">.</span><span class="n">alias</span>
</span><span id="qualify_tables-126"><a href="#qualify_tables-126"><span class="linenos">126</span></a> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">parent</span><span class="p">,</span> <span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">From</span><span class="p">,</span> <span class="n">exp</span><span class="o">.</span><span class="n">Join</span><span class="p">))</span>
</span><span id="qualify_tables-127"><a href="#qualify_tables-127"><span class="linenos">127</span></a> <span class="p">):</span>
</span><span id="qualify_tables-128"><a href="#qualify_tables-128"><span class="linenos">128</span></a> <span class="c1"># Mutates the table by attaching an alias to it</span>
</span><span id="qualify_tables-129"><a href="#qualify_tables-129"><span class="linenos">129</span></a> <span class="n">alias</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">node</span><span class="o">.</span><span class="n">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-130"><a href="#qualify_tables-130"><span class="linenos">130</span></a>
</span><span id="qualify_tables-131"><a href="#qualify_tables-131"><span class="linenos">131</span></a> <span class="k">return</span> <span class="n">expression</span>
</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 one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -591,8 +591,8 @@
</span><span id="L-485"><a href="#L-485"><span class="linenos">485</span></a> <span class="n">expression_type</span> <span class="o">=</span> <span class="nb">type</span><span class="p">(</span><span class="n">expression</span><span class="p">)</span>
</span><span id="L-486"><a href="#L-486"><span class="linenos">486</span></a>
</span><span id="L-487"><a href="#L-487"><span class="linenos">487</span></a> <span class="n">expression</span> <span class="o">=</span> <span class="n">transforms</span><span class="p">[</span><span class="mi">0</span><span class="p">](</span><span class="n">expression</span><span class="p">)</span>
</span><span id="L-488"><a href="#L-488"><span class="linenos">488</span></a> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">transforms</span><span class="p">[</span><span class="mi">1</span><span class="p">:]:</span>
</span><span id="L-489"><a href="#L-489"><span class="linenos">489</span></a> <span class="n">expression</span> <span class="o">=</span> <span class="n">t</span><span class="p">(</span><span class="n">expression</span><span class="p">)</span>
</span><span id="L-488"><a href="#L-488"><span class="linenos">488</span></a> <span class="k">for</span> <span class="n">transform</span> <span class="ow">in</span> <span class="n">transforms</span><span class="p">[</span><span class="mi">1</span><span class="p">:]:</span>
</span><span id="L-489"><a href="#L-489"><span class="linenos">489</span></a> <span class="n">expression</span> <span class="o">=</span> <span class="n">transform</span><span class="p">(</span><span class="n">expression</span><span class="p">)</span>
</span><span id="L-490"><a href="#L-490"><span class="linenos">490</span></a>
</span><span id="L-491"><a href="#L-491"><span class="linenos">491</span></a> <span class="n">_sql_handler</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">expression</span><span class="o">.</span><span class="n">key</span> <span class="o">+</span> <span class="s2">&quot;_sql&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
</span><span id="L-492"><a href="#L-492"><span class="linenos">492</span></a> <span class="k">if</span> <span class="n">_sql_handler</span><span class="p">:</span>
@ -1426,8 +1426,8 @@ moved to the top level so that the final SQL code is valid from a syntax standpo
</span><span id="preprocess-486"><a href="#preprocess-486"><span class="linenos">486</span></a> <span class="n">expression_type</span> <span class="o">=</span> <span class="nb">type</span><span class="p">(</span><span class="n">expression</span><span class="p">)</span>
</span><span id="preprocess-487"><a href="#preprocess-487"><span class="linenos">487</span></a>
</span><span id="preprocess-488"><a href="#preprocess-488"><span class="linenos">488</span></a> <span class="n">expression</span> <span class="o">=</span> <span class="n">transforms</span><span class="p">[</span><span class="mi">0</span><span class="p">](</span><span class="n">expression</span><span class="p">)</span>
</span><span id="preprocess-489"><a href="#preprocess-489"><span class="linenos">489</span></a> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">transforms</span><span class="p">[</span><span class="mi">1</span><span class="p">:]:</span>
</span><span id="preprocess-490"><a href="#preprocess-490"><span class="linenos">490</span></a> <span class="n">expression</span> <span class="o">=</span> <span class="n">t</span><span class="p">(</span><span class="n">expression</span><span class="p">)</span>
</span><span id="preprocess-489"><a href="#preprocess-489"><span class="linenos">489</span></a> <span class="k">for</span> <span class="n">transform</span> <span class="ow">in</span> <span class="n">transforms</span><span class="p">[</span><span class="mi">1</span><span class="p">:]:</span>
</span><span id="preprocess-490"><a href="#preprocess-490"><span class="linenos">490</span></a> <span class="n">expression</span> <span class="o">=</span> <span class="n">transform</span><span class="p">(</span><span class="n">expression</span><span class="p">)</span>
</span><span id="preprocess-491"><a href="#preprocess-491"><span class="linenos">491</span></a>
</span><span id="preprocess-492"><a href="#preprocess-492"><span class="linenos">492</span></a> <span class="n">_sql_handler</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">expression</span><span class="o">.</span><span class="n">key</span> <span class="o">+</span> <span class="s2">&quot;_sql&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
</span><span id="preprocess-493"><a href="#preprocess-493"><span class="linenos">493</span></a> <span class="k">if</span> <span class="n">_sql_handler</span><span class="p">:</span>

View file

@ -7,7 +7,7 @@ from unittest import mock
from pdoc.__main__ import cli, parser
# Need this import or else import_module doesn't work
import sqlglot
import sqlglot # noqa
def mocked_import(*args, **kwargs):

View file

@ -29,16 +29,14 @@ setup(
python_requires=">=3.7",
extras_require={
"dev": [
"autoflake",
"black",
"duckdb>=0.6",
"isort",
"mypy>=0.990",
"mypy",
"pandas",
"pyspark",
"python-dateutil",
"pdoc",
"pre-commit",
"ruff",
"types-python-dateutil",
"typing_extensions",
"maturin>=1.4,<2.0",

View file

@ -1,3 +1,4 @@
# ruff: noqa: F401
"""
.. include:: ../README.md
@ -87,11 +88,13 @@ def parse(
@t.overload
def parse_one(sql: str, *, into: t.Type[E], **opts) -> E: ...
def parse_one(sql: str, *, into: t.Type[E], **opts) -> E:
...
@t.overload
def parse_one(sql: str, **opts) -> Expression: ...
def parse_one(sql: str, **opts) -> Expression:
...
def parse_one(

View file

@ -13,4 +13,5 @@ if t.TYPE_CHECKING:
A = t.TypeVar("A", bound=t.Any)
B = t.TypeVar("B", bound="sqlglot.exp.Binary")
E = t.TypeVar("E", bound="sqlglot.exp.Expression")
F = t.TypeVar("F", bound="sqlglot.exp.Func")
T = t.TypeVar("T")

View file

@ -140,10 +140,12 @@ class DataFrame:
return cte, name
@t.overload
def _ensure_list_of_columns(self, cols: t.Collection[ColumnOrLiteral]) -> t.List[Column]: ...
def _ensure_list_of_columns(self, cols: t.Collection[ColumnOrLiteral]) -> t.List[Column]:
...
@t.overload
def _ensure_list_of_columns(self, cols: ColumnOrLiteral) -> t.List[Column]: ...
def _ensure_list_of_columns(self, cols: ColumnOrLiteral) -> t.List[Column]:
...
def _ensure_list_of_columns(self, cols):
return Column.ensure_cols(ensure_list(cols))

View file

@ -368,7 +368,10 @@ def covar_samp(col1: ColumnOrName, col2: ColumnOrName) -> Column:
def first(col: ColumnOrName, ignorenulls: t.Optional[bool] = None) -> Column:
return Column.invoke_expression_over_column(col, expression.First, ignore_nulls=ignorenulls)
this = Column.invoke_expression_over_column(col, expression.First)
if ignorenulls:
return Column.invoke_expression_over_column(this, expression.IgnoreNulls)
return this
def grouping_id(*cols: ColumnOrName) -> Column:
@ -392,7 +395,10 @@ def isnull(col: ColumnOrName) -> Column:
def last(col: ColumnOrName, ignorenulls: t.Optional[bool] = None) -> Column:
return Column.invoke_expression_over_column(col, expression.Last, ignore_nulls=ignorenulls)
this = Column.invoke_expression_over_column(col, expression.Last)
if ignorenulls:
return Column.invoke_expression_over_column(this, expression.IgnoreNulls)
return this
def monotonically_increasing_id() -> Column:
@ -485,31 +491,28 @@ def factorial(col: ColumnOrName) -> Column:
def lag(
col: ColumnOrName, offset: t.Optional[int] = 1, default: t.Optional[ColumnOrLiteral] = None
) -> Column:
if default is not None:
return Column.invoke_anonymous_function(col, "LAG", offset, default)
if offset != 1:
return Column.invoke_anonymous_function(col, "LAG", offset)
return Column.invoke_anonymous_function(col, "LAG")
return Column.invoke_expression_over_column(
col, expression.Lag, offset=None if offset == 1 else offset, default=default
)
def lead(
col: ColumnOrName, offset: t.Optional[int] = 1, default: t.Optional[t.Any] = None
) -> Column:
if default is not None:
return Column.invoke_anonymous_function(col, "LEAD", offset, default)
if offset != 1:
return Column.invoke_anonymous_function(col, "LEAD", offset)
return Column.invoke_anonymous_function(col, "LEAD")
return Column.invoke_expression_over_column(
col, expression.Lead, offset=None if offset == 1 else offset, default=default
)
def nth_value(
col: ColumnOrName, offset: t.Optional[int] = 1, ignoreNulls: t.Optional[bool] = None
) -> Column:
this = Column.invoke_expression_over_column(
col, expression.NthValue, offset=None if offset == 1 else offset
)
if ignoreNulls is not None:
raise NotImplementedError("There is currently not support for `ignoreNulls` parameter")
if offset != 1:
return Column.invoke_anonymous_function(col, "NTH_VALUE", offset)
return Column.invoke_anonymous_function(col, "NTH_VALUE")
return Column.invoke_expression_over_column(this, expression.IgnoreNulls)
return this
def ntile(n: int) -> Column:

View file

@ -1,3 +1,4 @@
# ruff: noqa: F401
"""
## Dialects

View file

@ -19,7 +19,6 @@ from sqlglot.dialects.dialect import (
min_or_least,
no_ilike_sql,
parse_date_delta_with_interval,
path_to_jsonpath,
regexp_replace_sql,
rename_func,
timestrtotime_sql,
@ -458,8 +457,10 @@ class BigQuery(Dialect):
return this
def _parse_table_parts(self, schema: bool = False) -> exp.Table:
table = super()._parse_table_parts(schema=schema)
def _parse_table_parts(
self, schema: bool = False, is_db_reference: bool = False
) -> exp.Table:
table = super()._parse_table_parts(schema=schema, is_db_reference=is_db_reference)
if isinstance(table.this, exp.Identifier) and "." in table.name:
catalog, db, this, *rest = (
t.cast(t.Optional[exp.Expression], exp.to_identifier(x))
@ -474,10 +475,12 @@ class BigQuery(Dialect):
return table
@t.overload
def _parse_json_object(self, agg: Lit[False]) -> exp.JSONObject: ...
def _parse_json_object(self, agg: Lit[False]) -> exp.JSONObject:
...
@t.overload
def _parse_json_object(self, agg: Lit[True]) -> exp.JSONObjectAgg: ...
def _parse_json_object(self, agg: Lit[True]) -> exp.JSONObjectAgg:
...
def _parse_json_object(self, agg=False):
json_object = super()._parse_json_object()
@ -536,6 +539,8 @@ class BigQuery(Dialect):
UNPIVOT_ALIASES_ARE_IDENTIFIERS = False
JSON_KEY_VALUE_PAIR_SEP = ","
NULL_ORDERING_SUPPORTED = False
IGNORE_NULLS_IN_FUNC = True
JSON_PATH_SINGLE_QUOTE_ESCAPE = True
TRANSFORMS = {
**generator.Generator.TRANSFORMS,
@ -554,7 +559,8 @@ class BigQuery(Dialect):
exp.Create: _create_sql,
exp.CTE: transforms.preprocess([_pushdown_cte_column_names]),
exp.DateAdd: date_add_interval_sql("DATE", "ADD"),
exp.DateDiff: lambda self, e: f"DATE_DIFF({self.sql(e, 'this')}, {self.sql(e, 'expression')}, {self.sql(e.args.get('unit', 'DAY'))})",
exp.DateDiff: lambda self,
e: f"DATE_DIFF({self.sql(e, 'this')}, {self.sql(e, 'expression')}, {self.sql(e.args.get('unit', 'DAY'))})",
exp.DateFromParts: rename_func("DATE"),
exp.DateStrToDate: datestrtodate_sql,
exp.DateSub: date_add_interval_sql("DATE", "SUB"),
@ -565,7 +571,6 @@ class BigQuery(Dialect):
"DATETIME", self.func("TIMESTAMP", e.this, e.args.get("zone")), "'UTC'"
),
exp.GenerateSeries: rename_func("GENERATE_ARRAY"),
exp.GetPath: path_to_jsonpath(),
exp.GroupConcat: rename_func("STRING_AGG"),
exp.Hex: rename_func("TO_HEX"),
exp.If: if_sql(false_value="NULL"),
@ -597,12 +602,13 @@ class BigQuery(Dialect):
]
),
exp.SHA2: lambda self, e: self.func(
f"SHA256" if e.text("length") == "256" else "SHA512", e.this
"SHA256" if e.text("length") == "256" else "SHA512", e.this
),
exp.StabilityProperty: lambda self, e: (
f"DETERMINISTIC" if e.name == "IMMUTABLE" else "NOT DETERMINISTIC"
"DETERMINISTIC" if e.name == "IMMUTABLE" else "NOT DETERMINISTIC"
),
exp.StrToDate: lambda self, e: f"PARSE_DATE({self.format_time(e)}, {self.sql(e, 'this')})",
exp.StrToDate: lambda self,
e: f"PARSE_DATE({self.format_time(e)}, {self.sql(e, 'this')})",
exp.StrToTime: lambda self, e: self.func(
"PARSE_TIMESTAMP", self.format_time(e), e.this, e.args.get("zone")
),
@ -610,9 +616,10 @@ class BigQuery(Dialect):
exp.TimeFromParts: rename_func("TIME"),
exp.TimeSub: date_add_interval_sql("TIME", "SUB"),
exp.TimestampAdd: date_add_interval_sql("TIMESTAMP", "ADD"),
exp.TimestampDiff: rename_func("TIMESTAMP_DIFF"),
exp.TimestampSub: date_add_interval_sql("TIMESTAMP", "SUB"),
exp.TimeStrToTime: timestrtotime_sql,
exp.Trim: lambda self, e: self.func(f"TRIM", e.this, e.expression),
exp.Trim: lambda self, e: self.func("TRIM", e.this, e.expression),
exp.TsOrDsAdd: _ts_or_ds_add_sql,
exp.TsOrDsDiff: _ts_or_ds_diff_sql,
exp.TsOrDsToTime: rename_func("TIME"),
@ -623,6 +630,12 @@ class BigQuery(Dialect):
exp.VariancePop: rename_func("VAR_POP"),
}
SUPPORTED_JSON_PATH_PARTS = {
exp.JSONPathKey,
exp.JSONPathRoot,
exp.JSONPathSubscript,
}
TYPE_MAPPING = {
**generator.Generator.TYPE_MAPPING,
exp.DataType.Type.BIGDECIMAL: "BIGNUMERIC",

View file

@ -8,12 +8,15 @@ from sqlglot.dialects.dialect import (
arg_max_or_min_no_count,
date_delta_sql,
inline_array_sql,
json_extract_segments,
json_path_key_only_name,
no_pivot_sql,
parse_json_extract_path,
rename_func,
var_map_sql,
)
from sqlglot.errors import ParseError
from sqlglot.helper import seq_get
from sqlglot.helper import is_int, seq_get
from sqlglot.parser import parse_var_map
from sqlglot.tokens import Token, TokenType
@ -120,6 +123,9 @@ class ClickHouse(Dialect):
"DATEDIFF": lambda args: exp.DateDiff(
this=seq_get(args, 2), expression=seq_get(args, 1), unit=seq_get(args, 0)
),
"JSONEXTRACTSTRING": parse_json_extract_path(
exp.JSONExtractScalar, zero_based_indexing=False
),
"MAP": parse_var_map,
"MATCH": exp.RegexpLike.from_arg_list,
"RANDCANONICAL": exp.Rand.from_arg_list,
@ -354,9 +360,14 @@ class ClickHouse(Dialect):
joins: bool = False,
alias_tokens: t.Optional[t.Collection[TokenType]] = None,
parse_bracket: bool = False,
is_db_reference: bool = False,
) -> t.Optional[exp.Expression]:
this = super()._parse_table(
schema=schema, joins=joins, alias_tokens=alias_tokens, parse_bracket=parse_bracket
schema=schema,
joins=joins,
alias_tokens=alias_tokens,
parse_bracket=parse_bracket,
is_db_reference=is_db_reference,
)
if self._match(TokenType.FINAL):
@ -518,6 +529,12 @@ class ClickHouse(Dialect):
exp.DataType.Type.VARCHAR: "String",
}
SUPPORTED_JSON_PATH_PARTS = {
exp.JSONPathKey,
exp.JSONPathRoot,
exp.JSONPathSubscript,
}
TYPE_MAPPING = {
**generator.Generator.TYPE_MAPPING,
**STRING_TYPE_MAPPING,
@ -570,6 +587,10 @@ class ClickHouse(Dialect):
exp.Explode: rename_func("arrayJoin"),
exp.Final: lambda self, e: f"{self.sql(e, 'this')} FINAL",
exp.IsNan: rename_func("isNaN"),
exp.JSONExtract: json_extract_segments("JSONExtractString", quoted_index=False),
exp.JSONExtractScalar: json_extract_segments("JSONExtractString", quoted_index=False),
exp.JSONPathKey: json_path_key_only_name,
exp.JSONPathRoot: lambda *_: "",
exp.Map: lambda self, e: _lower_func(var_map_sql(self, e)),
exp.Nullif: rename_func("nullIf"),
exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}",
@ -579,7 +600,8 @@ class ClickHouse(Dialect):
exp.Rand: rename_func("randCanonical"),
exp.Select: transforms.preprocess([transforms.eliminate_qualify]),
exp.StartsWith: rename_func("startsWith"),
exp.StrPosition: lambda self, e: f"position({self.format_args(e.this, e.args.get('substr'), e.args.get('position'))})",
exp.StrPosition: lambda self,
e: f"position({self.format_args(e.this, e.args.get('substr'), e.args.get('position'))})",
exp.VarMap: lambda self, e: _lower_func(var_map_sql(self, e)),
exp.Xor: lambda self, e: self.func("xor", e.this, e.expression, *e.expressions),
}
@ -608,6 +630,13 @@ class ClickHouse(Dialect):
"NAMED COLLECTION",
}
def _jsonpathsubscript_sql(self, expression: exp.JSONPathSubscript) -> str:
this = self.json_path_part(expression.this)
return str(int(this) + 1) if is_int(this) else this
def likeproperty_sql(self, expression: exp.LikeProperty) -> str:
return f"AS {self.sql(expression, 'this')}"
def _any_to_has(
self,
expression: exp.EQ | exp.NEQ,

View file

@ -22,6 +22,7 @@ class Databricks(Spark):
"DATEADD": parse_date_delta(exp.DateAdd),
"DATE_ADD": parse_date_delta(exp.DateAdd),
"DATEDIFF": parse_date_delta(exp.DateDiff),
"TIMESTAMPDIFF": parse_date_delta(exp.TimestampDiff),
}
FACTOR = {
@ -48,6 +49,9 @@ class Databricks(Spark):
exp.DatetimeDiff: lambda self, e: self.func(
"TIMESTAMPDIFF", e.text("unit"), e.expression, e.this
),
exp.TimestampDiff: lambda self, e: self.func(
"TIMESTAMPDIFF", e.text("unit"), e.expression, e.this
),
exp.DatetimeTrunc: timestamptrunc_sql,
exp.JSONExtract: lambda self, e: self.binary(e, ":"),
exp.Select: transforms.preprocess(

View file

@ -1,5 +1,6 @@
from __future__ import annotations
import logging
import typing as t
from enum import Enum, auto
from functools import reduce
@ -7,7 +8,8 @@ from functools import reduce
from sqlglot import exp
from sqlglot.errors import ParseError
from sqlglot.generator import Generator
from sqlglot.helper import AutoName, flatten, seq_get
from sqlglot.helper import AutoName, flatten, is_int, seq_get
from sqlglot.jsonpath import parse as parse_json_path
from sqlglot.parser import Parser
from sqlglot.time import TIMEZONES, format_time
from sqlglot.tokens import Token, Tokenizer, TokenType
@ -17,7 +19,11 @@ DATE_ADD_OR_DIFF = t.Union[exp.DateAdd, exp.TsOrDsAdd, exp.DateDiff, exp.TsOrDsD
DATE_ADD_OR_SUB = t.Union[exp.DateAdd, exp.TsOrDsAdd, exp.DateSub]
if t.TYPE_CHECKING:
from sqlglot._typing import B, E
from sqlglot._typing import B, E, F
JSON_EXTRACT_TYPE = t.Union[exp.JSONExtract, exp.JSONExtractScalar]
logger = logging.getLogger("sqlglot")
class Dialects(str, Enum):
@ -256,7 +262,7 @@ class Dialect(metaclass=_Dialect):
INVERSE_ESCAPE_SEQUENCES: t.Dict[str, str] = {}
# Delimiters for quotes, identifiers and the corresponding escape characters
# Delimiters for string literals and identifiers
QUOTE_START = "'"
QUOTE_END = "'"
IDENTIFIER_START = '"'
@ -373,7 +379,7 @@ class Dialect(metaclass=_Dialect):
"""
if (
isinstance(expression, exp.Identifier)
and not self.normalization_strategy is NormalizationStrategy.CASE_SENSITIVE
and self.normalization_strategy is not NormalizationStrategy.CASE_SENSITIVE
and (
not expression.quoted
or self.normalization_strategy is NormalizationStrategy.CASE_INSENSITIVE
@ -440,6 +446,19 @@ class Dialect(metaclass=_Dialect):
return expression
def to_json_path(self, path: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
if isinstance(path, exp.Literal):
path_text = path.name
if path.is_number:
path_text = f"[{path_text}]"
try:
return parse_json_path(path_text)
except ParseError as e:
logger.warning(f"Invalid JSON path syntax. {str(e)}")
return path
def parse(self, sql: str, **opts) -> t.List[t.Optional[exp.Expression]]:
return self.parser(**opts).parse(self.tokenize(sql), sql)
@ -500,14 +519,12 @@ def if_sql(
return _if_sql
def arrow_json_extract_sql(self: Generator, expression: exp.JSONExtract | exp.JSONBExtract) -> str:
return self.binary(expression, "->")
def arrow_json_extract_sql(self: Generator, expression: JSON_EXTRACT_TYPE) -> str:
this = expression.this
if self.JSON_TYPE_REQUIRED_FOR_EXTRACTION and isinstance(this, exp.Literal) and this.is_string:
this.replace(exp.cast(this, "json"))
def arrow_json_extract_scalar_sql(
self: Generator, expression: exp.JSONExtractScalar | exp.JSONBExtractScalar
) -> str:
return self.binary(expression, "->>")
return self.binary(expression, "->" if isinstance(expression, exp.JSONExtract) else "->>")
def inline_array_sql(self: Generator, expression: exp.Array) -> str:
@ -552,11 +569,6 @@ def no_trycast_sql(self: Generator, expression: exp.TryCast) -> str:
return self.cast_sql(expression)
def no_properties_sql(self: Generator, expression: exp.Properties) -> str:
self.unsupported("Properties unsupported")
return ""
def no_comment_column_constraint_sql(
self: Generator, expression: exp.CommentColumnConstraint
) -> str:
@ -965,32 +977,6 @@ def date_delta_sql(name: str, cast: bool = False) -> t.Callable[[Generator, DATE
return _delta_sql
def prepend_dollar_to_path(expression: exp.GetPath) -> exp.GetPath:
from sqlglot.optimizer.simplify import simplify
# Makes sure the path will be evaluated correctly at runtime to include the path root.
# For example, `[0].foo` will become `$[0].foo`, and `foo` will become `$.foo`.
path = expression.expression
path = exp.func(
"if",
exp.func("startswith", path, "'['"),
exp.func("concat", "'$'", path),
exp.func("concat", "'$.'", path),
)
expression.expression.replace(simplify(path))
return expression
def path_to_jsonpath(
name: str = "JSON_EXTRACT",
) -> t.Callable[[Generator, exp.GetPath], str]:
def _transform(self: Generator, expression: exp.GetPath) -> str:
return rename_func(name)(self, prepend_dollar_to_path(expression))
return _transform
def no_last_day_sql(self: Generator, expression: exp.LastDay) -> str:
trunc_curr_date = exp.func("date_trunc", "month", expression.this)
plus_one_month = exp.func("date_add", trunc_curr_date, 1, "month")
@ -1003,9 +989,8 @@ def merge_without_target_sql(self: Generator, expression: exp.Merge) -> str:
"""Remove table refs from columns in when statements."""
alias = expression.this.args.get("alias")
normalize = lambda identifier: (
self.dialect.normalize_identifier(identifier).name if identifier else None
)
def normalize(identifier: t.Optional[exp.Identifier]) -> t.Optional[str]:
return self.dialect.normalize_identifier(identifier).name if identifier else None
targets = {normalize(expression.this.this)}
@ -1023,3 +1008,60 @@ def merge_without_target_sql(self: Generator, expression: exp.Merge) -> str:
)
return self.merge_sql(expression)
def parse_json_extract_path(
expr_type: t.Type[F], zero_based_indexing: bool = True
) -> t.Callable[[t.List], F]:
def _parse_json_extract_path(args: t.List) -> F:
segments: t.List[exp.JSONPathPart] = [exp.JSONPathRoot()]
for arg in args[1:]:
if not isinstance(arg, exp.Literal):
# We use the fallback parser because we can't really transpile non-literals safely
return expr_type.from_arg_list(args)
text = arg.name
if is_int(text):
index = int(text)
segments.append(
exp.JSONPathSubscript(this=index if zero_based_indexing else index - 1)
)
else:
segments.append(exp.JSONPathKey(this=text))
# This is done to avoid failing in the expression validator due to the arg count
del args[2:]
return expr_type(this=seq_get(args, 0), expression=exp.JSONPath(expressions=segments))
return _parse_json_extract_path
def json_extract_segments(
name: str, quoted_index: bool = True
) -> t.Callable[[Generator, JSON_EXTRACT_TYPE], str]:
def _json_extract_segments(self: Generator, expression: JSON_EXTRACT_TYPE) -> str:
path = expression.expression
if not isinstance(path, exp.JSONPath):
return rename_func(name)(self, expression)
segments = []
for segment in path.expressions:
path = self.sql(segment)
if path:
if isinstance(segment, exp.JSONPathPart) and (
quoted_index or not isinstance(segment, exp.JSONPathSubscript)
):
path = f"{self.dialect.QUOTE_START}{path}{self.dialect.QUOTE_END}"
segments.append(path)
return self.func(name, expression.this, *segments)
return _json_extract_segments
def json_path_key_only_name(self: Generator, expression: exp.JSONPathKey) -> str:
if isinstance(expression.this, exp.JSONPathWildcard):
self.unsupported("Unsupported wildcard in JSONPathKey expression")
return expression.name

View file

@ -55,11 +55,14 @@ class Doris(MySQL):
exp.Map: rename_func("ARRAY_MAP"),
exp.RegexpLike: rename_func("REGEXP"),
exp.RegexpSplit: rename_func("SPLIT_BY_STRING"),
exp.StrToUnix: lambda self, e: f"UNIX_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})",
exp.StrToUnix: lambda self,
e: f"UNIX_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})",
exp.Split: rename_func("SPLIT_BY_STRING"),
exp.TimeStrToDate: rename_func("TO_DATE"),
exp.ToChar: lambda self, e: f"DATE_FORMAT({self.sql(e, 'this')}, {self.format_time(e)})",
exp.TsOrDsAdd: lambda self, e: f"DATE_ADD({self.sql(e, 'this')}, {self.sql(e, 'expression')})", # Only for day level
exp.ToChar: lambda self,
e: f"DATE_FORMAT({self.sql(e, 'this')}, {self.format_time(e)})",
exp.TsOrDsAdd: lambda self,
e: f"DATE_ADD({self.sql(e, 'this')}, {self.sql(e, 'expression')})", # Only for day level
exp.TsOrDsToDate: lambda self, e: self.func("TO_DATE", e.this),
exp.TimeToUnix: rename_func("UNIX_TIMESTAMP"),
exp.TimestampTrunc: lambda self, e: self.func(

View file

@ -99,6 +99,7 @@ class Drill(Dialect):
QUERY_HINTS = False
NVL2_SUPPORTED = False
LAST_DAY_SUPPORTS_DATE_PART = False
SUPPORTS_CREATE_TABLE_LIKE = False
TYPE_MAPPING = {
**generator.Generator.TYPE_MAPPING,
@ -128,10 +129,14 @@ class Drill(Dialect):
exp.DateAdd: _date_add_sql("ADD"),
exp.DateStrToDate: datestrtodate_sql,
exp.DateSub: _date_add_sql("SUB"),
exp.DateToDi: lambda self, e: f"CAST(TO_DATE({self.sql(e, 'this')}, {Drill.DATEINT_FORMAT}) AS INT)",
exp.DiToDate: lambda self, e: f"TO_DATE(CAST({self.sql(e, 'this')} AS VARCHAR), {Drill.DATEINT_FORMAT})",
exp.If: lambda self, e: f"`IF`({self.format_args(e.this, e.args.get('true'), e.args.get('false'))})",
exp.ILike: lambda self, e: f" {self.sql(e, 'this')} `ILIKE` {self.sql(e, 'expression')}",
exp.DateToDi: lambda self,
e: f"CAST(TO_DATE({self.sql(e, 'this')}, {Drill.DATEINT_FORMAT}) AS INT)",
exp.DiToDate: lambda self,
e: f"TO_DATE(CAST({self.sql(e, 'this')} AS VARCHAR), {Drill.DATEINT_FORMAT})",
exp.If: lambda self,
e: f"`IF`({self.format_args(e.this, e.args.get('true'), e.args.get('false'))})",
exp.ILike: lambda self,
e: f" {self.sql(e, 'this')} `ILIKE` {self.sql(e, 'expression')}",
exp.Levenshtein: rename_func("LEVENSHTEIN_DISTANCE"),
exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}",
exp.RegexpLike: rename_func("REGEXP_MATCHES"),
@ -141,7 +146,8 @@ class Drill(Dialect):
exp.Select: transforms.preprocess(
[transforms.eliminate_distinct_on, transforms.eliminate_semi_and_anti_joins]
),
exp.StrToTime: lambda self, e: f"TO_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})",
exp.StrToTime: lambda self,
e: f"TO_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})",
exp.TimeStrToDate: lambda self, e: f"CAST({self.sql(e, 'this')} AS DATE)",
exp.TimeStrToTime: timestrtotime_sql,
exp.TimeStrToUnix: rename_func("UNIX_TIMESTAMP"),
@ -149,8 +155,10 @@ class Drill(Dialect):
exp.TimeToUnix: rename_func("UNIX_TIMESTAMP"),
exp.ToChar: lambda self, e: self.function_fallback_sql(e),
exp.TryCast: no_trycast_sql,
exp.TsOrDsAdd: lambda self, e: f"DATE_ADD(CAST({self.sql(e, 'this')} AS DATE), {self.sql(exp.Interval(this=e.expression, unit=exp.var('DAY')))})",
exp.TsOrDiToDi: lambda self, e: f"CAST(SUBSTR(REPLACE(CAST({self.sql(e, 'this')} AS VARCHAR), '-', ''), 1, 8) AS INT)",
exp.TsOrDsAdd: lambda self,
e: f"DATE_ADD(CAST({self.sql(e, 'this')} AS DATE), {self.sql(exp.Interval(this=e.expression, unit=exp.var('DAY')))})",
exp.TsOrDiToDi: lambda self,
e: f"CAST(SUBSTR(REPLACE(CAST({self.sql(e, 'this')} AS VARCHAR), '-', ''), 1, 8) AS INT)",
}
def normalize_func(self, name: str) -> str:

View file

@ -8,7 +8,6 @@ from sqlglot.dialects.dialect import (
NormalizationStrategy,
approx_count_distinct_sql,
arg_max_or_min_no_count,
arrow_json_extract_scalar_sql,
arrow_json_extract_sql,
binary_from_function,
bool_xor_sql,
@ -18,11 +17,9 @@ from sqlglot.dialects.dialect import (
format_time_lambda,
inline_array_sql,
no_comment_column_constraint_sql,
no_properties_sql,
no_safe_divide_sql,
no_timestamp_sql,
pivot_column_names,
prepend_dollar_to_path,
regexp_extract_sql,
rename_func,
str_position_sql,
@ -172,6 +169,18 @@ class DuckDB(Dialect):
# https://duckdb.org/docs/sql/introduction.html#creating-a-new-table
NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_INSENSITIVE
def to_json_path(self, path: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
if isinstance(path, exp.Literal):
# DuckDB also supports the JSON pointer syntax, where every path starts with a `/`.
# Additionally, it allows accessing the back of lists using the `[#-i]` syntax.
# This check ensures we'll avoid trying to parse these as JSON paths, which can
# either result in a noisy warning or in an invalid representation of the path.
path_text = path.name
if path_text.startswith("/") or "[#" in path_text:
return path
return super().to_json_path(path)
class Tokenizer(tokens.Tokenizer):
KEYWORDS = {
**tokens.Tokenizer.KEYWORDS,
@ -229,6 +238,8 @@ class DuckDB(Dialect):
this=seq_get(args, 0), scale=exp.UnixToTime.MILLIS
),
"JSON": exp.ParseJSON.from_arg_list,
"JSON_EXTRACT_PATH": parser.parse_extract_json_with_path(exp.JSONExtract),
"JSON_EXTRACT_STRING": parser.parse_extract_json_with_path(exp.JSONExtractScalar),
"LIST_HAS": exp.ArrayContains.from_arg_list,
"LIST_REVERSE_SORT": _sort_array_reverse,
"LIST_SORT": exp.SortArray.from_arg_list,
@ -319,6 +330,9 @@ class DuckDB(Dialect):
TABLESAMPLE_SEED_KEYWORD = "REPEATABLE"
LAST_DAY_SUPPORTS_DATE_PART = False
JSON_KEY_VALUE_PAIR_SEP = ","
IGNORE_NULLS_IN_FUNC = True
JSON_PATH_BRACKETED_KEY_SUPPORTED = False
SUPPORTS_CREATE_TABLE_LIKE = False
TRANSFORMS = {
**generator.Generator.TRANSFORMS,
@ -350,18 +364,18 @@ class DuckDB(Dialect):
"DATE_DIFF", f"'{e.args.get('unit') or 'DAY'}'", e.expression, e.this
),
exp.DateStrToDate: datestrtodate_sql,
exp.DateToDi: lambda self, e: f"CAST(STRFTIME({self.sql(e, 'this')}, {DuckDB.DATEINT_FORMAT}) AS INT)",
exp.DateToDi: lambda self,
e: f"CAST(STRFTIME({self.sql(e, 'this')}, {DuckDB.DATEINT_FORMAT}) AS INT)",
exp.Decode: lambda self, e: encode_decode_sql(self, e, "DECODE", replace=False),
exp.DiToDate: lambda self, e: f"CAST(STRPTIME(CAST({self.sql(e, 'this')} AS TEXT), {DuckDB.DATEINT_FORMAT}) AS DATE)",
exp.DiToDate: lambda self,
e: f"CAST(STRPTIME(CAST({self.sql(e, 'this')} AS TEXT), {DuckDB.DATEINT_FORMAT}) AS DATE)",
exp.Encode: lambda self, e: encode_decode_sql(self, e, "ENCODE", replace=False),
exp.Explode: rename_func("UNNEST"),
exp.IntDiv: lambda self, e: self.binary(e, "//"),
exp.IsInf: rename_func("ISINF"),
exp.IsNan: rename_func("ISNAN"),
exp.JSONBExtract: arrow_json_extract_sql,
exp.JSONBExtractScalar: arrow_json_extract_scalar_sql,
exp.JSONExtract: arrow_json_extract_sql,
exp.JSONExtractScalar: arrow_json_extract_scalar_sql,
exp.JSONExtractScalar: arrow_json_extract_sql,
exp.JSONFormat: _json_format_sql,
exp.LogicalOr: rename_func("BOOL_OR"),
exp.LogicalAnd: rename_func("BOOL_AND"),
@ -377,7 +391,6 @@ class DuckDB(Dialect):
# DuckDB doesn't allow qualified columns inside of PIVOT expressions.
# See: https://github.com/duckdb/duckdb/blob/671faf92411182f81dce42ac43de8bfb05d9909e/src/planner/binder/tableref/bind_pivot.cpp#L61-L62
exp.Pivot: transforms.preprocess([transforms.unqualify_columns]),
exp.Properties: no_properties_sql,
exp.RegexpExtract: regexp_extract_sql,
exp.RegexpReplace: lambda self, e: self.func(
"REGEXP_REPLACE",
@ -395,7 +408,8 @@ class DuckDB(Dialect):
exp.StrPosition: str_position_sql,
exp.StrToDate: lambda self, e: f"CAST({str_to_time_sql(self, e)} AS DATE)",
exp.StrToTime: str_to_time_sql,
exp.StrToUnix: lambda self, e: f"EPOCH(STRPTIME({self.sql(e, 'this')}, {self.format_time(e)}))",
exp.StrToUnix: lambda self,
e: f"EPOCH(STRPTIME({self.sql(e, 'this')}, {self.format_time(e)}))",
exp.Struct: _struct_sql,
exp.Timestamp: no_timestamp_sql,
exp.TimestampDiff: lambda self, e: self.func(
@ -405,9 +419,11 @@ class DuckDB(Dialect):
exp.TimeStrToDate: lambda self, e: f"CAST({self.sql(e, 'this')} AS DATE)",
exp.TimeStrToTime: timestrtotime_sql,
exp.TimeStrToUnix: lambda self, e: f"EPOCH(CAST({self.sql(e, 'this')} AS TIMESTAMP))",
exp.TimeToStr: lambda self, e: f"STRFTIME({self.sql(e, 'this')}, {self.format_time(e)})",
exp.TimeToStr: lambda self,
e: f"STRFTIME({self.sql(e, 'this')}, {self.format_time(e)})",
exp.TimeToUnix: rename_func("EPOCH"),
exp.TsOrDiToDi: lambda self, e: f"CAST(SUBSTR(REPLACE(CAST({self.sql(e, 'this')} AS TEXT), '-', ''), 1, 8) AS INT)",
exp.TsOrDiToDi: lambda self,
e: f"CAST(SUBSTR(REPLACE(CAST({self.sql(e, 'this')} AS TEXT), '-', ''), 1, 8) AS INT)",
exp.TsOrDsAdd: _ts_or_ds_add_sql,
exp.TsOrDsDiff: lambda self, e: self.func(
"DATE_DIFF",
@ -415,7 +431,8 @@ class DuckDB(Dialect):
exp.cast(e.expression, "TIMESTAMP"),
exp.cast(e.this, "TIMESTAMP"),
),
exp.UnixToStr: lambda self, e: f"STRFTIME(TO_TIMESTAMP({self.sql(e, 'this')}), {self.format_time(e)})",
exp.UnixToStr: lambda self,
e: f"STRFTIME(TO_TIMESTAMP({self.sql(e, 'this')}), {self.format_time(e)})",
exp.UnixToTime: _unix_to_time_sql,
exp.UnixToTimeStr: lambda self, e: f"CAST(TO_TIMESTAMP({self.sql(e, 'this')}) AS TEXT)",
exp.VariancePop: rename_func("VAR_POP"),
@ -423,6 +440,13 @@ class DuckDB(Dialect):
exp.Xor: bool_xor_sql,
}
SUPPORTED_JSON_PATH_PARTS = {
exp.JSONPathKey,
exp.JSONPathRoot,
exp.JSONPathSubscript,
exp.JSONPathWildcard,
}
TYPE_MAPPING = {
**generator.Generator.TYPE_MAPPING,
exp.DataType.Type.BINARY: "BLOB",
@ -442,11 +466,18 @@ class DuckDB(Dialect):
UNWRAPPED_INTERVAL_VALUES = (exp.Column, exp.Literal, exp.Paren)
# DuckDB doesn't generally support CREATE TABLE .. properties
# https://duckdb.org/docs/sql/statements/create_table.html
PROPERTIES_LOCATION = {
**generator.Generator.PROPERTIES_LOCATION,
exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED,
prop: exp.Properties.Location.UNSUPPORTED
for prop in generator.Generator.PROPERTIES_LOCATION
}
# There are a few exceptions (e.g. temporary tables) which are supported or
# can be transpiled to DuckDB, so we explicitly override them accordingly
PROPERTIES_LOCATION[exp.LikeProperty] = exp.Properties.Location.POST_SCHEMA
PROPERTIES_LOCATION[exp.TemporaryProperty] = exp.Properties.Location.POST_CREATE
def timefromparts_sql(self, expression: exp.TimeFromParts) -> str:
nano = expression.args.get("nano")
if nano is not None:
@ -486,10 +517,6 @@ class DuckDB(Dialect):
expression, sep=sep, tablesample_keyword=tablesample_keyword
)
def getpath_sql(self, expression: exp.GetPath) -> str:
expression = prepend_dollar_to_path(expression)
return f"{self.sql(expression, 'this')} -> {self.sql(expression, 'expression')}"
def interval_sql(self, expression: exp.Interval) -> str:
multiplier: t.Optional[int] = None
unit = expression.text("unit").lower()

View file

@ -192,6 +192,18 @@ def _to_date_sql(self: Hive.Generator, expression: exp.TsOrDsToDate) -> str:
return f"TO_DATE({this})"
def _parse_ignore_nulls(
exp_class: t.Type[exp.Expression],
) -> t.Callable[[t.List[exp.Expression]], exp.Expression]:
def _parse(args: t.List[exp.Expression]) -> exp.Expression:
this = exp_class(this=seq_get(args, 0))
if seq_get(args, 1) == exp.true():
return exp.IgnoreNulls(this=this)
return this
return _parse
class Hive(Dialect):
ALIAS_POST_TABLESAMPLE = True
IDENTIFIERS_CAN_START_WITH_DIGIT = True
@ -298,8 +310,12 @@ class Hive(Dialect):
expression=exp.TsOrDsToDate(this=seq_get(args, 1)),
),
"DAY": lambda args: exp.Day(this=exp.TsOrDsToDate(this=seq_get(args, 0))),
"FIRST": _parse_ignore_nulls(exp.First),
"FIRST_VALUE": _parse_ignore_nulls(exp.FirstValue),
"FROM_UNIXTIME": format_time_lambda(exp.UnixToStr, "hive", True),
"GET_JSON_OBJECT": exp.JSONExtractScalar.from_arg_list,
"LAST": _parse_ignore_nulls(exp.Last),
"LAST_VALUE": _parse_ignore_nulls(exp.LastValue),
"LOCATE": locate_to_strposition,
"MAP": parse_var_map,
"MONTH": lambda args: exp.Month(this=exp.TsOrDsToDate.from_arg_list(args)),
@ -429,6 +445,7 @@ class Hive(Dialect):
EXTRACT_ALLOWS_QUOTES = False
NVL2_SUPPORTED = False
LAST_DAY_SUPPORTS_DATE_PART = False
JSON_PATH_SINGLE_QUOTE_ESCAPE = True
EXPRESSIONS_WITHOUT_NESTED_CTES = {
exp.Insert,
@ -437,6 +454,13 @@ class Hive(Dialect):
exp.Union,
}
SUPPORTED_JSON_PATH_PARTS = {
exp.JSONPathKey,
exp.JSONPathRoot,
exp.JSONPathSubscript,
exp.JSONPathWildcard,
}
TYPE_MAPPING = {
**generator.Generator.TYPE_MAPPING,
exp.DataType.Type.BIT: "BOOLEAN",
@ -471,9 +495,12 @@ class Hive(Dialect):
exp.DateDiff: _date_diff_sql,
exp.DateStrToDate: datestrtodate_sql,
exp.DateSub: _add_date_sql,
exp.DateToDi: lambda self, e: f"CAST(DATE_FORMAT({self.sql(e, 'this')}, {Hive.DATEINT_FORMAT}) AS INT)",
exp.DiToDate: lambda self, e: f"TO_DATE(CAST({self.sql(e, 'this')} AS STRING), {Hive.DATEINT_FORMAT})",
exp.FileFormatProperty: lambda self, e: f"STORED AS {self.sql(e, 'this') if isinstance(e.this, exp.InputOutputFormat) else e.name.upper()}",
exp.DateToDi: lambda self,
e: f"CAST(DATE_FORMAT({self.sql(e, 'this')}, {Hive.DATEINT_FORMAT}) AS INT)",
exp.DiToDate: lambda self,
e: f"TO_DATE(CAST({self.sql(e, 'this')} AS STRING), {Hive.DATEINT_FORMAT})",
exp.FileFormatProperty: lambda self,
e: f"STORED AS {self.sql(e, 'this') if isinstance(e.this, exp.InputOutputFormat) else e.name.upper()}",
exp.FromBase64: rename_func("UNBASE64"),
exp.If: if_sql(),
exp.ILike: no_ilike_sql,
@ -502,7 +529,8 @@ class Hive(Dialect):
exp.SafeDivide: no_safe_divide_sql,
exp.SchemaCommentProperty: lambda self, e: self.naked_property(e),
exp.ArrayUniqueAgg: rename_func("COLLECT_SET"),
exp.Split: lambda self, e: f"SPLIT({self.sql(e, 'this')}, CONCAT('\\\\Q', {self.sql(e, 'expression')}))",
exp.Split: lambda self,
e: f"SPLIT({self.sql(e, 'this')}, CONCAT('\\\\Q', {self.sql(e, 'expression')}))",
exp.StrPosition: strposition_to_locate_sql,
exp.StrToDate: _str_to_date_sql,
exp.StrToTime: _str_to_time_sql,
@ -514,7 +542,8 @@ class Hive(Dialect):
exp.TimeToStr: _time_to_str,
exp.TimeToUnix: rename_func("UNIX_TIMESTAMP"),
exp.ToBase64: rename_func("BASE64"),
exp.TsOrDiToDi: lambda self, e: f"CAST(SUBSTR(REPLACE(CAST({self.sql(e, 'this')} AS STRING), '-', ''), 1, 8) AS INT)",
exp.TsOrDiToDi: lambda self,
e: f"CAST(SUBSTR(REPLACE(CAST({self.sql(e, 'this')} AS STRING), '-', ''), 1, 8) AS INT)",
exp.TsOrDsAdd: _add_date_sql,
exp.TsOrDsDiff: _date_diff_sql,
exp.TsOrDsToDate: _to_date_sql,
@ -528,8 +557,10 @@ class Hive(Dialect):
exp.SerdeProperties: lambda self, e: self.properties(e, prefix="WITH SERDEPROPERTIES"),
exp.NumberToStr: rename_func("FORMAT_NUMBER"),
exp.National: lambda self, e: self.national_sql(e, prefix=""),
exp.ClusteredColumnConstraint: lambda self, e: f"({self.expressions(e, 'this', indent=False)})",
exp.NonClusteredColumnConstraint: lambda self, e: f"({self.expressions(e, 'this', indent=False)})",
exp.ClusteredColumnConstraint: lambda self,
e: f"({self.expressions(e, 'this', indent=False)})",
exp.NonClusteredColumnConstraint: lambda self,
e: f"({self.expressions(e, 'this', indent=False)})",
exp.NotForReplicationColumnConstraint: lambda self, e: "",
exp.OnProperty: lambda self, e: "",
exp.PrimaryKeyColumnConstraint: lambda self, e: "PRIMARY KEY",
@ -543,6 +574,13 @@ class Hive(Dialect):
exp.WithDataProperty: exp.Properties.Location.UNSUPPORTED,
}
def _jsonpathkey_sql(self, expression: exp.JSONPathKey) -> str:
if isinstance(expression.this, exp.JSONPathWildcard):
self.unsupported("Unsupported wildcard in JSONPathKey expression")
return ""
return super()._jsonpathkey_sql(expression)
def temporary_storage_provider(self, expression: exp.Create) -> exp.Create:
# Hive has no temporary storage provider (there are hive settings though)
return expression

View file

@ -6,7 +6,7 @@ from sqlglot import exp, generator, parser, tokens, transforms
from sqlglot.dialects.dialect import (
Dialect,
NormalizationStrategy,
arrow_json_extract_scalar_sql,
arrow_json_extract_sql,
date_add_interval_sql,
datestrtodate_sql,
format_time_lambda,
@ -19,8 +19,8 @@ from sqlglot.dialects.dialect import (
no_pivot_sql,
no_tablesample_sql,
no_trycast_sql,
parse_date_delta,
parse_date_delta_with_interval,
path_to_jsonpath,
rename_func,
strposition_to_locate_sql,
)
@ -306,6 +306,7 @@ class MySQL(Dialect):
format=exp.Literal.string("%B"),
),
"STR_TO_DATE": _str_to_date,
"TIMESTAMPDIFF": parse_date_delta(exp.TimestampDiff),
"TO_DAYS": lambda args: exp.paren(
exp.DateDiff(
this=exp.TsOrDsToDate(this=seq_get(args, 0)),
@ -357,6 +358,7 @@ class MySQL(Dialect):
"CREATE TRIGGER": _show_parser("CREATE TRIGGER", target=True),
"CREATE VIEW": _show_parser("CREATE VIEW", target=True),
"DATABASES": _show_parser("DATABASES"),
"SCHEMAS": _show_parser("DATABASES"),
"ENGINE": _show_parser("ENGINE", target=True),
"STORAGE ENGINES": _show_parser("ENGINES"),
"ENGINES": _show_parser("ENGINES"),
@ -630,6 +632,8 @@ class MySQL(Dialect):
VALUES_AS_TABLE = False
NVL2_SUPPORTED = False
LAST_DAY_SUPPORTS_DATE_PART = False
JSON_TYPE_REQUIRED_FOR_EXTRACTION = True
JSON_PATH_BRACKETED_KEY_SUPPORTED = False
JSON_KEY_VALUE_PAIR_SEP = ","
TRANSFORMS = {
@ -646,10 +650,10 @@ class MySQL(Dialect):
exp.DayOfMonth: _remove_ts_or_ds_to_date(rename_func("DAYOFMONTH")),
exp.DayOfWeek: _remove_ts_or_ds_to_date(rename_func("DAYOFWEEK")),
exp.DayOfYear: _remove_ts_or_ds_to_date(rename_func("DAYOFYEAR")),
exp.GetPath: path_to_jsonpath(),
exp.GroupConcat: lambda self, e: f"""GROUP_CONCAT({self.sql(e, "this")} SEPARATOR {self.sql(e, "separator") or "','"})""",
exp.GroupConcat: lambda self,
e: f"""GROUP_CONCAT({self.sql(e, "this")} SEPARATOR {self.sql(e, "separator") or "','"})""",
exp.ILike: no_ilike_sql,
exp.JSONExtractScalar: arrow_json_extract_scalar_sql,
exp.JSONExtractScalar: arrow_json_extract_sql,
exp.Max: max_or_greatest,
exp.Min: min_or_least,
exp.Month: _remove_ts_or_ds_to_date(),
@ -672,6 +676,9 @@ class MySQL(Dialect):
exp.TableSample: no_tablesample_sql,
exp.TimeFromParts: rename_func("MAKETIME"),
exp.TimestampAdd: date_add_interval_sql("DATE", "ADD"),
exp.TimestampDiff: lambda self, e: self.func(
"TIMESTAMPDIFF", e.text("unit"), e.expression, e.this
),
exp.TimestampSub: date_add_interval_sql("DATE", "SUB"),
exp.TimeStrToUnix: rename_func("UNIX_TIMESTAMP"),
exp.TimeStrToTime: lambda self, e: self.sql(exp.cast(e.this, "datetime", copy=True)),

View file

@ -199,7 +199,8 @@ class Oracle(Dialect):
transforms.eliminate_qualify,
]
),
exp.StrToTime: lambda self, e: f"TO_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})",
exp.StrToTime: lambda self,
e: f"TO_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})",
exp.StrToDate: lambda self, e: f"TO_DATE({self.sql(e, 'this')}, {self.format_time(e)})",
exp.Subquery: lambda self, e: self.subquery_sql(e, sep=" "),
exp.Substring: rename_func("SUBSTR"),
@ -208,7 +209,8 @@ class Oracle(Dialect):
exp.TimeToStr: lambda self, e: f"TO_CHAR({self.sql(e, 'this')}, {self.format_time(e)})",
exp.ToChar: lambda self, e: self.function_fallback_sql(e),
exp.Trim: trim_sql,
exp.UnixToTime: lambda self, e: f"TO_DATE('1970-01-01','YYYY-MM-DD') + ({self.sql(e, 'this')} / 86400)",
exp.UnixToTime: lambda self,
e: f"TO_DATE('1970-01-01','YYYY-MM-DD') + ({self.sql(e, 'this')} / 86400)",
}
PROPERTIES_LOCATION = {

View file

@ -7,11 +7,11 @@ from sqlglot.dialects.dialect import (
DATE_ADD_OR_SUB,
Dialect,
any_value_to_max_sql,
arrow_json_extract_scalar_sql,
arrow_json_extract_sql,
bool_xor_sql,
datestrtodate_sql,
format_time_lambda,
json_extract_segments,
json_path_key_only_name,
max_or_greatest,
merge_without_target_sql,
min_or_least,
@ -20,6 +20,7 @@ from sqlglot.dialects.dialect import (
no_paren_current_date_sql,
no_pivot_sql,
no_trycast_sql,
parse_json_extract_path,
parse_timestamp_trunc,
rename_func,
str_position_sql,
@ -292,6 +293,8 @@ class Postgres(Dialect):
**parser.Parser.FUNCTIONS,
"DATE_TRUNC": parse_timestamp_trunc,
"GENERATE_SERIES": _generate_series,
"JSON_EXTRACT_PATH": parse_json_extract_path(exp.JSONExtract),
"JSON_EXTRACT_PATH_TEXT": parse_json_extract_path(exp.JSONExtractScalar),
"MAKE_TIME": exp.TimeFromParts.from_arg_list,
"MAKE_TIMESTAMP": exp.TimestampFromParts.from_arg_list,
"NOW": exp.CurrentTimestamp.from_arg_list,
@ -375,8 +378,15 @@ class Postgres(Dialect):
TABLESAMPLE_SIZE_IS_ROWS = False
TABLESAMPLE_SEED_KEYWORD = "REPEATABLE"
SUPPORTS_SELECT_INTO = True
# https://www.postgresql.org/docs/current/sql-createtable.html
JSON_TYPE_REQUIRED_FOR_EXTRACTION = True
SUPPORTS_UNLOGGED_TABLES = True
LIKE_PROPERTY_INSIDE_SCHEMA = True
SUPPORTED_JSON_PATH_PARTS = {
exp.JSONPathKey,
exp.JSONPathRoot,
exp.JSONPathSubscript,
}
TYPE_MAPPING = {
**generator.Generator.TYPE_MAPPING,
@ -412,11 +422,14 @@ class Postgres(Dialect):
exp.DateSub: _date_add_sql("-"),
exp.Explode: rename_func("UNNEST"),
exp.GroupConcat: _string_agg_sql,
exp.JSONExtract: arrow_json_extract_sql,
exp.JSONExtractScalar: arrow_json_extract_scalar_sql,
exp.JSONExtract: json_extract_segments("JSON_EXTRACT_PATH"),
exp.JSONExtractScalar: json_extract_segments("JSON_EXTRACT_PATH_TEXT"),
exp.JSONBExtract: lambda self, e: self.binary(e, "#>"),
exp.JSONBExtractScalar: lambda self, e: self.binary(e, "#>>"),
exp.JSONBContains: lambda self, e: self.binary(e, "?"),
exp.JSONPathKey: json_path_key_only_name,
exp.JSONPathRoot: lambda *_: "",
exp.JSONPathSubscript: lambda self, e: self.json_path_part(e.this),
exp.LastDay: no_last_day_sql,
exp.LogicalOr: rename_func("BOOL_OR"),
exp.LogicalAnd: rename_func("BOOL_AND"),
@ -443,7 +456,8 @@ class Postgres(Dialect):
]
),
exp.StrPosition: str_position_sql,
exp.StrToTime: lambda self, e: f"TO_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})",
exp.StrToTime: lambda self,
e: f"TO_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})",
exp.StructExtract: struct_extract_sql,
exp.Substring: _substring_sql,
exp.TimeFromParts: rename_func("MAKE_TIME"),

View file

@ -18,7 +18,6 @@ from sqlglot.dialects.dialect import (
no_pivot_sql,
no_safe_divide_sql,
no_timestamp_sql,
path_to_jsonpath,
regexp_extract_sql,
rename_func,
right_to_substring_sql,
@ -150,7 +149,7 @@ def _unnest_sequence(expression: exp.Expression) -> exp.Expression:
return expression
def _first_last_sql(self: Presto.Generator, expression: exp.First | exp.Last) -> str:
def _first_last_sql(self: Presto.Generator, expression: exp.Func) -> str:
"""
Trino doesn't support FIRST / LAST as functions, but they're valid in the context
of MATCH_RECOGNIZE, so we need to preserve them in that case. In all other cases
@ -292,6 +291,7 @@ class Presto(Dialect):
STRUCT_DELIMITER = ("(", ")")
LIMIT_ONLY_LITERALS = True
SUPPORTS_SINGLE_ARG_CONCAT = False
LIKE_PROPERTY_INSIDE_SCHEMA = True
PROPERTIES_LOCATION = {
**generator.Generator.PROPERTIES_LOCATION,
@ -324,12 +324,18 @@ class Presto(Dialect):
exp.ArrayContains: rename_func("CONTAINS"),
exp.ArraySize: rename_func("CARDINALITY"),
exp.ArrayUniqueAgg: rename_func("SET_AGG"),
exp.BitwiseAnd: lambda self, e: f"BITWISE_AND({self.sql(e, 'this')}, {self.sql(e, 'expression')})",
exp.BitwiseLeftShift: lambda self, e: f"BITWISE_ARITHMETIC_SHIFT_LEFT({self.sql(e, 'this')}, {self.sql(e, 'expression')})",
exp.AtTimeZone: rename_func("AT_TIMEZONE"),
exp.BitwiseAnd: lambda self,
e: f"BITWISE_AND({self.sql(e, 'this')}, {self.sql(e, 'expression')})",
exp.BitwiseLeftShift: lambda self,
e: f"BITWISE_ARITHMETIC_SHIFT_LEFT({self.sql(e, 'this')}, {self.sql(e, 'expression')})",
exp.BitwiseNot: lambda self, e: f"BITWISE_NOT({self.sql(e, 'this')})",
exp.BitwiseOr: lambda self, e: f"BITWISE_OR({self.sql(e, 'this')}, {self.sql(e, 'expression')})",
exp.BitwiseRightShift: lambda self, e: f"BITWISE_ARITHMETIC_SHIFT_RIGHT({self.sql(e, 'this')}, {self.sql(e, 'expression')})",
exp.BitwiseXor: lambda self, e: f"BITWISE_XOR({self.sql(e, 'this')}, {self.sql(e, 'expression')})",
exp.BitwiseOr: lambda self,
e: f"BITWISE_OR({self.sql(e, 'this')}, {self.sql(e, 'expression')})",
exp.BitwiseRightShift: lambda self,
e: f"BITWISE_ARITHMETIC_SHIFT_RIGHT({self.sql(e, 'this')}, {self.sql(e, 'expression')})",
exp.BitwiseXor: lambda self,
e: f"BITWISE_XOR({self.sql(e, 'this')}, {self.sql(e, 'expression')})",
exp.Cast: transforms.preprocess([transforms.epoch_cast_to_ts]),
exp.CurrentTimestamp: lambda *_: "CURRENT_TIMESTAMP",
exp.DateAdd: lambda self, e: self.func(
@ -344,7 +350,8 @@ class Presto(Dialect):
"DATE_DIFF", exp.Literal.string(e.text("unit") or "DAY"), e.expression, e.this
),
exp.DateStrToDate: datestrtodate_sql,
exp.DateToDi: lambda self, e: f"CAST(DATE_FORMAT({self.sql(e, 'this')}, {Presto.DATEINT_FORMAT}) AS INT)",
exp.DateToDi: lambda self,
e: f"CAST(DATE_FORMAT({self.sql(e, 'this')}, {Presto.DATEINT_FORMAT}) AS INT)",
exp.DateSub: lambda self, e: self.func(
"DATE_ADD",
exp.Literal.string(e.text("unit") or "DAY"),
@ -352,12 +359,14 @@ class Presto(Dialect):
e.this,
),
exp.Decode: lambda self, e: encode_decode_sql(self, e, "FROM_UTF8"),
exp.DiToDate: lambda self, e: f"CAST(DATE_PARSE(CAST({self.sql(e, 'this')} AS VARCHAR), {Presto.DATEINT_FORMAT}) AS DATE)",
exp.DiToDate: lambda self,
e: f"CAST(DATE_PARSE(CAST({self.sql(e, 'this')} AS VARCHAR), {Presto.DATEINT_FORMAT}) AS DATE)",
exp.Encode: lambda self, e: encode_decode_sql(self, e, "TO_UTF8"),
exp.FileFormatProperty: lambda self, e: f"FORMAT='{e.name.upper()}'",
exp.First: _first_last_sql,
exp.FromTimeZone: lambda self, e: f"WITH_TIMEZONE({self.sql(e, 'this')}, {self.sql(e, 'zone')}) AT TIME ZONE 'UTC'",
exp.GetPath: path_to_jsonpath(),
exp.FirstValue: _first_last_sql,
exp.FromTimeZone: lambda self,
e: f"WITH_TIMEZONE({self.sql(e, 'this')}, {self.sql(e, 'zone')}) AT TIME ZONE 'UTC'",
exp.Group: transforms.preprocess([transforms.unalias_group]),
exp.GroupConcat: lambda self, e: self.func(
"ARRAY_JOIN", self.func("ARRAY_AGG", e.this), e.args.get("separator")
@ -368,6 +377,7 @@ class Presto(Dialect):
exp.Initcap: _initcap_sql,
exp.ParseJSON: rename_func("JSON_PARSE"),
exp.Last: _first_last_sql,
exp.LastValue: _first_last_sql,
exp.LastDay: lambda self, e: self.func("LAST_DAY_OF_MONTH", e.this),
exp.Lateral: _explode_to_unnest_sql,
exp.Left: left_to_substring_sql,
@ -394,26 +404,33 @@ class Presto(Dialect):
exp.StrToDate: lambda self, e: f"CAST({_str_to_time_sql(self, e)} AS DATE)",
exp.StrToMap: rename_func("SPLIT_TO_MAP"),
exp.StrToTime: _str_to_time_sql,
exp.StrToUnix: lambda self, e: f"TO_UNIXTIME(DATE_PARSE({self.sql(e, 'this')}, {self.format_time(e)}))",
exp.StrToUnix: lambda self,
e: f"TO_UNIXTIME(DATE_PARSE({self.sql(e, 'this')}, {self.format_time(e)}))",
exp.StructExtract: struct_extract_sql,
exp.Table: transforms.preprocess([_unnest_sequence]),
exp.Timestamp: no_timestamp_sql,
exp.TimestampTrunc: timestamptrunc_sql,
exp.TimeStrToDate: timestrtotime_sql,
exp.TimeStrToTime: timestrtotime_sql,
exp.TimeStrToUnix: lambda self, e: f"TO_UNIXTIME(DATE_PARSE({self.sql(e, 'this')}, {Presto.TIME_FORMAT}))",
exp.TimeToStr: lambda self, e: f"DATE_FORMAT({self.sql(e, 'this')}, {self.format_time(e)})",
exp.TimeStrToUnix: lambda self,
e: f"TO_UNIXTIME(DATE_PARSE({self.sql(e, 'this')}, {Presto.TIME_FORMAT}))",
exp.TimeToStr: lambda self,
e: f"DATE_FORMAT({self.sql(e, 'this')}, {self.format_time(e)})",
exp.TimeToUnix: rename_func("TO_UNIXTIME"),
exp.ToChar: lambda self, e: f"DATE_FORMAT({self.sql(e, 'this')}, {self.format_time(e)})",
exp.ToChar: lambda self,
e: f"DATE_FORMAT({self.sql(e, 'this')}, {self.format_time(e)})",
exp.TryCast: transforms.preprocess([transforms.epoch_cast_to_ts]),
exp.TsOrDiToDi: lambda self, e: f"CAST(SUBSTR(REPLACE(CAST({self.sql(e, 'this')} AS VARCHAR), '-', ''), 1, 8) AS INT)",
exp.TsOrDiToDi: lambda self,
e: f"CAST(SUBSTR(REPLACE(CAST({self.sql(e, 'this')} AS VARCHAR), '-', ''), 1, 8) AS INT)",
exp.TsOrDsAdd: _ts_or_ds_add_sql,
exp.TsOrDsDiff: _ts_or_ds_diff_sql,
exp.TsOrDsToDate: _ts_or_ds_to_date_sql,
exp.Unhex: rename_func("FROM_HEX"),
exp.UnixToStr: lambda self, e: f"DATE_FORMAT(FROM_UNIXTIME({self.sql(e, 'this')}), {self.format_time(e)})",
exp.UnixToStr: lambda self,
e: f"DATE_FORMAT(FROM_UNIXTIME({self.sql(e, 'this')}), {self.format_time(e)})",
exp.UnixToTime: _unix_to_time_sql,
exp.UnixToTimeStr: lambda self, e: f"CAST(FROM_UNIXTIME({self.sql(e, 'this')}) AS VARCHAR)",
exp.UnixToTimeStr: lambda self,
e: f"CAST(FROM_UNIXTIME({self.sql(e, 'this')}) AS VARCHAR)",
exp.VariancePop: rename_func("VAR_POP"),
exp.With: transforms.preprocess([transforms.add_recursive_cte_column_names]),
exp.WithinGroup: transforms.preprocess(

View file

@ -9,6 +9,7 @@ from sqlglot.dialects.dialect import (
concat_ws_to_dpipe_sql,
date_delta_sql,
generatedasidentitycolumnconstraint_sql,
json_extract_segments,
no_tablesample_sql,
rename_func,
)
@ -20,10 +21,6 @@ if t.TYPE_CHECKING:
from sqlglot._typing import E
def _json_sql(self: Redshift.Generator, expression: exp.JSONExtract | exp.JSONExtractScalar) -> str:
return f'{self.sql(expression, "this")}."{expression.expression.name}"'
def _parse_date_delta(expr_type: t.Type[E]) -> t.Callable[[t.List], E]:
def _parse_delta(args: t.List) -> E:
expr = expr_type(this=seq_get(args, 2), expression=seq_get(args, 1), unit=seq_get(args, 0))
@ -62,6 +59,7 @@ class Redshift(Postgres):
"DATE_ADD": _parse_date_delta(exp.TsOrDsAdd),
"DATEDIFF": _parse_date_delta(exp.TsOrDsDiff),
"DATE_DIFF": _parse_date_delta(exp.TsOrDsDiff),
"GETDATE": exp.CurrentTimestamp.from_arg_list,
"LISTAGG": exp.GroupConcat.from_arg_list,
"STRTOL": exp.FromBase.from_arg_list,
}
@ -69,6 +67,7 @@ class Redshift(Postgres):
NO_PAREN_FUNCTION_PARSERS = {
**Postgres.Parser.NO_PAREN_FUNCTION_PARSERS,
"APPROXIMATE": lambda self: self._parse_approximate_count(),
"SYSDATE": lambda self: self.expression(exp.CurrentTimestamp, transaction=True),
}
def _parse_table(
@ -77,6 +76,7 @@ class Redshift(Postgres):
joins: bool = False,
alias_tokens: t.Optional[t.Collection[TokenType]] = None,
parse_bracket: bool = False,
is_db_reference: bool = False,
) -> t.Optional[exp.Expression]:
# Redshift supports UNPIVOTing SUPER objects, e.g. `UNPIVOT foo.obj[0] AS val AT attr`
unpivot = self._match(TokenType.UNPIVOT)
@ -85,6 +85,7 @@ class Redshift(Postgres):
joins=joins,
alias_tokens=alias_tokens,
parse_bracket=parse_bracket,
is_db_reference=is_db_reference,
)
return self.expression(exp.Pivot, this=table, unpivot=True) if unpivot else table
@ -153,7 +154,6 @@ class Redshift(Postgres):
**Postgres.Tokenizer.KEYWORDS,
"HLLSKETCH": TokenType.HLLSKETCH,
"SUPER": TokenType.SUPER,
"SYSDATE": TokenType.CURRENT_TIMESTAMP,
"TOP": TokenType.TOP,
"UNLOAD": TokenType.COMMAND,
"VARBYTE": TokenType.VARBINARY,
@ -180,31 +180,29 @@ class Redshift(Postgres):
exp.DataType.Type.VARBINARY: "VARBYTE",
}
PROPERTIES_LOCATION = {
**Postgres.Generator.PROPERTIES_LOCATION,
exp.LikeProperty: exp.Properties.Location.POST_WITH,
}
TRANSFORMS = {
**Postgres.Generator.TRANSFORMS,
exp.Concat: concat_to_dpipe_sql,
exp.ConcatWs: concat_ws_to_dpipe_sql,
exp.ApproxDistinct: lambda self, e: f"APPROXIMATE COUNT(DISTINCT {self.sql(e, 'this')})",
exp.CurrentTimestamp: lambda self, e: "SYSDATE",
exp.ApproxDistinct: lambda self,
e: f"APPROXIMATE COUNT(DISTINCT {self.sql(e, 'this')})",
exp.CurrentTimestamp: lambda self, e: (
"SYSDATE" if e.args.get("transaction") else "GETDATE()"
),
exp.DateAdd: date_delta_sql("DATEADD"),
exp.DateDiff: date_delta_sql("DATEDIFF"),
exp.DistKeyProperty: lambda self, e: f"DISTKEY({e.name})",
exp.DistStyleProperty: lambda self, e: self.naked_property(e),
exp.FromBase: rename_func("STRTOL"),
exp.GeneratedAsIdentityColumnConstraint: generatedasidentitycolumnconstraint_sql,
exp.JSONExtract: _json_sql,
exp.JSONExtractScalar: _json_sql,
exp.JSONExtract: json_extract_segments("JSON_EXTRACT_PATH_TEXT"),
exp.GroupConcat: rename_func("LISTAGG"),
exp.ParseJSON: rename_func("JSON_PARSE"),
exp.Select: transforms.preprocess(
[transforms.eliminate_distinct_on, transforms.eliminate_semi_and_anti_joins]
),
exp.SortKeyProperty: lambda self, e: f"{'COMPOUND ' if e.args['compound'] else ''}SORTKEY({self.format_args(*e.this)})",
exp.SortKeyProperty: lambda self,
e: f"{'COMPOUND ' if e.args['compound'] else ''}SORTKEY({self.format_args(*e.this)})",
exp.TableSample: no_tablesample_sql,
exp.TsOrDsAdd: date_delta_sql("DATEADD"),
exp.TsOrDsDiff: date_delta_sql("DATEDIFF"),
@ -228,6 +226,13 @@ class Redshift(Postgres):
"""Redshift doesn't have `WITH` as part of their with_properties so we remove it"""
return self.properties(properties, prefix=" ", suffix="")
def cast_sql(self, expression: exp.Cast, safe_prefix: t.Optional[str] = None) -> str:
if expression.is_type(exp.DataType.Type.JSON):
# Redshift doesn't support a JSON type, so casting to it is treated as a noop
return self.sql(expression, "this")
return super().cast_sql(expression, safe_prefix=safe_prefix)
def datatype_sql(self, expression: exp.DataType) -> str:
"""
Redshift converts the `TEXT` data type to `VARCHAR(255)` by default when people more generally mean

View file

@ -21,19 +21,13 @@ from sqlglot.dialects.dialect import (
var_map_sql,
)
from sqlglot.expressions import Literal
from sqlglot.helper import seq_get
from sqlglot.helper import is_int, seq_get
from sqlglot.tokens import TokenType
if t.TYPE_CHECKING:
from sqlglot._typing import E
def _check_int(s: str) -> bool:
if s[0] in ("-", "+"):
return s[1:].isdigit()
return s.isdigit()
# from https://docs.snowflake.com/en/sql-reference/functions/to_timestamp.html
def _parse_to_timestamp(args: t.List) -> t.Union[exp.StrToTime, exp.UnixToTime, exp.TimeStrToTime]:
if len(args) == 2:
@ -53,7 +47,7 @@ def _parse_to_timestamp(args: t.List) -> t.Union[exp.StrToTime, exp.UnixToTime,
return exp.TimeStrToTime.from_arg_list(args)
if first_arg.is_string:
if _check_int(first_arg.this):
if is_int(first_arg.this):
# case: <integer>
return exp.UnixToTime.from_arg_list(args)
@ -241,7 +235,6 @@ DATE_PART_MAPPING = {
"NSECOND": "NANOSECOND",
"NSECONDS": "NANOSECOND",
"NANOSECS": "NANOSECOND",
"NSECONDS": "NANOSECOND",
"EPOCH": "EPOCH_SECOND",
"EPOCH_SECONDS": "EPOCH_SECOND",
"EPOCH_MILLISECONDS": "EPOCH_MILLISECOND",
@ -291,7 +284,9 @@ def _parse_colon_get_path(
path = exp.Literal.string(path.sql(dialect="snowflake"))
# The extraction operator : is left-associative
this = self.expression(exp.GetPath, this=this, expression=path)
this = self.expression(
exp.JSONExtract, this=this, expression=self.dialect.to_json_path(path)
)
if target_type:
this = exp.cast(this, target_type)
@ -411,6 +406,9 @@ class Snowflake(Dialect):
"DATEDIFF": _parse_datediff,
"DIV0": _div0_to_if,
"FLATTEN": exp.Explode.from_arg_list,
"GET_PATH": lambda args, dialect: exp.JSONExtract(
this=seq_get(args, 0), expression=dialect.to_json_path(seq_get(args, 1))
),
"IFF": exp.If.from_arg_list,
"LAST_DAY": lambda args: exp.LastDay(
this=seq_get(args, 0), unit=_map_date_part(seq_get(args, 1))
@ -474,6 +472,8 @@ class Snowflake(Dialect):
"TERSE SCHEMAS": _show_parser("SCHEMAS"),
"OBJECTS": _show_parser("OBJECTS"),
"TERSE OBJECTS": _show_parser("OBJECTS"),
"TABLES": _show_parser("TABLES"),
"TERSE TABLES": _show_parser("TABLES"),
"PRIMARY KEYS": _show_parser("PRIMARY KEYS"),
"TERSE PRIMARY KEYS": _show_parser("PRIMARY KEYS"),
"COLUMNS": _show_parser("COLUMNS"),
@ -534,7 +534,9 @@ class Snowflake(Dialect):
return table
def _parse_table_parts(self, schema: bool = False) -> exp.Table:
def _parse_table_parts(
self, schema: bool = False, is_db_reference: bool = False
) -> exp.Table:
# https://docs.snowflake.com/en/user-guide/querying-stage
if self._match(TokenType.STRING, advance=False):
table = self._parse_string()
@ -550,7 +552,9 @@ class Snowflake(Dialect):
self._match(TokenType.L_PAREN)
while self._curr and not self._match(TokenType.R_PAREN):
if self._match_text_seq("FILE_FORMAT", "=>"):
file_format = self._parse_string() or super()._parse_table_parts()
file_format = self._parse_string() or super()._parse_table_parts(
is_db_reference=is_db_reference
)
elif self._match_text_seq("PATTERN", "=>"):
pattern = self._parse_string()
else:
@ -560,7 +564,7 @@ class Snowflake(Dialect):
table = self.expression(exp.Table, this=table, format=file_format, pattern=pattern)
else:
table = super()._parse_table_parts(schema=schema)
table = super()._parse_table_parts(schema=schema, is_db_reference=is_db_reference)
return self._parse_at_before(table)
@ -587,6 +591,8 @@ class Snowflake(Dialect):
# which is syntactically valid but has no effect on the output
terse = self._tokens[self._index - 2].text.upper() == "TERSE"
history = self._match_text_seq("HISTORY")
like = self._parse_string() if self._match(TokenType.LIKE) else None
if self._match(TokenType.IN):
@ -597,7 +603,7 @@ class Snowflake(Dialect):
if self._curr:
scope = self._parse_table_parts()
elif self._curr:
scope_kind = "SCHEMA" if this == "OBJECTS" else "TABLE"
scope_kind = "SCHEMA" if this in ("OBJECTS", "TABLES") else "TABLE"
scope = self._parse_table_parts()
return self.expression(
@ -605,6 +611,7 @@ class Snowflake(Dialect):
**{
"terse": terse,
"this": this,
"history": history,
"like": like,
"scope": scope,
"scope_kind": scope_kind,
@ -715,8 +722,10 @@ class Snowflake(Dialect):
),
exp.GroupConcat: rename_func("LISTAGG"),
exp.If: if_sql(name="IFF", false_value="NULL"),
exp.JSONExtract: lambda self, e: f"{self.sql(e, 'this')}[{self.sql(e, 'expression')}]",
exp.JSONExtract: rename_func("GET_PATH"),
exp.JSONExtractScalar: rename_func("JSON_EXTRACT_PATH_TEXT"),
exp.JSONObject: lambda self, e: self.func("OBJECT_CONSTRUCT_KEEP_NULL", *e.expressions),
exp.JSONPathRoot: lambda *_: "",
exp.LogicalAnd: rename_func("BOOLAND_AGG"),
exp.LogicalOr: rename_func("BOOLOR_AGG"),
exp.Map: lambda self, e: var_map_sql(self, e, "OBJECT_CONSTRUCT"),
@ -745,7 +754,8 @@ class Snowflake(Dialect):
exp.StrPosition: lambda self, e: self.func(
"POSITION", e.args.get("substr"), e.this, e.args.get("position")
),
exp.StrToTime: lambda self, e: f"TO_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})",
exp.StrToTime: lambda self,
e: f"TO_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})",
exp.Struct: lambda self, e: self.func(
"OBJECT_CONSTRUCT",
*(arg for expression in e.expressions for arg in expression.flatten()),
@ -771,6 +781,12 @@ class Snowflake(Dialect):
exp.Xor: rename_func("BOOLXOR"),
}
SUPPORTED_JSON_PATH_PARTS = {
exp.JSONPathKey,
exp.JSONPathRoot,
exp.JSONPathSubscript,
}
TYPE_MAPPING = {
**generator.Generator.TYPE_MAPPING,
exp.DataType.Type.TIMESTAMP: "TIMESTAMPNTZ",
@ -841,6 +857,7 @@ class Snowflake(Dialect):
def show_sql(self, expression: exp.Show) -> str:
terse = "TERSE " if expression.args.get("terse") else ""
history = " HISTORY" if expression.args.get("history") else ""
like = self.sql(expression, "like")
like = f" LIKE {like}" if like else ""
@ -861,9 +878,7 @@ class Snowflake(Dialect):
if from_:
from_ = f" FROM {from_}"
return (
f"SHOW {terse}{expression.name}{like}{scope_kind}{scope}{starts_with}{limit}{from_}"
)
return f"SHOW {terse}{expression.name}{history}{like}{scope_kind}{scope}{starts_with}{limit}{from_}"
def regexpextract_sql(self, expression: exp.RegexpExtract) -> str:
# Other dialects don't support all of the following parameters, so we need to

View file

@ -4,6 +4,7 @@ import typing as t
from sqlglot import exp
from sqlglot.dialects.dialect import rename_func
from sqlglot.dialects.hive import _parse_ignore_nulls
from sqlglot.dialects.spark2 import Spark2
from sqlglot.helper import seq_get
@ -45,9 +46,7 @@ class Spark(Spark2):
class Parser(Spark2.Parser):
FUNCTIONS = {
**Spark2.Parser.FUNCTIONS,
"ANY_VALUE": lambda args: exp.AnyValue(
this=seq_get(args, 0), ignore_nulls=seq_get(args, 1)
),
"ANY_VALUE": _parse_ignore_nulls(exp.AnyValue),
"DATEDIFF": _parse_datediff,
}

View file

@ -187,8 +187,10 @@ class Spark2(Hive):
TRANSFORMS = {
**Hive.Generator.TRANSFORMS,
exp.ApproxDistinct: rename_func("APPROX_COUNT_DISTINCT"),
exp.ArraySum: lambda self, e: f"AGGREGATE({self.sql(e, 'this')}, 0, (acc, x) -> acc + x, acc -> acc)",
exp.AtTimeZone: lambda self, e: f"FROM_UTC_TIMESTAMP({self.sql(e, 'this')}, {self.sql(e, 'zone')})",
exp.ArraySum: lambda self,
e: f"AGGREGATE({self.sql(e, 'this')}, 0, (acc, x) -> acc + x, acc -> acc)",
exp.AtTimeZone: lambda self,
e: f"FROM_UTC_TIMESTAMP({self.sql(e, 'this')}, {self.sql(e, 'zone')})",
exp.BitwiseLeftShift: rename_func("SHIFTLEFT"),
exp.BitwiseRightShift: rename_func("SHIFTRIGHT"),
exp.DateFromParts: rename_func("MAKE_DATE"),
@ -198,7 +200,8 @@ class Spark2(Hive):
exp.DayOfYear: rename_func("DAYOFYEAR"),
exp.FileFormatProperty: lambda self, e: f"USING {e.name.upper()}",
exp.From: transforms.preprocess([_unalias_pivot]),
exp.FromTimeZone: lambda self, e: f"TO_UTC_TIMESTAMP({self.sql(e, 'this')}, {self.sql(e, 'zone')})",
exp.FromTimeZone: lambda self,
e: f"TO_UTC_TIMESTAMP({self.sql(e, 'this')}, {self.sql(e, 'zone')})",
exp.LogicalAnd: rename_func("BOOL_AND"),
exp.LogicalOr: rename_func("BOOL_OR"),
exp.Map: _map_sql,
@ -212,7 +215,8 @@ class Spark2(Hive):
e.args.get("position"),
),
exp.StrToDate: _str_to_date,
exp.StrToTime: lambda self, e: f"TO_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})",
exp.StrToTime: lambda self,
e: f"TO_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})",
exp.TimestampTrunc: lambda self, e: self.func(
"DATE_TRUNC", exp.Literal.string(e.text("unit")), e.this
),

View file

@ -7,7 +7,6 @@ from sqlglot.dialects.dialect import (
Dialect,
NormalizationStrategy,
any_value_to_max_sql,
arrow_json_extract_scalar_sql,
arrow_json_extract_sql,
concat_to_dpipe_sql,
count_if_to_sum,
@ -28,6 +27,12 @@ def _date_add_sql(self: SQLite.Generator, expression: exp.DateAdd) -> str:
return self.func("DATE", expression.this, modifier)
def _json_extract_sql(self: SQLite.Generator, expression: exp.JSONExtract) -> str:
if expression.expressions:
return self.function_fallback_sql(expression)
return arrow_json_extract_sql(self, expression)
def _transform_create(expression: exp.Expression) -> exp.Expression:
"""Move primary key to a column and enforce auto_increment on primary keys."""
schema = expression.this
@ -85,6 +90,14 @@ class SQLite(Dialect):
TABLE_HINTS = False
QUERY_HINTS = False
NVL2_SUPPORTED = False
JSON_PATH_BRACKETED_KEY_SUPPORTED = False
SUPPORTS_CREATE_TABLE_LIKE = False
SUPPORTED_JSON_PATH_PARTS = {
exp.JSONPathKey,
exp.JSONPathRoot,
exp.JSONPathSubscript,
}
TYPE_MAPPING = {
**generator.Generator.TYPE_MAPPING,
@ -120,10 +133,8 @@ class SQLite(Dialect):
exp.DateAdd: _date_add_sql,
exp.DateStrToDate: lambda self, e: self.sql(e, "this"),
exp.ILike: no_ilike_sql,
exp.JSONExtract: arrow_json_extract_sql,
exp.JSONExtractScalar: arrow_json_extract_scalar_sql,
exp.JSONBExtract: arrow_json_extract_sql,
exp.JSONBExtractScalar: arrow_json_extract_scalar_sql,
exp.JSONExtract: _json_extract_sql,
exp.JSONExtractScalar: arrow_json_extract_sql,
exp.Levenshtein: rename_func("EDITDIST3"),
exp.LogicalOr: rename_func("MAX"),
exp.LogicalAnd: rename_func("MIN"),
@ -141,11 +152,18 @@ class SQLite(Dialect):
exp.TryCast: no_trycast_sql,
}
# SQLite doesn't generally support CREATE TABLE .. properties
# https://www.sqlite.org/lang_createtable.html
PROPERTIES_LOCATION = {
k: exp.Properties.Location.UNSUPPORTED
for k, v in generator.Generator.PROPERTIES_LOCATION.items()
prop: exp.Properties.Location.UNSUPPORTED
for prop in generator.Generator.PROPERTIES_LOCATION
}
# There are a few exceptions (e.g. temporary tables) which are supported or
# can be transpiled to SQLite, so we explicitly override them accordingly
PROPERTIES_LOCATION[exp.LikeProperty] = exp.Properties.Location.POST_SCHEMA
PROPERTIES_LOCATION[exp.TemporaryProperty] = exp.Properties.Location.POST_CREATE
LIMIT_FETCH = "LIMIT"
def cast_sql(self, expression: exp.Cast, safe_prefix: t.Optional[str] = None) -> str:

View file

@ -44,12 +44,14 @@ class StarRocks(MySQL):
exp.JSONExtractScalar: arrow_json_extract_sql,
exp.JSONExtract: arrow_json_extract_sql,
exp.RegexpLike: rename_func("REGEXP"),
exp.StrToUnix: lambda self, e: f"UNIX_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})",
exp.StrToUnix: lambda self,
e: f"UNIX_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})",
exp.TimestampTrunc: lambda self, e: self.func(
"DATE_TRUNC", exp.Literal.string(e.text("unit")), e.this
),
exp.TimeStrToDate: rename_func("TO_DATE"),
exp.UnixToStr: lambda self, e: f"FROM_UNIXTIME({self.sql(e, 'this')}, {self.format_time(e)})",
exp.UnixToStr: lambda self,
e: f"FROM_UNIXTIME({self.sql(e, 'this')}, {self.format_time(e)})",
exp.UnixToTime: rename_func("FROM_UNIXTIME"),
}

View file

@ -200,7 +200,8 @@ class Teradata(Dialect):
exp.Select: transforms.preprocess(
[transforms.eliminate_distinct_on, transforms.eliminate_semi_and_anti_joins]
),
exp.StrToDate: lambda self, e: f"CAST({self.sql(e, 'this')} AS DATE FORMAT {self.format_time(e)})",
exp.StrToDate: lambda self,
e: f"CAST({self.sql(e, 'this')} AS DATE FORMAT {self.format_time(e)})",
exp.ToChar: lambda self, e: self.function_fallback_sql(e),
exp.Use: lambda self, e: f"DATABASE {self.sql(e, 'this')}",
}

View file

@ -11,9 +11,16 @@ class Trino(Presto):
class Generator(Presto.Generator):
TRANSFORMS = {
**Presto.Generator.TRANSFORMS,
exp.ArraySum: lambda self, e: f"REDUCE({self.sql(e, 'this')}, 0, (acc, x) -> acc + x, acc -> acc)",
exp.ArraySum: lambda self,
e: f"REDUCE({self.sql(e, 'this')}, 0, (acc, x) -> acc + x, acc -> acc)",
exp.Merge: merge_without_target_sql,
}
SUPPORTED_JSON_PATH_PARTS = {
exp.JSONPathKey,
exp.JSONPathRoot,
exp.JSONPathSubscript,
}
class Tokenizer(Presto.Tokenizer):
HEX_STRINGS = [("X'", "'")]

View file

@ -14,7 +14,6 @@ from sqlglot.dialects.dialect import (
max_or_greatest,
min_or_least,
parse_date_delta,
path_to_jsonpath,
rename_func,
timestrtotime_sql,
trim_sql,
@ -266,13 +265,32 @@ def _parse_timefromparts(args: t.List) -> exp.TimeFromParts:
)
def _parse_len(args: t.List) -> exp.Length:
this = seq_get(args, 0)
def _parse_as_text(
klass: t.Type[exp.Expression],
) -> t.Callable[[t.List[exp.Expression]], exp.Expression]:
def _parse(args: t.List[exp.Expression]) -> exp.Expression:
this = seq_get(args, 0)
if this and not this.is_string:
this = exp.cast(this, exp.DataType.Type.TEXT)
if this and not this.is_string:
this = exp.cast(this, exp.DataType.Type.TEXT)
return exp.Length(this=this)
expression = seq_get(args, 1)
kwargs = {"this": this}
if expression:
kwargs["expression"] = expression
return klass(**kwargs)
return _parse
def _json_extract_sql(
self: TSQL.Generator, expression: exp.JSONExtract | exp.JSONExtractScalar
) -> str:
json_query = rename_func("JSON_QUERY")(self, expression)
json_value = rename_func("JSON_VALUE")(self, expression)
return self.func("ISNULL", json_query, json_value)
class TSQL(Dialect):
@ -441,8 +459,11 @@ class TSQL(Dialect):
"HASHBYTES": _parse_hashbytes,
"IIF": exp.If.from_arg_list,
"ISNULL": exp.Coalesce.from_arg_list,
"JSON_VALUE": exp.JSONExtractScalar.from_arg_list,
"LEN": _parse_len,
"JSON_QUERY": parser.parse_extract_json_with_path(exp.JSONExtract),
"JSON_VALUE": parser.parse_extract_json_with_path(exp.JSONExtractScalar),
"LEN": _parse_as_text(exp.Length),
"LEFT": _parse_as_text(exp.Left),
"RIGHT": _parse_as_text(exp.Right),
"REPLICATE": exp.Repeat.from_arg_list,
"SQUARE": lambda args: exp.Pow(this=seq_get(args, 0), expression=exp.Literal.number(2)),
"SYSDATETIME": exp.CurrentTimestamp.from_arg_list,
@ -677,6 +698,7 @@ class TSQL(Dialect):
SUPPORTS_SINGLE_ARG_CONCAT = False
TABLESAMPLE_SEED_KEYWORD = "REPEATABLE"
SUPPORTS_SELECT_INTO = True
JSON_PATH_BRACKETED_KEY_SUPPORTED = False
EXPRESSIONS_WITHOUT_NESTED_CTES = {
exp.Delete,
@ -688,6 +710,12 @@ class TSQL(Dialect):
exp.Update,
}
SUPPORTED_JSON_PATH_PARTS = {
exp.JSONPathKey,
exp.JSONPathRoot,
exp.JSONPathSubscript,
}
TYPE_MAPPING = {
**generator.Generator.TYPE_MAPPING,
exp.DataType.Type.BOOLEAN: "BIT",
@ -712,9 +740,10 @@ class TSQL(Dialect):
exp.CurrentTimestamp: rename_func("GETDATE"),
exp.Extract: rename_func("DATEPART"),
exp.GeneratedAsIdentityColumnConstraint: generatedasidentitycolumnconstraint_sql,
exp.GetPath: path_to_jsonpath("JSON_VALUE"),
exp.GroupConcat: _string_agg_sql,
exp.If: rename_func("IIF"),
exp.JSONExtract: _json_extract_sql,
exp.JSONExtractScalar: _json_extract_sql,
exp.LastDay: lambda self, e: self.func("EOMONTH", e.this),
exp.Max: max_or_greatest,
exp.MD5: lambda self, e: self.func("HASHBYTES", exp.Literal.string("MD5"), e.this),
@ -831,15 +860,21 @@ class TSQL(Dialect):
exists = expression.args.pop("exists", None)
sql = super().create_sql(expression)
like_property = expression.find(exp.LikeProperty)
if like_property:
ctas_expression = like_property.this
else:
ctas_expression = expression.expression
table = expression.find(exp.Table)
# Convert CTAS statement to SELECT .. INTO ..
if kind == "TABLE" and expression.expression:
ctas_with = expression.expression.args.get("with")
if kind == "TABLE" and ctas_expression:
ctas_with = ctas_expression.args.get("with")
if ctas_with:
ctas_with = ctas_with.pop()
subquery = expression.expression
subquery = ctas_expression
if isinstance(subquery, exp.Subqueryable):
subquery = subquery.subquery()
@ -847,6 +882,9 @@ class TSQL(Dialect):
select_into.set("into", exp.Into(this=table))
select_into.set("with", ctas_with)
if like_property:
select_into.limit(0, copy=False)
sql = self.sql(select_into)
if exists:
@ -937,9 +975,19 @@ class TSQL(Dialect):
return f"CONSTRAINT {this} {expressions}"
def length_sql(self, expression: exp.Length) -> str:
return self._uncast_text(expression, "LEN")
def right_sql(self, expression: exp.Right) -> str:
return self._uncast_text(expression, "RIGHT")
def left_sql(self, expression: exp.Left) -> str:
return self._uncast_text(expression, "LEFT")
def _uncast_text(self, expression: exp.Expression, name: str) -> str:
this = expression.this
if isinstance(this, exp.Cast) and this.is_type(exp.DataType.Type.TEXT):
this_sql = self.sql(this, "this")
else:
this_sql = self.sql(this)
return self.func("LEN", this_sql)
expression_sql = self.sql(expression, "expression")
return self.func(name, this_sql, expression_sql if expression_sql else None)

View file

@ -10,7 +10,6 @@ import logging
import time
import typing as t
from sqlglot import maybe_parse
from sqlglot.errors import ExecuteError
from sqlglot.executor.python import PythonExecutor
from sqlglot.executor.table import Table, ensure_tables
@ -23,7 +22,6 @@ logger = logging.getLogger("sqlglot")
if t.TYPE_CHECKING:
from sqlglot.dialects.dialect import DialectType
from sqlglot.executor.table import Tables
from sqlglot.expressions import Expression
from sqlglot.schema import Schema

View file

@ -44,9 +44,9 @@ class Context:
for other in self.tables.values():
if self._table.columns != other.columns:
raise Exception(f"Columns are different.")
raise Exception("Columns are different.")
if len(self._table.rows) != len(other.rows):
raise Exception(f"Rows are different.")
raise Exception("Rows are different.")
return self._table

View file

@ -6,7 +6,7 @@ from functools import wraps
from sqlglot import exp
from sqlglot.generator import Generator
from sqlglot.helper import PYTHON_VERSION
from sqlglot.helper import PYTHON_VERSION, is_int, seq_get
class reverse_key:
@ -143,6 +143,22 @@ def arrayjoin(this, expression, null=None):
return expression.join(x for x in (x if x is not None else null for x in this) if x is not None)
@null_if_any("this", "expression")
def jsonextract(this, expression):
for path_segment in expression:
if isinstance(this, dict):
this = this.get(path_segment)
elif isinstance(this, list) and is_int(path_segment):
this = seq_get(this, int(path_segment))
else:
raise NotImplementedError(f"Unable to extract value for {this} at {path_segment}.")
if this is None:
break
return this
ENV = {
"exp": exp,
# aggs
@ -175,12 +191,12 @@ ENV = {
"DOT": null_if_any(lambda e, this: e[this]),
"EQ": null_if_any(lambda this, e: this == e),
"EXTRACT": null_if_any(lambda this, e: getattr(e, this)),
"GETPATH": null_if_any(lambda this, e: this.get(e)),
"GT": null_if_any(lambda this, e: this > e),
"GTE": null_if_any(lambda this, e: this >= e),
"IF": lambda predicate, true, false: true if predicate else false,
"INTDIV": null_if_any(lambda e, this: e // this),
"INTERVAL": interval,
"JSONEXTRACT": jsonextract,
"LEFT": null_if_any(lambda this, e: this[:e]),
"LIKE": null_if_any(
lambda this, e: bool(re.match(e.replace("_", ".").replace("%", ".*"), this))

View file

@ -9,7 +9,7 @@ from sqlglot.errors import ExecuteError
from sqlglot.executor.context import Context
from sqlglot.executor.env import ENV
from sqlglot.executor.table import RowReader, Table
from sqlglot.helper import csv_reader, subclasses
from sqlglot.helper import csv_reader, ensure_list, subclasses
class PythonExecutor:
@ -368,7 +368,7 @@ def _rename(self, e):
if isinstance(e, exp.Func) and e.is_var_len_args:
*head, tail = values
return self.func(e.key, *head, *tail)
return self.func(e.key, *head, *ensure_list(tail))
return self.func(e.key, *values)
except Exception as ex:
@ -429,18 +429,24 @@ class Python(Dialect):
exp.Between: _rename,
exp.Boolean: lambda self, e: "True" if e.this else "False",
exp.Cast: lambda self, e: f"CAST({self.sql(e.this)}, exp.DataType.Type.{e.args['to']})",
exp.Column: lambda self, e: f"scope[{self.sql(e, 'table') or None}][{self.sql(e.this)}]",
exp.Column: lambda self,
e: f"scope[{self.sql(e, 'table') or None}][{self.sql(e.this)}]",
exp.Concat: lambda self, e: self.func(
"SAFECONCAT" if e.args.get("safe") else "CONCAT", *e.expressions
),
exp.Distinct: lambda self, e: f"set({self.sql(e, 'this')})",
exp.Div: _div_sql,
exp.Extract: lambda self, e: f"EXTRACT('{e.name.lower()}', {self.sql(e, 'expression')})",
exp.In: lambda self, e: f"{self.sql(e, 'this')} in {{{self.expressions(e, flat=True)}}}",
exp.Extract: lambda self,
e: f"EXTRACT('{e.name.lower()}', {self.sql(e, 'expression')})",
exp.In: lambda self,
e: f"{self.sql(e, 'this')} in {{{self.expressions(e, flat=True)}}}",
exp.Interval: lambda self, e: f"INTERVAL({self.sql(e.this)}, '{self.sql(e.unit)}')",
exp.Is: lambda self, e: (
self.binary(e, "==") if isinstance(e.this, exp.Literal) else self.binary(e, "is")
),
exp.JSONPath: lambda self, e: f"[{','.join(self.sql(p) for p in e.expressions[1:])}]",
exp.JSONPathKey: lambda self, e: f"'{self.sql(e.this)}'",
exp.JSONPathSubscript: lambda self, e: f"'{e.this}'",
exp.Lambda: _lambda_sql,
exp.Not: lambda self, e: f"not {self.sql(e.this)}",
exp.Null: lambda *_: "None",

View file

@ -29,6 +29,7 @@ from sqlglot.helper import (
camel_to_snake_case,
ensure_collection,
ensure_list,
is_int,
seq_get,
subclasses,
)
@ -175,13 +176,7 @@ class Expression(metaclass=_Expression):
"""
Checks whether a Literal expression is an integer.
"""
if self.is_number:
try:
int(self.name)
return True
except ValueError:
pass
return False
return self.is_number and is_int(self.name)
@property
def is_star(self) -> bool:
@ -493,8 +488,8 @@ class Expression(metaclass=_Expression):
A AND B AND C -> [A, B, C]
"""
for node, _, _ in self.dfs(prune=lambda n, p, *_: p and not type(n) is self.__class__):
if not type(node) is self.__class__:
for node, _, _ in self.dfs(prune=lambda n, p, *_: p and type(n) is not self.__class__):
if type(node) is not self.__class__:
yield node.unnest() if unnest and not isinstance(node, Subquery) else node
def __str__(self) -> str:
@ -553,10 +548,12 @@ class Expression(metaclass=_Expression):
return new_node
@t.overload
def replace(self, expression: E) -> E: ...
def replace(self, expression: E) -> E:
...
@t.overload
def replace(self, expression: None) -> None: ...
def replace(self, expression: None) -> None:
...
def replace(self, expression):
"""
@ -610,7 +607,8 @@ class Expression(metaclass=_Expression):
>>> sqlglot.parse_one("SELECT x from y").assert_is(Select).select("z").sql()
'SELECT x, z FROM y'
"""
assert isinstance(self, type_)
if not isinstance(self, type_):
raise AssertionError(f"{self} is not {type_}.")
return self
def error_messages(self, args: t.Optional[t.Sequence] = None) -> t.List[str]:
@ -1133,6 +1131,7 @@ class SetItem(Expression):
class Show(Expression):
arg_types = {
"this": True,
"history": False,
"terse": False,
"target": False,
"offset": False,
@ -1676,7 +1675,6 @@ class Index(Expression):
"amp": False, # teradata
"include": False,
"partition_by": False, # teradata
"where": False, # postgres partial indexes
}
@ -2573,7 +2571,7 @@ class HistoricalData(Expression):
class Table(Expression):
arg_types = {
"this": True,
"this": False,
"alias": False,
"db": False,
"catalog": False,
@ -3664,6 +3662,7 @@ class DataType(Expression):
BINARY = auto()
BIT = auto()
BOOLEAN = auto()
BPCHAR = auto()
CHAR = auto()
DATE = auto()
DATE32 = auto()
@ -3805,6 +3804,7 @@ class DataType(Expression):
dtype: DATA_TYPE,
dialect: DialectType = None,
udt: bool = False,
copy: bool = True,
**kwargs,
) -> DataType:
"""
@ -3815,7 +3815,8 @@ class DataType(Expression):
dialect: the dialect to use for parsing `dtype`, in case it's a string.
udt: when set to True, `dtype` will be used as-is if it can't be parsed into a
DataType, thus creating a user-defined type.
kawrgs: additional arguments to pass in the constructor of DataType.
copy: whether or not to copy the data type.
kwargs: additional arguments to pass in the constructor of DataType.
Returns:
The constructed DataType object.
@ -3837,7 +3838,7 @@ class DataType(Expression):
elif isinstance(dtype, DataType.Type):
data_type_exp = DataType(this=dtype)
elif isinstance(dtype, DataType):
return dtype
return maybe_copy(dtype, copy)
else:
raise ValueError(f"Invalid data type: {type(dtype)}. Expected str or DataType.Type")
@ -3855,7 +3856,7 @@ class DataType(Expression):
True, if and only if there is a type in `dtypes` which is equal to this DataType.
"""
for dtype in dtypes:
other = DataType.build(dtype, udt=True)
other = DataType.build(dtype, copy=False, udt=True)
if (
other.expressions
@ -4001,7 +4002,7 @@ class Dot(Binary):
def build(self, expressions: t.Sequence[Expression]) -> Dot:
"""Build a Dot object with a sequence of expressions."""
if len(expressions) < 2:
raise ValueError(f"Dot requires >= 2 expressions.")
raise ValueError("Dot requires >= 2 expressions.")
return t.cast(Dot, reduce(lambda x, y: Dot(this=x, expression=y), expressions))
@ -4128,10 +4129,6 @@ class Sub(Binary):
pass
class ArrayOverlaps(Binary):
pass
# Unary Expressions
# (NOT a)
class Unary(Condition):
@ -4469,6 +4466,10 @@ class ArrayJoin(Func):
arg_types = {"this": True, "expression": True, "null": False}
class ArrayOverlaps(Binary, Func):
pass
class ArraySize(Func):
arg_types = {"this": True, "expression": False}
@ -4490,15 +4491,37 @@ class Avg(AggFunc):
class AnyValue(AggFunc):
arg_types = {"this": True, "having": False, "max": False, "ignore_nulls": False}
arg_types = {"this": True, "having": False, "max": False}
class First(Func):
arg_types = {"this": True, "ignore_nulls": False}
class Lag(AggFunc):
arg_types = {"this": True, "offset": False, "default": False}
class Last(Func):
arg_types = {"this": True, "ignore_nulls": False}
class Lead(AggFunc):
arg_types = {"this": True, "offset": False, "default": False}
# some dialects have a distinction between first and first_value, usually first is an aggregate func
# and first_value is a window func
class First(AggFunc):
pass
class Last(AggFunc):
pass
class FirstValue(AggFunc):
pass
class LastValue(AggFunc):
pass
class NthValue(AggFunc):
arg_types = {"this": True, "offset": True}
class Case(Func):
@ -4611,7 +4634,7 @@ class CurrentTime(Func):
class CurrentTimestamp(Func):
arg_types = {"this": False}
arg_types = {"this": False, "transaction": False}
class CurrentUser(Func):
@ -4712,6 +4735,7 @@ class TimestampSub(Func, TimeUnit):
class TimestampDiff(Func, TimeUnit):
_sql_names = ["TIMESTAMPDIFF", "TIMESTAMP_DIFF"]
arg_types = {"this": True, "expression": True, "unit": False}
@ -4857,6 +4881,59 @@ class IsInf(Func):
_sql_names = ["IS_INF", "ISINF"]
class JSONPath(Expression):
arg_types = {"expressions": True}
@property
def output_name(self) -> str:
last_segment = self.expressions[-1].this
return last_segment if isinstance(last_segment, str) else ""
class JSONPathPart(Expression):
arg_types = {}
class JSONPathFilter(JSONPathPart):
arg_types = {"this": True}
class JSONPathKey(JSONPathPart):
arg_types = {"this": True}
class JSONPathRecursive(JSONPathPart):
arg_types = {"this": False}
class JSONPathRoot(JSONPathPart):
pass
class JSONPathScript(JSONPathPart):
arg_types = {"this": True}
class JSONPathSlice(JSONPathPart):
arg_types = {"start": False, "end": False, "step": False}
class JSONPathSelector(JSONPathPart):
arg_types = {"this": True}
class JSONPathSubscript(JSONPathPart):
arg_types = {"this": True}
class JSONPathUnion(JSONPathPart):
arg_types = {"expressions": True}
class JSONPathWildcard(JSONPathPart):
pass
class FormatJson(Expression):
pass
@ -4940,18 +5017,30 @@ class JSONBContains(Binary):
class JSONExtract(Binary, Func):
arg_types = {"this": True, "expression": True, "expressions": False}
_sql_names = ["JSON_EXTRACT"]
is_var_len_args = True
@property
def output_name(self) -> str:
return self.expression.output_name if not self.expressions else ""
class JSONExtractScalar(JSONExtract):
class JSONExtractScalar(Binary, Func):
arg_types = {"this": True, "expression": True, "expressions": False}
_sql_names = ["JSON_EXTRACT_SCALAR"]
is_var_len_args = True
@property
def output_name(self) -> str:
return self.expression.output_name
class JSONBExtract(JSONExtract):
class JSONBExtract(Binary, Func):
_sql_names = ["JSONB_EXTRACT"]
class JSONBExtractScalar(JSONExtract):
class JSONBExtractScalar(Binary, Func):
_sql_names = ["JSONB_EXTRACT_SCALAR"]
@ -4972,15 +5061,6 @@ class ParseJSON(Func):
is_var_len_args = True
# https://docs.snowflake.com/en/sql-reference/functions/get_path
class GetPath(Func):
arg_types = {"this": True, "expression": True}
@property
def output_name(self) -> str:
return self.expression.output_name
class Least(Func):
arg_types = {"this": True, "expressions": False}
is_var_len_args = True
@ -5476,6 +5556,8 @@ def _norm_arg(arg):
ALL_FUNCTIONS = subclasses(__name__, Func, (AggFunc, Anonymous, Func))
FUNCTION_BY_NAME = {name: func for func in ALL_FUNCTIONS for name in func.sql_names()}
JSON_PATH_PARTS = subclasses(__name__, JSONPathPart, (JSONPathPart,))
# Helpers
@t.overload
@ -5487,7 +5569,8 @@ def maybe_parse(
prefix: t.Optional[str] = None,
copy: bool = False,
**opts,
) -> E: ...
) -> E:
...
@t.overload
@ -5499,7 +5582,8 @@ def maybe_parse(
prefix: t.Optional[str] = None,
copy: bool = False,
**opts,
) -> E: ...
) -> E:
...
def maybe_parse(
@ -5539,7 +5623,7 @@ def maybe_parse(
return sql_or_expression
if sql_or_expression is None:
raise ParseError(f"SQL cannot be None")
raise ParseError("SQL cannot be None")
import sqlglot
@ -5551,11 +5635,13 @@ def maybe_parse(
@t.overload
def maybe_copy(instance: None, copy: bool = True) -> None: ...
def maybe_copy(instance: None, copy: bool = True) -> None:
...
@t.overload
def maybe_copy(instance: E, copy: bool = True) -> E: ...
def maybe_copy(instance: E, copy: bool = True) -> E:
...
def maybe_copy(instance, copy=True):
@ -6174,17 +6260,19 @@ def paren(expression: ExpOrStr, copy: bool = True) -> Paren:
return Paren(this=maybe_parse(expression, copy=copy))
SAFE_IDENTIFIER_RE = re.compile(r"^[_a-zA-Z][\w]*$")
SAFE_IDENTIFIER_RE: t.Pattern[str] = re.compile(r"^[_a-zA-Z][\w]*$")
@t.overload
def to_identifier(name: None, quoted: t.Optional[bool] = None, copy: bool = True) -> None: ...
def to_identifier(name: None, quoted: t.Optional[bool] = None, copy: bool = True) -> None:
...
@t.overload
def to_identifier(
name: str | Identifier, quoted: t.Optional[bool] = None, copy: bool = True
) -> Identifier: ...
) -> Identifier:
...
def to_identifier(name, quoted=None, copy=True):
@ -6256,11 +6344,13 @@ def to_interval(interval: str | Literal) -> Interval:
@t.overload
def to_table(sql_path: str | Table, **kwargs) -> Table: ...
def to_table(sql_path: str | Table, **kwargs) -> Table:
...
@t.overload
def to_table(sql_path: None, **kwargs) -> None: ...
def to_table(sql_path: None, **kwargs) -> None:
...
def to_table(
@ -6460,7 +6550,7 @@ def column(
return this
def cast(expression: ExpOrStr, to: DATA_TYPE, **opts) -> Cast:
def cast(expression: ExpOrStr, to: DATA_TYPE, copy: bool = True, **opts) -> Cast:
"""Cast an expression to a data type.
Example:
@ -6470,12 +6560,13 @@ def cast(expression: ExpOrStr, to: DATA_TYPE, **opts) -> Cast:
Args:
expression: The expression to cast.
to: The datatype to cast to.
copy: Whether or not to copy the supplied expressions.
Returns:
The new Cast instance.
"""
expression = maybe_parse(expression, **opts)
data_type = DataType.build(to, **opts)
expression = maybe_parse(expression, copy=copy, **opts)
data_type = DataType.build(to, copy=copy, **opts)
expression = Cast(this=expression, to=data_type)
expression.type = data_type
return expression

View file

@ -9,6 +9,7 @@ from functools import reduce
from sqlglot import exp
from sqlglot.errors import ErrorLevel, UnsupportedError, concat_messages
from sqlglot.helper import apply_index_offset, csv, seq_get
from sqlglot.jsonpath import ALL_JSON_PATH_PARTS, JSON_PATH_PART_TRANSFORMS
from sqlglot.time import format_time
from sqlglot.tokens import TokenType
@ -21,7 +22,18 @@ logger = logging.getLogger("sqlglot")
ESCAPED_UNICODE_RE = re.compile(r"\\(\d+)")
class Generator:
class _Generator(type):
def __new__(cls, clsname, bases, attrs):
klass = super().__new__(cls, clsname, bases, attrs)
# Remove transforms that correspond to unsupported JSONPathPart expressions
for part in ALL_JSON_PATH_PARTS - klass.SUPPORTED_JSON_PATH_PARTS:
klass.TRANSFORMS.pop(part, None)
return klass
class Generator(metaclass=_Generator):
"""
Generator converts a given syntax tree to the corresponding SQL string.
@ -58,19 +70,23 @@ class Generator:
Default: True
"""
TRANSFORMS = {
TRANSFORMS: t.Dict[t.Type[exp.Expression], t.Callable[..., str]] = {
**JSON_PATH_PART_TRANSFORMS,
exp.AutoRefreshProperty: lambda self, e: f"AUTO REFRESH {self.sql(e, 'this')}",
exp.CaseSpecificColumnConstraint: lambda self,
e: f"{'NOT ' if e.args.get('not_') else ''}CASESPECIFIC",
exp.CharacterSetColumnConstraint: lambda self, e: f"CHARACTER SET {self.sql(e, 'this')}",
exp.CharacterSetProperty: lambda self,
e: f"{'DEFAULT ' if e.args.get('default') else ''}CHARACTER SET={self.sql(e, 'this')}",
exp.CheckColumnConstraint: lambda self, e: f"CHECK ({self.sql(e, 'this')})",
exp.ClusteredColumnConstraint: lambda self,
e: f"CLUSTERED ({self.expressions(e, 'this', indent=False)})",
exp.CollateColumnConstraint: lambda self, e: f"COLLATE {self.sql(e, 'this')}",
exp.CommentColumnConstraint: lambda self, e: f"COMMENT {self.sql(e, 'this')}",
exp.CopyGrantsProperty: lambda self, e: "COPY GRANTS",
exp.DateAdd: lambda self, e: self.func(
"DATE_ADD", e.this, e.expression, exp.Literal.string(e.text("unit"))
),
exp.CaseSpecificColumnConstraint: lambda self, e: f"{'NOT ' if e.args.get('not_') else ''}CASESPECIFIC",
exp.CharacterSetColumnConstraint: lambda self, e: f"CHARACTER SET {self.sql(e, 'this')}",
exp.CharacterSetProperty: lambda self, e: f"{'DEFAULT ' if e.args.get('default') else ''}CHARACTER SET={self.sql(e, 'this')}",
exp.CheckColumnConstraint: lambda self, e: f"CHECK ({self.sql(e, 'this')})",
exp.ClusteredColumnConstraint: lambda self, e: f"CLUSTERED ({self.expressions(e, 'this', indent=False)})",
exp.CollateColumnConstraint: lambda self, e: f"COLLATE {self.sql(e, 'this')}",
exp.AutoRefreshProperty: lambda self, e: f"AUTO REFRESH {self.sql(e, 'this')}",
exp.CopyGrantsProperty: lambda self, e: "COPY GRANTS",
exp.CommentColumnConstraint: lambda self, e: f"COMMENT {self.sql(e, 'this')}",
exp.DateFormatColumnConstraint: lambda self, e: f"FORMAT {self.sql(e, 'this')}",
exp.DefaultColumnConstraint: lambda self, e: f"DEFAULT {self.sql(e, 'this')}",
exp.EncodeColumnConstraint: lambda self, e: f"ENCODE {self.sql(e, 'this')}",
@ -85,29 +101,33 @@ class Generator:
exp.LocationProperty: lambda self, e: self.naked_property(e),
exp.LogProperty: lambda self, e: f"{'NO ' if e.args.get('no') else ''}LOG",
exp.MaterializedProperty: lambda self, e: "MATERIALIZED",
exp.NonClusteredColumnConstraint: lambda self,
e: f"NONCLUSTERED ({self.expressions(e, 'this', indent=False)})",
exp.NoPrimaryIndexProperty: lambda self, e: "NO PRIMARY INDEX",
exp.NonClusteredColumnConstraint: lambda self, e: f"NONCLUSTERED ({self.expressions(e, 'this', indent=False)})",
exp.NotForReplicationColumnConstraint: lambda self, e: "NOT FOR REPLICATION",
exp.OnCommitProperty: lambda self, e: f"ON COMMIT {'DELETE' if e.args.get('delete') else 'PRESERVE'} ROWS",
exp.OnCommitProperty: lambda self,
e: f"ON COMMIT {'DELETE' if e.args.get('delete') else 'PRESERVE'} ROWS",
exp.OnProperty: lambda self, e: f"ON {self.sql(e, 'this')}",
exp.OnUpdateColumnConstraint: lambda self, e: f"ON UPDATE {self.sql(e, 'this')}",
exp.OutputModelProperty: lambda self, e: f"OUTPUT{self.sql(e, 'this')}",
exp.PathColumnConstraint: lambda self, e: f"PATH {self.sql(e, 'this')}",
exp.RemoteWithConnectionModelProperty: lambda self, e: f"REMOTE WITH CONNECTION {self.sql(e, 'this')}",
exp.RemoteWithConnectionModelProperty: lambda self,
e: f"REMOTE WITH CONNECTION {self.sql(e, 'this')}",
exp.ReturnsProperty: lambda self, e: self.naked_property(e),
exp.SampleProperty: lambda self, e: f"SAMPLE BY {self.sql(e, 'this')}",
exp.SetProperty: lambda self, e: f"{'MULTI' if e.args.get('multi') else ''}SET",
exp.SetConfigProperty: lambda self, e: self.sql(e, "this"),
exp.SetProperty: lambda self, e: f"{'MULTI' if e.args.get('multi') else ''}SET",
exp.SettingsProperty: lambda self, e: f"SETTINGS{self.seg('')}{(self.expressions(e))}",
exp.SqlReadWriteProperty: lambda self, e: e.name,
exp.SqlSecurityProperty: lambda self, e: f"SQL SECURITY {'DEFINER' if e.args.get('definer') else 'INVOKER'}",
exp.SqlSecurityProperty: lambda self,
e: f"SQL SECURITY {'DEFINER' if e.args.get('definer') else 'INVOKER'}",
exp.StabilityProperty: lambda self, e: e.name,
exp.TemporaryProperty: lambda self, e: f"TEMPORARY",
exp.ToTableProperty: lambda self, e: f"TO {self.sql(e.this)}",
exp.TransientProperty: lambda self, e: "TRANSIENT",
exp.TransformModelProperty: lambda self, e: self.func("TRANSFORM", *e.expressions),
exp.TemporaryProperty: lambda self, e: "TEMPORARY",
exp.TitleColumnConstraint: lambda self, e: f"TITLE {self.sql(e, 'this')}",
exp.UppercaseColumnConstraint: lambda self, e: f"UPPERCASE",
exp.ToTableProperty: lambda self, e: f"TO {self.sql(e.this)}",
exp.TransformModelProperty: lambda self, e: self.func("TRANSFORM", *e.expressions),
exp.TransientProperty: lambda self, e: "TRANSIENT",
exp.UppercaseColumnConstraint: lambda self, e: "UPPERCASE",
exp.VarMap: lambda self, e: self.func("MAP", e.args["keys"], e.args["values"]),
exp.VolatileProperty: lambda self, e: "VOLATILE",
exp.WithJournalTableProperty: lambda self, e: f"WITH JOURNAL TABLE={self.sql(e, 'this')}",
@ -117,6 +137,10 @@ class Generator:
# True: Full Support, None: No support, False: No support in window specifications
NULL_ORDERING_SUPPORTED: t.Optional[bool] = True
# Whether or not ignore nulls is inside the agg or outside.
# FIRST(x IGNORE NULLS) OVER vs FIRST (x) IGNORE NULLS OVER
IGNORE_NULLS_IN_FUNC = False
# Whether or not locking reads (i.e. SELECT ... FOR UPDATE/SHARE) are supported
LOCKING_READS_SUPPORTED = False
@ -266,6 +290,24 @@ class Generator:
# Whether or not UNLOGGED tables can be created
SUPPORTS_UNLOGGED_TABLES = False
# Whether or not the CREATE TABLE LIKE statement is supported
SUPPORTS_CREATE_TABLE_LIKE = True
# Whether or not the LikeProperty needs to be specified inside of the schema clause
LIKE_PROPERTY_INSIDE_SCHEMA = False
# Whether or not the JSON extraction operators expect a value of type JSON
JSON_TYPE_REQUIRED_FOR_EXTRACTION = False
# Whether or not bracketed keys like ["foo"] are supported in JSON paths
JSON_PATH_BRACKETED_KEY_SUPPORTED = True
# Whether or not to escape keys using single quotes in JSON paths
JSON_PATH_SINGLE_QUOTE_ESCAPE = False
# The JSONPathPart expressions supported by this dialect
SUPPORTED_JSON_PATH_PARTS = ALL_JSON_PATH_PARTS.copy()
TYPE_MAPPING = {
exp.DataType.Type.NCHAR: "CHAR",
exp.DataType.Type.NVARCHAR: "VARCHAR",
@ -641,8 +683,6 @@ class Generator:
if callable(transform):
sql = transform(self, expression)
elif transform:
sql = transform
elif isinstance(expression, exp.Expression):
exp_handler_name = f"{expression.key}_sql"
@ -802,7 +842,7 @@ class Generator:
desc = expression.args.get("desc")
if desc is not None:
return f"PRIMARY KEY{' DESC' if desc else ' ASC'}"
return f"PRIMARY KEY"
return "PRIMARY KEY"
def uniquecolumnconstraint_sql(self, expression: exp.UniqueColumnConstraint) -> str:
this = self.sql(expression, "this")
@ -1218,9 +1258,21 @@ class Generator:
return f"{property_name}={self.sql(expression, 'this')}"
def likeproperty_sql(self, expression: exp.LikeProperty) -> str:
options = " ".join(f"{e.name} {self.sql(e, 'value')}" for e in expression.expressions)
options = f" {options}" if options else ""
return f"LIKE {self.sql(expression, 'this')}{options}"
if self.SUPPORTS_CREATE_TABLE_LIKE:
options = " ".join(f"{e.name} {self.sql(e, 'value')}" for e in expression.expressions)
options = f" {options}" if options else ""
like = f"LIKE {self.sql(expression, 'this')}{options}"
if self.LIKE_PROPERTY_INSIDE_SCHEMA and not isinstance(expression.parent, exp.Schema):
like = f"({like})"
return like
if expression.expressions:
self.unsupported("Transpilation of LIKE property options is unsupported")
select = exp.select("*").from_(expression.this).limit(0)
return f"AS {self.sql(select)}"
def fallbackproperty_sql(self, expression: exp.FallbackProperty) -> str:
no = "NO " if expression.args.get("no") else ""
@ -2367,6 +2419,31 @@ class Generator:
def jsonkeyvalue_sql(self, expression: exp.JSONKeyValue) -> str:
return f"{self.sql(expression, 'this')}{self.JSON_KEY_VALUE_PAIR_SEP} {self.sql(expression, 'expression')}"
def jsonpath_sql(self, expression: exp.JSONPath) -> str:
path = self.expressions(expression, sep="", flat=True).lstrip(".")
return f"{self.dialect.QUOTE_START}{path}{self.dialect.QUOTE_END}"
def json_path_part(self, expression: int | str | exp.JSONPathPart) -> str:
if isinstance(expression, exp.JSONPathPart):
transform = self.TRANSFORMS.get(expression.__class__)
if not callable(transform):
self.unsupported(f"Unsupported JSONPathPart type {expression.__class__.__name__}")
return ""
return transform(self, expression)
if isinstance(expression, int):
return str(expression)
if self.JSON_PATH_SINGLE_QUOTE_ESCAPE:
escaped = expression.replace("'", "\\'")
escaped = f"\\'{expression}\\'"
else:
escaped = expression.replace('"', '\\"')
escaped = f'"{escaped}"'
return escaped
def formatjson_sql(self, expression: exp.FormatJson) -> str:
return f"{self.sql(expression, 'this')} FORMAT JSON"
@ -2620,6 +2697,9 @@ class Generator:
zone = self.sql(expression, "this")
return f"CURRENT_DATE({zone})" if zone else "CURRENT_DATE"
def currenttimestamp_sql(self, expression: exp.CurrentTimestamp) -> str:
return self.func("CURRENT_TIMESTAMP", expression.this)
def collate_sql(self, expression: exp.Collate) -> str:
if self.COLLATE_IS_FUNC:
return self.function_fallback_sql(expression)
@ -2761,10 +2841,20 @@ class Generator:
return f"DISTINCT{this}{on}"
def ignorenulls_sql(self, expression: exp.IgnoreNulls) -> str:
return f"{self.sql(expression, 'this')} IGNORE NULLS"
return self._embed_ignore_nulls(expression, "IGNORE NULLS")
def respectnulls_sql(self, expression: exp.RespectNulls) -> str:
return f"{self.sql(expression, 'this')} RESPECT NULLS"
return self._embed_ignore_nulls(expression, "RESPECT NULLS")
def _embed_ignore_nulls(self, expression: exp.IgnoreNulls | exp.RespectNulls, text: str) -> str:
if self.IGNORE_NULLS_IN_FUNC:
this = expression.find(exp.AggFunc)
if this:
sql = self.sql(this)
sql = sql[:-1] + f" {text})"
return sql
return f"{self.sql(expression, 'this')} {text}"
def intdiv_sql(self, expression: exp.IntDiv) -> str:
return self.sql(
@ -2935,7 +3025,7 @@ class Generator:
def format_args(self, *args: t.Optional[str | exp.Expression]) -> str:
arg_sqls = tuple(self.sql(arg) for arg in args if arg is not None)
if self.pretty and self.text_width(arg_sqls) > self.max_text_width:
return self.indent("\n" + f",\n".join(arg_sqls) + "\n", skip_first=True, skip_last=True)
return self.indent("\n" + ",\n".join(arg_sqls) + "\n", skip_first=True, skip_last=True)
return ", ".join(arg_sqls)
def text_width(self, args: t.Iterable) -> int:
@ -3279,6 +3369,22 @@ class Generator:
return self.func("LAST_DAY", expression.this)
def _jsonpathkey_sql(self, expression: exp.JSONPathKey) -> str:
this = expression.this
if isinstance(this, exp.JSONPathWildcard):
this = self.json_path_part(this)
return f".{this}" if this else ""
if exp.SAFE_IDENTIFIER_RE.match(this):
return f".{this}"
this = self.json_path_part(this)
return f"[{this}]" if self.JSON_PATH_BRACKETED_KEY_SUPPORTED else f".{this}"
def _jsonpathsubscript_sql(self, expression: exp.JSONPathSubscript) -> str:
this = self.json_path_part(expression.this)
return f"[{this}]" if this else ""
def _simplify_unless_literal(self, expression: E) -> E:
if not isinstance(expression, exp.Literal):
from sqlglot.optimizer.simplify import simplify

View file

@ -53,11 +53,13 @@ def seq_get(seq: t.Sequence[T], index: int) -> t.Optional[T]:
@t.overload
def ensure_list(value: t.Collection[T]) -> t.List[T]: ...
def ensure_list(value: t.Collection[T]) -> t.List[T]:
...
@t.overload
def ensure_list(value: T) -> t.List[T]: ...
def ensure_list(value: T) -> t.List[T]:
...
def ensure_list(value):
@ -79,11 +81,13 @@ def ensure_list(value):
@t.overload
def ensure_collection(value: t.Collection[T]) -> t.Collection[T]: ...
def ensure_collection(value: t.Collection[T]) -> t.Collection[T]:
...
@t.overload
def ensure_collection(value: T) -> t.Collection[T]: ...
def ensure_collection(value: T) -> t.Collection[T]:
...
def ensure_collection(value):
@ -232,7 +236,7 @@ def tsort(dag: t.Dict[T, t.Set[T]]) -> t.List[T]:
for node, deps in tuple(dag.items()):
for dep in deps:
if not dep in dag:
if dep not in dag:
dag[dep] = set()
while dag:
@ -316,6 +320,14 @@ def find_new_name(taken: t.Collection[str], base: str) -> str:
return new
def is_int(text: str) -> bool:
try:
int(text)
return True
except ValueError:
return False
def name_sequence(prefix: str) -> t.Callable[[], str]:
"""Returns a name generator given a prefix (e.g. a0, a1, a2, ... if the prefix is "a")."""
sequence = count()

View file

@ -2,8 +2,8 @@ from __future__ import annotations
import typing as t
import sqlglot.expressions as exp
from sqlglot.errors import ParseError
from sqlglot.expressions import SAFE_IDENTIFIER_RE
from sqlglot.tokens import Token, Tokenizer, TokenType
if t.TYPE_CHECKING:
@ -36,20 +36,8 @@ class JSONPathTokenizer(Tokenizer):
STRING_ESCAPES = ["\\"]
JSONPathNode = t.Dict[str, t.Any]
def _node(kind: str, value: t.Any = None, **kwargs: t.Any) -> JSONPathNode:
node = {"kind": kind, **kwargs}
if value is not None:
node["value"] = value
return node
def parse(path: str) -> t.List[JSONPathNode]:
"""Takes in a JSONPath string and converts into a list of nodes."""
def parse(path: str) -> exp.JSONPath:
"""Takes in a JSON path string and parses it into a JSONPath expression."""
tokens = JSONPathTokenizer().tokenize(path)
size = len(tokens)
@ -89,7 +77,7 @@ def parse(path: str) -> t.List[JSONPathNode]:
if token:
return token.text
if _match(TokenType.STAR):
return _node("wildcard")
return exp.JSONPathWildcard()
if _match(TokenType.PLACEHOLDER) or _match(TokenType.L_PAREN):
script = _prev().text == "("
start = i
@ -100,9 +88,9 @@ def parse(path: str) -> t.List[JSONPathNode]:
if _curr() in (TokenType.R_BRACKET, None):
break
_advance()
return _node(
"script" if script else "filter", path[tokens[start].start : tokens[i].end]
)
expr_type = exp.JSONPathScript if script else exp.JSONPathFilter
return expr_type(this=path[tokens[start].start : tokens[i].end])
number = "-" if _match(TokenType.DASH) else ""
@ -112,6 +100,7 @@ def parse(path: str) -> t.List[JSONPathNode]:
if number:
return int(number)
return False
def _parse_slice() -> t.Any:
@ -121,9 +110,10 @@ def parse(path: str) -> t.List[JSONPathNode]:
if end is None and step is None:
return start
return _node("slice", start=start, end=end, step=step)
def _parse_bracket() -> JSONPathNode:
return exp.JSONPathSlice(start=start, end=end, step=step)
def _parse_bracket() -> exp.JSONPathPart:
literal = _parse_slice()
if isinstance(literal, str) or literal is not False:
@ -136,13 +126,15 @@ def parse(path: str) -> t.List[JSONPathNode]:
if len(indexes) == 1:
if isinstance(literal, str):
node = _node("key", indexes[0])
elif isinstance(literal, dict) and literal["kind"] in ("script", "filter"):
node = _node("selector", indexes[0])
node: exp.JSONPathPart = exp.JSONPathKey(this=indexes[0])
elif isinstance(literal, exp.JSONPathPart) and isinstance(
literal, (exp.JSONPathScript, exp.JSONPathFilter)
):
node = exp.JSONPathSelector(this=indexes[0])
else:
node = _node("subscript", indexes[0])
node = exp.JSONPathSubscript(this=indexes[0])
else:
node = _node("union", indexes)
node = exp.JSONPathUnion(expressions=indexes)
else:
raise ParseError(_error("Cannot have empty segment"))
@ -150,66 +142,56 @@ def parse(path: str) -> t.List[JSONPathNode]:
return node
nodes = []
# We canonicalize the JSON path AST so that it always starts with a
# "root" element, so paths like "field" will be generated as "$.field"
_match(TokenType.DOLLAR)
expressions: t.List[exp.JSONPathPart] = [exp.JSONPathRoot()]
while _curr():
if _match(TokenType.DOLLAR):
nodes.append(_node("root"))
elif _match(TokenType.DOT):
if _match(TokenType.DOT) or _match(TokenType.COLON):
recursive = _prev().text == ".."
value = _match(TokenType.VAR) or _match(TokenType.STAR)
nodes.append(
_node("recursive" if recursive else "child", value=value.text if value else None)
)
if _match(TokenType.VAR) or _match(TokenType.IDENTIFIER):
value: t.Optional[str | exp.JSONPathWildcard] = _prev().text
elif _match(TokenType.STAR):
value = exp.JSONPathWildcard()
else:
value = None
if recursive:
expressions.append(exp.JSONPathRecursive(this=value))
elif value:
expressions.append(exp.JSONPathKey(this=value))
else:
raise ParseError(_error("Expected key name or * after DOT"))
elif _match(TokenType.L_BRACKET):
nodes.append(_parse_bracket())
elif _match(TokenType.VAR):
nodes.append(_node("key", _prev().text))
expressions.append(_parse_bracket())
elif _match(TokenType.VAR) or _match(TokenType.IDENTIFIER):
expressions.append(exp.JSONPathKey(this=_prev().text))
elif _match(TokenType.STAR):
nodes.append(_node("wildcard"))
elif _match(TokenType.PARAMETER):
nodes.append(_node("current"))
expressions.append(exp.JSONPathWildcard())
else:
raise ParseError(_error(f"Unexpected {tokens[i].token_type}"))
return nodes
return exp.JSONPath(expressions=expressions)
MAPPING = {
"child": lambda n: f".{n['value']}" if n.get("value") is not None else "",
"filter": lambda n: f"?{n['value']}",
"key": lambda n: (
f".{n['value']}" if SAFE_IDENTIFIER_RE.match(n["value"]) else f'[{generate([n["value"]])}]'
),
"recursive": lambda n: f"..{n['value']}" if n.get("value") is not None else "..",
"root": lambda _: "$",
"script": lambda n: f"({n['value']}",
"slice": lambda n: ":".join(
"" if p is False else generate([p])
for p in [n["start"], n["end"], n["step"]]
JSON_PATH_PART_TRANSFORMS: t.Dict[t.Type[exp.Expression], t.Callable[..., str]] = {
exp.JSONPathFilter: lambda _, e: f"?{e.this}",
exp.JSONPathKey: lambda self, e: self._jsonpathkey_sql(e),
exp.JSONPathRecursive: lambda _, e: f"..{e.this or ''}",
exp.JSONPathRoot: lambda *_: "$",
exp.JSONPathScript: lambda _, e: f"({e.this}",
exp.JSONPathSelector: lambda self, e: f"[{self.json_path_part(e.this)}]",
exp.JSONPathSlice: lambda self, e: ":".join(
"" if p is False else self.json_path_part(p)
for p in [e.args.get("start"), e.args.get("end"), e.args.get("step")]
if p is not None
),
"selector": lambda n: f"[{generate([n['value']])}]",
"subscript": lambda n: f"[{generate([n['value']])}]",
"union": lambda n: f"[{','.join(generate([p]) for p in n['value'])}]",
"wildcard": lambda _: "*",
exp.JSONPathSubscript: lambda self, e: self._jsonpathsubscript_sql(e),
exp.JSONPathUnion: lambda self,
e: f"[{','.join(self.json_path_part(p) for p in e.expressions)}]",
exp.JSONPathWildcard: lambda *_: "*",
}
def generate(
nodes: t.List[JSONPathNode],
mapping: t.Optional[t.Dict[str, t.Callable[[JSONPathNode], str]]] = None,
) -> str:
mapping = MAPPING if mapping is None else mapping
path = []
for node in nodes:
if isinstance(node, dict):
path.append(mapping[node["kind"]](node))
elif isinstance(node, str):
escaped = node.replace('"', '\\"')
path.append(f'"{escaped}"')
else:
path.append(str(node))
return "".join(path)
ALL_JSON_PATH_PARTS = set(JSON_PATH_PART_TRANSFORMS)

View file

@ -1,3 +1,5 @@
# ruff: noqa: F401
from sqlglot.optimizer.optimizer import RULES, optimize
from sqlglot.optimizer.scope import (
Scope,

View file

@ -10,11 +10,13 @@ if t.TYPE_CHECKING:
@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.Identifier: ...
def normalize_identifiers(expression: str, dialect: DialectType = None) -> exp.Identifier:
...
def normalize_identifiers(expression, dialect=None):

View file

@ -8,10 +8,10 @@ from sqlglot.schema import ensure_schema
# Sentinel value that means an outer query selecting ALL columns
SELECT_ALL = object()
# Selection to use if selection list is empty
DEFAULT_SELECTION = lambda is_agg: alias(
exp.Max(this=exp.Literal.number(1)) if is_agg else "1", "_"
)
def default_selection(is_agg: bool) -> exp.Alias:
return alias(exp.Max(this=exp.Literal.number(1)) if is_agg else "1", "_")
def pushdown_projections(expression, schema=None, remove_unused_selections=True):
@ -129,7 +129,7 @@ def _remove_unused_selections(scope, parent_selections, schema, alias_count):
# If there are no remaining selections, just select a single constant
if not new_selections:
new_selections.append(DEFAULT_SELECTION(is_agg))
new_selections.append(default_selection(is_agg))
scope.expression.select(*new_selections, append=False, copy=False)

View file

@ -104,7 +104,6 @@ def simplify(
if root:
expression.replace(node)
return node
expression = while_changing(expression, _simplify)
@ -174,16 +173,20 @@ def simplify_not(expression):
if isinstance(this, exp.Paren):
condition = this.unnest()
if isinstance(condition, exp.And):
return exp.or_(
exp.not_(condition.left, copy=False),
exp.not_(condition.right, copy=False),
copy=False,
return exp.paren(
exp.or_(
exp.not_(condition.left, copy=False),
exp.not_(condition.right, copy=False),
copy=False,
)
)
if isinstance(condition, exp.Or):
return exp.and_(
exp.not_(condition.left, copy=False),
exp.not_(condition.right, copy=False),
copy=False,
return exp.paren(
exp.and_(
exp.not_(condition.left, copy=False),
exp.not_(condition.right, copy=False),
copy=False,
)
)
if is_null(condition):
return exp.null()
@ -490,7 +493,7 @@ def simplify_equality(expression: exp.Expression) -> exp.Expression:
if isinstance(expression, COMPARISONS):
l, r = expression.left, expression.right
if not l.__class__ in INVERSE_OPS:
if l.__class__ not in INVERSE_OPS:
return expression
if r.is_number:
@ -714,8 +717,7 @@ def simplify_concat(expression):
"""Reduces all groups that contain string literals by concatenating them."""
if not isinstance(expression, CONCATS) or (
# We can't reduce a CONCAT_WS call if we don't statically know the separator
isinstance(expression, exp.ConcatWs)
and not expression.expressions[0].is_string
isinstance(expression, exp.ConcatWs) and not expression.expressions[0].is_string
):
return expression

View file

@ -60,6 +60,19 @@ def parse_logarithm(args: t.List, dialect: Dialect) -> exp.Func:
return (exp.Ln if dialect.parser_class.LOG_DEFAULTS_TO_LN else exp.Log)(this=this)
def parse_extract_json_with_path(expr_type: t.Type[E]) -> t.Callable[[t.List, Dialect], E]:
def _parser(args: t.List, dialect: Dialect) -> E:
expression = expr_type(
this=seq_get(args, 0), expression=dialect.to_json_path(seq_get(args, 1))
)
if len(args) > 2 and expr_type is exp.JSONExtract:
expression.set("expressions", args[2:])
return expression
return _parser
class _Parser(type):
def __new__(cls, clsname, bases, attrs):
klass = super().__new__(cls, clsname, bases, attrs)
@ -102,6 +115,9 @@ class Parser(metaclass=_Parser):
to=exp.DataType(this=exp.DataType.Type.TEXT),
),
"GLOB": lambda args: exp.Glob(this=seq_get(args, 1), expression=seq_get(args, 0)),
"JSON_EXTRACT": parse_extract_json_with_path(exp.JSONExtract),
"JSON_EXTRACT_SCALAR": parse_extract_json_with_path(exp.JSONExtractScalar),
"JSON_EXTRACT_PATH_TEXT": parse_extract_json_with_path(exp.JSONExtractScalar),
"LIKE": parse_like,
"LOG": parse_logarithm,
"TIME_TO_TIME_STR": lambda args: exp.Cast(
@ -175,6 +191,7 @@ class Parser(metaclass=_Parser):
TokenType.NCHAR,
TokenType.VARCHAR,
TokenType.NVARCHAR,
TokenType.BPCHAR,
TokenType.TEXT,
TokenType.MEDIUMTEXT,
TokenType.LONGTEXT,
@ -295,6 +312,7 @@ class Parser(metaclass=_Parser):
TokenType.ASC,
TokenType.AUTO_INCREMENT,
TokenType.BEGIN,
TokenType.BPCHAR,
TokenType.CACHE,
TokenType.CASE,
TokenType.COLLATE,
@ -531,12 +549,12 @@ class Parser(metaclass=_Parser):
TokenType.ARROW: lambda self, this, path: self.expression(
exp.JSONExtract,
this=this,
expression=path,
expression=self.dialect.to_json_path(path),
),
TokenType.DARROW: lambda self, this, path: self.expression(
exp.JSONExtractScalar,
this=this,
expression=path,
expression=self.dialect.to_json_path(path),
),
TokenType.HASH_ARROW: lambda self, this, path: self.expression(
exp.JSONBExtract,
@ -1334,7 +1352,9 @@ class Parser(metaclass=_Parser):
exp.Drop,
comments=start.comments,
exists=exists or self._parse_exists(),
this=self._parse_table(schema=True),
this=self._parse_table(
schema=True, is_db_reference=self._prev.token_type == TokenType.SCHEMA
),
kind=kind,
temporary=temporary,
materialized=materialized,
@ -1422,7 +1442,9 @@ class Parser(metaclass=_Parser):
elif create_token.token_type == TokenType.INDEX:
this = self._parse_index(index=self._parse_id_var())
elif create_token.token_type in self.DB_CREATABLES:
table_parts = self._parse_table_parts(schema=True)
table_parts = self._parse_table_parts(
schema=True, is_db_reference=create_token.token_type == TokenType.SCHEMA
)
# exp.Properties.Location.POST_NAME
self._match(TokenType.COMMA)
@ -2499,11 +2521,11 @@ class Parser(metaclass=_Parser):
elif self._match_text_seq("ALL", "ROWS", "PER", "MATCH"):
text = "ALL ROWS PER MATCH"
if self._match_text_seq("SHOW", "EMPTY", "MATCHES"):
text += f" SHOW EMPTY MATCHES"
text += " SHOW EMPTY MATCHES"
elif self._match_text_seq("OMIT", "EMPTY", "MATCHES"):
text += f" OMIT EMPTY MATCHES"
text += " OMIT EMPTY MATCHES"
elif self._match_text_seq("WITH", "UNMATCHED", "ROWS"):
text += f" WITH UNMATCHED ROWS"
text += " WITH UNMATCHED ROWS"
rows = exp.var(text)
else:
rows = None
@ -2511,9 +2533,9 @@ class Parser(metaclass=_Parser):
if self._match_text_seq("AFTER", "MATCH", "SKIP"):
text = "AFTER MATCH SKIP"
if self._match_text_seq("PAST", "LAST", "ROW"):
text += f" PAST LAST ROW"
text += " PAST LAST ROW"
elif self._match_text_seq("TO", "NEXT", "ROW"):
text += f" TO NEXT ROW"
text += " TO NEXT ROW"
elif self._match_text_seq("TO", "FIRST"):
text += f" TO FIRST {self._advance_any().text}" # type: ignore
elif self._match_text_seq("TO", "LAST"):
@ -2772,7 +2794,7 @@ class Parser(metaclass=_Parser):
or self._parse_placeholder()
)
def _parse_table_parts(self, schema: bool = False) -> exp.Table:
def _parse_table_parts(self, schema: bool = False, is_db_reference: bool = False) -> exp.Table:
catalog = None
db = None
table: t.Optional[exp.Expression | str] = self._parse_table_part(schema=schema)
@ -2788,8 +2810,15 @@ class Parser(metaclass=_Parser):
db = table
table = self._parse_table_part(schema=schema) or ""
if not table:
if is_db_reference:
catalog = db
db = table
table = None
if not table and not is_db_reference:
self.raise_error(f"Expected table name but got {self._curr}")
if not db and is_db_reference:
self.raise_error(f"Expected database name but got {self._curr}")
return self.expression(
exp.Table, this=table, db=db, catalog=catalog, pivots=self._parse_pivots()
@ -2801,6 +2830,7 @@ class Parser(metaclass=_Parser):
joins: bool = False,
alias_tokens: t.Optional[t.Collection[TokenType]] = None,
parse_bracket: bool = False,
is_db_reference: bool = False,
) -> t.Optional[exp.Expression]:
lateral = self._parse_lateral()
if lateral:
@ -2823,7 +2853,11 @@ class Parser(metaclass=_Parser):
bracket = parse_bracket and self._parse_bracket(None)
bracket = self.expression(exp.Table, this=bracket) if bracket else None
this = t.cast(
exp.Expression, bracket or self._parse_bracket(self._parse_table_parts(schema=schema))
exp.Expression,
bracket
or self._parse_bracket(
self._parse_table_parts(schema=schema, is_db_reference=is_db_reference)
),
)
if schema:
@ -3650,7 +3684,6 @@ class Parser(metaclass=_Parser):
identifier = allow_identifiers and self._parse_id_var(
any_token=False, tokens=(TokenType.VAR,)
)
if identifier:
tokens = self.dialect.tokenize(identifier.name)
@ -3818,12 +3851,14 @@ class Parser(metaclass=_Parser):
return self.expression(exp.AtTimeZone, this=this, zone=self._parse_unary())
def _parse_column(self) -> t.Optional[exp.Expression]:
this = self._parse_column_reference()
return self._parse_column_ops(this) if this else self._parse_bracket(this)
def _parse_column_reference(self) -> t.Optional[exp.Expression]:
this = self._parse_field()
if isinstance(this, exp.Identifier):
this = self.expression(exp.Column, this=this)
elif not this:
return self._parse_bracket(this)
return self._parse_column_ops(this)
return this
def _parse_column_ops(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
this = self._parse_bracket(this)
@ -3837,13 +3872,7 @@ class Parser(metaclass=_Parser):
if not field:
self.raise_error("Expected type")
elif op and self._curr:
self._advance()
value = self._prev.text
field = (
exp.Literal.number(value)
if self._prev.token_type == TokenType.NUMBER
else exp.Literal.string(value)
)
field = self._parse_column_reference()
else:
field = self._parse_field(anonymous_func=True, any_token=True)
@ -4375,7 +4404,10 @@ class Parser(metaclass=_Parser):
options[kind] = action
return self.expression(
exp.ForeignKey, expressions=expressions, reference=reference, **options # type: ignore
exp.ForeignKey,
expressions=expressions,
reference=reference,
**options, # type: ignore
)
def _parse_primary_key_part(self) -> t.Optional[exp.Expression]:
@ -4692,10 +4724,12 @@ class Parser(metaclass=_Parser):
return None
@t.overload
def _parse_json_object(self, agg: Lit[False]) -> exp.JSONObject: ...
def _parse_json_object(self, agg: Lit[False]) -> exp.JSONObject:
...
@t.overload
def _parse_json_object(self, agg: Lit[True]) -> exp.JSONObjectAgg: ...
def _parse_json_object(self, agg: Lit[True]) -> exp.JSONObjectAgg:
...
def _parse_json_object(self, agg=False):
star = self._parse_star()
@ -4937,6 +4971,13 @@ class Parser(metaclass=_Parser):
# (https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/img_text/first_value.html)
# and Snowflake chose to do the same for familiarity
# https://docs.snowflake.com/en/sql-reference/functions/first_value.html#usage-notes
if isinstance(this, exp.AggFunc):
ignore_respect = this.find(exp.IgnoreNulls, exp.RespectNulls)
if ignore_respect and ignore_respect is not this:
ignore_respect.replace(ignore_respect.this)
this = self.expression(ignore_respect.__class__, this=this)
this = self._parse_respect_or_ignore_nulls(this)
# bigquery select from window x AS (partition by ...)
@ -5732,12 +5773,14 @@ class Parser(metaclass=_Parser):
return True
@t.overload
def _replace_columns_with_dots(self, this: exp.Expression) -> exp.Expression: ...
def _replace_columns_with_dots(self, this: exp.Expression) -> exp.Expression:
...
@t.overload
def _replace_columns_with_dots(
self, this: t.Optional[exp.Expression]
) -> t.Optional[exp.Expression]: ...
) -> t.Optional[exp.Expression]:
...
def _replace_columns_with_dots(self, this):
if isinstance(this, exp.Dot):

View file

@ -125,6 +125,7 @@ class TokenType(AutoName):
NCHAR = auto()
VARCHAR = auto()
NVARCHAR = auto()
BPCHAR = auto()
TEXT = auto()
MEDIUMTEXT = auto()
LONGTEXT = auto()
@ -801,6 +802,7 @@ class Tokenizer(metaclass=_Tokenizer):
"VARCHAR2": TokenType.VARCHAR,
"NVARCHAR": TokenType.NVARCHAR,
"NVARCHAR2": TokenType.NVARCHAR,
"BPCHAR": TokenType.BPCHAR,
"STR": TokenType.TEXT,
"STRING": TokenType.TEXT,
"TEXT": TokenType.TEXT,
@ -1141,7 +1143,7 @@ class Tokenizer(metaclass=_Tokenizer):
self._comments.append(self._text[comment_start_size : -comment_end_size + 1])
self._advance(comment_end_size - 1)
else:
while not self._end and not self.WHITE_SPACE.get(self._peek) is TokenType.BREAK:
while not self._end and self.WHITE_SPACE.get(self._peek) is not TokenType.BREAK:
self._advance(alnum=True)
self._comments.append(self._text[comment_start_size:])
@ -1259,7 +1261,7 @@ class Tokenizer(metaclass=_Tokenizer):
if base:
try:
int(text, base)
except:
except Exception:
raise TokenError(
f"Numeric string contains invalid characters from {self._line}:{self._start}"
)

View file

@ -485,8 +485,8 @@ def preprocess(
expression_type = type(expression)
expression = transforms[0](expression)
for t in transforms[1:]:
expression = t(expression)
for transform in transforms[1:]:
expression = transform(expression)
_sql_handler = getattr(self, expression.key + "_sql", None)
if _sql_handler:

View file

@ -528,7 +528,7 @@ class TestFunctions(unittest.TestCase):
col = SF.first(SF.col("cola"))
self.assertEqual("FIRST(cola)", col.sql())
ignore_nulls = SF.first("cola", True)
self.assertEqual("FIRST(cola, TRUE)", ignore_nulls.sql())
self.assertEqual("FIRST(cola) IGNORE NULLS", ignore_nulls.sql())
def test_grouping_id(self):
col_str = SF.grouping_id("cola", "colb")
@ -562,7 +562,7 @@ class TestFunctions(unittest.TestCase):
col = SF.last(SF.col("cola"))
self.assertEqual("LAST(cola)", col.sql())
ignore_nulls = SF.last("cola", True)
self.assertEqual("LAST(cola, TRUE)", ignore_nulls.sql())
self.assertEqual("LAST(cola) IGNORE NULLS", ignore_nulls.sql())
def test_monotonically_increasing_id(self):
col = SF.monotonically_increasing_id()
@ -713,8 +713,10 @@ class TestFunctions(unittest.TestCase):
self.assertEqual("NTH_VALUE(cola, 3)", col.sql())
col_no_offset = SF.nth_value("cola")
self.assertEqual("NTH_VALUE(cola)", col_no_offset.sql())
with self.assertRaises(NotImplementedError):
SF.nth_value("cola", ignoreNulls=True)
self.assertEqual(
"NTH_VALUE(cola) IGNORE NULLS", SF.nth_value("cola", ignoreNulls=True).sql()
)
def test_ntile(self):
col = SF.ntile(2)

View file

@ -18,6 +18,64 @@ class TestBigQuery(Validator):
maxDiff = None
def test_bigquery(self):
self.validate_all(
"SELECT SUM(x IGNORE NULLS) AS x",
read={
"bigquery": "SELECT SUM(x IGNORE NULLS) AS x",
"duckdb": "SELECT SUM(x IGNORE NULLS) AS x",
"postgres": "SELECT SUM(x) IGNORE NULLS AS x",
"spark": "SELECT SUM(x) IGNORE NULLS AS x",
"snowflake": "SELECT SUM(x) IGNORE NULLS AS x",
},
write={
"bigquery": "SELECT SUM(x IGNORE NULLS) AS x",
"duckdb": "SELECT SUM(x IGNORE NULLS) AS x",
"postgres": "SELECT SUM(x) IGNORE NULLS AS x",
"spark": "SELECT SUM(x) IGNORE NULLS AS x",
"snowflake": "SELECT SUM(x) IGNORE NULLS AS x",
},
)
self.validate_all(
"SELECT SUM(x RESPECT NULLS) AS x",
read={
"bigquery": "SELECT SUM(x RESPECT NULLS) AS x",
"duckdb": "SELECT SUM(x RESPECT NULLS) AS x",
"postgres": "SELECT SUM(x) RESPECT NULLS AS x",
"spark": "SELECT SUM(x) RESPECT NULLS AS x",
"snowflake": "SELECT SUM(x) RESPECT NULLS AS x",
},
write={
"bigquery": "SELECT SUM(x RESPECT NULLS) AS x",
"duckdb": "SELECT SUM(x RESPECT NULLS) AS x",
"postgres": "SELECT SUM(x) RESPECT NULLS AS x",
"spark": "SELECT SUM(x) RESPECT NULLS AS x",
"snowflake": "SELECT SUM(x) RESPECT NULLS AS x",
},
)
self.validate_all(
"SELECT PERCENTILE_CONT(x, 0.5 RESPECT NULLS) OVER ()",
write={
"duckdb": "SELECT QUANTILE_CONT(x, 0.5 RESPECT NULLS) OVER ()",
"spark": "SELECT PERCENTILE_CONT(x, 0.5) RESPECT NULLS OVER ()",
},
)
self.validate_all(
"SELECT ARRAY_AGG(DISTINCT x IGNORE NULLS ORDER BY a, b DESC LIMIT 10) AS x",
write={
"duckdb": "SELECT ARRAY_AGG(DISTINCT x ORDER BY a NULLS FIRST, b DESC LIMIT 10 IGNORE NULLS) AS x",
"spark": "SELECT COLLECT_LIST(DISTINCT x ORDER BY a, b DESC LIMIT 10) IGNORE NULLS AS x",
},
)
self.validate_all(
"SELECT ARRAY_AGG(DISTINCT x IGNORE NULLS ORDER BY a, b DESC LIMIT 1, 10) AS x",
write={
"duckdb": "SELECT ARRAY_AGG(DISTINCT x ORDER BY a NULLS FIRST, b DESC LIMIT 1, 10 IGNORE NULLS) AS x",
"spark": "SELECT COLLECT_LIST(DISTINCT x ORDER BY a, b DESC LIMIT 1, 10) IGNORE NULLS AS x",
},
)
self.validate_identity("SELECT COUNT(x RESPECT NULLS)")
self.validate_identity("SELECT LAST_VALUE(x IGNORE NULLS) OVER y AS x")
self.validate_identity(
"create or replace view test (tenant_id OPTIONS(description='Test description on table creation')) select 1 as tenant_id, 1 as customer_id;",
"CREATE OR REPLACE VIEW test (tenant_id OPTIONS (description='Test description on table creation')) AS SELECT 1 AS tenant_id, 1 AS customer_id",
@ -358,10 +416,25 @@ class TestBigQuery(Validator):
"SELECT TIMESTAMP_DIFF(TIMESTAMP_SECONDS(60), TIMESTAMP_SECONDS(0), minute)",
write={
"bigquery": "SELECT TIMESTAMP_DIFF(TIMESTAMP_SECONDS(60), TIMESTAMP_SECONDS(0), MINUTE)",
"databricks": "SELECT TIMESTAMPDIFF(MINUTE, CAST(FROM_UNIXTIME(0) AS TIMESTAMP), CAST(FROM_UNIXTIME(60) AS TIMESTAMP))",
"duckdb": "SELECT DATE_DIFF('MINUTE', TO_TIMESTAMP(0), TO_TIMESTAMP(60))",
"snowflake": "SELECT TIMESTAMPDIFF(MINUTE, TO_TIMESTAMP(0), TO_TIMESTAMP(60))",
},
)
self.validate_all(
"TIMESTAMP_DIFF(a, b, MONTH)",
read={
"bigquery": "TIMESTAMP_DIFF(a, b, month)",
"databricks": "TIMESTAMPDIFF(month, b, a)",
"mysql": "TIMESTAMPDIFF(month, b, a)",
},
write={
"databricks": "TIMESTAMPDIFF(MONTH, b, a)",
"mysql": "TIMESTAMPDIFF(MONTH, b, a)",
"snowflake": "TIMESTAMPDIFF(MONTH, b, a)",
},
)
self.validate_all(
"SELECT TIMESTAMP_MICROS(x)",
read={
@ -419,34 +492,42 @@ class TestBigQuery(Validator):
"snowflake": "CREATE OR REPLACE TABLE a.b.c CLONE a.b.d",
},
)
self.validate_all(
"SELECT DATETIME_DIFF('2023-01-01T00:00:00', '2023-01-01T05:00:00', MILLISECOND)",
write={
"bigquery": "SELECT DATETIME_DIFF('2023-01-01T00:00:00', '2023-01-01T05:00:00', MILLISECOND)",
"databricks": "SELECT TIMESTAMPDIFF(MILLISECOND, '2023-01-01T05:00:00', '2023-01-01T00:00:00')",
},
),
self.validate_all(
"SELECT DATETIME_ADD('2023-01-01T00:00:00', INTERVAL 1 MILLISECOND)",
write={
"bigquery": "SELECT DATETIME_ADD('2023-01-01T00:00:00', INTERVAL 1 MILLISECOND)",
"databricks": "SELECT TIMESTAMPADD(MILLISECOND, 1, '2023-01-01T00:00:00')",
},
),
self.validate_all(
"SELECT DATETIME_SUB('2023-01-01T00:00:00', INTERVAL 1 MILLISECOND)",
write={
"bigquery": "SELECT DATETIME_SUB('2023-01-01T00:00:00', INTERVAL 1 MILLISECOND)",
"databricks": "SELECT TIMESTAMPADD(MILLISECOND, 1 * -1, '2023-01-01T00:00:00')",
},
),
self.validate_all(
"SELECT DATETIME_TRUNC('2023-01-01T01:01:01', HOUR)",
write={
"bigquery": "SELECT DATETIME_TRUNC('2023-01-01T01:01:01', HOUR)",
"databricks": "SELECT DATE_TRUNC('HOUR', '2023-01-01T01:01:01')",
},
),
(
self.validate_all(
"SELECT DATETIME_DIFF('2023-01-01T00:00:00', '2023-01-01T05:00:00', MILLISECOND)",
write={
"bigquery": "SELECT DATETIME_DIFF('2023-01-01T00:00:00', '2023-01-01T05:00:00', MILLISECOND)",
"databricks": "SELECT TIMESTAMPDIFF(MILLISECOND, '2023-01-01T05:00:00', '2023-01-01T00:00:00')",
},
),
)
(
self.validate_all(
"SELECT DATETIME_ADD('2023-01-01T00:00:00', INTERVAL 1 MILLISECOND)",
write={
"bigquery": "SELECT DATETIME_ADD('2023-01-01T00:00:00', INTERVAL 1 MILLISECOND)",
"databricks": "SELECT TIMESTAMPADD(MILLISECOND, 1, '2023-01-01T00:00:00')",
},
),
)
(
self.validate_all(
"SELECT DATETIME_SUB('2023-01-01T00:00:00', INTERVAL 1 MILLISECOND)",
write={
"bigquery": "SELECT DATETIME_SUB('2023-01-01T00:00:00', INTERVAL 1 MILLISECOND)",
"databricks": "SELECT TIMESTAMPADD(MILLISECOND, 1 * -1, '2023-01-01T00:00:00')",
},
),
)
(
self.validate_all(
"SELECT DATETIME_TRUNC('2023-01-01T01:01:01', HOUR)",
write={
"bigquery": "SELECT DATETIME_TRUNC('2023-01-01T01:01:01', HOUR)",
"databricks": "SELECT DATE_TRUNC('HOUR', '2023-01-01T01:01:01')",
},
),
)
self.validate_all("LEAST(x, y)", read={"sqlite": "MIN(x, y)"})
self.validate_all("CAST(x AS CHAR)", write={"bigquery": "CAST(x AS STRING)"})
self.validate_all("CAST(x AS NCHAR)", write={"bigquery": "CAST(x AS STRING)"})

View file

@ -74,6 +74,10 @@ class TestClickhouse(Validator):
self.validate_identity("CAST(x AS DATETIME)")
self.validate_identity("CAST(x as MEDIUMINT)", "CAST(x AS Int32)")
self.validate_identity("SELECT arrayJoin([1, 2, 3] AS src) AS dst, 'Hello', src")
self.validate_identity("""SELECT JSONExtractString('{"x": {"y": 1}}', 'x', 'y')""")
self.validate_identity(
"""SELECT JSONExtractString('{"a": "hello", "b": [-100, 200.0, 300]}', 'a')"""
)
self.validate_identity(
"ATTACH DATABASE DEFAULT ENGINE = ORDINARY", check_command_warning=True
)

View file

@ -378,6 +378,31 @@ class TestDialect(Validator):
read={"postgres": "INET '127.0.0.1/32'"},
)
def test_ddl(self):
self.validate_all(
"CREATE TABLE a LIKE b",
write={
"": "CREATE TABLE a LIKE b",
"bigquery": "CREATE TABLE a LIKE b",
"clickhouse": "CREATE TABLE a AS b",
"databricks": "CREATE TABLE a LIKE b",
"doris": "CREATE TABLE a LIKE b",
"drill": "CREATE TABLE a AS SELECT * FROM b LIMIT 0",
"duckdb": "CREATE TABLE a AS SELECT * FROM b LIMIT 0",
"hive": "CREATE TABLE a LIKE b",
"mysql": "CREATE TABLE a LIKE b",
"oracle": "CREATE TABLE a LIKE b",
"postgres": "CREATE TABLE a (LIKE b)",
"presto": "CREATE TABLE a (LIKE b)",
"redshift": "CREATE TABLE a (LIKE b)",
"snowflake": "CREATE TABLE a LIKE b",
"spark": "CREATE TABLE a LIKE b",
"sqlite": "CREATE TABLE a AS SELECT * FROM b LIMIT 0",
"trino": "CREATE TABLE a (LIKE b)",
"tsql": "SELECT TOP 0 * INTO a FROM b AS temp",
},
)
def test_heredoc_strings(self):
for dialect in ("clickhouse", "postgres", "redshift"):
# Invalid matching tag
@ -1097,61 +1122,173 @@ class TestDialect(Validator):
def test_json(self):
self.validate_all(
"JSON_EXTRACT(x, 'y')",
"""JSON_EXTRACT(x, '$["a b"]')""",
write={
"": """JSON_EXTRACT(x, '$["a b"]')""",
"bigquery": """JSON_EXTRACT(x, '$[\\'a b\\']')""",
"clickhouse": "JSONExtractString(x, 'a b')",
"duckdb": """x -> '$."a b"'""",
"mysql": """JSON_EXTRACT(x, '$."a b"')""",
"postgres": "JSON_EXTRACT_PATH(x, 'a b')",
"presto": """JSON_EXTRACT(x, '$["a b"]')""",
"redshift": "JSON_EXTRACT_PATH_TEXT(x, 'a b')",
"snowflake": """GET_PATH(x, '["a b"]')""",
"spark": """GET_JSON_OBJECT(x, '$[\\'a b\\']')""",
"sqlite": """x -> '$."a b"'""",
"trino": """JSON_EXTRACT(x, '$["a b"]')""",
"tsql": """ISNULL(JSON_QUERY(x, '$."a b"'), JSON_VALUE(x, '$."a b"'))""",
},
)
self.validate_all(
"JSON_EXTRACT(x, '$.y')",
read={
"mysql": "JSON_EXTRACT(x, 'y')",
"bigquery": "JSON_EXTRACT(x, '$.y')",
"duckdb": "x -> 'y'",
"doris": "x -> '$.y'",
"mysql": "JSON_EXTRACT(x, '$.y')",
"postgres": "x->'y'",
"presto": "JSON_EXTRACT(x, 'y')",
"starrocks": "x -> 'y'",
"doris": "x -> 'y'",
"presto": "JSON_EXTRACT(x, '$.y')",
"snowflake": "GET_PATH(x, 'y')",
"sqlite": "x -> '$.y'",
"starrocks": "x -> '$.y'",
},
write={
"mysql": "JSON_EXTRACT(x, 'y')",
"oracle": "JSON_EXTRACT(x, 'y')",
"postgres": "x -> 'y'",
"presto": "JSON_EXTRACT(x, 'y')",
"starrocks": "x -> 'y'",
"doris": "x -> 'y'",
"bigquery": "JSON_EXTRACT(x, '$.y')",
"clickhouse": "JSONExtractString(x, 'y')",
"doris": "x -> '$.y'",
"duckdb": "x -> '$.y'",
"mysql": "JSON_EXTRACT(x, '$.y')",
"oracle": "JSON_EXTRACT(x, '$.y')",
"postgres": "JSON_EXTRACT_PATH(x, 'y')",
"presto": "JSON_EXTRACT(x, '$.y')",
"snowflake": "GET_PATH(x, 'y')",
"spark": "GET_JSON_OBJECT(x, '$.y')",
"sqlite": "x -> '$.y'",
"starrocks": "x -> '$.y'",
"tsql": "ISNULL(JSON_QUERY(x, '$.y'), JSON_VALUE(x, '$.y'))",
},
)
self.validate_all(
"JSON_EXTRACT_SCALAR(x, 'y')",
"JSON_EXTRACT_SCALAR(x, '$.y')",
read={
"bigquery": "JSON_EXTRACT_SCALAR(x, '$.y')",
"clickhouse": "JSONExtractString(x, 'y')",
"duckdb": "x ->> 'y'",
"postgres": "x ->> 'y'",
"presto": "JSON_EXTRACT_SCALAR(x, 'y')",
"presto": "JSON_EXTRACT_SCALAR(x, '$.y')",
"redshift": "JSON_EXTRACT_PATH_TEXT(x, 'y')",
"spark": "GET_JSON_OBJECT(x, '$.y')",
"snowflake": "JSON_EXTRACT_PATH_TEXT(x, 'y')",
"sqlite": "x ->> '$.y'",
},
write={
"postgres": "x ->> 'y'",
"presto": "JSON_EXTRACT_SCALAR(x, 'y')",
"bigquery": "JSON_EXTRACT_SCALAR(x, '$.y')",
"clickhouse": "JSONExtractString(x, 'y')",
"duckdb": "x ->> '$.y'",
"postgres": "JSON_EXTRACT_PATH_TEXT(x, 'y')",
"presto": "JSON_EXTRACT_SCALAR(x, '$.y')",
"redshift": "JSON_EXTRACT_PATH_TEXT(x, 'y')",
"snowflake": "JSON_EXTRACT_PATH_TEXT(x, 'y')",
"spark": "GET_JSON_OBJECT(x, '$.y')",
"sqlite": "x ->> '$.y'",
"tsql": "ISNULL(JSON_QUERY(x, '$.y'), JSON_VALUE(x, '$.y'))",
},
)
self.validate_all(
"JSON_EXTRACT_SCALAR(stream_data, '$.data.results')",
"JSON_EXTRACT(x, '$.y[0].z')",
read={
"hive": "GET_JSON_OBJECT(stream_data, '$.data.results')",
"mysql": "stream_data ->> '$.data.results'",
"bigquery": "JSON_EXTRACT(x, '$.y[0].z')",
"duckdb": "x -> '$.y[0].z'",
"doris": "x -> '$.y[0].z'",
"mysql": "JSON_EXTRACT(x, '$.y[0].z')",
"presto": "JSON_EXTRACT(x, '$.y[0].z')",
"snowflake": "GET_PATH(x, 'y[0].z')",
"sqlite": "x -> '$.y[0].z'",
"starrocks": "x -> '$.y[0].z'",
},
write={
"hive": "GET_JSON_OBJECT(stream_data, '$.data.results')",
"mysql": "stream_data ->> '$.data.results'",
"bigquery": "JSON_EXTRACT(x, '$.y[0].z')",
"clickhouse": "JSONExtractString(x, 'y', 1, 'z')",
"doris": "x -> '$.y[0].z'",
"duckdb": "x -> '$.y[0].z'",
"mysql": "JSON_EXTRACT(x, '$.y[0].z')",
"oracle": "JSON_EXTRACT(x, '$.y[0].z')",
"postgres": "JSON_EXTRACT_PATH(x, 'y', '0', 'z')",
"presto": "JSON_EXTRACT(x, '$.y[0].z')",
"redshift": "JSON_EXTRACT_PATH_TEXT(x, 'y', '0', 'z')",
"snowflake": "GET_PATH(x, 'y[0].z')",
"spark": "GET_JSON_OBJECT(x, '$.y[0].z')",
"sqlite": "x -> '$.y[0].z'",
"starrocks": "x -> '$.y[0].z'",
"tsql": "ISNULL(JSON_QUERY(x, '$.y[0].z'), JSON_VALUE(x, '$.y[0].z'))",
},
)
self.validate_all(
"JSONB_EXTRACT(x, 'y')",
"JSON_EXTRACT_SCALAR(x, '$.y[0].z')",
read={
"postgres": "x#>'y'",
"bigquery": "JSON_EXTRACT_SCALAR(x, '$.y[0].z')",
"clickhouse": "JSONExtractString(x, 'y', 1, 'z')",
"duckdb": "x ->> '$.y[0].z'",
"presto": "JSON_EXTRACT_SCALAR(x, '$.y[0].z')",
"snowflake": "JSON_EXTRACT_PATH_TEXT(x, 'y[0].z')",
"spark": 'GET_JSON_OBJECT(x, "$.y[0].z")',
"sqlite": "x ->> '$.y[0].z'",
},
write={
"postgres": "x #> 'y'",
"bigquery": "JSON_EXTRACT_SCALAR(x, '$.y[0].z')",
"clickhouse": "JSONExtractString(x, 'y', 1, 'z')",
"duckdb": "x ->> '$.y[0].z'",
"postgres": "JSON_EXTRACT_PATH_TEXT(x, 'y', '0', 'z')",
"presto": "JSON_EXTRACT_SCALAR(x, '$.y[0].z')",
"redshift": "JSON_EXTRACT_PATH_TEXT(x, 'y', '0', 'z')",
"snowflake": "JSON_EXTRACT_PATH_TEXT(x, 'y[0].z')",
"spark": "GET_JSON_OBJECT(x, '$.y[0].z')",
"sqlite": "x ->> '$.y[0].z'",
"tsql": "ISNULL(JSON_QUERY(x, '$.y[0].z'), JSON_VALUE(x, '$.y[0].z'))",
},
)
self.validate_all(
"JSONB_EXTRACT_SCALAR(x, 'y')",
read={
"postgres": "x#>>'y'",
},
"JSON_EXTRACT(x, '$.y[*]')",
write={
"postgres": "x #>> 'y'",
"bigquery": UnsupportedError,
"clickhouse": UnsupportedError,
"duckdb": "x -> '$.y[*]'",
"mysql": "JSON_EXTRACT(x, '$.y[*]')",
"postgres": UnsupportedError,
"presto": "JSON_EXTRACT(x, '$.y[*]')",
"redshift": UnsupportedError,
"snowflake": UnsupportedError,
"spark": "GET_JSON_OBJECT(x, '$.y[*]')",
"sqlite": UnsupportedError,
"tsql": UnsupportedError,
},
)
self.validate_all(
"JSON_EXTRACT(x, '$.y[*]')",
write={
"bigquery": "JSON_EXTRACT(x, '$.y')",
"clickhouse": "JSONExtractString(x, 'y')",
"postgres": "JSON_EXTRACT_PATH(x, 'y')",
"redshift": "JSON_EXTRACT_PATH_TEXT(x, 'y')",
"snowflake": "GET_PATH(x, 'y')",
"sqlite": "x -> '$.y'",
"tsql": "ISNULL(JSON_QUERY(x, '$.y'), JSON_VALUE(x, '$.y'))",
},
)
self.validate_all(
"JSON_EXTRACT(x, '$.y.*')",
write={
"bigquery": UnsupportedError,
"clickhouse": UnsupportedError,
"duckdb": "x -> '$.y.*'",
"mysql": "JSON_EXTRACT(x, '$.y.*')",
"postgres": UnsupportedError,
"presto": "JSON_EXTRACT(x, '$.y.*')",
"redshift": UnsupportedError,
"snowflake": UnsupportedError,
"spark": UnsupportedError,
"sqlite": UnsupportedError,
"tsql": UnsupportedError,
},
)

View file

@ -41,6 +41,7 @@ class TestDuckDB(Validator):
)
self.validate_identity("SELECT 1 WHERE x > $1")
self.validate_identity("SELECT 1 WHERE x > $name")
self.validate_identity("""SELECT '{"x": 1}' -> c FROM t""")
self.assertEqual(
parse_one("select * from t limit (select 5)").sql(dialect="duckdb"),
@ -89,18 +90,26 @@ class TestDuckDB(Validator):
},
)
self.validate_identity("""SELECT '{"duck": [1, 2, 3]}' -> '$.duck[#-1]'""")
self.validate_all(
"""SELECT JSON_EXTRACT('{"duck": [1, 2, 3]}', '/duck/0')""",
write={
"": """SELECT JSON_EXTRACT('{"duck": [1, 2, 3]}', '/duck/0')""",
"duckdb": """SELECT '{"duck": [1, 2, 3]}' -> '/duck/0'""",
},
)
self.validate_all(
"""SELECT JSON('{"fruit":"banana"}') -> 'fruit'""",
write={
"duckdb": """SELECT JSON('{"fruit":"banana"}') -> 'fruit'""",
"snowflake": """SELECT PARSE_JSON('{"fruit":"banana"}')['fruit']""",
"duckdb": """SELECT JSON('{"fruit":"banana"}') -> '$.fruit'""",
"snowflake": """SELECT GET_PATH(PARSE_JSON('{"fruit":"banana"}'), 'fruit')""",
},
)
self.validate_all(
"""SELECT JSON('{"fruit": {"foo": "banana"}}') -> 'fruit' -> 'foo'""",
write={
"duckdb": """SELECT JSON('{"fruit": {"foo": "banana"}}') -> 'fruit' -> 'foo'""",
"snowflake": """SELECT PARSE_JSON('{"fruit": {"foo": "banana"}}')['fruit']['foo']""",
"duckdb": """SELECT JSON('{"fruit": {"foo": "banana"}}') -> '$.fruit' -> '$.foo'""",
"snowflake": """SELECT GET_PATH(GET_PATH(PARSE_JSON('{"fruit": {"foo": "banana"}}'), 'fruit'), 'foo')""",
},
)
self.validate_all(
@ -199,6 +208,27 @@ class TestDuckDB(Validator):
self.validate_identity("FROM x SELECT x UNION SELECT 1", "SELECT x FROM x UNION SELECT 1")
self.validate_identity("FROM (FROM tbl)", "SELECT * FROM (SELECT * FROM tbl)")
self.validate_identity("FROM tbl", "SELECT * FROM tbl")
self.validate_identity("x -> '$.family'")
self.validate_identity(
"""SELECT '{"foo": [1, 2, 3]}' -> 'foo' -> 0""",
"""SELECT '{"foo": [1, 2, 3]}' -> '$.foo' -> '$[0]'""",
)
self.validate_identity(
"JSON_EXTRACT(x, '$.family')",
"x -> '$.family'",
)
self.validate_identity(
"JSON_EXTRACT_PATH(x, '$.family')",
"x -> '$.family'",
)
self.validate_identity(
"JSON_EXTRACT_STRING(x, '$.family')",
"x ->> '$.family'",
)
self.validate_identity(
"JSON_EXTRACT_PATH_TEXT(x, '$.family')",
"x ->> '$.family'",
)
self.validate_identity(
"ATTACH DATABASE ':memory:' AS new_database", check_command_warning=True
)

Some files were not shown because too many files have changed in this diff Show more