Merging upstream version 26.26.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
768f936511
commit
1ac9fca060
62 changed files with 938 additions and 453 deletions
81
.github/scripts/format_benchmark.py
vendored
Executable file
81
.github/scripts/format_benchmark.py
vendored
Executable file
|
@ -0,0 +1,81 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Format benchmark comparison output with visual indicators for GitHub markdown."""
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
def format_benchmark_output(content):
|
||||
"""Add visual formatting to benchmark comparison output."""
|
||||
lines = content.split("\n")
|
||||
formatted_lines = []
|
||||
|
||||
for line in lines:
|
||||
# Skip empty lines and headers
|
||||
if not line.strip() or line.startswith("|") and "---" in line:
|
||||
formatted_lines.append(line)
|
||||
continue
|
||||
|
||||
# Process benchmark result lines
|
||||
if "|" in line and ("faster" in line or "slower" in line):
|
||||
# Extract the speed factor (e.g., "1.23x faster" or "1.10x slower")
|
||||
speed_match = re.search(r"(\d+\.\d+)x\s+(faster|slower)", line)
|
||||
if speed_match:
|
||||
factor = float(speed_match.group(1))
|
||||
direction = speed_match.group(2)
|
||||
|
||||
# Add visual indicators based on performance
|
||||
if direction == "faster":
|
||||
# Green indicator for faster
|
||||
if factor >= 2.0:
|
||||
indicator = "🟢🟢" # Double green for 2x+ faster
|
||||
elif factor >= 1.1:
|
||||
indicator = "🟢" # Single green for 1.1x+ faster
|
||||
else:
|
||||
indicator = "⚪" # White for marginal improvement
|
||||
formatted_text = f"{indicator} **{speed_match.group(0)}**"
|
||||
else:
|
||||
# Red indicator for slower
|
||||
if factor >= 2.0:
|
||||
indicator = "🔴🔴" # Double red for 2x+ slower
|
||||
elif factor >= 1.1:
|
||||
indicator = "🔴" # Single red for 1.1x+ slower
|
||||
else:
|
||||
indicator = "⚪" # White for marginal slowdown
|
||||
formatted_text = f"{indicator} **{speed_match.group(0)}**"
|
||||
|
||||
# Replace the original text with formatted version
|
||||
line = line.replace(speed_match.group(0), formatted_text)
|
||||
elif "not significant" in line:
|
||||
# Add neutral indicator for non-significant changes
|
||||
line = re.sub(r"not significant", "⚪ not significant", line)
|
||||
|
||||
formatted_lines.append(line)
|
||||
|
||||
return "\n".join(formatted_lines)
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: python format_benchmark.py <input_file>")
|
||||
sys.exit(1)
|
||||
|
||||
input_file = sys.argv[1]
|
||||
|
||||
try:
|
||||
with open(input_file, "r") as f:
|
||||
content = f.read()
|
||||
|
||||
formatted = format_benchmark_output(content)
|
||||
print(formatted)
|
||||
|
||||
except FileNotFoundError:
|
||||
print(f"Error: File '{input_file}' not found")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
21
.github/workflows/benchmark-sqlglot.yml
vendored
21
.github/workflows/benchmark-sqlglot.yml
vendored
|
@ -61,14 +61,27 @@ jobs:
|
|||
- name: Compare benchmarks and save results
|
||||
run: |
|
||||
source ./.venv/bin/activate
|
||||
python -m pyperf compare_to bench_parse_pr.json bench_parse_main.json --table --table-format=md > bench_parse_comparison.txt
|
||||
python -m pyperf compare_to bench_optimize_pr.json bench_optimize_main.json --table --table-format=md > bench_optimize_comparison.txt
|
||||
python -m pyperf compare_to bench_parse_main.json bench_parse_pr.json --table --table-format=md > bench_parse_comparison_raw.txt
|
||||
python -m pyperf compare_to bench_optimize_main.json bench_optimize_pr.json --table --table-format=md > bench_optimize_comparison_raw.txt
|
||||
|
||||
# Format with colors
|
||||
python .github/scripts/format_benchmark.py bench_parse_comparison_raw.txt > bench_parse_comparison.txt
|
||||
python .github/scripts/format_benchmark.py bench_optimize_comparison_raw.txt > bench_optimize_comparison.txt
|
||||
- name: Combine benchmark outputs
|
||||
run: |
|
||||
echo "## Parsing Benchmark" > combined_benchmarks.md
|
||||
echo "## Benchmark Results" > combined_benchmarks.md
|
||||
echo "" >> combined_benchmarks.md
|
||||
echo "**Legend:**" >> combined_benchmarks.md
|
||||
echo "- 🟢🟢 = 2x+ faster" >> combined_benchmarks.md
|
||||
echo "- 🟢 = 1.1x - 2x faster" >> combined_benchmarks.md
|
||||
echo "- ⚪ = No significant change (< 1.1x)" >> combined_benchmarks.md
|
||||
echo "- 🔴 = 1.1x - 2x slower" >> combined_benchmarks.md
|
||||
echo "- 🔴🔴 = 2x+ slower" >> combined_benchmarks.md
|
||||
echo "" >> combined_benchmarks.md
|
||||
echo "### Parsing Benchmark" >> combined_benchmarks.md
|
||||
cat bench_parse_comparison.txt >> combined_benchmarks.md
|
||||
echo -e "\n---\n" >> combined_benchmarks.md
|
||||
echo "## Optimization Benchmark" >> combined_benchmarks.md
|
||||
echo "### Optimization Benchmark" >> combined_benchmarks.md
|
||||
cat bench_optimize_comparison.txt >> combined_benchmarks.md
|
||||
- name: Comment on PR for parse benchmark results
|
||||
uses: peter-evans/create-or-update-comment@v4
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
Changelog
|
||||
=========
|
||||
|
||||
## [v26.25.3] - 2025-06-04
|
||||
### :sparkles: New Features
|
||||
- [`964b4a1`](https://github.com/tobymao/sqlglot/commit/964b4a1e367e00e243b80edf677cd48d453ed31e) - add line/col position for Star *(commit by [@georgesittas](https://github.com/georgesittas))*
|
||||
|
||||
|
||||
## [v26.25.2] - 2025-06-04
|
||||
### :sparkles: New Features
|
||||
- [`8b5129f`](https://github.com/tobymao/sqlglot/commit/8b5129f288880032f0bf9d649984d82314039af1) - **postgres**: improve pretty-formatting of ARRAY[...] *(commit by [@georgesittas](https://github.com/georgesittas))*
|
||||
|
@ -4788,3 +4793,4 @@ Changelog
|
|||
[v26.25.0]: https://github.com/tobymao/sqlglot/compare/v26.24.0...v26.25.0
|
||||
[v26.25.1]: https://github.com/tobymao/sqlglot/compare/v26.25.0...v26.25.1
|
||||
[v26.25.2]: https://github.com/tobymao/sqlglot/compare/v26.25.1...v26.25.2
|
||||
[v26.25.3]: https://github.com/tobymao/sqlglot/compare/v26.25.2...v26.25.3
|
||||
|
|
|
@ -497,6 +497,7 @@ See also: [Writing a Python SQL engine from scratch](https://github.com/tobymao/
|
|||
* [Dagster](https://github.com/dagster-io/dagster)
|
||||
* [Fugue](https://github.com/fugue-project/fugue)
|
||||
* [Ibis](https://github.com/ibis-project/ibis)
|
||||
* [dlt](https://github.com/dlt-hub/dlt)
|
||||
* [mysql-mimic](https://github.com/kelsin/mysql-mimic)
|
||||
* [Querybook](https://github.com/pinterest/querybook)
|
||||
* [Quokka](https://github.com/marsupialtail/quokka)
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -84,8 +84,8 @@
|
|||
</span><span id="L-17"><a href="#L-17"><span class="linenos">17</span></a><span class="n">__version_tuple__</span><span class="p">:</span> <span class="n">VERSION_TUPLE</span>
|
||||
</span><span id="L-18"><a href="#L-18"><span class="linenos">18</span></a><span class="n">version_tuple</span><span class="p">:</span> <span class="n">VERSION_TUPLE</span>
|
||||
</span><span id="L-19"><a href="#L-19"><span class="linenos">19</span></a>
|
||||
</span><span id="L-20"><a href="#L-20"><span class="linenos">20</span></a><span class="n">__version__</span> <span class="o">=</span> <span class="n">version</span> <span class="o">=</span> <span class="s1">'26.25.2'</span>
|
||||
</span><span id="L-21"><a href="#L-21"><span class="linenos">21</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">26</span><span class="p">,</span> <span class="mi">25</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
|
||||
</span><span id="L-20"><a href="#L-20"><span class="linenos">20</span></a><span class="n">__version__</span> <span class="o">=</span> <span class="n">version</span> <span class="o">=</span> <span class="s1">'26.25.3'</span>
|
||||
</span><span id="L-21"><a href="#L-21"><span class="linenos">21</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">26</span><span class="p">,</span> <span class="mi">25</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
|
||||
</span></pre></div>
|
||||
|
||||
|
||||
|
@ -93,7 +93,7 @@
|
|||
<section id="__version__">
|
||||
<div class="attr variable">
|
||||
<span class="name">__version__</span><span class="annotation">: str</span> =
|
||||
<span class="default_value">'26.25.2'</span>
|
||||
<span class="default_value">'26.25.3'</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -105,7 +105,7 @@
|
|||
<section id="__version_tuple__">
|
||||
<div class="attr variable">
|
||||
<span class="name">__version_tuple__</span><span class="annotation">: object</span> =
|
||||
<span class="default_value">(26, 25, 2)</span>
|
||||
<span class="default_value">(26, 25, 3)</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -117,7 +117,7 @@
|
|||
<section id="version">
|
||||
<div class="attr variable">
|
||||
<span class="name">version</span><span class="annotation">: str</span> =
|
||||
<span class="default_value">'26.25.2'</span>
|
||||
<span class="default_value">'26.25.3'</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -129,7 +129,7 @@
|
|||
<section id="version_tuple">
|
||||
<div class="attr variable">
|
||||
<span class="name">version_tuple</span><span class="annotation">: object</span> =
|
||||
<span class="default_value">(26, 25, 2)</span>
|
||||
<span class="default_value">(26, 25, 3)</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
|
|
@ -359,7 +359,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="Athena">
|
||||
<div class="attr variable">
|
||||
<span class="name">Athena</span> =
|
||||
<span class="default_value"><MagicMock id='140634507837104'></span>
|
||||
<span class="default_value"><MagicMock id='140571796728384'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -371,7 +371,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="BigQuery">
|
||||
<div class="attr variable">
|
||||
<span class="name">BigQuery</span> =
|
||||
<span class="default_value"><MagicMock id='140634507824912'></span>
|
||||
<span class="default_value"><MagicMock id='140571796081632'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -383,7 +383,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="ClickHouse">
|
||||
<div class="attr variable">
|
||||
<span class="name">ClickHouse</span> =
|
||||
<span class="default_value"><MagicMock id='140634506710896'></span>
|
||||
<span class="default_value"><MagicMock id='140571798395520'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -395,7 +395,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="Databricks">
|
||||
<div class="attr variable">
|
||||
<span class="name">Databricks</span> =
|
||||
<span class="default_value"><MagicMock id='140634506014208'></span>
|
||||
<span class="default_value"><MagicMock id='140571786944400'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -407,7 +407,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="Doris">
|
||||
<div class="attr variable">
|
||||
<span class="name">Doris</span> =
|
||||
<span class="default_value"><MagicMock id='140634502703680'></span>
|
||||
<span class="default_value"><MagicMock id='140571799701632'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -419,7 +419,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="Drill">
|
||||
<div class="attr variable">
|
||||
<span class="name">Drill</span> =
|
||||
<span class="default_value"><MagicMock id='140634506225040'></span>
|
||||
<span class="default_value"><MagicMock id='140571798507328'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -431,7 +431,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="Druid">
|
||||
<div class="attr variable">
|
||||
<span class="name">Druid</span> =
|
||||
<span class="default_value"><MagicMock id='140634506216304'></span>
|
||||
<span class="default_value"><MagicMock id='140571784920080'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -443,7 +443,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="DuckDB">
|
||||
<div class="attr variable">
|
||||
<span class="name">DuckDB</span> =
|
||||
<span class="default_value"><MagicMock id='140634494301136'></span>
|
||||
<span class="default_value"><MagicMock id='140571784909808'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -455,7 +455,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="Dune">
|
||||
<div class="attr variable">
|
||||
<span class="name">Dune</span> =
|
||||
<span class="default_value"><MagicMock id='140634505383792'></span>
|
||||
<span class="default_value"><MagicMock id='140571785635072'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -467,7 +467,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="Hive">
|
||||
<div class="attr variable">
|
||||
<span class="name">Hive</span> =
|
||||
<span class="default_value"><MagicMock id='140634502237920'></span>
|
||||
<span class="default_value"><MagicMock id='140571796939552'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -479,7 +479,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="Materialize">
|
||||
<div class="attr variable">
|
||||
<span class="name">Materialize</span> =
|
||||
<span class="default_value"><MagicMock id='140634509349440'></span>
|
||||
<span class="default_value"><MagicMock id='140571796933216'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -491,7 +491,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="MySQL">
|
||||
<div class="attr variable">
|
||||
<span class="name">MySQL</span> =
|
||||
<span class="default_value"><MagicMock id='140634507150432'></span>
|
||||
<span class="default_value"><MagicMock id='140571802007920'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -503,7 +503,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="Oracle">
|
||||
<div class="attr variable">
|
||||
<span class="name">Oracle</span> =
|
||||
<span class="default_value"><MagicMock id='140634496723616'></span>
|
||||
<span class="default_value"><MagicMock id='140571798015520'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -515,7 +515,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="Postgres">
|
||||
<div class="attr variable">
|
||||
<span class="name">Postgres</span> =
|
||||
<span class="default_value"><MagicMock id='140634496715216'></span>
|
||||
<span class="default_value"><MagicMock id='140571787331280'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -527,7 +527,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="Presto">
|
||||
<div class="attr variable">
|
||||
<span class="name">Presto</span> =
|
||||
<span class="default_value"><MagicMock id='140634508955024'></span>
|
||||
<span class="default_value"><MagicMock id='140571792711184'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -539,7 +539,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="PRQL">
|
||||
<div class="attr variable">
|
||||
<span class="name">PRQL</span> =
|
||||
<span class="default_value"><MagicMock id='140634507747792'></span>
|
||||
<span class="default_value"><MagicMock id='140571790276352'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -551,7 +551,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="Redshift">
|
||||
<div class="attr variable">
|
||||
<span class="name">Redshift</span> =
|
||||
<span class="default_value"><MagicMock id='140634504908416'></span>
|
||||
<span class="default_value"><MagicMock id='140571796486896'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -563,7 +563,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="RisingWave">
|
||||
<div class="attr variable">
|
||||
<span class="name">RisingWave</span> =
|
||||
<span class="default_value"><MagicMock id='140634504916624'></span>
|
||||
<span class="default_value"><MagicMock id='140571796480032'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -575,7 +575,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="Snowflake">
|
||||
<div class="attr variable">
|
||||
<span class="name">Snowflake</span> =
|
||||
<span class="default_value"><MagicMock id='140634507238688'></span>
|
||||
<span class="default_value"><MagicMock id='140571798302544'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -587,7 +587,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="Spark">
|
||||
<div class="attr variable">
|
||||
<span class="name">Spark</span> =
|
||||
<span class="default_value"><MagicMock id='140634507369712'></span>
|
||||
<span class="default_value"><MagicMock id='140571798306144'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -599,7 +599,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="Spark2">
|
||||
<div class="attr variable">
|
||||
<span class="name">Spark2</span> =
|
||||
<span class="default_value"><MagicMock id='140634506022528'></span>
|
||||
<span class="default_value"><MagicMock id='140571795407632'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -611,7 +611,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="SQLite">
|
||||
<div class="attr variable">
|
||||
<span class="name">SQLite</span> =
|
||||
<span class="default_value"><MagicMock id='140634506023632'></span>
|
||||
<span class="default_value"><MagicMock id='140571791304560'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -623,7 +623,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="StarRocks">
|
||||
<div class="attr variable">
|
||||
<span class="name">StarRocks</span> =
|
||||
<span class="default_value"><MagicMock id='140634509005568'></span>
|
||||
<span class="default_value"><MagicMock id='140571795611968'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -635,7 +635,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="Tableau">
|
||||
<div class="attr variable">
|
||||
<span class="name">Tableau</span> =
|
||||
<span class="default_value"><MagicMock id='140634508366016'></span>
|
||||
<span class="default_value"><MagicMock id='140571793529520'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -647,7 +647,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="Teradata">
|
||||
<div class="attr variable">
|
||||
<span class="name">Teradata</span> =
|
||||
<span class="default_value"><MagicMock id='140634494650928'></span>
|
||||
<span class="default_value"><MagicMock id='140571785251376'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -659,7 +659,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="Trino">
|
||||
<div class="attr variable">
|
||||
<span class="name">Trino</span> =
|
||||
<span class="default_value"><MagicMock id='140634494658800'></span>
|
||||
<span class="default_value"><MagicMock id='140571785259248'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -671,7 +671,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="TSQL">
|
||||
<div class="attr variable">
|
||||
<span class="name">TSQL</span> =
|
||||
<span class="default_value"><MagicMock id='140634494683168'></span>
|
||||
<span class="default_value"><MagicMock id='140571785300000'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -683,7 +683,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="Dialect">
|
||||
<div class="attr variable">
|
||||
<span class="name">Dialect</span> =
|
||||
<span class="default_value"><MagicMock id='140634494691088'></span>
|
||||
<span class="default_value"><MagicMock id='140571785307920'></span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -695,7 +695,7 @@ dialect implementations in order to understand how their various components can
|
|||
<section id="Dialects">
|
||||
<div class="attr variable">
|
||||
<span class="name">Dialects</span> =
|
||||
<span class="default_value"><MagicMock id='140634494715456'></span>
|
||||
<span class="default_value"><MagicMock id='140571785332288'></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
|
@ -63337,7 +63337,7 @@ Otherwise, this resets the expressions.</li>
|
|||
<div id="DataType.STRUCT_TYPES" class="classattr">
|
||||
<div class="attr variable">
|
||||
<span class="name">STRUCT_TYPES</span> =
|
||||
<span class="default_value">{<Type.UNION: 'UNION'>, <Type.OBJECT: 'OBJECT'>, <Type.NESTED: 'NESTED'>, <Type.STRUCT: 'STRUCT'>}</span>
|
||||
<span class="default_value">{<Type.NESTED: 'NESTED'>, <Type.UNION: 'UNION'>, <Type.STRUCT: 'STRUCT'>, <Type.OBJECT: 'OBJECT'>}</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -63349,7 +63349,7 @@ Otherwise, this resets the expressions.</li>
|
|||
<div id="DataType.ARRAY_TYPES" class="classattr">
|
||||
<div class="attr variable">
|
||||
<span class="name">ARRAY_TYPES</span> =
|
||||
<span class="default_value">{<Type.LIST: 'LIST'>, <Type.ARRAY: 'ARRAY'>}</span>
|
||||
<span class="default_value">{<Type.ARRAY: 'ARRAY'>, <Type.LIST: 'LIST'>}</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -63362,7 +63362,7 @@ Otherwise, this resets the expressions.</li>
|
|||
<div class="attr variable">
|
||||
<span class="name">NESTED_TYPES</span> =
|
||||
<input id="DataType.NESTED_TYPES-view-value" class="view-value-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
|
||||
<label class="view-value-button pdoc-button" for="DataType.NESTED_TYPES-view-value"></label><span class="default_value">{<Type.MAP: 'MAP'>, <Type.STRUCT: 'STRUCT'>, <Type.LIST: 'LIST'>, <Type.UNION: 'UNION'>, <Type.OBJECT: 'OBJECT'>, <Type.NESTED: 'NESTED'>, <Type.ARRAY: 'ARRAY'>}</span>
|
||||
<label class="view-value-button pdoc-button" for="DataType.NESTED_TYPES-view-value"></label><span class="default_value">{<Type.OBJECT: 'OBJECT'>, <Type.MAP: 'MAP'>, <Type.LIST: 'LIST'>, <Type.NESTED: 'NESTED'>, <Type.UNION: 'UNION'>, <Type.ARRAY: 'ARRAY'>, <Type.STRUCT: 'STRUCT'>}</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -63375,7 +63375,7 @@ Otherwise, this resets the expressions.</li>
|
|||
<div class="attr variable">
|
||||
<span class="name">TEXT_TYPES</span> =
|
||||
<input id="DataType.TEXT_TYPES-view-value" class="view-value-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
|
||||
<label class="view-value-button pdoc-button" for="DataType.TEXT_TYPES-view-value"></label><span class="default_value">{<Type.NAME: 'NAME'>, <Type.VARCHAR: 'VARCHAR'>, <Type.TEXT: 'TEXT'>, <Type.NVARCHAR: 'NVARCHAR'>, <Type.CHAR: 'CHAR'>, <Type.NCHAR: 'NCHAR'>}</span>
|
||||
<label class="view-value-button pdoc-button" for="DataType.TEXT_TYPES-view-value"></label><span class="default_value">{<Type.NAME: 'NAME'>, <Type.NVARCHAR: 'NVARCHAR'>, <Type.VARCHAR: 'VARCHAR'>, <Type.CHAR: 'CHAR'>, <Type.NCHAR: 'NCHAR'>, <Type.TEXT: 'TEXT'>}</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -63388,7 +63388,7 @@ Otherwise, this resets the expressions.</li>
|
|||
<div class="attr variable">
|
||||
<span class="name">SIGNED_INTEGER_TYPES</span> =
|
||||
<input id="DataType.SIGNED_INTEGER_TYPES-view-value" class="view-value-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
|
||||
<label class="view-value-button pdoc-button" for="DataType.SIGNED_INTEGER_TYPES-view-value"></label><span class="default_value">{<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.INT128: 'INT128'>, <Type.INT: 'INT'>, <Type.INT256: 'INT256'>, <Type.BIGINT: 'BIGINT'>, <Type.SMALLINT: 'SMALLINT'>, <Type.TINYINT: 'TINYINT'>}</span>
|
||||
<label class="view-value-button pdoc-button" for="DataType.SIGNED_INTEGER_TYPES-view-value"></label><span class="default_value">{<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.INT128: 'INT128'>, <Type.BIGINT: 'BIGINT'>, <Type.INT256: 'INT256'>, <Type.SMALLINT: 'SMALLINT'>, <Type.INT: 'INT'>, <Type.TINYINT: 'TINYINT'>}</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -63401,7 +63401,7 @@ Otherwise, this resets the expressions.</li>
|
|||
<div class="attr variable">
|
||||
<span class="name">UNSIGNED_INTEGER_TYPES</span> =
|
||||
<input id="DataType.UNSIGNED_INTEGER_TYPES-view-value" class="view-value-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
|
||||
<label class="view-value-button pdoc-button" for="DataType.UNSIGNED_INTEGER_TYPES-view-value"></label><span class="default_value">{<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.USMALLINT: 'USMALLINT'>, <Type.UINT256: 'UINT256'>, <Type.UINT: 'UINT'>, <Type.UINT128: 'UINT128'>, <Type.UTINYINT: 'UTINYINT'>, <Type.UBIGINT: 'UBIGINT'>}</span>
|
||||
<label class="view-value-button pdoc-button" for="DataType.UNSIGNED_INTEGER_TYPES-view-value"></label><span class="default_value">{<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.UINT256: 'UINT256'>, <Type.UINT128: 'UINT128'>, <Type.USMALLINT: 'USMALLINT'>, <Type.UTINYINT: 'UTINYINT'>, <Type.UINT: 'UINT'>, <Type.UBIGINT: 'UBIGINT'>}</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -63414,7 +63414,7 @@ Otherwise, this resets the expressions.</li>
|
|||
<div class="attr variable">
|
||||
<span class="name">INTEGER_TYPES</span> =
|
||||
<input id="DataType.INTEGER_TYPES-view-value" class="view-value-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
|
||||
<label class="view-value-button pdoc-button" for="DataType.INTEGER_TYPES-view-value"></label><span class="default_value">{<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.BIT: 'BIT'>, <Type.INT128: 'INT128'>, <Type.MEDIUMINT: 'MEDIUMINT'>, <Type.UBIGINT: 'UBIGINT'>, <Type.USMALLINT: 'USMALLINT'>, <Type.INT: 'INT'>, <Type.UINT256: 'UINT256'>, <Type.INT256: 'INT256'>, <Type.BIGINT: 'BIGINT'>, <Type.UINT: 'UINT'>, <Type.UINT128: 'UINT128'>, <Type.UTINYINT: 'UTINYINT'>, <Type.SMALLINT: 'SMALLINT'>, <Type.TINYINT: 'TINYINT'>}</span>
|
||||
<label class="view-value-button pdoc-button" for="DataType.INTEGER_TYPES-view-value"></label><span class="default_value">{<Type.UINT: 'UINT'>, <Type.MEDIUMINT: 'MEDIUMINT'>, <Type.INT128: 'INT128'>, <Type.BIT: 'BIT'>, <Type.BIGINT: 'BIGINT'>, <Type.INT256: 'INT256'>, <Type.SMALLINT: 'SMALLINT'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.UINT256: 'UINT256'>, <Type.UINT128: 'UINT128'>, <Type.USMALLINT: 'USMALLINT'>, <Type.UTINYINT: 'UTINYINT'>, <Type.INT: 'INT'>, <Type.UBIGINT: 'UBIGINT'>, <Type.TINYINT: 'TINYINT'>}</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -63439,7 +63439,7 @@ Otherwise, this resets the expressions.</li>
|
|||
<div class="attr variable">
|
||||
<span class="name">REAL_TYPES</span> =
|
||||
<input id="DataType.REAL_TYPES-view-value" class="view-value-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
|
||||
<label class="view-value-button pdoc-button" for="DataType.REAL_TYPES-view-value"></label><span class="default_value">{<Type.DOUBLE: 'DOUBLE'>, <Type.DECIMAL128: 'DECIMAL128'>, <Type.UDOUBLE: 'UDOUBLE'>, <Type.FLOAT: 'FLOAT'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.DECIMAL: 'DECIMAL'>, <Type.DECIMAL64: 'DECIMAL64'>, <Type.UDECIMAL: 'UDECIMAL'>, <Type.SMALLMONEY: 'SMALLMONEY'>, <Type.DECIMAL256: 'DECIMAL256'>, <Type.MONEY: 'MONEY'>, <Type.DECIMAL32: 'DECIMAL32'>}</span>
|
||||
<label class="view-value-button pdoc-button" for="DataType.REAL_TYPES-view-value"></label><span class="default_value">{<Type.DECIMAL256: 'DECIMAL256'>, <Type.MONEY: 'MONEY'>, <Type.DECIMAL32: 'DECIMAL32'>, <Type.DOUBLE: 'DOUBLE'>, <Type.DECIMAL: 'DECIMAL'>, <Type.DECIMAL64: 'DECIMAL64'>, <Type.UDECIMAL: 'UDECIMAL'>, <Type.UDOUBLE: 'UDOUBLE'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.SMALLMONEY: 'SMALLMONEY'>, <Type.FLOAT: 'FLOAT'>, <Type.DECIMAL128: 'DECIMAL128'>}</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -63452,7 +63452,7 @@ Otherwise, this resets the expressions.</li>
|
|||
<div class="attr variable">
|
||||
<span class="name">NUMERIC_TYPES</span> =
|
||||
<input id="DataType.NUMERIC_TYPES-view-value" class="view-value-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
|
||||
<label class="view-value-button pdoc-button" for="DataType.NUMERIC_TYPES-view-value"></label><span class="default_value">{<Type.DOUBLE: 'DOUBLE'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.BIT: 'BIT'>, <Type.DECIMAL64: 'DECIMAL64'>, <Type.UDECIMAL: 'UDECIMAL'>, <Type.INT: 'INT'>, <Type.SMALLMONEY: 'SMALLMONEY'>, <Type.INT256: 'INT256'>, <Type.UINT: 'UINT'>, <Type.UINT128: 'UINT128'>, <Type.MONEY: 'MONEY'>, <Type.UTINYINT: 'UTINYINT'>, <Type.UBIGINT: 'UBIGINT'>, <Type.SMALLINT: 'SMALLINT'>, <Type.TINYINT: 'TINYINT'>, <Type.DECIMAL32: 'DECIMAL32'>, <Type.DECIMAL128: 'DECIMAL128'>, <Type.UDOUBLE: 'UDOUBLE'>, <Type.FLOAT: 'FLOAT'>, <Type.INT128: 'INT128'>, <Type.MEDIUMINT: 'MEDIUMINT'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.USMALLINT: 'USMALLINT'>, <Type.UINT256: 'UINT256'>, <Type.DECIMAL: 'DECIMAL'>, <Type.DECIMAL256: 'DECIMAL256'>, <Type.BIGINT: 'BIGINT'>}</span>
|
||||
<label class="view-value-button pdoc-button" for="DataType.NUMERIC_TYPES-view-value"></label><span class="default_value">{<Type.INT128: 'INT128'>, <Type.BIT: 'BIT'>, <Type.BIGINT: 'BIGINT'>, <Type.DECIMAL32: 'DECIMAL32'>, <Type.UDOUBLE: 'UDOUBLE'>, <Type.UINT: 'UINT'>, <Type.UBIGINT: 'UBIGINT'>, <Type.UDECIMAL: 'UDECIMAL'>, <Type.DECIMAL128: 'DECIMAL128'>, <Type.DECIMAL256: 'DECIMAL256'>, <Type.MEDIUMINT: 'MEDIUMINT'>, <Type.MONEY: 'MONEY'>, <Type.INT256: 'INT256'>, <Type.DOUBLE: 'DOUBLE'>, <Type.SMALLINT: 'SMALLINT'>, <Type.DECIMAL: 'DECIMAL'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.UINT256: 'UINT256'>, <Type.DECIMAL64: 'DECIMAL64'>, <Type.FLOAT: 'FLOAT'>, <Type.UINT128: 'UINT128'>, <Type.USMALLINT: 'USMALLINT'>, <Type.UTINYINT: 'UTINYINT'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.SMALLMONEY: 'SMALLMONEY'>, <Type.INT: 'INT'>, <Type.TINYINT: 'TINYINT'>}</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -63465,7 +63465,7 @@ Otherwise, this resets the expressions.</li>
|
|||
<div class="attr variable">
|
||||
<span class="name">TEMPORAL_TYPES</span> =
|
||||
<input id="DataType.TEMPORAL_TYPES-view-value" class="view-value-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
|
||||
<label class="view-value-button pdoc-button" for="DataType.TEMPORAL_TYPES-view-value"></label><span class="default_value">{<Type.DATETIME2: 'DATETIME2'>, <Type.TIME: 'TIME'>, <Type.TIMETZ: 'TIMETZ'>, <Type.DATE: 'DATE'>, <Type.DATE32: 'DATE32'>, <Type.TIMESTAMPNTZ: 'TIMESTAMPNTZ'>, <Type.TIMESTAMP_MS: 'TIMESTAMP_MS'>, <Type.TIMESTAMP: 'TIMESTAMP'>, <Type.TIMESTAMP_NS: 'TIMESTAMP_NS'>, <Type.DATETIME: 'DATETIME'>, <Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <Type.TIMESTAMP_S: 'TIMESTAMP_S'>, <Type.DATETIME64: 'DATETIME64'>, <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <Type.SMALLDATETIME: 'SMALLDATETIME'>}</span>
|
||||
<label class="view-value-button pdoc-button" for="DataType.TEMPORAL_TYPES-view-value"></label><span class="default_value">{<Type.DATETIME: 'DATETIME'>, <Type.DATETIME2: 'DATETIME2'>, <Type.DATE: 'DATE'>, <Type.DATE32: 'DATE32'>, <Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <Type.DATETIME64: 'DATETIME64'>, <Type.SMALLDATETIME: 'SMALLDATETIME'>, <Type.TIMESTAMP: 'TIMESTAMP'>, <Type.TIMESTAMPNTZ: 'TIMESTAMPNTZ'>, <Type.TIMESTAMP_NS: 'TIMESTAMP_NS'>, <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <Type.TIMETZ: 'TIMETZ'>, <Type.TIMESTAMP_MS: 'TIMESTAMP_MS'>, <Type.TIMESTAMP_S: 'TIMESTAMP_S'>, <Type.TIME: 'TIME'>}</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
|
|
@ -12871,7 +12871,7 @@ Default: True</li>
|
|||
<div id="Generator.PARAMETERIZABLE_TEXT_TYPES" class="classattr">
|
||||
<div class="attr variable">
|
||||
<span class="name">PARAMETERIZABLE_TEXT_TYPES</span> =
|
||||
<span class="default_value">{<Type.NVARCHAR: 'NVARCHAR'>, <Type.CHAR: 'CHAR'>, <Type.VARCHAR: 'VARCHAR'>, <Type.NCHAR: 'NCHAR'>}</span>
|
||||
<span class="default_value">{<Type.VARCHAR: 'VARCHAR'>, <Type.NCHAR: 'NCHAR'>, <Type.NVARCHAR: 'NVARCHAR'>, <Type.CHAR: 'CHAR'>}</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
|
|
@ -2003,7 +2003,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">{'year_month', 'year', 'day', 'month', 'quarter', 'week'}</span>
|
||||
<span class="default_value">{'day', 'year', 'year_month', 'quarter', 'week', 'month'}</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -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">{'kind', 'laterals', 'locks', 'sort', 'limit', 'settings', 'qualify', 'distinct', 'with', 'match', 'pivots', 'having', 'sample', 'windows', 'operation_modifiers', 'offset', 'format', 'cluster', 'connect', 'into', 'options', 'prewhere', 'group', 'distribute'}</span>
|
||||
<label class="view-value-button pdoc-button" for="UNMERGABLE_ARGS-view-value"></label><span class="default_value">{'options', 'qualify', 'group', 'locks', 'having', 'prewhere', 'kind', 'offset', 'cluster', 'distinct', 'operation_modifiers', 'settings', 'windows', 'limit', 'match', 'into', 'laterals', 'distribute', 'format', 'sample', 'connect', 'with', 'sort', 'pivots'}</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
|
|
@ -3285,7 +3285,7 @@ prefix are statically known.</p>
|
|||
<section id="JOINS">
|
||||
<div class="attr variable">
|
||||
<span class="name">JOINS</span> =
|
||||
<span class="default_value">{('RIGHT', ''), ('', 'INNER'), ('RIGHT', 'OUTER'), ('', '')}</span>
|
||||
<span class="default_value">{('', ''), ('RIGHT', 'OUTER'), ('RIGHT', ''), ('', 'INNER')}</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -9516,7 +9516,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">{<<a href="#TokenType.INSERT">TokenType.INSERT</a>: 'INSERT'>, <<a href="#TokenType.DELETE">TokenType.DELETE</a>: 'DELETE'>, <<a href="#TokenType.UPDATE">TokenType.UPDATE</a>: 'UPDATE'>, <<a href="#TokenType.SELECT">TokenType.SELECT</a>: 'SELECT'>}</span>
|
||||
<label class="view-value-button pdoc-button" for="Tokenizer.TOKENS_PRECEDING_HINT-view-value"></label><span class="default_value">{<<a href="#TokenType.SELECT">TokenType.SELECT</a>: 'SELECT'>, <<a href="#TokenType.INSERT">TokenType.INSERT</a>: 'INSERT'>, <<a href="#TokenType.UPDATE">TokenType.UPDATE</a>: 'UPDATE'>, <<a href="#TokenType.DELETE">TokenType.DELETE</a>: 'DELETE'>}</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -9555,7 +9555,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">{<<a href="#TokenType.FETCH">TokenType.FETCH</a>: 'FETCH'>, <<a href="#TokenType.COMMAND">TokenType.COMMAND</a>: 'COMMAND'>, <<a href="#TokenType.SHOW">TokenType.SHOW</a>: 'SHOW'>, <<a href="#TokenType.EXECUTE">TokenType.EXECUTE</a>: 'EXECUTE'>, <<a href="#TokenType.RENAME">TokenType.RENAME</a>: 'RENAME'>}</span>
|
||||
<label class="view-value-button pdoc-button" for="Tokenizer.COMMANDS-view-value"></label><span class="default_value">{<<a href="#TokenType.EXECUTE">TokenType.EXECUTE</a>: 'EXECUTE'>, <<a href="#TokenType.SHOW">TokenType.SHOW</a>: 'SHOW'>, <<a href="#TokenType.RENAME">TokenType.RENAME</a>: 'RENAME'>, <<a href="#TokenType.COMMAND">TokenType.COMMAND</a>: 'COMMAND'>, <<a href="#TokenType.FETCH">TokenType.FETCH</a>: 'FETCH'>}</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
|
|
@ -525,6 +525,16 @@ class BigQuery(Dialect):
|
|||
LOG_DEFAULTS_TO_LN = True
|
||||
SUPPORTS_IMPLICIT_UNNEST = True
|
||||
|
||||
# BigQuery does not allow ASC/DESC to be used as an identifier
|
||||
ID_VAR_TOKENS = parser.Parser.ID_VAR_TOKENS - {TokenType.ASC, TokenType.DESC}
|
||||
ALIAS_TOKENS = parser.Parser.ALIAS_TOKENS - {TokenType.ASC, TokenType.DESC}
|
||||
TABLE_ALIAS_TOKENS = parser.Parser.TABLE_ALIAS_TOKENS - {TokenType.ASC, TokenType.DESC}
|
||||
COMMENT_TABLE_ALIAS_TOKENS = parser.Parser.COMMENT_TABLE_ALIAS_TOKENS - {
|
||||
TokenType.ASC,
|
||||
TokenType.DESC,
|
||||
}
|
||||
UPDATE_ALIAS_TOKENS = parser.Parser.UPDATE_ALIAS_TOKENS - {TokenType.ASC, TokenType.DESC}
|
||||
|
||||
FUNCTIONS = {
|
||||
**parser.Parser.FUNCTIONS,
|
||||
"CONTAINS_SUBSTR": _build_contains_substring,
|
||||
|
|
|
@ -1096,6 +1096,7 @@ class ClickHouse(Dialect):
|
|||
exp.RegexpLike: lambda self, e: self.func("match", e.this, e.expression),
|
||||
exp.Rand: rename_func("randCanonical"),
|
||||
exp.StartsWith: rename_func("startsWith"),
|
||||
exp.EndsWith: rename_func("endsWith"),
|
||||
exp.StrPosition: lambda self, e: strposition_sql(
|
||||
self,
|
||||
e,
|
||||
|
|
|
@ -36,6 +36,7 @@ from sqlglot.dialects.dialect import (
|
|||
strposition_sql,
|
||||
count_if_to_sum,
|
||||
groupconcat_sql,
|
||||
Version,
|
||||
)
|
||||
from sqlglot.generator import unsupported_args
|
||||
from sqlglot.helper import is_int, seq_get
|
||||
|
@ -255,6 +256,15 @@ def _levenshtein_sql(self: Postgres.Generator, expression: exp.Levenshtein) -> s
|
|||
return rename_func(name)(self, expression)
|
||||
|
||||
|
||||
def _versioned_anyvalue_sql(self: Postgres.Generator, expression: exp.AnyValue) -> str:
|
||||
# https://www.postgresql.org/docs/16/functions-aggregate.html
|
||||
# https://www.postgresql.org/about/featurematrix/
|
||||
if self.dialect.version < Version("16.0"):
|
||||
return any_value_to_max_sql(self, expression)
|
||||
|
||||
return rename_func("ANY_VALUE")(self, expression)
|
||||
|
||||
|
||||
class Postgres(Dialect):
|
||||
INDEX_OFFSET = 1
|
||||
TYPED_DIVISION = True
|
||||
|
@ -546,7 +556,7 @@ class Postgres(Dialect):
|
|||
|
||||
TRANSFORMS = {
|
||||
**generator.Generator.TRANSFORMS,
|
||||
exp.AnyValue: any_value_to_max_sql,
|
||||
exp.AnyValue: _versioned_anyvalue_sql,
|
||||
exp.ArrayConcat: lambda self, e: self.arrayconcat_sql(e, name="ARRAY_CAT"),
|
||||
exp.ArrayFilter: filter_array_using_unnest,
|
||||
exp.BitwiseXor: lambda self, e: self.binary(e, "#"),
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from __future__ import annotations
|
||||
from sqlglot.dialects.postgres import Postgres
|
||||
from sqlglot.generator import Generator
|
||||
from sqlglot.tokens import TokenType
|
||||
import typing as t
|
||||
|
||||
|
@ -72,3 +73,6 @@ class RisingWave(Postgres):
|
|||
}
|
||||
|
||||
EXPRESSION_PRECEDES_PROPERTIES_CREATABLES = {"SINK"}
|
||||
|
||||
def computedcolumnconstraint_sql(self, expression: exp.ComputedColumnConstraint) -> str:
|
||||
return Generator.computedcolumnconstraint_sql(self, expression)
|
||||
|
|
|
@ -1019,6 +1019,7 @@ class Snowflake(Dialect):
|
|||
exp.ArgMin: rename_func("MIN_BY"),
|
||||
exp.ArrayConcat: lambda self, e: self.arrayconcat_sql(e, name="ARRAY_CAT"),
|
||||
exp.ArrayContains: lambda self, e: self.func("ARRAY_CONTAINS", e.expression, e.this),
|
||||
exp.ArrayIntersect: rename_func("ARRAY_INTERSECTION"),
|
||||
exp.AtTimeZone: lambda self, e: self.func(
|
||||
"CONVERT_TIMEZONE", e.args.get("zone"), e.this
|
||||
),
|
||||
|
@ -1094,11 +1095,13 @@ class Snowflake(Dialect):
|
|||
exp.SHA: rename_func("SHA1"),
|
||||
exp.StarMap: rename_func("OBJECT_CONSTRUCT"),
|
||||
exp.StartsWith: rename_func("STARTSWITH"),
|
||||
exp.EndsWith: rename_func("ENDSWITH"),
|
||||
exp.StrPosition: lambda self, e: strposition_sql(
|
||||
self, e, func_name="CHARINDEX", supports_position=True
|
||||
),
|
||||
exp.StrToDate: lambda self, e: self.func("DATE", e.this, self.format_time(e)),
|
||||
exp.Stuff: rename_func("INSERT"),
|
||||
exp.StPoint: rename_func("ST_MAKEPOINT"),
|
||||
exp.TimeAdd: date_delta_sql("TIMEADD"),
|
||||
exp.Timestamp: no_timestamp_sql,
|
||||
exp.TimestampAdd: date_delta_sql("TIMESTAMPADD"),
|
||||
|
|
|
@ -163,6 +163,7 @@ class Spark(Spark2):
|
|||
move_partitioned_by_to_schema_columns,
|
||||
]
|
||||
),
|
||||
exp.EndsWith: rename_func("ENDSWITH"),
|
||||
exp.PartitionedByProperty: lambda self,
|
||||
e: f"PARTITIONED BY {self.wrap(self.expressions(sqls=[_normalize_partition(e) for e in e.this.expressions], skip_first=True))}",
|
||||
exp.StartsWith: rename_func("STARTSWITH"),
|
||||
|
|
|
@ -99,6 +99,8 @@ class SQLite(Dialect):
|
|||
KEYWORDS = tokens.Tokenizer.KEYWORDS.copy()
|
||||
KEYWORDS.pop("/*+")
|
||||
|
||||
COMMANDS = {*tokens.Tokenizer.COMMANDS, TokenType.REPLACE}
|
||||
|
||||
class Parser(parser.Parser):
|
||||
FUNCTIONS = {
|
||||
**parser.Parser.FUNCTIONS,
|
||||
|
@ -307,3 +309,10 @@ class SQLite(Dialect):
|
|||
@unsupported_args("this")
|
||||
def currentschema_sql(self, expression: exp.CurrentSchema) -> str:
|
||||
return "'main'"
|
||||
|
||||
def ignorenulls_sql(self, expression: exp.IgnoreNulls) -> str:
|
||||
self.unsupported("SQLite does not support IGNORE NULLS.")
|
||||
return self.sql(expression.this)
|
||||
|
||||
def respectnulls_sql(self, expression: exp.RespectNulls) -> str:
|
||||
return self.sql(expression.this)
|
||||
|
|
|
@ -17,6 +17,19 @@ from sqlglot.helper import seq_get
|
|||
from sqlglot.tokens import TokenType
|
||||
|
||||
|
||||
# https://docs.starrocks.io/docs/sql-reference/sql-functions/spatial-functions/st_distance_sphere/
|
||||
def st_distance_sphere(self, expression: exp.StDistance) -> str:
|
||||
point1 = expression.this
|
||||
point2 = expression.expression
|
||||
|
||||
point1_x = self.func("ST_X", point1)
|
||||
point1_y = self.func("ST_Y", point1)
|
||||
point2_x = self.func("ST_X", point2)
|
||||
point2_y = self.func("ST_Y", point2)
|
||||
|
||||
return self.func("ST_Distance_Sphere", point1_x, point1_y, point2_x, point2_y)
|
||||
|
||||
|
||||
class StarRocks(MySQL):
|
||||
STRICT_JSON_PATH_SYNTAX = False
|
||||
|
||||
|
@ -132,6 +145,8 @@ class StarRocks(MySQL):
|
|||
TRANSFORMS = {
|
||||
**MySQL.Generator.TRANSFORMS,
|
||||
exp.Array: inline_array_sql,
|
||||
exp.ArrayAgg: rename_func("ARRAY_AGG"),
|
||||
exp.ArrayFilter: rename_func("ARRAY_FILTER"),
|
||||
exp.ArrayToString: rename_func("ARRAY_JOIN"),
|
||||
exp.ApproxDistinct: approx_count_distinct_sql,
|
||||
exp.DateDiff: lambda self, e: self.func(
|
||||
|
@ -141,12 +156,12 @@ class StarRocks(MySQL):
|
|||
exp.JSONExtract: arrow_json_extract_sql,
|
||||
exp.Property: property_sql,
|
||||
exp.RegexpLike: rename_func("REGEXP"),
|
||||
exp.StDistance: st_distance_sphere,
|
||||
exp.StrToUnix: lambda self, e: self.func("UNIX_TIMESTAMP", e.this, self.format_time(e)),
|
||||
exp.TimestampTrunc: lambda self, e: self.func("DATE_TRUNC", unit_to_str(e), e.this),
|
||||
exp.TimeStrToDate: rename_func("TO_DATE"),
|
||||
exp.UnixToStr: lambda self, e: self.func("FROM_UNIXTIME", e.this, self.format_time(e)),
|
||||
exp.UnixToTime: rename_func("FROM_UNIXTIME"),
|
||||
exp.ArrayFilter: rename_func("ARRAY_FILTER"),
|
||||
}
|
||||
|
||||
TRANSFORMS.pop(exp.DateTrunc)
|
||||
|
|
|
@ -31,6 +31,7 @@ from sqlglot.helper import (
|
|||
ensure_collection,
|
||||
ensure_list,
|
||||
seq_get,
|
||||
split_num_words,
|
||||
subclasses,
|
||||
to_bool,
|
||||
)
|
||||
|
@ -1993,11 +1994,6 @@ class OnUpdateColumnConstraint(ColumnConstraintKind):
|
|||
pass
|
||||
|
||||
|
||||
# https://docs.snowflake.com/en/sql-reference/sql/create-external-table#optional-parameters
|
||||
class TransformColumnConstraint(ColumnConstraintKind):
|
||||
pass
|
||||
|
||||
|
||||
class PrimaryKeyColumnConstraint(ColumnConstraintKind):
|
||||
arg_types = {"desc": False, "options": False}
|
||||
|
||||
|
@ -5570,6 +5566,21 @@ class ArrayToString(Func):
|
|||
_sql_names = ["ARRAY_TO_STRING", "ARRAY_JOIN"]
|
||||
|
||||
|
||||
class ArrayIntersect(Func):
|
||||
arg_types = {"expressions": True}
|
||||
is_var_len_args = True
|
||||
_sql_names = ["ARRAY_INTERSECT", "ARRAY_INTERSECTION"]
|
||||
|
||||
|
||||
class StPoint(Func):
|
||||
arg_types = {"this": True, "expression": True, "null": False}
|
||||
_sql_names = ["ST_POINT", "ST_MAKEPOINT"]
|
||||
|
||||
|
||||
class StDistance(Func):
|
||||
arg_types = {"this": True, "expression": True, "use_spheroid": False}
|
||||
|
||||
|
||||
# https://cloud.google.com/bigquery/docs/reference/standard-sql/timestamp_functions#string
|
||||
class String(Func):
|
||||
arg_types = {"this": True, "zone": False}
|
||||
|
@ -6706,6 +6717,11 @@ class StartsWith(Func):
|
|||
arg_types = {"this": True, "expression": True}
|
||||
|
||||
|
||||
class EndsWith(Func):
|
||||
_sql_names = ["ENDS_WITH", "ENDSWITH"]
|
||||
arg_types = {"this": True, "expression": True}
|
||||
|
||||
|
||||
class StrPosition(Func):
|
||||
arg_types = {
|
||||
"this": True,
|
||||
|
@ -7366,7 +7382,7 @@ def _apply_set_operation(
|
|||
**opts,
|
||||
) -> S:
|
||||
return reduce(
|
||||
lambda x, y: set_operation(this=x, expression=y, distinct=distinct),
|
||||
lambda x, y: set_operation(this=x, expression=y, distinct=distinct, **opts),
|
||||
(maybe_parse(e, dialect=dialect, copy=copy, **opts) for e in expressions),
|
||||
)
|
||||
|
||||
|
@ -7962,7 +7978,15 @@ def to_table(
|
|||
if isinstance(sql_path, Table):
|
||||
return maybe_copy(sql_path, copy=copy)
|
||||
|
||||
try:
|
||||
table = maybe_parse(sql_path, into=Table, dialect=dialect)
|
||||
except ParseError:
|
||||
catalog, db, this = split_num_words(sql_path, ".", 3)
|
||||
|
||||
if not this:
|
||||
raise
|
||||
|
||||
table = table_(this, db=db, catalog=catalog)
|
||||
|
||||
for k, v in kwargs.items():
|
||||
table.set(k, v)
|
||||
|
@ -8110,7 +8134,7 @@ def column(
|
|||
|
||||
@t.overload
|
||||
def column(
|
||||
col: str | Identifier,
|
||||
col: str | Identifier | Star,
|
||||
table: t.Optional[str | Identifier] = None,
|
||||
db: t.Optional[str | Identifier] = None,
|
||||
catalog: t.Optional[str | Identifier] = None,
|
||||
|
@ -8147,8 +8171,11 @@ def column(
|
|||
Returns:
|
||||
The new Column instance.
|
||||
"""
|
||||
if not isinstance(col, Star):
|
||||
col = to_identifier(col, quoted=quoted, copy=copy)
|
||||
|
||||
this = Column(
|
||||
this=to_identifier(col, quoted=quoted, copy=copy),
|
||||
this=col,
|
||||
table=to_identifier(table, quoted=quoted, copy=copy),
|
||||
db=to_identifier(db, quoted=quoted, copy=copy),
|
||||
catalog=to_identifier(catalog, quoted=quoted, copy=copy),
|
||||
|
|
|
@ -1018,6 +1018,7 @@ class Generator(metaclass=_Generator):
|
|||
persisted = " PERSISTED"
|
||||
else:
|
||||
persisted = ""
|
||||
|
||||
return f"AS {this}{persisted}"
|
||||
|
||||
def autoincrementcolumnconstraint_sql(self, _) -> str:
|
||||
|
@ -1079,9 +1080,6 @@ class Generator(metaclass=_Generator):
|
|||
def notnullcolumnconstraint_sql(self, expression: exp.NotNullColumnConstraint) -> str:
|
||||
return f"{'' if expression.args.get('allow_null') else 'NOT '}NULL"
|
||||
|
||||
def transformcolumnconstraint_sql(self, expression: exp.TransformColumnConstraint) -> str:
|
||||
return f"AS {self.sql(expression, 'this')}"
|
||||
|
||||
def primarykeycolumnconstraint_sql(self, expression: exp.PrimaryKeyColumnConstraint) -> str:
|
||||
desc = expression.args.get("desc")
|
||||
if desc is not None:
|
||||
|
|
|
@ -936,6 +936,7 @@ class Parser(metaclass=_Parser):
|
|||
"ORDER BY": lambda self, query: query.order_by(self._parse_order(), copy=False),
|
||||
"LIMIT": lambda self, query: self._parse_pipe_syntax_limit(query),
|
||||
"OFFSET": lambda self, query: query.offset(self._parse_offset(), copy=False),
|
||||
"AGGREGATE": lambda self, query: self._parse_pipe_syntax_aggregate(query),
|
||||
}
|
||||
|
||||
PROPERTY_PARSERS: t.Dict[str, t.Callable] = {
|
||||
|
@ -1143,6 +1144,78 @@ class Parser(metaclass=_Parser):
|
|||
query.offset(offset, copy=False)
|
||||
return query
|
||||
|
||||
def _parse_pipe_syntax_aggregate_fields(self) -> t.Optional[exp.Expression]:
|
||||
this = self._parse_assignment()
|
||||
if self._match_text_seq("GROUP", "AND", advance=False):
|
||||
return this
|
||||
|
||||
this = self._parse_alias(this)
|
||||
|
||||
if self._match_set((TokenType.ASC, TokenType.DESC), advance=False):
|
||||
return self._parse_ordered(lambda: this)
|
||||
|
||||
return this
|
||||
|
||||
def _parse_pipe_syntax_aggregate_group_order_by(
|
||||
self, query: exp.Query, group_by_exists: bool = True
|
||||
) -> exp.Query:
|
||||
expr = self._parse_csv(self._parse_pipe_syntax_aggregate_fields)
|
||||
aggregates_or_groups, orders = [], []
|
||||
for element in expr:
|
||||
if isinstance(element, exp.Ordered):
|
||||
this = element.this
|
||||
if isinstance(this, exp.Alias):
|
||||
element.set("this", this.args["alias"])
|
||||
orders.append(element)
|
||||
else:
|
||||
this = element
|
||||
aggregates_or_groups.append(this)
|
||||
|
||||
if group_by_exists and isinstance(query, exp.Select):
|
||||
query = query.select(*aggregates_or_groups, copy=False).group_by(
|
||||
*[element.args.get("alias", element) for element in aggregates_or_groups],
|
||||
copy=False,
|
||||
)
|
||||
else:
|
||||
query = exp.select(*aggregates_or_groups, copy=False).from_(
|
||||
query.subquery(copy=False), copy=False
|
||||
)
|
||||
|
||||
if orders:
|
||||
return query.order_by(*orders, copy=False)
|
||||
|
||||
return query
|
||||
|
||||
def _parse_pipe_syntax_aggregate(self, query: exp.Query) -> exp.Query:
|
||||
self._match_text_seq("AGGREGATE")
|
||||
query = self._parse_pipe_syntax_aggregate_group_order_by(query, group_by_exists=False)
|
||||
|
||||
if self._match(TokenType.GROUP_BY) or (
|
||||
self._match_text_seq("GROUP", "AND") and self._match(TokenType.ORDER_BY)
|
||||
):
|
||||
return self._parse_pipe_syntax_aggregate_group_order_by(query)
|
||||
|
||||
return query
|
||||
|
||||
def _parse_pipe_syntax_set_operator(
|
||||
self, query: t.Optional[exp.Query]
|
||||
) -> t.Optional[exp.Query]:
|
||||
first_setop = self.parse_set_operation(this=query)
|
||||
|
||||
if not first_setop or not query:
|
||||
return None
|
||||
|
||||
first_setop.this.pop()
|
||||
distinct = first_setop.args.pop("distinct")
|
||||
|
||||
setops = [first_setop.expression.pop(), *self._parse_expressions()]
|
||||
|
||||
if isinstance(first_setop, exp.Union):
|
||||
return query.union(*setops, distinct=distinct, **first_setop.args)
|
||||
if isinstance(first_setop, exp.Except):
|
||||
return query.except_(*setops, distinct=distinct, **first_setop.args)
|
||||
return query.intersect(*setops, distinct=distinct, **first_setop.args)
|
||||
|
||||
def _parse_partitioned_by_bucket_or_truncate(self) -> exp.Expression:
|
||||
klass = (
|
||||
exp.PartitionedByBucket
|
||||
|
@ -5900,7 +5973,7 @@ class Parser(metaclass=_Parser):
|
|||
constraints.append(
|
||||
self.expression(
|
||||
exp.ColumnConstraint,
|
||||
kind=exp.TransformColumnConstraint(this=self._parse_disjunction()),
|
||||
kind=exp.ComputedColumnConstraint(this=self._parse_disjunction()),
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -7163,11 +7236,18 @@ class Parser(metaclass=_Parser):
|
|||
|
||||
return this
|
||||
|
||||
def _parse_pipe_syntax_query(self, query: exp.Select) -> exp.Query:
|
||||
def _parse_pipe_syntax_query(self, query: exp.Query) -> t.Optional[exp.Query]:
|
||||
while self._match(TokenType.PIPE_GT):
|
||||
start = self._curr
|
||||
parser = self.PIPE_SYNTAX_TRANSFORM_PARSERS.get(self._curr.text.upper())
|
||||
if not parser:
|
||||
self.raise_error(f"Unsupported pipe syntax operator: '{self._curr.text.upper()}'.")
|
||||
set_op_query = self._parse_pipe_syntax_set_operator(query)
|
||||
if not set_op_query:
|
||||
self._retreat(start)
|
||||
self.raise_error(f"Unsupported pipe syntax operator: '{start.text.upper()}'.")
|
||||
break
|
||||
|
||||
query = set_op_query
|
||||
else:
|
||||
query = parser(self, query)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::settings::TokenType;
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::{PyList, PyString};
|
||||
use pyo3::{pyclass, Py, PyObject, Python};
|
||||
use pyo3::{pyclass, pymethods, Py, PyObject, Python};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[pyclass]
|
||||
|
@ -57,3 +57,25 @@ impl Token {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl Token {
|
||||
fn __repr__(&self, py: Python) -> PyResult<String> {
|
||||
let text = self.text.bind(py).to_str()?;
|
||||
let comments = self.comments.bind(py);
|
||||
let token_type_str = self.token_type_py.bind(py).str()?;
|
||||
let comments_repr = comments.repr()?;
|
||||
let comments_str = comments_repr.to_str()?;
|
||||
|
||||
Ok(format!(
|
||||
"<Token token_type: {}, text: {}, line: {}, col: {}, start: {}, end: {}, comments: {}>",
|
||||
token_type_str,
|
||||
text,
|
||||
self.line,
|
||||
self.col,
|
||||
self.start,
|
||||
self.end,
|
||||
comments_str
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -462,6 +462,16 @@ class TestDialect(Validator):
|
|||
"CAST('127.0.0.1/32' AS INET)",
|
||||
read={"postgres": "INET '127.0.0.1/32'"},
|
||||
)
|
||||
self.assertIsNotNone(
|
||||
self.validate_identity("CREATE TABLE foo (bar INT AS (foo))").find(
|
||||
exp.ComputedColumnConstraint
|
||||
)
|
||||
)
|
||||
self.assertIsNotNone(
|
||||
self.validate_identity(
|
||||
"CREATE TABLE foo (t1 INT, t2 INT, bar INT AS (t1 * t2 * 2))"
|
||||
).find(exp.ComputedColumnConstraint)
|
||||
)
|
||||
|
||||
def test_ddl(self):
|
||||
self.validate_all(
|
||||
|
@ -1304,6 +1314,32 @@ class TestDialect(Validator):
|
|||
},
|
||||
)
|
||||
|
||||
self.validate_all(
|
||||
"ARRAY_INTERSECT(x, y)",
|
||||
read={
|
||||
"hive": "ARRAY_INTERSECT(x, y)",
|
||||
"spark2": "ARRAY_INTERSECT(x, y)",
|
||||
"spark": "ARRAY_INTERSECT(x, y)",
|
||||
"databricks": "ARRAY_INTERSECT(x, y)",
|
||||
"presto": "ARRAY_INTERSECT(x, y)",
|
||||
"trino": "ARRAY_INTERSECT(x, y)",
|
||||
"snowflake": "ARRAY_INTERSECTION(x, y)",
|
||||
"starrocks": "ARRAY_INTERSECT(x, y)",
|
||||
},
|
||||
write={
|
||||
"hive": "ARRAY_INTERSECT(x, y)",
|
||||
"spark2": "ARRAY_INTERSECT(x, y)",
|
||||
"spark": "ARRAY_INTERSECT(x, y)",
|
||||
"databricks": "ARRAY_INTERSECT(x, y)",
|
||||
"presto": "ARRAY_INTERSECT(x, y)",
|
||||
"trino": "ARRAY_INTERSECT(x, y)",
|
||||
"snowflake": "ARRAY_INTERSECTION(x, y)",
|
||||
"starrocks": "ARRAY_INTERSECT(x, y)",
|
||||
},
|
||||
)
|
||||
|
||||
self.validate_identity("SELECT ARRAY_INTERSECT(x, y, z)")
|
||||
|
||||
def test_order_by(self):
|
||||
self.validate_identity(
|
||||
"SELECT c FROM t ORDER BY a, b,",
|
||||
|
@ -3528,3 +3564,81 @@ FROM subquery2""",
|
|||
f"FROM x |> SELECT x1, x2 |> WHERE x1 > 0 |> WHERE x2 > 0 |> ORDER BY x1, x2 |> {option}",
|
||||
f"SELECT x1, x2 FROM (SELECT * FROM x) WHERE x1 > 0 AND x2 > 0 ORDER BY x1, x2 {option}",
|
||||
)
|
||||
self.validate_identity(
|
||||
"FROM x |> AGGREGATE SUM(x1), MAX(x2), MIN(x3)",
|
||||
"SELECT SUM(x1), MAX(x2), MIN(x3) FROM (SELECT * FROM x)",
|
||||
)
|
||||
self.validate_identity(
|
||||
"FROM x |> AGGREGATE SUM(x1) AS s_x1 |> SELECT s_x1",
|
||||
"SELECT s_x1 FROM (SELECT SUM(x1) AS s_x1 FROM (SELECT * FROM x))",
|
||||
)
|
||||
self.validate_identity(
|
||||
"FROM x |> AGGREGATE SUM(x1), MAX(x2), MIN(x3) GROUP BY x4, x5",
|
||||
"SELECT SUM(x1), MAX(x2), MIN(x3), x4, x5 FROM (SELECT * FROM x) GROUP BY x4, x5",
|
||||
)
|
||||
self.validate_identity(
|
||||
"FROM x |> AGGREGATE SUM(x1), MAX(x2), MIN(x3) GROUP BY x4 AS a_x4, x5 AS a_x5",
|
||||
"SELECT SUM(x1), MAX(x2), MIN(x3), x4 AS a_x4, x5 AS a_x5 FROM (SELECT * FROM x) GROUP BY a_x4, a_x5",
|
||||
)
|
||||
self.validate_identity(
|
||||
"FROM x |> AGGREGATE SUM(x1) as s_x1 GROUP BY x1 |> SELECT s_x1, x1 as ss_x1",
|
||||
"SELECT s_x1, x1 AS ss_x1 FROM (SELECT SUM(x1) AS s_x1, x1 FROM (SELECT * FROM x) GROUP BY x1)",
|
||||
)
|
||||
self.validate_identity(
|
||||
"FROM x |> AGGREGATE SUM(x1) GROUP", "SELECT SUM(x1) AS GROUP FROM (SELECT * FROM x)"
|
||||
)
|
||||
for order_option in ("ASC", "DESC", "ASC NULLS LAST", "DESC NULLS FIRST"):
|
||||
with self.subTest(f"Testing pipe syntax AGGREGATE for order option: {order_option}"):
|
||||
self.validate_all(
|
||||
f"SELECT SUM(x1) AS x_s FROM (SELECT * FROM x) ORDER BY x_s {order_option}",
|
||||
read={
|
||||
"bigquery": f"FROM x |> AGGREGATE SUM(x1) AS x_s {order_option}",
|
||||
},
|
||||
)
|
||||
self.validate_all(
|
||||
f"SELECT SUM(x1) AS x_s, x1 AS g_x1 FROM (SELECT * FROM x) GROUP BY g_x1 ORDER BY x_s {order_option}",
|
||||
read={
|
||||
"bigquery": f"FROM x |> AGGREGATE SUM(x1) AS x_s {order_option} GROUP BY x1 AS g_x1",
|
||||
},
|
||||
)
|
||||
with self.subTest(
|
||||
f"Testing pipe syntax AGGREGATE with GROUP AND ORDER BY for order option: {order_option}"
|
||||
):
|
||||
self.validate_all(
|
||||
f"SELECT g_x1, x_s FROM (SELECT SUM(x1) AS x_s, x1 AS g_x1 FROM (SELECT * FROM x) GROUP BY g_x1 ORDER BY g_x1 {order_option})",
|
||||
read={
|
||||
"bigquery": f"FROM x |> AGGREGATE SUM(x1) AS x_s GROUP AND ORDER BY x1 AS g_x1 {order_option} |> SELECT g_x1, x_s",
|
||||
},
|
||||
)
|
||||
|
||||
for op_operator in (
|
||||
"UNION ALL",
|
||||
"UNION DISTINCT",
|
||||
"INTERSECT DISTINCT",
|
||||
"EXCEPT DISTINCT",
|
||||
):
|
||||
with self.subTest(f"Testing pipe syntax SET OPERATORS: {op_operator}"):
|
||||
self.validate_all(
|
||||
f"FROM x|> {op_operator} (SELECT y1 FROM y), (SELECT z1 FROM z)",
|
||||
write={
|
||||
"bigquery": f"SELECT * FROM x {op_operator} (SELECT y1 FROM y) {op_operator} (SELECT z1 FROM z)",
|
||||
},
|
||||
)
|
||||
|
||||
for op_prefix in ("LEFT OUTER", "FULL OUTER"):
|
||||
for op_operator in (
|
||||
"UNION ALL",
|
||||
"UNION DISTINCT",
|
||||
"INTERSECT DISTINCT",
|
||||
"EXCEPT DISTINCT",
|
||||
):
|
||||
for suffix_operator in ("BY NAME", "CORRESPONDING"):
|
||||
with self.subTest(
|
||||
f"Testing pipe syntax SET OPERATORS: {op_prefix} {op_operator} {suffix_operator}"
|
||||
):
|
||||
self.validate_all(
|
||||
f"FROM x|> SELECT x1, x2 FROM x |> {op_prefix} {op_operator} {suffix_operator} (SELECT y1, y2 FROM y), (SELECT z1, z2 FROM z)",
|
||||
write={
|
||||
"bigquery": f"SELECT x1, x2 FROM (SELECT * FROM x) {op_prefix} {op_operator} BY NAME (SELECT y1, y2 FROM y) {op_prefix} {op_operator} BY NAME (SELECT z1, z2 FROM z)",
|
||||
},
|
||||
)
|
||||
|
|
|
@ -9,13 +9,6 @@ class TestDuckDB(Validator):
|
|||
dialect = "duckdb"
|
||||
|
||||
def test_duckdb(self):
|
||||
self.validate_identity("SELECT * FROM my_ducklake.demo AT (VERSION => 2)")
|
||||
self.validate_identity("SELECT UUIDV7()")
|
||||
self.validate_identity("SELECT TRY(LOG(0))")
|
||||
self.validate_identity("x::timestamp", "CAST(x AS TIMESTAMP)")
|
||||
self.validate_identity("x::timestamp without time zone", "CAST(x AS TIMESTAMP)")
|
||||
self.validate_identity("x::timestamp with time zone", "CAST(x AS TIMESTAMPTZ)")
|
||||
|
||||
with self.assertRaises(ParseError):
|
||||
parse_one("1 //", read="duckdb")
|
||||
|
||||
|
@ -36,6 +29,20 @@ class TestDuckDB(Validator):
|
|||
"STRUCT(k TEXT, v STRUCT(v_str TEXT, v_int INT, v_int_arr INT[]))[]",
|
||||
)
|
||||
|
||||
self.validate_all(
|
||||
"SELECT FIRST_VALUE(c IGNORE NULLS) OVER (PARTITION BY gb ORDER BY ob) FROM t",
|
||||
write={
|
||||
"duckdb": "SELECT FIRST_VALUE(c IGNORE NULLS) OVER (PARTITION BY gb ORDER BY ob) FROM t",
|
||||
"sqlite": UnsupportedError,
|
||||
},
|
||||
)
|
||||
self.validate_all(
|
||||
"SELECT FIRST_VALUE(c RESPECT NULLS) OVER (PARTITION BY gb ORDER BY ob) FROM t",
|
||||
write={
|
||||
"duckdb": "SELECT FIRST_VALUE(c RESPECT NULLS) OVER (PARTITION BY gb ORDER BY ob) FROM t",
|
||||
"sqlite": "SELECT FIRST_VALUE(c) OVER (PARTITION BY gb ORDER BY ob NULLS LAST) FROM t",
|
||||
},
|
||||
)
|
||||
self.validate_all(
|
||||
"CAST(x AS UUID)",
|
||||
write={
|
||||
|
@ -264,6 +271,12 @@ class TestDuckDB(Validator):
|
|||
parse_one("a // b", read="duckdb").assert_is(exp.IntDiv).sql(dialect="duckdb"), "a // b"
|
||||
)
|
||||
|
||||
self.validate_identity("SELECT * FROM my_ducklake.demo AT (VERSION => 2)")
|
||||
self.validate_identity("SELECT UUIDV7()")
|
||||
self.validate_identity("SELECT TRY(LOG(0))")
|
||||
self.validate_identity("x::timestamp", "CAST(x AS TIMESTAMP)")
|
||||
self.validate_identity("x::timestamp without time zone", "CAST(x AS TIMESTAMP)")
|
||||
self.validate_identity("x::timestamp with time zone", "CAST(x AS TIMESTAMPTZ)")
|
||||
self.validate_identity("CAST(x AS FOO)")
|
||||
self.validate_identity("SELECT UNNEST([1, 2])").selects[0].assert_is(exp.UDTF)
|
||||
self.validate_identity("'red' IN flags").args["field"].assert_is(exp.Column)
|
||||
|
|
|
@ -22,6 +22,7 @@ class TestPostgres(Validator):
|
|||
expected_sql = "ARRAY[\n x" + (",\n x" * 27) + "\n]"
|
||||
self.validate_identity(sql, expected_sql, pretty=True)
|
||||
|
||||
self.validate_identity("SELECT ST_DISTANCE(gg1, gg2, FALSE) AS sphere_dist")
|
||||
self.validate_identity("SHA384(x)")
|
||||
self.validate_identity("1.x", "1. AS x")
|
||||
self.validate_identity("|/ x", "SQRT(x)")
|
||||
|
@ -908,6 +909,18 @@ FROM json_data, field_ids""",
|
|||
},
|
||||
)
|
||||
|
||||
# Postgres introduced ANY_VALUE in version 16
|
||||
self.validate_all(
|
||||
"SELECT ANY_VALUE(1) AS col",
|
||||
write={
|
||||
"postgres": "SELECT ANY_VALUE(1) AS col",
|
||||
"postgres, version=16": "SELECT ANY_VALUE(1) AS col",
|
||||
"postgres, version=17.5": "SELECT ANY_VALUE(1) AS col",
|
||||
"postgres, version=15": "SELECT MAX(1) AS col",
|
||||
"postgres, version=13.9": "SELECT MAX(1) AS col",
|
||||
},
|
||||
)
|
||||
|
||||
def test_ddl(self):
|
||||
# Checks that user-defined types are parsed into DataType instead of Identifier
|
||||
self.parse_one("CREATE TABLE t (a udt)").this.expressions[0].args["kind"].assert_is(
|
||||
|
|
|
@ -778,7 +778,7 @@ class TestPresto(Validator):
|
|||
"hive": "FIRST(x)",
|
||||
"mysql": "ANY_VALUE(x)",
|
||||
"oracle": "ANY_VALUE(x)",
|
||||
"postgres": "MAX(x)",
|
||||
"postgres": "ANY_VALUE(x)",
|
||||
"presto": "ARBITRARY(x)",
|
||||
"redshift": "ANY_VALUE(x)",
|
||||
"snowflake": "ANY_VALUE(x)",
|
||||
|
|
|
@ -318,6 +318,13 @@ class TestSnowflake(Validator):
|
|||
"SELECT * FROM xxx, yyy, zzz",
|
||||
)
|
||||
|
||||
self.validate_all(
|
||||
"SELECT ARRAY_INTERSECTION([1, 2], [2, 3])",
|
||||
write={
|
||||
"starrocks": "SELECT ARRAY_INTERSECT([1, 2], [2, 3])",
|
||||
},
|
||||
)
|
||||
|
||||
self.validate_all(
|
||||
"CREATE TABLE test_table (id NUMERIC NOT NULL AUTOINCREMENT)",
|
||||
write={
|
||||
|
@ -1079,6 +1086,22 @@ class TestSnowflake(Validator):
|
|||
},
|
||||
)
|
||||
|
||||
self.validate_all(
|
||||
"SELECT ST_MAKEPOINT(10, 20)",
|
||||
write={
|
||||
"snowflake": "SELECT ST_MAKEPOINT(10, 20)",
|
||||
"starrocks": "SELECT ST_POINT(10, 20)",
|
||||
},
|
||||
)
|
||||
|
||||
self.validate_all(
|
||||
"SELECT ST_DISTANCE(a, b)",
|
||||
write={
|
||||
"snowflake": "SELECT ST_DISTANCE(a, b)",
|
||||
"starrocks": "SELECT ST_DISTANCE_SPHERE(ST_X(a), ST_Y(a), ST_X(b), ST_Y(b))",
|
||||
},
|
||||
)
|
||||
|
||||
def test_null_treatment(self):
|
||||
self.validate_all(
|
||||
r"SELECT FIRST_VALUE(TABLE1.COLUMN1) OVER (PARTITION BY RANDOM_COLUMN1, RANDOM_COLUMN2 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS MY_ALIAS FROM TABLE1",
|
||||
|
@ -1687,12 +1710,6 @@ class TestSnowflake(Validator):
|
|||
},
|
||||
)
|
||||
|
||||
self.assertIsNotNone(
|
||||
self.validate_identity("CREATE TABLE foo (bar INT AS (foo))").find(
|
||||
exp.TransformColumnConstraint
|
||||
)
|
||||
)
|
||||
|
||||
def test_user_defined_functions(self):
|
||||
self.validate_all(
|
||||
"CREATE FUNCTION a(x DATE, y BIGINT) RETURNS ARRAY LANGUAGE JAVASCRIPT AS $$ SELECT 1 $$",
|
||||
|
@ -2013,6 +2030,26 @@ FROM persons AS p, LATERAL FLATTEN(input => p.c, path => 'contact') AS _flattene
|
|||
"spark": "DESCRIBE db.table",
|
||||
},
|
||||
)
|
||||
self.validate_all(
|
||||
"ENDSWITH('abc', 'c')",
|
||||
read={
|
||||
"bigquery": "ENDS_WITH('abc', 'c')",
|
||||
"clickhouse": "endsWith('abc', 'c')",
|
||||
"databricks": "ENDSWITH('abc', 'c')",
|
||||
"duckdb": "ENDS_WITH('abc', 'c')",
|
||||
"presto": "ENDS_WITH('abc', 'c')",
|
||||
"spark": "ENDSWITH('abc', 'c')",
|
||||
},
|
||||
write={
|
||||
"bigquery": "ENDS_WITH('abc', 'c')",
|
||||
"clickhouse": "endsWith('abc', 'c')",
|
||||
"databricks": "ENDSWITH('abc', 'c')",
|
||||
"duckdb": "ENDS_WITH('abc', 'c')",
|
||||
"presto": "ENDS_WITH('abc', 'c')",
|
||||
"snowflake": "ENDSWITH('abc', 'c')",
|
||||
"spark": "ENDSWITH('abc', 'c')",
|
||||
},
|
||||
)
|
||||
|
||||
def test_parse_like_any(self):
|
||||
like = parse_one("a LIKE ANY fun('foo')", read="snowflake")
|
||||
|
|
|
@ -113,6 +113,7 @@ class TestSQLite(Validator):
|
|||
'CREATE TABLE "foo t" ("foo t id" TEXT NOT NULL, PRIMARY KEY ("foo t id"))',
|
||||
'CREATE TABLE "foo t" ("foo t id" TEXT NOT NULL PRIMARY KEY)',
|
||||
)
|
||||
self.validate_identity("REPLACE INTO foo (x, y) VALUES (1, 2)", check_command_warning=True)
|
||||
|
||||
def test_strftime(self):
|
||||
self.validate_identity("SELECT STRFTIME('%Y/%m/%d', 'now')")
|
||||
|
|
|
@ -9,6 +9,9 @@ class TestStarrocks(Validator):
|
|||
self.validate_identity("SELECT ARRAY_JOIN([1, 3, 5, NULL], '_', 'NULL')")
|
||||
self.validate_identity("SELECT ARRAY_JOIN([1, 3, 5, NULL], '_')")
|
||||
self.validate_identity("ALTER TABLE a SWAP WITH b")
|
||||
self.validate_identity("SELECT ARRAY_AGG(a) FROM x")
|
||||
self.validate_identity("SELECT ST_POINT(10, 20)")
|
||||
self.validate_identity("SELECT ST_DISTANCE_SPHERE(10.1, 20.2, 30.3, 40.4)")
|
||||
|
||||
def test_ddl(self):
|
||||
ddl_sqls = [
|
||||
|
|
|
@ -669,6 +669,8 @@ class TestExpressions(unittest.TestCase):
|
|||
self.assertIsInstance(parse_one("ARRAY_AGG(a)"), exp.ArrayAgg)
|
||||
self.assertIsInstance(parse_one("ARRAY_CONTAINS(a, 'a')"), exp.ArrayContains)
|
||||
self.assertIsInstance(parse_one("ARRAY_SIZE(a)"), exp.ArraySize)
|
||||
self.assertIsInstance(parse_one("ARRAY_INTERSECTION([1, 2], [2, 3])"), exp.ArrayIntersect)
|
||||
self.assertIsInstance(parse_one("ARRAY_INTERSECT([1, 2], [2, 3])"), exp.ArrayIntersect)
|
||||
self.assertIsInstance(parse_one("AVG(a)"), exp.Avg)
|
||||
self.assertIsInstance(parse_one("BEGIN DEFERRED TRANSACTION"), exp.Transaction)
|
||||
self.assertIsInstance(parse_one("CEIL(a)"), exp.Ceil)
|
||||
|
@ -710,6 +712,8 @@ class TestExpressions(unittest.TestCase):
|
|||
self.assertIsInstance(parse_one("ROUND(a)"), exp.Round)
|
||||
self.assertIsInstance(parse_one("ROUND(a, 2)"), exp.Round)
|
||||
self.assertIsInstance(parse_one("SPLIT(a, 'test')"), exp.Split)
|
||||
self.assertIsInstance(parse_one("ST_POINT(10, 20)"), exp.StPoint)
|
||||
self.assertIsInstance(parse_one("ST_DISTANCE(a, b)"), exp.StDistance)
|
||||
self.assertIsInstance(parse_one("STR_POSITION(a, 'test')"), exp.StrPosition)
|
||||
self.assertIsInstance(parse_one("STR_TO_UNIX(a, 'format')"), exp.StrToUnix)
|
||||
self.assertIsInstance(parse_one("STRUCT_EXTRACT(a, 'test')"), exp.StructExtract)
|
||||
|
@ -752,6 +756,9 @@ class TestExpressions(unittest.TestCase):
|
|||
self.assertIsInstance(parse_one("ADD_MONTHS(a, b)"), exp.AddMonths)
|
||||
|
||||
def test_column(self):
|
||||
column = exp.column(exp.Star(), table="t")
|
||||
self.assertEqual(column.sql(), "t.*")
|
||||
|
||||
column = parse_one("a.b.c.d")
|
||||
self.assertEqual(column.catalog, "a")
|
||||
self.assertEqual(column.db, "b")
|
||||
|
@ -987,15 +994,20 @@ FROM foo""",
|
|||
self.assertEqual(table_only.name, "table_name")
|
||||
self.assertIsNone(table_only.args.get("db"))
|
||||
self.assertIsNone(table_only.args.get("catalog"))
|
||||
|
||||
db_and_table = exp.to_table("db.table_name")
|
||||
self.assertEqual(db_and_table.name, "table_name")
|
||||
self.assertEqual(db_and_table.args.get("db"), exp.to_identifier("db"))
|
||||
self.assertIsNone(db_and_table.args.get("catalog"))
|
||||
|
||||
catalog_db_and_table = exp.to_table("catalog.db.table_name")
|
||||
self.assertEqual(catalog_db_and_table.name, "table_name")
|
||||
self.assertEqual(catalog_db_and_table.args.get("db"), exp.to_identifier("db"))
|
||||
self.assertEqual(catalog_db_and_table.args.get("catalog"), exp.to_identifier("catalog"))
|
||||
|
||||
table_only_unsafe_identifier = exp.to_table("3e")
|
||||
self.assertEqual(table_only_unsafe_identifier.sql(), '"3e"')
|
||||
|
||||
def test_to_column(self):
|
||||
column_only = exp.to_column("column_name")
|
||||
self.assertEqual(column_only.name, "column_name")
|
||||
|
|
|
@ -201,3 +201,10 @@ x"""
|
|||
self.assertEqual(len(partial_tokens), 1)
|
||||
self.assertEqual(partial_tokens[0].token_type, TokenType.VAR)
|
||||
self.assertEqual(partial_tokens[0].text, "foo")
|
||||
|
||||
def test_token_repr(self):
|
||||
# Ensures both the Python and the Rust tokenizer produce a human-friendly representation
|
||||
self.assertEqual(
|
||||
repr(Tokenizer().tokenize("foo")),
|
||||
"[<Token token_type: TokenType.VAR, text: foo, line: 1, col: 3, start: 0, end: 2, comments: []>]",
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue