Process derived table which is part of a from clause.
| 983 | |
| 984 | // Process derived table which is part of a from clause. |
| 985 | RseNode* PASS1_derived_table(DsqlCompilerScratch* dsqlScratch, SelectExprNode* input, |
| 986 | const char* cte_alias, const SelectNode* select) |
| 987 | { |
| 988 | DEV_BLKCHK(dsqlScratch, dsql_type_req); |
| 989 | |
| 990 | thread_db* tdbb = JRD_get_thread_data(); |
| 991 | MemoryPool& pool = *tdbb->getDefaultPool(); |
| 992 | |
| 993 | const string& alias = input->alias; |
| 994 | |
| 995 | // Create the context now, because we need to know it for the tables inside. |
| 996 | dsql_ctx* const context = PASS1_make_context(dsqlScratch, input); |
| 997 | |
| 998 | // Save some values to restore after rse process. |
| 999 | DsqlContextStack* const req_base = dsqlScratch->context; |
| 1000 | const string aliasRelationPrefix = dsqlScratch->aliasRelationPrefix; |
| 1001 | |
| 1002 | // Change context, because the derived table cannot reference other streams |
| 1003 | // at the same scope_level (unless this is a lateral derived table). |
| 1004 | DsqlContextStack temp; |
| 1005 | // Put special contexts (NEW/OLD) also on the stack |
| 1006 | for (DsqlContextStack::iterator stack(*dsqlScratch->context); stack.hasData(); ++stack) |
| 1007 | { |
| 1008 | dsql_ctx* local_context = stack.object(); |
| 1009 | |
| 1010 | if ((context->ctx_flags & CTX_lateral) || |
| 1011 | (local_context->ctx_scope_level < dsqlScratch->scopeLevel) || |
| 1012 | (local_context->ctx_flags & CTX_system)) |
| 1013 | { |
| 1014 | temp.push(local_context); |
| 1015 | } |
| 1016 | } |
| 1017 | |
| 1018 | dsql_ctx* baseContext = NULL; |
| 1019 | |
| 1020 | if (temp.hasData()) |
| 1021 | baseContext = temp.object(); |
| 1022 | |
| 1023 | dsqlScratch->context = &temp; |
| 1024 | dsqlScratch->aliasRelationPrefix = pass1_alias_concat(aliasRelationPrefix, alias); |
| 1025 | |
| 1026 | RecordSourceNode* query = input->querySpec; |
| 1027 | UnionSourceNode* unionQuery = nodeAs<UnionSourceNode>(query); |
| 1028 | RseNode* rse = NULL; |
| 1029 | const bool isRecursive = unionQuery && unionQuery->recursive; |
| 1030 | USHORT recursive_map_ctx = 0; |
| 1031 | |
| 1032 | if (isRecursive) |
| 1033 | { |
| 1034 | // Create dummy, non-recursive select dsqlScratch by doing a union of |
| 1035 | // one, non-recursive member. The dummy will be replaced at the end |
| 1036 | // of this function. |
| 1037 | |
| 1038 | RecordSourceNode* save = unionQuery->dsqlClauses->items.pop(); |
| 1039 | unionQuery->recursive = false; |
| 1040 | |
| 1041 | dsql_ctx* baseUnionCtx = dsqlScratch->unionContext.hasData() ? |
| 1042 | dsqlScratch->unionContext.object() : NULL; |
no test coverage detected