Adding upstream version 26.25.3.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
bc7749846c
commit
d9e621c994
83 changed files with 67317 additions and 67680 deletions
78
.github/workflows/benchmark-sqlglot.yml
vendored
Normal file
78
.github/workflows/benchmark-sqlglot.yml
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
name: Benchmark pull requests
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created, edited, deleted]
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
jobs:
|
||||
run-benchmark:
|
||||
name: run benchmark
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
(github.event_name == 'issue_comment' &&
|
||||
contains(github.event.comment.body, '/benchmark') &&
|
||||
github.event.issue.pull_request) ||
|
||||
(github.event_name == 'pull_request' &&
|
||||
contains(github.event.pull_request.body, '/benchmark'))
|
||||
steps:
|
||||
- name: Checkout PR branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Needed to fetch main branch too
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.13
|
||||
- name: Create a virtual environment
|
||||
run: |
|
||||
python -m venv .venv
|
||||
source ./.venv/bin/activate
|
||||
python -m pip install --upgrade pip
|
||||
pip install pyperf
|
||||
- name: Run benchmark on PR branch
|
||||
run: |
|
||||
source ./.venv/bin/activate
|
||||
make install-dev
|
||||
make install-dev-rs-release
|
||||
python benchmarks/parse.py --quiet --output bench_parse_pr.json
|
||||
python benchmarks/optimize.py --quiet --fast --output bench_optimize_pr.json
|
||||
- name: Checkout main branch into subdir
|
||||
run: |
|
||||
git fetch origin main
|
||||
git worktree add main-branch origin/main
|
||||
- name: Reset virtual environment
|
||||
run: |
|
||||
rm -rf .venv
|
||||
python -m venv .venv
|
||||
source ./.venv/bin/activate
|
||||
python -m pip install --upgrade pip
|
||||
pip install pyperf
|
||||
- name: Run benchmark on main branch
|
||||
run: |
|
||||
source ./.venv/bin/activate
|
||||
cd main-branch
|
||||
make install-dev
|
||||
make install-dev-rs-release
|
||||
python benchmarks/parse.py --quiet --output ../bench_parse_main.json
|
||||
python benchmarks/optimize.py --quiet --fast --output ../bench_optimize_main.json
|
||||
cd ..
|
||||
- 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
|
||||
- name: Combine benchmark outputs
|
||||
run: |
|
||||
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
|
||||
cat bench_optimize_comparison.txt >> combined_benchmarks.md
|
||||
- name: Comment on PR for parse benchmark results
|
||||
uses: peter-evans/create-or-update-comment@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number || github.event.pull_request.number }}
|
||||
body-file: combined_benchmarks.md
|
|
@ -1,8 +1,10 @@
|
|||
name: Benchmark Rust tokenizer changes
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'sqlglotrs/**'
|
||||
name: benchmark pull requests
|
||||
|
||||
jobs:
|
||||
run-benchmark:
|
||||
name: run benchmark
|
|
@ -1,4 +1,4 @@
|
|||
name: Publish Python Release to PyPI
|
||||
name: Publish sqlglot and sqlglotrs to PyPI
|
||||
|
||||
on:
|
||||
push:
|
|
@ -1,20 +1,21 @@
|
|||
name: Test and Lint Python Package
|
||||
name: Run tests and linter checks
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
run-checks:
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: pip
|
||||
|
@ -26,7 +27,7 @@ jobs:
|
|||
source ./.venv/bin/activate
|
||||
python -m pip install --upgrade pip
|
||||
make install-dev
|
||||
- name: Run checks (linter, code style, tests)
|
||||
- name: Run tests and linter checks
|
||||
run: |
|
||||
source ./.venv/bin/activate
|
||||
make check
|
2257
CHANGELOG.md
2257
CHANGELOG.md
File diff suppressed because it is too large
Load diff
|
@ -1,28 +0,0 @@
|
|||
import typing as t
|
||||
|
||||
|
||||
def border(columns: t.Iterable[str]) -> str:
|
||||
columns = " | ".join(columns)
|
||||
return f"| {columns} |"
|
||||
|
||||
|
||||
def ascii_table(table: list[dict[str, t.Any]]) -> str:
|
||||
columns = []
|
||||
for row in table:
|
||||
for key in row:
|
||||
if key not in columns:
|
||||
columns.append(key)
|
||||
|
||||
widths = {column: max(len(column), 15) for column in columns}
|
||||
|
||||
lines = [
|
||||
border(column.rjust(width) for column, width in widths.items()),
|
||||
border(str("-" * width) for width in widths.values()),
|
||||
]
|
||||
|
||||
for row in table:
|
||||
lines.append(
|
||||
border(str(row[column]).rjust(width)[0:width] for column, width in widths.items())
|
||||
)
|
||||
|
||||
return "\n".join(lines)
|
|
@ -1,12 +1,13 @@
|
|||
import sys
|
||||
import typing as t
|
||||
from argparse import ArgumentParser
|
||||
import os
|
||||
import pyperf
|
||||
|
||||
# Add the project root to the path so we can import from tests
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from benchmarks.helpers import ascii_table
|
||||
from sqlglot.optimizer import optimize
|
||||
from sqlglot import parse_one
|
||||
from tests.helpers import load_sql_fixture_pairs, TPCH_SCHEMA, TPCDS_SCHEMA
|
||||
from timeit import Timer
|
||||
|
||||
# Deeply nested conditions currently require a lot of recursion
|
||||
sys.setrecursionlimit(10000)
|
||||
|
@ -16,55 +17,56 @@ def gen_condition(n):
|
|||
return parse_one(" OR ".join(f"a = {i} AND b = {i}" for i in range(n)))
|
||||
|
||||
|
||||
BENCHMARKS = {
|
||||
"tpch": lambda: (
|
||||
# Create benchmark functions that return the setup data
|
||||
def get_tpch_setup():
|
||||
return (
|
||||
[parse_one(sql) for _, sql, _ in load_sql_fixture_pairs("optimizer/tpc-h/tpc-h.sql")],
|
||||
TPCH_SCHEMA,
|
||||
3,
|
||||
),
|
||||
"tpcds": lambda: (
|
||||
)
|
||||
|
||||
|
||||
def get_tpcds_setup():
|
||||
return (
|
||||
[parse_one(sql) for _, sql, _ in load_sql_fixture_pairs("optimizer/tpc-ds/tpc-ds.sql")],
|
||||
TPCDS_SCHEMA,
|
||||
3,
|
||||
),
|
||||
"condition_10": lambda: (
|
||||
[gen_condition(10)],
|
||||
{},
|
||||
10,
|
||||
),
|
||||
"condition_100": lambda: (
|
||||
[gen_condition(100)],
|
||||
{},
|
||||
10,
|
||||
),
|
||||
"condition_1000": lambda: (
|
||||
[gen_condition(1000)],
|
||||
{},
|
||||
3,
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def bench() -> list[dict[str, t.Any]]:
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument("-b", "--benchmark", choices=BENCHMARKS, action="append")
|
||||
args = parser.parse_args()
|
||||
benchmarks = list(args.benchmark or BENCHMARKS)
|
||||
def get_condition_10_setup():
|
||||
return ([gen_condition(10)], {})
|
||||
|
||||
table = []
|
||||
for benchmark in benchmarks:
|
||||
expressions, schema, n = BENCHMARKS[benchmark]()
|
||||
|
||||
def func():
|
||||
def get_condition_100_setup():
|
||||
return ([gen_condition(100)], {})
|
||||
|
||||
|
||||
def get_condition_1000_setup():
|
||||
return ([gen_condition(1000)], {})
|
||||
|
||||
|
||||
# Optimizer functions that will be benchmarked
|
||||
def optimize_queries(expressions, schema):
|
||||
for e in expressions:
|
||||
optimize(e, schema)
|
||||
|
||||
timer = Timer(func)
|
||||
min_duration = min(timer.repeat(repeat=n, number=1))
|
||||
table.append({"Benchmark": benchmark, "Duration (s)": round(min_duration, 4)})
|
||||
|
||||
return table
|
||||
def run_benchmarks():
|
||||
runner = pyperf.Runner()
|
||||
|
||||
# Define benchmarks with their setup functions
|
||||
benchmarks = {
|
||||
"tpch": get_tpch_setup,
|
||||
# "tpcds": get_tpcds_setup, # This is left out because it's too slow in CI
|
||||
"condition_10": get_condition_10_setup,
|
||||
"condition_100": get_condition_100_setup,
|
||||
"condition_1000": get_condition_1000_setup,
|
||||
}
|
||||
|
||||
for benchmark_name, benchmark_setup in benchmarks.items():
|
||||
expressions, schema = benchmark_setup()
|
||||
|
||||
runner.bench_func(f"optimize_{benchmark_name}", optimize_queries, expressions, schema)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(ascii_table(bench()))
|
||||
run_benchmarks()
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
import collections.abc
|
||||
|
||||
from benchmarks.helpers import ascii_table
|
||||
import pyperf
|
||||
|
||||
# moz_sql_parser 3.10 compatibility
|
||||
collections.Iterable = collections.abc.Iterable
|
||||
import timeit
|
||||
|
||||
import numpy as np
|
||||
|
||||
# import sqlfluff
|
||||
# import moz_sql_parser
|
||||
|
@ -56,7 +52,7 @@ ORDER BY
|
|||
"e"."employee_id"
|
||||
"""
|
||||
|
||||
short = "select 1 as a, case when 1 then 1 when 2 then 2 else 3 end as b, c from x"
|
||||
short = "SELECT 1 AS a, CASE WHEN 1 THEN 1 WHEN 2 THEN 2 ELSE 3 END AS b, c FROM x"
|
||||
|
||||
crazy = "SELECT 1+"
|
||||
crazy += "+".join(str(i) for i in range(500))
|
||||
|
@ -190,41 +186,20 @@ def sqlfluff_parse(sql):
|
|||
sqlfluff.parse(sql)
|
||||
|
||||
|
||||
def diff(row, column):
|
||||
if column == "Query":
|
||||
return ""
|
||||
column = row[column]
|
||||
if isinstance(column, str):
|
||||
return " (N/A)"
|
||||
return f" ({str(column / row['sqlglot'])[0:5]})"
|
||||
QUERIES = {"tpch": tpch, "short": short, "long": long, "crazy": crazy}
|
||||
|
||||
|
||||
libs = [
|
||||
"sqlglot",
|
||||
"sqlglotrs",
|
||||
# "sqlfluff",
|
||||
# "sqltree",
|
||||
# "sqlparse",
|
||||
# "moz_sql_parser",
|
||||
# "sqloxide",
|
||||
]
|
||||
table = []
|
||||
def run_benchmarks():
|
||||
runner = pyperf.Runner()
|
||||
|
||||
for name, sql in {"tpch": tpch, "short": short, "long": long, "crazy": crazy}.items():
|
||||
row = {"Query": name}
|
||||
table.append(row)
|
||||
libs = ["sqlglot", "sqlglotrs"]
|
||||
for lib in libs:
|
||||
try:
|
||||
row[lib] = np.mean(timeit.repeat(lambda: globals()[lib + "_parse"](sql), number=3))
|
||||
except Exception as e:
|
||||
print(e)
|
||||
row[lib] = "error"
|
||||
for query_name, sql in QUERIES.items():
|
||||
bench_name = f"parse_{lib}_{query_name}"
|
||||
parse_func = globals()[f"{lib}_parse"]
|
||||
|
||||
print(
|
||||
ascii_table(
|
||||
[
|
||||
{k: v if v == "Query" else str(row[k])[0:7] + diff(row, k) for k, v in row.items()}
|
||||
for row in table
|
||||
]
|
||||
)
|
||||
)
|
||||
runner.bench_func(bench_name, parse_func, sql)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_benchmarks()
|
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.23.0'</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">23</span><span class="p">,</span> <span class="mi">0</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.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></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.23.0'</span>
|
||||
<span class="default_value">'26.25.2'</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, 23, 0)</span>
|
||||
<span class="default_value">(26, 25, 2)</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.23.0'</span>
|
||||
<span class="default_value">'26.25.2'</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, 23, 0)</span>
|
||||
<span class="default_value">(26, 25, 2)</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='139904393074608'></span>
|
||||
<span class="default_value"><MagicMock id='140634507837104'></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='139904406061312'></span>
|
||||
<span class="default_value"><MagicMock id='140634507824912'></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='139904391016128'></span>
|
||||
<span class="default_value"><MagicMock id='140634506710896'></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='139904405693408'></span>
|
||||
<span class="default_value"><MagicMock id='140634506014208'></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='139904405691728'></span>
|
||||
<span class="default_value"><MagicMock id='140634502703680'></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='139904402062592'></span>
|
||||
<span class="default_value"><MagicMock id='140634506225040'></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='139904389006720'></span>
|
||||
<span class="default_value"><MagicMock id='140634506216304'></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='139904389011808'></span>
|
||||
<span class="default_value"><MagicMock id='140634494301136'></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='139904405826688'></span>
|
||||
<span class="default_value"><MagicMock id='140634505383792'></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='139904397287840'></span>
|
||||
<span class="default_value"><MagicMock id='140634502237920'></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='139904407772256'></span>
|
||||
<span class="default_value"><MagicMock id='140634509349440'></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='139904405858928'></span>
|
||||
<span class="default_value"><MagicMock id='140634507150432'></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='139904401435536'></span>
|
||||
<span class="default_value"><MagicMock id='140634496723616'></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='139904406312352'></span>
|
||||
<span class="default_value"><MagicMock id='140634496715216'></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='139904406604816'></span>
|
||||
<span class="default_value"><MagicMock id='140634508955024'></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='139904406615424'></span>
|
||||
<span class="default_value"><MagicMock id='140634507747792'></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='139904401186272'></span>
|
||||
<span class="default_value"><MagicMock id='140634504908416'></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='139904401188912'></span>
|
||||
<span class="default_value"><MagicMock id='140634504916624'></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='139904405754480'></span>
|
||||
<span class="default_value"><MagicMock id='140634507238688'></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='139904405919904'></span>
|
||||
<span class="default_value"><MagicMock id='140634507369712'></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='139904406383936'></span>
|
||||
<span class="default_value"><MagicMock id='140634506022528'></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='139904406386960'></span>
|
||||
<span class="default_value"><MagicMock id='140634506023632'></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='139904391390896'></span>
|
||||
<span class="default_value"><MagicMock id='140634509005568'></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='139904396179488'></span>
|
||||
<span class="default_value"><MagicMock id='140634508366016'></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='139904389318016'></span>
|
||||
<span class="default_value"><MagicMock id='140634494650928'></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='139904389325888'></span>
|
||||
<span class="default_value"><MagicMock id='140634494658800'></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='139904389333872'></span>
|
||||
<span class="default_value"><MagicMock id='140634494683168'></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='139904389341792'></span>
|
||||
<span class="default_value"><MagicMock id='140634494691088'></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='139904389366160'></span>
|
||||
<span class="default_value"><MagicMock id='140634494715456'></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
|
@ -739,6 +739,7 @@ Default: True</li>
|
|||
<dd id="Druid.Generator.SUPPORTS_CONVERT_TIMEZONE" class="variable"><a href="../generator.html#Generator.SUPPORTS_CONVERT_TIMEZONE">SUPPORTS_CONVERT_TIMEZONE</a></dd>
|
||||
<dd id="Druid.Generator.SUPPORTS_MEDIAN" class="variable"><a href="../generator.html#Generator.SUPPORTS_MEDIAN">SUPPORTS_MEDIAN</a></dd>
|
||||
<dd id="Druid.Generator.SUPPORTS_UNIX_SECONDS" class="variable"><a href="../generator.html#Generator.SUPPORTS_UNIX_SECONDS">SUPPORTS_UNIX_SECONDS</a></dd>
|
||||
<dd id="Druid.Generator.ALTER_SET_WRAPPED" class="variable"><a href="../generator.html#Generator.ALTER_SET_WRAPPED">ALTER_SET_WRAPPED</a></dd>
|
||||
<dd id="Druid.Generator.PARSE_JSON_NAME" class="variable"><a href="../generator.html#Generator.PARSE_JSON_NAME">PARSE_JSON_NAME</a></dd>
|
||||
<dd id="Druid.Generator.ARRAY_SIZE_NAME" class="variable"><a href="../generator.html#Generator.ARRAY_SIZE_NAME">ARRAY_SIZE_NAME</a></dd>
|
||||
<dd id="Druid.Generator.ALTER_SET_TYPE" class="variable"><a href="../generator.html#Generator.ALTER_SET_TYPE">ALTER_SET_TYPE</a></dd>
|
||||
|
@ -756,6 +757,7 @@ Default: True</li>
|
|||
<dd id="Druid.Generator.UNWRAPPED_INTERVAL_VALUES" class="variable"><a href="../generator.html#Generator.UNWRAPPED_INTERVAL_VALUES">UNWRAPPED_INTERVAL_VALUES</a></dd>
|
||||
<dd id="Druid.Generator.PARAMETERIZABLE_TEXT_TYPES" class="variable"><a href="../generator.html#Generator.PARAMETERIZABLE_TEXT_TYPES">PARAMETERIZABLE_TEXT_TYPES</a></dd>
|
||||
<dd id="Druid.Generator.EXPRESSIONS_WITHOUT_NESTED_CTES" class="variable"><a href="../generator.html#Generator.EXPRESSIONS_WITHOUT_NESTED_CTES">EXPRESSIONS_WITHOUT_NESTED_CTES</a></dd>
|
||||
<dd id="Druid.Generator.RESPECT_IGNORE_NULLS_UNSUPPORTED_EXPRESSIONS" class="variable"><a href="../generator.html#Generator.RESPECT_IGNORE_NULLS_UNSUPPORTED_EXPRESSIONS">RESPECT_IGNORE_NULLS_UNSUPPORTED_EXPRESSIONS</a></dd>
|
||||
<dd id="Druid.Generator.SENTINEL_LINE_BREAK" class="variable"><a href="../generator.html#Generator.SENTINEL_LINE_BREAK">SENTINEL_LINE_BREAK</a></dd>
|
||||
<dd id="Druid.Generator.pretty" class="variable"><a href="../generator.html#Generator.pretty">pretty</a></dd>
|
||||
<dd id="Druid.Generator.identify" class="variable"><a href="../generator.html#Generator.identify">identify</a></dd>
|
||||
|
@ -774,7 +776,7 @@ Default: True</li>
|
|||
<dd id="Druid.Generator.unsupported" class="function"><a href="../generator.html#Generator.unsupported">unsupported</a></dd>
|
||||
<dd id="Druid.Generator.sep" class="function"><a href="../generator.html#Generator.sep">sep</a></dd>
|
||||
<dd id="Druid.Generator.seg" class="function"><a href="../generator.html#Generator.seg">seg</a></dd>
|
||||
<dd id="Druid.Generator.pad_comment" class="function"><a href="../generator.html#Generator.pad_comment">pad_comment</a></dd>
|
||||
<dd id="Druid.Generator.sanitize_comment" class="function"><a href="../generator.html#Generator.sanitize_comment">sanitize_comment</a></dd>
|
||||
<dd id="Druid.Generator.maybe_comment" class="function"><a href="../generator.html#Generator.maybe_comment">maybe_comment</a></dd>
|
||||
<dd id="Druid.Generator.wrap" class="function"><a href="../generator.html#Generator.wrap">wrap</a></dd>
|
||||
<dd id="Druid.Generator.no_identify" class="function"><a href="../generator.html#Generator.no_identify">no_identify</a></dd>
|
||||
|
@ -909,6 +911,7 @@ Default: True</li>
|
|||
<dd id="Druid.Generator.matchrecognize_sql" class="function"><a href="../generator.html#Generator.matchrecognize_sql">matchrecognize_sql</a></dd>
|
||||
<dd id="Druid.Generator.query_modifiers" class="function"><a href="../generator.html#Generator.query_modifiers">query_modifiers</a></dd>
|
||||
<dd id="Druid.Generator.options_modifier" class="function"><a href="../generator.html#Generator.options_modifier">options_modifier</a></dd>
|
||||
<dd id="Druid.Generator.for_modifiers" class="function"><a href="../generator.html#Generator.for_modifiers">for_modifiers</a></dd>
|
||||
<dd id="Druid.Generator.queryoption_sql" class="function"><a href="../generator.html#Generator.queryoption_sql">queryoption_sql</a></dd>
|
||||
<dd id="Druid.Generator.offset_limit_modifiers" class="function"><a href="../generator.html#Generator.offset_limit_modifiers">offset_limit_modifiers</a></dd>
|
||||
<dd id="Druid.Generator.after_limit_modifiers" class="function"><a href="../generator.html#Generator.after_limit_modifiers">after_limit_modifiers</a></dd>
|
||||
|
@ -1142,6 +1145,7 @@ Default: True</li>
|
|||
<dd id="Druid.Generator.encodeproperty_sql" class="function"><a href="../generator.html#Generator.encodeproperty_sql">encodeproperty_sql</a></dd>
|
||||
<dd id="Druid.Generator.includeproperty_sql" class="function"><a href="../generator.html#Generator.includeproperty_sql">includeproperty_sql</a></dd>
|
||||
<dd id="Druid.Generator.xmlelement_sql" class="function"><a href="../generator.html#Generator.xmlelement_sql">xmlelement_sql</a></dd>
|
||||
<dd id="Druid.Generator.xmlkeyvalueoption_sql" class="function"><a href="../generator.html#Generator.xmlkeyvalueoption_sql">xmlkeyvalueoption_sql</a></dd>
|
||||
<dd id="Druid.Generator.partitionbyrangeproperty_sql" class="function"><a href="../generator.html#Generator.partitionbyrangeproperty_sql">partitionbyrangeproperty_sql</a></dd>
|
||||
<dd id="Druid.Generator.partitionbyrangepropertydynamic_sql" class="function"><a href="../generator.html#Generator.partitionbyrangepropertydynamic_sql">partitionbyrangepropertydynamic_sql</a></dd>
|
||||
<dd id="Druid.Generator.unpivotcolumns_sql" class="function"><a href="../generator.html#Generator.unpivotcolumns_sql">unpivotcolumns_sql</a></dd>
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -590,7 +590,6 @@
|
|||
<dd id="Dune.Tokenizer.HEREDOC_TAG_IS_IDENTIFIER" class="variable"><a href="../tokens.html#Tokenizer.HEREDOC_TAG_IS_IDENTIFIER">HEREDOC_TAG_IS_IDENTIFIER</a></dd>
|
||||
<dd id="Dune.Tokenizer.HEREDOC_STRING_ALTERNATIVE" class="variable"><a href="../tokens.html#Tokenizer.HEREDOC_STRING_ALTERNATIVE">HEREDOC_STRING_ALTERNATIVE</a></dd>
|
||||
<dd id="Dune.Tokenizer.STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS" class="variable"><a href="../tokens.html#Tokenizer.STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS">STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS</a></dd>
|
||||
<dd id="Dune.Tokenizer.NESTED_COMMENTS" class="variable"><a href="../tokens.html#Tokenizer.NESTED_COMMENTS">NESTED_COMMENTS</a></dd>
|
||||
<dd id="Dune.Tokenizer.HINT_START" class="variable"><a href="../tokens.html#Tokenizer.HINT_START">HINT_START</a></dd>
|
||||
<dd id="Dune.Tokenizer.TOKENS_PRECEDING_HINT" class="variable"><a href="../tokens.html#Tokenizer.TOKENS_PRECEDING_HINT">TOKENS_PRECEDING_HINT</a></dd>
|
||||
<dd id="Dune.Tokenizer.WHITE_SPACE" class="variable"><a href="../tokens.html#Tokenizer.WHITE_SPACE">WHITE_SPACE</a></dd>
|
||||
|
@ -610,6 +609,7 @@
|
|||
</div>
|
||||
<div><dt><a href="presto.html#Presto.Tokenizer">sqlglot.dialects.presto.Presto.Tokenizer</a></dt>
|
||||
<dd id="Dune.Tokenizer.UNICODE_STRINGS" class="variable"><a href="presto.html#Presto.Tokenizer.UNICODE_STRINGS">UNICODE_STRINGS</a></dd>
|
||||
<dd id="Dune.Tokenizer.NESTED_COMMENTS" class="variable"><a href="presto.html#Presto.Tokenizer.NESTED_COMMENTS">NESTED_COMMENTS</a></dd>
|
||||
<dd id="Dune.Tokenizer.KEYWORDS" class="variable"><a href="presto.html#Presto.Tokenizer.KEYWORDS">KEYWORDS</a></dd>
|
||||
|
||||
</div>
|
||||
|
@ -798,6 +798,7 @@ Default: True</li>
|
|||
<dd id="Dune.Generator.ARRAY_CONCAT_IS_VAR_LEN" class="variable"><a href="../generator.html#Generator.ARRAY_CONCAT_IS_VAR_LEN">ARRAY_CONCAT_IS_VAR_LEN</a></dd>
|
||||
<dd id="Dune.Generator.SUPPORTS_CONVERT_TIMEZONE" class="variable"><a href="../generator.html#Generator.SUPPORTS_CONVERT_TIMEZONE">SUPPORTS_CONVERT_TIMEZONE</a></dd>
|
||||
<dd id="Dune.Generator.SUPPORTS_UNIX_SECONDS" class="variable"><a href="../generator.html#Generator.SUPPORTS_UNIX_SECONDS">SUPPORTS_UNIX_SECONDS</a></dd>
|
||||
<dd id="Dune.Generator.ALTER_SET_WRAPPED" class="variable"><a href="../generator.html#Generator.ALTER_SET_WRAPPED">ALTER_SET_WRAPPED</a></dd>
|
||||
<dd id="Dune.Generator.ALTER_SET_TYPE" class="variable"><a href="../generator.html#Generator.ALTER_SET_TYPE">ALTER_SET_TYPE</a></dd>
|
||||
<dd id="Dune.Generator.ARRAY_SIZE_DIM_REQUIRED" class="variable"><a href="../generator.html#Generator.ARRAY_SIZE_DIM_REQUIRED">ARRAY_SIZE_DIM_REQUIRED</a></dd>
|
||||
<dd id="Dune.Generator.TIME_PART_SINGULARS" class="variable"><a href="../generator.html#Generator.TIME_PART_SINGULARS">TIME_PART_SINGULARS</a></dd>
|
||||
|
@ -810,6 +811,7 @@ Default: True</li>
|
|||
<dd id="Dune.Generator.UNWRAPPED_INTERVAL_VALUES" class="variable"><a href="../generator.html#Generator.UNWRAPPED_INTERVAL_VALUES">UNWRAPPED_INTERVAL_VALUES</a></dd>
|
||||
<dd id="Dune.Generator.PARAMETERIZABLE_TEXT_TYPES" class="variable"><a href="../generator.html#Generator.PARAMETERIZABLE_TEXT_TYPES">PARAMETERIZABLE_TEXT_TYPES</a></dd>
|
||||
<dd id="Dune.Generator.EXPRESSIONS_WITHOUT_NESTED_CTES" class="variable"><a href="../generator.html#Generator.EXPRESSIONS_WITHOUT_NESTED_CTES">EXPRESSIONS_WITHOUT_NESTED_CTES</a></dd>
|
||||
<dd id="Dune.Generator.RESPECT_IGNORE_NULLS_UNSUPPORTED_EXPRESSIONS" class="variable"><a href="../generator.html#Generator.RESPECT_IGNORE_NULLS_UNSUPPORTED_EXPRESSIONS">RESPECT_IGNORE_NULLS_UNSUPPORTED_EXPRESSIONS</a></dd>
|
||||
<dd id="Dune.Generator.SENTINEL_LINE_BREAK" class="variable"><a href="../generator.html#Generator.SENTINEL_LINE_BREAK">SENTINEL_LINE_BREAK</a></dd>
|
||||
<dd id="Dune.Generator.pretty" class="variable"><a href="../generator.html#Generator.pretty">pretty</a></dd>
|
||||
<dd id="Dune.Generator.identify" class="variable"><a href="../generator.html#Generator.identify">identify</a></dd>
|
||||
|
@ -828,7 +830,7 @@ Default: True</li>
|
|||
<dd id="Dune.Generator.unsupported" class="function"><a href="../generator.html#Generator.unsupported">unsupported</a></dd>
|
||||
<dd id="Dune.Generator.sep" class="function"><a href="../generator.html#Generator.sep">sep</a></dd>
|
||||
<dd id="Dune.Generator.seg" class="function"><a href="../generator.html#Generator.seg">seg</a></dd>
|
||||
<dd id="Dune.Generator.pad_comment" class="function"><a href="../generator.html#Generator.pad_comment">pad_comment</a></dd>
|
||||
<dd id="Dune.Generator.sanitize_comment" class="function"><a href="../generator.html#Generator.sanitize_comment">sanitize_comment</a></dd>
|
||||
<dd id="Dune.Generator.maybe_comment" class="function"><a href="../generator.html#Generator.maybe_comment">maybe_comment</a></dd>
|
||||
<dd id="Dune.Generator.wrap" class="function"><a href="../generator.html#Generator.wrap">wrap</a></dd>
|
||||
<dd id="Dune.Generator.no_identify" class="function"><a href="../generator.html#Generator.no_identify">no_identify</a></dd>
|
||||
|
@ -961,6 +963,7 @@ Default: True</li>
|
|||
<dd id="Dune.Generator.matchrecognize_sql" class="function"><a href="../generator.html#Generator.matchrecognize_sql">matchrecognize_sql</a></dd>
|
||||
<dd id="Dune.Generator.query_modifiers" class="function"><a href="../generator.html#Generator.query_modifiers">query_modifiers</a></dd>
|
||||
<dd id="Dune.Generator.options_modifier" class="function"><a href="../generator.html#Generator.options_modifier">options_modifier</a></dd>
|
||||
<dd id="Dune.Generator.for_modifiers" class="function"><a href="../generator.html#Generator.for_modifiers">for_modifiers</a></dd>
|
||||
<dd id="Dune.Generator.queryoption_sql" class="function"><a href="../generator.html#Generator.queryoption_sql">queryoption_sql</a></dd>
|
||||
<dd id="Dune.Generator.after_limit_modifiers" class="function"><a href="../generator.html#Generator.after_limit_modifiers">after_limit_modifiers</a></dd>
|
||||
<dd id="Dune.Generator.select_sql" class="function"><a href="../generator.html#Generator.select_sql">select_sql</a></dd>
|
||||
|
@ -1189,6 +1192,7 @@ Default: True</li>
|
|||
<dd id="Dune.Generator.encodeproperty_sql" class="function"><a href="../generator.html#Generator.encodeproperty_sql">encodeproperty_sql</a></dd>
|
||||
<dd id="Dune.Generator.includeproperty_sql" class="function"><a href="../generator.html#Generator.includeproperty_sql">includeproperty_sql</a></dd>
|
||||
<dd id="Dune.Generator.xmlelement_sql" class="function"><a href="../generator.html#Generator.xmlelement_sql">xmlelement_sql</a></dd>
|
||||
<dd id="Dune.Generator.xmlkeyvalueoption_sql" class="function"><a href="../generator.html#Generator.xmlkeyvalueoption_sql">xmlkeyvalueoption_sql</a></dd>
|
||||
<dd id="Dune.Generator.partitionbyrangeproperty_sql" class="function"><a href="../generator.html#Generator.partitionbyrangeproperty_sql">partitionbyrangeproperty_sql</a></dd>
|
||||
<dd id="Dune.Generator.partitionbyrangepropertydynamic_sql" class="function"><a href="../generator.html#Generator.partitionbyrangepropertydynamic_sql">partitionbyrangepropertydynamic_sql</a></dd>
|
||||
<dd id="Dune.Generator.unpivotcolumns_sql" class="function"><a href="../generator.html#Generator.unpivotcolumns_sql">unpivotcolumns_sql</a></dd>
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
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 it is too large
Load diff
|
@ -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">{'quarter', 'year_month', 'week', 'year', 'month', 'day'}</span>
|
||||
<span class="default_value">{'year_month', 'year', 'day', 'month', 'quarter', 'week'}</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
|
|
@ -641,7 +641,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">{<class '<a href="expressions.html#JSONPathFilter">sqlglot.expressions.JSONPathFilter</a>'>, <class '<a href="expressions.html#JSONPathUnion">sqlglot.expressions.JSONPathUnion</a>'>, <class '<a href="expressions.html#JSONPathSubscript">sqlglot.expressions.JSONPathSubscript</a>'>, <class '<a href="expressions.html#JSONPathWildcard">sqlglot.expressions.JSONPathWildcard</a>'>, <class '<a href="expressions.html#JSONPathSelector">sqlglot.expressions.JSONPathSelector</a>'>, <class '<a href="expressions.html#JSONPathSlice">sqlglot.expressions.JSONPathSlice</a>'>, <class '<a href="expressions.html#JSONPathScript">sqlglot.expressions.JSONPathScript</a>'>, <class '<a href="expressions.html#JSONPathRoot">sqlglot.expressions.JSONPathRoot</a>'>, <class '<a href="expressions.html#JSONPathRecursive">sqlglot.expressions.JSONPathRecursive</a>'>, <class '<a href="expressions.html#JSONPathKey">sqlglot.expressions.JSONPathKey</a>'>}</span>
|
||||
<label class="view-value-button pdoc-button" for="ALL_JSON_PATH_PARTS-view-value"></label><span class="default_value">{<class '<a href="expressions.html#JSONPathScript">sqlglot.expressions.JSONPathScript</a>'>, <class '<a href="expressions.html#JSONPathRoot">sqlglot.expressions.JSONPathRoot</a>'>, <class '<a href="expressions.html#JSONPathRecursive">sqlglot.expressions.JSONPathRecursive</a>'>, <class '<a href="expressions.html#JSONPathKey">sqlglot.expressions.JSONPathKey</a>'>, <class '<a href="expressions.html#JSONPathWildcard">sqlglot.expressions.JSONPathWildcard</a>'>, <class '<a href="expressions.html#JSONPathFilter">sqlglot.expressions.JSONPathFilter</a>'>, <class '<a href="expressions.html#JSONPathUnion">sqlglot.expressions.JSONPathUnion</a>'>, <class '<a href="expressions.html#JSONPathSubscript">sqlglot.expressions.JSONPathSubscript</a>'>, <class '<a href="expressions.html#JSONPathSelector">sqlglot.expressions.JSONPathSelector</a>'>, <class '<a href="expressions.html#JSONPathSlice">sqlglot.expressions.JSONPathSlice</a>'>}</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">{'settings', 'connect', 'pivots', 'options', 'qualify', 'windows', 'into', 'with', 'prewhere', 'having', 'distribute', 'limit', 'sample', 'operation_modifiers', 'offset', 'distinct', 'format', 'locks', 'cluster', 'match', 'laterals', 'kind', 'group', 'sort'}</span>
|
||||
<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>
|
||||
|
||||
|
||||
</div>
|
||||
|
|
|
@ -133,7 +133,7 @@
|
|||
</span><span id="L-69"><a href="#L-69"><span class="linenos"> 69</span></a> <span class="c1"># kind / side syntax (e.g INNER UNION ALL BY NAME) which changes the semantics of the operation</span>
|
||||
</span><span id="L-70"><a href="#L-70"><span class="linenos"> 70</span></a> <span class="n">left</span><span class="p">,</span> <span class="n">right</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="n">union_scopes</span>
|
||||
</span><span id="L-71"><a href="#L-71"><span class="linenos"> 71</span></a> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">left</span><span class="o">.</span><span class="n">expression</span><span class="o">.</span><span class="n">selects</span><span class="p">)</span> <span class="o">!=</span> <span class="nb">len</span><span class="p">(</span><span class="n">right</span><span class="o">.</span><span class="n">expression</span><span class="o">.</span><span class="n">selects</span><span class="p">):</span>
|
||||
</span><span id="L-72"><a href="#L-72"><span class="linenos"> 72</span></a> <span class="n">scope_sql</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="n">expression</span><span class="o">.</span><span class="n">sql</span><span class="p">()</span>
|
||||
</span><span id="L-72"><a href="#L-72"><span class="linenos"> 72</span></a> <span class="n">scope_sql</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="n">expression</span><span class="o">.</span><span class="n">sql</span><span class="p">(</span><span class="n">dialect</span><span class="o">=</span><span class="n">dialect</span><span class="p">)</span>
|
||||
</span><span id="L-73"><a href="#L-73"><span class="linenos"> 73</span></a> <span class="k">raise</span> <span class="n">OptimizeError</span><span class="p">(</span>
|
||||
</span><span id="L-74"><a href="#L-74"><span class="linenos"> 74</span></a> <span class="sa">f</span><span class="s2">"Invalid set operation due to column mismatch: </span><span class="si">{</span><span class="n">scope_sql</span><span class="si">}</span><span class="s2">."</span>
|
||||
</span><span id="L-75"><a href="#L-75"><span class="linenos"> 75</span></a> <span class="p">)</span>
|
||||
|
@ -325,7 +325,7 @@
|
|||
</span><span id="pushdown_projections-70"><a href="#pushdown_projections-70"><span class="linenos"> 70</span></a> <span class="c1"># kind / side syntax (e.g INNER UNION ALL BY NAME) which changes the semantics of the operation</span>
|
||||
</span><span id="pushdown_projections-71"><a href="#pushdown_projections-71"><span class="linenos"> 71</span></a> <span class="n">left</span><span class="p">,</span> <span class="n">right</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="n">union_scopes</span>
|
||||
</span><span id="pushdown_projections-72"><a href="#pushdown_projections-72"><span class="linenos"> 72</span></a> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">left</span><span class="o">.</span><span class="n">expression</span><span class="o">.</span><span class="n">selects</span><span class="p">)</span> <span class="o">!=</span> <span class="nb">len</span><span class="p">(</span><span class="n">right</span><span class="o">.</span><span class="n">expression</span><span class="o">.</span><span class="n">selects</span><span class="p">):</span>
|
||||
</span><span id="pushdown_projections-73"><a href="#pushdown_projections-73"><span class="linenos"> 73</span></a> <span class="n">scope_sql</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="n">expression</span><span class="o">.</span><span class="n">sql</span><span class="p">()</span>
|
||||
</span><span id="pushdown_projections-73"><a href="#pushdown_projections-73"><span class="linenos"> 73</span></a> <span class="n">scope_sql</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="n">expression</span><span class="o">.</span><span class="n">sql</span><span class="p">(</span><span class="n">dialect</span><span class="o">=</span><span class="n">dialect</span><span class="p">)</span>
|
||||
</span><span id="pushdown_projections-74"><a href="#pushdown_projections-74"><span class="linenos"> 74</span></a> <span class="k">raise</span> <span class="n">OptimizeError</span><span class="p">(</span>
|
||||
</span><span id="pushdown_projections-75"><a href="#pushdown_projections-75"><span class="linenos"> 75</span></a> <span class="sa">f</span><span class="s2">"Invalid set operation due to column mismatch: </span><span class="si">{</span><span class="n">scope_sql</span><span class="si">}</span><span class="s2">."</span>
|
||||
</span><span id="pushdown_projections-76"><a href="#pushdown_projections-76"><span class="linenos"> 76</span></a> <span class="p">)</span>
|
||||
|
|
|
@ -3201,7 +3201,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">{<class '<a href="../expressions.html#In">sqlglot.expressions.In</a>'>, <class '<a href="../expressions.html#LT">sqlglot.expressions.LT</a>'>, <class '<a href="../expressions.html#NEQ">sqlglot.expressions.NEQ</a>'>, <class '<a href="../expressions.html#EQ">sqlglot.expressions.EQ</a>'>, <class '<a href="../expressions.html#GTE">sqlglot.expressions.GTE</a>'>, <class '<a href="../expressions.html#GT">sqlglot.expressions.GT</a>'>, <class '<a href="../expressions.html#LTE">sqlglot.expressions.LTE</a>'>}</span>
|
||||
<label class="view-value-button pdoc-button" for="DATETRUNC_COMPARISONS-view-value"></label><span class="default_value">{<class '<a href="../expressions.html#LT">sqlglot.expressions.LT</a>'>, <class '<a href="../expressions.html#GTE">sqlglot.expressions.GTE</a>'>, <class '<a href="../expressions.html#EQ">sqlglot.expressions.EQ</a>'>, <class '<a href="../expressions.html#LTE">sqlglot.expressions.LTE</a>'>, <class '<a href="../expressions.html#NEQ">sqlglot.expressions.NEQ</a>'>, <class '<a href="../expressions.html#GT">sqlglot.expressions.GT</a>'>, <class '<a href="../expressions.html#In">sqlglot.expressions.In</a>'>}</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', ''), ('RIGHT', 'OUTER'), ('', 'INNER'), ('', '')}</span>
|
||||
<span class="default_value">{('RIGHT', ''), ('', 'INNER'), ('RIGHT', 'OUTER'), ('', '')}</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
|
28915
docs/sqlglot/parser.html
28915
docs/sqlglot/parser.html
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
1
setup.py
1
setup.py
|
@ -29,6 +29,7 @@ setup(
|
|||
"types-pytz",
|
||||
"typing_extensions",
|
||||
"maturin>=1.4,<2.0",
|
||||
"pyperf",
|
||||
],
|
||||
"rs": [f"sqlglotrs=={sqlglotrs_version()}"],
|
||||
},
|
||||
|
|
|
@ -494,6 +494,8 @@ class BigQuery(Dialect):
|
|||
(prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("r", "R")
|
||||
]
|
||||
|
||||
NESTED_COMMENTS = False
|
||||
|
||||
KEYWORDS = {
|
||||
**tokens.Tokenizer.KEYWORDS,
|
||||
"ANY TYPE": TokenType.VARIANT,
|
||||
|
@ -930,6 +932,7 @@ class BigQuery(Dialect):
|
|||
exp.Array: inline_array_unless_query,
|
||||
exp.ArrayContains: _array_contains_sql,
|
||||
exp.ArrayFilter: filter_array_using_unnest,
|
||||
exp.ArrayRemove: filter_array_using_unnest,
|
||||
exp.Cast: transforms.preprocess([transforms.remove_precision_parameterized_types]),
|
||||
exp.CollateProperty: lambda self, e: (
|
||||
f"DEFAULT COLLATE {self.sql(e, 'this')}"
|
||||
|
|
|
@ -15,6 +15,7 @@ from sqlglot.dialects.dialect import (
|
|||
no_pivot_sql,
|
||||
build_json_extract_path,
|
||||
rename_func,
|
||||
remove_from_array_using_filter,
|
||||
sha256_sql,
|
||||
strposition_sql,
|
||||
var_map_sql,
|
||||
|
@ -1061,6 +1062,7 @@ class ClickHouse(Dialect):
|
|||
exp.ApproxDistinct: rename_func("uniq"),
|
||||
exp.ArrayConcat: rename_func("arrayConcat"),
|
||||
exp.ArrayFilter: lambda self, e: self.func("arrayFilter", e.expression, e.this),
|
||||
exp.ArrayRemove: remove_from_array_using_filter,
|
||||
exp.ArraySum: rename_func("arraySum"),
|
||||
exp.ArgMax: arg_max_or_min_no_count("argMax"),
|
||||
exp.ArgMin: arg_max_or_min_no_count("argMin"),
|
||||
|
|
|
@ -499,6 +499,9 @@ class Dialect(metaclass=_Dialect):
|
|||
equivalent of CREATE SCHEMA is CREATE DATABASE.
|
||||
"""
|
||||
|
||||
# Whether ADD is present for each column added by ALTER TABLE
|
||||
ALTER_TABLE_ADD_REQUIRED_FOR_EACH_COLUMN = True
|
||||
|
||||
# --- Autofilled ---
|
||||
|
||||
tokenizer_class = Tokenizer
|
||||
|
@ -1733,13 +1736,18 @@ def json_path_key_only_name(self: Generator, expression: exp.JSONPathKey) -> str
|
|||
return expression.name
|
||||
|
||||
|
||||
def filter_array_using_unnest(self: Generator, expression: exp.ArrayFilter) -> str:
|
||||
def filter_array_using_unnest(
|
||||
self: Generator, expression: exp.ArrayFilter | exp.ArrayRemove
|
||||
) -> str:
|
||||
cond = expression.expression
|
||||
if isinstance(cond, exp.Lambda) and len(cond.expressions) == 1:
|
||||
alias = cond.expressions[0]
|
||||
cond = cond.this
|
||||
elif isinstance(cond, exp.Predicate):
|
||||
alias = "_u"
|
||||
elif isinstance(expression, exp.ArrayRemove):
|
||||
alias = "_u"
|
||||
cond = exp.NEQ(this=alias, expression=expression.expression)
|
||||
else:
|
||||
self.unsupported("Unsupported filter condition")
|
||||
return ""
|
||||
|
@ -1749,6 +1757,16 @@ def filter_array_using_unnest(self: Generator, expression: exp.ArrayFilter) -> s
|
|||
return self.sql(exp.Array(expressions=[filtered]))
|
||||
|
||||
|
||||
def remove_from_array_using_filter(self: Generator, expression: exp.ArrayRemove) -> str:
|
||||
lambda_id = exp.to_identifier("_u")
|
||||
cond = exp.NEQ(this=lambda_id, expression=expression.expression)
|
||||
return self.sql(
|
||||
exp.ArrayFilter(
|
||||
this=expression.this, expression=exp.Lambda(this=cond, expressions=[lambda_id])
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def to_number_with_nls_param(self: Generator, expression: exp.ToNumber) -> str:
|
||||
return self.func(
|
||||
"TO_NUMBER",
|
||||
|
|
|
@ -26,6 +26,7 @@ from sqlglot.dialects.dialect import (
|
|||
no_timestamp_sql,
|
||||
pivot_column_names,
|
||||
rename_func,
|
||||
remove_from_array_using_filter,
|
||||
strposition_sql,
|
||||
str_to_time_sql,
|
||||
timestamptrunc_sql,
|
||||
|
@ -625,6 +626,7 @@ class DuckDB(Dialect):
|
|||
exp.ApproxDistinct: approx_count_distinct_sql,
|
||||
exp.Array: inline_array_unless_query,
|
||||
exp.ArrayFilter: rename_func("LIST_FILTER"),
|
||||
exp.ArrayRemove: remove_from_array_using_filter,
|
||||
exp.ArraySort: _array_sort_sql,
|
||||
exp.ArraySum: rename_func("LIST_SUM"),
|
||||
exp.BitwiseXor: rename_func("XOR"),
|
||||
|
|
|
@ -741,6 +741,17 @@ class Hive(Dialect):
|
|||
|
||||
return self.func("STRUCT", *values)
|
||||
|
||||
def columndef_sql(self, expression: exp.ColumnDef, sep: str = " ") -> str:
|
||||
return super().columndef_sql(
|
||||
expression,
|
||||
sep=(
|
||||
": "
|
||||
if isinstance(expression.parent, exp.DataType)
|
||||
and expression.parent.is_type("struct")
|
||||
else sep
|
||||
),
|
||||
)
|
||||
|
||||
def alterset_sql(self, expression: exp.AlterSet) -> str:
|
||||
exprs = self.expressions(expression, flat=True)
|
||||
exprs = f" {exprs}" if exprs else ""
|
||||
|
|
|
@ -187,6 +187,8 @@ class MySQL(Dialect):
|
|||
BIT_STRINGS = [("b'", "'"), ("B'", "'"), ("0b", "")]
|
||||
HEX_STRINGS = [("x'", "'"), ("X'", "'"), ("0x", "")]
|
||||
|
||||
NESTED_COMMENTS = False
|
||||
|
||||
KEYWORDS = {
|
||||
**tokens.Tokenizer.KEYWORDS,
|
||||
"CHARSET": TokenType.CHARACTER_SET,
|
||||
|
@ -211,6 +213,7 @@ class MySQL(Dialect):
|
|||
"START": TokenType.BEGIN,
|
||||
"SIGNED": TokenType.BIGINT,
|
||||
"SIGNED INTEGER": TokenType.BIGINT,
|
||||
"TIMESTAMP": TokenType.TIMESTAMPTZ,
|
||||
"UNLOCK TABLES": TokenType.COMMAND,
|
||||
"UNSIGNED": TokenType.UBIGINT,
|
||||
"UNSIGNED INTEGER": TokenType.UBIGINT,
|
||||
|
|
|
@ -44,6 +44,7 @@ class Oracle(Dialect):
|
|||
TABLESAMPLE_SIZE_IS_PERCENT = True
|
||||
NULL_ORDERING = "nulls_are_large"
|
||||
ON_CONDITION_EMPTY_BEFORE_ERROR = False
|
||||
ALTER_TABLE_ADD_REQUIRED_FOR_EACH_COLUMN = False
|
||||
|
||||
# See section 8: https://docs.oracle.com/cd/A97630_01/server.920/a96540/sql_elements9a.htm
|
||||
NORMALIZATION_STRATEGY = NormalizationStrategy.UPPERCASE
|
||||
|
@ -104,7 +105,6 @@ class Oracle(Dialect):
|
|||
}
|
||||
|
||||
class Parser(parser.Parser):
|
||||
ALTER_TABLE_ADD_REQUIRED_FOR_EACH_COLUMN = False
|
||||
WINDOW_BEFORE_PAREN_TOKENS = {TokenType.OVER, TokenType.KEEP}
|
||||
VALUES_FOLLOWED_BY_PAREN = False
|
||||
|
||||
|
@ -341,11 +341,8 @@ class Oracle(Dialect):
|
|||
def offset_sql(self, expression: exp.Offset) -> str:
|
||||
return f"{super().offset_sql(expression)} ROWS"
|
||||
|
||||
def add_column_sql(self, expression: exp.Alter) -> str:
|
||||
actions = self.expressions(expression, key="actions", flat=True)
|
||||
if len(expression.args.get("actions", [])) > 1:
|
||||
return f"ADD ({actions})"
|
||||
return f"ADD {actions}"
|
||||
def add_column_sql(self, expression: exp.Expression) -> str:
|
||||
return f"ADD {self.sql(expression)}"
|
||||
|
||||
def queryoption_sql(self, expression: exp.QueryOption) -> str:
|
||||
option = self.sql(expression, "this")
|
||||
|
|
|
@ -13,6 +13,7 @@ from sqlglot.dialects.dialect import (
|
|||
datestrtodate_sql,
|
||||
build_formatted_time,
|
||||
filter_array_using_unnest,
|
||||
inline_array_sql,
|
||||
json_extract_segments,
|
||||
json_path_key_only_name,
|
||||
max_or_greatest,
|
||||
|
@ -728,11 +729,12 @@ class Postgres(Dialect):
|
|||
|
||||
def array_sql(self, expression: exp.Array) -> str:
|
||||
exprs = expression.expressions
|
||||
return (
|
||||
f"{self.normalize_func('ARRAY')}({self.sql(exprs[0])})"
|
||||
if isinstance(seq_get(exprs, 0), exp.Select)
|
||||
else f"{self.normalize_func('ARRAY')}[{self.expressions(expression, flat=True)}]"
|
||||
)
|
||||
func_name = self.normalize_func("ARRAY")
|
||||
|
||||
if isinstance(seq_get(exprs, 0), exp.Select):
|
||||
return f"{func_name}({self.sql(exprs[0])})"
|
||||
|
||||
return f"{func_name}{inline_array_sql(self, expression)}"
|
||||
|
||||
def computedcolumnconstraint_sql(self, expression: exp.ComputedColumnConstraint) -> str:
|
||||
return f"GENERATED ALWAYS AS ({self.sql(expression, 'this')}) STORED"
|
||||
|
|
|
@ -294,6 +294,8 @@ class Presto(Dialect):
|
|||
for prefix in ("U&", "u&")
|
||||
]
|
||||
|
||||
NESTED_COMMENTS = False
|
||||
|
||||
KEYWORDS = {
|
||||
**tokens.Tokenizer.KEYWORDS,
|
||||
"DEALLOCATE PREPARE": TokenType.COMMAND,
|
||||
|
|
|
@ -47,7 +47,7 @@ class PRQL(Dialect):
|
|||
"DERIVE": lambda self, query: self._parse_selection(query),
|
||||
"SELECT": lambda self, query: self._parse_selection(query, append=False),
|
||||
"TAKE": lambda self, query: self._parse_take(query),
|
||||
"FILTER": lambda self, query: query.where(self._parse_assignment()),
|
||||
"FILTER": lambda self, query: query.where(self._parse_disjunction()),
|
||||
"APPEND": lambda self, query: query.union(
|
||||
_select_all(self._parse_table()), distinct=False, copy=False
|
||||
),
|
||||
|
|
|
@ -347,14 +347,3 @@ class Spark2(Hive):
|
|||
return self.func("TO_JSON", arg)
|
||||
|
||||
return super(Hive.Generator, self).cast_sql(expression, safe_prefix=safe_prefix)
|
||||
|
||||
def columndef_sql(self, expression: exp.ColumnDef, sep: str = " ") -> str:
|
||||
return super().columndef_sql(
|
||||
expression,
|
||||
sep=(
|
||||
": "
|
||||
if isinstance(expression.parent, exp.DataType)
|
||||
and expression.parent.is_type("struct")
|
||||
else sep
|
||||
),
|
||||
)
|
||||
|
|
|
@ -94,6 +94,8 @@ class SQLite(Dialect):
|
|||
IDENTIFIERS = ['"', ("[", "]"), "`"]
|
||||
HEX_STRINGS = [("x'", "'"), ("X'", "'"), ("0x", ""), ("0X", "")]
|
||||
|
||||
NESTED_COMMENTS = False
|
||||
|
||||
KEYWORDS = tokens.Tokenizer.KEYWORDS.copy()
|
||||
KEYWORDS.pop("/*+")
|
||||
|
||||
|
|
|
@ -102,6 +102,24 @@ OPTIONS: parser.OPTIONS_TYPE = {
|
|||
"USE": ("PLAN",),
|
||||
}
|
||||
|
||||
|
||||
XML_OPTIONS: parser.OPTIONS_TYPE = {
|
||||
**dict.fromkeys(
|
||||
(
|
||||
"AUTO",
|
||||
"EXPLICIT",
|
||||
"TYPE",
|
||||
),
|
||||
tuple(),
|
||||
),
|
||||
"ELEMENTS": (
|
||||
"XSINIL",
|
||||
"ABSENT",
|
||||
),
|
||||
"BINARY": ("BASE64",),
|
||||
}
|
||||
|
||||
|
||||
OPTIONS_THAT_REQUIRE_EQUAL = ("MAX_GRANT_PERCENT", "MIN_GRANT_PERCENT", "LABEL")
|
||||
|
||||
|
||||
|
@ -390,6 +408,7 @@ class TSQL(Dialect):
|
|||
TYPED_DIVISION = True
|
||||
CONCAT_COALESCE = True
|
||||
NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_INSENSITIVE
|
||||
ALTER_TABLE_ADD_REQUIRED_FOR_EACH_COLUMN = False
|
||||
|
||||
TIME_FORMAT = "'yyyy-mm-dd hh:mm:ss'"
|
||||
|
||||
|
@ -474,6 +493,7 @@ class TSQL(Dialect):
|
|||
"114": "%H:%M:%S:%f",
|
||||
"120": "%Y-%m-%d %H:%M:%S",
|
||||
"121": "%Y-%m-%d %H:%M:%S.%f",
|
||||
"126": "%Y-%m-%dT%H:%M:%S.%f",
|
||||
}
|
||||
|
||||
FORMAT_TIME_MAPPING = {
|
||||
|
@ -540,13 +560,13 @@ class TSQL(Dialect):
|
|||
class Parser(parser.Parser):
|
||||
SET_REQUIRES_ASSIGNMENT_DELIMITER = False
|
||||
LOG_DEFAULTS_TO_LN = True
|
||||
ALTER_TABLE_ADD_REQUIRED_FOR_EACH_COLUMN = False
|
||||
STRING_ALIASES = True
|
||||
NO_PAREN_IF_COMMANDS = False
|
||||
|
||||
QUERY_MODIFIER_PARSERS = {
|
||||
**parser.Parser.QUERY_MODIFIER_PARSERS,
|
||||
TokenType.OPTION: lambda self: ("options", self._parse_options()),
|
||||
TokenType.FOR: lambda self: ("for", self._parse_for()),
|
||||
}
|
||||
|
||||
# T-SQL does not allow BEGIN to be used as an identifier
|
||||
|
@ -637,6 +657,9 @@ class TSQL(Dialect):
|
|||
else self.expression(exp.ScopeResolution, this=this, expression=to),
|
||||
}
|
||||
|
||||
def _parse_alter_table_set(self) -> exp.AlterSet:
|
||||
return self._parse_wrapped(super()._parse_alter_table_set)
|
||||
|
||||
def _parse_wrapped_select(self, table: bool = False) -> t.Optional[exp.Expression]:
|
||||
if self._match(TokenType.MERGE):
|
||||
comments = self._prev_comments
|
||||
|
@ -670,6 +693,28 @@ class TSQL(Dialect):
|
|||
|
||||
return self._parse_wrapped_csv(_parse_option)
|
||||
|
||||
def _parse_xml_key_value_option(self) -> exp.XMLKeyValueOption:
|
||||
this = self._parse_primary_or_var()
|
||||
if self._match(TokenType.L_PAREN, advance=False):
|
||||
expression = self._parse_wrapped(self._parse_string)
|
||||
else:
|
||||
expression = None
|
||||
|
||||
return exp.XMLKeyValueOption(this=this, expression=expression)
|
||||
|
||||
def _parse_for(self) -> t.Optional[t.List[exp.Expression]]:
|
||||
if not self._match_pair(TokenType.FOR, TokenType.XML):
|
||||
return None
|
||||
|
||||
def _parse_for_xml() -> t.Optional[exp.Expression]:
|
||||
return self.expression(
|
||||
exp.QueryOption,
|
||||
this=self._parse_var_from_options(XML_OPTIONS, raise_unmatched=False)
|
||||
or self._parse_xml_key_value_option(),
|
||||
)
|
||||
|
||||
return self._parse_csv(_parse_for_xml)
|
||||
|
||||
def _parse_projections(self) -> t.List[exp.Expression]:
|
||||
"""
|
||||
T-SQL supports the syntax alias = expression in the SELECT's projection list,
|
||||
|
@ -921,6 +966,7 @@ class TSQL(Dialect):
|
|||
COPY_PARAMS_EQ_REQUIRED = True
|
||||
PARSE_JSON_NAME = None
|
||||
EXCEPT_INTERSECT_SUPPORT_ALL_CLAUSE = False
|
||||
ALTER_SET_WRAPPED = True
|
||||
ALTER_SET_TYPE = ""
|
||||
|
||||
EXPRESSIONS_WITHOUT_NESTED_CTES = {
|
||||
|
|
|
@ -1243,6 +1243,45 @@ class Query(Expression):
|
|||
"""
|
||||
raise NotImplementedError("Query objects must implement `select`")
|
||||
|
||||
def where(
|
||||
self: Q,
|
||||
*expressions: t.Optional[ExpOrStr],
|
||||
append: bool = True,
|
||||
dialect: DialectType = None,
|
||||
copy: bool = True,
|
||||
**opts,
|
||||
) -> Q:
|
||||
"""
|
||||
Append to or set the WHERE expressions.
|
||||
|
||||
Examples:
|
||||
>>> Select().select("x").from_("tbl").where("x = 'a' OR x < 'b'").sql()
|
||||
"SELECT x FROM tbl WHERE x = 'a' OR x < 'b'"
|
||||
|
||||
Args:
|
||||
*expressions: the SQL code strings to parse.
|
||||
If an `Expression` instance is passed, it will be used as-is.
|
||||
Multiple expressions are combined with an AND operator.
|
||||
append: if `True`, AND the new expressions to any existing expression.
|
||||
Otherwise, this resets the expression.
|
||||
dialect: the dialect used to parse the input expressions.
|
||||
copy: if `False`, modify this expression instance in-place.
|
||||
opts: other options to use to parse the input expressions.
|
||||
|
||||
Returns:
|
||||
The modified expression.
|
||||
"""
|
||||
return _apply_conjunction_builder(
|
||||
*[expr.this if isinstance(expr, Where) else expr for expr in expressions],
|
||||
instance=self,
|
||||
arg="where",
|
||||
append=append,
|
||||
into=Where,
|
||||
dialect=dialect,
|
||||
copy=copy,
|
||||
**opts,
|
||||
)
|
||||
|
||||
def with_(
|
||||
self: Q,
|
||||
alias: ExpOrStr,
|
||||
|
@ -4054,45 +4093,6 @@ class Select(Query):
|
|||
**opts,
|
||||
)
|
||||
|
||||
def where(
|
||||
self,
|
||||
*expressions: t.Optional[ExpOrStr],
|
||||
append: bool = True,
|
||||
dialect: DialectType = None,
|
||||
copy: bool = True,
|
||||
**opts,
|
||||
) -> Select:
|
||||
"""
|
||||
Append to or set the WHERE expressions.
|
||||
|
||||
Example:
|
||||
>>> Select().select("x").from_("tbl").where("x = 'a' OR x < 'b'").sql()
|
||||
"SELECT x FROM tbl WHERE x = 'a' OR x < 'b'"
|
||||
|
||||
Args:
|
||||
*expressions: the SQL code strings to parse.
|
||||
If an `Expression` instance is passed, it will be used as-is.
|
||||
Multiple expressions are combined with an AND operator.
|
||||
append: if `True`, AND the new expressions to any existing expression.
|
||||
Otherwise, this resets the expression.
|
||||
dialect: the dialect used to parse the input expressions.
|
||||
copy: if `False`, modify this expression instance in-place.
|
||||
opts: other options to use to parse the input expressions.
|
||||
|
||||
Returns:
|
||||
Select: the modified expression.
|
||||
"""
|
||||
return _apply_conjunction_builder(
|
||||
*expressions,
|
||||
instance=self,
|
||||
arg="where",
|
||||
append=append,
|
||||
into=Where,
|
||||
dialect=dialect,
|
||||
copy=copy,
|
||||
**opts,
|
||||
)
|
||||
|
||||
def having(
|
||||
self,
|
||||
*expressions: t.Optional[ExpOrStr],
|
||||
|
@ -5370,6 +5370,10 @@ class AggFunc(Func):
|
|||
pass
|
||||
|
||||
|
||||
class ArrayRemove(Func):
|
||||
arg_types = {"this": True, "expression": True}
|
||||
|
||||
|
||||
class ParameterizedAgg(AggFunc):
|
||||
arg_types = {"this": True, "expressions": True, "params": True}
|
||||
|
||||
|
@ -5573,7 +5577,7 @@ class String(Func):
|
|||
|
||||
class StringToArray(Func):
|
||||
arg_types = {"this": True, "expression": True, "null": False}
|
||||
_sql_names = ["STRING_TO_ARRAY", "SPLIT_BY_STRING"]
|
||||
_sql_names = ["STRING_TO_ARRAY", "SPLIT_BY_STRING", "STRTOK_TO_ARRAY"]
|
||||
|
||||
|
||||
class ArrayOverlaps(Binary, Func):
|
||||
|
@ -6972,6 +6976,11 @@ class XMLNamespace(Expression):
|
|||
pass
|
||||
|
||||
|
||||
# https://learn.microsoft.com/en-us/sql/t-sql/queries/select-for-clause-transact-sql?view=sql-server-ver17#syntax
|
||||
class XMLKeyValueOption(Expression):
|
||||
arg_types = {"this": True, "expression": False}
|
||||
|
||||
|
||||
class Year(Func):
|
||||
pass
|
||||
|
||||
|
@ -7918,7 +7927,7 @@ def parse_identifier(name: str | Identifier, dialect: DialectType = None) -> Ide
|
|||
return expression
|
||||
|
||||
|
||||
INTERVAL_STRING_RE = re.compile(r"\s*(-?[0-9]+)\s*([a-zA-Z]+)\s*")
|
||||
INTERVAL_STRING_RE = re.compile(r"\s*(-?[0-9]+(?:\.[0-9]+)?)\s*([a-zA-Z]+)\s*")
|
||||
|
||||
|
||||
def to_interval(interval: str | Literal) -> Interval:
|
||||
|
|
|
@ -460,6 +460,9 @@ class Generator(metaclass=_Generator):
|
|||
# Whether UNIX_SECONDS(timestamp) is supported
|
||||
SUPPORTS_UNIX_SECONDS = False
|
||||
|
||||
# Whether to wrap <props> in `AlterSet`, e.g., ALTER ... SET (<props>)
|
||||
ALTER_SET_WRAPPED = False
|
||||
|
||||
# The name to generate for the JSONPath expression. If `None`, only `this` will be generated
|
||||
PARSE_JSON_NAME: t.Optional[str] = "PARSE_JSON"
|
||||
|
||||
|
@ -808,9 +811,14 @@ class Generator(metaclass=_Generator):
|
|||
def seg(self, sql: str, sep: str = " ") -> str:
|
||||
return f"{self.sep(sep)}{sql}"
|
||||
|
||||
def pad_comment(self, comment: str) -> str:
|
||||
def sanitize_comment(self, comment: str) -> str:
|
||||
comment = " " + comment if comment[0].strip() else comment
|
||||
comment = comment + " " if comment[-1].strip() else comment
|
||||
|
||||
if not self.dialect.tokenizer_class.NESTED_COMMENTS:
|
||||
# Necessary workaround to avoid syntax errors due to nesting: /* ... */ ... */
|
||||
comment = comment.replace("*/", "* /")
|
||||
|
||||
return comment
|
||||
|
||||
def maybe_comment(
|
||||
|
@ -830,7 +838,7 @@ class Generator(metaclass=_Generator):
|
|||
return sql
|
||||
|
||||
comments_sql = " ".join(
|
||||
f"/*{self.pad_comment(comment)}*/" for comment in comments if comment
|
||||
f"/*{self.sanitize_comment(comment)}*/" for comment in comments if comment
|
||||
)
|
||||
|
||||
if not comments_sql:
|
||||
|
@ -2596,6 +2604,7 @@ class Generator(metaclass=_Generator):
|
|||
*self.offset_limit_modifiers(expression, isinstance(limit, exp.Fetch), limit),
|
||||
*self.after_limit_modifiers(expression),
|
||||
self.options_modifier(expression),
|
||||
self.for_modifiers(expression),
|
||||
sep="",
|
||||
)
|
||||
|
||||
|
@ -2603,6 +2612,10 @@ class Generator(metaclass=_Generator):
|
|||
options = self.expressions(expression, key="options")
|
||||
return f" {options}" if options else ""
|
||||
|
||||
def for_modifiers(self, expression: exp.Expression) -> str:
|
||||
for_modifiers = self.expressions(expression, key="for")
|
||||
return f"{self.sep()}FOR XML{self.seg(for_modifiers)}" if for_modifiers else ""
|
||||
|
||||
def queryoption_sql(self, expression: exp.QueryOption) -> str:
|
||||
self.unsupported("Unsupported query option.")
|
||||
return ""
|
||||
|
@ -3248,7 +3261,7 @@ class Generator(metaclass=_Generator):
|
|||
if expression.comments and self.comments:
|
||||
for comment in expression.comments:
|
||||
if comment:
|
||||
op += f" /*{self.pad_comment(comment)}*/"
|
||||
op += f" /*{self.sanitize_comment(comment)}*/"
|
||||
stack.extend((op, expression.left))
|
||||
return op
|
||||
|
||||
|
@ -3430,21 +3443,32 @@ class Generator(metaclass=_Generator):
|
|||
|
||||
def alterset_sql(self, expression: exp.AlterSet) -> str:
|
||||
exprs = self.expressions(expression, flat=True)
|
||||
if self.ALTER_SET_WRAPPED:
|
||||
exprs = f"({exprs})"
|
||||
|
||||
return f"SET {exprs}"
|
||||
|
||||
def alter_sql(self, expression: exp.Alter) -> str:
|
||||
actions = expression.args["actions"]
|
||||
|
||||
if isinstance(actions[0], exp.ColumnDef):
|
||||
actions = self.add_column_sql(expression)
|
||||
elif isinstance(actions[0], exp.Schema):
|
||||
actions = self.expressions(expression, key="actions", prefix="ADD COLUMNS ")
|
||||
elif isinstance(actions[0], exp.Delete):
|
||||
actions = self.expressions(expression, key="actions", flat=True)
|
||||
elif isinstance(actions[0], exp.Query):
|
||||
actions = "AS " + self.expressions(expression, key="actions")
|
||||
if not self.dialect.ALTER_TABLE_ADD_REQUIRED_FOR_EACH_COLUMN and isinstance(
|
||||
actions[0], exp.ColumnDef
|
||||
):
|
||||
actions_sql = self.expressions(expression, key="actions", flat=True)
|
||||
actions_sql = f"ADD {actions_sql}"
|
||||
else:
|
||||
actions = self.expressions(expression, key="actions", flat=True)
|
||||
actions_list = []
|
||||
for action in actions:
|
||||
if isinstance(action, (exp.ColumnDef, exp.Schema)):
|
||||
action_sql = self.add_column_sql(action)
|
||||
else:
|
||||
action_sql = self.sql(action)
|
||||
if isinstance(action, exp.Query):
|
||||
action_sql = f"AS {action_sql}"
|
||||
|
||||
actions_list.append(action_sql)
|
||||
|
||||
actions_sql = self.format_args(*actions_list)
|
||||
|
||||
exists = " IF EXISTS" if expression.args.get("exists") else ""
|
||||
on_cluster = self.sql(expression, "cluster")
|
||||
|
@ -3455,17 +3479,18 @@ class Generator(metaclass=_Generator):
|
|||
kind = self.sql(expression, "kind")
|
||||
not_valid = " NOT VALID" if expression.args.get("not_valid") else ""
|
||||
|
||||
return f"ALTER {kind}{exists}{only} {self.sql(expression, 'this')}{on_cluster} {actions}{not_valid}{options}"
|
||||
return f"ALTER {kind}{exists}{only} {self.sql(expression, 'this')}{on_cluster} {actions_sql}{not_valid}{options}"
|
||||
|
||||
def add_column_sql(self, expression: exp.Alter) -> str:
|
||||
if self.ALTER_TABLE_INCLUDE_COLUMN_KEYWORD:
|
||||
return self.expressions(
|
||||
expression,
|
||||
key="actions",
|
||||
prefix="ADD COLUMN ",
|
||||
skip_first=True,
|
||||
)
|
||||
return f"ADD {self.expressions(expression, key='actions', flat=True)}"
|
||||
def add_column_sql(self, expression: exp.Expression) -> str:
|
||||
sql = self.sql(expression)
|
||||
if isinstance(expression, exp.Schema):
|
||||
column_text = " COLUMNS"
|
||||
elif isinstance(expression, exp.ColumnDef) and self.ALTER_TABLE_INCLUDE_COLUMN_KEYWORD:
|
||||
column_text = " COLUMN"
|
||||
else:
|
||||
column_text = ""
|
||||
|
||||
return f"ADD{column_text} {sql}"
|
||||
|
||||
def droppartition_sql(self, expression: exp.DropPartition) -> str:
|
||||
expressions = self.expressions(expression)
|
||||
|
@ -4795,6 +4820,12 @@ class Generator(metaclass=_Generator):
|
|||
name = f"NAME {self.sql(expression, 'this')}"
|
||||
return self.func("XMLELEMENT", name, *expression.expressions)
|
||||
|
||||
def xmlkeyvalueoption_sql(self, expression: exp.XMLKeyValueOption) -> str:
|
||||
this = self.sql(expression, "this")
|
||||
expr = self.sql(expression, "expression")
|
||||
expr = f"({expr})" if expr else ""
|
||||
return f"{this}{expr}"
|
||||
|
||||
def partitionbyrangeproperty_sql(self, expression: exp.PartitionByRangeProperty) -> str:
|
||||
partitions = self.expressions(expression, "partition_expressions")
|
||||
create = self.expressions(expression, "create_expressions")
|
||||
|
|
|
@ -69,7 +69,7 @@ def pushdown_projections(
|
|||
# kind / side syntax (e.g INNER UNION ALL BY NAME) which changes the semantics of the operation
|
||||
left, right = scope.union_scopes
|
||||
if len(left.expression.selects) != len(right.expression.selects):
|
||||
scope_sql = scope.expression.sql()
|
||||
scope_sql = scope.expression.sql(dialect=dialect)
|
||||
raise OptimizeError(
|
||||
f"Invalid set operation due to column mismatch: {scope_sql}."
|
||||
)
|
||||
|
|
|
@ -930,6 +930,14 @@ class Parser(metaclass=_Parser):
|
|||
TokenType.FOR: lambda self, this: self._parse_comprehension(this),
|
||||
}
|
||||
|
||||
PIPE_SYNTAX_TRANSFORM_PARSERS = {
|
||||
"SELECT": lambda self, query: self._parse_pipe_syntax_select(query),
|
||||
"WHERE": lambda self, query: self._parse_pipe_syntax_where(query),
|
||||
"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),
|
||||
}
|
||||
|
||||
PROPERTY_PARSERS: t.Dict[str, t.Callable] = {
|
||||
"ALLOWED_VALUES": lambda self: self.expression(
|
||||
exp.AllowedValuesProperty, expressions=self._parse_csv(self._parse_primary)
|
||||
|
@ -1116,6 +1124,25 @@ class Parser(metaclass=_Parser):
|
|||
"TRUNCATE": lambda self: self._parse_partitioned_by_bucket_or_truncate(),
|
||||
}
|
||||
|
||||
def _parse_pipe_syntax_select(self, query: exp.Query) -> exp.Query:
|
||||
select = self._parse_select()
|
||||
if isinstance(select, exp.Select):
|
||||
return select.from_(query.subquery(copy=False), copy=False)
|
||||
return query
|
||||
|
||||
def _parse_pipe_syntax_where(self, query: exp.Query) -> exp.Query:
|
||||
where = self._parse_where()
|
||||
return query.where(where, copy=False)
|
||||
|
||||
def _parse_pipe_syntax_limit(self, query: exp.Query) -> exp.Query:
|
||||
limit = self._parse_limit()
|
||||
offset = self._parse_offset()
|
||||
if limit:
|
||||
query.limit(limit, copy=False)
|
||||
if offset:
|
||||
query.offset(offset, copy=False)
|
||||
return query
|
||||
|
||||
def _parse_partitioned_by_bucket_or_truncate(self) -> exp.Expression:
|
||||
klass = (
|
||||
exp.PartitionedByBucket
|
||||
|
@ -1449,9 +1476,6 @@ class Parser(metaclass=_Parser):
|
|||
|
||||
LOG_DEFAULTS_TO_LN = False
|
||||
|
||||
# Whether ADD is present for each column added by ALTER TABLE
|
||||
ALTER_TABLE_ADD_REQUIRED_FOR_EACH_COLUMN = True
|
||||
|
||||
# Whether the table sample clause expects CSV syntax
|
||||
TABLESAMPLE_CSV = False
|
||||
|
||||
|
@ -3239,6 +3263,8 @@ class Parser(metaclass=_Parser):
|
|||
this = self._parse_derived_table_values()
|
||||
elif from_:
|
||||
this = exp.select("*").from_(from_.this, copy=False)
|
||||
if self._match(TokenType.PIPE_GT, advance=False):
|
||||
return self._parse_pipe_syntax_query(this)
|
||||
elif self._match(TokenType.SUMMARIZE):
|
||||
table = self._match(TokenType.TABLE)
|
||||
this = self._parse_select() or self._parse_string() or self._parse_table()
|
||||
|
@ -7137,6 +7163,16 @@ class Parser(metaclass=_Parser):
|
|||
|
||||
return this
|
||||
|
||||
def _parse_pipe_syntax_query(self, query: exp.Select) -> exp.Query:
|
||||
while self._match(TokenType.PIPE_GT):
|
||||
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()}'.")
|
||||
else:
|
||||
query = parser(self, query)
|
||||
|
||||
return query
|
||||
|
||||
def _parse_wrapped_id_vars(self, optional: bool = False) -> t.List[exp.Expression]:
|
||||
return self._parse_wrapped_csv(self._parse_id_var, optional=optional)
|
||||
|
||||
|
@ -7216,7 +7252,7 @@ class Parser(metaclass=_Parser):
|
|||
return self.expression(exp.Refresh, this=self._parse_string() or self._parse_table())
|
||||
|
||||
def _parse_add_column(self) -> t.Optional[exp.Expression]:
|
||||
if not self._match_text_seq("ADD"):
|
||||
if not self._prev.text.upper() == "ADD":
|
||||
return None
|
||||
|
||||
self._match(TokenType.COLUMN)
|
||||
|
@ -7249,26 +7285,22 @@ class Parser(metaclass=_Parser):
|
|||
)
|
||||
|
||||
def _parse_alter_table_add(self) -> t.List[exp.Expression]:
|
||||
index = self._index - 1
|
||||
|
||||
def _parse_add_column_or_constraint():
|
||||
self._match_text_seq("ADD")
|
||||
if self._match_set(self.ADD_CONSTRAINT_TOKENS, advance=False):
|
||||
return self._parse_csv(
|
||||
lambda: self.expression(
|
||||
return self.expression(
|
||||
exp.AddConstraint, expressions=self._parse_csv(self._parse_constraint)
|
||||
)
|
||||
)
|
||||
return self._parse_add_column()
|
||||
|
||||
self._retreat(index)
|
||||
if not self.ALTER_TABLE_ADD_REQUIRED_FOR_EACH_COLUMN and self._match_text_seq("ADD"):
|
||||
return self._parse_wrapped_csv(self._parse_field_def, optional=True)
|
||||
|
||||
if self._match_text_seq("ADD", "COLUMNS"):
|
||||
if not self.dialect.ALTER_TABLE_ADD_REQUIRED_FOR_EACH_COLUMN or self._match_text_seq(
|
||||
"COLUMNS"
|
||||
):
|
||||
schema = self._parse_schema()
|
||||
if schema:
|
||||
return [schema]
|
||||
return []
|
||||
|
||||
return self._parse_wrapped_csv(self._parse_add_column, optional=True)
|
||||
return ensure_list(schema) if schema else self._parse_csv(self._parse_field_def)
|
||||
|
||||
return self._parse_csv(_parse_add_column_or_constraint)
|
||||
|
||||
def _parse_alter_table_alter(self) -> t.Optional[exp.Expression]:
|
||||
if self._match_texts(self.ALTER_ALTER_PARSERS):
|
||||
|
@ -7391,7 +7423,8 @@ class Parser(metaclass=_Parser):
|
|||
if self._match_text_seq("SERDE"):
|
||||
alter_set.set("serde", self._parse_field())
|
||||
|
||||
alter_set.set("expressions", [self._parse_properties()])
|
||||
properties = self._parse_wrapped(self._parse_properties, optional=True)
|
||||
alter_set.set("expressions", [properties])
|
||||
|
||||
return alter_set
|
||||
|
||||
|
@ -8180,6 +8213,8 @@ class Parser(metaclass=_Parser):
|
|||
)
|
||||
|
||||
def _parse_star_ops(self) -> t.Optional[exp.Expression]:
|
||||
star_token = self._prev
|
||||
|
||||
if self._match_text_seq("COLUMNS", "(", advance=False):
|
||||
this = self._parse_function()
|
||||
if isinstance(this, exp.Columns):
|
||||
|
@ -8193,7 +8228,7 @@ class Parser(metaclass=_Parser):
|
|||
"replace": self._parse_star_op("REPLACE"),
|
||||
"rename": self._parse_star_op("RENAME"),
|
||||
},
|
||||
)
|
||||
).update_positions(star_token)
|
||||
|
||||
def _parse_grant_privilege(self) -> t.Optional[exp.GrantPrivilege]:
|
||||
privilege_parts = []
|
||||
|
|
|
@ -57,6 +57,7 @@ class TokenType(AutoName):
|
|||
OR = auto()
|
||||
AMP = auto()
|
||||
DPIPE = auto()
|
||||
PIPE_GT = auto()
|
||||
PIPE = auto()
|
||||
PIPE_SLASH = auto()
|
||||
DPIPE_SLASH = auto()
|
||||
|
@ -680,6 +681,7 @@ class Tokenizer(metaclass=_Tokenizer):
|
|||
"==": TokenType.EQ,
|
||||
"::": TokenType.DCOLON,
|
||||
"||": TokenType.DPIPE,
|
||||
"|>": TokenType.PIPE_GT,
|
||||
">=": TokenType.GTE,
|
||||
"<=": TokenType.LTE,
|
||||
"<>": TokenType.NEQ,
|
||||
|
@ -1505,10 +1507,14 @@ class Tokenizer(metaclass=_Tokenizer):
|
|||
if not self._RS_TOKENIZER:
|
||||
raise SqlglotError("Rust tokenizer is not available")
|
||||
|
||||
try:
|
||||
tokens = self._RS_TOKENIZER.tokenize(sql, self._rs_dialect_settings)
|
||||
tokens, error_msg = self._RS_TOKENIZER.tokenize(sql, self._rs_dialect_settings)
|
||||
for token in tokens:
|
||||
token.token_type = _ALL_TOKEN_TYPES[token.token_type_index]
|
||||
|
||||
# Setting this here so partial token lists can be inspected even if there is a failure
|
||||
self.tokens = tokens
|
||||
|
||||
if error_msg is not None:
|
||||
raise TokenError(error_msg)
|
||||
|
||||
return tokens
|
||||
except Exception as e:
|
||||
raise TokenError(str(e))
|
||||
|
|
2
sqlglotrs/Cargo.lock
generated
2
sqlglotrs/Cargo.lock
generated
|
@ -502,7 +502,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "sqlglotrs"
|
||||
version = "0.5.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"criterion",
|
||||
"pyo3",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "sqlglotrs"
|
||||
version = "0.5.0"
|
||||
version = "0.6.1"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use crate::settings::TokenType;
|
||||
use crate::trie::{Trie, TrieResult};
|
||||
use crate::{Token, TokenTypeSettings, TokenizerDialectSettings, TokenizerSettings};
|
||||
use pyo3::exceptions::PyException;
|
||||
use pyo3::prelude::*;
|
||||
use std::cmp::{max, min};
|
||||
|
||||
|
@ -45,7 +44,7 @@ impl Tokenizer {
|
|||
&self,
|
||||
sql: &str,
|
||||
dialect_settings: &TokenizerDialectSettings,
|
||||
) -> Result<Vec<Token>, PyErr> {
|
||||
) -> (Vec<Token>, Option<String>) {
|
||||
let mut state = TokenizerState::new(
|
||||
sql,
|
||||
&self.settings,
|
||||
|
@ -53,9 +52,14 @@ impl Tokenizer {
|
|||
dialect_settings,
|
||||
&self.keyword_trie,
|
||||
);
|
||||
state.tokenize().map_err(|e| {
|
||||
PyException::new_err(format!("Error tokenizing '{}': {}", e.context, e.message))
|
||||
})
|
||||
let tokenize_result = state.tokenize();
|
||||
match tokenize_result {
|
||||
Ok(tokens) => (tokens, None),
|
||||
Err(e) => {
|
||||
let msg = format!("Error tokenizing '{}': {}", e.context, e.message);
|
||||
(state.tokens, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1234,7 +1234,7 @@ LANGUAGE js AS
|
|||
"bigquery": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a INT64, struct_col_b STRING>)",
|
||||
"duckdb": "CREATE TABLE db.example_table (col_a STRUCT(struct_col_a INT, struct_col_b TEXT))",
|
||||
"presto": "CREATE TABLE db.example_table (col_a ROW(struct_col_a INTEGER, struct_col_b VARCHAR))",
|
||||
"hive": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a INT, struct_col_b STRING>)",
|
||||
"hive": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a: INT, struct_col_b: STRING>)",
|
||||
"spark": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a: INT, struct_col_b: STRING>)",
|
||||
},
|
||||
)
|
||||
|
@ -1244,7 +1244,7 @@ LANGUAGE js AS
|
|||
"bigquery": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a INT64, struct_col_b STRUCT<nested_col_a STRING, nested_col_b STRING>>)",
|
||||
"duckdb": "CREATE TABLE db.example_table (col_a STRUCT(struct_col_a BIGINT, struct_col_b STRUCT(nested_col_a TEXT, nested_col_b TEXT)))",
|
||||
"presto": "CREATE TABLE db.example_table (col_a ROW(struct_col_a BIGINT, struct_col_b ROW(nested_col_a VARCHAR, nested_col_b VARCHAR)))",
|
||||
"hive": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a BIGINT, struct_col_b STRUCT<nested_col_a STRING, nested_col_b STRING>>)",
|
||||
"hive": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a: BIGINT, struct_col_b: STRUCT<nested_col_a: STRING, nested_col_b: STRING>>)",
|
||||
"spark": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a: BIGINT, struct_col_b: STRUCT<nested_col_a: STRING, nested_col_b: STRING>>)",
|
||||
},
|
||||
)
|
||||
|
@ -2616,3 +2616,14 @@ OPTIONS (
|
|||
"snowflake": "WITH t1 AS (SELECT (SELECT ARRAY_AGG(OBJECT_CONSTRUCT('alias_x1', x1, 'x2', x2 /* test */)) FROM t2 WHERE x2 = 4) AS array_col) SELECT array_col[0].alias_x1, array_col[0].x2 FROM t1",
|
||||
},
|
||||
)
|
||||
|
||||
def test_avoid_generating_nested_comment(self):
|
||||
sql = """
|
||||
select
|
||||
id,
|
||||
foo,
|
||||
-- bar, /* the thing */
|
||||
from facts
|
||||
"""
|
||||
expected = "SELECT\n id,\n foo\n/* bar, /* the thing * / */\nFROM facts"
|
||||
self.assertEqual(self.parse_one(sql).sql("bigquery", pretty=True), expected)
|
||||
|
|
|
@ -2191,6 +2191,21 @@ class TestDialect(Validator):
|
|||
"bigquery": "MOD(a, b + 1)",
|
||||
},
|
||||
)
|
||||
self.validate_all(
|
||||
"ARRAY_REMOVE(the_array, target)",
|
||||
write={
|
||||
"": "ARRAY_REMOVE(the_array, target)",
|
||||
"clickhouse": "arrayFilter(_u -> _u <> target, the_array)",
|
||||
"duckdb": "LIST_FILTER(the_array, _u -> _u <> target)",
|
||||
"bigquery": "ARRAY(SELECT _u FROM UNNEST(the_array) AS _u WHERE _u <> target)",
|
||||
"hive": "ARRAY_REMOVE(the_array, target)",
|
||||
"postgres": "ARRAY_REMOVE(the_array, target)",
|
||||
"presto": "ARRAY_REMOVE(the_array, target)",
|
||||
"starrocks": "ARRAY_REMOVE(the_array, target)",
|
||||
"databricks": "ARRAY_REMOVE(the_array, target)",
|
||||
"snowflake": "ARRAY_REMOVE(the_array, target)",
|
||||
},
|
||||
)
|
||||
|
||||
def test_typeddiv(self):
|
||||
typed_div = exp.Div(this=exp.column("a"), expression=exp.column("b"), typed=True)
|
||||
|
@ -3453,3 +3468,63 @@ FROM subquery2""",
|
|||
parse_one("SELECT 0xCC", read=read_dialect).sql(other_integer_dialects),
|
||||
"SELECT 0xCC",
|
||||
)
|
||||
|
||||
def test_pipe_syntax(self):
|
||||
self.validate_identity("FROM x", "SELECT * FROM x")
|
||||
self.validate_identity("FROM x |> SELECT x1, x2", "SELECT x1, x2 FROM (SELECT * FROM x)")
|
||||
self.validate_identity(
|
||||
"FROM x |> SELECT x1 as c1, x2 as c2",
|
||||
"SELECT x1 AS c1, x2 AS c2 FROM (SELECT * FROM x)",
|
||||
)
|
||||
self.validate_identity(
|
||||
"FROM x |> SELECT x1 + 1 as x1_a, x2 - 1 as x2_a |> WHERE x1_a > 1",
|
||||
"SELECT x1 + 1 AS x1_a, x2 - 1 AS x2_a FROM (SELECT * FROM x) WHERE x1_a > 1",
|
||||
)
|
||||
self.validate_identity(
|
||||
"FROM x |> SELECT x1 + 1 as x1_a, x2 - 1 as x2_a |> WHERE x1_a > 1 |> SELECT x2_a",
|
||||
"SELECT x2_a FROM (SELECT x1 + 1 AS x1_a, x2 - 1 AS x2_a FROM (SELECT * FROM x) WHERE x1_a > 1)",
|
||||
)
|
||||
self.validate_identity(
|
||||
"FROM x |> WHERE x1 > 0 OR x2 > 0 |> WHERE x3 > 1 AND x4 > 1 |> SELECT x1, x4",
|
||||
"SELECT x1, x4 FROM (SELECT * FROM x WHERE (x1 > 0 OR x2 > 0) AND (x3 > 1 AND x4 > 1))",
|
||||
)
|
||||
self.validate_identity(
|
||||
"FROM x |> WHERE x1 > 1 |> WHERE x2 > 2 |> SELECT x1 as gt1, x2 as gt2",
|
||||
"SELECT x1 AS gt1, x2 AS gt2 FROM (SELECT * FROM x WHERE x1 > 1 AND x2 > 2)",
|
||||
)
|
||||
self.validate_identity(
|
||||
"FROM x |> WHERE x1 > 1 AND x2 > 2 |> SELECT x1 as gt1, x2 as gt2 |> SELECT gt1 * 2 + gt2 * 2 AS gt2_2",
|
||||
"SELECT gt1 * 2 + gt2 * 2 AS gt2_2 FROM (SELECT x1 AS gt1, x2 AS gt2 FROM (SELECT * FROM x WHERE x1 > 1 AND x2 > 2))",
|
||||
)
|
||||
self.validate_identity("FROM x |> ORDER BY x1", "SELECT * FROM x ORDER BY x1")
|
||||
self.validate_identity(
|
||||
"FROM x |> ORDER BY x1 |> ORDER BY x2", "SELECT * FROM x ORDER BY x1, x2"
|
||||
)
|
||||
self.validate_identity(
|
||||
"FROM x |> ORDER BY x1 |> WHERE x1 > 0 OR x1 != 1 |> ORDER BY x2 |> WHERE x2 > 0 AND x2 != 1 |> SELECT x1, x2",
|
||||
"SELECT x1, x2 FROM (SELECT * FROM x WHERE (x1 > 0 OR x1 <> 1) AND (x2 > 0 AND x2 <> 1) ORDER BY x1, x2)",
|
||||
)
|
||||
self.validate_identity(
|
||||
"FROM x |> ORDER BY x1 |> WHERE x1 > 0 |> SELECT x1",
|
||||
"SELECT x1 FROM (SELECT * FROM x WHERE x1 > 0 ORDER BY x1)",
|
||||
)
|
||||
self.validate_identity(
|
||||
"FROM x |> WHERE x1 > 0 |> SELECT x1 |> ORDER BY x1",
|
||||
"SELECT x1 FROM (SELECT * FROM x WHERE x1 > 0) ORDER BY x1",
|
||||
)
|
||||
self.validate_identity(
|
||||
"FROM x |> SELECT x1, x2, x3 |> ORDER BY x1 DESC NULLS FIRST, x2 ASC NULLS LAST, x3",
|
||||
"SELECT x1, x2, x3 FROM (SELECT * FROM x) ORDER BY x1 DESC NULLS FIRST, x2 ASC NULLS LAST, x3",
|
||||
)
|
||||
for option in ("LIMIT 1", "OFFSET 2", "LIMIT 1 OFFSET 2"):
|
||||
with self.subTest(f"Testing pipe syntax LIMIT and OFFSET option: {option}"):
|
||||
self.validate_identity(f"FROM x |> {option}", f"SELECT * FROM x {option}")
|
||||
self.validate_identity(f"FROM x |> {option}", f"SELECT * FROM x {option}")
|
||||
self.validate_identity(
|
||||
f"FROM x |> {option} |> SELECT x1, x2 |> WHERE x1 > 0 |> WHERE x2 > 0 |> ORDER BY x1, x2 ",
|
||||
f"SELECT x1, x2 FROM (SELECT * FROM x {option}) WHERE x1 > 0 AND x2 > 0 ORDER BY x1, x2",
|
||||
)
|
||||
self.validate_identity(
|
||||
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}",
|
||||
)
|
||||
|
|
|
@ -568,6 +568,9 @@ class TestDuckDB(Validator):
|
|||
)
|
||||
self.validate_all(
|
||||
"STRING_TO_ARRAY(x, 'a')",
|
||||
read={
|
||||
"snowflake": "STRTOK_TO_ARRAY(x, 'a')",
|
||||
},
|
||||
write={
|
||||
"duckdb": "STR_SPLIT(x, 'a')",
|
||||
"presto": "SPLIT(x, 'a')",
|
||||
|
|
|
@ -184,6 +184,28 @@ class TestHive(Validator):
|
|||
self.validate_identity(
|
||||
"ALTER VIEW v1 UNSET TBLPROPERTIES ('tblp1', 'tblp2')", check_command_warning=True
|
||||
)
|
||||
self.validate_identity("CREATE TABLE foo (col STRUCT<struct_col_a: VARCHAR((50))>)")
|
||||
|
||||
self.validate_all(
|
||||
"CREATE TABLE db.example_table (col_a struct<struct_col_a:int, struct_col_b:string>)",
|
||||
write={
|
||||
"duckdb": "CREATE TABLE db.example_table (col_a STRUCT(struct_col_a INT, struct_col_b TEXT))",
|
||||
"presto": "CREATE TABLE db.example_table (col_a ROW(struct_col_a INTEGER, struct_col_b VARCHAR))",
|
||||
"hive": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a: INT, struct_col_b: STRING>)",
|
||||
"spark": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a: INT, struct_col_b: STRING>)",
|
||||
},
|
||||
)
|
||||
|
||||
self.validate_all(
|
||||
"CREATE TABLE db.example_table (col_a struct<struct_col_a:int, struct_col_b:struct<nested_col_a:string, nested_col_b:string>>)",
|
||||
write={
|
||||
"bigquery": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a INT64, struct_col_b STRUCT<nested_col_a STRING, nested_col_b STRING>>)",
|
||||
"duckdb": "CREATE TABLE db.example_table (col_a STRUCT(struct_col_a INT, struct_col_b STRUCT(nested_col_a TEXT, nested_col_b TEXT)))",
|
||||
"presto": "CREATE TABLE db.example_table (col_a ROW(struct_col_a INTEGER, struct_col_b ROW(nested_col_a VARCHAR, nested_col_b VARCHAR)))",
|
||||
"hive": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a: INT, struct_col_b: STRUCT<nested_col_a: STRING, nested_col_b: STRING>>)",
|
||||
"spark": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a: INT, struct_col_b: STRUCT<nested_col_a: STRING, nested_col_b: STRING>>)",
|
||||
},
|
||||
)
|
||||
|
||||
def test_lateral_view(self):
|
||||
self.validate_all(
|
||||
|
|
|
@ -111,7 +111,7 @@ class TestMySQL(Validator):
|
|||
)
|
||||
self.validate_identity(
|
||||
"CREATE TABLE test (ts TIMESTAMP, ts_tz TIMESTAMPTZ, ts_ltz TIMESTAMPLTZ)",
|
||||
"CREATE TABLE test (ts DATETIME, ts_tz TIMESTAMP, ts_ltz TIMESTAMP)",
|
||||
"CREATE TABLE test (ts TIMESTAMP, ts_tz TIMESTAMP, ts_ltz TIMESTAMP)",
|
||||
)
|
||||
self.validate_identity(
|
||||
"ALTER TABLE test_table ALTER COLUMN test_column SET DATA TYPE LONGTEXT",
|
||||
|
@ -298,7 +298,7 @@ class TestMySQL(Validator):
|
|||
)
|
||||
self.validate_identity(
|
||||
"CAST(x AS TIMESTAMP)",
|
||||
"CAST(x AS DATETIME)",
|
||||
"TIMESTAMP(x)",
|
||||
)
|
||||
self.validate_identity(
|
||||
"CAST(x AS TIMESTAMPTZ)",
|
||||
|
|
|
@ -8,19 +8,6 @@ class TestPostgres(Validator):
|
|||
dialect = "postgres"
|
||||
|
||||
def test_postgres(self):
|
||||
self.validate_all(
|
||||
"x ? y",
|
||||
write={
|
||||
"": "JSONB_CONTAINS(x, y)",
|
||||
"postgres": "x ? y",
|
||||
},
|
||||
)
|
||||
|
||||
self.validate_identity("SHA384(x)")
|
||||
self.validate_identity("1.x", "1. AS x")
|
||||
self.validate_identity("|/ x", "SQRT(x)")
|
||||
self.validate_identity("||/ x", "CBRT(x)")
|
||||
|
||||
expr = self.parse_one("SELECT * FROM r CROSS JOIN LATERAL UNNEST(ARRAY[1]) AS s(location)")
|
||||
unnest = expr.args["joins"][0].this.this
|
||||
unnest.assert_is(exp.Unnest)
|
||||
|
@ -31,6 +18,14 @@ class TestPostgres(Validator):
|
|||
self.assertIsInstance(expr, exp.Alter)
|
||||
self.assertEqual(expr.sql(dialect="postgres"), alter_table_only)
|
||||
|
||||
sql = "ARRAY[x" + ",x" * 27 + "]"
|
||||
expected_sql = "ARRAY[\n x" + (",\n x" * 27) + "\n]"
|
||||
self.validate_identity(sql, expected_sql, pretty=True)
|
||||
|
||||
self.validate_identity("SHA384(x)")
|
||||
self.validate_identity("1.x", "1. AS x")
|
||||
self.validate_identity("|/ x", "SQRT(x)")
|
||||
self.validate_identity("||/ x", "CBRT(x)")
|
||||
self.validate_identity("SELECT EXTRACT(QUARTER FROM CAST('2025-04-26' AS DATE))")
|
||||
self.validate_identity("SELECT DATE_TRUNC('QUARTER', CAST('2025-04-26' AS DATE))")
|
||||
self.validate_identity("STRING_TO_ARRAY('xx~^~yy~^~zz', '~^~', 'yy')")
|
||||
|
@ -79,6 +74,11 @@ class TestPostgres(Validator):
|
|||
self.validate_identity("SELECT CURRENT_USER")
|
||||
self.validate_identity("SELECT * FROM ONLY t1")
|
||||
self.validate_identity("SELECT INTERVAL '-1 MONTH'")
|
||||
self.validate_identity("SELECT INTERVAL '4.1 DAY'")
|
||||
self.validate_identity("SELECT INTERVAL '3.14159 HOUR'")
|
||||
self.validate_identity("SELECT INTERVAL '2.5 MONTH'")
|
||||
self.validate_identity("SELECT INTERVAL '-10.75 MINUTE'")
|
||||
self.validate_identity("SELECT INTERVAL '0.123456789 SECOND'")
|
||||
self.validate_identity(
|
||||
"SELECT * FROM test_data, LATERAL JSONB_ARRAY_ELEMENTS(data) WITH ORDINALITY AS elem(value, ordinality)"
|
||||
)
|
||||
|
@ -374,6 +374,13 @@ FROM json_data, field_ids""",
|
|||
pretty=True,
|
||||
)
|
||||
|
||||
self.validate_all(
|
||||
"x ? y",
|
||||
write={
|
||||
"": "JSONB_CONTAINS(x, y)",
|
||||
"postgres": "x ? y",
|
||||
},
|
||||
)
|
||||
self.validate_all(
|
||||
"SELECT CURRENT_TIMESTAMP + INTERVAL '-3 MONTH'",
|
||||
read={
|
||||
|
@ -1050,6 +1057,9 @@ FROM json_data, field_ids""",
|
|||
self.validate_identity(
|
||||
"CREATE UNLOGGED TABLE foo AS WITH t(c) AS (SELECT 1) SELECT * FROM (SELECT c AS c FROM t) AS temp"
|
||||
)
|
||||
self.validate_identity(
|
||||
"ALTER TABLE foo ADD COLUMN id BIGINT NOT NULL PRIMARY KEY DEFAULT 1, ADD CONSTRAINT fk_orders_user FOREIGN KEY (id) REFERENCES foo (id)"
|
||||
)
|
||||
self.validate_identity(
|
||||
"CREATE TABLE t (col integer ARRAY[3])",
|
||||
"CREATE TABLE t (col INT[3])",
|
||||
|
|
|
@ -511,7 +511,7 @@ class TestPresto(Validator):
|
|||
write={
|
||||
"duckdb": "CREATE TABLE db.example_table (col_a STRUCT(struct_col_a INT, struct_col_b TEXT))",
|
||||
"presto": "CREATE TABLE db.example_table (col_a ROW(struct_col_a INTEGER, struct_col_b VARCHAR))",
|
||||
"hive": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a INT, struct_col_b STRING>)",
|
||||
"hive": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a: INT, struct_col_b: STRING>)",
|
||||
"spark": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a: INT, struct_col_b: STRING>)",
|
||||
},
|
||||
)
|
||||
|
@ -520,7 +520,7 @@ class TestPresto(Validator):
|
|||
write={
|
||||
"duckdb": "CREATE TABLE db.example_table (col_a STRUCT(struct_col_a INT, struct_col_b STRUCT(nested_col_a TEXT, nested_col_b TEXT)))",
|
||||
"presto": "CREATE TABLE db.example_table (col_a ROW(struct_col_a INTEGER, struct_col_b ROW(nested_col_a VARCHAR, nested_col_b VARCHAR)))",
|
||||
"hive": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a INT, struct_col_b STRUCT<nested_col_a STRING, nested_col_b STRING>>)",
|
||||
"hive": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a: INT, struct_col_b: STRUCT<nested_col_a: STRING, nested_col_b: STRING>>)",
|
||||
"spark": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a: INT, struct_col_b: STRUCT<nested_col_a: STRING, nested_col_b: STRING>>)",
|
||||
},
|
||||
)
|
||||
|
|
|
@ -27,7 +27,7 @@ class TestSpark(Validator):
|
|||
write={
|
||||
"duckdb": "CREATE TABLE db.example_table (col_a STRUCT(struct_col_a INT, struct_col_b TEXT))",
|
||||
"presto": "CREATE TABLE db.example_table (col_a ROW(struct_col_a INTEGER, struct_col_b VARCHAR))",
|
||||
"hive": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a INT, struct_col_b STRING>)",
|
||||
"hive": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a: INT, struct_col_b: STRING>)",
|
||||
"spark": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a: INT, struct_col_b: STRING>)",
|
||||
},
|
||||
)
|
||||
|
@ -37,7 +37,7 @@ class TestSpark(Validator):
|
|||
"bigquery": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a INT64, struct_col_b STRUCT<nested_col_a STRING, nested_col_b STRING>>)",
|
||||
"duckdb": "CREATE TABLE db.example_table (col_a STRUCT(struct_col_a INT, struct_col_b STRUCT(nested_col_a TEXT, nested_col_b TEXT)))",
|
||||
"presto": "CREATE TABLE db.example_table (col_a ROW(struct_col_a INTEGER, struct_col_b ROW(nested_col_a VARCHAR, nested_col_b VARCHAR)))",
|
||||
"hive": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a INT, struct_col_b STRUCT<nested_col_a STRING, nested_col_b STRING>>)",
|
||||
"hive": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a: INT, struct_col_b: STRUCT<nested_col_a: STRING, nested_col_b: STRING>>)",
|
||||
"spark": "CREATE TABLE db.example_table (col_a STRUCT<struct_col_a: INT, struct_col_b: STRUCT<nested_col_a: STRING, nested_col_b: STRING>>)",
|
||||
},
|
||||
)
|
||||
|
|
|
@ -62,6 +62,13 @@ class TestTSQL(Validator):
|
|||
"SELECT 1 WHERE EXISTS(SELECT 1)",
|
||||
)
|
||||
|
||||
self.validate_all(
|
||||
"SELECT CONVERT(DATETIME, '2006-04-25T15:50:59.997', 126)",
|
||||
write={
|
||||
"duckdb": "SELECT STRPTIME('2006-04-25T15:50:59.997', '%Y-%m-%dT%H:%M:%S.%f')",
|
||||
"tsql": "SELECT CONVERT(DATETIME, '2006-04-25T15:50:59.997', 126)",
|
||||
},
|
||||
)
|
||||
self.validate_all(
|
||||
"WITH A AS (SELECT 2 AS value), C AS (SELECT * FROM A) SELECT * INTO TEMP_NESTED_WITH FROM (SELECT * FROM C) AS temp",
|
||||
read={
|
||||
|
@ -569,6 +576,79 @@ class TestTSQL(Validator):
|
|||
},
|
||||
)
|
||||
|
||||
def test_for_xml(self):
|
||||
xml_possible_options = [
|
||||
"RAW('ElementName')",
|
||||
"RAW('ElementName'), BINARY BASE64",
|
||||
"RAW('ElementName'), TYPE",
|
||||
"RAW('ElementName'), ROOT('RootName')",
|
||||
"RAW('ElementName'), BINARY BASE64, TYPE",
|
||||
"RAW('ElementName'), BINARY BASE64, ROOT('RootName')",
|
||||
"RAW('ElementName'), TYPE, ROOT('RootName')",
|
||||
"RAW('ElementName'), BINARY BASE64, TYPE, ROOT('RootName')",
|
||||
"RAW('ElementName'), XMLDATA",
|
||||
"RAW('ElementName'), XMLSCHEMA('TargetNameSpaceURI')",
|
||||
"RAW('ElementName'), XMLDATA, ELEMENTS XSINIL",
|
||||
"RAW('ElementName'), XMLSCHEMA('TargetNameSpaceURI'), ELEMENTS ABSENT",
|
||||
"RAW('ElementName'), XMLDATA, ELEMENTS ABSENT",
|
||||
"RAW('ElementName'), XMLSCHEMA('TargetNameSpaceURI'), ELEMENTS XSINIL",
|
||||
"AUTO",
|
||||
"AUTO, BINARY BASE64",
|
||||
"AUTO, TYPE",
|
||||
"AUTO, ROOT('RootName')",
|
||||
"AUTO, BINARY BASE64, TYPE",
|
||||
"AUTO, TYPE, ROOT('RootName')",
|
||||
"AUTO, BINARY BASE64, TYPE, ROOT('RootName')",
|
||||
"AUTO, XMLDATA",
|
||||
"AUTO, XMLSCHEMA('TargetNameSpaceURI')",
|
||||
"AUTO, XMLDATA, ELEMENTS XSINIL",
|
||||
"AUTO, XMLSCHEMA('TargetNameSpaceURI'), ELEMENTS ABSENT",
|
||||
"AUTO, XMLDATA, ELEMENTS ABSENT",
|
||||
"AUTO, XMLSCHEMA('TargetNameSpaceURI'), ELEMENTS XSINIL",
|
||||
"EXPLICIT",
|
||||
"EXPLICIT, BINARY BASE64",
|
||||
"EXPLICIT, TYPE",
|
||||
"EXPLICIT, ROOT('RootName')",
|
||||
"EXPLICIT, BINARY BASE64, TYPE",
|
||||
"EXPLICIT, TYPE, ROOT('RootName')",
|
||||
"EXPLICIT, BINARY BASE64, TYPE, ROOT('RootName')",
|
||||
"EXPLICIT, XMLDATA",
|
||||
"EXPLICIT, XMLDATA, BINARY BASE64",
|
||||
"EXPLICIT, XMLDATA, TYPE",
|
||||
"EXPLICIT, XMLDATA, ROOT('RootName')",
|
||||
"EXPLICIT, XMLDATA, BINARY BASE64, TYPE",
|
||||
"EXPLICIT, XMLDATA, BINARY BASE64, TYPE, ROOT('RootName')",
|
||||
"PATH('ElementName')",
|
||||
"PATH('ElementName'), BINARY BASE64",
|
||||
"PATH('ElementName'), TYPE",
|
||||
"PATH('ElementName'), ROOT('RootName')",
|
||||
"PATH('ElementName'), BINARY BASE64, TYPE",
|
||||
"PATH('ElementName'), TYPE, ROOT('RootName')",
|
||||
"PATH('ElementName'), BINARY BASE64, TYPE, ROOT('RootName')",
|
||||
"PATH('ElementName'), ELEMENTS XSINIL",
|
||||
"PATH('ElementName'), ELEMENTS ABSENT",
|
||||
"PATH('ElementName'), BINARY BASE64, ELEMENTS XSINIL",
|
||||
"PATH('ElementName'), TYPE, ELEMENTS ABSENT",
|
||||
"PATH('ElementName'), ROOT('RootName'), ELEMENTS XSINIL",
|
||||
"PATH('ElementName'), BINARY BASE64, TYPE, ROOT('RootName'), ELEMENTS ABSENT",
|
||||
]
|
||||
|
||||
for xml_option in xml_possible_options:
|
||||
with self.subTest(f"Testing FOR XML option: {xml_option}"):
|
||||
self.validate_identity(f"SELECT * FROM t FOR XML {xml_option}")
|
||||
|
||||
self.validate_identity(
|
||||
"SELECT * FROM t FOR XML PATH, BINARY BASE64, ELEMENTS XSINIL",
|
||||
"""SELECT
|
||||
*
|
||||
FROM t
|
||||
FOR XML
|
||||
PATH,
|
||||
BINARY BASE64,
|
||||
ELEMENTS XSINIL""",
|
||||
pretty=True,
|
||||
)
|
||||
|
||||
def test_types(self):
|
||||
self.validate_identity("CAST(x AS XML)")
|
||||
self.validate_identity("CAST(x AS UNIQUEIDENTIFIER)")
|
||||
|
@ -904,18 +984,18 @@ class TestTSQL(Validator):
|
|||
|
||||
self.validate_identity("CREATE SCHEMA testSchema")
|
||||
self.validate_identity("CREATE VIEW t AS WITH cte AS (SELECT 1 AS c) SELECT c FROM cte")
|
||||
self.validate_identity("ALTER TABLE tbl SET SYSTEM_VERSIONING=OFF")
|
||||
self.validate_identity("ALTER TABLE tbl SET FILESTREAM_ON = 'test'")
|
||||
self.validate_identity("ALTER TABLE tbl SET DATA_DELETION=ON")
|
||||
self.validate_identity("ALTER TABLE tbl SET DATA_DELETION=OFF")
|
||||
self.validate_identity("ALTER TABLE tbl SET (SYSTEM_VERSIONING=OFF)")
|
||||
self.validate_identity("ALTER TABLE tbl SET (FILESTREAM_ON = 'test')")
|
||||
self.validate_identity("ALTER TABLE tbl SET (DATA_DELETION=ON)")
|
||||
self.validate_identity("ALTER TABLE tbl SET (DATA_DELETION=OFF)")
|
||||
self.validate_identity(
|
||||
"ALTER TABLE tbl SET SYSTEM_VERSIONING=ON(HISTORY_TABLE=db.tbl, DATA_CONSISTENCY_CHECK=OFF, HISTORY_RETENTION_PERIOD=5 DAYS)"
|
||||
"ALTER TABLE tbl SET (SYSTEM_VERSIONING=ON(HISTORY_TABLE=db.tbl, DATA_CONSISTENCY_CHECK=OFF, HISTORY_RETENTION_PERIOD=5 DAYS))"
|
||||
)
|
||||
self.validate_identity(
|
||||
"ALTER TABLE tbl SET SYSTEM_VERSIONING=ON(HISTORY_TABLE=db.tbl, HISTORY_RETENTION_PERIOD=INFINITE)"
|
||||
"ALTER TABLE tbl SET (SYSTEM_VERSIONING=ON(HISTORY_TABLE=db.tbl, HISTORY_RETENTION_PERIOD=INFINITE))"
|
||||
)
|
||||
self.validate_identity(
|
||||
"ALTER TABLE tbl SET DATA_DELETION=ON(FILTER_COLUMN=col, RETENTION_PERIOD=5 MONTHS)"
|
||||
"ALTER TABLE tbl SET (DATA_DELETION=ON(FILTER_COLUMN=col, RETENTION_PERIOD=5 MONTHS))"
|
||||
)
|
||||
|
||||
self.validate_identity("ALTER VIEW v AS SELECT a, b, c, d FROM foo")
|
||||
|
|
|
@ -957,7 +957,7 @@ class TestParser(unittest.TestCase):
|
|||
ast = parse_one("YEAR(a) /* sqlglot.anon */")
|
||||
self.assertIsInstance(ast, exp.Year)
|
||||
|
||||
def test_identifier_meta(self):
|
||||
def test_token_position_meta(self):
|
||||
ast = parse_one(
|
||||
"SELECT a, b FROM test_schema.test_table_a UNION ALL SELECT c, d FROM test_catalog.test_schema.test_table_b"
|
||||
)
|
||||
|
@ -988,6 +988,12 @@ class TestParser(unittest.TestCase):
|
|||
ast = parse_one("SELECT FOO()")
|
||||
self.assertEqual(ast.find(exp.Anonymous).meta, {"line": 1, "col": 10, "start": 7, "end": 9})
|
||||
|
||||
ast = parse_one("SELECT * FROM t")
|
||||
self.assertEqual(ast.find(exp.Star).meta, {"line": 1, "col": 8, "start": 7, "end": 7})
|
||||
|
||||
ast = parse_one("SELECT t.* FROM t")
|
||||
self.assertEqual(ast.find(exp.Star).meta, {"line": 1, "col": 10, "start": 9, "end": 9})
|
||||
|
||||
def test_quoted_identifier_meta(self):
|
||||
sql = 'SELECT "a" FROM "test_schema"."test_table_a"'
|
||||
ast = parse_one(sql)
|
||||
|
|
|
@ -186,3 +186,18 @@ x"""
|
|||
(TokenType.STRING, ") }}"),
|
||||
],
|
||||
)
|
||||
|
||||
def test_partial_token_list(self):
|
||||
tokenizer = Tokenizer()
|
||||
|
||||
try:
|
||||
# This is expected to fail due to the unbalanced string quotes
|
||||
tokenizer.tokenize("foo 'bar")
|
||||
except TokenError as e:
|
||||
self.assertIn("Error tokenizing 'foo 'ba'", str(e))
|
||||
|
||||
partial_tokens = tokenizer.tokens
|
||||
|
||||
self.assertEqual(len(partial_tokens), 1)
|
||||
self.assertEqual(partial_tokens[0].token_type, TokenType.VAR)
|
||||
self.assertEqual(partial_tokens[0].text, "foo")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue