Repository navigation
SQLite: Support IN with a table name or table-valued function - #2680
LucaCappelletti94 wants to merge 8 commits into
Conversation
d231a4c to
bd79005
Compare
bd79005 to
4cfa09d
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2680 +/- ##
==========================================
+ Coverage 81.94% 82.03% +0.08%
==========================================
Files 42 42
Lines 34949 35004 +55
Branches 34949 35004 +55
==========================================
+ Hits 28638 28714 +76
+ Misses 2744 2721 -23
- Partials 3567 3569 +2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
9ecae2c to
2e2304d
Compare
| InTarget::Unnest(Box::new(array_expr)) | ||
| } else if !global | ||
| && self.dialect.supports_in_table_expression() | ||
| && matches!(self.peek_token_ref().token, Token::Word(_)) |
There was a problem hiding this comment.
Any word is taken as the table name, so SELECT 1 IN FROM t parses and round-trips to SELECT 1 IN FROM AS t. Worth the same reserved-keyword check as the table factor position (is_table_factor, cf. #2633).
There was a problem hiding this comment.
is_table_factor with the shared list would still accept this one, since FROM is not in RESERVED_FOR_TABLE_FACTOR. I ran every keyword of the crate through SQLite 3.51.1 as SELECT 1 IN <kw>, and SQLite refuses 57 of them there, so now SQLiteDialect overrides is_table_factor with those, so SELECT 1 IN FROM t fails again.
228f53d to
ed9c13d
Compare
3910006 to
74938bb
Compare
s5dsn-eqee
left a comment
There was a problem hiding this comment.
LGTM! Left a few non-blocking comments inline.
| /// Returns true if the next token is a word the dialect accepts as a table | ||
| /// name. The word is consumed while asking, so `is_table_factor` peeks past | ||
| /// it as it does at the trailing comma check. | ||
| fn next_word_is_table_name(&mut self) -> bool { |
There was a problem hiding this comment.
might be next_word_is_table_factor?
| true | ||
| } | ||
|
|
||
| fn supports_in_table_expression(&self) -> bool { |
There was a problem hiding this comment.
GenericDialect now accepts reserved words as an IN table name, because it
keeps the default is_table_factor (which reserves only INTO, LIMIT,
HAVING, WHERE). Inputs that failed with Expected: ( before now parse:
SELECT 1 IN NULL-> table namedNULLSELECT 1 IN select-> table namedselectSELECT 1 IN case-> table namedcase
| @@ -0,0 +1,3 @@ | |||
| SELECT a IN t, a NOT IN t, a IN main.t, a IN f(), a NOT IN f(1, 2), a IN main.f(1) FROM t; | |||
d399102 to
afe93cf
Compare
Stacked on the
INrefactor PR.In SQLite "the right-hand side of an IN or NOT IN operator can be a table name or table-valued function name in which case the right-hand side is understood to be a subquery of the form
(SELECT * FROM name)" (https://www.sqlite.org/lang_expr.html#in_op). SQLite 3.51.1 runsSELECT 1 IN t,SELECT 1 NOT IN tandSELECT 1 IN main.t, but the SQLite dialect failed withExpected: (, found: t.InTargetgains aTable { name, args }variant, and a new dialect method,supports_in_table_expression, enables it for SQLite and the generic dialect. It does not apply to ClickHouse'sGLOBAL IN. Tests round-trip plain, qualified and function forms with and withoutNOT, check the parsed name and arguments, and check that parenthesized lists and subqueries still parse as before.