apache / apache/datafusion-sqlparser-rs

[PG Dialect] `SELECT ARRAY(SELECT 1)` fails to parse

オープン
#400 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る
主要言語
Rust
スター
3.5k
フォーク
772
平均マージ
4日 9時間
マージ済み PR(30日)
17

説明

Whilst working on a project that uses `sqlparser` to parse some real SQL queries from a common PG client (PGAdmin 6.1) I found that the following query emitted by PGAdmin at startup fails to parse correctly:

```sql
SELECT
roles.oid as id, roles.rolname as name,
roles.rolsuper as is_superuser,
CASE WHEN roles.rolsuper THEN true ELSE roles.rolcreaterole END as
can_create_role,
CASE WHEN roles.rolsuper THEN true
ELSE roles.rolcreatedb END as can_create_db,
CASE WHEN 'pg_signal_backend'=ANY(ARRAY(WITH RECURSIVE cte AS (
SELECT pg_roles.oid,pg_roles.rolname FROM pg_roles
WHERE pg_roles.oid = roles.oid
UNION ALL
SELECT m.roleid,pgr.rolname FROM cte cte_1
JOIN pg_auth_members m ON m.member = cte_1.oid
JOIN pg_roles pgr ON pgr.oid = m.roleid)
SELECT rolname FROM cte)) THEN True
ELSE False END as can_signal_backend
FROM
pg_catalog.pg_roles as roles
WHERE
rolname = current_user
```

I poked around a bit and managed to reduce the failing query to:

```sql
SELECT ARRAY(SELECT 1))
```

which against PG 13 produces the following results:

```
edd=# SELECT ARRAY(SELECT 1);
array
-------
{1}
(1 row)
```

However, the following program panics:

```rust
use sqlparser;

let q = "SELECT ARRAY(SELECT 1)";
let dialect = sqlparser::dialect::PostgreSqlDialect {};
let ast = sqlparser::parser::Parser::parse_sql(&dialect, &q).unwrap();
```

with the following panic (due to an error being returned)

```
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ParserError("Expected ), found: 1")
```

Finally, if I change the query to something that is _invalid_ in PG:

```sql
SELECT ARRAY(1);
```

then whilst this query fails against PG 13 it actually gets parsed by `sqlparser`:

```
[2022-01-06T18:38:38Z DEBUG sqlparser::parser] Parsing sql 'SELECT ARRAY(1)'...
[2022-01-06T18:38:38Z DEBUG sqlparser::parser] parsing expr
[2022-01-06T18:38:38Z DEBUG sqlparser::parser] parsing expr
[2022-01-06T18:38:38Z DEBUG sqlparser::parser] prefix: Value(Number("1", false))
[2022-01-06T18:38:38Z DEBUG sqlparser::parser] get_next_precedence() RParen
[2022-01-06T18:38:38Z DEBUG sqlparser::parser] next precedence: 0
[2022-01-06T18:38:38Z DEBUG sqlparser::parser] prefix: Function(Function { name: ObjectName([Ident { value: "ARRAY", quote_style: None }]), args: [Unnamed(Value(Number("1", false)))], over: None, distinct: false })
[2022-01-06T18:38:38Z DEBUG sqlparser::parser] get_next_precedence() EOF
[2022-01-06T18:38:38Z DEBUG sqlparser::parser] next precedence: 0
```

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

調査の方向性

まず、PostgreSqlDialect を指定して SELECT ARRAY(SELECT 1) に対して Parser::parse_sql を実行し、ARRAY を処理する PostgreSQL の式パーシング経路を追跡してください。この有効なクエリのリグレッションテストを追加し、パースが成功することを確認するとともに、無効な ARRAY(1) の例に対する既存の動作を維持してください。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
postgresql, rust, sql
領域
databases
issue の種類
バグ
難易度
3/5
見積もり時間
1〜2日
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
48/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。