On 10/03/2021 05:30, Dmitry Yemanov wrote: > 06.03.2021 14:53, Mark Rotteveel wrote: > >> Now I wonder, what would be necessary to introduce this alternative? >> Would this be a matter of adding the right alternative and adding the >> order by and offset/fetch info to the RseNode returned by the query >> expression, or would more be needed? > > I'm afraid it's not gonna work. > > RseNode has dsqlOrder, but it's not used directly inside the parser > (query_spec does not define ordering itself), so at the first glance it > looks like it could be safely assigned in the new parser rules. However, > implementation inside pass1.cpp moves the order node from SelectExprNode > into underlying RseNode::dsqlOrder, so it might undo your work at the > parser level in cases like this: > > ( select ... order by A ) order by B > > in this particular example it's OK, as nobody would see the ordering by > A anyway. But it FIRST/ROWS/FETCH is applied too, ordering by A becomes > a requirement. > > As for OFFSET/FETCH, things are even trickier. RseNode supports > dsqlFirst/dsqlSkip, but they're used for legacy FIRST/SKIP inside > query_spec. What to do in these cases: > > (select first 10 ...) fetch first 5 rows > ( select ... fetch first 10 rows ) fetch first 5 rows > > where "10" may be replaced with "5". This looks safer than for the ORDER > BY case but I'm not sure I can see all the subsequences. > > Perhaps query_term should return SelectExprNode* and the new parser > rules define new SelectExprNode with querySpec/orderClause/rowsClause > set up based on select_expr_body/order_clause_opt/rows_clause. But I'm > pretty sure some code places are not prepared to see query_term as > SelectExprNode*. >
I did some tests and attached is a patch (v3). It introduces conflicts which I didn't looked yet. Looks like it's with derived tables support. It allows this funny statement: (select * from t); If I'm looking in the standard correctly, at least from syntax rules it should be allowed. :) After reading your examples again, perhaps you knew about it. :) Adriano
diff --git a/src/dsql/parse.y b/src/dsql/parse.y index e2a4070b73..436609d201 100644 --- a/src/dsql/parse.y +++ b/src/dsql/parse.y @@ -5072,9 +5072,36 @@ select_expr_body } ; -%type <rseNode> query_term +%type <recSourceNode> query_term query_term + : query_primary + ; + +%type <recSourceNode> query_primary +query_primary : query_spec + { $$ = $1; } + | '(' select_expr_body order_clause result_offset_clause fetch_first_clause ')' + { + if ($3 || $4 || $5) + { + SelectExprNode* node = newNode<SelectExprNode>(); + node->querySpec = $2; + node->orderClause = $3; + + if ($4 || $5) + { + RowsClause* rowsNode = newNode<RowsClause>(); + rowsNode->skip = $4; + rowsNode->length = $5; + node->rowsClause = rowsNode; + } + + $$ = node; + } + else + $$ = $2; + } ; %type <rseNode> query_spec
Firebird-Devel mailing list, web interface at https://lists.sourceforge.net/lists/listinfo/firebird-devel