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

Reply via email to