1
0
Fork 0

Merging upstream version 25.34.0.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-13 21:58:22 +01:00
parent f19abab1f0
commit 589d8e33dc
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
66 changed files with 53358 additions and 52814 deletions

View file

@ -1,6 +1,41 @@
Changelog
=========
## [v25.33.0] - 2024-12-04
### :boom: BREAKING CHANGES
- due to [`07fa69d`](https://github.com/tobymao/sqlglot/commit/07fa69dcb8970167ba0c55fff39175ab856ea9f3) - Make TIMESTAMP map to Type.TIMESTAMPTZ *(PR [#4451](https://github.com/tobymao/sqlglot/pull/4451) by [@VaggelisD](https://github.com/VaggelisD))*:
Make TIMESTAMP map to Type.TIMESTAMPTZ (#4451)
- due to [`63d8f41`](https://github.com/tobymao/sqlglot/commit/63d8f41794b2e9d22f87d0a8fbfbd83125889ca2) - treat NEXT as a func keyword, parse NEXT VALUE FOR in tsql, oracle *(PR [#4467](https://github.com/tobymao/sqlglot/pull/4467) by [@georgesittas](https://github.com/georgesittas))*:
treat NEXT as a func keyword, parse NEXT VALUE FOR in tsql, oracle (#4467)
### :sparkles: New Features
- [`3945acc`](https://github.com/tobymao/sqlglot/commit/3945acc4a0dfd58147de929c9a2c71734d8f1ade) - allow tables to be preserved in replace_table *(PR [#4468](https://github.com/tobymao/sqlglot/pull/4468) by [@georgesittas](https://github.com/georgesittas))*
- [`a9dca8d`](https://github.com/tobymao/sqlglot/commit/a9dca8dd1b523efd703003694d4389f9af9d1a12) - **postgres**: Support generated columns *(PR [#4472](https://github.com/tobymao/sqlglot/pull/4472) by [@VaggelisD](https://github.com/VaggelisD))*
- :arrow_lower_right: *addresses issue [#4463](https://github.com/tobymao/sqlglot/issues/4463) opened by [@AKST](https://github.com/AKST)*
### :bug: Bug Fixes
- [`380dad2`](https://github.com/tobymao/sqlglot/commit/380dad2f5826caa820a69442c42805c7b3c23ada) - **bigquery**: Rename CONTAINS_SUBSTRING to CONTAINS_SUBSTR *(PR [#4457](https://github.com/tobymao/sqlglot/pull/4457) by [@VaggelisD](https://github.com/VaggelisD))*
- :arrow_lower_right: *fixes issue [#4456](https://github.com/tobymao/sqlglot/issues/4456) opened by [@romanhaa](https://github.com/romanhaa)*
- [`ca5023d`](https://github.com/tobymao/sqlglot/commit/ca5023db5ea2a2ece804f6e389640e0bd4987598) - **presto**: Remove parentheses from CURRENT_USER *(PR [#4459](https://github.com/tobymao/sqlglot/pull/4459) by [@MikeWallis42](https://github.com/MikeWallis42))*
- :arrow_lower_right: *fixes issue [#4458](https://github.com/tobymao/sqlglot/issues/4458) opened by [@MikeWallis42](https://github.com/MikeWallis42)*
- [`07fa69d`](https://github.com/tobymao/sqlglot/commit/07fa69dcb8970167ba0c55fff39175ab856ea9f3) - **spark**: Make TIMESTAMP map to Type.TIMESTAMPTZ *(PR [#4451](https://github.com/tobymao/sqlglot/pull/4451) by [@VaggelisD](https://github.com/VaggelisD))*
- :arrow_lower_right: *fixes issue [#4442](https://github.com/tobymao/sqlglot/issues/4442) opened by [@dor-bernstein](https://github.com/dor-bernstein)*
- [`63d8f41`](https://github.com/tobymao/sqlglot/commit/63d8f41794b2e9d22f87d0a8fbfbd83125889ca2) - **parser**: treat NEXT as a func keyword, parse NEXT VALUE FOR in tsql, oracle *(PR [#4467](https://github.com/tobymao/sqlglot/pull/4467) by [@georgesittas](https://github.com/georgesittas))*
- :arrow_lower_right: *fixes issue [#4466](https://github.com/tobymao/sqlglot/issues/4466) opened by [@Harmuth94](https://github.com/Harmuth94)*
## [v25.32.1] - 2024-11-27
### :bug: Bug Fixes
- [`954d8fd`](https://github.com/tobymao/sqlglot/commit/954d8fd12740071e0951d1df3a405a4b9634868d) - parse DEFAULT in VALUES clause into a Var *(PR [#4448](https://github.com/tobymao/sqlglot/pull/4448) by [@georgesittas](https://github.com/georgesittas))*
- :arrow_lower_right: *fixes issue [#4446](https://github.com/tobymao/sqlglot/issues/4446) opened by [@ddh-5230](https://github.com/ddh-5230)*
- [`73afd0f`](https://github.com/tobymao/sqlglot/commit/73afd0f435b7e7ccde831ee311c9a76c14797fdc) - **bigquery**: Make JSONPathTokenizer more lenient for new standards *(PR [#4447](https://github.com/tobymao/sqlglot/pull/4447) by [@VaggelisD](https://github.com/VaggelisD))*
- :arrow_lower_right: *fixes issue [#4441](https://github.com/tobymao/sqlglot/issues/4441) opened by [@patricksurry](https://github.com/patricksurry)*
## [v25.32.0] - 2024-11-22
### :boom: BREAKING CHANGES
- due to [`0eed45c`](https://github.com/tobymao/sqlglot/commit/0eed45cce82681bfbafc8bfb78eb2a1bce86ae53) - Add support for ATTACH/DETACH statements *(PR [#4419](https://github.com/tobymao/sqlglot/pull/4419) by [@VaggelisD](https://github.com/VaggelisD))*:
@ -5375,3 +5410,5 @@ Changelog
[v25.31.3]: https://github.com/tobymao/sqlglot/compare/v25.31.2...v25.31.3
[v25.31.4]: https://github.com/tobymao/sqlglot/compare/v25.31.3...v25.31.4
[v25.32.0]: https://github.com/tobymao/sqlglot/compare/v25.31.4...v25.32.0
[v25.32.1]: https://github.com/tobymao/sqlglot/compare/v25.32.0...v25.32.1
[v25.33.0]: https://github.com/tobymao/sqlglot/compare/v25.32.1...v25.33.0

File diff suppressed because one or more lines are too long

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;25.32.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">25</span><span class="p">,</span> <span class="mi">32</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;25.33.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">25</span><span class="p">,</span> <span class="mi">33</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;25.32.0&#39;</span>
<span class="default_value">&#39;25.33.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">(25, 32, 0)</span>
<span class="default_value">(25, 33, 0)</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

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

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

@ -2077,6 +2077,7 @@
<dd id="Python.ON_CONDITION_EMPTY_BEFORE_ERROR" class="variable"><a href="../dialects/dialect.html#Dialect.ON_CONDITION_EMPTY_BEFORE_ERROR">ON_CONDITION_EMPTY_BEFORE_ERROR</a></dd>
<dd id="Python.ARRAY_AGG_INCLUDES_NULLS" class="variable"><a href="../dialects/dialect.html#Dialect.ARRAY_AGG_INCLUDES_NULLS">ARRAY_AGG_INCLUDES_NULLS</a></dd>
<dd id="Python.PROMOTE_TO_INFERRED_DATETIME_TYPE" class="variable"><a href="../dialects/dialect.html#Dialect.PROMOTE_TO_INFERRED_DATETIME_TYPE">PROMOTE_TO_INFERRED_DATETIME_TYPE</a></dd>
<dd id="Python.SUPPORTS_VALUES_DEFAULT" class="variable"><a href="../dialects/dialect.html#Dialect.SUPPORTS_VALUES_DEFAULT">SUPPORTS_VALUES_DEFAULT</a></dd>
<dd id="Python.REGEXP_EXTRACT_DEFAULT_GROUP" class="variable"><a href="../dialects/dialect.html#Dialect.REGEXP_EXTRACT_DEFAULT_GROUP">REGEXP_EXTRACT_DEFAULT_GROUP</a></dd>
<dd id="Python.SET_OP_DISTINCT_BY_DEFAULT" class="variable"><a href="../dialects/dialect.html#Dialect.SET_OP_DISTINCT_BY_DEFAULT">SET_OP_DISTINCT_BY_DEFAULT</a></dd>
<dd id="Python.CREATABLE_KIND_MAPPING" class="variable"><a href="../dialects/dialect.html#Dialect.CREATABLE_KIND_MAPPING">CREATABLE_KIND_MAPPING</a></dd>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -117,6 +117,9 @@
<li>
<a class="function" href="#first">first</a>
</li>
<li>
<a class="function" href="#to_bool">to_bool</a>
</li>
<li>
<a class="function" href="#merge_ranges">merge_ranges</a>
</li>
@ -622,83 +625,97 @@
</span><span id="L-456"><a href="#L-456"><span class="linenos">456</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-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><span id="L-459"><a href="#L-459"><span class="linenos">459</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-460"><a href="#L-460"><span class="linenos">460</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-461"><a href="#L-461"><span class="linenos">461</span></a><span class="sd"> Merges a sequence of ranges, represented as tuples (low, high) whose values</span>
</span><span id="L-462"><a href="#L-462"><span class="linenos">462</span></a><span class="sd"> belong to some totally-ordered set.</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="sd"> Example:</span>
</span><span id="L-465"><a href="#L-465"><span class="linenos">465</span></a><span class="sd"> &gt;&gt;&gt; merge_ranges([(1, 3), (2, 6)])</span>
</span><span id="L-466"><a href="#L-466"><span class="linenos">466</span></a><span class="sd"> [(1, 6)]</span>
</span><span id="L-467"><a href="#L-467"><span class="linenos">467</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-468"><a href="#L-468"><span class="linenos">468</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-469"><a href="#L-469"><span class="linenos">469</span></a> <span class="k">return</span> <span class="p">[]</span>
</span><span id="L-470"><a href="#L-470"><span class="linenos">470</span></a>
</span><span id="L-471"><a href="#L-471"><span class="linenos">471</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-459"><a href="#L-459"><span class="linenos">459</span></a><span class="k">def</span> <span class="nf">to_bool</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">Optional</span><span class="p">[</span><span class="nb">str</span> <span class="o">|</span> <span class="nb">bool</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="nb">str</span> <span class="o">|</span> <span class="nb">bool</span><span class="p">]:</span>
</span><span id="L-460"><a href="#L-460"><span class="linenos">460</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="nb">bool</span><span class="p">)</span> <span class="ow">or</span> <span class="n">value</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="L-461"><a href="#L-461"><span class="linenos">461</span></a> <span class="k">return</span> <span class="n">value</span>
</span><span id="L-462"><a href="#L-462"><span class="linenos">462</span></a>
</span><span id="L-463"><a href="#L-463"><span class="linenos">463</span></a> <span class="c1"># Coerce the value to boolean if it matches to the truthy/falsy values below</span>
</span><span id="L-464"><a href="#L-464"><span class="linenos">464</span></a> <span class="n">value_lower</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span><span id="L-465"><a href="#L-465"><span class="linenos">465</span></a> <span class="k">if</span> <span class="n">value_lower</span> <span class="ow">in</span> <span class="p">(</span><span class="s2">&quot;true&quot;</span><span class="p">,</span> <span class="s2">&quot;1&quot;</span><span class="p">):</span>
</span><span id="L-466"><a href="#L-466"><span class="linenos">466</span></a> <span class="k">return</span> <span class="kc">True</span>
</span><span id="L-467"><a href="#L-467"><span class="linenos">467</span></a> <span class="k">if</span> <span class="n">value_lower</span> <span class="ow">in</span> <span class="p">(</span><span class="s2">&quot;false&quot;</span><span class="p">,</span> <span class="s2">&quot;0&quot;</span><span class="p">):</span>
</span><span id="L-468"><a href="#L-468"><span class="linenos">468</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><span id="L-470"><a href="#L-470"><span class="linenos">470</span></a> <span class="k">return</span> <span class="n">value</span>
</span><span id="L-471"><a href="#L-471"><span class="linenos">471</span></a>
</span><span id="L-472"><a href="#L-472"><span class="linenos">472</span></a>
</span><span id="L-473"><a href="#L-473"><span class="linenos">473</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-474"><a href="#L-474"><span class="linenos">474</span></a>
</span><span id="L-475"><a href="#L-475"><span class="linenos">475</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-476"><a href="#L-476"><span class="linenos">476</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-473"><a href="#L-473"><span class="linenos">473</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-474"><a href="#L-474"><span class="linenos">474</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-475"><a href="#L-475"><span class="linenos">475</span></a><span class="sd"> Merges a sequence of ranges, represented as tuples (low, high) whose values</span>
</span><span id="L-476"><a href="#L-476"><span class="linenos">476</span></a><span class="sd"> belong to some totally-ordered set.</span>
</span><span id="L-477"><a href="#L-477"><span class="linenos">477</span></a>
</span><span id="L-478"><a href="#L-478"><span class="linenos">478</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-479"><a href="#L-479"><span class="linenos">479</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-480"><a href="#L-480"><span class="linenos">480</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-481"><a href="#L-481"><span class="linenos">481</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-482"><a href="#L-482"><span class="linenos">482</span></a>
</span><span id="L-483"><a href="#L-483"><span class="linenos">483</span></a> <span class="k">return</span> <span class="n">merged</span>
</span><span id="L-478"><a href="#L-478"><span class="linenos">478</span></a><span class="sd"> Example:</span>
</span><span id="L-479"><a href="#L-479"><span class="linenos">479</span></a><span class="sd"> &gt;&gt;&gt; merge_ranges([(1, 3), (2, 6)])</span>
</span><span id="L-480"><a href="#L-480"><span class="linenos">480</span></a><span class="sd"> [(1, 6)]</span>
</span><span id="L-481"><a href="#L-481"><span class="linenos">481</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-482"><a href="#L-482"><span class="linenos">482</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-483"><a href="#L-483"><span class="linenos">483</span></a> <span class="k">return</span> <span class="p">[]</span>
</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><span id="L-486"><a href="#L-486"><span class="linenos">486</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-487"><a href="#L-487"><span class="linenos">487</span></a> <span class="k">try</span><span class="p">:</span>
</span><span id="L-488"><a href="#L-488"><span class="linenos">488</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-489"><a href="#L-489"><span class="linenos">489</span></a> <span class="k">return</span> <span class="kc">True</span>
</span><span id="L-490"><a href="#L-490"><span class="linenos">490</span></a> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
</span><span id="L-491"><a href="#L-491"><span class="linenos">491</span></a> <span class="k">return</span> <span class="kc">False</span>
</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><span id="L-494"><a href="#L-494"><span class="linenos">494</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-495"><a href="#L-495"><span class="linenos">495</span></a> <span class="k">try</span><span class="p">:</span>
</span><span id="L-496"><a href="#L-496"><span class="linenos">496</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-497"><a href="#L-497"><span class="linenos">497</span></a> <span class="k">return</span> <span class="kc">True</span>
</span><span id="L-498"><a href="#L-498"><span class="linenos">498</span></a> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
</span><span id="L-499"><a href="#L-499"><span class="linenos">499</span></a> <span class="k">return</span> <span class="kc">False</span>
</span><span id="L-500"><a href="#L-500"><span class="linenos">500</span></a>
</span><span id="L-501"><a href="#L-501"><span class="linenos">501</span></a>
</span><span id="L-502"><a href="#L-502"><span class="linenos">502</span></a><span class="c1"># Interval units that operate on date components</span>
</span><span id="L-503"><a href="#L-503"><span class="linenos">503</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-504"><a href="#L-504"><span class="linenos">504</span></a>
</span><span id="L-505"><a href="#L-505"><span class="linenos">505</span></a>
</span><span id="L-506"><a href="#L-506"><span class="linenos">506</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-507"><a href="#L-507"><span class="linenos">507</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-508"><a href="#L-508"><span class="linenos">508</span></a>
</span><span id="L-509"><a href="#L-509"><span class="linenos">509</span></a>
</span><span id="L-510"><a href="#L-510"><span class="linenos">510</span></a><span class="n">K</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;K&quot;</span><span class="p">)</span>
</span><span id="L-511"><a href="#L-511"><span class="linenos">511</span></a><span class="n">V</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;V&quot;</span><span class="p">)</span>
</span><span id="L-512"><a href="#L-512"><span class="linenos">512</span></a>
</span><span id="L-513"><a href="#L-513"><span class="linenos">513</span></a>
</span><span id="L-514"><a href="#L-514"><span class="linenos">514</span></a><span class="k">class</span> <span class="nc">SingleValuedMapping</span><span class="p">(</span><span class="n">t</span><span class="o">.</span><span class="n">Mapping</span><span class="p">[</span><span class="n">K</span><span class="p">,</span> <span class="n">V</span><span class="p">]):</span>
</span><span id="L-515"><a href="#L-515"><span class="linenos">515</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-516"><a href="#L-516"><span class="linenos">516</span></a><span class="sd"> Mapping where all keys return the same value.</span>
</span><span id="L-517"><a href="#L-517"><span class="linenos">517</span></a>
</span><span id="L-518"><a href="#L-518"><span class="linenos">518</span></a><span class="sd"> This rigamarole is meant to avoid copying keys, which was originally intended</span>
</span><span id="L-519"><a href="#L-519"><span class="linenos">519</span></a><span class="sd"> as an optimization while qualifying columns for tables with lots of columns.</span>
</span><span id="L-520"><a href="#L-520"><span class="linenos">520</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-521"><a href="#L-521"><span class="linenos">521</span></a>
</span><span id="L-522"><a href="#L-522"><span class="linenos">522</span></a> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">keys</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Collection</span><span class="p">[</span><span class="n">K</span><span class="p">],</span> <span class="n">value</span><span class="p">:</span> <span class="n">V</span><span class="p">):</span>
</span><span id="L-523"><a href="#L-523"><span class="linenos">523</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_keys</span> <span class="o">=</span> <span class="n">keys</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">keys</span><span class="p">,</span> <span class="n">Set</span><span class="p">)</span> <span class="k">else</span> <span class="nb">set</span><span class="p">(</span><span class="n">keys</span><span class="p">)</span>
</span><span id="L-524"><a href="#L-524"><span class="linenos">524</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_value</span> <span class="o">=</span> <span class="n">value</span>
</span><span id="L-525"><a href="#L-525"><span class="linenos">525</span></a>
</span><span id="L-526"><a href="#L-526"><span class="linenos">526</span></a> <span class="k">def</span> <span class="fm">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">:</span> <span class="n">K</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">V</span><span class="p">:</span>
</span><span id="L-527"><a href="#L-527"><span class="linenos">527</span></a> <span class="k">if</span> <span class="n">key</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_keys</span><span class="p">:</span>
</span><span id="L-528"><a href="#L-528"><span class="linenos">528</span></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_value</span>
</span><span id="L-529"><a href="#L-529"><span class="linenos">529</span></a> <span class="k">raise</span> <span class="ne">KeyError</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
</span><span id="L-530"><a href="#L-530"><span class="linenos">530</span></a>
</span><span id="L-531"><a href="#L-531"><span class="linenos">531</span></a> <span class="k">def</span> <span class="fm">__len__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span><span id="L-532"><a href="#L-532"><span class="linenos">532</span></a> <span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_keys</span><span class="p">)</span>
</span><span id="L-533"><a href="#L-533"><span class="linenos">533</span></a>
</span><span id="L-534"><a href="#L-534"><span class="linenos">534</span></a> <span class="k">def</span> <span class="fm">__iter__</span><span class="p">(</span><span class="bp">self</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">K</span><span class="p">]:</span>
</span><span id="L-535"><a href="#L-535"><span class="linenos">535</span></a> <span class="k">return</span> <span class="nb">iter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_keys</span><span class="p">)</span>
</span><span id="L-485"><a href="#L-485"><span class="linenos">485</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-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">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-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">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-490"><a href="#L-490"><span class="linenos">490</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-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 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-493"><a href="#L-493"><span class="linenos">493</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-494"><a href="#L-494"><span class="linenos">494</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-495"><a href="#L-495"><span class="linenos">495</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-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">return</span> <span class="n">merged</span>
</span><span id="L-498"><a href="#L-498"><span class="linenos">498</span></a>
</span><span id="L-499"><a href="#L-499"><span class="linenos">499</span></a>
</span><span id="L-500"><a href="#L-500"><span class="linenos">500</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-501"><a href="#L-501"><span class="linenos">501</span></a> <span class="k">try</span><span class="p">:</span>
</span><span id="L-502"><a href="#L-502"><span class="linenos">502</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-503"><a href="#L-503"><span class="linenos">503</span></a> <span class="k">return</span> <span class="kc">True</span>
</span><span id="L-504"><a href="#L-504"><span class="linenos">504</span></a> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
</span><span id="L-505"><a href="#L-505"><span class="linenos">505</span></a> <span class="k">return</span> <span class="kc">False</span>
</span><span id="L-506"><a href="#L-506"><span class="linenos">506</span></a>
</span><span id="L-507"><a href="#L-507"><span class="linenos">507</span></a>
</span><span id="L-508"><a href="#L-508"><span class="linenos">508</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-509"><a href="#L-509"><span class="linenos">509</span></a> <span class="k">try</span><span class="p">:</span>
</span><span id="L-510"><a href="#L-510"><span class="linenos">510</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-511"><a href="#L-511"><span class="linenos">511</span></a> <span class="k">return</span> <span class="kc">True</span>
</span><span id="L-512"><a href="#L-512"><span class="linenos">512</span></a> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
</span><span id="L-513"><a href="#L-513"><span class="linenos">513</span></a> <span class="k">return</span> <span class="kc">False</span>
</span><span id="L-514"><a href="#L-514"><span class="linenos">514</span></a>
</span><span id="L-515"><a href="#L-515"><span class="linenos">515</span></a>
</span><span id="L-516"><a href="#L-516"><span class="linenos">516</span></a><span class="c1"># Interval units that operate on date components</span>
</span><span id="L-517"><a href="#L-517"><span class="linenos">517</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-518"><a href="#L-518"><span class="linenos">518</span></a>
</span><span id="L-519"><a href="#L-519"><span class="linenos">519</span></a>
</span><span id="L-520"><a href="#L-520"><span class="linenos">520</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-521"><a href="#L-521"><span class="linenos">521</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-522"><a href="#L-522"><span class="linenos">522</span></a>
</span><span id="L-523"><a href="#L-523"><span class="linenos">523</span></a>
</span><span id="L-524"><a href="#L-524"><span class="linenos">524</span></a><span class="n">K</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;K&quot;</span><span class="p">)</span>
</span><span id="L-525"><a href="#L-525"><span class="linenos">525</span></a><span class="n">V</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;V&quot;</span><span class="p">)</span>
</span><span id="L-526"><a href="#L-526"><span class="linenos">526</span></a>
</span><span id="L-527"><a href="#L-527"><span class="linenos">527</span></a>
</span><span id="L-528"><a href="#L-528"><span class="linenos">528</span></a><span class="k">class</span> <span class="nc">SingleValuedMapping</span><span class="p">(</span><span class="n">t</span><span class="o">.</span><span class="n">Mapping</span><span class="p">[</span><span class="n">K</span><span class="p">,</span> <span class="n">V</span><span class="p">]):</span>
</span><span id="L-529"><a href="#L-529"><span class="linenos">529</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-530"><a href="#L-530"><span class="linenos">530</span></a><span class="sd"> Mapping where all keys return the same value.</span>
</span><span id="L-531"><a href="#L-531"><span class="linenos">531</span></a>
</span><span id="L-532"><a href="#L-532"><span class="linenos">532</span></a><span class="sd"> This rigamarole is meant to avoid copying keys, which was originally intended</span>
</span><span id="L-533"><a href="#L-533"><span class="linenos">533</span></a><span class="sd"> as an optimization while qualifying columns for tables with lots of columns.</span>
</span><span id="L-534"><a href="#L-534"><span class="linenos">534</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-535"><a href="#L-535"><span class="linenos">535</span></a>
</span><span id="L-536"><a href="#L-536"><span class="linenos">536</span></a> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">keys</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Collection</span><span class="p">[</span><span class="n">K</span><span class="p">],</span> <span class="n">value</span><span class="p">:</span> <span class="n">V</span><span class="p">):</span>
</span><span id="L-537"><a href="#L-537"><span class="linenos">537</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_keys</span> <span class="o">=</span> <span class="n">keys</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">keys</span><span class="p">,</span> <span class="n">Set</span><span class="p">)</span> <span class="k">else</span> <span class="nb">set</span><span class="p">(</span><span class="n">keys</span><span class="p">)</span>
</span><span id="L-538"><a href="#L-538"><span class="linenos">538</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_value</span> <span class="o">=</span> <span class="n">value</span>
</span><span id="L-539"><a href="#L-539"><span class="linenos">539</span></a>
</span><span id="L-540"><a href="#L-540"><span class="linenos">540</span></a> <span class="k">def</span> <span class="fm">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">:</span> <span class="n">K</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">V</span><span class="p">:</span>
</span><span id="L-541"><a href="#L-541"><span class="linenos">541</span></a> <span class="k">if</span> <span class="n">key</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_keys</span><span class="p">:</span>
</span><span id="L-542"><a href="#L-542"><span class="linenos">542</span></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_value</span>
</span><span id="L-543"><a href="#L-543"><span class="linenos">543</span></a> <span class="k">raise</span> <span class="ne">KeyError</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
</span><span id="L-544"><a href="#L-544"><span class="linenos">544</span></a>
</span><span id="L-545"><a href="#L-545"><span class="linenos">545</span></a> <span class="k">def</span> <span class="fm">__len__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span><span id="L-546"><a href="#L-546"><span class="linenos">546</span></a> <span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_keys</span><span class="p">)</span>
</span><span id="L-547"><a href="#L-547"><span class="linenos">547</span></a>
</span><span id="L-548"><a href="#L-548"><span class="linenos">548</span></a> <span class="k">def</span> <span class="fm">__iter__</span><span class="p">(</span><span class="bp">self</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">K</span><span class="p">]:</span>
</span><span id="L-549"><a href="#L-549"><span class="linenos">549</span></a> <span class="k">return</span> <span class="nb">iter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_keys</span><span class="p">)</span>
</span></pre></div>
@ -1769,6 +1786,35 @@ type <code>str</code> and <code>bytes</code> are not regarded as iterables.</p>
</div>
</section>
<section id="to_bool">
<input id="to_bool-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">to_bool</span><span class="signature pdoc-code condensed">(<span class="param"><span class="n">value</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="nb">bool</span><span class="p">,</span> <span class="n">NoneType</span><span class="p">]</span></span><span class="return-annotation">) -> <span class="n">Union</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="nb">bool</span><span class="p">,</span> <span class="n">NoneType</span><span class="p">]</span>:</span></span>
<label class="view-source-button" for="to_bool-view-source"><span>View Source</span></label>
</div>
<a class="headerlink" href="#to_bool"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="to_bool-460"><a href="#to_bool-460"><span class="linenos">460</span></a><span class="k">def</span> <span class="nf">to_bool</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">Optional</span><span class="p">[</span><span class="nb">str</span> <span class="o">|</span> <span class="nb">bool</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="nb">str</span> <span class="o">|</span> <span class="nb">bool</span><span class="p">]:</span>
</span><span id="to_bool-461"><a href="#to_bool-461"><span class="linenos">461</span></a> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="nb">bool</span><span class="p">)</span> <span class="ow">or</span> <span class="n">value</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="to_bool-462"><a href="#to_bool-462"><span class="linenos">462</span></a> <span class="k">return</span> <span class="n">value</span>
</span><span id="to_bool-463"><a href="#to_bool-463"><span class="linenos">463</span></a>
</span><span id="to_bool-464"><a href="#to_bool-464"><span class="linenos">464</span></a> <span class="c1"># Coerce the value to boolean if it matches to the truthy/falsy values below</span>
</span><span id="to_bool-465"><a href="#to_bool-465"><span class="linenos">465</span></a> <span class="n">value_lower</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span><span id="to_bool-466"><a href="#to_bool-466"><span class="linenos">466</span></a> <span class="k">if</span> <span class="n">value_lower</span> <span class="ow">in</span> <span class="p">(</span><span class="s2">&quot;true&quot;</span><span class="p">,</span> <span class="s2">&quot;1&quot;</span><span class="p">):</span>
</span><span id="to_bool-467"><a href="#to_bool-467"><span class="linenos">467</span></a> <span class="k">return</span> <span class="kc">True</span>
</span><span id="to_bool-468"><a href="#to_bool-468"><span class="linenos">468</span></a> <span class="k">if</span> <span class="n">value_lower</span> <span class="ow">in</span> <span class="p">(</span><span class="s2">&quot;false&quot;</span><span class="p">,</span> <span class="s2">&quot;0&quot;</span><span class="p">):</span>
</span><span id="to_bool-469"><a href="#to_bool-469"><span class="linenos">469</span></a> <span class="k">return</span> <span class="kc">False</span>
</span><span id="to_bool-470"><a href="#to_bool-470"><span class="linenos">470</span></a>
</span><span id="to_bool-471"><a href="#to_bool-471"><span class="linenos">471</span></a> <span class="k">return</span> <span class="n">value</span>
</span></pre></div>
</section>
<section id="merge_ranges">
<input id="merge_ranges-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
@ -1781,31 +1827,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-460"><a href="#merge_ranges-460"><span class="linenos">460</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-461"><a href="#merge_ranges-461"><span class="linenos">461</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="merge_ranges-462"><a href="#merge_ranges-462"><span class="linenos">462</span></a><span class="sd"> Merges a sequence of ranges, represented as tuples (low, high) whose values</span>
</span><span id="merge_ranges-463"><a href="#merge_ranges-463"><span class="linenos">463</span></a><span class="sd"> belong to some totally-ordered set.</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="sd"> Example:</span>
</span><span id="merge_ranges-466"><a href="#merge_ranges-466"><span class="linenos">466</span></a><span class="sd"> &gt;&gt;&gt; merge_ranges([(1, 3), (2, 6)])</span>
</span><span id="merge_ranges-467"><a href="#merge_ranges-467"><span class="linenos">467</span></a><span class="sd"> [(1, 6)]</span>
</span><span id="merge_ranges-468"><a href="#merge_ranges-468"><span class="linenos">468</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="merge_ranges-469"><a href="#merge_ranges-469"><span class="linenos">469</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-470"><a href="#merge_ranges-470"><span class="linenos">470</span></a> <span class="k">return</span> <span class="p">[]</span>
</span><span id="merge_ranges-471"><a href="#merge_ranges-471"><span class="linenos">471</span></a>
</span><span id="merge_ranges-472"><a href="#merge_ranges-472"><span class="linenos">472</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-473"><a href="#merge_ranges-473"><span class="linenos">473</span></a>
</span><span id="merge_ranges-474"><a href="#merge_ranges-474"><span class="linenos">474</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-475"><a href="#merge_ranges-475"><span class="linenos">475</span></a>
</span><span id="merge_ranges-476"><a href="#merge_ranges-476"><span class="linenos">476</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-477"><a href="#merge_ranges-477"><span class="linenos">477</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>
<div class="pdoc-code codehilite"><pre><span></span><span id="merge_ranges-474"><a href="#merge_ranges-474"><span class="linenos">474</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-475"><a href="#merge_ranges-475"><span class="linenos">475</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="merge_ranges-476"><a href="#merge_ranges-476"><span class="linenos">476</span></a><span class="sd"> Merges a sequence of ranges, represented as tuples (low, high) whose values</span>
</span><span id="merge_ranges-477"><a href="#merge_ranges-477"><span class="linenos">477</span></a><span class="sd"> belong to some totally-ordered set.</span>
</span><span id="merge_ranges-478"><a href="#merge_ranges-478"><span class="linenos">478</span></a>
</span><span id="merge_ranges-479"><a href="#merge_ranges-479"><span class="linenos">479</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-480"><a href="#merge_ranges-480"><span class="linenos">480</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-481"><a href="#merge_ranges-481"><span class="linenos">481</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="merge_ranges-482"><a href="#merge_ranges-482"><span class="linenos">482</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-483"><a href="#merge_ranges-483"><span class="linenos">483</span></a>
</span><span id="merge_ranges-484"><a href="#merge_ranges-484"><span class="linenos">484</span></a> <span class="k">return</span> <span class="n">merged</span>
</span><span id="merge_ranges-479"><a href="#merge_ranges-479"><span class="linenos">479</span></a><span class="sd"> Example:</span>
</span><span id="merge_ranges-480"><a href="#merge_ranges-480"><span class="linenos">480</span></a><span class="sd"> &gt;&gt;&gt; merge_ranges([(1, 3), (2, 6)])</span>
</span><span id="merge_ranges-481"><a href="#merge_ranges-481"><span class="linenos">481</span></a><span class="sd"> [(1, 6)]</span>
</span><span id="merge_ranges-482"><a href="#merge_ranges-482"><span class="linenos">482</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="merge_ranges-483"><a href="#merge_ranges-483"><span class="linenos">483</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-484"><a href="#merge_ranges-484"><span class="linenos">484</span></a> <span class="k">return</span> <span class="p">[]</span>
</span><span id="merge_ranges-485"><a href="#merge_ranges-485"><span class="linenos">485</span></a>
</span><span id="merge_ranges-486"><a href="#merge_ranges-486"><span class="linenos">486</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-487"><a href="#merge_ranges-487"><span class="linenos">487</span></a>
</span><span id="merge_ranges-488"><a href="#merge_ranges-488"><span class="linenos">488</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-489"><a href="#merge_ranges-489"><span class="linenos">489</span></a>
</span><span id="merge_ranges-490"><a href="#merge_ranges-490"><span class="linenos">490</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-491"><a href="#merge_ranges-491"><span class="linenos">491</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-492"><a href="#merge_ranges-492"><span class="linenos">492</span></a>
</span><span id="merge_ranges-493"><a href="#merge_ranges-493"><span class="linenos">493</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-494"><a href="#merge_ranges-494"><span class="linenos">494</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-495"><a href="#merge_ranges-495"><span class="linenos">495</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="merge_ranges-496"><a href="#merge_ranges-496"><span class="linenos">496</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-497"><a href="#merge_ranges-497"><span class="linenos">497</span></a>
</span><span id="merge_ranges-498"><a href="#merge_ranges-498"><span class="linenos">498</span></a> <span class="k">return</span> <span class="n">merged</span>
</span></pre></div>
@ -1836,12 +1882,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-487"><a href="#is_iso_date-487"><span class="linenos">487</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-488"><a href="#is_iso_date-488"><span class="linenos">488</span></a> <span class="k">try</span><span class="p">:</span>
</span><span id="is_iso_date-489"><a href="#is_iso_date-489"><span class="linenos">489</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-490"><a href="#is_iso_date-490"><span class="linenos">490</span></a> <span class="k">return</span> <span class="kc">True</span>
</span><span id="is_iso_date-491"><a href="#is_iso_date-491"><span class="linenos">491</span></a> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
</span><span id="is_iso_date-492"><a href="#is_iso_date-492"><span class="linenos">492</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-501"><a href="#is_iso_date-501"><span class="linenos">501</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-502"><a href="#is_iso_date-502"><span class="linenos">502</span></a> <span class="k">try</span><span class="p">:</span>
</span><span id="is_iso_date-503"><a href="#is_iso_date-503"><span class="linenos">503</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-504"><a href="#is_iso_date-504"><span class="linenos">504</span></a> <span class="k">return</span> <span class="kc">True</span>
</span><span id="is_iso_date-505"><a href="#is_iso_date-505"><span class="linenos">505</span></a> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
</span><span id="is_iso_date-506"><a href="#is_iso_date-506"><span class="linenos">506</span></a> <span class="k">return</span> <span class="kc">False</span>
</span></pre></div>
@ -1859,12 +1905,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-495"><a href="#is_iso_datetime-495"><span class="linenos">495</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-496"><a href="#is_iso_datetime-496"><span class="linenos">496</span></a> <span class="k">try</span><span class="p">:</span>
</span><span id="is_iso_datetime-497"><a href="#is_iso_datetime-497"><span class="linenos">497</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-498"><a href="#is_iso_datetime-498"><span class="linenos">498</span></a> <span class="k">return</span> <span class="kc">True</span>
</span><span id="is_iso_datetime-499"><a href="#is_iso_datetime-499"><span class="linenos">499</span></a> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
</span><span id="is_iso_datetime-500"><a href="#is_iso_datetime-500"><span class="linenos">500</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-509"><a href="#is_iso_datetime-509"><span class="linenos">509</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-510"><a href="#is_iso_datetime-510"><span class="linenos">510</span></a> <span class="k">try</span><span class="p">:</span>
</span><span id="is_iso_datetime-511"><a href="#is_iso_datetime-511"><span class="linenos">511</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-512"><a href="#is_iso_datetime-512"><span class="linenos">512</span></a> <span class="k">return</span> <span class="kc">True</span>
</span><span id="is_iso_datetime-513"><a href="#is_iso_datetime-513"><span class="linenos">513</span></a> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
</span><span id="is_iso_datetime-514"><a href="#is_iso_datetime-514"><span class="linenos">514</span></a> <span class="k">return</span> <span class="kc">False</span>
</span></pre></div>
@ -1874,7 +1920,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;quarter&#39;, &#39;year&#39;, &#39;day&#39;, &#39;week&#39;, &#39;year_month&#39;, &#39;month&#39;}</span>
<span class="default_value">{&#39;quarter&#39;, &#39;day&#39;, &#39;year&#39;, &#39;year_month&#39;, &#39;month&#39;, &#39;week&#39;}</span>
</div>
@ -1894,8 +1940,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-507"><a href="#is_date_unit-507"><span class="linenos">507</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-508"><a href="#is_date_unit-508"><span class="linenos">508</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-521"><a href="#is_date_unit-521"><span class="linenos">521</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-522"><a href="#is_date_unit-522"><span class="linenos">522</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>
@ -1913,28 +1959,28 @@ belong to some totally-ordered set.</p>
</div>
<a class="headerlink" href="#SingleValuedMapping"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="SingleValuedMapping-515"><a href="#SingleValuedMapping-515"><span class="linenos">515</span></a><span class="k">class</span> <span class="nc">SingleValuedMapping</span><span class="p">(</span><span class="n">t</span><span class="o">.</span><span class="n">Mapping</span><span class="p">[</span><span class="n">K</span><span class="p">,</span> <span class="n">V</span><span class="p">]):</span>
</span><span id="SingleValuedMapping-516"><a href="#SingleValuedMapping-516"><span class="linenos">516</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="SingleValuedMapping-517"><a href="#SingleValuedMapping-517"><span class="linenos">517</span></a><span class="sd"> Mapping where all keys return the same value.</span>
</span><span id="SingleValuedMapping-518"><a href="#SingleValuedMapping-518"><span class="linenos">518</span></a>
</span><span id="SingleValuedMapping-519"><a href="#SingleValuedMapping-519"><span class="linenos">519</span></a><span class="sd"> This rigamarole is meant to avoid copying keys, which was originally intended</span>
</span><span id="SingleValuedMapping-520"><a href="#SingleValuedMapping-520"><span class="linenos">520</span></a><span class="sd"> as an optimization while qualifying columns for tables with lots of columns.</span>
</span><span id="SingleValuedMapping-521"><a href="#SingleValuedMapping-521"><span class="linenos">521</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="SingleValuedMapping-522"><a href="#SingleValuedMapping-522"><span class="linenos">522</span></a>
</span><span id="SingleValuedMapping-523"><a href="#SingleValuedMapping-523"><span class="linenos">523</span></a> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">keys</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Collection</span><span class="p">[</span><span class="n">K</span><span class="p">],</span> <span class="n">value</span><span class="p">:</span> <span class="n">V</span><span class="p">):</span>
</span><span id="SingleValuedMapping-524"><a href="#SingleValuedMapping-524"><span class="linenos">524</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_keys</span> <span class="o">=</span> <span class="n">keys</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">keys</span><span class="p">,</span> <span class="n">Set</span><span class="p">)</span> <span class="k">else</span> <span class="nb">set</span><span class="p">(</span><span class="n">keys</span><span class="p">)</span>
</span><span id="SingleValuedMapping-525"><a href="#SingleValuedMapping-525"><span class="linenos">525</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_value</span> <span class="o">=</span> <span class="n">value</span>
</span><span id="SingleValuedMapping-526"><a href="#SingleValuedMapping-526"><span class="linenos">526</span></a>
</span><span id="SingleValuedMapping-527"><a href="#SingleValuedMapping-527"><span class="linenos">527</span></a> <span class="k">def</span> <span class="fm">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">:</span> <span class="n">K</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">V</span><span class="p">:</span>
</span><span id="SingleValuedMapping-528"><a href="#SingleValuedMapping-528"><span class="linenos">528</span></a> <span class="k">if</span> <span class="n">key</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_keys</span><span class="p">:</span>
</span><span id="SingleValuedMapping-529"><a href="#SingleValuedMapping-529"><span class="linenos">529</span></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_value</span>
</span><span id="SingleValuedMapping-530"><a href="#SingleValuedMapping-530"><span class="linenos">530</span></a> <span class="k">raise</span> <span class="ne">KeyError</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
</span><span id="SingleValuedMapping-531"><a href="#SingleValuedMapping-531"><span class="linenos">531</span></a>
</span><span id="SingleValuedMapping-532"><a href="#SingleValuedMapping-532"><span class="linenos">532</span></a> <span class="k">def</span> <span class="fm">__len__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span><span id="SingleValuedMapping-533"><a href="#SingleValuedMapping-533"><span class="linenos">533</span></a> <span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_keys</span><span class="p">)</span>
</span><span id="SingleValuedMapping-534"><a href="#SingleValuedMapping-534"><span class="linenos">534</span></a>
</span><span id="SingleValuedMapping-535"><a href="#SingleValuedMapping-535"><span class="linenos">535</span></a> <span class="k">def</span> <span class="fm">__iter__</span><span class="p">(</span><span class="bp">self</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">K</span><span class="p">]:</span>
</span><span id="SingleValuedMapping-536"><a href="#SingleValuedMapping-536"><span class="linenos">536</span></a> <span class="k">return</span> <span class="nb">iter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_keys</span><span class="p">)</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="SingleValuedMapping-529"><a href="#SingleValuedMapping-529"><span class="linenos">529</span></a><span class="k">class</span> <span class="nc">SingleValuedMapping</span><span class="p">(</span><span class="n">t</span><span class="o">.</span><span class="n">Mapping</span><span class="p">[</span><span class="n">K</span><span class="p">,</span> <span class="n">V</span><span class="p">]):</span>
</span><span id="SingleValuedMapping-530"><a href="#SingleValuedMapping-530"><span class="linenos">530</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="SingleValuedMapping-531"><a href="#SingleValuedMapping-531"><span class="linenos">531</span></a><span class="sd"> Mapping where all keys return the same value.</span>
</span><span id="SingleValuedMapping-532"><a href="#SingleValuedMapping-532"><span class="linenos">532</span></a>
</span><span id="SingleValuedMapping-533"><a href="#SingleValuedMapping-533"><span class="linenos">533</span></a><span class="sd"> This rigamarole is meant to avoid copying keys, which was originally intended</span>
</span><span id="SingleValuedMapping-534"><a href="#SingleValuedMapping-534"><span class="linenos">534</span></a><span class="sd"> as an optimization while qualifying columns for tables with lots of columns.</span>
</span><span id="SingleValuedMapping-535"><a href="#SingleValuedMapping-535"><span class="linenos">535</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="SingleValuedMapping-536"><a href="#SingleValuedMapping-536"><span class="linenos">536</span></a>
</span><span id="SingleValuedMapping-537"><a href="#SingleValuedMapping-537"><span class="linenos">537</span></a> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">keys</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Collection</span><span class="p">[</span><span class="n">K</span><span class="p">],</span> <span class="n">value</span><span class="p">:</span> <span class="n">V</span><span class="p">):</span>
</span><span id="SingleValuedMapping-538"><a href="#SingleValuedMapping-538"><span class="linenos">538</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_keys</span> <span class="o">=</span> <span class="n">keys</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">keys</span><span class="p">,</span> <span class="n">Set</span><span class="p">)</span> <span class="k">else</span> <span class="nb">set</span><span class="p">(</span><span class="n">keys</span><span class="p">)</span>
</span><span id="SingleValuedMapping-539"><a href="#SingleValuedMapping-539"><span class="linenos">539</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_value</span> <span class="o">=</span> <span class="n">value</span>
</span><span id="SingleValuedMapping-540"><a href="#SingleValuedMapping-540"><span class="linenos">540</span></a>
</span><span id="SingleValuedMapping-541"><a href="#SingleValuedMapping-541"><span class="linenos">541</span></a> <span class="k">def</span> <span class="fm">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">:</span> <span class="n">K</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">V</span><span class="p">:</span>
</span><span id="SingleValuedMapping-542"><a href="#SingleValuedMapping-542"><span class="linenos">542</span></a> <span class="k">if</span> <span class="n">key</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_keys</span><span class="p">:</span>
</span><span id="SingleValuedMapping-543"><a href="#SingleValuedMapping-543"><span class="linenos">543</span></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_value</span>
</span><span id="SingleValuedMapping-544"><a href="#SingleValuedMapping-544"><span class="linenos">544</span></a> <span class="k">raise</span> <span class="ne">KeyError</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
</span><span id="SingleValuedMapping-545"><a href="#SingleValuedMapping-545"><span class="linenos">545</span></a>
</span><span id="SingleValuedMapping-546"><a href="#SingleValuedMapping-546"><span class="linenos">546</span></a> <span class="k">def</span> <span class="fm">__len__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span><span id="SingleValuedMapping-547"><a href="#SingleValuedMapping-547"><span class="linenos">547</span></a> <span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_keys</span><span class="p">)</span>
</span><span id="SingleValuedMapping-548"><a href="#SingleValuedMapping-548"><span class="linenos">548</span></a>
</span><span id="SingleValuedMapping-549"><a href="#SingleValuedMapping-549"><span class="linenos">549</span></a> <span class="k">def</span> <span class="fm">__iter__</span><span class="p">(</span><span class="bp">self</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">K</span><span class="p">]:</span>
</span><span id="SingleValuedMapping-550"><a href="#SingleValuedMapping-550"><span class="linenos">550</span></a> <span class="k">return</span> <span class="nb">iter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_keys</span><span class="p">)</span>
</span></pre></div>
@ -1955,9 +2001,9 @@ as an optimization while qualifying columns for tables with lots of columns.</p>
</div>
<a class="headerlink" href="#SingleValuedMapping.__init__"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="SingleValuedMapping.__init__-523"><a href="#SingleValuedMapping.__init__-523"><span class="linenos">523</span></a> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">keys</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Collection</span><span class="p">[</span><span class="n">K</span><span class="p">],</span> <span class="n">value</span><span class="p">:</span> <span class="n">V</span><span class="p">):</span>
</span><span id="SingleValuedMapping.__init__-524"><a href="#SingleValuedMapping.__init__-524"><span class="linenos">524</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_keys</span> <span class="o">=</span> <span class="n">keys</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">keys</span><span class="p">,</span> <span class="n">Set</span><span class="p">)</span> <span class="k">else</span> <span class="nb">set</span><span class="p">(</span><span class="n">keys</span><span class="p">)</span>
</span><span id="SingleValuedMapping.__init__-525"><a href="#SingleValuedMapping.__init__-525"><span class="linenos">525</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_value</span> <span class="o">=</span> <span class="n">value</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="SingleValuedMapping.__init__-537"><a href="#SingleValuedMapping.__init__-537"><span class="linenos">537</span></a> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">keys</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Collection</span><span class="p">[</span><span class="n">K</span><span class="p">],</span> <span class="n">value</span><span class="p">:</span> <span class="n">V</span><span class="p">):</span>
</span><span id="SingleValuedMapping.__init__-538"><a href="#SingleValuedMapping.__init__-538"><span class="linenos">538</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_keys</span> <span class="o">=</span> <span class="n">keys</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">keys</span><span class="p">,</span> <span class="n">Set</span><span class="p">)</span> <span class="k">else</span> <span class="nb">set</span><span class="p">(</span><span class="n">keys</span><span class="p">)</span>
</span><span id="SingleValuedMapping.__init__-539"><a href="#SingleValuedMapping.__init__-539"><span class="linenos">539</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_value</span> <span class="o">=</span> <span class="n">value</span>
</span></pre></div>

View file

@ -228,59 +228,85 @@
</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="k">return</span> <span class="n">node</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="c1"># We canonicalize the JSON path AST so that it always starts with a</span>
</span><span id="L-150"><a href="#L-150"><span class="linenos">150</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-151"><a href="#L-151"><span class="linenos">151</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-152"><a href="#L-152"><span class="linenos">152</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-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">while</span> <span class="n">_curr</span><span class="p">():</span>
</span><span id="L-155"><a href="#L-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">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-156"><a href="#L-156"><span class="linenos">156</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-149"><a href="#L-149"><span class="linenos">149</span></a> <span class="k">def</span> <span class="nf">_parse_var_text</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span><span id="L-150"><a href="#L-150"><span class="linenos">150</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-151"><a href="#L-151"><span class="linenos">151</span></a><span class="sd"> Consumes &amp; returns the text for a var. In BigQuery it&#39;s valid to have a key with spaces</span>
</span><span id="L-152"><a href="#L-152"><span class="linenos">152</span></a><span class="sd"> in it, e.g JSON_QUERY(..., &#39;$. a b c &#39;) should produce a single JSONPathKey(&#39; a b c &#39;).</span>
</span><span id="L-153"><a href="#L-153"><span class="linenos">153</span></a><span class="sd"> This is done by merging &quot;consecutive&quot; vars until a key separator is found (dot, colon etc)</span>
</span><span id="L-154"><a href="#L-154"><span class="linenos">154</span></a><span class="sd"> or the path string is exhausted.</span>
</span><span id="L-155"><a href="#L-155"><span class="linenos">155</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="L-156"><a href="#L-156"><span class="linenos">156</span></a> <span class="n">prev_index</span> <span class="o">=</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">2</span>
</span><span id="L-157"><a href="#L-157"><span class="linenos">157</span></a>
</span><span id="L-158"><a href="#L-158"><span class="linenos">158</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-159"><a href="#L-159"><span class="linenos">159</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-160"><a href="#L-160"><span class="linenos">160</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-161"><a href="#L-161"><span class="linenos">161</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-162"><a href="#L-162"><span class="linenos">162</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-163"><a href="#L-163"><span class="linenos">163</span></a> <span class="n">value</span> <span class="o">=</span> <span class="kc">None</span>
</span><span id="L-164"><a href="#L-164"><span class="linenos">164</span></a>
</span><span id="L-165"><a href="#L-165"><span class="linenos">165</span></a> <span class="k">if</span> <span class="n">recursive</span><span class="p">:</span>
</span><span id="L-166"><a href="#L-166"><span class="linenos">166</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-167"><a href="#L-167"><span class="linenos">167</span></a> <span class="k">elif</span> <span class="n">value</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">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-169"><a href="#L-169"><span class="linenos">169</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-170"><a href="#L-170"><span class="linenos">170</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-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">L_BRACKET</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">_parse_bracket</span><span class="p">())</span>
</span><span id="L-173"><a href="#L-173"><span class="linenos">173</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-174"><a href="#L-174"><span class="linenos">174</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-175"><a href="#L-175"><span class="linenos">175</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-176"><a href="#L-176"><span class="linenos">176</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-177"><a href="#L-177"><span class="linenos">177</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-178"><a href="#L-178"><span class="linenos">178</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-158"><a href="#L-158"><span class="linenos">158</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">VAR</span><span class="p">):</span>
</span><span id="L-159"><a href="#L-159"><span class="linenos">159</span></a> <span class="k">pass</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="n">start</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">if</span> <span class="n">prev_index</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="k">else</span> <span class="n">tokens</span><span class="p">[</span><span class="n">prev_index</span><span class="p">]</span><span class="o">.</span><span class="n">end</span> <span class="o">+</span> <span class="mi">1</span>
</span><span id="L-162"><a href="#L-162"><span class="linenos">162</span></a>
</span><span id="L-163"><a href="#L-163"><span class="linenos">163</span></a> <span class="k">if</span> <span class="n">i</span> <span class="o">&gt;=</span> <span class="nb">len</span><span class="p">(</span><span class="n">tokens</span><span class="p">):</span>
</span><span id="L-164"><a href="#L-164"><span class="linenos">164</span></a> <span class="c1"># This key is the last token for the path, so it&#39;s text is the remaining path</span>
</span><span id="L-165"><a href="#L-165"><span class="linenos">165</span></a> <span class="n">text</span> <span class="o">=</span> <span class="n">path</span><span class="p">[</span><span class="n">start</span><span class="p">:]</span>
</span><span id="L-166"><a href="#L-166"><span class="linenos">166</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-167"><a href="#L-167"><span class="linenos">167</span></a> <span class="n">text</span> <span class="o">=</span> <span class="n">path</span><span class="p">[</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">start</span><span class="p">]</span>
</span><span id="L-168"><a href="#L-168"><span class="linenos">168</span></a>
</span><span id="L-169"><a href="#L-169"><span class="linenos">169</span></a> <span class="k">return</span> <span class="n">text</span>
</span><span id="L-170"><a href="#L-170"><span class="linenos">170</span></a>
</span><span id="L-171"><a href="#L-171"><span class="linenos">171</span></a> <span class="c1"># We canonicalize the JSON path AST so that it always starts with a</span>
</span><span id="L-172"><a href="#L-172"><span class="linenos">172</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-173"><a href="#L-173"><span class="linenos">173</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-174"><a href="#L-174"><span class="linenos">174</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-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">while</span> <span class="n">_curr</span><span class="p">():</span>
</span><span id="L-177"><a href="#L-177"><span class="linenos">177</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-178"><a href="#L-178"><span class="linenos">178</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-179"><a href="#L-179"><span class="linenos">179</span></a>
</span><span id="L-180"><a href="#L-180"><span class="linenos">180</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-181"><a href="#L-181"><span class="linenos">181</span></a>
</span><span id="L-182"><a href="#L-182"><span class="linenos">182</span></a>
</span><span id="L-183"><a href="#L-183"><span class="linenos">183</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-184"><a href="#L-184"><span class="linenos">184</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-185"><a href="#L-185"><span class="linenos">185</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-186"><a href="#L-186"><span class="linenos">186</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-187"><a href="#L-187"><span class="linenos">187</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-188"><a href="#L-188"><span class="linenos">188</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-189"><a href="#L-189"><span class="linenos">189</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-190"><a href="#L-190"><span class="linenos">190</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-191"><a href="#L-191"><span class="linenos">191</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-192"><a href="#L-192"><span class="linenos">192</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-193"><a href="#L-193"><span class="linenos">193</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-194"><a href="#L-194"><span class="linenos">194</span></a> <span class="p">),</span>
</span><span id="L-195"><a href="#L-195"><span class="linenos">195</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-196"><a href="#L-196"><span class="linenos">196</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-197"><a href="#L-197"><span class="linenos">197</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-198"><a href="#L-198"><span class="linenos">198</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-199"><a href="#L-199"><span class="linenos">199</span></a><span class="p">}</span>
</span><span id="L-200"><a href="#L-200"><span class="linenos">200</span></a>
</span><span id="L-201"><a href="#L-201"><span class="linenos">201</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><span id="L-180"><a href="#L-180"><span class="linenos">180</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><span id="L-181"><a href="#L-181"><span class="linenos">181</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">_parse_var_text</span><span class="p">()</span>
</span><span id="L-182"><a href="#L-182"><span class="linenos">182</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">IDENTIFIER</span><span class="p">):</span>
</span><span id="L-183"><a href="#L-183"><span class="linenos">183</span></a> <span class="n">value</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-184"><a href="#L-184"><span class="linenos">184</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-185"><a href="#L-185"><span class="linenos">185</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-186"><a href="#L-186"><span class="linenos">186</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-187"><a href="#L-187"><span class="linenos">187</span></a> <span class="n">value</span> <span class="o">=</span> <span class="kc">None</span>
</span><span id="L-188"><a href="#L-188"><span class="linenos">188</span></a>
</span><span id="L-189"><a href="#L-189"><span class="linenos">189</span></a> <span class="k">if</span> <span class="n">recursive</span><span class="p">:</span>
</span><span id="L-190"><a href="#L-190"><span class="linenos">190</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-191"><a href="#L-191"><span class="linenos">191</span></a> <span class="k">elif</span> <span class="n">value</span><span class="p">:</span>
</span><span id="L-192"><a href="#L-192"><span class="linenos">192</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-193"><a href="#L-193"><span class="linenos">193</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-194"><a href="#L-194"><span class="linenos">194</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-195"><a href="#L-195"><span class="linenos">195</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-196"><a href="#L-196"><span class="linenos">196</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-197"><a href="#L-197"><span class="linenos">197</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-198"><a href="#L-198"><span class="linenos">198</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">_parse_var_text</span><span class="p">()))</span>
</span><span id="L-199"><a href="#L-199"><span class="linenos">199</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">IDENTIFIER</span><span class="p">):</span>
</span><span id="L-200"><a href="#L-200"><span class="linenos">200</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-201"><a href="#L-201"><span class="linenos">201</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-202"><a href="#L-202"><span class="linenos">202</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-203"><a href="#L-203"><span class="linenos">203</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-204"><a href="#L-204"><span class="linenos">204</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-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">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-207"><a href="#L-207"><span class="linenos">207</span></a>
</span><span id="L-208"><a href="#L-208"><span class="linenos">208</span></a>
</span><span id="L-209"><a href="#L-209"><span class="linenos">209</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-210"><a href="#L-210"><span class="linenos">210</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-211"><a href="#L-211"><span class="linenos">211</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-212"><a href="#L-212"><span class="linenos">212</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-213"><a href="#L-213"><span class="linenos">213</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-214"><a href="#L-214"><span class="linenos">214</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-215"><a href="#L-215"><span class="linenos">215</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-216"><a href="#L-216"><span class="linenos">216</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-217"><a href="#L-217"><span class="linenos">217</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-218"><a href="#L-218"><span class="linenos">218</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-219"><a href="#L-219"><span class="linenos">219</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-220"><a href="#L-220"><span class="linenos">220</span></a> <span class="p">),</span>
</span><span id="L-221"><a href="#L-221"><span class="linenos">221</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-222"><a href="#L-222"><span class="linenos">222</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-223"><a href="#L-223"><span class="linenos">223</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-224"><a href="#L-224"><span class="linenos">224</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-225"><a href="#L-225"><span class="linenos">225</span></a><span class="p">}</span>
</span><span id="L-226"><a href="#L-226"><span class="linenos">226</span></a>
</span><span id="L-227"><a href="#L-227"><span class="linenos">227</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>
@ -531,38 +557,64 @@
</span><span id="parse-147"><a href="#parse-147"><span class="linenos">147</span></a>
</span><span id="parse-148"><a href="#parse-148"><span class="linenos">148</span></a> <span class="k">return</span> <span class="n">node</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="c1"># We canonicalize the JSON path AST so that it always starts with a</span>
</span><span id="parse-151"><a href="#parse-151"><span class="linenos">151</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-152"><a href="#parse-152"><span class="linenos">152</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-153"><a href="#parse-153"><span class="linenos">153</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-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">while</span> <span class="n">_curr</span><span class="p">():</span>
</span><span id="parse-156"><a href="#parse-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">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-157"><a href="#parse-157"><span class="linenos">157</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-150"><a href="#parse-150"><span class="linenos">150</span></a> <span class="k">def</span> <span class="nf">_parse_var_text</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span><span id="parse-151"><a href="#parse-151"><span class="linenos">151</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
</span><span id="parse-152"><a href="#parse-152"><span class="linenos">152</span></a><span class="sd"> Consumes &amp; returns the text for a var. In BigQuery it&#39;s valid to have a key with spaces</span>
</span><span id="parse-153"><a href="#parse-153"><span class="linenos">153</span></a><span class="sd"> in it, e.g JSON_QUERY(..., &#39;$. a b c &#39;) should produce a single JSONPathKey(&#39; a b c &#39;).</span>
</span><span id="parse-154"><a href="#parse-154"><span class="linenos">154</span></a><span class="sd"> This is done by merging &quot;consecutive&quot; vars until a key separator is found (dot, colon etc)</span>
</span><span id="parse-155"><a href="#parse-155"><span class="linenos">155</span></a><span class="sd"> or the path string is exhausted.</span>
</span><span id="parse-156"><a href="#parse-156"><span class="linenos">156</span></a><span class="sd"> &quot;&quot;&quot;</span>
</span><span id="parse-157"><a href="#parse-157"><span class="linenos">157</span></a> <span class="n">prev_index</span> <span class="o">=</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">2</span>
</span><span id="parse-158"><a href="#parse-158"><span class="linenos">158</span></a>
</span><span id="parse-159"><a href="#parse-159"><span class="linenos">159</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-160"><a href="#parse-160"><span class="linenos">160</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-161"><a href="#parse-161"><span class="linenos">161</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-162"><a href="#parse-162"><span class="linenos">162</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-163"><a href="#parse-163"><span class="linenos">163</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="parse-164"><a href="#parse-164"><span class="linenos">164</span></a> <span class="n">value</span> <span class="o">=</span> <span class="kc">None</span>
</span><span id="parse-165"><a href="#parse-165"><span class="linenos">165</span></a>
</span><span id="parse-166"><a href="#parse-166"><span class="linenos">166</span></a> <span class="k">if</span> <span class="n">recursive</span><span class="p">:</span>
</span><span id="parse-167"><a href="#parse-167"><span class="linenos">167</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-168"><a href="#parse-168"><span class="linenos">168</span></a> <span class="k">elif</span> <span class="n">value</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">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-170"><a href="#parse-170"><span class="linenos">170</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="parse-171"><a href="#parse-171"><span class="linenos">171</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-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">L_BRACKET</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">_parse_bracket</span><span class="p">())</span>
</span><span id="parse-174"><a href="#parse-174"><span class="linenos">174</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-175"><a href="#parse-175"><span class="linenos">175</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-176"><a href="#parse-176"><span class="linenos">176</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-177"><a href="#parse-177"><span class="linenos">177</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-178"><a href="#parse-178"><span class="linenos">178</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="parse-179"><a href="#parse-179"><span class="linenos">179</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-159"><a href="#parse-159"><span class="linenos">159</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">VAR</span><span class="p">):</span>
</span><span id="parse-160"><a href="#parse-160"><span class="linenos">160</span></a> <span class="k">pass</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="n">start</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">if</span> <span class="n">prev_index</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="k">else</span> <span class="n">tokens</span><span class="p">[</span><span class="n">prev_index</span><span class="p">]</span><span class="o">.</span><span class="n">end</span> <span class="o">+</span> <span class="mi">1</span>
</span><span id="parse-163"><a href="#parse-163"><span class="linenos">163</span></a>
</span><span id="parse-164"><a href="#parse-164"><span class="linenos">164</span></a> <span class="k">if</span> <span class="n">i</span> <span class="o">&gt;=</span> <span class="nb">len</span><span class="p">(</span><span class="n">tokens</span><span class="p">):</span>
</span><span id="parse-165"><a href="#parse-165"><span class="linenos">165</span></a> <span class="c1"># This key is the last token for the path, so it&#39;s text is the remaining path</span>
</span><span id="parse-166"><a href="#parse-166"><span class="linenos">166</span></a> <span class="n">text</span> <span class="o">=</span> <span class="n">path</span><span class="p">[</span><span class="n">start</span><span class="p">:]</span>
</span><span id="parse-167"><a href="#parse-167"><span class="linenos">167</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="parse-168"><a href="#parse-168"><span class="linenos">168</span></a> <span class="n">text</span> <span class="o">=</span> <span class="n">path</span><span class="p">[</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">start</span><span class="p">]</span>
</span><span id="parse-169"><a href="#parse-169"><span class="linenos">169</span></a>
</span><span id="parse-170"><a href="#parse-170"><span class="linenos">170</span></a> <span class="k">return</span> <span class="n">text</span>
</span><span id="parse-171"><a href="#parse-171"><span class="linenos">171</span></a>
</span><span id="parse-172"><a href="#parse-172"><span class="linenos">172</span></a> <span class="c1"># We canonicalize the JSON path AST so that it always starts with a</span>
</span><span id="parse-173"><a href="#parse-173"><span class="linenos">173</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-174"><a href="#parse-174"><span class="linenos">174</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-175"><a href="#parse-175"><span class="linenos">175</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-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">while</span> <span class="n">_curr</span><span class="p">():</span>
</span><span id="parse-178"><a href="#parse-178"><span class="linenos">178</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-179"><a href="#parse-179"><span class="linenos">179</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-180"><a href="#parse-180"><span class="linenos">180</span></a>
</span><span id="parse-181"><a href="#parse-181"><span class="linenos">181</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="parse-181"><a href="#parse-181"><span class="linenos">181</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><span id="parse-182"><a href="#parse-182"><span class="linenos">182</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">_parse_var_text</span><span class="p">()</span>
</span><span id="parse-183"><a href="#parse-183"><span class="linenos">183</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">IDENTIFIER</span><span class="p">):</span>
</span><span id="parse-184"><a href="#parse-184"><span class="linenos">184</span></a> <span class="n">value</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-185"><a href="#parse-185"><span class="linenos">185</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-186"><a href="#parse-186"><span class="linenos">186</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-187"><a href="#parse-187"><span class="linenos">187</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="parse-188"><a href="#parse-188"><span class="linenos">188</span></a> <span class="n">value</span> <span class="o">=</span> <span class="kc">None</span>
</span><span id="parse-189"><a href="#parse-189"><span class="linenos">189</span></a>
</span><span id="parse-190"><a href="#parse-190"><span class="linenos">190</span></a> <span class="k">if</span> <span class="n">recursive</span><span class="p">:</span>
</span><span id="parse-191"><a href="#parse-191"><span class="linenos">191</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-192"><a href="#parse-192"><span class="linenos">192</span></a> <span class="k">elif</span> <span class="n">value</span><span class="p">:</span>
</span><span id="parse-193"><a href="#parse-193"><span class="linenos">193</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-194"><a href="#parse-194"><span class="linenos">194</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="parse-195"><a href="#parse-195"><span class="linenos">195</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-196"><a href="#parse-196"><span class="linenos">196</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-197"><a href="#parse-197"><span class="linenos">197</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-198"><a href="#parse-198"><span class="linenos">198</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-199"><a href="#parse-199"><span class="linenos">199</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">_parse_var_text</span><span class="p">()))</span>
</span><span id="parse-200"><a href="#parse-200"><span class="linenos">200</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">IDENTIFIER</span><span class="p">):</span>
</span><span id="parse-201"><a href="#parse-201"><span class="linenos">201</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-202"><a href="#parse-202"><span class="linenos">202</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-203"><a href="#parse-203"><span class="linenos">203</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-204"><a href="#parse-204"><span class="linenos">204</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="parse-205"><a href="#parse-205"><span class="linenos">205</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-206"><a href="#parse-206"><span class="linenos">206</span></a>
</span><span id="parse-207"><a href="#parse-207"><span class="linenos">207</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>
@ -588,7 +640,7 @@
<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#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;, &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;}</span>
<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#JSONPathSlice">sqlglot.expressions.JSONPathSlice</a>&#39;&gt;, &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;}</span>
</div>

File diff suppressed because one or more lines are too long

View file

@ -581,7 +581,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;match&#39;, &#39;format&#39;, &#39;laterals&#39;, &#39;into&#39;, &#39;group&#39;, &#39;connect&#39;, &#39;distribute&#39;, &#39;options&#39;, &#39;having&#39;, &#39;qualify&#39;, &#39;sample&#39;, &#39;operation_modifiers&#39;, &#39;locks&#39;, &#39;offset&#39;, &#39;settings&#39;, &#39;sort&#39;, &#39;pivots&#39;, &#39;prewhere&#39;, &#39;windows&#39;, &#39;with&#39;, &#39;cluster&#39;, &#39;limit&#39;, &#39;distinct&#39;}</span>
<label class="view-value-button pdoc-button" for="UNMERGABLE_ARGS-view-value"></label><span class="default_value">{&#39;qualify&#39;, &#39;prewhere&#39;, &#39;windows&#39;, &#39;options&#39;, &#39;operation_modifiers&#39;, &#39;settings&#39;, &#39;match&#39;, &#39;with&#39;, &#39;pivots&#39;, &#39;locks&#39;, &#39;having&#39;, &#39;sample&#39;, &#39;format&#39;, &#39;limit&#39;, &#39;distribute&#39;, &#39;sort&#39;, &#39;connect&#39;, &#39;kind&#39;, &#39;group&#39;, &#39;offset&#39;, &#39;distinct&#39;, &#39;into&#39;, &#39;laterals&#39;, &#39;cluster&#39;}</span>
</div>

View file

@ -3231,7 +3231,7 @@ prefix are statically known.</p>
<div class="attr variable">
<span class="name">DATETRUNC_COMPARISONS</span> =
<input id="DATETRUNC_COMPARISONS-view-value" class="view-value-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
<label class="view-value-button pdoc-button" for="DATETRUNC_COMPARISONS-view-value"></label><span class="default_value">{&lt;class &#39;<a href="../expressions.html#In">sqlglot.expressions.In</a>&#39;&gt;, &lt;class &#39;<a href="../expressions.html#GTE">sqlglot.expressions.GTE</a>&#39;&gt;, &lt;class &#39;<a href="../expressions.html#LTE">sqlglot.expressions.LTE</a>&#39;&gt;, &lt;class &#39;<a href="../expressions.html#GT">sqlglot.expressions.GT</a>&#39;&gt;, &lt;class &#39;<a href="../expressions.html#EQ">sqlglot.expressions.EQ</a>&#39;&gt;, &lt;class &#39;<a href="../expressions.html#LT">sqlglot.expressions.LT</a>&#39;&gt;, &lt;class &#39;<a href="../expressions.html#NEQ">sqlglot.expressions.NEQ</a>&#39;&gt;}</span>
<label class="view-value-button pdoc-button" for="DATETRUNC_COMPARISONS-view-value"></label><span class="default_value">{&lt;class &#39;<a href="../expressions.html#EQ">sqlglot.expressions.EQ</a>&#39;&gt;, &lt;class &#39;<a href="../expressions.html#GTE">sqlglot.expressions.GTE</a>&#39;&gt;, &lt;class &#39;<a href="../expressions.html#GT">sqlglot.expressions.GT</a>&#39;&gt;, &lt;class &#39;<a href="../expressions.html#NEQ">sqlglot.expressions.NEQ</a>&#39;&gt;, &lt;class &#39;<a href="../expressions.html#LT">sqlglot.expressions.LT</a>&#39;&gt;, &lt;class &#39;<a href="../expressions.html#LTE">sqlglot.expressions.LTE</a>&#39;&gt;, &lt;class &#39;<a href="../expressions.html#In">sqlglot.expressions.In</a>&#39;&gt;}</span>
</div>
@ -3315,7 +3315,7 @@ prefix are statically known.</p>
<section id="JOINS">
<div class="attr variable">
<span class="name">JOINS</span> =
<span class="default_value">{(&#39;&#39;, &#39;INNER&#39;), (&#39;RIGHT&#39;, &#39;OUTER&#39;), (&#39;RIGHT&#39;, &#39;&#39;), (&#39;&#39;, &#39;&#39;)}</span>
<span class="default_value">{(&#39;RIGHT&#39;, &#39;&#39;), (&#39;&#39;, &#39;INNER&#39;), (&#39;RIGHT&#39;, &#39;OUTER&#39;), (&#39;&#39;, &#39;&#39;)}</span>
</div>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -9164,7 +9164,7 @@
<div class="attr variable">
<span class="name">TOKENS_PRECEDING_HINT</span> =
<input id="Tokenizer.TOKENS_PRECEDING_HINT-view-value" class="view-value-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
<label class="view-value-button pdoc-button" for="Tokenizer.TOKENS_PRECEDING_HINT-view-value"></label><span class="default_value">{&lt;<a href="#TokenType.INSERT">TokenType.INSERT</a>: &#39;INSERT&#39;&gt;, &lt;<a href="#TokenType.SELECT">TokenType.SELECT</a>: &#39;SELECT&#39;&gt;, &lt;<a href="#TokenType.UPDATE">TokenType.UPDATE</a>: &#39;UPDATE&#39;&gt;, &lt;<a href="#TokenType.DELETE">TokenType.DELETE</a>: &#39;DELETE&#39;&gt;}</span>
<label class="view-value-button pdoc-button" for="Tokenizer.TOKENS_PRECEDING_HINT-view-value"></label><span class="default_value">{&lt;<a href="#TokenType.INSERT">TokenType.INSERT</a>: &#39;INSERT&#39;&gt;, &lt;<a href="#TokenType.UPDATE">TokenType.UPDATE</a>: &#39;UPDATE&#39;&gt;, &lt;<a href="#TokenType.DELETE">TokenType.DELETE</a>: &#39;DELETE&#39;&gt;, &lt;<a href="#TokenType.SELECT">TokenType.SELECT</a>: &#39;SELECT&#39;&gt;}</span>
</div>
@ -9203,7 +9203,7 @@
<div class="attr variable">
<span class="name">COMMANDS</span> =
<input id="Tokenizer.COMMANDS-view-value" class="view-value-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
<label class="view-value-button pdoc-button" for="Tokenizer.COMMANDS-view-value"></label><span class="default_value">{&lt;<a href="#TokenType.SHOW">TokenType.SHOW</a>: &#39;SHOW&#39;&gt;, &lt;<a href="#TokenType.RENAME">TokenType.RENAME</a>: &#39;RENAME&#39;&gt;, &lt;<a href="#TokenType.COMMAND">TokenType.COMMAND</a>: &#39;COMMAND&#39;&gt;, &lt;<a href="#TokenType.EXECUTE">TokenType.EXECUTE</a>: &#39;EXECUTE&#39;&gt;, &lt;<a href="#TokenType.FETCH">TokenType.FETCH</a>: &#39;FETCH&#39;&gt;}</span>
<label class="view-value-button pdoc-button" for="Tokenizer.COMMANDS-view-value"></label><span class="default_value">{&lt;<a href="#TokenType.COMMAND">TokenType.COMMAND</a>: &#39;COMMAND&#39;&gt;, &lt;<a href="#TokenType.RENAME">TokenType.RENAME</a>: &#39;RENAME&#39;&gt;, &lt;<a href="#TokenType.EXECUTE">TokenType.EXECUTE</a>: &#39;EXECUTE&#39;&gt;, &lt;<a href="#TokenType.FETCH">TokenType.FETCH</a>: &#39;FETCH&#39;&gt;, &lt;<a href="#TokenType.SHOW">TokenType.SHOW</a>: &#39;SHOW&#39;&gt;}</span>
</div>
@ -9215,7 +9215,7 @@
<div id="Tokenizer.COMMAND_PREFIX_TOKENS" class="classattr">
<div class="attr variable">
<span class="name">COMMAND_PREFIX_TOKENS</span> =
<span class="default_value">{&lt;<a href="#TokenType.SEMICOLON">TokenType.SEMICOLON</a>: &#39;SEMICOLON&#39;&gt;, &lt;<a href="#TokenType.BEGIN">TokenType.BEGIN</a>: &#39;BEGIN&#39;&gt;}</span>
<span class="default_value">{&lt;<a href="#TokenType.BEGIN">TokenType.BEGIN</a>: &#39;BEGIN&#39;&gt;, &lt;<a href="#TokenType.SEMICOLON">TokenType.SEMICOLON</a>: &#39;SEMICOLON&#39;&gt;}</span>
</div>

View file

@ -319,7 +319,7 @@ def _build_format_time(expr_type: t.Type[exp.Expression]) -> t.Callable[[t.List]
def _build_contains_substring(args: t.List) -> exp.Contains | exp.Anonymous:
if len(args) == 3:
return exp.Anonymous(this="CONTAINS_SUBSTRING", expressions=args)
return exp.Anonymous(this="CONTAINS_SUBSTR", expressions=args)
# Lowercase the operands in case of transpilation, as exp.Contains
# is case-sensitive on other dialects
@ -492,7 +492,7 @@ class BigQuery(Dialect):
FUNCTIONS = {
**parser.Parser.FUNCTIONS,
"CONTAINS_SUBSTRING": _build_contains_substring,
"CONTAINS_SUBSTR": _build_contains_substring,
"DATE": _build_date,
"DATE_ADD": build_date_delta_with_interval(exp.DateAdd),
"DATE_SUB": build_date_delta_with_interval(exp.DateSub),
@ -589,6 +589,8 @@ class BigQuery(Dialect):
NULL_TOKENS = {TokenType.NULL, TokenType.UNKNOWN}
DASHED_TABLE_PART_FOLLOW_TOKENS = {TokenType.DOT, TokenType.L_PAREN, TokenType.R_PAREN}
STATEMENT_PARSERS = {
**parser.Parser.STATEMENT_PARSERS,
TokenType.ELSE: lambda self: self._parse_as_command(self._prev),
@ -615,11 +617,13 @@ class BigQuery(Dialect):
if isinstance(this, exp.Identifier):
table_name = this.name
while self._match(TokenType.DASH, advance=False) and self._next:
text = ""
while self._is_connected() and self._curr.token_type != TokenType.DOT:
start = self._curr
while self._is_connected() and not self._match_set(
self.DASHED_TABLE_PART_FOLLOW_TOKENS, advance=False
):
self._advance()
text += self._prev.text
table_name += text
table_name += self._find_sql(start, self._prev)
this = exp.Identifier(this=table_name, quoted=this.args.get("quoted"))
elif isinstance(this, exp.Literal):
@ -1219,4 +1223,4 @@ class BigQuery(Dialect):
this = this.this
expr = expr.this
return self.func("CONTAINS_SUBSTRING", this, expr)
return self.func("CONTAINS_SUBSTR", this, expr)

View file

@ -8,7 +8,7 @@ from functools import reduce
from sqlglot import exp
from sqlglot.errors import ParseError
from sqlglot.generator import Generator, unsupported_args
from sqlglot.helper import AutoName, flatten, is_int, seq_get, subclasses
from sqlglot.helper import AutoName, flatten, is_int, seq_get, subclasses, to_bool
from sqlglot.jsonpath import JSONPathTokenizer, parse as parse_json_path
from sqlglot.parser import Parser
from sqlglot.time import TIMEZONES, format_time, subsecond_precision
@ -770,14 +770,7 @@ class Dialect(metaclass=_Dialect):
elif len(pair) == 2:
value = pair[1].strip()
# Coerce the value to boolean if it matches to the truthy/falsy values below
value_lower = value.lower()
if value_lower in ("true", "1"):
value = True
elif value_lower in ("false", "0"):
value = False
kwargs[key] = value
kwargs[key] = to_bool(value)
except ValueError:
raise ValueError(

View file

@ -128,6 +128,7 @@ class Oracle(Dialect):
NO_PAREN_FUNCTION_PARSERS = {
**parser.Parser.NO_PAREN_FUNCTION_PARSERS,
"NEXT": lambda self: self._parse_next_value_for(),
"SYSDATE": lambda self: self.expression(exp.CurrentTimestamp, sysdate=True),
}

View file

@ -476,6 +476,20 @@ class Postgres(Dialect):
and self.dialect.to_json_path(self._parse_bitwise()),
)
def _parse_generated_as_identity(
self,
) -> (
exp.GeneratedAsIdentityColumnConstraint
| exp.ComputedColumnConstraint
| exp.GeneratedAsRowColumnConstraint
):
this = super()._parse_generated_as_identity()
if self._match_text_seq("STORED"):
this = self.expression(exp.ComputedColumnConstraint, this=this.expression)
return this
class Generator(generator.Generator):
SINGLE_STRING_INTERVAL = True
RENAME_TABLE_WITH_DB = False
@ -691,3 +705,6 @@ class Postgres(Dialect):
if isinstance(seq_get(exprs, 0), exp.Select)
else f"{self.normalize_func('ARRAY')}[{self.expressions(expression, flat=True)}]"
)
def computedcolumnconstraint_sql(self, expression: exp.ComputedColumnConstraint) -> str:
return f"GENERATED ALWAYS AS ({self.sql(expression, 'this')}) STORED"

View file

@ -376,6 +376,7 @@ class Presto(Dialect):
exp.Cast: transforms.preprocess([transforms.epoch_cast_to_ts]),
exp.CurrentTime: lambda *_: "CURRENT_TIME",
exp.CurrentTimestamp: lambda *_: "CURRENT_TIMESTAMP",
exp.CurrentUser: lambda *_: "CURRENT_USER",
exp.DateAdd: _date_delta_sql("DATE_ADD"),
exp.DateDiff: lambda self, e: self.func(
"DATE_DIFF", unit_to_str(e), e.expression, e.this

View file

@ -41,9 +41,12 @@ def _build_datetime(
) -> t.Callable[[t.List], exp.Func]:
def _builder(args: t.List) -> exp.Func:
value = seq_get(args, 0)
int_value = value is not None and is_int(value.name)
scale_or_fmt = seq_get(args, 1)
if isinstance(value, exp.Literal):
int_value = value is not None and is_int(value.name)
int_scale_or_fmt = scale_or_fmt is not None and scale_or_fmt.is_int
if isinstance(value, exp.Literal) or (value and scale_or_fmt):
# Converts calls like `TO_TIME('01:02:03')` into casts
if len(args) == 1 and value.is_string and not int_value:
return (
@ -55,11 +58,11 @@ def _build_datetime(
# Handles `TO_TIMESTAMP(str, fmt)` and `TO_TIMESTAMP(num, scale)` as special
# cases so we can transpile them, since they're relatively common
if kind == exp.DataType.Type.TIMESTAMP:
if int_value and not safe:
if not safe and (int_value or int_scale_or_fmt):
# TRY_TO_TIMESTAMP('integer') is not parsed into exp.UnixToTime as
# it's not easily transpilable
return exp.UnixToTime(this=value, scale=seq_get(args, 1))
if not is_float(value.this):
return exp.UnixToTime(this=value, scale=scale_or_fmt)
if not int_scale_or_fmt and not is_float(value.name):
expr = build_formatted_time(exp.StrToTime, "snowflake")(args)
expr.set("safe", safe)
return expr

View file

@ -14,6 +14,7 @@ from sqlglot.dialects.dialect import (
)
from sqlglot.dialects.hive import Hive
from sqlglot.helper import seq_get, ensure_list
from sqlglot.tokens import TokenType
from sqlglot.transforms import (
preprocess,
remove_unique_constraints,
@ -159,6 +160,14 @@ class Spark2(Hive):
),
}
class Tokenizer(Hive.Tokenizer):
HEX_STRINGS = [("X'", "'"), ("x'", "'")]
KEYWORDS = {
**Hive.Tokenizer.KEYWORDS,
"TIMESTAMP": TokenType.TIMESTAMPTZ,
}
class Parser(Hive.Parser):
TRIM_PATTERN_FIRST = True
@ -337,6 +346,3 @@ class Spark2(Hive):
else sep
),
)
class Tokenizer(Hive.Tokenizer):
HEX_STRINGS = [("X'", "'"), ("x'", "'")]

View file

@ -597,6 +597,11 @@ class TSQL(Dialect):
),
}
NO_PAREN_FUNCTION_PARSERS = {
**parser.Parser.NO_PAREN_FUNCTION_PARSERS,
"NEXT": lambda self: self._parse_next_value_for(),
}
# The DCOLON (::) operator serves as a scope resolution (exp.ScopeResolution) operator in T-SQL
COLUMN_OPERATORS = {
**parser.Parser.COLUMN_OPERATORS,

View file

@ -31,6 +31,7 @@ from sqlglot.helper import (
ensure_list,
seq_get,
subclasses,
to_bool,
)
from sqlglot.tokens import Token, TokenError
@ -312,7 +313,7 @@ class Expression(metaclass=_Expression):
for kv in "".join(meta).split(","):
k, *v = kv.split("=")
value = v[0].strip() if v else True
self.meta[k.strip()] = value
self.meta[k.strip()] = to_bool(value)
if not prepend:
self.comments.append(comment)
@ -8231,7 +8232,7 @@ def replace_tables(
mapping = {normalize_table_name(k, dialect=dialect): v for k, v in mapping.items()}
def _replace_tables(node: Expression) -> Expression:
if isinstance(node, Table):
if isinstance(node, Table) and node.meta.get("replace") is not False:
original = normalize_table_name(node, dialect=dialect)
new_name = mapping.get(original)

View file

@ -2399,14 +2399,17 @@ class Generator(metaclass=_Generator):
f"'{nulls_sort_change.strip()}' translation not supported in window functions"
)
nulls_sort_change = ""
elif (
self.NULL_ORDERING_SUPPORTED is False
and (isinstance(expression.find_ancestor(exp.AggFunc, exp.Select), exp.AggFunc))
and (
elif self.NULL_ORDERING_SUPPORTED is False and (
(asc and nulls_sort_change == " NULLS LAST")
or (desc and nulls_sort_change == " NULLS FIRST")
)
):
# BigQuery does not allow these ordering/nulls combinations when used under
# an aggregation func or under a window containing one
ancestor = expression.find_ancestor(exp.AggFunc, exp.Window, exp.Select)
if isinstance(ancestor, exp.Window):
ancestor = ancestor.this
if isinstance(ancestor, exp.AggFunc):
self.unsupported(
f"'{nulls_sort_change.strip()}' translation not supported for aggregate functions with {sort_order} sort order"
)

View file

@ -456,6 +456,20 @@ def first(it: t.Iterable[T]) -> T:
return next(i for i in it)
def to_bool(value: t.Optional[str | bool]) -> t.Optional[str | bool]:
if isinstance(value, bool) or value is None:
return value
# Coerce the value to boolean if it matches to the truthy/falsy values below
value_lower = value.lower()
if value_lower in ("true", "1"):
return True
if value_lower in ("false", "0"):
return False
return value
def merge_ranges(ranges: t.List[t.Tuple[A, A]]) -> t.List[t.Tuple[A, A]]:
"""
Merges a sequence of ranges, represented as tuples (low, high) whose values

View file

@ -220,11 +220,16 @@ def _expand_using(scope: Scope, resolver: Resolver) -> t.Dict[str, t.Any]:
if not column.table and column.name in column_tables:
tables = column_tables[column.name]
coalesce_args = [exp.column(column.name, table=table) for table in tables]
replacement = exp.func("coalesce", *coalesce_args)
replacement: exp.Expression = exp.func("coalesce", *coalesce_args)
# Ensure selects keep their output name
if isinstance(column.parent, exp.Select):
# Ensure the USING column keeps its name if it's projected
replacement = alias(replacement, alias=column.name, copy=False)
elif isinstance(column.parent, exp.Struct):
# Ensure the USING column keeps its name if it's an anonymous STRUCT field
replacement = exp.PropertyEQ(
this=exp.to_identifier(column.name), expression=replacement
)
scope.replace(column, replacement)

View file

@ -586,6 +586,7 @@ class Parser(metaclass=_Parser):
TokenType.INSERT,
TokenType.LIKE,
TokenType.MERGE,
TokenType.NEXT,
TokenType.OFFSET,
TokenType.PRIMARY_KEY,
TokenType.RANGE,
@ -1107,7 +1108,6 @@ class Parser(metaclass=_Parser):
exp.ConnectByRoot, this=self._parse_column()
),
"IF": lambda self: self._parse_if(),
"NEXT": lambda self: self._parse_next_value_for(),
}
INVALID_FUNC_NAME_TOKENS = {

View file

@ -200,24 +200,7 @@ LANGUAGE js AS
self.validate_identity("CAST(x AS NVARCHAR)", "CAST(x AS STRING)")
self.validate_identity("CAST(x AS TIMESTAMPTZ)", "CAST(x AS TIMESTAMP)")
self.validate_identity("CAST(x AS RECORD)", "CAST(x AS STRUCT)")
self.validate_all(
"EDIT_DISTANCE(col1, col2, max_distance => 3)",
write={
"bigquery": "EDIT_DISTANCE(col1, col2, max_distance => 3)",
"clickhouse": UnsupportedError,
"databricks": UnsupportedError,
"drill": UnsupportedError,
"duckdb": UnsupportedError,
"hive": UnsupportedError,
"postgres": "LEVENSHTEIN_LESS_EQUAL(col1, col2, 3)",
"presto": UnsupportedError,
"snowflake": "EDITDISTANCE(col1, col2, 3)",
"spark": UnsupportedError,
"spark2": UnsupportedError,
"sqlite": UnsupportedError,
},
)
self.validate_identity("SELECT * FROM x WHERE x.y >= (SELECT MAX(a) FROM b-c) - 20")
self.validate_identity(
"MERGE INTO dataset.NewArrivals USING (SELECT * FROM UNNEST([('microwave', 10, 'warehouse #1'), ('dryer', 30, 'warehouse #1'), ('oven', 20, 'warehouse #2')])) ON FALSE WHEN NOT MATCHED THEN INSERT ROW WHEN NOT MATCHED BY SOURCE THEN DELETE"
)
@ -332,6 +315,23 @@ LANGUAGE js AS
"SELECT CAST(1 AS INT64)",
)
self.validate_all(
"EDIT_DISTANCE(col1, col2, max_distance => 3)",
write={
"bigquery": "EDIT_DISTANCE(col1, col2, max_distance => 3)",
"clickhouse": UnsupportedError,
"databricks": UnsupportedError,
"drill": UnsupportedError,
"duckdb": UnsupportedError,
"hive": UnsupportedError,
"postgres": "LEVENSHTEIN_LESS_EQUAL(col1, col2, 3)",
"presto": UnsupportedError,
"snowflake": "EDITDISTANCE(col1, col2, 3)",
"spark": UnsupportedError,
"spark2": UnsupportedError,
"sqlite": UnsupportedError,
},
)
self.validate_all(
"EDIT_DISTANCE(a, b)",
write={
@ -1608,11 +1608,11 @@ WHERE
)
self.validate_identity(
"CONTAINS_SUBSTRING(a, b, json_scope => 'JSON_KEYS_AND_VALUES')"
"CONTAINS_SUBSTR(a, b, json_scope => 'JSON_KEYS_AND_VALUES')"
).assert_is(exp.Anonymous)
self.validate_all(
"""CONTAINS_SUBSTRING(a, b)""",
"""CONTAINS_SUBSTR(a, b)""",
read={
"": "CONTAINS(a, b)",
"spark": "CONTAINS(a, b)",
@ -1628,7 +1628,7 @@ WHERE
"snowflake": "CONTAINS(LOWER(a), LOWER(b))",
"duckdb": "CONTAINS(LOWER(a), LOWER(b))",
"oracle": "CONTAINS(LOWER(a), LOWER(b))",
"bigquery": "CONTAINS_SUBSTRING(a, b)",
"bigquery": "CONTAINS_SUBSTR(a, b)",
},
)
@ -2131,6 +2131,16 @@ OPTIONS (
},
)
self.validate_all(
f"SELECT SUM(f1) OVER (ORDER BY f2 {sort_order}) FROM t",
read={
"": f"SELECT SUM(f1) OVER (ORDER BY f2 {sort_order} {null_order}) FROM t",
},
write={
"bigquery": f"SELECT SUM(f1) OVER (ORDER BY f2 {sort_order}) FROM t",
},
)
def test_json_extract(self):
self.validate_all(
"""SELECT JSON_QUERY('{"class": {"students": []}}', '$.class')""",

View file

@ -33,7 +33,8 @@ class TestDatabricks(Validator):
"CREATE TABLE IF NOT EXISTS db.table (a TIMESTAMP, b BOOLEAN GENERATED ALWAYS AS (NOT a IS NULL)) USING DELTA"
)
self.validate_identity(
"SELECT DATE_FORMAT(CAST(FROM_UTC_TIMESTAMP(CAST(foo AS TIMESTAMP), 'America/Los_Angeles') AS TIMESTAMP), 'yyyy-MM-dd HH:mm:ss') AS foo FROM t"
"SELECT DATE_FORMAT(CAST(FROM_UTC_TIMESTAMP(foo, 'America/Los_Angeles') AS TIMESTAMP), 'yyyy-MM-dd HH:mm:ss') AS foo FROM t",
"SELECT DATE_FORMAT(CAST(FROM_UTC_TIMESTAMP(CAST(foo AS TIMESTAMP), 'America/Los_Angeles') AS TIMESTAMP), 'yyyy-MM-dd HH:mm:ss') AS foo FROM t",
)
self.validate_identity(
"SELECT * FROM sales UNPIVOT INCLUDE NULLS (sales FOR quarter IN (q1 AS `Jan-Mar`))"

View file

@ -79,7 +79,7 @@ class TestDuckDB(Validator):
self.validate_all(
"SELECT SUM(X) OVER (ORDER BY x)",
write={
"bigquery": "SELECT SUM(X) OVER (ORDER BY x NULLS LAST)",
"bigquery": "SELECT SUM(X) OVER (ORDER BY x)",
"duckdb": "SELECT SUM(X) OVER (ORDER BY x)",
"mysql": "SELECT SUM(X) OVER (ORDER BY CASE WHEN x IS NULL THEN 1 ELSE 0 END, x)",
},

View file

@ -761,13 +761,13 @@ class TestHive(Validator):
},
)
self.validate_all(
"SELECT TRUNC(CAST(ds AS TIMESTAMP), 'MONTH') AS mm FROM tbl WHERE ds BETWEEN '2023-10-01' AND '2024-02-29'",
"SELECT TRUNC(CAST(ds AS TIMESTAMP), 'MONTH')",
read={
"hive": "SELECT TRUNC(CAST(ds AS TIMESTAMP), 'MONTH') AS mm FROM tbl WHERE ds BETWEEN '2023-10-01' AND '2024-02-29'",
"presto": "SELECT DATE_TRUNC('MONTH', CAST(ds AS TIMESTAMP)) AS mm FROM tbl WHERE ds BETWEEN '2023-10-01' AND '2024-02-29'",
"hive": "SELECT TRUNC(CAST(ds AS TIMESTAMP), 'MONTH')",
"presto": "SELECT DATE_TRUNC('MONTH', CAST(ds AS TIMESTAMP))",
},
write={
"presto": "SELECT DATE_TRUNC('MONTH', TRY_CAST(ds AS TIMESTAMP)) AS mm FROM tbl WHERE ds BETWEEN '2023-10-01' AND '2024-02-29'",
"presto": "SELECT DATE_TRUNC('MONTH', TRY_CAST(ds AS TIMESTAMP))",
},
)
self.validate_all(

View file

@ -1273,22 +1273,27 @@ COMMENT='客户账户表'"""
)
def test_timestamp_trunc(self):
for dialect in ("postgres", "snowflake", "duckdb", "spark", "databricks"):
hive_dialects = ("spark", "databricks")
for dialect in ("postgres", "snowflake", "duckdb", *hive_dialects):
for unit in (
"MILLISECOND",
"SECOND",
"DAY",
"MONTH",
"YEAR",
):
with self.subTest(f"MySQL -> {dialect} Timestamp Trunc with unit {unit}: "):
cast = (
"TIMESTAMP('2001-02-16 20:38:40')"
if dialect in hive_dialects
else "CAST('2001-02-16 20:38:40' AS DATETIME)"
)
self.validate_all(
f"DATE_ADD('0000-01-01 00:00:00', INTERVAL (TIMESTAMPDIFF({unit}, '0000-01-01 00:00:00', CAST('2001-02-16 20:38:40' AS DATETIME))) {unit})",
f"DATE_ADD('0000-01-01 00:00:00', INTERVAL (TIMESTAMPDIFF({unit}, '0000-01-01 00:00:00', {cast})) {unit})",
read={
dialect: f"DATE_TRUNC({unit}, TIMESTAMP '2001-02-16 20:38:40')",
},
write={
"mysql": f"DATE_ADD('0000-01-01 00:00:00', INTERVAL (TIMESTAMPDIFF({unit}, '0000-01-01 00:00:00', CAST('2001-02-16 20:38:40' AS DATETIME))) {unit})",
"mysql": f"DATE_ADD('0000-01-01 00:00:00', INTERVAL (TIMESTAMPDIFF({unit}, '0000-01-01 00:00:00', {cast})) {unit})",
},
)

View file

@ -1047,6 +1047,7 @@ class TestPostgres(Validator):
self.validate_identity("CREATE TABLE tbl (col INT UNIQUE NULLS NOT DISTINCT DEFAULT 9.99)")
self.validate_identity("CREATE TABLE tbl (col UUID UNIQUE DEFAULT GEN_RANDOM_UUID())")
self.validate_identity("CREATE TABLE tbl (col UUID, UNIQUE NULLS NOT DISTINCT (col))")
self.validate_identity("CREATE TABLE tbl (col_a INT GENERATED ALWAYS AS (1 + 2) STORED)")
self.validate_identity("CREATE INDEX CONCURRENTLY ix_table_id ON tbl USING btree(id)")
self.validate_identity(

View file

@ -354,7 +354,7 @@ class TestPresto(Validator):
},
)
self.validate_all(
"((DAY_OF_WEEK(CAST(TRY_CAST('2012-08-08 01:00:00' AS TIMESTAMP) AS DATE)) % 7) + 1)",
"((DAY_OF_WEEK(CAST(CAST(TRY_CAST('2012-08-08 01:00:00' AS TIMESTAMP WITH TIME ZONE) AS TIMESTAMP) AS DATE)) % 7) + 1)",
read={
"spark": "DAYOFWEEK(CAST('2012-08-08 01:00:00' AS TIMESTAMP))",
},
@ -406,7 +406,7 @@ class TestPresto(Validator):
},
)
self.validate_all(
"SELECT AT_TIMEZONE(CAST('2012-10-31 00:00' AS TIMESTAMP), 'America/Sao_Paulo')",
"SELECT AT_TIMEZONE(CAST(CAST('2012-10-31 00:00' AS TIMESTAMP WITH TIME ZONE) AS TIMESTAMP), 'America/Sao_Paulo')",
read={
"spark": "SELECT FROM_UTC_TIMESTAMP(TIMESTAMP '2012-10-31 00:00', 'America/Sao_Paulo')",
},
@ -1071,6 +1071,18 @@ class TestPresto(Validator):
"databricks": "REGEXP_EXTRACT('abc', '(a)(b)(c)', 0)",
},
)
self.validate_all(
"CURRENT_USER",
read={
"presto": "CURRENT_USER",
"trino": "CURRENT_USER",
"snowflake": "CURRENT_USER()", # Although the ANSI standard is CURRENT_USER
},
write={
"trino": "CURRENT_USER",
"snowflake": "CURRENT_USER()",
},
)
def test_encode_decode(self):
self.validate_identity("FROM_UTF8(x, y)")
@ -1191,7 +1203,8 @@ MATCH_RECOGNIZE (
DEFINE
B AS totalprice < PREV(totalprice),
C AS totalprice > PREV(totalprice) AND totalprice <= A.totalprice,
D AS totalprice > PREV(totalprice)
D AS totalprice > PREV(totalprice),
E AS MAX(foo) >= NEXT(bar)
)""",
pretty=True,
)

View file

@ -124,6 +124,7 @@ WHERE
self.validate_identity(
"SELECT * FROM DATA AS DATA_L ASOF JOIN DATA AS DATA_R MATCH_CONDITION (DATA_L.VAL > DATA_R.VAL) ON DATA_L.ID = DATA_R.ID"
)
self.validate_identity("TO_TIMESTAMP(col, fmt)")
self.validate_identity(
"CAST(x AS GEOGRAPHY)",
"TO_GEOGRAPHY(x)",
@ -670,6 +671,15 @@ WHERE
"snowflake": "SELECT a FROM test AS t QUALIFY ROW_NUMBER() OVER (PARTITION BY a ORDER BY Z) = 1",
},
)
self.validate_all(
"SELECT TO_TIMESTAMP(col, 'DD-MM-YYYY HH12:MI:SS') FROM t",
write={
"bigquery": "SELECT PARSE_TIMESTAMP('%d-%m-%Y %I:%M:%S', col) FROM t",
"duckdb": "SELECT STRPTIME(col, '%d-%m-%Y %I:%M:%S') FROM t",
"snowflake": "SELECT TO_TIMESTAMP(col, 'DD-mm-yyyy hh12:mi:ss') FROM t",
"spark": "SELECT TO_TIMESTAMP(col, 'dd-MM-yyyy hh:mm:ss') FROM t",
},
)
self.validate_all(
"SELECT TO_TIMESTAMP(1659981729)",
write={

View file

@ -765,6 +765,16 @@ TBLPROPERTIES (
},
)
self.validate_all(
"SELECT CAST(col AS TIMESTAMP)",
write={
"spark2": "SELECT CAST(col AS TIMESTAMP)",
"spark": "SELECT CAST(col AS TIMESTAMP)",
"databricks": "SELECT TRY_CAST(col AS TIMESTAMP)",
"duckdb": "SELECT TRY_CAST(col AS TIMESTAMPTZ)",
},
)
def test_bool_or(self):
self.validate_all(
"SELECT a, LOGICAL_OR(b) FROM table GROUP BY a",

View file

@ -2075,3 +2075,18 @@ FROM OPENJSON(@json) WITH (
"tsql": UnsupportedError,
},
)
def test_next_value_for(self):
self.validate_identity(
"SELECT NEXT VALUE FOR db.schema.sequence_name OVER (ORDER BY foo), col"
)
self.validate_all(
"SELECT NEXT VALUE FOR db.schema.sequence_name",
read={
"oracle": "SELECT NEXT VALUE FOR db.schema.sequence_name",
"tsql": "SELECT NEXT VALUE FOR db.schema.sequence_name",
},
write={
"oracle": "SELECT NEXT VALUE FOR db.schema.sequence_name",
},
)

View file

@ -830,8 +830,6 @@ JSON_OBJECT('x': 1 RETURNING VARCHAR(100))
JSON_OBJECT('x': 1 RETURNING VARBINARY FORMAT JSON ENCODING UTF8)
PRIOR AS x
SELECT if.x
SELECT NEXT VALUE FOR db.schema.sequence_name
SELECT NEXT VALUE FOR db.schema.sequence_name OVER (ORDER BY foo), col
SELECT PERCENTILE_CONT(x, 0.5) OVER ()
WITH my_cte AS (SELECT 'a' AS desc) SELECT desc AS description FROM my_cte
WITH my_cte AS (SELECT 'a' AS asc) SELECT asc AS description FROM my_cte

View file

@ -532,6 +532,14 @@ WITH t1 AS (SELECT 'x' AS id, CAST('2024-01-01' AS DATE) AS foo, 000 AS value),
WITH t1 AS (SELECT 'x' AS id, CAST('2024-01-01' AS DATE) AS foo, 000 AS value), t2 AS (SELECT 'x' AS id, CAST('2024-02-02' AS DATE) AS foo, 123 AS value), t3 AS (SELECT 'x' AS id, CAST('2024-02-02' AS DATE) AS foo, 456 AS value), t4 AS (SELECT 'x' AS id, CAST('2024-03-03' AS DATE) AS foo, 789 AS value) SELECT * FROM t1 FULL OUTER JOIN t2 USING (id, foo) FULL OUTER JOIN t3 USING (id, foo) FULL OUTER JOIN t4 USING (id, foo);
WITH t1 AS (SELECT 'x' AS id, CAST('2024-01-01' AS DATE) AS foo, 000 AS value), t2 AS (SELECT 'x' AS id, CAST('2024-02-02' AS DATE) AS foo, 123 AS value), t3 AS (SELECT 'x' AS id, CAST('2024-02-02' AS DATE) AS foo, 456 AS value), t4 AS (SELECT 'x' AS id, CAST('2024-03-03' AS DATE) AS foo, 789 AS value) SELECT COALESCE(t1.id, t2.id, t3.id, t4.id) AS id, COALESCE(t1.foo, t2.foo, t3.foo, t4.foo) AS foo, t1.value AS value, t2.value AS value, t3.value AS value, t4.value AS value FROM t1 AS t1 FULL OUTER JOIN t2 AS t2 ON t1.id = t2.id AND t1.foo = t2.foo FULL OUTER JOIN t3 AS t3 ON COALESCE(t1.id, t2.id) = t3.id AND COALESCE(t1.foo, t2.foo) = t3.foo FULL OUTER JOIN t4 AS t4 ON COALESCE(t1.id, t2.id, t3.id) = t4.id AND COALESCE(t1.foo, t2.foo, t3.foo) = t4.foo;
# title: Name anonymous STRUCT fields if replacing USING columns
WITH t1 AS (SELECT 1 AS id), t2 AS (SELECT 2 AS id) SELECT STRUCT(id) AS my_field FROM t1 JOIN t2 USING (id);
WITH t1 AS (SELECT 1 AS id), t2 AS (SELECT 2 AS id) SELECT STRUCT(COALESCE(t1.id, t2.id) AS id) AS my_field FROM t1 AS t1 JOIN t2 AS t2 ON t1.id = t2.id;
# title: Do not rename aliased STRUCT fields if replacing USING columns
WITH t1 AS (SELECT 1 AS id), t2 AS (SELECT 2 AS id) SELECT STRUCT(id AS col) AS my_field FROM t1 JOIN t2 USING (id);
WITH t1 AS (SELECT 1 AS id), t2 AS (SELECT 2 AS id) SELECT STRUCT(COALESCE(t1.id, t2.id) AS col) AS my_field FROM t1 AS t1 JOIN t2 AS t2 ON t1.id = t2.id;
--------------------------------------
-- Hint with table reference
--------------------------------------

View file

@ -258,6 +258,14 @@ class TestExpressions(unittest.TestCase):
'SELECT * FROM "my-project"."example"."table" /* example.table */',
)
self.assertEqual(
exp.replace_tables(
parse_one("select * from example.table /* sqlglot.meta replace=false */"),
{"example.table": "a.b"},
).sql(),
"SELECT * FROM example.table /* sqlglot.meta replace=false */",
)
def test_expand(self):
self.assertEqual(
exp.expand(
@ -1168,7 +1176,7 @@ FROM foo""",
def test_set_meta(self):
query = parse_one("SELECT * FROM foo /* sqlglot.meta x = 1, y = a, z */")
self.assertEqual(query.find(exp.Table).meta, {"x": "1", "y": "a", "z": True})
self.assertEqual(query.find(exp.Table).meta, {"x": True, "y": "a", "z": True})
self.assertEqual(query.sql(), "SELECT * FROM foo /* sqlglot.meta x = 1, y = a, z */")
def test_assert_is(self):