apache / apache/datafusion-sqlparser-rs

Keywords are parsed as functions in select statements

Aberta
#1,909 0 comentários 0 reações 0 responsáveis Ver no GitHub
Linguagem predominante
Rust
Estrelas
3.5k
Forks
772
Merge médio
4d 9h
PRs com merge (30d)
17

Descrição

# 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

Guia de contribuição

Nenhum guia de contribuição indexado para este repositório

Direção de pesquisa

Reproduza o problema com o comando mencionado cargo run --example cli usando test.sql e tanto --generic quanto --postgres. Rastreie o parsing da expressão SQL que classifica t.user como Function em vez do CompoundIdentifier mostrado para t.foo; depois, adicione cobertura para a consulta que falha e verifique se ambos os dialetos produzem a forma de parsing esperada.

Escrita pelo modelo de indexação a partir do texto da issue.

Avaliação

Stack de tecnologia
rust, sql
Domínio
compilers
Tipo de issue
Bug
Dificuldade
3/5
Tempo estimado
1-2 dias
Status de atividade
Estagnada
Clareza
Razoavelmente clara
Facilidade para iniciantes
45/100

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.