MCPcopy Create free account
hub / github.com/FirebirdSQL/firebird / pass1RecursiveCte

Method pass1RecursiveCte

src/dsql/DsqlCompilerScratch.cpp:744–923  ·  view source on GitHub ↗

Process derived table which can be recursive CTE. If it is non-recursive return input node unchanged. If it is recursive return new derived table which is an union of union of anchor (non-recursive) queries and union of recursive queries. Check recursive queries to satisfy various criteria. Note that our parser is right-to-left therefore nested list linked as first node in parent list and second n

Source from the content-addressed store, hash-verified

742// Also, we should not change layout of original parse tree to allow it to be parsed again if
743// needed. Therefore recursive part is built using newly allocated list nodes.
744SelectExprNode* DsqlCompilerScratch::pass1RecursiveCte(SelectExprNode* input)
745{
746 RecordSourceNode* const query = input->querySpec;
747 UnionSourceNode* unionQuery = nodeAs<UnionSourceNode>(query);
748
749 if (!unionQuery)
750 {
751 if (!pass1RseIsRecursive(nodeAs<RseNode>(query)))
752 return input;
753
754 ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
755 // Recursive CTE (%s) must be an UNION
756 Arg::Gds(isc_dsql_cte_not_a_union) << input->alias);
757 }
758
759 // Split queries list on two parts: anchor and recursive.
760 // In turn, the anchor part consists of:
761 // - a number of rightmost nodes combined by UNION ALL
762 // - the leftmost node representing a union of all other nodes
763
764 MemoryPool& pool = getPool();
765
766 unsigned anchors = 0;
767 RecordSourceNode* anchorRse = NULL;
768 Stack<RseNode*> anchorStack(pool);
769 Stack<RseNode*> recursiveStack(pool);
770
771 NestConst<RecordSourceNode>* iter = unionQuery->dsqlClauses->items.end();
772 bool dsqlAll = unionQuery->dsqlAll;
773
774 while (unionQuery)
775 {
776 RecordSourceNode* clause = *--iter;
777
778 if (iter == unionQuery->dsqlClauses->items.begin())
779 {
780 unionQuery = nodeAs<UnionSourceNode>(clause);
781
782 if (unionQuery)
783 {
784 iter = unionQuery->dsqlClauses->items.end();
785 dsqlAll = unionQuery->dsqlAll;
786
787 clause = *--iter;
788
789 if (!anchorRse && !dsqlAll)
790 anchorRse = unionQuery;
791 }
792 }
793
794 RseNode* const rse = nodeAs<RseNode>(clause);
795 fb_assert(rse);
796 RseNode* const newRse = pass1RseIsRecursive(rse);
797
798 if (newRse) // rse is recursive
799 {
800 if (anchors)
801 {

Callers

nothing calls this directly

Calls 14

ERRD_postFunction · 0.85
GdsClass · 0.85
NumClass · 0.85
StrClass · 0.85
UnionSourceNodeClass · 0.85
RecSourceListNodeClass · 0.70
SelectExprNodeClass · 0.70
endMethod · 0.45
beginMethod · 0.45
pushMethod · 0.45
hasDataMethod · 0.45
getCountMethod · 0.45

Tested by

no test coverage detected