apache / apache/datafusion-sqlparser-rs
Support for `IN $placeholder` syntax
- Ngôn ngữ chính
- Rust
- Star
- 3.5k
- Fork
- 772
- Merge trung bình
- 4 ngày 9 giờ
- Pull request đã merge (30 ngày)
- 17
Mô tả
Some DBs support using placeholders for `IN` clauses in prepared statements. For example in DuckDB:
```
$ duckdb
DuckDB v1.3.0 (Ossivalis) 71c5c07cdd
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
D PREPARE qry AS SELECT 'a' in $list;
D EXECUTE qry(list := ['a', 'b']);
┌──────────────────────┐
│ contains($list, 'a') │
│ boolean │
├──────────────────────┤
│ true │
└──────────────────────┘
```
However, currently the parser doesn't handle this, for example:
```rust
#[test]
fn test_parse_in_placeholder() {
let stmt = all_dialects().verified_stmt("SELECT i IN $placeholder");
dbg!(&stmt);
}
```
Fails w/ `SELECT i IN $placeholder: ParserError("Expected: (, found: $placeholder")`.
To fix this, I think we would need to make two changes:
First off, the definition of `Expr::InList`:
```rust
/// `[ NOT ] IN (val1, val2, ...)`
InList {
expr: Box,
list: Vec,
negated: bool,
},
```
The issue is that `list` is always a Vec, where in this case we want list to be a `Expr::Value` w/ `value = Placeholder("$placeholder")`.
If `InList` supports that, then in `parse_in` we can do a check like this before the `expect_token(LParen)`:
```rust
if let Token::Placeholder(_) = &self.peek_token_ref().token {
let placeholder = self.parse_expr()?;
return Ok(Expr::InList {
expr: Box::new(expr),
list: placeholder,
negated,
})
};
self.expect_token(&Token::LParen)?;
```
But, how can we cleanly support this, without too much breakage for existing consumers? Note that I considered just putting the placeholder inside the list, but that doesn't work since that would represent `IN ($placeholder)` which has a very different meaning.
Hướng dẫn đóng góp
Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này
Hướng nghiên cứu
Bắt đầu với định nghĩa Expr::InList và logic parse_in của parser, sau đó chạy case all_dialects().verified_stmt("SELECT i IN $placeholder") được cung cấp để tái hiện lỗi. Xác định một biểu diễn phân biệt IN $placeholder với IN ($placeholder), đồng thời hạn chế ảnh hưởng đến các consumer hiện có, và bổ sung coverage cho thấy cả hai dạng đều được parse chính xác.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- rust, sql
- Lĩnh vực
- compilers, databases
- Loại issue
- Tính năng
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 35/100