-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Parser fails recognising set operations in correlated subqueries #918
Comments
I'm really curious how this could be fixed in a recursive descent parser, @thomasmueller / @grandinj :-) There are so many edge cases, including: Parentheses can wrap a sum:select (((select 1) union (select 1)) + 1) Parentheses can wrap a row value expression (array in H2):select (((select 1) union (select 1)), 1) The problem is that this call to Is already inside of some parentheses that really belongs to a select statement, not to an expression. In other words: select ( ((select 1) union (select 1)) + 1 )
-- ^ ^^
-- | ++--- Parentheses belonging to a select
-- +---- Parentheses belonging to an expression |
Usually, a recursive descent parser either uses context or look-ahead to solve the problem. What does the stack above readTerm look like? |
I suspect here we will need a new method readExpressionOrSelect, which keeps peeling off parentheses until it hits something that resolves the ambiguity, we have similar methods elsewhere in that class |
This is the stack when I'm reaching the following position:
Stack:
And then, the parser fails because it expects a closing parenthesis rather than a
I'm just doing the same thing in jOOQ's parser right now, which solves the problem. Whenever I encounter a I'm not too fond of this solution as it isn't linear and might take quite some time when parsing something extreme... |
If you're interested, this is a short program helping to reproduce this: import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class H2 {
public static void main(String[] args) throws Exception {
Class.forName("org.h2.Driver");
String url = "jdbc:h2:~/test";
String user = "sa";
String password = "";
try (Connection c = DriverManager.getConnection(url, user, password);
Statement s = c.createStatement();
ResultSet rs = s.executeQuery("select (((select 1) union (select 1)) + 1)")) {
while (rs.next())
System.out.println(rs.getString(1));
}
}
} |
Hmmm, it's the brackets that are confusing us. Both work for me. Not sure how to fix it. |
As you mentioned here: #918 (comment) Essentially, you'll have to "look ahead" inside of
The way I solved it for jOOQ is before consuming the opening paren, I'm peeking into all the immediately subsequent parens for a Example for:
Pseudo parse stack: 1
2
3
I'm not sure if this is the most efficient way to parse this kind of syntax as we need to look ahead and try parsing a subquery until it works, or "peel off" those parentheses, assuming ordinary parenthesised expressions, until we do find a subquery. But the overhead should be manageable given that this is probably not a very frequent edge case. |
I don't see anyone assign for that bug, can you please suggest a workaround for my use case? #2050 |
You need to rewrite a query to make
|
The following query runs fine in PostgreSQL:
H2 fails to parse it with the following exception:
As a workaround, this works:
But if
ORDER BY .. LIMIT
would be required in the first set operation subquery, then there wouldn't be a reasonable solution, as the parentheses around that first subquery are now mandatory:The text was updated successfully, but these errors were encountered: