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

Method pass1RseIsRecursive

src/dsql/DsqlCompilerScratch.cpp:928–1006  ·  view source on GitHub ↗

Check if rse is recursive. If recursive reference is a table in the FROM list remove it. If recursive reference is a part of join add join boolean (returned by pass1JoinIsRecursive) to the WHERE clause. Punt if more than one recursive reference is found.

Source from the content-addressed store, hash-verified

926// If recursive reference is a part of join add join boolean (returned by pass1JoinIsRecursive)
927// to the WHERE clause. Punt if more than one recursive reference is found.
928RseNode* DsqlCompilerScratch::pass1RseIsRecursive(RseNode* input)
929{
930 MemoryPool& pool = getPool();
931
932 RseNode* result = FB_NEW_POOL(getPool()) RseNode(getPool());
933 result->dsqlFirst = input->dsqlFirst;
934 result->dsqlSkip = input->dsqlSkip;
935 result->dsqlDistinct = input->dsqlDistinct;
936 result->dsqlSelectList = input->dsqlSelectList;
937 result->dsqlWhere = input->dsqlWhere;
938 result->dsqlGroup = input->dsqlGroup;
939 result->dsqlHaving = input->dsqlHaving;
940 result->rse_plan = input->rse_plan;
941
942 RecSourceListNode* srcTables = input->dsqlFrom;
943 RecSourceListNode* dstTables = FB_NEW_POOL(pool) RecSourceListNode(pool, srcTables->items.getCount());
944 result->dsqlFrom = dstTables;
945
946 NestConst<RecordSourceNode>* pDstTable = dstTables->items.begin();
947 NestConst<RecordSourceNode>* pSrcTable = srcTables->items.begin();
948 NestConst<RecordSourceNode>* end = srcTables->items.end();
949 bool found = false;
950
951 for (NestConst<RecordSourceNode>* prev = pDstTable; pSrcTable < end; ++pSrcTable, ++pDstTable)
952 {
953 *prev++ = *pDstTable = *pSrcTable;
954
955 RseNode* rseNode = nodeAs<RseNode>(*pDstTable);
956
957 if (rseNode)
958 {
959 fb_assert(rseNode->dsqlExplicitJoin);
960
961 RseNode* dstRse = rseNode->clone(getPool());
962
963 *pDstTable = dstRse;
964
965 BoolExprNode* joinBool = pass1JoinIsRecursive(*pDstTable->getAddress());
966
967 if (joinBool)
968 {
969 if (found)
970 {
971 ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
972 // Recursive member of CTE can't reference itself more than once
973 Arg::Gds(isc_dsql_cte_mult_references));
974 }
975
976 found = true;
977
978 result->dsqlWhere = PASS1_compose(result->dsqlWhere, joinBool, blr_and);
979 }
980 }
981 else if (nodeIs<ProcedureSourceNode>(*pDstTable) || nodeIs<RelationSourceNode>(*pDstTable))
982 //// TODO: LocalTableSourceNode
983 {
984 if (pass1RelProcIsRecursive(*pDstTable))
985 {

Callers

nothing calls this directly

Calls 12

ERRD_postFunction · 0.85
GdsClass · 0.85
NumClass · 0.85
PASS1_composeFunction · 0.85
getAddressMethod · 0.80
RseNodeClass · 0.70
RecSourceListNodeClass · 0.70
getCountMethod · 0.45
beginMethod · 0.45
endMethod · 0.45
cloneMethod · 0.45
popMethod · 0.45

Tested by

no test coverage detected