apache / apache/datafusion-sqlparser-rs
Keywords are parsed as functions in select statements
- Lingua principale
- Rust
- Stelle
- 3.5k
- Fork
- 772
- Merge medio
- 4g 9h
- PR unite (30g)
- 17
Descrizione
# Abstract
Qualified names like of the form `.` are sometimes parsed as functions, like in:
```sql
SELECT t.user FROM t;
```
# Current Behavior
This is done with `cargo run --example cli -- test.sql --generic`:
```sql
select t.user from t;
```
results in:
```text
[
Query(
Query {
with: None,
body: Select(
Select {
select_token: TokenWithSpan {
token: Word(
Word {
value: "select",
quote_style: None,
keyword: SELECT,
},
),
span: Span(Location(1,1)..Location(1,7)),
},
distinct: None,
top: None,
top_before_distinct: false,
projection: [
UnnamedExpr(
Function(
Function {
name: ObjectName(
[
Identifier(
Ident {
value: "t",
quote_style: None,
span: Span(Location(1,8)..Location(1,9)),
},
),
Identifier(
Ident {
value: "user",
quote_style: None,
span: Span(Location(1,10)..Location(1,14)),
},
),
],
),
uses_odbc_syntax: false,
parameters: None,
args: None,
filter: None,
null_treatment: None,
over: None,
within_group: [],
},
),
),
],
into: None,
from: [
TableWithJoins {
relation: Table {
name: ObjectName(
[
Identifier(
Ident {
value: "t",
quote_style: None,
span: Span(Location(1,20)..Location(1,21)),
},
),
],
),
alias: None,
args: None,
with_hints: [],
version: None,
with_ordinality: false,
partitions: [],
json_path: None,
sample: None,
index_hints: [],
},
joins: [],
},
],
lateral_views: [],
prewhere: None,
selection: None,
group_by: Expressions(
[],
[],
),
cluster_by: [],
distribute_by: [],
sort_by: [],
having: None,
named_window: [],
qualify: None,
window_before_qualify: false,
value_table_mode: None,
connect_by: None,
flavor: Standard,
},
),
order_by: None,
limit_clause: None,
fetch: None,
locks: [],
for_clause: None,
settings: None,
format_clause: None,
pipe_operators: [],
},
),
]
```
and `cargo run --example cli -- test.sql --postgres` is the same:
```text
[
Query(
Query {
with: None,
body: Select(
Select {
select_token: TokenWithSpan {
token: Word(
Word {
value: "select",
quote_style: None,
keyword: SELECT,
},
),
span: Span(Location(1,1)..Location(1,7)),
},
distinct: None,
top: None,
top_before_distinct: false,
projection: [
UnnamedExpr(
Function(
Function {
name: ObjectName(
[
Identifier(
Ident {
value: "t",
quote_style: None,
span: Span(Location(1,8)..Location(1,9)),
},
),
Identifier(
Ident {
value: "user",
quote_style: None,
span: Span(Location(1,10)..Location(1,14)),
},
),
],
),
uses_odbc_syntax: false,
parameters: None,
args: None,
filter: None,
null_treatment: None,
over: None,
within_group: [],
},
),
),
],
into: None,
from: [
TableWithJoins {
relation: Table {
name: ObjectName(
[
Identifier(
Ident {
value: "t",
quote_style: None,
span: Span(Location(1,20)..Location(1,21)),
},
),
],
),
alias: None,
args: None,
with_hints: [],
version: None,
with_ordinality: false,
partitions: [],
json_path: None,
sample: None,
index_hints: [],
},
joins: [],
},
],
lateral_views: [],
prewhere: None,
selection: None,
group_by: Expressions(
[],
[],
),
cluster_by: [],
distribute_by: [],
sort_by: [],
having: None,
named_window: [],
qualify: None,
window_before_qualify: false,
value_table_mode: None,
connect_by: None,
flavor: Standard,
},
),
order_by: None,
limit_clause: None,
fetch: None,
locks: [],
for_clause: None,
settings: None,
format_clause: None,
pipe_operators: [],
},
),
]
```
# Expected Behavior
I think this should parse similar to
```sql
select t.foo from t;
```
with `cargo run --example cli -- test.sql --generic`:
```text
[
Query(
Query {
with: None,
body: Select(
Select {
select_token: TokenWithSpan {
token: Word(
Word {
value: "select",
quote_style: None,
keyword: SELECT,
},
),
span: Span(Location(1,1)..Location(1,7)),
},
distinct: None,
top: None,
top_before_distinct: false,
projection: [
UnnamedExpr(
CompoundIdentifier(
[
Ident {
value: "t",
quote_style: None,
span: Span(Location(1,8)..Location(1,9)),
},
Ident {
value: "foo",
quote_style: None,
span: Span(Location(1,10)..Location(1,13)),
},
],
),
),
],
into: None,
from: [
TableWithJoins {
relation: Table {
name: ObjectName(
[
Identifier(
Ident {
value: "t",
quote_style: None,
span: Span(Location(1,19)..Location(1,20)),
},
),
],
),
alias: None,
args: None,
with_hints: [],
version: None,
with_ordinality: false,
partitions: [],
json_path: None,
sample: None,
index_hints: [],
},
joins: [],
},
],
lateral_views: [],
prewhere: None,
selection: None,
group_by: Expressions(
[],
[],
),
cluster_by: [],
distribute_by: [],
sort_by: [],
having: None,
named_window: [],
qualify: None,
window_before_qualify: false,
value_table_mode: None,
connect_by: None,
flavor: Standard,
},
),
order_by: None,
limit_clause: None,
fetch: None,
locks: [],
for_clause: None,
settings: None,
format_clause: None,
pipe_operators: [],
},
),
]
```
# Others
Also see PostgreSQL:
```text
psql (17.5 (Debian 17.5-1.pgdg120+1))
Type "help" for help.
postgres=# create table t(a int, "user" text);
CREATE TABLE
postgres=# insert into t values (1, 'foo');
INSERT 0 1
postgres=# select t.user from t;
user
------
foo
(1 row)
```
Interestingly, even the plain `user` works:
```text
postgres=# select user from t;
user
----------
postgres
(1 row)
```
# References
- a potentially valid case of treating `user` as a function: #1658
- downstream: https://github.com/apache/datafusion/issues/14141
Guida per i contributori
Nessuna guida per i contributori indicizzata per questo repository
Direzione di ricerca
Riproduci il problema con il comando cargo run --example cli menzionato usando test.sql e sia --generic sia --postgres. Traccia il parsing dell’espressione SQL che classifica t.user come Function invece del CompoundIdentifier mostrato per t.foo, quindi aggiungi una coverage per la query che fallisce e verifica che entrambi i dialetti producano la forma di parsing prevista.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- rust, sql
- Ambito
- compilers
- Tipo di issue
- Bug
- Difficoltà
- 3/5
- Tempo stimato
- 1-2 giorni
- Stato di attività
- Ferma
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 45/100