diff --git a/src/dsql/BoolNodes.cpp b/src/dsql/BoolNodes.cpp index 677a060f2c..7e0464700d 100644 --- a/src/dsql/BoolNodes.cpp +++ b/src/dsql/BoolNodes.cpp @@ -1340,43 +1340,47 @@ BoolExprNode* ComparativeBoolNode::createRseNode(DsqlCompilerScratch* dsqlScratc { PASS1_set_parameter_type(dsqlScratch, dsqlArg1, dsqlArg2, false); - // create a derived table representing our subquery - dsql_nod* dt = MAKE_node(Dsql::nod_derived_table, Dsql::e_derived_table_count); - // Ignore validation for columnames that must exist for "user" derived tables. - dt->nod_flags |= NOD_DT_IGNORE_COLUMN_CHECK; - dt->nod_arg[Dsql::e_derived_table_rse] = dsqlArg2; + // Create a derived table representing our subquery. + dsql_nod* dt = MAKE_node(Dsql::nod_select_expr, Dsql::e_sel_count); + // Ignore validation for colum names that must exist for "user" derived tables. + dt->nod_flags |= NOD_SELECT_EXPR_DT_IGNORE_COLUMN_CHECK | NOD_SELECT_EXPR_DERIVED; + dt->nod_arg[Dsql::e_sel_query_spec] = dsqlArg2; dsql_nod* from = MAKE_node(Dsql::nod_list, 1); from->nod_arg[0] = dt; - dsql_nod* query_spec = MAKE_node(Dsql::nod_query_spec, Dsql::e_qry_count); - query_spec->nod_arg[Dsql::e_qry_from] = from; + + RseNode* querySpec = FB_NEW(getPool()) RseNode(getPool()); + querySpec->dsqlFrom = from; + dsql_nod* select_expr = MAKE_node(Dsql::nod_select_expr, Dsql::e_sel_count); - select_expr->nod_arg[Dsql::e_sel_query_spec] = query_spec; + select_expr->nod_arg[Dsql::e_sel_query_spec] = MAKE_node(Dsql::nod_class_exprnode, 1); + select_expr->nod_arg[Dsql::e_sel_query_spec]->nod_arg[0] = reinterpret_cast(querySpec); const DsqlContextStack::iterator base(*dsqlScratch->context); const DsqlContextStack::iterator baseDT(dsqlScratch->derivedContext); const DsqlContextStack::iterator baseUnion(dsqlScratch->unionContext); - dsql_nod* rse = PASS1_rse(dsqlScratch, select_expr, NULL); + dsql_nod* rseNod = PASS1_rse(dsqlScratch, select_expr, NULL); + RseNode* rse = ExprNode::as(rseNod); + fb_assert(rse); - // create a conjunct to be injected + // Create a conjunct to be injected. ComparativeBoolNode* cmpNode = FB_NEW(getPool()) ComparativeBoolNode(getPool(), blrOp, - PASS1_node_psql(dsqlScratch, dsqlArg1, false), rse->nod_arg[Dsql::e_rse_items]->nod_arg[0]); + PASS1_node_psql(dsqlScratch, dsqlArg1, false), rse->dsqlSelectList->nod_arg[0]); dsql_nod* temp = MAKE_node(Dsql::nod_class_exprnode, 1); temp->nod_arg[0] = reinterpret_cast(cmpNode); - rse->nod_arg[Dsql::e_rse_boolean] = temp; + rse->dsqlWhere = temp; - // create output node - - RseBoolNode* rseNode = FB_NEW(getPool()) RseBoolNode(getPool(), rseBlrOp, rse); + // Create output node. + RseBoolNode* rseBoolNode = FB_NEW(getPool()) RseBoolNode(getPool(), rseBlrOp, rseNod); // Finish off by cleaning up contexts dsqlScratch->unionContext.clear(baseUnion); dsqlScratch->derivedContext.clear(baseDT); dsqlScratch->context->clear(base); - return rseNode; + return rseBoolNode; } diff --git a/src/dsql/DdlNodes.epp b/src/dsql/DdlNodes.epp index eb6dc85030..64efb93372 100644 --- a/src/dsql/DdlNodes.epp +++ b/src/dsql/DdlNodes.epp @@ -7156,7 +7156,7 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra DDL_reset_context_stack(dsqlScratch); ++dsqlScratch->contextNumber; - selectExpr->nod_flags |= NOD_SELECT_VIEW_FIELDS; + selectExpr->nod_flags |= NOD_SELECT_EXPR_VIEW_FIELDS; dsql_nod* rse = PASS1_rse(dsqlScratch, selectExpr, NULL); dsqlScratch->getBlrData().clear(); @@ -7341,7 +7341,7 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra // If an expression is specified rather than a field, define a global // field for the computed value as well. - dsql_nod* items = rse->nod_arg[Dsql::e_rse_items]; + dsql_nod* items = ExprNode::as(rse)->dsqlSelectList; dsql_nod** itemsPtr = items->nod_arg; SortedArray modifiedFields; bool updatable = true; @@ -7654,9 +7654,9 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra Arg::Gds(isc_col_name_err)); } - dsql_nod* querySpec = selectExpr->nod_arg[Dsql::e_sel_query_spec]; + dsql_nod* querySpecNod = selectExpr->nod_arg[Dsql::e_sel_query_spec]; - if (querySpec->nod_type == Dsql::nod_list) + if (querySpecNod->nod_type == Dsql::nod_list) { // Only one table allowed for VIEW WITH CHECK OPTION status_exception::raise( @@ -7665,7 +7665,10 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra Arg::Gds(isc_table_view_err)); } - if (querySpec->nod_arg[Dsql::e_qry_from]->nod_count != 1) + RseNode* querySpec = ExprNode::as(querySpecNod); + fb_assert(querySpec); + + if (querySpec->dsqlFrom->nod_count != 1) { // Only one table allowed for VIEW WITH CHECK OPTION status_exception::raise( @@ -7674,7 +7677,7 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra Arg::Gds(isc_table_view_err)); } - if (!querySpec->nod_arg[Dsql::e_qry_where]) + if (!querySpec->dsqlWhere) { // No where clause for VIEW WITH CHECK OPTION status_exception::raise( @@ -7683,8 +7686,7 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra Arg::Gds(isc_where_err)); } - if (querySpec->nod_arg[Dsql::e_qry_distinct] || querySpec->nod_arg[Dsql::e_qry_group] || - querySpec->nod_arg[Dsql::e_qry_having]) + if (querySpec->dsqlDistinct || querySpec->dsqlGroup || querySpec->dsqlHaving) { // DISTINCT, GROUP or HAVING not permitted for VIEW WITH CHECK OPTION status_exception::raise( @@ -7711,6 +7713,8 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra void CreateAlterViewNode::createCheckTriggers(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, dsql_nod* items) { + MemoryPool& pool = *tdbb->getDefaultPool(); + // Specify that the trigger should abort if the condition is not met. dsql_nod* actionNode = MAKE_node(Dsql::nod_list, 1); actionNode->nod_arg[0] = MAKE_node(Dsql::nod_gdscode, 1); @@ -7724,13 +7728,15 @@ void CreateAlterViewNode::createCheckTriggers(thread_db* tdbb, DsqlCompilerScrat fb_assert(baseAndNode); fb_assert(baseRelation); - dsql_nod* rse = MAKE_node(Dsql::nod_rse, e_rse_count); - rse->nod_arg[e_rse_boolean] = baseAndNode; - dsql_nod* temp = MAKE_node(Dsql::nod_list, 1); - rse->nod_arg[e_rse_streams] = temp; - temp->nod_arg[0] = baseRelation; + RseNode* rse = FB_NEW(pool) RseNode(pool); + rse->dsqlWhere = baseAndNode; + rse->dsqlStreams = MAKE_node(Dsql::nod_list, 1); + rse->dsqlStreams->nod_arg[0] = baseRelation; - createCheckTrigger(tdbb, dsqlScratch, rse, items, actionNode, PRE_MODIFY_TRIGGER); + dsql_nod* rseNod = MAKE_node(Dsql::nod_class_exprnode, 1); + rseNod->nod_arg[0] = reinterpret_cast(rse); + + createCheckTrigger(tdbb, dsqlScratch, rseNod, items, actionNode, PRE_MODIFY_TRIGGER); createCheckTrigger(tdbb, dsqlScratch, NULL, items, actionNode, PRE_STORE_TRIGGER); } @@ -7742,7 +7748,7 @@ void CreateAlterViewNode::createCheckTrigger(thread_db* tdbb, DsqlCompilerScratc AutoSetRestore autoCheckConstraintTrigger(&dsqlScratch->checkConstraintTrigger, true); - const dsql_nod* querySpec = selectExpr->nod_arg[Dsql::e_sel_query_spec]; + const dsql_nod* querySpecNod = selectExpr->nod_arg[Dsql::e_sel_query_spec]; dsql_nod* relationNode = dsqlNode; // Generate the trigger blr. @@ -7797,27 +7803,26 @@ void CreateAlterViewNode::createCheckTrigger(thread_db* tdbb, DsqlCompilerScratc // Generate the condition for firing the trigger. + const RseNode* querySpec = ExprNode::as(querySpecNod); + fb_assert(querySpec); + dsql_nod* condition; if (triggerType == PRE_MODIFY_TRIGGER) { dsqlScratch->appendUChar(blr_for); - dsql_nod* temp = rse->nod_arg[Dsql::e_rse_streams]; - temp->nod_arg[0] = PASS1_node(dsqlScratch, temp->nod_arg[0]); - temp = rse->nod_arg[Dsql::e_rse_boolean]; + RseNode* rseNode = ExprNode::as(rse); + + rseNode->dsqlStreams->nod_arg[0] = PASS1_node(dsqlScratch, rseNode->dsqlStreams->nod_arg[0]); + rseNode->dsqlWhere = PASS1_node(dsqlScratch, rseNode->dsqlWhere); - rse->nod_arg[Dsql::e_rse_boolean] = PASS1_node(dsqlScratch, temp); GEN_expr(dsqlScratch, rse); - condition = replaceFieldNames(querySpec->nod_arg[Dsql::e_qry_where], items, - viewFields, false, NEW_CONTEXT); + condition = replaceFieldNames(querySpec->dsqlWhere, items, viewFields, false, NEW_CONTEXT); } else if (triggerType == PRE_STORE_TRIGGER) - { - condition = replaceFieldNames(querySpec->nod_arg[Dsql::e_qry_where], items, - viewFields, true, NEW_CONTEXT); - } + condition = replaceFieldNames(querySpec->dsqlWhere, items, viewFields, true, NEW_CONTEXT); else { fb_assert(false); @@ -7858,12 +7863,10 @@ void CreateAlterViewNode::defineUpdateAction(DsqlCompilerScratch* dsqlScratch, // Check whether this is an updatable view definition. - dsql_nod* querySpec = NULL; + RseNode* querySpec = ExprNode::as(selectExpr->nod_arg[Dsql::e_sel_query_spec]); dsql_nod* fromList = NULL; - if (!(querySpec = selectExpr->nod_arg[Dsql::e_sel_query_spec]) || - !(fromList = querySpec->nod_arg[Dsql::e_qry_from]) || - fromList->nod_count != 1) + if (!querySpec || !(fromList = querySpec->dsqlFrom) || fromList->nod_count != 1) { // The caller seems throwing proper errors for all the above conditions. // But just in case it doesn't, here we have the final attempt to prevent the bad things. @@ -7881,7 +7884,7 @@ void CreateAlterViewNode::defineUpdateAction(DsqlCompilerScratch* dsqlScratch, // fields in the base relation that are not computed. dsql_nod* valuesNode = viewFields; - dsql_nod* fieldsNode = querySpec->nod_arg[Dsql::e_qry_list]; + dsql_nod* fieldsNode = querySpec->dsqlSelectList; if (!fieldsNode) { @@ -7977,21 +7980,15 @@ void CreateAlterViewNode::defineUpdateAction(DsqlCompilerScratch* dsqlScratch, } if (andArg == 0) - { - andNode->dsqlArg1 = replaceFieldNames(querySpec->nod_arg[Dsql::e_qry_where], - items, NULL, false, TEMP_CONTEXT); - } + andNode->dsqlArg1 = replaceFieldNames(querySpec->dsqlWhere, items, NULL, false, TEMP_CONTEXT); else if (andArg == 1) - { - andNode->dsqlArg2 = replaceFieldNames(querySpec->nod_arg[Dsql::e_qry_where], - items, NULL, false, TEMP_CONTEXT); - } + andNode->dsqlArg2 = replaceFieldNames(querySpec->dsqlWhere, items, NULL, false, TEMP_CONTEXT); else { dsql_nod* oldAnd = andNod; andNode = FB_NEW(pool) BinaryBoolNode(pool, blr_and, oldAnd, - replaceFieldNames(querySpec->nod_arg[Dsql::e_qry_where], items, NULL, false, TEMP_CONTEXT)); + replaceFieldNames(querySpec->dsqlWhere, items, NULL, false, TEMP_CONTEXT)); andNod = MAKE_node(Dsql::nod_class_exprnode, 1); andNod->nod_arg[0] = reinterpret_cast(andNode); diff --git a/src/dsql/DsqlCompilerScratch.cpp b/src/dsql/DsqlCompilerScratch.cpp index 8ef505bfff..517d542bac 100644 --- a/src/dsql/DsqlCompilerScratch.cpp +++ b/src/dsql/DsqlCompilerScratch.cpp @@ -25,6 +25,7 @@ #include "../dsql/ExprNodes.h" #include "../jrd/jrd.h" #include "../jrd/blr.h" +#include "../jrd/RecordSourceNodes.h" #include "../dsql/node.h" #include "../dsql/ddl_proto.h" #include "../dsql/errd_proto.h" @@ -421,7 +422,7 @@ void DsqlCompilerScratch::addCTEs(dsql_nod* with) for (dsql_nod* const* cte = list->nod_arg; cte < end; cte++) { - fb_assert((*cte)->nod_type == Dsql::nod_derived_table); + fb_assert((*cte)->nod_type == Dsql::nod_select_expr); if (with->nod_flags & NOD_UNION_RECURSIVE) { @@ -432,7 +433,7 @@ void DsqlCompilerScratch::addCTEs(dsql_nod* with) // Add CTE name into CTE aliases stack. It allows later to search for // aliases of given CTE. - const dsql_str* cteName = (dsql_str*) (*cte)->nod_arg[Dsql::e_derived_table_alias]; + const dsql_str* cteName = (dsql_str*) (*cte)->nod_arg[Dsql::e_sel_alias]; addCTEAlias(cteName); } else @@ -445,7 +446,9 @@ dsql_nod* DsqlCompilerScratch::findCTE(const dsql_str* name) for (size_t i = 0; i < ctes.getCount(); ++i) { dsql_nod* cte = ctes[i]; - const dsql_str* cteName = (dsql_str*) cte->nod_arg[Dsql::e_derived_table_alias]; + fb_assert(cte->nod_type == Dsql::nod_select_expr); + + const dsql_str* cteName = (dsql_str*) cte->nod_arg[Dsql::e_sel_alias]; if (name->str_length == cteName->str_length && strncmp(name->str_data, cteName->str_data, cteName->str_length) == 0) @@ -469,10 +472,11 @@ void DsqlCompilerScratch::checkUnusedCTEs() const for (size_t i = 0; i < ctes.getCount(); ++i) { const dsql_nod* cte = ctes[i]; + fb_assert(cte->nod_type == Dsql::nod_select_expr); - if (!(cte->nod_flags & NOD_DT_CTE_USED)) + if (!(cte->nod_flags & NOD_SELECT_EXPR_DT_CTE_USED)) { - const dsql_str* cteName = (dsql_str*) cte->nod_arg[Dsql::e_derived_table_alias]; + const dsql_str* cteName = (dsql_str*) cte->nod_arg[Dsql::e_sel_alias]; ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << Arg::Gds(isc_dsql_cte_not_used) << Arg::Str(cteName->str_data)); @@ -500,9 +504,8 @@ void DsqlCompilerScratch::checkUnusedCTEs() const // needed. Therefore recursive part is built using newly allocated list nodes. dsql_nod* DsqlCompilerScratch::pass1RecursiveCte(dsql_nod* input) { - dsql_str* const cte_alias = (dsql_str*) input->nod_arg[Dsql::e_derived_table_alias]; - dsql_nod* const select_expr = input->nod_arg[Dsql::e_derived_table_rse]; - dsql_nod* query = select_expr->nod_arg[Dsql::e_sel_query_spec]; + dsql_str* const cte_alias = (dsql_str*) input->nod_arg[Dsql::e_sel_alias]; + dsql_nod* query = input->nod_arg[Dsql::e_sel_query_spec]; if (query->nod_type != Dsql::nod_list && pass1RseIsRecursive(query)) { @@ -512,7 +515,8 @@ dsql_nod* DsqlCompilerScratch::pass1RecursiveCte(dsql_nod* input) } // split queries list on two parts: anchor and recursive - dsql_nod* anchorRse = NULL, *recursiveRse = NULL; + dsql_nod* anchorRse = NULL; + dsql_nod* recursiveRse = NULL; dsql_nod* qry = query; dsql_nod* newQry = MAKE_node(Dsql::nod_list, 2); @@ -527,10 +531,12 @@ dsql_nod* DsqlCompilerScratch::pass1RecursiveCte(dsql_nod* input) else rse = qry; - dsql_nod* newRse = pass1RseIsRecursive(rse); + dsql_nod* newRseNod = pass1RseIsRecursive(rse); - if (newRse) // rse is recursive + if (newRseNod) // rse is recursive { + RseNode* newRse = ExprNode::as(newRseNod); + if (anchorRse) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << @@ -538,7 +544,7 @@ dsql_nod* DsqlCompilerScratch::pass1RecursiveCte(dsql_nod* input) Arg::Gds(isc_dsql_cte_nonrecurs_after_recurs) << Arg::Str(cte_alias->str_data)); } - if (newRse->nod_arg[Dsql::e_qry_distinct]) + if (newRse->dsqlDistinct) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << // Recursive member of CTE '%s' has %s clause @@ -546,7 +552,7 @@ dsql_nod* DsqlCompilerScratch::pass1RecursiveCte(dsql_nod* input) Arg::Str("DISTINCT")); } - if (newRse->nod_arg[Dsql::e_qry_group]) + if (newRse->dsqlGroup) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << // Recursive member of CTE '%s' has %s clause @@ -554,7 +560,7 @@ dsql_nod* DsqlCompilerScratch::pass1RecursiveCte(dsql_nod* input) Arg::Str("GROUP BY")); } - if (newRse->nod_arg[Dsql::e_qry_having]) + if (newRse->dsqlHaving) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << // Recursive member of CTE '%s' has %s clause @@ -574,12 +580,12 @@ dsql_nod* DsqlCompilerScratch::pass1RecursiveCte(dsql_nod* input) if (!recursiveRse) recursiveRse = newQry; - newRse->nod_flags |= NOD_SELECT_EXPR_RECURSIVE; + newRseNod->nod_flags |= NOD_SELECT_EXPR_RECURSIVE; if (qry->nod_type == Dsql::nod_list) - newQry->nod_arg[1] = newRse; + newQry->nod_arg[1] = newRseNod; else - newQry->nod_arg[0] = newRse; + newQry->nod_arg[0] = newRseNod; } else { @@ -646,30 +652,33 @@ dsql_nod* DsqlCompilerScratch::pass1RecursiveCte(dsql_nod* input) select->nod_arg[Dsql::e_sel_order] = select->nod_arg[Dsql::e_sel_rows] = select->nod_arg[Dsql::e_sel_with_list] = NULL; - dsql_nod* node = MAKE_node(Dsql::nod_derived_table, Dsql::e_derived_table_count); - dsql_str* alias = (dsql_str*) input->nod_arg[Dsql::e_derived_table_alias]; - node->nod_arg[Dsql::e_derived_table_alias] = (dsql_nod*) alias; - node->nod_arg[Dsql::e_derived_table_column_alias] = - input->nod_arg[Dsql::e_derived_table_column_alias]; - node->nod_arg[Dsql::e_derived_table_rse] = select; - node->nod_arg[Dsql::e_derived_table_context] = input->nod_arg[Dsql::e_derived_table_context]; + select->nod_arg[Dsql::e_sel_alias] = input->nod_arg[Dsql::e_sel_alias]; + select->nod_arg[Dsql::e_sel_columns] = input->nod_arg[Dsql::e_sel_columns]; - return node; + return select; } // 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. -dsql_nod* DsqlCompilerScratch::pass1RseIsRecursive(dsql_nod* input) +dsql_nod* DsqlCompilerScratch::pass1RseIsRecursive(dsql_nod* inputNod) { - fb_assert(input->nod_type == Dsql::nod_query_spec); + RseNode* input = ExprNode::as(inputNod); + fb_assert(input); - dsql_nod* result = MAKE_node(Dsql::nod_query_spec, Dsql::e_qry_count); - memcpy(result->nod_arg, input->nod_arg, Dsql::e_qry_count * sizeof(dsql_nod*)); + RseNode* result = FB_NEW(getPool()) RseNode(getPool()); + result->dsqlFirst = input->dsqlFirst; + result->dsqlSkip = input->dsqlSkip; + result->dsqlDistinct = input->dsqlDistinct; + result->dsqlSelectList = input->dsqlSelectList; + result->dsqlWhere = input->dsqlWhere; + result->dsqlGroup = input->dsqlGroup; + result->dsqlHaving = input->dsqlHaving; + result->dsqlPlan = input->dsqlPlan; - dsql_nod* srcTables = input->nod_arg[Dsql::e_qry_from]; + dsql_nod* srcTables = input->dsqlFrom; dsql_nod* dstTables = MAKE_node(Dsql::nod_list, srcTables->nod_count); - result->nod_arg[Dsql::e_qry_from] = dstTables; + result->dsqlFrom = dstTables; dsql_nod** pDstTable = dstTables->nod_arg; dsql_nod** pSrcTable = srcTables->nod_arg; @@ -718,14 +727,13 @@ dsql_nod* DsqlCompilerScratch::pass1RseIsRecursive(dsql_nod* input) found = true; - result->nod_arg[Dsql::e_qry_where] = PASS1_compose( - result->nod_arg[Dsql::e_qry_where], joinBool, blr_and); + result->dsqlWhere = PASS1_compose(result->dsqlWhere, joinBool, blr_and); } break; } - case Dsql::nod_derived_table: + case Dsql::nod_select_expr: break; default: @@ -733,7 +741,14 @@ dsql_nod* DsqlCompilerScratch::pass1RseIsRecursive(dsql_nod* input) } } - return found ? result : NULL; + if (found) + { + dsql_nod* resultNod = MAKE_node(Dsql::nod_class_exprnode, 1); + resultNod->nod_arg[0] = reinterpret_cast(result); + return resultNod; + } + else + return NULL; } // Check if table reference is recursive i.e. its name is equal to the name of current processing CTE. @@ -760,7 +775,7 @@ bool DsqlCompilerScratch::pass1RelProcIsRecursive(dsql_nod* input) fb_assert(currCtes.hasData()); const dsql_nod* curr_cte = currCtes.object(); - const dsql_str* cte_name = (dsql_str*) curr_cte->nod_arg[Dsql::e_derived_table_alias]; + const dsql_str* cte_name = (dsql_str*) curr_cte->nod_arg[Dsql::e_sel_alias]; const bool recursive = (cte_name->str_length == relName->str_length) && (strncmp(relName->str_data, cte_name->str_data, cte_name->str_length) == 0); diff --git a/src/dsql/ExprNodes.cpp b/src/dsql/ExprNodes.cpp index 2510cffd07..b3affb9582 100644 --- a/src/dsql/ExprNodes.cpp +++ b/src/dsql/ExprNodes.cpp @@ -6966,9 +6966,12 @@ ValueExprNode* RecordKeyNode::dsqlPass(DsqlCompilerScratch* dsqlScratch) PASS1_ambiguity_check(dsqlScratch, MAKE_cstring("RDB$DB_KEY"), contexts); + RelationSourceNode* relNode = FB_NEW(getPool()) RelationSourceNode(getPool()); + relNode->dsqlContext = context; + RecordKeyNode* node = FB_NEW(getPool()) RecordKeyNode(getPool(), blrOp); - node->dsqlRelation = MAKE_node(Dsql::nod_relation, Dsql::e_rel_count); - node->dsqlRelation->nod_arg[0] = (dsql_nod*) context; + node->dsqlRelation = MAKE_node(Dsql::nod_class_exprnode, 1); + node->dsqlRelation->nod_arg[0] = reinterpret_cast(relNode); return node; } @@ -7002,9 +7005,12 @@ ValueExprNode* RecordKeyNode::dsqlPass(DsqlCompilerScratch* dsqlScratch) if (context->ctx_flags & CTX_null) return FB_NEW(*tdbb->getDefaultPool()) NullNode(*tdbb->getDefaultPool()); + RelationSourceNode* relNode = FB_NEW(getPool()) RelationSourceNode(getPool()); + relNode->dsqlContext = context; + RecordKeyNode* node = FB_NEW(getPool()) RecordKeyNode(getPool(), blrOp); - node->dsqlRelation = MAKE_node(Dsql::nod_relation, Dsql::e_rel_count); - node->dsqlRelation->nod_arg[0] = (dsql_nod*) context; + node->dsqlRelation = MAKE_node(Dsql::nod_class_exprnode, 1); + node->dsqlRelation->nod_arg[0] = reinterpret_cast(relNode); return node; } @@ -7030,13 +7036,15 @@ bool RecordKeyNode::dsqlAggregate2Finder(Aggregate2Finder& visitor) bool RecordKeyNode::dsqlInvalidReferenceFinder(InvalidReferenceFinder& visitor) { - if (dsqlRelation && dsqlRelation->nod_type == Dsql::nod_relation) - { - const dsql_ctx* localContext = - reinterpret_cast(dsqlRelation->nod_arg[Dsql::e_rel_context]); + RelationSourceNode* relNode; - if (localContext && localContext->ctx_scope_level == visitor.context->ctx_scope_level) + if (dsqlRelation && (relNode = ExprNode::as(dsqlRelation))) + { + if (relNode->dsqlContext && + relNode->dsqlContext->ctx_scope_level == visitor.context->ctx_scope_level) + { return true; + } } return false; @@ -7084,7 +7092,7 @@ void RecordKeyNode::setParameterName(dsql_par* parameter) const void RecordKeyNode::genBlr(DsqlCompilerScratch* dsqlScratch) { - dsql_ctx* context = (dsql_ctx*) dsqlRelation->nod_arg[Dsql::e_rel_context]; + dsql_ctx* context = ExprNode::as(dsqlRelation)->dsqlContext; dsqlScratch->appendUChar(blrOp); GEN_stuff_context(dsqlScratch, context); } @@ -8127,7 +8135,7 @@ bool SubQueryNode::dsqlFieldFinder(FieldFinder& visitor) bool SubQueryNode::dsqlFieldRemapper(FieldRemapper& visitor) { visitor.visit(&dsqlRse); - dsqlValue1 = dsqlRse->nod_arg[Dsql::e_rse_items]->nod_arg[0]; + dsqlValue1 = ExprNode::as(dsqlRse)->dsqlSelectList->nod_arg[0]; return false; } diff --git a/src/dsql/Parser.h b/src/dsql/Parser.h index 2ee79d7b2d..41cd0e7c7a 100644 --- a/src/dsql/Parser.h +++ b/src/dsql/Parser.h @@ -33,6 +33,7 @@ #include "../dsql/WinNodes.h" #include "../dsql/PackageNodes.h" #include "../dsql/StmtNodes.h" +#include "../jrd/RecordSourceNodes.h" #include "../common/classes/Nullable.h" #include "../common/classes/stack.h" diff --git a/src/dsql/StmtNodes.cpp b/src/dsql/StmtNodes.cpp index 1e10cc9fd4..aa2bcae277 100644 --- a/src/dsql/StmtNodes.cpp +++ b/src/dsql/StmtNodes.cpp @@ -810,7 +810,7 @@ void CursorStmtNode::genBlr(DsqlCompilerScratch* dsqlScratch) if (listInto) { - dsql_nod* list = cursor->nod_arg[Dsql::e_cur_rse]->nod_arg[Dsql::e_rse_items]; + dsql_nod* list = ExprNode::as(cursor->nod_arg[Dsql::e_cur_rse])->dsqlSelectList; if (list->nod_count != listInto->nod_count) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-313) << @@ -3432,7 +3432,7 @@ void ForNode::genBlr(DsqlCompilerScratch* dsqlScratch) // Build body of FOR loop - dsql_nod* list = dsqlSelect->nod_arg[Dsql::e_rse_items]; + dsql_nod* list = ExprNode::as(dsqlSelect)->dsqlSelectList; if (dsqlInto) { diff --git a/src/dsql/gen.cpp b/src/dsql/gen.cpp index 7652827bae..7f37cc33c2 100644 --- a/src/dsql/gen.cpp +++ b/src/dsql/gen.cpp @@ -41,6 +41,7 @@ #include "../dsql/DdlNodes.h" #include "../dsql/ExprNodes.h" #include "../dsql/StmtNodes.h" +#include "../jrd/RecordSourceNodes.h" #include "../jrd/ibase.h" #include "../jrd/align.h" #include "../jrd/constants.h" @@ -63,17 +64,13 @@ using namespace Jrd; using namespace Dsql; using namespace Firebird; -static void gen_aggregate(DsqlCompilerScratch*, const dsql_nod*); static void gen_coalesce(DsqlCompilerScratch*, const dsql_nod*); static void gen_error_condition(DsqlCompilerScratch*, const dsql_nod*); static void gen_join_rse(DsqlCompilerScratch*, const dsql_nod*); -static void gen_map(DsqlCompilerScratch*, dsql_map*); static void gen_plan(DsqlCompilerScratch*, const dsql_nod*); -static void gen_relation(DsqlCompilerScratch*, dsql_ctx*); static void gen_searched_case(DsqlCompilerScratch*, const dsql_nod*); static void gen_select(DsqlCompilerScratch*, dsql_nod*); static void gen_simple_case(DsqlCompilerScratch*, const dsql_nod*); -static void gen_sort(DsqlCompilerScratch*, dsql_nod*); static void gen_statement(DsqlCompilerScratch*, const dsql_nod*); static void gen_table_lock(DsqlCompilerScratch*, const dsql_nod*, USHORT); static void gen_union(DsqlCompilerScratch*, const dsql_nod*); @@ -139,6 +136,13 @@ void GEN_expr(DsqlCompilerScratch* dsqlScratch, dsql_nod* node) case nod_class_exprnode: { ExprNode* exprNode = reinterpret_cast(node->nod_arg[0]); + + if (exprNode->is()) + { + GEN_rse(dsqlScratch, node); + return; + } + exprNode->genBlr(dsqlScratch); // Check whether the node we just processed is for a dialect 3 @@ -169,10 +173,6 @@ void GEN_expr(DsqlCompilerScratch* dsqlScratch, dsql_nod* node) GEN_expr(dsqlScratch, node->nod_arg[e_alias_value]); return; - case nod_aggregate: - gen_aggregate(dsqlScratch, node); - return; - case nod_dom_value: dsqlScratch->appendUChar(blr_fid); dsqlScratch->appendUChar(0); // Context @@ -183,18 +183,6 @@ void GEN_expr(DsqlCompilerScratch* dsqlScratch, dsql_nod* node) gen_join_rse(dsqlScratch, node); return; - case nod_relation: - gen_relation(dsqlScratch, (dsql_ctx*) node->nod_arg[e_rel_context]); - return; - - case nod_rse: - GEN_rse(dsqlScratch, node); - return; - - case nod_derived_table: - GEN_rse(dsqlScratch, node->nod_arg[e_derived_table_rse]); - return; - case nod_coalesce: gen_coalesce(dsqlScratch, node); return; @@ -727,18 +715,19 @@ void GEN_statement( DsqlCompilerScratch* dsqlScratch, dsql_nod* node) case nod_cursor: dsqlScratch->appendUChar(blr_dcl_cursor); dsqlScratch->appendUShort((int)(IPTR) node->nod_arg[e_cur_number]); + if (node->nod_arg[e_cur_scroll]) - { dsqlScratch->appendUChar(blr_scrollable); - } + GEN_rse(dsqlScratch, node->nod_arg[e_cur_rse]); - temp = node->nod_arg[e_cur_rse]->nod_arg[e_rse_items]; + temp = ExprNode::as(node->nod_arg[e_cur_rse])->dsqlSelectList; dsqlScratch->appendUShort(temp->nod_count); ptr = temp->nod_arg; end = ptr + temp->nod_count; - while (ptr < end) { + + while (ptr < end) GEN_expr(dsqlScratch, *ptr++); - } + return; case nod_src_info: @@ -755,92 +744,6 @@ void GEN_statement( DsqlCompilerScratch* dsqlScratch, dsql_nod* node) } -/** - - gen_aggregate - - @brief Generate blr for a relation reference. - - - @param - @param - - **/ -static void gen_aggregate( DsqlCompilerScratch* dsqlScratch, const dsql_nod* node) -{ - dsql_ctx* context = (dsql_ctx*) node->nod_arg[e_agg_context]; - const bool window = (node->nod_flags & NOD_AGG_WINDOW); - dsqlScratch->appendUChar((window ? blr_window : blr_aggregate)); - - if (!window) - GEN_stuff_context(dsqlScratch, context); - - GEN_rse(dsqlScratch, node->nod_arg[e_agg_rse]); - - // Handle PARTITION BY and GROUP BY clause - - if (window) - { - fb_assert(context->ctx_win_maps.hasData()); - dsqlScratch->appendUChar(context->ctx_win_maps.getCount()); // number of windows - - for (Array::iterator i = context->ctx_win_maps.begin(); - i != context->ctx_win_maps.end(); - ++i) - { - dsqlScratch->appendUChar(blr_partition_by); - dsql_nod* partition = (*i)->partition; - dsql_nod* partitionRemapped = (*i)->partitionRemapped; - dsql_nod* order = (*i)->order; - - dsqlScratch->appendUChar((*i)->context); - - if (partition) - { - dsqlScratch->appendUChar(partition->nod_count); // partition by expression count - - dsql_nod** ptr = partition->nod_arg; - for (const dsql_nod* const* end = ptr + partition->nod_count; ptr < end; ++ptr) - GEN_expr(dsqlScratch, *ptr); - - ptr = partitionRemapped->nod_arg; - for (const dsql_nod* const* end = ptr + partitionRemapped->nod_count; ptr < end; ++ptr) - GEN_expr(dsqlScratch, *ptr); - } - else - dsqlScratch->appendUChar(0); // partition by expression count - - if (order) - gen_sort(dsqlScratch, order); - else - { - dsqlScratch->appendUChar(blr_sort); - dsqlScratch->appendUChar(0); - } - - gen_map(dsqlScratch, (*i)->map); - } - } - else - { - dsqlScratch->appendUChar(blr_group_by); - - dsql_nod* list = node->nod_arg[e_agg_group]; - if (list != NULL) - { - dsqlScratch->appendUChar(list->nod_count); - dsql_nod** ptr = list->nod_arg; - for (const dsql_nod* const* end = ptr + list->nod_count; ptr < end; ptr++) - GEN_expr(dsqlScratch, *ptr); - } - else - dsqlScratch->appendUChar(0); - - gen_map(dsqlScratch, context->ctx_map); - } -} - - /** gen_coalesce @@ -1084,34 +987,6 @@ static void gen_join_rse( DsqlCompilerScratch* dsqlScratch, const dsql_nod* rse) } -/** - - gen_map - - @brief Generate a value map for a record selection expression. - - - @param dsqlScratch - @param map - - **/ -static void gen_map( DsqlCompilerScratch* dsqlScratch, dsql_map* map) -{ - USHORT count = 0; - dsql_map* temp; - for (temp = map; temp; temp = temp->map_next) - ++count; - - dsqlScratch->appendUChar(blr_map); - dsqlScratch->appendUShort(count); - - for (temp = map; temp; temp = temp->map_next) - { - dsqlScratch->appendUShort(temp->map_position); - GEN_expr(dsqlScratch, temp->map_node); - } -} - // Generate a parameter reference. void GEN_parameter( DsqlCompilerScratch* dsqlScratch, const dsql_par* parameter) { @@ -1175,8 +1050,8 @@ static void gen_plan( DsqlCompilerScratch* dsqlScratch, const dsql_nod* plan_exp // stuff the relation--the relation id itself is redundant except // when there is a need to differentiate the base tables of views - const dsql_nod* arg = node->nod_arg[0]; - gen_relation(dsqlScratch, (dsql_ctx*) arg->nod_arg[e_rel_context]); + /*const*/ dsql_nod* arg = node->nod_arg[0]; + ExprNode::as(arg)->genBlr(dsqlScratch); // now stuff the access method for this stream const dsql_str* index_string; @@ -1219,86 +1094,6 @@ static void gen_plan( DsqlCompilerScratch* dsqlScratch, const dsql_nod* plan_exp } - -/** - - gen_relation - - @brief Generate blr for a relation reference. - - - @param dsqlScratch - @param context - - **/ -static void gen_relation( DsqlCompilerScratch* dsqlScratch, dsql_ctx* context) -{ - const dsql_rel* relation = context->ctx_relation; - const dsql_prc* procedure = context->ctx_procedure; - - // if this is a trigger or procedure, don't want relation id used - if (relation) - { - if (DDL_ids(dsqlScratch)) - { - dsqlScratch->appendUChar(context->ctx_alias ? blr_rid2 : blr_rid); - dsqlScratch->appendUShort(relation->rel_id); - } - else - { - dsqlScratch->appendUChar(context->ctx_alias ? blr_relation2 : blr_relation); - dsqlScratch->appendMetaString(relation->rel_name.c_str()); - } - - if (context->ctx_alias) - dsqlScratch->appendMetaString(context->ctx_alias); - - GEN_stuff_context(dsqlScratch, context); - } - else if (procedure) - { - if (DDL_ids(dsqlScratch)) - { - dsqlScratch->appendUChar(context->ctx_alias ? blr_pid2 : blr_pid); - dsqlScratch->appendUShort(procedure->prc_id); - } - else - { - if (procedure->prc_name.package.hasData()) - { - dsqlScratch->appendUChar(context->ctx_alias ? blr_procedure4 : blr_procedure3); - dsqlScratch->appendMetaString(procedure->prc_name.package.c_str()); - dsqlScratch->appendMetaString(procedure->prc_name.identifier.c_str()); - } - else - { - dsqlScratch->appendUChar(context->ctx_alias ? blr_procedure2 : blr_procedure); - dsqlScratch->appendMetaString(procedure->prc_name.identifier.c_str()); - } - } - - if (context->ctx_alias) - dsqlScratch->appendMetaString(context->ctx_alias); - - GEN_stuff_context(dsqlScratch, context); - - dsql_nod* inputs = context->ctx_proc_inputs; - if (inputs) - { - dsqlScratch->appendUShort(inputs->nod_count); - - dsql_nod* const* ptr = inputs->nod_arg; - for (const dsql_nod* const* const end = ptr + inputs->nod_count; ptr < end; ptr++) - { - GEN_expr(dsqlScratch, *ptr); - } - } - else - dsqlScratch->appendUShort(0); - } -} - - /** GEN_rse @@ -1310,23 +1105,23 @@ static void gen_relation( DsqlCompilerScratch* dsqlScratch, dsql_ctx* context) @param rse **/ -void GEN_rse( DsqlCompilerScratch* dsqlScratch, const dsql_nod* rse) +void GEN_rse( DsqlCompilerScratch* dsqlScratch, const dsql_nod* rseNod) { - if (rse->nod_flags & NOD_SELECT_EXPR_SINGLETON) - { + const RseNode* rse = ExprNode::as(rseNod); + + if (rseNod->nod_flags & NOD_SELECT_EXPR_SINGLETON) dsqlScratch->appendUChar(blr_singular); - } dsqlScratch->appendUChar(blr_rse); - dsql_nod* list = rse->nod_arg[e_rse_streams]; + dsql_nod* list = rse->dsqlStreams; // Handle source streams if (list->nod_type == nod_union) { dsqlScratch->appendUChar(1); - gen_union(dsqlScratch, rse); + gen_union(dsqlScratch, rseNod); } else if (list->nod_type == nod_list) { @@ -1337,14 +1132,10 @@ void GEN_rse( DsqlCompilerScratch* dsqlScratch, const dsql_nod* rse) dsql_nod* node = *ptr; switch (node->nod_type) { - case nod_relation: - case nod_aggregate: + case nod_class_exprnode: case nod_join: GEN_expr(dsqlScratch, node); break; - case nod_derived_table: - GEN_expr(dsqlScratch, node->nod_arg[e_derived_table_rse]); - break; } } } @@ -1354,48 +1145,46 @@ void GEN_rse( DsqlCompilerScratch* dsqlScratch, const dsql_nod* rse) GEN_expr(dsqlScratch, list); } - if (rse->nod_arg[e_rse_lock]) + if (rse->flags & RseNode::FLAG_WRITELOCK) dsqlScratch->appendUChar(blr_writelock); dsql_nod* node; - if ((node = rse->nod_arg[e_rse_first]) != NULL) + if ((node = rse->dsqlFirst)) { dsqlScratch->appendUChar(blr_first); GEN_expr(dsqlScratch, node); } - if ((node = rse->nod_arg[e_rse_skip]) != NULL) + if ((node = rse->dsqlSkip)) { dsqlScratch->appendUChar(blr_skip); GEN_expr(dsqlScratch, node); } - if ((node = rse->nod_arg[e_rse_boolean]) != NULL) + if ((node = rse->dsqlWhere)) { dsqlScratch->appendUChar(blr_boolean); GEN_expr(dsqlScratch, node); } - if ((list = rse->nod_arg[e_rse_sort]) != NULL) - { - gen_sort(dsqlScratch, list); - } + if ((list = rse->dsqlOrder)) + GEN_sort(dsqlScratch, list); - if ((list = rse->nod_arg[e_rse_reduced]) != NULL) + if ((list = rse->dsqlDistinct)) { dsqlScratch->appendUChar(blr_project); dsqlScratch->appendUChar(list->nod_count); + dsql_nod** ptr = list->nod_arg; + for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end; ptr++) - { GEN_expr(dsqlScratch, *ptr); - } } // if the user specified an access plan to use, add it here - if ((node = rse->nod_arg[e_rse_plan]) != NULL) + if ((node = rse->dsqlPlan) != NULL) { dsqlScratch->appendUChar(blr_plan); gen_plan(dsqlScratch, node); @@ -1449,16 +1238,17 @@ static void gen_searched_case( DsqlCompilerScratch* dsqlScratch, const dsql_nod* @param rse **/ -static void gen_select(DsqlCompilerScratch* dsqlScratch, dsql_nod* rse) +static void gen_select(DsqlCompilerScratch* dsqlScratch, dsql_nod* rseNod) { dsql_ctx* context; - fb_assert(rse->nod_type == nod_rse); + RseNode* rse = ExprNode::as(rseNod); + fb_assert(rse); DsqlCompiledStatement* statement = dsqlScratch->getStatement(); // Set up parameter for things in the select list - const dsql_nod* list = rse->nod_arg[e_rse_items]; + const dsql_nod* list = rse->dsqlSelectList; dsql_nod* const* ptr = list->nod_arg; for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end; ptr++) { @@ -1477,20 +1267,23 @@ static void gen_select(DsqlCompilerScratch* dsqlScratch, dsql_nod* rse) // Save DBKEYs for possible update later - list = rse->nod_arg[e_rse_streams]; + list = rse->dsqlStreams; GenericMap > paramContexts(*getDefaultMemoryPool()); - if (!rse->nod_arg[e_rse_reduced]) + if (!rse->dsqlDistinct) { dsql_nod* const* ptr2 = list->nod_arg; for (const dsql_nod* const* const end2 = ptr2 + list->nod_count; ptr2 < end2; ptr2++) { dsql_nod* item = *ptr2; - if (item && item->nod_type == nod_relation) + RelationSourceNode* relNode; + + if (item && (relNode = ExprNode::as(item))) { - context = (dsql_ctx*) item->nod_arg[e_rel_context]; + context = relNode->dsqlContext; const dsql_rel* relation = context->ctx_relation; + if (relation) { // Set up dbkey @@ -1541,7 +1334,7 @@ static void gen_select(DsqlCompilerScratch* dsqlScratch, dsql_nod* rse) dsqlScratch->appendUChar(blr_for); dsqlScratch->appendUChar(blr_stall); - GEN_rse(dsqlScratch, rse); + GEN_rse(dsqlScratch, rseNod); dsqlScratch->appendUChar(blr_send); dsqlScratch->appendUChar(message->msg_number); @@ -1644,18 +1437,8 @@ static void gen_simple_case( DsqlCompilerScratch* dsqlScratch, const dsql_nod* n } -/** - - gen_sort - - @brief Generate a sort clause. - - - @param dsqlScratch - @param list - - **/ -static void gen_sort( DsqlCompilerScratch* dsqlScratch, dsql_nod* list) +// Generate a sort clause. +void GEN_sort( DsqlCompilerScratch* dsqlScratch, dsql_nod* list) { dsqlScratch->appendUChar(blr_sort); dsqlScratch->appendUChar(list->nod_count); @@ -1677,10 +1460,12 @@ static void gen_sort( DsqlCompilerScratch* dsqlScratch, dsql_nod* list) break; } } + if ((*ptr)->nod_arg[e_order_flag]) dsqlScratch->appendUChar(blr_descending); else dsqlScratch->appendUChar(blr_ascending); + GEN_expr(dsqlScratch, (*ptr)->nod_arg[e_order_field]); } } @@ -1760,23 +1545,21 @@ static void gen_statement(DsqlCompilerScratch* dsqlScratch, const dsql_nod* node dsqlScratch->appendUChar(node->nod_arg[e_sto_return] ? blr_store2 : blr_store); GEN_expr(dsqlScratch, node->nod_arg[e_sto_relation]); GEN_statement(dsqlScratch, node->nod_arg[e_sto_statement]); - if (node->nod_arg[e_sto_return]) { + if (node->nod_arg[e_sto_return]) GEN_statement(dsqlScratch, node->nod_arg[e_sto_return]); - } break; case nod_modify: dsqlScratch->appendUChar(node->nod_arg[e_mod_return] ? blr_modify2 : blr_modify); temp = node->nod_arg[e_mod_source]; - context = (dsql_ctx*) temp->nod_arg[e_rel_context]; + context = ExprNode::as(temp)->dsqlContext; GEN_stuff_context(dsqlScratch, context); temp = node->nod_arg[e_mod_update]; - context = (dsql_ctx*) temp->nod_arg[e_rel_context]; + context = ExprNode::as(temp)->dsqlContext; GEN_stuff_context(dsqlScratch, context); GEN_statement(dsqlScratch, node->nod_arg[e_mod_statement]); - if (node->nod_arg[e_mod_return]) { + if (node->nod_arg[e_mod_return]) GEN_statement(dsqlScratch, node->nod_arg[e_mod_return]); - } break; case nod_modify_current: @@ -1784,17 +1567,16 @@ static void gen_statement(DsqlCompilerScratch* dsqlScratch, const dsql_nod* node context = (dsql_ctx*) node->nod_arg[e_mdc_context]; GEN_stuff_context(dsqlScratch, context); temp = node->nod_arg[e_mdc_update]; - context = (dsql_ctx*) temp->nod_arg[e_rel_context]; + context = ExprNode::as(temp)->dsqlContext; GEN_stuff_context(dsqlScratch, context); GEN_statement(dsqlScratch, node->nod_arg[e_mdc_statement]); - if (node->nod_arg[e_mdc_return]) { + if (node->nod_arg[e_mdc_return]) GEN_statement(dsqlScratch, node->nod_arg[e_mdc_return]); - } break; case nod_erase: temp = node->nod_arg[e_era_relation]; - context = (dsql_ctx*) temp->nod_arg[e_rel_context]; + context = ExprNode::as(temp)->dsqlContext; if (node->nod_arg[e_era_return]) { dsqlScratch->appendUChar(blr_begin); @@ -1831,9 +1613,8 @@ static void gen_statement(DsqlCompilerScratch* dsqlScratch, const dsql_nod* node fb_assert(false); } - if (message) { + if (message) dsqlScratch->appendUChar(blr_end); - } } @@ -1898,13 +1679,15 @@ static void gen_table_lock( DsqlCompilerScratch* dsqlScratch, const dsql_nod* tb **/ static void gen_union( DsqlCompilerScratch* dsqlScratch, const dsql_nod* union_node) { - if (union_node->nod_arg[0]->nod_flags & NOD_UNION_RECURSIVE) + const RseNode* unionRse = ExprNode::as(union_node); + + if (unionRse->dsqlStreams->nod_flags & NOD_UNION_RECURSIVE) dsqlScratch->appendUChar(blr_recurse); else dsqlScratch->appendUChar(blr_union); // Obtain the context for UNION from the first dsql_map* node - dsql_nod* items = union_node->nod_arg[e_rse_items]; + dsql_nod* items = unionRse->dsqlSelectList; dsql_nod* map_item = items->nod_arg[0]; // AB: First item could be a virtual field generated by derived table. @@ -1918,7 +1701,7 @@ static void gen_union( DsqlCompilerScratch* dsqlScratch, const dsql_nod* union_n // secondary context number must be present once in generated blr union_context->ctx_flags &= ~CTX_recursive; - dsql_nod* streams = union_node->nod_arg[e_rse_streams]; + dsql_nod* streams = unionRse->dsqlStreams; dsqlScratch->appendUChar(streams->nod_count); // number of substreams dsql_nod** ptr = streams->nod_arg; @@ -1926,7 +1709,7 @@ static void gen_union( DsqlCompilerScratch* dsqlScratch, const dsql_nod* union_n { dsql_nod* sub_rse = *ptr; GEN_rse(dsqlScratch, sub_rse); - items = sub_rse->nod_arg[e_rse_items]; + items = ExprNode::as(sub_rse)->dsqlSelectList; dsqlScratch->appendUChar(blr_map); dsqlScratch->appendUShort(items->nod_count); USHORT count = 0; diff --git a/src/dsql/gen_proto.h b/src/dsql/gen_proto.h index d5bcf9714b..dcb5efaf0c 100644 --- a/src/dsql/gen_proto.h +++ b/src/dsql/gen_proto.h @@ -32,6 +32,7 @@ void GEN_port(Jrd::DsqlCompilerScratch*, Jrd::dsql_msg*); void GEN_request(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*); void GEN_rse(Jrd::DsqlCompilerScratch*, const Jrd::dsql_nod*); void GEN_return(Jrd::DsqlCompilerScratch*, const Firebird::Array& variables, bool, bool); +void GEN_sort(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*); void GEN_start_transaction(Jrd::DsqlCompilerScratch*, const Jrd::dsql_nod*); void GEN_statement(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*); void GEN_stuff_context(Jrd::DsqlCompilerScratch*, const Jrd::dsql_ctx*); diff --git a/src/dsql/make.cpp b/src/dsql/make.cpp index ebe93dc2b7..321f97a4ab 100644 --- a/src/dsql/make.cpp +++ b/src/dsql/make.cpp @@ -51,6 +51,7 @@ #include "../dsql/utld_proto.h" #include "../dsql/DSqlDataTypeUtil.h" #include "../jrd/DataTypeUtil.h" +#include "../jrd/RecordSourceNodes.h" #include "../jrd/jrd.h" #include "../jrd/ods.h" #include "../jrd/ini.h" @@ -405,7 +406,6 @@ void MAKE_desc(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* node) MAKE_desc(dsqlScratch, desc, node->nod_arg[e_alias_value]); return; - case nod_limit: case nod_rows: if (dsqlScratch->clientDialect <= SQL_DIALECT_V5) { @@ -427,11 +427,14 @@ void MAKE_desc(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* node) return; case nod_select_expr: // this should come from pass1_any call to set_parameter_type - node = node->nod_arg[e_sel_query_spec]; - fb_assert(node->nod_type == nod_query_spec); - node = node->nod_arg[e_qry_list]; - fb_assert(node->nod_type == nod_list && node->nod_count > 0); - MAKE_desc(dsqlScratch, desc, node->nod_arg[0]); + { + node = node->nod_arg[e_sel_query_spec]; + RseNode* rseNode = ExprNode::as(node); + fb_assert(rseNode); + node = rseNode->dsqlSelectList; + fb_assert(node->nod_type == nod_list && node->nod_count > 0); + MAKE_desc(dsqlScratch, desc, node->nod_arg[0]); + } return; default: diff --git a/src/dsql/node.h b/src/dsql/node.h index 686244bddb..e94938a324 100644 --- a/src/dsql/node.h +++ b/src/dsql/node.h @@ -109,14 +109,11 @@ enum nod_t nod_start_savepoint, nod_end_savepoint, nod_cursor, - nod_relation, nod_relation_name, nod_procedure_name, nod_rel_proc_name, - nod_rse, nod_select_expr, nod_union, - nod_aggregate, nod_order, nod_flag, nod_join, @@ -177,7 +174,6 @@ enum nod_t nod_mod_field_pos, nod_breakleave, nod_udf_param, // there should be a way to signal a param by descriptor! - nod_limit, // limit support nod_searched_case, // searched CASE function nod_simple_case, // simple CASE function nod_coalesce, // COALESCE function @@ -187,9 +183,7 @@ enum nod_t nod_drop_difference, nod_begin_backup, nod_end_backup, - nod_derived_table, // Derived table support nod_rows, // ROWS support - nod_query_spec, nod_mod_udf, nod_returning, nod_tra_misc, @@ -257,29 +251,6 @@ enum node_args { e_fln_name, e_fln_count, - e_rel_context = 0, // nod_relation - e_rel_count, - - e_agg_context = 0, // nod_aggregate - e_agg_group, - e_agg_rse, - e_agg_count, - - e_rse_streams = 0, // nod_rse - e_rse_boolean, - e_rse_sort, - e_rse_reduced, - e_rse_items, - e_rse_first, - e_rse_plan, - e_rse_skip, - e_rse_lock, - e_rse_count, - - e_limit_skip = 0, // nod_limit - e_limit_length, - e_limit_count, - e_rows_skip = 0, // nod_rows e_rows_length, e_rows_count, @@ -294,18 +265,10 @@ enum node_args { e_sel_order, e_sel_rows, e_sel_with_list, + e_sel_alias, // Alias name for derived table + e_sel_columns, // List with alias names from derived table columns e_sel_count, - e_qry_limit = 0, // nod_query_spec - e_qry_distinct, - e_qry_list, - e_qry_from, - e_qry_where, - e_qry_group, - e_qry_having, - e_qry_plan, - e_qry_count, - e_ins_relation = 0, // nod_insert e_ins_fields, e_ins_values, @@ -605,12 +568,6 @@ enum node_args { e_label_number, e_label_count, - e_derived_table_rse = 0, // Contains select_expr - e_derived_table_alias, // Alias name for derived table - e_derived_table_column_alias, // List with alias names from derived table columns - e_derived_table_context, // Context for derived table - e_derived_table_count, - e_mod_udf_name = 0, // nod_mod_udf e_mod_udf_entry_pt, e_mod_udf_module, @@ -715,19 +672,17 @@ enum nod_flags_vals { // depending on the SQL dialect. NOD_COMP_DIALECT = 16, // nod_...2, see MAKE_desc - NOD_SELECT_EXPR_SINGLETON = 1, // nod_select_expr - NOD_SELECT_EXPR_VALUE = 2, - NOD_SELECT_EXPR_RECURSIVE = 4, // recursive member of recursive CTE - NOD_SELECT_VIEW_FIELDS = 8, // view's field list + NOD_SELECT_EXPR_SINGLETON = 1, // nod_select_expr + NOD_SELECT_EXPR_VALUE = 2, + NOD_SELECT_EXPR_RECURSIVE = 4, // recursive member of recursive CTE + NOD_SELECT_EXPR_VIEW_FIELDS = 8, // view's field list + NOD_SELECT_EXPR_DERIVED = 16, + NOD_SELECT_EXPR_DT_IGNORE_COLUMN_CHECK = 32, + NOD_SELECT_EXPR_DT_CTE_USED = 64, NOD_CURSOR_EXPLICIT = 1, // nod_cursor NOD_CURSOR_FOR = 2, - NOD_CURSOR_ALL = USHORT(~0), - - NOD_DT_IGNORE_COLUMN_CHECK = 1, // nod_cursor, see pass1_cursor_name - NOD_DT_CTE_USED = 2, // nod_derived_table - - NOD_AGG_WINDOW = 1 // nod_aggregate + NOD_CURSOR_ALL = USHORT(~0) }; } // namespace diff --git a/src/dsql/parse.y b/src/dsql/parse.y index a137a795e0..73431b35dc 100644 --- a/src/dsql/parse.y +++ b/src/dsql/parse.y @@ -4273,7 +4273,7 @@ lock_clause : WITH LOCK select_expr : with_clause select_expr_body order_clause rows_clause - { $$ = make_node (nod_select_expr, (int) e_sel_count, $2, $3, $4, $1); } + { $$ = make_node(nod_select_expr, (int) e_sel_count, $2, $3, $4, $1, NULL); } ; with_clause @@ -4293,7 +4293,12 @@ with_list with_item : symbol_table_alias_name derived_column_list AS '(' select_expr ')' - { $$ = make_node (nod_derived_table, (int) e_derived_table_count, $5, $1, $2, NULL); } + { + $$ = $5; + $$->nod_flags |= NOD_SELECT_EXPR_DERIVED; + $$->nod_arg[e_sel_alias] = $1; + $$->nod_arg[e_sel_columns] = $2; + } ; column_select @@ -4333,18 +4338,30 @@ query_spec group_clause having_clause plan_clause - { $$ = make_node (nod_query_spec, (int) e_qry_count, $2, $3, $4, $5, $6, $7, $8, $9); } + { + RseNode* rse = newNode(); + rse->dsqlFirst = $2 ? $2->nod_arg[1] : NULL; + rse->dsqlSkip = $2 ? $2->nod_arg[0] : NULL; + rse->dsqlDistinct = $3; + rse->dsqlSelectList = $4; + rse->dsqlFrom = $5; + rse->dsqlWhere = $6; + rse->dsqlGroup = $7; + rse->dsqlHaving = $8; + rse->dsqlPlan = $9; + $$ = makeClassNode(rse); + } ; limit_clause : { $$ = NULL; } | first_clause skip_clause - { $$ = make_node (nod_limit, (int) e_limit_count, $2, $1); } + { $$ = make_node(nod_list, 2, $2, $1); } | first_clause - { $$ = make_node (nod_limit, (int) e_limit_count, NULL, $1); } + { $$ = make_node(nod_list, 2, NULL, $1); } | skip_clause - { $$ = make_node (nod_limit, (int) e_limit_count, $1, NULL); } + { $$ = make_node(nod_list, 2, $1, NULL); } ; first_clause @@ -4365,27 +4382,25 @@ skip_clause { $$ = $2; } ; -distinct_clause : DISTINCT - { $$ = make_node (nod_flag, 0, NULL); } - | all_noise - { $$ = 0; } - ; +distinct_clause + : DISTINCT { $$ = make_node(nod_flag, 0, NULL); } + | all_noise { $$ = NULL; } + ; -select_list : select_items - { $$ = make_list ($1); } - | '*' - { $$ = 0; } - ; +select_list + : select_items { $$ = make_list($1); } + | '*' { $$ = NULL; } + ; -select_items : select_item - | select_items ',' select_item - { $$ = make_node (nod_list, 2, $1, $3); } - ; +select_items + : select_item + | select_items ',' select_item { $$ = make_node(nod_list, 2, $1, $3); } + ; -select_item : value - | value as_noise symbol_item_alias_name - { $$ = make_node (nod_alias, 2, $1, $3); } - ; +select_item + : value + | value as_noise symbol_item_alias_name { $$ = make_node(nod_alias, 2, $1, $3); } + ; as_noise : @@ -4395,78 +4410,85 @@ as_noise // FROM clause from_clause - : FROM from_list - { $$ = make_list ($2); } + : FROM from_list { $$ = make_list($2); } ; from_list : table_reference - | from_list ',' table_reference - { $$ = make_node (nod_list, 2, $1, $3); } + | from_list ',' table_reference { $$ = make_node(nod_list, 2, $1, $3); } ; -table_reference : joined_table - | table_primary - ; +table_reference + : joined_table + | table_primary + ; -table_primary : table_proc - | derived_table - | '(' joined_table ')' - { $$ = $2; } - ; +table_primary + : table_proc + | derived_table + | '(' joined_table ')' { $$ = $2; } + ; // AB: derived table support -derived_table : - '(' select_expr ')' as_noise correlation_name derived_column_list - { $$ = make_node(nod_derived_table, (int) e_derived_table_count, $2, $5, $6, NULL); } - ; +derived_table + : '(' select_expr ')' as_noise correlation_name derived_column_list + { + $$ = $2; + $$->nod_flags |= NOD_SELECT_EXPR_DERIVED; + $$->nod_arg[e_sel_alias] = $5; + $$->nod_arg[e_sel_columns] = $6; + } + ; -correlation_name : symbol_table_alias_name - | - { $$ = NULL; } - ; +correlation_name + : /* nothing */ { $$ = NULL; } + | symbol_table_alias_name + ; -derived_column_list : '(' alias_list ')' - { $$ = make_list ($2); } - | - { $$ = NULL; } - ; +derived_column_list + : /* nothing */ { $$ = NULL; } + | '(' alias_list ')' { $$ = make_list($2); } + ; -alias_list : symbol_item_alias_name - | alias_list ',' symbol_item_alias_name - { $$ = make_node (nod_list, 2, $1, $3); } - ; +alias_list + : symbol_item_alias_name + | alias_list ',' symbol_item_alias_name { $$ = make_node(nod_list, 2, $1, $3); } + ; -joined_table : cross_join - | natural_join - | qualified_join - ; +joined_table + : cross_join + | natural_join + | qualified_join + ; -cross_join : table_reference CROSS JOIN table_primary - { $$ = make_node (nod_join, (int) e_join_count, $1, - make_node (nod_join_inner, (int) 0, NULL), $4, NULL); } - ; +cross_join + : table_reference CROSS JOIN table_primary + { $$ = make_node(nod_join, (int) e_join_count, $1, + make_node(nod_join_inner, (int) 0, NULL), $4, NULL); } + ; -natural_join : table_reference NATURAL join_type JOIN table_primary - { $$ = make_node (nod_join, (int) e_join_count, $1, $3, $5, - make_node (nod_flag, 0, NULL)); } - ; +natural_join + : table_reference NATURAL join_type JOIN table_primary + { $$ = make_node(nod_join, (int) e_join_count, $1, $3, $5, make_node(nod_flag, 0, NULL)); } + ; -qualified_join : table_reference join_type JOIN table_reference join_specification - { $$ = make_node (nod_join, (int) e_join_count, $1, $2, $4, $5); } - ; +qualified_join + : table_reference join_type JOIN table_reference join_specification + { $$ = make_node(nod_join, (int) e_join_count, $1, $2, $4, $5); } + ; -join_specification : join_condition - | named_columns_join - ; +join_specification + : join_condition + | named_columns_join + ; -join_condition : ON search_condition - { $$ = $2; } - ; +join_condition + : ON search_condition { $$ = $2; } + ; -named_columns_join : USING '(' column_list ')' - { $$ = make_list ($3); } - ; +named_columns_join + : USING '(' column_list ')' { $$ = make_list($3); } + ; table_proc : symbol_procedure_name table_proc_inputs as_noise symbol_table_alias_name diff --git a/src/dsql/pass1.cpp b/src/dsql/pass1.cpp index a9753bc305..a4c6eeffcb 100644 --- a/src/dsql/pass1.cpp +++ b/src/dsql/pass1.cpp @@ -152,6 +152,7 @@ #include "../jrd/jrd.h" #include "../jrd/constants.h" #include "../jrd/intl_classes.h" +#include "../jrd/RecordSourceNodes.h" #include "../dsql/DdlNodes.h" #include "../dsql/StmtNodes.h" #include "../dsql/ddl_proto.h" @@ -192,7 +193,7 @@ static dsql_par* find_dbkey(const dsql_req*, const dsql_nod*); static dsql_par* find_record_version(const dsql_req*, const dsql_nod*); static dsql_ctx* get_context(const dsql_nod* node); static dsql_nod* nullify_returning(DsqlCompilerScratch*, dsql_nod* input, dsql_nod** list = NULL); -static dsql_nod* pass1_alias_list(DsqlCompilerScratch*, dsql_nod*); +static dsql_ctx* pass1_alias_list(DsqlCompilerScratch*, dsql_nod*); static dsql_ctx* pass1_alias(DsqlCompilerScratch*, DsqlContextStack&, dsql_str*); static dsql_str* pass1_alias_concat(const dsql_str*, const dsql_str*); static dsql_rel* pass1_base_table(DsqlCompilerScratch*, const dsql_rel*, const dsql_str*); @@ -354,19 +355,6 @@ bool AggregateFinder::internalVisit(const dsql_nod* node) switch (node->nod_type) { - case nod_rse: - ++currentLevel; - aggregate |= visit(&node->nod_arg[e_rse_streams]); - aggregate |= visit(&node->nod_arg[e_rse_boolean]); - aggregate |= visit(&node->nod_arg[e_rse_items]); - --currentLevel; - return aggregate; - - case nod_aggregate: - if (!ignoreSubSelects) - aggregate = visit(&node->nod_arg[e_agg_rse]); - return aggregate; - case nod_coalesce: { const dsql_nod* const* ptr = node->nod_arg; @@ -375,21 +363,6 @@ bool AggregateFinder::internalVisit(const dsql_nod* node) return aggregate; } - case nod_relation: - { - const dsql_ctx* localRelationContext = - reinterpret_cast(node->nod_arg[e_rel_context]); - - // Check if relation is a procedure - if (localRelationContext->ctx_procedure) - { - // Check if a aggregate is buried inside the input parameters - aggregate |= visit(&localRelationContext->ctx_proc_inputs); - } - - return aggregate; - } - default: return visitChildren(node); } @@ -419,20 +392,6 @@ bool Aggregate2Finder::internalVisit(const dsql_nod* node) switch (node->nod_type) { - case nod_rse: - { - AutoSetRestore autoCurrentScopeLevelEqual(¤tScopeLevelEqual, false); - // Pass rse_boolean (where clause) and rse_items (select items) - found |= visit(&node->nod_arg[e_rse_boolean]); - found |= visit(&node->nod_arg[e_rse_items]); - break; - } - - case nod_aggregate: - // Pass only rse_group (group by clause) - found |= visit(&node->nod_arg[e_agg_group]); - break; - case nod_coalesce: ///case nod_unique: { @@ -442,9 +401,6 @@ bool Aggregate2Finder::internalVisit(const dsql_nod* node) break; } - case nod_relation: - return false; - default: return visitChildren(node); } @@ -480,17 +436,6 @@ bool FieldFinder::internalVisit(const dsql_nod* node) fb_assert(false); break; - case nod_rse: - // Pass rse_boolean (where clause) and rse_items (select items) - found |= visit(&node->nod_arg[e_rse_boolean]); - found |= visit(&node->nod_arg[e_rse_items]); - break; - - case nod_aggregate: - // Pass only rse_group (group by clause) - found |= visit(&node->nod_arg[e_agg_group]); - break; - case nod_coalesce: ///case nod_unique: { @@ -500,9 +445,6 @@ bool FieldFinder::internalVisit(const dsql_nod* node) break; } - case nod_relation: - return false; - default: return visitChildren(node); } @@ -552,13 +494,8 @@ bool InvalidReferenceFinder::internalVisit(const dsql_nod* node) switch (node->nod_type) { - case nod_aggregate: - invalid |= visit(&node->nod_arg[e_agg_rse]); - break; - case nod_coalesce: ///case nod_unique: - case nod_rse: { const dsql_nod* const* ptr = node->nod_arg; for (const dsql_nod* const* const end = ptr + node->nod_count; ptr < end; ptr++) @@ -566,18 +503,6 @@ bool InvalidReferenceFinder::internalVisit(const dsql_nod* node) break; } - case nod_relation: - { - const dsql_ctx* localRelationContext = reinterpret_cast(node->nod_arg[e_rel_context]); - - // If relation is a procedure, check if the parameters are valid. - if (localRelationContext->ctx_procedure) - invalid |= visit(&localRelationContext->ctx_proc_inputs); - - break; - } - - case nod_derived_table: case nod_plan_expr: return false; @@ -612,16 +537,6 @@ bool FieldRemapper::internalVisit(dsql_nod* node) switch (node->nod_type) { - case nod_rse: - { - AutoSetRestore autoCurrentLevel(¤tLevel, currentLevel + 1); - visit(&node->nod_arg[e_rse_streams]); - visit(&node->nod_arg[e_rse_boolean]); - visit(&node->nod_arg[e_rse_items]); - visit(&node->nod_arg[e_rse_sort]); - break; - } - case nod_coalesce: // ASF: We had deliberately changed nod_count to 1, to not process the second list. // But we should remap its fields. CORE-2176 @@ -629,26 +544,6 @@ bool FieldRemapper::internalVisit(dsql_nod* node) visit(&node->nod_arg[1]); break; - case nod_aggregate: - visit(&node->nod_arg[e_agg_rse]); - break; - - case nod_relation: - { - dsql_ctx* localRelationContext = reinterpret_cast(node->nod_arg[e_rel_context]); - // Check if relation is a procedure - if (localRelationContext->ctx_procedure) - visit(&localRelationContext->ctx_proc_inputs); // Remap the input parameters - break; - } - - case nod_derived_table: - { - dsql_nod* copy = node->nod_arg[e_derived_table_rse]; - visit(©); - break; - } - default: return visitChildren(node); } @@ -683,9 +578,6 @@ bool SubSelectFinder::internalVisit(const dsql_nod* node) break; } - case nod_aggregate: - - case nod_relation: case nod_field_name: return false; @@ -731,8 +623,8 @@ dsql_ctx* PASS1_make_context(DsqlCompilerScratch* dsqlScratch, const dsql_nod* r case nod_rel_proc_name: relation_name = (dsql_str*) relation_node->nod_arg[e_rpn_name]; break; - case nod_derived_table: - relation_name = (dsql_str*) relation_node->nod_arg[e_derived_table_alias]; + case nod_select_expr: + relation_name = (dsql_str*) relation_node->nod_arg[e_sel_alias]; break; default: relation_name = (dsql_str*) relation_node->nod_arg[e_rln_name]; @@ -740,16 +632,16 @@ dsql_ctx* PASS1_make_context(DsqlCompilerScratch* dsqlScratch, const dsql_nod* r } // CVC: Let's skim the context, too. - if (relation_name && relation_name->str_data) { + if (relation_name && relation_name->str_data) fb_utils::exact_name(relation_name->str_data); - } DEV_BLKCHK(relation_name, dsql_type_str); const dsql_nod* cte = NULL; const dsql_str* package = NULL; - if (relation_node->nod_type == nod_derived_table) { + if (relation_node->nod_type == nod_select_expr) + { // No processing needed here for derived tables. } else if ((relation_node->nod_type == nod_rel_proc_name) && @@ -808,7 +700,7 @@ dsql_ctx* PASS1_make_context(DsqlCompilerScratch* dsqlScratch, const dsql_nod* r context->ctx_relation = relation; context->ctx_procedure = procedure; - if (relation_node->nod_type == nod_derived_table) + if (relation_node->nod_type == nod_select_expr) context->ctx_context = USHORT(MAX_UCHAR) + 1 + dsqlScratch->derivedContextNumber++; else context->ctx_context = dsqlScratch->contextNumber++; @@ -822,32 +714,28 @@ dsql_ctx* PASS1_make_context(DsqlCompilerScratch* dsqlScratch, const dsql_nod* r // find the context alias name, if it exists. dsql_str* string; - if (relation_node->nod_type == nod_rel_proc_name) { + + if (relation_node->nod_type == nod_rel_proc_name) string = (dsql_str*) relation_node->nod_arg[e_rpn_alias]; - } - else if (relation_node->nod_type == nod_derived_table) + else if (relation_node->nod_type == nod_select_expr) { - string = (dsql_str*) relation_node->nod_arg[e_derived_table_alias]; - context->ctx_rse = relation_node->nod_arg[e_derived_table_rse]; + string = (dsql_str*) relation_node->nod_arg[e_sel_alias]; + context->ctx_rse = relation_node->nod_arg[e_sel_query_spec]; } - else { + else string = (dsql_str*) relation_node->nod_arg[e_rln_alias]; - } if (string) - { context->ctx_internal_alias = string->str_data; - } DEV_BLKCHK(string, dsql_type_str); - if (dsqlScratch->aliasRelationPrefix && !(relation_node->nod_type == nod_derived_table)) + + if (dsqlScratch->aliasRelationPrefix && relation_node->nod_type != nod_select_expr) { - if (string) { + if (string) string = pass1_alias_concat(dsqlScratch->aliasRelationPrefix, string); - } - else { + else string = pass1_alias_concat(dsqlScratch->aliasRelationPrefix, relation_name); - } } if (string) @@ -861,12 +749,12 @@ dsql_ctx* PASS1_make_context(DsqlCompilerScratch* dsqlScratch, const dsql_nod* r { const dsql_ctx* conflict = stack.object(); - if (conflict->ctx_scope_level != context->ctx_scope_level) { + if (conflict->ctx_scope_level != context->ctx_scope_level) continue; - } const TEXT* conflict_name; ISC_STATUS error_code; + if (conflict->ctx_alias) { conflict_name = conflict->ctx_alias; @@ -885,9 +773,8 @@ dsql_ctx* PASS1_make_context(DsqlCompilerScratch* dsqlScratch, const dsql_nod* r error_code = isc_relation_conflict_err; // alias %s conflicts with a relation in the same dsqlScratch. } - else { + else continue; - } if (!strcmp(conflict_name, context->ctx_alias)) { @@ -1016,26 +903,27 @@ dsql_nod* PASS1_node(DsqlCompilerScratch* dsqlScratch, dsql_nod* input) ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << Arg::Gds(isc_dsql_command_err)); - case nod_derived_table: - return pass1_derived_table(dsqlScratch, input, NULL); - case nod_select_expr: { + if (input->nod_flags & NOD_SELECT_EXPR_DERIVED) + return pass1_derived_table(dsqlScratch, input, NULL); + const DsqlContextStack::iterator base(*dsqlScratch->context); - dsql_nod* rse = PASS1_rse(dsqlScratch, input, NULL); + dsql_nod* rseNod = PASS1_rse(dsqlScratch, input, NULL); + RseNode* rse = ExprNode::as(rseNod); SubQueryNode* subQueryNode = FB_NEW(*tdbb->getDefaultPool()) SubQueryNode(*tdbb->getDefaultPool(), - blr_via, rse, rse->nod_arg[e_rse_items]->nod_arg[0], MAKE_node(nod_class_exprnode, 1)); + blr_via, rseNod, rse->dsqlSelectList->nod_arg[0], MAKE_node(nod_class_exprnode, 1)); subQueryNode->dsqlValue2->nod_arg[0] = reinterpret_cast( FB_NEW(*tdbb->getDefaultPool()) NullNode(*tdbb->getDefaultPool())); - // Finish off by cleaning up contexts - dsqlScratch->context->clear(base); - node = MAKE_node(nod_class_exprnode, 1); node->nod_arg[0] = reinterpret_cast(subQueryNode); + // Finish off by cleaning up contexts + dsqlScratch->context->clear(base); + return node; } @@ -1084,7 +972,7 @@ dsql_nod* PASS1_node(DsqlCompilerScratch* dsqlScratch, dsql_nod* input) dsql_nod* cte = couldBeCte ? dsqlScratch->findCTE(rel_name) : NULL; if (cte) { - cte->nod_flags |= NOD_DT_CTE_USED; + cte->nod_flags |= NOD_SELECT_EXPR_DT_CTE_USED; if ((dsqlScratch->flags & DsqlCompilerScratch::FLAG_RECURSIVE_CTE) && dsqlScratch->currCtes.hasData() && @@ -1107,24 +995,22 @@ dsql_nod* PASS1_node(DsqlCompilerScratch* dsqlScratch, dsql_nod* input) } } - dsql_nod* const select_expr = cte->nod_arg[e_derived_table_rse]; - dsql_nod* const query = select_expr->nod_arg[e_sel_query_spec]; + dsql_nod* const query = cte->nod_arg[e_sel_query_spec]; const bool isRecursive = (query->nod_type == nod_list) && (query->nod_flags & NOD_UNION_RECURSIVE); - dsql_str* cte_name = (dsql_str*) cte->nod_arg[e_derived_table_alias]; - if (!isRecursive) { - cte->nod_arg[e_derived_table_alias] = (dsql_nod*) rel_alias; - } + dsql_str* cte_name = (dsql_str*) cte->nod_arg[e_sel_alias]; + if (!isRecursive) + cte->nod_arg[e_sel_alias] = (dsql_nod*) rel_alias; dsqlScratch->currCtes.push(cte); dsql_nod* derived_node = pass1_derived_table(dsqlScratch, cte, (isRecursive ? rel_alias : NULL)); - if (!isRecursive) { - cte->nod_arg[e_derived_table_alias] = (dsql_nod*) cte_name; - } + if (!isRecursive) + cte->nod_arg[e_sel_alias] = (dsql_nod*) cte_name; + dsqlScratch->currCtes.pop(); return derived_node; @@ -1136,11 +1022,18 @@ dsql_nod* PASS1_node(DsqlCompilerScratch* dsqlScratch, dsql_nod* input) // access plan node types case nod_plan_item: - node = MAKE_node(input->nod_type, 2); - node->nod_arg[0] = sub1 = MAKE_node(nod_relation, e_rel_count); - sub1->nod_arg[e_rel_context] = pass1_alias_list(dsqlScratch, input->nod_arg[0]); - node->nod_arg[1] = PASS1_node(dsqlScratch, input->nod_arg[1]); - return node; + { + RelationSourceNode* relNode = FB_NEW(*tdbb->getDefaultPool()) RelationSourceNode( + *tdbb->getDefaultPool()); + relNode->dsqlContext = pass1_alias_list(dsqlScratch, input->nod_arg[0]); + + node = MAKE_node(input->nod_type, 2); + node->nod_arg[0] = sub1 = MAKE_node(nod_class_exprnode, 1); + sub1->nod_arg[0] = reinterpret_cast(relNode); + node->nod_arg[1] = PASS1_node(dsqlScratch, input->nod_arg[1]); + + return node; + } case nod_index: node = MAKE_node(input->nod_type, 1); @@ -1440,7 +1333,9 @@ dsql_nod* PASS1_statement(DsqlCompilerScratch* dsqlScratch, dsql_nod* input) // list. In these cases all of stored procedure is executed under // savepoint for open cursor. - if (node->nod_arg[e_rse_sort] || node->nod_arg[e_rse_reduced]) + RseNode* rseNode = ExprNode::as(node); + + if (rseNode->dsqlOrder || rseNode->dsqlDistinct) { dsqlScratch->getStatement()->setFlags(dsqlScratch->getStatement()->getFlags() & ~DsqlCompiledStatement::FLAG_NO_BATCH); @@ -2001,13 +1896,16 @@ static dsql_par* find_record_version(const dsql_req* request, const dsql_nod* re **/ static dsql_ctx* get_context(const dsql_nod* node) { - fb_assert(node->nod_type == nod_relation || node->nod_type == nod_derived_table); + const RelationSourceNode* relNode; + const RseNode* rseNode; - if (node->nod_type == nod_relation) - return (dsql_ctx*) node->nod_arg[e_rel_context]; + if ((relNode = ExprNode::as(node))) + return relNode->dsqlContext; + else if ((rseNode = ExprNode::as(node))) + return rseNode->dsqlContext; - // nod_derived_table - return (dsql_ctx*) node->nod_arg[e_derived_table_context]; + fb_assert(false); + return NULL; } @@ -2144,7 +2042,7 @@ bool PASS1_node_match(const dsql_nod* node1, const dsql_nod* node2, bool ignore_ switch (node1->nod_type) { - case nod_class_exprnode: + case nod_class_exprnode: { ExprNode* expr1Node = reinterpret_cast(node1->nod_arg[0]); ExprNode* expr2Node = reinterpret_cast(node2->nod_arg[0]); @@ -2154,49 +2052,6 @@ bool PASS1_node_match(const dsql_nod* node1, const dsql_nod* node2, bool ignore_ return expr1Node->dsqlMatch(expr2Node, ignore_map_cast); } - - case nod_aggregate: - - if (node1->nod_arg[e_agg_context] != node2->nod_arg[e_agg_context]) { - return false; - } - - return PASS1_node_match(node1->nod_arg[e_agg_group], node2->nod_arg[e_agg_group], ignore_map_cast) && - PASS1_node_match(node1->nod_arg[e_agg_rse], node2->nod_arg[e_agg_rse], ignore_map_cast); - - case nod_relation: - if (node1->nod_arg[e_rel_context] != node2->nod_arg[e_rel_context]) { - return false; - } - return true; - - case nod_derived_table: - { - const dsql_ctx* ctx1 = (dsql_ctx*) node1->nod_arg[e_derived_table_context]; - const dsql_ctx* ctx2 = (dsql_ctx*) node2->nod_arg[e_derived_table_context]; - fb_assert(ctx1 && ctx2); - - if (ctx1->ctx_context != ctx2->ctx_context) - return false; - - // hvlad: i'm not sure if we need comparisons below. I.e. if two DT have the - // same context number how it can be different in other aspects ? - - const dsql_str* alias1 = (dsql_str*) node1->nod_arg[e_derived_table_alias]; - const dsql_str* alias2 = (dsql_str*) node2->nod_arg[e_derived_table_alias]; - if ((alias1 && !alias2) || (!alias1 && alias2)) - return false; - - if (alias1 && (alias1->str_charset != alias2->str_charset || - alias1->str_length != alias2->str_length || - strncmp(alias1->str_data, alias2->str_data, alias1->str_length))) - { - return false; - } - - return PASS1_node_match(node1->nod_arg[e_derived_table_rse], - node2->nod_arg[e_derived_table_rse], ignore_map_cast); - } } // switch const dsql_nod* const* ptr1 = node1->nod_arg; @@ -2526,17 +2381,17 @@ static dsql_ctx* pass1_cursor_context( DsqlCompilerScratch* dsqlScratch, const d const dsql_nod* node = PASS1_cursor_name(dsqlScratch, string->str_data, NOD_CURSOR_ALL, true); fb_assert(node); - const dsql_nod* rse = node->nod_arg[e_cur_rse]; + const RseNode* rse = ExprNode::as(node->nod_arg[e_cur_rse]); fb_assert(rse); - if (rse->nod_arg[e_rse_reduced]) + if (rse->dsqlDistinct) { // cursor with DISTINCT is not updatable ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-510) << Arg::Gds(isc_dsql_cursor_update_err) << Arg::Str(string->str_data)); } - const dsql_nod* temp = rse->nod_arg[e_rse_streams]; + const dsql_nod* temp = rse->dsqlStreams; dsql_ctx* context = NULL; dsql_nod* const* ptr = temp->nod_arg; @@ -2544,12 +2399,15 @@ static dsql_ctx* pass1_cursor_context( DsqlCompilerScratch* dsqlScratch, const d { DEV_BLKCHK(*ptr, dsql_type_nod); dsql_nod* r_node = *ptr; - if (r_node->nod_type == nod_relation) + RelationSourceNode* relNode = ExprNode::as(r_node); + + if (relNode) { - dsql_ctx* candidate = (dsql_ctx*) r_node->nod_arg[e_rel_context]; + dsql_ctx* candidate = relNode->dsqlContext; DEV_BLKCHK(candidate, dsql_type_ctx); const dsql_rel* relation = candidate->ctx_relation; DEV_BLKCHK(rname, dsql_type_str); + if (relation->rel_name == rname->str_data) { if (context) @@ -2563,7 +2421,7 @@ static dsql_ctx* pass1_cursor_context( DsqlCompilerScratch* dsqlScratch, const d context = candidate; } } - else if (r_node->nod_type == nod_aggregate) + else if (ExprNode::as(r_node)) { // cursor with aggregation is not updatable ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-510) << @@ -2706,9 +2564,8 @@ static dsql_nod* pass1_cursor_reference( DsqlCompilerScratch* dsqlScratch, const // Build record selection expression - dsql_nod* rse = MAKE_node(nod_rse, e_rse_count); - dsql_nod* temp = MAKE_node(nod_list, 1); - rse->nod_arg[e_rse_streams] = temp; + RseNode* rse = FB_NEW(pool) RseNode(pool); + dsql_nod* temp = rse->dsqlStreams = MAKE_node(nod_list, 1); dsql_nod* relation_node = pass1_relation(dsqlScratch, relation_name); temp->nod_arg[0] = relation_node; @@ -2718,7 +2575,7 @@ static dsql_nod* pass1_cursor_reference( DsqlCompilerScratch* dsqlScratch, const dsql_nod* node = MAKE_node(nod_class_exprnode, 1); node->nod_arg[0] = reinterpret_cast(eqlNode); - rse->nod_arg[e_rse_boolean] = node; + rse->dsqlWhere = node; RecordKeyNode* dbKeyNode = FB_NEW(pool) RecordKeyNode(pool, blr_dbkey); dbKeyNode->dsqlRelation = relation_node; @@ -2763,10 +2620,13 @@ static dsql_nod* pass1_cursor_reference( DsqlCompilerScratch* dsqlScratch, const parameter->par_desc = rv_source->par_desc; - rse->nod_arg[e_rse_boolean] = PASS1_compose(rse->nod_arg[e_rse_boolean], node, blr_and); + rse->dsqlWhere = PASS1_compose(rse->dsqlWhere, node, blr_and); } - return rse; + dsql_nod* rseNod = MAKE_node(nod_class_exprnode, 1); + rseNod->nod_arg[0] = reinterpret_cast(rse); + + return rseNod; } @@ -2783,6 +2643,8 @@ static dsql_nod* pass1_cursor_reference( DsqlCompilerScratch* dsqlScratch, const **/ static dsql_nod* pass1_delete( DsqlCompilerScratch* dsqlScratch, dsql_nod* input) { + thread_db* tdbb = JRD_get_thread_data(); + DEV_BLKCHK(dsqlScratch, dsql_type_req); DEV_BLKCHK(input, dsql_type_nod); @@ -2802,40 +2664,40 @@ static dsql_nod* pass1_delete( DsqlCompilerScratch* dsqlScratch, dsql_nod* input // Generate record selection expression - dsql_nod* rse; + dsql_nod* rseNod; if (cursor) - rse = pass1_cursor_reference(dsqlScratch, cursor, relation); + rseNod = pass1_cursor_reference(dsqlScratch, cursor, relation); else { - rse = MAKE_node(nod_rse, e_rse_count); - dsql_nod* temp = MAKE_node(nod_list, 1); - rse->nod_arg[e_rse_streams] = temp; + RseNode* rse = FB_NEW(*tdbb->getDefaultPool()) RseNode(*tdbb->getDefaultPool()); + + rseNod = MAKE_node(nod_class_exprnode, 1); + rseNod->nod_arg[0] = reinterpret_cast(rse); + + dsql_nod* temp = rse->dsqlStreams = MAKE_node(nod_list, 1); temp->nod_arg[0] = PASS1_node_psql(dsqlScratch, relation, false); - if ( (temp = input->nod_arg[e_del_boolean]) ) { - rse->nod_arg[e_rse_boolean] = PASS1_node_psql(dsqlScratch, temp, false); - } + if ((temp = input->nod_arg[e_del_boolean])) + rse->dsqlWhere = PASS1_node_psql(dsqlScratch, temp, false); - if ( (temp = input->nod_arg[e_del_plan]) ) { - rse->nod_arg[e_rse_plan] = PASS1_node_psql(dsqlScratch, temp, false); - } + if ((temp = input->nod_arg[e_del_plan])) + rse->dsqlPlan = PASS1_node_psql(dsqlScratch, temp, false); - if ( (temp = input->nod_arg[e_del_sort]) ) { - rse->nod_arg[e_rse_sort] = pass1_sort(dsqlScratch, temp, NULL); - } + if ((temp = input->nod_arg[e_del_sort])) + rse->dsqlOrder = pass1_sort(dsqlScratch, temp, NULL); - if ( (temp = input->nod_arg[e_del_rows]) ) + if ((temp = input->nod_arg[e_del_rows])) { - rse->nod_arg[e_rse_first] = PASS1_node_psql(dsqlScratch, temp->nod_arg[e_rows_length], false); - rse->nod_arg[e_rse_skip] = PASS1_node_psql(dsqlScratch, temp->nod_arg[e_rows_skip], false); + rse->dsqlFirst = PASS1_node_psql(dsqlScratch, temp->nod_arg[e_rows_length], false); + rse->dsqlSkip = PASS1_node_psql(dsqlScratch, temp->nod_arg[e_rows_skip], false); } if (input->nod_arg[e_del_return]) - rse->nod_flags |= NOD_SELECT_EXPR_SINGLETON; + rseNod->nod_flags |= NOD_SELECT_EXPR_SINGLETON; } - node->nod_arg[e_era_rse] = rse; - node->nod_arg[e_era_relation] = rse->nod_arg[e_rse_streams]->nod_arg[0]; + node->nod_arg[e_era_rse] = rseNod; + node->nod_arg[e_era_relation] = ExprNode::as(rseNod)->dsqlStreams->nod_arg[0]; node->nod_arg[e_era_return] = process_returning(dsqlScratch, input->nod_arg[e_del_return]); @@ -2913,14 +2775,10 @@ static dsql_nod* pass1_derived_table(DsqlCompilerScratch* dsqlScratch, dsql_nod* thread_db* tdbb = JRD_get_thread_data(); MemoryPool& pool = *tdbb->getDefaultPool(); - dsql_nod* node = MAKE_node (nod_derived_table, e_derived_table_count); - dsql_str* alias = (dsql_str*) input->nod_arg[e_derived_table_alias]; - node->nod_arg[e_derived_table_alias] = (dsql_nod*) alias; - node->nod_arg[e_derived_table_column_alias] = input->nod_arg[e_derived_table_column_alias]; + dsql_str* alias = (dsql_str*) input->nod_arg[e_sel_alias]; // Create the context now, because we need to know it for the tables inside. - dsql_ctx* const context = PASS1_make_context(dsqlScratch, node); - node->nod_arg[e_derived_table_context] = (dsql_nod*) context; + dsql_ctx* const context = PASS1_make_context(dsqlScratch, input); // Save some values to restore after rse process. DsqlContextStack* const req_base = dsqlScratch->context; @@ -2939,15 +2797,16 @@ static dsql_nod* pass1_derived_table(DsqlCompilerScratch* dsqlScratch, dsql_nod* temp.push(local_context); } } + dsql_ctx* baseContext = NULL; - if (temp.hasData()) { + + if (temp.hasData()) baseContext = temp.object(); - } + dsqlScratch->context = &temp; dsqlScratch->aliasRelationPrefix = pass1_alias_concat(aliasRelationPrefix, alias); - dsql_nod* const select_expr = input->nod_arg[e_derived_table_rse]; - dsql_nod* query = select_expr->nod_arg[e_sel_query_spec]; + dsql_nod* query = input->nod_arg[e_sel_query_spec]; dsql_nod* rse = NULL; const bool isRecursive = (query->nod_type == nod_list) && (query->nod_flags & NOD_UNION_RECURSIVE); USHORT recursive_map_ctx = 0; @@ -2995,8 +2854,9 @@ static dsql_nod* pass1_derived_table(DsqlCompilerScratch* dsqlScratch, dsql_nod* // the worse thing is that a UNION currently can't be used in // deciding the JOIN order. bool foundSubSelect = false; - if (query->nod_type == nod_query_spec) - foundSubSelect = SubSelectFinder::find(query->nod_arg[e_qry_list]); + RseNode* queryNode = ExprNode::as(query); + if (queryNode) + foundSubSelect = SubSelectFinder::find(queryNode->dsqlSelectList); int unionContexts = 0; @@ -3005,7 +2865,7 @@ static dsql_nod* pass1_derived_table(DsqlCompilerScratch* dsqlScratch, dsql_nod* DsqlContextStack::const_iterator baseUnion(dsqlScratch->unionContext); dsql_nod* union_expr = MAKE_node(nod_list, 1); - union_expr->nod_arg[0] = select_expr; + union_expr->nod_arg[0] = input; union_expr->nod_flags = NOD_UNION_ALL; rse = pass1_union(dsqlScratch, union_expr, NULL, NULL, NULL, 0); @@ -3018,7 +2878,7 @@ static dsql_nod* pass1_derived_table(DsqlCompilerScratch* dsqlScratch, dsql_nod* } } else - rse = PASS1_rse(dsqlScratch, select_expr, NULL); + rse = PASS1_rse(dsqlScratch, input, NULL); USHORT minOuterJoin = MAX_USHORT; @@ -3059,7 +2919,8 @@ static dsql_nod* pass1_derived_table(DsqlCompilerScratch* dsqlScratch, dsql_nod* while (temp.hasData()) temp.pop(); } - context->ctx_rse = node->nod_arg[e_derived_table_rse] = rse; + + context->ctx_rse = rse; // CVC: prepare a truncated alias for the derived table here // because we need it several times. @@ -3080,21 +2941,24 @@ static dsql_nod* pass1_derived_table(DsqlCompilerScratch* dsqlScratch, dsql_nod* else aliasname = ""; - // If an alias-list is specified process it. - const bool ignoreColumnChecks = (input->nod_flags & NOD_DT_IGNORE_COLUMN_CHECK); - if (node->nod_arg[e_derived_table_column_alias] && - node->nod_arg[e_derived_table_column_alias]->nod_count) + dsql_nod* selectList = ExprNode::as(rse)->dsqlSelectList; + + // If an alias-list is specified, process it. + + const bool ignoreColumnChecks = (input->nod_flags & NOD_SELECT_EXPR_DT_IGNORE_COLUMN_CHECK); + + if (input->nod_arg[e_sel_columns] && input->nod_arg[e_sel_columns]->nod_count) { - dsql_nod* list = node->nod_arg[e_derived_table_column_alias]; + dsql_nod* list = input->nod_arg[e_sel_columns]; // Do both lists have the same number of items? - if (list->nod_count != rse->nod_arg[e_rse_items]->nod_count) + if (list->nod_count != selectList->nod_count) { // Column list by derived table %s [alias-name] has %s [more/fewer] columns // than the number of items. - // + int errcode = isc_dsql_derived_table_less_columns; - if (list->nod_count > rse->nod_arg[e_rse_items]->nod_count) + if (list->nod_count > selectList->nod_count) errcode = isc_dsql_derived_table_more_columns; ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << @@ -3102,10 +2966,10 @@ static dsql_nod* pass1_derived_table(DsqlCompilerScratch* dsqlScratch, dsql_nod* Arg::Gds(errcode) << Arg::Str(aliasname)); } - // Generate derived fields and assign alias-name to it. + // Generate derived fields and assign alias-name to them. for (int count = 0; count < list->nod_count; count++) { - dsql_nod* select_item = rse->nod_arg[e_rse_items]->nod_arg[count]; + dsql_nod* select_item = selectList->nod_arg[count]; MAKE_desc(dsqlScratch, &select_item->nod_desc, select_item); // Make new derived field node. @@ -3113,8 +2977,7 @@ static dsql_nod* pass1_derived_table(DsqlCompilerScratch* dsqlScratch, dsql_nod* DerivedFieldNode* derivedField = FB_NEW(pool) DerivedFieldNode(pool, ((dsql_str*) list->nod_arg[count])->str_data, dsqlScratch->scopeLevel, select_item); - dsql_nod* nod = rse->nod_arg[e_rse_items]->nod_arg[count] = - MAKE_node(nod_class_exprnode, 1); + dsql_nod* nod = selectList->nod_arg[count] = MAKE_node(nod_class_exprnode, 1); nod->nod_arg[0] = reinterpret_cast(derivedField); nod->nod_desc = select_item->nod_desc; } @@ -3123,10 +2986,10 @@ static dsql_nod* pass1_derived_table(DsqlCompilerScratch* dsqlScratch, dsql_nod* { // For those select-items where no alias is specified try // to generate one from the field_name. - for (int count = 0; count < rse->nod_arg[e_rse_items]->nod_count; count++) + for (int count = 0; count < selectList->nod_count; count++) { dsql_nod* select_item = pass1_make_derived_field(dsqlScratch, tdbb, - rse->nod_arg[e_rse_items]->nod_arg[count]); + selectList->nod_arg[count]); // Auto-create dummy column name for pass1_any() if (ignoreColumnChecks && !ExprNode::is(select_item)) @@ -3149,15 +3012,16 @@ static dsql_nod* pass1_derived_table(DsqlCompilerScratch* dsqlScratch, dsql_nod* select_item = nod; } - rse->nod_arg[e_rse_items]->nod_arg[count] = select_item; + selectList->nod_arg[count] = select_item; } } int count; + // Check if all root select-items have a derived field else show a message. - for (count = 0; count < rse->nod_arg[e_rse_items]->nod_count; count++) + for (count = 0; count < selectList->nod_count; count++) { - dsql_nod* select_item = rse->nod_arg[e_rse_items]->nod_arg[count]; + dsql_nod* select_item = selectList->nod_arg[count]; DerivedFieldNode* derivedField; if ((derivedField = ExprNode::as(select_item))) @@ -3174,15 +3038,15 @@ static dsql_nod* pass1_derived_table(DsqlCompilerScratch* dsqlScratch, dsql_nod* } // Check for ambiguous column names inside this derived table. - for (count = 0; count < rse->nod_arg[e_rse_items]->nod_count; ++count) + for (count = 0; count < selectList->nod_count; ++count) { const DerivedFieldNode* selectItem1 = - ExprNode::as(rse->nod_arg[e_rse_items]->nod_arg[count]); + ExprNode::as(selectList->nod_arg[count]); - for (int count2 = (count + 1); count2 < rse->nod_arg[e_rse_items]->nod_count; ++count2) + for (int count2 = (count + 1); count2 < selectList->nod_count; ++count2) { const DerivedFieldNode* selectItem2 = - ExprNode::as(rse->nod_arg[e_rse_items]->nod_arg[count2]); + ExprNode::as(selectList->nod_arg[count2]); if (selectItem1->name == selectItem2->name) { @@ -3205,7 +3069,7 @@ static dsql_nod* pass1_derived_table(DsqlCompilerScratch* dsqlScratch, dsql_nod* dsqlScratch->resetCTEAlias(alias); - rse = PASS1_rse(dsqlScratch, input->nod_arg[e_derived_table_rse], NULL); + rse = PASS1_rse(dsqlScratch, input, NULL); // Finish off by cleaning up contexts and put them into derivedContext // so create view (ddl) can deal with it. @@ -3218,23 +3082,17 @@ static dsql_nod* pass1_derived_table(DsqlCompilerScratch* dsqlScratch, dsql_nod* temp.clear(); - rse->nod_arg[e_rse_items] = context->ctx_rse->nod_arg[e_rse_items]; - - dsql_nod* node2 = MAKE_node(nod_derived_table, e_derived_table_count); - *node2 = *node; - node2->nod_arg[e_derived_table_rse] = rse; - node = node2; + ExprNode::as(rse)->dsqlSelectList = ExprNode::as(context->ctx_rse)->dsqlSelectList; context->ctx_rse = rse; - if (cte_alias) { + + if (cte_alias) context->ctx_alias = cte_alias->str_data; - } dsqlScratch->context = req_base; - // mark union's map context as recursive and assign - // secondary context number to it - dsql_nod* items = rse->nod_arg[e_rse_items]; + // Mark union's map context as recursive and assign secondary context number to it. + dsql_nod* items = ExprNode::as(rse)->dsqlSelectList; dsql_nod* map_item = items->nod_arg[0]; DerivedFieldNode* derivedField; @@ -3252,7 +3110,9 @@ static dsql_nod* pass1_derived_table(DsqlCompilerScratch* dsqlScratch, dsql_nod* dsqlScratch->context = req_base; dsqlScratch->aliasRelationPrefix = aliasRelationPrefix; - return node; + ExprNode::as(rse)->dsqlContext = context; + + return rse; } @@ -3301,16 +3161,19 @@ static void pass1_expand_select_node(DsqlCompilerScratch* dsqlScratch, dsql_nod* { DEV_BLKCHK(node, dsql_type_nod); + RseNode* rseNode; + RelationSourceNode* relNode; + if (node->nod_type == nod_join) { pass1_expand_select_node(dsqlScratch, node->nod_arg[e_join_left_rel], stack, true); pass1_expand_select_node(dsqlScratch, node->nod_arg[e_join_rght_rel], stack, true); } - else if (node->nod_type == nod_derived_table) + else if ((rseNode = ExprNode::as(node))) // AB: Derived table support { - // AB: Derived table support - dsql_nod* sub_items = node->nod_arg[e_derived_table_rse]->nod_arg[e_rse_items]; + dsql_nod* sub_items = rseNode->dsqlSelectList; dsql_nod** ptr = sub_items->nod_arg; + for (const dsql_nod* const* const end = ptr + sub_items->nod_count; ptr < end; ++ptr) { // Create a new alias else mappings would be mangled. @@ -3335,12 +3198,13 @@ static void pass1_expand_select_node(DsqlCompilerScratch* dsqlScratch, dsql_nod* stack.push(select_item); } } - else if (node->nod_type == nod_relation) + else if ((relNode = ExprNode::as(node))) { - dsql_ctx* context = (dsql_ctx*) node->nod_arg[e_rel_context]; + dsql_ctx* context = relNode->dsqlContext; DEV_BLKCHK(context, dsql_type_ctx); dsql_prc* procedure; dsql_rel* relation = context->ctx_relation; + if (relation) { for (dsql_fld* field = relation->rel_fields; field; field = field->fld_next) @@ -3378,9 +3242,8 @@ static void pass1_expand_select_node(DsqlCompilerScratch* dsqlScratch, dsql_nod* // The node could be a relation so call recursively. pass1_expand_select_node(dsqlScratch, select_item, stack, false); } - else { + else stack.push(node); - } } @@ -3482,7 +3345,6 @@ static dsql_nod* pass1_field(DsqlCompilerScratch* dsqlScratch, dsql_nod* input, Claudio Valderrama - 2001.1.29. */ - if (select_list && !qualifier && name && name->str_data) { // AB: Check first against the select list for matching column. @@ -3512,9 +3374,8 @@ static dsql_nod* pass1_field(DsqlCompilerScratch* dsqlScratch, dsql_nod* input, { // If we've found a node we're done. - if (node) { + if (node) break; - } for (DsqlContextStack::iterator stack(*dsqlScratch->context); stack.hasData(); ++stack) { @@ -3542,8 +3403,13 @@ static dsql_nod* pass1_field(DsqlCompilerScratch* dsqlScratch, dsql_nod* input, { if (list) { - node = MAKE_node(nod_relation, e_rel_count); - node->nod_arg[e_rel_context] = reinterpret_cast(stack.object()); + RelationSourceNode* relNode = FB_NEW(*tdbb->getDefaultPool()) + RelationSourceNode(*tdbb->getDefaultPool()); + relNode->dsqlContext = stack.object(); + + node = MAKE_node(nod_class_exprnode, 1); + node->nod_arg[0] = reinterpret_cast(relNode); + return node; } @@ -3631,13 +3497,10 @@ static dsql_nod* pass1_field(DsqlCompilerScratch* dsqlScratch, dsql_nod* input, if (context->ctx_alias) { if (strcmp(qualifier->str_data, context->ctx_alias)) - { continue; - } } - else { + else continue; - } } // If there's no name then we have most probable a asterisk that @@ -3647,11 +3510,8 @@ static dsql_nod* pass1_field(DsqlCompilerScratch* dsqlScratch, dsql_nod* input, { if (list) { - // Node is created so caller pass1_expand_select_node() - // can deal with it. - node = MAKE_node(nod_derived_table, e_derived_table_count); - node->nod_arg[e_derived_table_rse] = context->ctx_rse; - return node; + // Return node which pass1_expand_select_node() can deal with it. + return context->ctx_rse; } break; @@ -3659,7 +3519,7 @@ static dsql_nod* pass1_field(DsqlCompilerScratch* dsqlScratch, dsql_nod* input, // Because every select item has an alias we can just walk // through the list and return the correct node when found. - const dsql_nod* rse_items = context->ctx_rse->nod_arg[e_rse_items]; + const dsql_nod* rse_items = ExprNode::as(context->ctx_rse)->dsqlSelectList; dsql_nod* const* ptr = rse_items->nod_arg; for (const dsql_nod* const* const end = ptr + rse_items->nod_count; @@ -3885,7 +3745,7 @@ static dsql_nod* pass1_insert( DsqlCompilerScratch* dsqlScratch, dsql_nod* input rse->nod_flags |= NOD_SELECT_EXPR_SINGLETON; node->nod_arg[e_sto_rse] = rse = PASS1_rse(dsqlScratch, rse, NULL); - values = rse->nod_arg[e_rse_items]; + values = ExprNode::as(rse)->dsqlSelectList; } else values = PASS1_node_psql(dsqlScratch, input->nod_arg[e_ins_values], false); @@ -3894,7 +3754,7 @@ static dsql_nod* pass1_insert( DsqlCompilerScratch* dsqlScratch, dsql_nod* input dsql_nod* temp_rel = pass1_relation(dsqlScratch, input->nod_arg[e_ins_relation]); node->nod_arg[e_sto_relation] = temp_rel; - dsql_ctx* context = (dsql_ctx*) temp_rel->nod_arg[0]; + dsql_ctx* context = ExprNode::as(temp_rel)->dsqlContext; DEV_BLKCHK(context, dsql_type_ctx); dsql_rel* relation = context->ctx_relation; @@ -4711,14 +4571,15 @@ static dsql_nod* pass1_merge(DsqlCompilerScratch* dsqlScratch, dsql_nod* input) join->nod_arg[e_join_rght_rel] = target; join->nod_arg[e_join_boolean] = input->nod_arg[e_mrg_condition]; - dsql_nod* query_spec = MAKE_node(nod_query_spec, e_qry_count); - query_spec->nod_arg[e_qry_from] = MAKE_node(nod_list, 1); - query_spec->nod_arg[e_qry_from]->nod_arg[0] = join; + RseNode* querySpec = FB_NEW(pool) RseNode(pool); + querySpec->dsqlFrom = MAKE_node(nod_list, 1); + querySpec->dsqlFrom->nod_arg[0] = join; + + dsql_nod* querySpecNod = MAKE_node(nod_class_exprnode, 1); + querySpecNod->nod_arg[0] = reinterpret_cast(querySpec); if (updDelCondition || insCondition) { - dsql_nod*& whereNode = query_spec->nod_arg[e_qry_where]; - dsql_str* targetName = (dsql_str*) target->nod_arg[e_rln_alias]; if (!targetName) targetName = (dsql_str*) target->nod_arg[e_rln_name]; @@ -4734,12 +4595,12 @@ static dsql_nod* pass1_merge(DsqlCompilerScratch* dsqlScratch, dsql_nod* input) pool, MAKE_node(nod_class_exprnode, 1)); notNode->dsqlArg->nod_arg[0] = reinterpret_cast(missingNode); - whereNode = MAKE_node(nod_class_exprnode, 1); - whereNode->nod_arg[0] = reinterpret_cast(notNode); + querySpec->dsqlWhere = MAKE_node(nod_class_exprnode, 1); + querySpec->dsqlWhere->nod_arg[0] = reinterpret_cast(notNode); } if (updDelCondition) - whereNode = PASS1_compose(whereNode, updDelCondition, blr_and); + querySpec->dsqlWhere = PASS1_compose(querySpec->dsqlWhere, updDelCondition, blr_and); dsql_nod* temp = NULL; @@ -4756,12 +4617,12 @@ static dsql_nod* pass1_merge(DsqlCompilerScratch* dsqlScratch, dsql_nod* input) if (insCondition) temp = PASS1_compose(temp, insCondition, blr_and); - whereNode = PASS1_compose(whereNode, temp, blr_or); + querySpec->dsqlWhere = PASS1_compose(querySpec->dsqlWhere, temp, blr_or); } } dsql_nod* select_expr = MAKE_node(nod_select_expr, e_sel_count); - select_expr->nod_arg[e_sel_query_spec] = query_spec; + select_expr->nod_arg[e_sel_query_spec] = querySpecNod; dsql_nod* select = MAKE_node(nod_select, e_select_count); select->nod_arg[e_select_expr] = select_expr; @@ -4780,8 +4641,8 @@ static dsql_nod* pass1_merge(DsqlCompilerScratch* dsqlScratch, dsql_nod* input) forNode->dsqlForceSingular = true; // get the already processed relations - source = forNode->dsqlSelect->nod_arg[e_select_expr]->nod_arg[0]->nod_arg[e_join_left_rel]; - target = forNode->dsqlSelect->nod_arg[e_select_expr]->nod_arg[0]->nod_arg[e_join_rght_rel]; + source = ExprNode::as(forNode->dsqlSelect)->dsqlStreams->nod_arg[0]->nod_arg[e_join_left_rel]; + target = ExprNode::as(forNode->dsqlSelect)->dsqlStreams->nod_arg[0]->nod_arg[e_join_rght_rel]; dsql_ctx* usingCtx = get_context(source); dsql_nod* update = NULL; @@ -5061,12 +4922,17 @@ static void pass1_put_args_on_stack( DsqlCompilerScratch* dsqlScratch, dsql_nod* **/ static dsql_nod* pass1_relation( DsqlCompilerScratch* dsqlScratch, dsql_nod* input) { + thread_db* tdbb = JRD_get_thread_data(); + DEV_BLKCHK(dsqlScratch, dsql_type_req); DEV_BLKCHK(input, dsql_type_nod); - dsql_nod* node = MAKE_node(nod_relation, e_rel_count); + RelationSourceNode* relNode = FB_NEW(*tdbb->getDefaultPool()) RelationSourceNode( + *tdbb->getDefaultPool()); + relNode->dsqlContext = PASS1_make_context(dsqlScratch, input); - node->nod_arg[e_rel_context] = (dsql_nod*) PASS1_make_context(dsqlScratch, input); + dsql_nod* node = MAKE_node(nod_class_exprnode, 1); + node->nod_arg[0] = reinterpret_cast(relNode); return node; } @@ -5089,7 +4955,7 @@ static dsql_nod* pass1_relation( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp @param alias_list **/ -static dsql_nod* pass1_alias_list(DsqlCompilerScratch* dsqlScratch, dsql_nod* alias_list) +static dsql_ctx* pass1_alias_list(DsqlCompilerScratch* dsqlScratch, dsql_nod* alias_list) { DEV_BLKCHK(dsqlScratch, dsql_type_req); DEV_BLKCHK(alias_list, dsql_type_nod); @@ -5193,7 +5059,7 @@ static dsql_nod* pass1_alias_list(DsqlCompilerScratch* dsqlScratch, dsql_nod* al Arg::Gds(isc_dsql_no_relation_alias) << Arg::Str(((dsql_str*) *arg)->str_data)); } - return (dsql_nod*) context; + return context; } @@ -5515,11 +5381,12 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp DEV_BLKCHK(order, dsql_type_nod); thread_db* tdbb = JRD_get_thread_data(); + MemoryPool& pool = *tdbb->getDefaultPool(); // Verify if we're processing view fields and reset flag to not pass to // more than required inner nodes. - const USHORT viewFlags = input->nod_flags | (flags & NOD_SELECT_VIEW_FIELDS); - flags &= ~NOD_SELECT_VIEW_FIELDS; + const USHORT viewFlags = input->nod_flags | (flags & NOD_SELECT_EXPR_VIEW_FIELDS); + flags &= ~NOD_SELECT_EXPR_VIEW_FIELDS; if (input->nod_type == nod_select_expr) { @@ -5555,22 +5422,29 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp return pass1_union(dsqlScratch, input, order, rows, update_lock, flags); } - fb_assert(input->nod_type == nod_query_spec); + RseNode* inputRse = ExprNode::as(input); + fb_assert(inputRse); // Save the original base of the context stack and process relations - dsql_nod* target_rse = MAKE_node(nod_rse, e_rse_count); - dsql_nod* rse = target_rse; - rse->nod_arg[e_rse_lock] = update_lock; + RseNode* targetRse = FB_NEW(pool) RseNode(pool); + RseNode* rse = targetRse; - dsql_nod* list = rse->nod_arg[e_rse_streams] = - PASS1_node_psql(dsqlScratch, input->nod_arg[e_qry_from], false); + dsql_nod* rseNod = MAKE_node(nod_class_exprnode, 1); + rseNod->nod_arg[0] = reinterpret_cast(rse); + + if (update_lock) + rse->flags |= RseNode::FLAG_WRITELOCK; + + dsql_nod* list = rse->dsqlStreams = PASS1_node_psql(dsqlScratch, inputRse->dsqlFrom, false); { // scope block + RelationSourceNode* relNode; const dsql_rel* relation; + if (update_lock && - (list->nod_count != 1 || list->nod_arg[0]->nod_type != nod_relation || - !(relation = ((dsql_ctx*)list->nod_arg[0]->nod_arg[e_rel_context])->ctx_relation) || + (list->nod_count != 1 || !(relNode = ExprNode::as(list->nod_arg[0])) || + !(relation = relNode->dsqlContext->ctx_relation) || (relation->rel_flags & REL_view) || (relation->rel_flags & REL_external))) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << @@ -5582,45 +5456,66 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp // Process LIMIT and/or ROWS, if any - dsql_nod* node = input->nod_arg[e_qry_limit]; - if (node && rows) + if ((inputRse->dsqlFirst || inputRse->dsqlSkip) && rows) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << // Token unknown Arg::Gds(isc_token_err) << Arg::Gds(isc_random) << Arg::Str("ROWS")); } - else if (node || (node = rows) ) + else if (rows) { - const int length_index = rows ? e_rows_length : e_limit_length; - const int skip_index = rows ? e_rows_skip : e_limit_skip; - - if (node->nod_arg[length_index]) + if (rows->nod_arg[e_rows_length]) { - dsql_nod* sub = PASS1_node_psql(dsqlScratch, node->nod_arg[length_index], false); - rse->nod_arg[e_rse_first] = sub; - PASS1_set_parameter_type(dsqlScratch, sub, node, false); + dsql_nod* sub = PASS1_node_psql(dsqlScratch, rows->nod_arg[e_rows_length], false); + rse->dsqlFirst = sub; + PASS1_set_parameter_type(dsqlScratch, sub, rows, false); } - if (node->nod_arg[skip_index]) + + if (rows->nod_arg[e_rows_skip]) { - dsql_nod* sub = PASS1_node_psql(dsqlScratch, node->nod_arg[skip_index], false); - rse->nod_arg[e_rse_skip] = sub; - PASS1_set_parameter_type(dsqlScratch, sub, node, false); + dsql_nod* sub = PASS1_node_psql(dsqlScratch, rows->nod_arg[e_rows_skip], false); + rse->dsqlSkip = sub; + PASS1_set_parameter_type(dsqlScratch, sub, rows, false); + } + } + else if (inputRse->dsqlFirst || inputRse->dsqlSkip) + { + // Initialize this stack variable, and make it look like a node. + AutoPtr descNode(FB_NEW_RPT(*getDefaultMemoryPool(), 0) dsql_nod); + + if (dsqlScratch->clientDialect <= SQL_DIALECT_V5) + descNode->nod_desc.makeLong(0); + else + descNode->nod_desc.makeInt64(0); + + if (inputRse->dsqlFirst) + { + dsql_nod* sub = PASS1_node_psql(dsqlScratch, inputRse->dsqlFirst, false); + rse->dsqlFirst = sub; + PASS1_set_parameter_type(dsqlScratch, sub, descNode, false); + } + + if (inputRse->dsqlSkip) + { + dsql_nod* sub = PASS1_node_psql(dsqlScratch, inputRse->dsqlSkip, false); + rse->dsqlSkip = sub; + PASS1_set_parameter_type(dsqlScratch, sub, descNode, false); } } // Process boolean, if any - if ( (node = input->nod_arg[e_qry_where]) ) + if (inputRse->dsqlWhere) { ++dsqlScratch->inWhereClause; - rse->nod_arg[e_rse_boolean] = PASS1_node_psql(dsqlScratch, node, false); + rse->dsqlWhere = PASS1_node_psql(dsqlScratch, inputRse->dsqlWhere, false); --dsqlScratch->inWhereClause; // AB: An aggregate pointing to it's own parent_context isn't // allowed, HAVING should be used instead if (Aggregate2Finder::find(dsqlScratch->scopeLevel, FIELD_MATCH_TYPE_EQUAL, false, - rse->nod_arg[e_rse_boolean])) + rse->dsqlWhere)) { // Cannot use an aggregate in a WHERE clause, use HAVING instead ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << @@ -5637,10 +5532,10 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp #endif // Process select list, if any. If not, generate one - dsql_nod* selectList = input->nod_arg[e_qry_list]; + dsql_nod* selectList = inputRse->dsqlSelectList; // First expand select list, this will expand nodes with asterisk. ++dsqlScratch->inSelectList; - selectList = pass1_expand_select_list(dsqlScratch, selectList, rse->nod_arg[e_rse_streams]); + selectList = pass1_expand_select_list(dsqlScratch, selectList, rse->dsqlStreams); if ((flags & NOD_SELECT_EXPR_VALUE) && (!selectList || selectList->nod_count > 1)) { @@ -5651,28 +5546,28 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp } // Pass select list - rse->nod_arg[e_rse_items] = - pass1_sel_list(dsqlScratch, selectList, (viewFlags & NOD_SELECT_VIEW_FIELDS)); + rse->dsqlSelectList = pass1_sel_list(dsqlScratch, selectList, + (viewFlags & NOD_SELECT_EXPR_VIEW_FIELDS)); --dsqlScratch->inSelectList; // Process ORDER clause, if any if (order) { ++dsqlScratch->inOrderByClause; - rse->nod_arg[e_rse_sort] = pass1_sort(dsqlScratch, order, selectList); + rse->dsqlOrder = pass1_sort(dsqlScratch, order, selectList); --dsqlScratch->inOrderByClause; } // A GROUP BY, HAVING, or any aggregate function in the select list // will force an aggregate dsql_ctx* parent_context = NULL; - dsql_nod* parent_rse = NULL; - dsql_nod* aggregate = NULL; + RseNode* parentRse = NULL; + AggregateSourceNode* aggregate = NULL; - if (input->nod_arg[e_qry_group] || - input->nod_arg[e_qry_having] || - (rse->nod_arg[e_rse_items] && AggregateFinder::find(dsqlScratch, false, rse->nod_arg[e_rse_items])) || - (rse->nod_arg[e_rse_sort] && AggregateFinder::find(dsqlScratch, false, rse->nod_arg[e_rse_sort]))) + if (inputRse->dsqlGroup || + inputRse->dsqlHaving || + (rse->dsqlSelectList && AggregateFinder::find(dsqlScratch, false, rse->dsqlSelectList)) || + (rse->dsqlOrder && AggregateFinder::find(dsqlScratch, false, rse->dsqlOrder))) { // dimitr: don't allow WITH LOCK for aggregates if (update_lock) @@ -5691,45 +5586,47 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp parent_context->ctx_flags |= CTX_outer_join; parent_context->ctx_in_outer_join = dsqlScratch->inOuterJoin; - aggregate = MAKE_node(nod_aggregate, e_agg_count); - aggregate->nod_arg[e_agg_context] = (dsql_nod*) parent_context; - aggregate->nod_arg[e_agg_rse] = rse; - parent_rse = target_rse = MAKE_node(nod_rse, e_rse_count); - parent_rse->nod_arg[e_rse_streams] = list = MAKE_node(nod_list, 1); - list->nod_arg[0] = aggregate; + aggregate = FB_NEW(pool) AggregateSourceNode(pool); + aggregate->dsqlContext = parent_context; + aggregate->dsqlRse = rseNod; + parentRse = targetRse = FB_NEW(pool) RseNode(pool); + parentRse->dsqlStreams = list = MAKE_node(nod_list, 1); - if (rse->nod_arg[e_rse_first]) + dsql_nod* aggregateNod = MAKE_node(nod_class_exprnode, 1); + aggregateNod->nod_arg[0] = reinterpret_cast(aggregate); + list->nod_arg[0] = aggregateNod; + + if (rse->dsqlFirst) { - parent_rse->nod_arg[e_rse_first] = rse->nod_arg[e_rse_first]; - rse->nod_arg[e_rse_first] = NULL; + parentRse->dsqlFirst = rse->dsqlFirst; + rse->dsqlFirst = NULL; } - if (rse->nod_arg[e_rse_skip]) + + if (rse->dsqlSkip) { - parent_rse->nod_arg[e_rse_skip] = rse->nod_arg[e_rse_skip]; - rse->nod_arg[e_rse_skip] = NULL; + parentRse->dsqlSkip = rse->dsqlSkip; + rse->dsqlSkip = NULL; } dsqlScratch->context->push(parent_context); // replace original contexts with parent context - remap_streams_to_parent_context(rse->nod_arg[e_rse_streams], parent_context); + remap_streams_to_parent_context(rse->dsqlStreams, parent_context); } // Process GROUP BY clause, if any - if (node = input->nod_arg[e_qry_group]) + if (inputRse->dsqlGroup) { // if there are positions in the group by clause then replace them // by the (newly pass) items from the select_list ++dsqlScratch->inGroupByClause; - aggregate->nod_arg[e_agg_group] = - pass1_group_by_list(dsqlScratch, input->nod_arg[e_qry_group], selectList); + aggregate->dsqlGroup = pass1_group_by_list(dsqlScratch, inputRse->dsqlGroup, selectList); --dsqlScratch->inGroupByClause; // AB: An field pointing to another parent_context isn't // allowed and GROUP BY items can't contain aggregates - if (FieldFinder::find(dsqlScratch->scopeLevel, FIELD_MATCH_TYPE_LOWER, - aggregate->nod_arg[e_agg_group]) || + if (FieldFinder::find(dsqlScratch->scopeLevel, FIELD_MATCH_TYPE_LOWER, aggregate->dsqlGroup) || Aggregate2Finder::find(dsqlScratch->scopeLevel, FIELD_MATCH_TYPE_LOWER_EQUAL, - false, aggregate->nod_arg[e_agg_group])) + false, aggregate->dsqlGroup)) { // Cannot use an aggregate in a GROUP BY clause ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << @@ -5738,11 +5635,11 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp } // Parse a user-specified access PLAN - rse->nod_arg[e_rse_plan] = PASS1_node_psql(dsqlScratch, input->nod_arg[e_qry_plan], false); + rse->dsqlPlan = PASS1_node_psql(dsqlScratch, inputRse->dsqlPlan, false); // AB: Pass select-items for distinct operation again, because for // sub-selects a new context number should be generated - if (input->nod_arg[e_qry_distinct]) + if (inputRse->dsqlDistinct) { if (update_lock) { @@ -5755,7 +5652,7 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp ++dsqlScratch->inSelectList; // ASF: We pass false to viewFields parameter here because these expressions are // generated inside the view body, and not in view fields. - target_rse->nod_arg[e_rse_reduced] = pass1_sel_list(dsqlScratch, selectList, false); + targetRse->dsqlDistinct = pass1_sel_list(dsqlScratch, selectList, false); --dsqlScratch->inSelectList; // sort, group and distinct have the same limit for now @@ -5772,18 +5669,18 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp { // Reset context of select items to point to the parent stream - parent_rse->nod_arg[e_rse_items] = FieldRemapper::remap(dsqlScratch, parent_context, false, - rse->nod_arg[e_rse_items]); - rse->nod_arg[e_rse_items] = NULL; + parentRse->dsqlSelectList = FieldRemapper::remap(dsqlScratch, parent_context, false, + rse->dsqlSelectList); + rse->dsqlSelectList = NULL; // AB: Check for invalid constructions inside selected-items list - list = parent_rse->nod_arg[e_rse_items]; + list = parentRse->dsqlSelectList; + { // scope block const dsql_nod* const* ptr = list->nod_arg; for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end; ptr++) { - if (InvalidReferenceFinder::find(parent_context, - aggregate->nod_arg[e_agg_group], *ptr)) + if (InvalidReferenceFinder::find(parent_context, aggregate->dsqlGroup, *ptr)) { // Invalid expression in the select list // (not contained in either an aggregate or the GROUP BY clause) @@ -5797,17 +5694,16 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp if (order) { - parent_rse->nod_arg[e_rse_sort] = FieldRemapper::remap(dsqlScratch, parent_context, - false, rse->nod_arg[e_rse_sort]); - rse->nod_arg[e_rse_sort] = NULL; + parentRse->dsqlOrder = FieldRemapper::remap(dsqlScratch, parent_context, + false, rse->dsqlOrder); + rse->dsqlOrder = NULL; // AB: Check for invalid contructions inside the ORDER BY clause - list = target_rse->nod_arg[e_rse_sort]; + list = targetRse->dsqlOrder; const dsql_nod* const* ptr = list->nod_arg; for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end; ptr++) { - if (InvalidReferenceFinder::find(parent_context, - aggregate->nod_arg[e_agg_group], *ptr)) + if (InvalidReferenceFinder::find(parent_context, aggregate->dsqlGroup, *ptr)) { // Invalid expression in the ORDER BY clause // (not contained in either an aggregate or the GROUP BY clause) @@ -5818,27 +5714,27 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp } // And, of course, reduction clauses must also apply to the parent - if (input->nod_arg[e_qry_distinct]) + if (inputRse->dsqlDistinct) { - parent_rse->nod_arg[e_rse_reduced] = FieldRemapper::remap(dsqlScratch, parent_context, - false, parent_rse->nod_arg[e_rse_reduced]); + parentRse->dsqlDistinct = FieldRemapper::remap(dsqlScratch, parent_context, + false, parentRse->dsqlDistinct); } // Process HAVING clause, if any - if ((node = input->nod_arg[e_qry_having])) + if (inputRse->dsqlHaving) { ++dsqlScratch->inHavingClause; - parent_rse->nod_arg[e_rse_boolean] = PASS1_node_psql(dsqlScratch, node, false); + parentRse->dsqlWhere = PASS1_node_psql(dsqlScratch, inputRse->dsqlHaving, false); --dsqlScratch->inHavingClause; - parent_rse->nod_arg[e_rse_boolean] = FieldRemapper::remap(dsqlScratch, parent_context, - false, parent_rse->nod_arg[e_rse_boolean]); + parentRse->dsqlWhere = FieldRemapper::remap(dsqlScratch, parent_context, + false, parentRse->dsqlWhere); // AB: Check for invalid contructions inside the HAVING clause - if (InvalidReferenceFinder::find(parent_context, aggregate->nod_arg[e_agg_group], - parent_rse->nod_arg[e_rse_boolean])) + if (InvalidReferenceFinder::find(parent_context, aggregate->dsqlGroup, + parentRse->dsqlWhere)) { // Invalid expression in the HAVING clause // (neither an aggregate nor contained in the GROUP BY clause) @@ -5846,7 +5742,7 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp Arg::Gds(isc_dsql_agg_having_err) << Arg::Str("HAVING clause")); } - if (AggregateFinder::find(dsqlScratch, true, parent_rse->nod_arg[e_rse_boolean])) + if (AggregateFinder::find(dsqlScratch, true, parentRse->dsqlWhere)) { // Cannot use an aggregate in a WHERE clause, use HAVING instead ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << @@ -5854,61 +5750,66 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp } } - rse = parent_rse; + rse = parentRse; + rseNod = MAKE_node(nod_class_exprnode, 1); + rseNod->nod_arg[0] = reinterpret_cast(rse); parent_context->ctx_context = dsqlScratch->contextNumber++; } - const bool sortWindow = rse->nod_arg[e_rse_sort] && - AggregateFinder::find(dsqlScratch, true, rse->nod_arg[e_rse_sort]); + const bool sortWindow = rse->dsqlOrder && AggregateFinder::find(dsqlScratch, true, rse->dsqlOrder); // WINDOW functions - if ((rse->nod_arg[e_rse_items] && AggregateFinder::find(dsqlScratch, true, rse->nod_arg[e_rse_items])) || + if ((rse->dsqlSelectList && AggregateFinder::find(dsqlScratch, true, rse->dsqlSelectList)) || sortWindow) { AutoSetRestore autoProcessingWindow(&dsqlScratch->processingWindow, true); parent_context = FB_NEW(*tdbb->getDefaultPool()) dsql_ctx(*tdbb->getDefaultPool()); parent_context->ctx_scope_level = dsqlScratch->scopeLevel; - dsql_nod* window = MAKE_node(nod_aggregate, e_agg_count); - window->nod_flags = NOD_AGG_WINDOW; - window->nod_arg[e_agg_context] = (dsql_nod*) parent_context; - window->nod_arg[e_agg_rse] = rse; - parent_rse = target_rse = MAKE_node(nod_rse, e_rse_count); - parent_rse->nod_arg[e_rse_streams] = list = MAKE_node(nod_list, 1); - list->nod_arg[0] = window; - if (rse->nod_arg[e_rse_lock]) + AggregateSourceNode* window = FB_NEW(pool) AggregateSourceNode(pool); + window->dsqlContext = parent_context; + window->dsqlRse = rseNod; + window->dsqlWindow = true; + + dsql_nod* windowNod = MAKE_node(nod_class_exprnode, 1); + windowNod->nod_arg[0] = reinterpret_cast(window); + + parentRse = targetRse = FB_NEW(pool) RseNode(pool); + parentRse->dsqlStreams = list = MAKE_node(nod_list, 1); + list->nod_arg[0] = windowNod; + + if (rse->flags & RseNode::FLAG_WRITELOCK) { - parent_rse->nod_arg[e_rse_lock] = rse->nod_arg[e_rse_lock]; - rse->nod_arg[e_rse_lock] = NULL; + parentRse->flags |= RseNode::FLAG_WRITELOCK; + rse->flags &= ~RseNode::FLAG_WRITELOCK; } - if (rse->nod_arg[e_rse_first]) + if (rse->dsqlFirst) { - parent_rse->nod_arg[e_rse_first] = rse->nod_arg[e_rse_first]; - rse->nod_arg[e_rse_first] = NULL; + parentRse->dsqlFirst = rse->dsqlFirst; + rse->dsqlFirst = NULL; } - if (rse->nod_arg[e_rse_skip]) + if (rse->dsqlSkip) { - parent_rse->nod_arg[e_rse_skip] = rse->nod_arg[e_rse_skip]; - rse->nod_arg[e_rse_skip] = NULL; + parentRse->dsqlSkip = rse->dsqlSkip; + rse->dsqlSkip = NULL; } dsqlScratch->context->push(parent_context); // replace original contexts with parent context - remap_streams_to_parent_context(rse->nod_arg[e_rse_streams], parent_context); + remap_streams_to_parent_context(rse->dsqlStreams, parent_context); if (aggregate) { // Check for invalid contructions inside selected-items list - list = rse->nod_arg[e_rse_items]; + list = rse->dsqlSelectList; const dsql_nod* const* ptr = list->nod_arg; for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end; ptr++) { - if (InvalidReferenceFinder::find(parent_context, - aggregate->nod_arg[e_agg_group], *ptr)) + if (InvalidReferenceFinder::find(parent_context, aggregate->dsqlGroup, *ptr)) { // Invalid expression in the select list // (not contained in either an aggregate or the GROUP BY clause) @@ -5918,8 +5819,8 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp } } - parent_rse->nod_arg[e_rse_items] = FieldRemapper::remap(dsqlScratch, parent_context, true, - rse->nod_arg[e_rse_items]); + parentRse->dsqlSelectList = FieldRemapper::remap(dsqlScratch, parent_context, true, + rse->dsqlSelectList); // Remap the nodes to the partition context. for (size_t i = 0, mapCount = parent_context->ctx_win_maps.getCount(); i < mapCount; ++i) @@ -5934,19 +5835,18 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp } } - rse->nod_arg[e_rse_items] = NULL; + rse->dsqlSelectList = NULL; if (order) { if (aggregate) { // Check for invalid contructions inside the order-by list - list = rse->nod_arg[e_rse_sort]; + list = rse->dsqlOrder; const dsql_nod* const* ptr = list->nod_arg; for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end; ptr++) { - if (InvalidReferenceFinder::find(parent_context, - aggregate->nod_arg[e_agg_group], *ptr)) + if (InvalidReferenceFinder::find(parent_context, aggregate->dsqlGroup, *ptr)) { // Invalid expression in the ORDER BY list // (not contained in either an aggregate or the GROUP BY clause) @@ -5956,25 +5856,28 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp } } - parent_rse->nod_arg[e_rse_sort] = FieldRemapper::remap(dsqlScratch, parent_context, - true, rse->nod_arg[e_rse_sort]); + parentRse->dsqlOrder = FieldRemapper::remap(dsqlScratch, parent_context, + true, rse->dsqlOrder); - rse->nod_arg[e_rse_sort] = NULL; + rse->dsqlOrder = NULL; } // And, of course, reduction clauses must also apply to the parent - if (rse->nod_arg[e_rse_reduced]) + if (rse->dsqlDistinct) { - parent_rse->nod_arg[e_rse_reduced] = FieldRemapper::remap(dsqlScratch, parent_context, - true, rse->nod_arg[e_rse_reduced]); - rse->nod_arg[e_rse_reduced] = NULL; + parentRse->dsqlDistinct = FieldRemapper::remap(dsqlScratch, parent_context, + true, rse->dsqlDistinct); + rse->dsqlDistinct = NULL; } - rse = parent_rse; + rse = parentRse; + rseNod = MAKE_node(nod_class_exprnode, 1); + rseNod->nod_arg[0] = reinterpret_cast(rse); } - rse->nod_flags = flags; - return rse; + rseNod->nod_flags = flags; + + return rseNod; } @@ -6325,21 +6228,20 @@ static dsql_nod* pass1_union( DsqlCompilerScratch* dsqlScratch, dsql_nod* input, DEV_BLKCHK(order_list, dsql_type_nod); thread_db* tdbb = JRD_get_thread_data(); + MemoryPool& pool = *tdbb->getDefaultPool(); // set up the rse node for the union. - dsql_nod* union_rse = MAKE_node(nod_rse, e_rse_count); - dsql_nod* union_node = union_rse->nod_arg[e_rse_streams] = MAKE_node(nod_union, input->nod_count); + RseNode* unionRse = FB_NEW(pool) RseNode(pool); + dsql_nod* union_node = unionRse->dsqlStreams = MAKE_node(nod_union, input->nod_count); union_node->nod_flags = input->nod_flags; // generate a context for the union itself. dsql_ctx* union_context = FB_NEW(*tdbb->getDefaultPool()) dsql_ctx(*tdbb->getDefaultPool()); - if (input->nod_flags & NOD_UNION_RECURSIVE) { + if (input->nod_flags & NOD_UNION_RECURSIVE) union_context->ctx_context = dsqlScratch->recursiveCtxId; - } - else { + else union_context->ctx_context = dsqlScratch->contextNumber++; - } // process all the sub-rse's. { // scope block @@ -6351,10 +6253,9 @@ static dsql_nod* pass1_union( DsqlCompilerScratch* dsqlScratch, dsql_nod* input, dsqlScratch->scopeLevel++; *uptr = pass1_rse(dsqlScratch, *ptr, NULL, NULL, NULL, 0); dsqlScratch->scopeLevel--; + while (*(dsqlScratch->context) != base) - { dsqlScratch->unionContext.push(dsqlScratch->context->pop()); - } // Push recursive context after initial select has been processed. // Corresponding pop occurs in pass1_derived_table @@ -6364,14 +6265,14 @@ static dsql_nod* pass1_union( DsqlCompilerScratch* dsqlScratch, dsql_nod* input, } // end scope block // generate the list of fields to select. - dsql_nod* items = union_node->nod_arg[0]->nod_arg[e_rse_items]; + dsql_nod* items = ExprNode::as(union_node->nod_arg[0])->dsqlSelectList; // loop through the list nodes, checking to be sure that they have the // same number of items for (int i = 1; i < union_node->nod_count; i++) { - const dsql_nod* nod1 = union_node->nod_arg[i]->nod_arg[e_rse_items]; + const dsql_nod* nod1 = ExprNode::as(union_node->nod_arg[i])->dsqlSelectList; if (items->nod_count != nod1->nod_count) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << @@ -6399,7 +6300,7 @@ static dsql_nod* pass1_union( DsqlCompilerScratch* dsqlScratch, dsql_nod* input, { for (int i = 0; i < union_node->nod_count; i++) { - dsql_nod* nod1 = union_node->nod_arg[i]->nod_arg[e_rse_items]; + dsql_nod* nod1 = ExprNode::as(union_node->nod_arg[i])->dsqlSelectList; MAKE_desc(dsqlScratch, &nod1->nod_arg[j]->nod_desc, nod1->nod_arg[j]); tmp_list->nod_arg[i] = nod1->nod_arg[j]; @@ -6423,7 +6324,8 @@ static dsql_nod* pass1_union( DsqlCompilerScratch* dsqlScratch, dsql_nod* input, for (int i = 0; i < union_node->nod_count; i++) pass1_union_auto_cast(dsqlScratch, union_node->nod_arg[i], desc, j); } - items = union_node->nod_arg[0]->nod_arg[e_rse_items]; + + items = ExprNode::as(union_node->nod_arg[0])->dsqlSelectList; // Create mappings for union. dsql_nod* union_items = MAKE_node(nod_list, items->nod_count); @@ -6446,7 +6348,8 @@ static dsql_nod* pass1_union( DsqlCompilerScratch* dsqlScratch, dsql_nod* input, *ptr = MAKE_node(nod_class_exprnode, 1); (*ptr)->nod_arg[0] = reinterpret_cast(mapNode); } - union_rse->nod_arg[e_rse_items] = union_items; + + unionRse->dsqlSelectList = union_items; } // end scope block // Process ORDER clause, if any. @@ -6455,6 +6358,7 @@ static dsql_nod* pass1_union( DsqlCompilerScratch* dsqlScratch, dsql_nod* input, dsql_nod* sort = MAKE_node(nod_list, order_list->nod_count); dsql_nod** uptr = sort->nod_arg; dsql_nod** ptr = order_list->nod_arg; + for (const dsql_nod* const* const end = ptr + order_list->nod_count; ptr < end; ptr++, uptr++) { dsql_nod* order1 = *ptr; @@ -6502,7 +6406,7 @@ static dsql_nod* pass1_union( DsqlCompilerScratch* dsqlScratch, dsql_nod* input, order2->nod_arg[e_order_nulls] = order1->nod_arg[e_order_nulls]; } - union_rse->nod_arg[e_rse_sort] = sort; + unionRse->dsqlOrder = sort; } if (rows) @@ -6510,13 +6414,14 @@ static dsql_nod* pass1_union( DsqlCompilerScratch* dsqlScratch, dsql_nod* input, if (rows->nod_arg[e_rows_length]) { dsql_nod* sub = PASS1_node_psql(dsqlScratch, rows->nod_arg[e_rows_length], false); - union_rse->nod_arg[e_rse_first] = sub; + unionRse->dsqlFirst = sub; PASS1_set_parameter_type(dsqlScratch, sub, rows, false); } + if (rows->nod_arg[e_rows_skip]) { dsql_nod* sub = PASS1_node_psql(dsqlScratch, rows->nod_arg[e_rows_skip], false); - union_rse->nod_arg[e_rse_skip] = sub; + unionRse->dsqlSkip = sub; PASS1_set_parameter_type(dsqlScratch, sub, rows, false); } } @@ -6532,12 +6437,17 @@ static dsql_nod* pass1_union( DsqlCompilerScratch* dsqlScratch, dsql_nod* input, Arg::Gds(isc_random) << Arg::Str("WITH LOCK")); } - union_rse->nod_arg[e_rse_reduced] = union_items; + unionRse->dsqlDistinct = union_items; } - union_rse->nod_arg[e_rse_lock] = update_lock; - union_rse->nod_flags = flags; - return union_rse; + if (update_lock) + unionRse->flags |= RseNode::FLAG_WRITELOCK; + + dsql_nod* unionRseNod = MAKE_node(nod_class_exprnode, 1); + unionRseNod->nod_arg[0] = reinterpret_cast(unionRse); + unionRseNod->nod_flags = flags; + + return unionRseNod; } @@ -6562,6 +6472,8 @@ static dsql_nod* pass1_union( DsqlCompilerScratch* dsqlScratch, dsql_nod* input, static void pass1_union_auto_cast(DsqlCompilerScratch* dsqlScratch, dsql_nod* input, const dsc& desc, SSHORT position, bool in_select_list) { + thread_db* tdbb = JRD_get_thread_data(); + DEV_BLKCHK(input, dsql_type_nod); switch (input->nod_type) @@ -6609,8 +6521,6 @@ static void pass1_union_auto_cast(DsqlCompilerScratch* dsqlScratch, dsql_nod* in cast_node = select_item; else { - thread_db* tdbb = JRD_get_thread_data(); - CastNode* castNode = FB_NEW(*tdbb->getDefaultPool()) CastNode( *tdbb->getDefaultPool()); @@ -6719,33 +6629,30 @@ static void pass1_union_auto_cast(DsqlCompilerScratch* dsqlScratch, dsql_nod* in } break; - case nod_rse: - { - dsql_nod* streams = input->nod_arg[e_rse_streams]; - pass1_union_auto_cast(dsqlScratch, streams, desc, position); + case nod_class_exprnode: + { + RseNode* rseNode = ExprNode::as(input); - if (streams->nod_type == nod_union) + if (rseNode) + { + pass1_union_auto_cast(dsqlScratch, rseNode->dsqlStreams, desc, position); + + if (rseNode->dsqlStreams->nod_type == nod_union) { // We're now in a UNION under a UNION so don't change the existing mappings. // Only replace the node where the map points to, because they could be changed. - dsql_nod* union_items = input->nod_arg[e_rse_items]; - dsql_nod* sub_rse_items = streams->nod_arg[0]->nod_arg[e_rse_items]; - dsql_map* map = ExprNode::as(union_items->nod_arg[position])->map; + dsql_nod* sub_rse_items = ExprNode::as( + rseNode->dsqlStreams->nod_arg[0])->dsqlSelectList; + dsql_map* map = ExprNode::as(rseNode->dsqlSelectList->nod_arg[position])->map; map->map_node = sub_rse_items->nod_arg[position]; - union_items->nod_arg[position]->nod_desc = desc; + rseNode->dsqlSelectList->nod_arg[position]->nod_desc = desc; } else - { - pass1_union_auto_cast(dsqlScratch, input->nod_arg[e_rse_items], - desc, position, true); - } + pass1_union_auto_cast(dsqlScratch, rseNode->dsqlSelectList, desc, position, true); } + break; - - - default: - // Nothing - ; + } } } @@ -6763,6 +6670,9 @@ static void pass1_union_auto_cast(DsqlCompilerScratch* dsqlScratch, dsql_nod* in **/ static dsql_nod* pass1_update(DsqlCompilerScratch* dsqlScratch, dsql_nod* input, bool insert_or_update) { + thread_db* tdbb = JRD_get_thread_data(); + MemoryPool& pool = *tdbb->getDefaultPool(); + DEV_BLKCHK(dsqlScratch, dsql_type_req); DEV_BLKCHK(input, dsql_type_nod); @@ -6855,53 +6765,50 @@ static dsql_nod* pass1_update(DsqlCompilerScratch* dsqlScratch, dsql_nod* input, { // Process old context values for (ptr = org_values.begin(); ptr < org_values.end(); ++ptr) - { *ptr = PASS1_node_psql(dsqlScratch, *ptr, false); - } } // Process new context values for (ptr = new_values.begin(); ptr < new_values.end(); ++ptr) - { *ptr = PASS1_node_psql(dsqlScratch, *ptr, false); - } dsqlScratch->context->pop(); // Generate record selection expression - dsql_nod* rse; - if (cursor) { - rse = pass1_cursor_reference(dsqlScratch, cursor, relation); - } + dsql_nod* rseNod; + + if (cursor) + rseNod = pass1_cursor_reference(dsqlScratch, cursor, relation); else { - rse = MAKE_node(nod_rse, e_rse_count); - rse->nod_flags = (USHORT)(IPTR) input->nod_arg[e_upd_rse_flags]; + RseNode* rse = FB_NEW(pool) RseNode(pool); + + rseNod = MAKE_node(nod_class_exprnode, 1); + rseNod->nod_arg[0] = reinterpret_cast(rse); + rseNod->nod_flags = (USHORT)(IPTR) input->nod_arg[e_upd_rse_flags]; + if (input->nod_arg[e_upd_return]) - rse->nod_flags |= NOD_SELECT_EXPR_SINGLETON; + rseNod->nod_flags |= NOD_SELECT_EXPR_SINGLETON; dsql_nod* temp = MAKE_node(nod_list, 1); - rse->nod_arg[e_rse_streams] = temp; + rse->dsqlStreams = temp; temp->nod_arg[0] = PASS1_node_psql(dsqlScratch, relation, false); dsql_ctx* old_context = get_context(temp->nod_arg[0]); - if ( (temp = input->nod_arg[e_upd_boolean]) ) { - rse->nod_arg[e_rse_boolean] = PASS1_node_psql(dsqlScratch, temp, false); - } + if ((temp = input->nod_arg[e_upd_boolean])) + rse->dsqlWhere = PASS1_node_psql(dsqlScratch, temp, false); - if ( (temp = input->nod_arg[e_upd_plan]) ) { - rse->nod_arg[e_rse_plan] = PASS1_node_psql(dsqlScratch, temp, false); - } + if ((temp = input->nod_arg[e_upd_plan])) + rse->dsqlPlan = PASS1_node_psql(dsqlScratch, temp, false); - if ( (temp = input->nod_arg[e_upd_sort]) ) { - rse->nod_arg[e_rse_sort] = pass1_sort(dsqlScratch, temp, NULL); - } + if ((temp = input->nod_arg[e_upd_sort])) + rse->dsqlOrder = pass1_sort(dsqlScratch, temp, NULL); - if ( (temp = input->nod_arg[e_upd_rows]) ) + if ((temp = input->nod_arg[e_upd_rows])) { - rse->nod_arg[e_rse_first] = PASS1_node_psql(dsqlScratch, temp->nod_arg[e_rows_length], false); - rse->nod_arg[e_rse_skip] = PASS1_node_psql(dsqlScratch, temp->nod_arg[e_rows_skip], false); + rse->dsqlFirst = PASS1_node_psql(dsqlScratch, temp->nod_arg[e_rows_length], false); + rse->dsqlSkip = PASS1_node_psql(dsqlScratch, temp->nod_arg[e_rows_skip], false); } if (input->nod_arg[e_upd_return]) @@ -6911,8 +6818,8 @@ static dsql_nod* pass1_update(DsqlCompilerScratch* dsqlScratch, dsql_nod* input, } } - node->nod_arg[e_mod_source] = rse->nod_arg[e_rse_streams]->nod_arg[0]; - node->nod_arg[e_mod_rse] = rse; + node->nod_arg[e_mod_source] = ExprNode::as(rseNod)->dsqlStreams->nod_arg[0]; + node->nod_arg[e_mod_rse] = rseNod; if (isUpdateSqlCompliant) { @@ -6994,7 +6901,7 @@ static dsql_nod* pass1_update_or_insert(DsqlCompilerScratch* dsqlScratch, dsql_n // PASS1_statement will transform nod_insert to nod_store fb_assert(insert->nod_type == nod_store); - dsql_ctx* context = (dsql_ctx*) insert->nod_arg[e_sto_relation]->nod_arg[e_rel_context]; + dsql_ctx* context = ExprNode::as(insert->nod_arg[e_sto_relation])->dsqlContext; DEV_BLKCHK(context, dsql_type_ctx); dsql_rel* relation = context->ctx_relation; @@ -7359,42 +7266,36 @@ static void remap_streams_to_parent_context( dsql_nod* input, dsql_ctx* parent_c } break; - case nod_relation: - { - dsql_ctx* context = (dsql_ctx*) input->nod_arg[e_rel_context]; - DEV_BLKCHK(context, dsql_type_ctx); - context->ctx_parent = parent_context; - } - break; - case nod_join: remap_streams_to_parent_context(input->nod_arg[e_join_left_rel], parent_context); remap_streams_to_parent_context(input->nod_arg[e_join_rght_rel], parent_context); break; - case nod_derived_table: - { - dsql_nod* list = input->nod_arg[e_derived_table_rse]->nod_arg[e_rse_streams]; - remap_streams_to_parent_context(list, parent_context); - } - break; - case nod_union: { dsql_nod** rse = input->nod_arg; for (const dsql_nod* const* const end = rse + input->nod_count; rse < end; rse++) - { - remap_streams_to_parent_context((*rse)->nod_arg[e_rse_streams], parent_context); - } + remap_streams_to_parent_context(ExprNode::as(*rse)->dsqlStreams, parent_context); } break; - case nod_aggregate: - // nothing to do here. - break; - default: - fb_assert(false); + { + RelationSourceNode* relNode; + RseNode* rseNode; + + if ((relNode = ExprNode::as(input))) + { + DEV_BLKCHK(relNode->dsqlContext, dsql_type_ctx); + relNode->dsqlContext->ctx_parent = parent_context; + } + else if ((rseNode = ExprNode::as(input))) + remap_streams_to_parent_context(rseNode->dsqlStreams, parent_context); + else if (!ExprNode::as(input)) + { + fb_assert(false); + } + } break; } } @@ -7583,7 +7484,6 @@ bool PASS1_set_parameter_type(DsqlCompilerScratch* dsqlScratch, dsql_nod* in_nod return false; } - case nod_limit: case nod_rows: { bool result = false; @@ -7621,7 +7521,7 @@ static void set_parameters_name( dsql_nod* list_node, const dsql_nod* rel_node) DEV_BLKCHK(list_node, dsql_type_nod); DEV_BLKCHK(rel_node, dsql_type_nod); - const dsql_ctx* context = reinterpret_cast(rel_node->nod_arg[e_rel_context]); + const dsql_ctx* context = ExprNode::as(rel_node)->dsqlContext; DEV_BLKCHK(context, dsql_type_ctx); const dsql_rel* relation = context->ctx_relation; @@ -7708,7 +7608,6 @@ static void set_parameter_name( dsql_nod* par_node, const dsql_nod* fld_node, co } return; - case nod_limit: case nod_rows: { dsql_nod** ptr = par_node->nod_arg; @@ -8001,9 +7900,6 @@ void DSQL_pretty(const dsql_nod* node, int column) case nod_revoke: verb = "revoke"; break; - case nod_rse: - verb = "rse"; - break; case nod_select: verb = "select"; break; @@ -8035,9 +7931,6 @@ void DSQL_pretty(const dsql_nod* node, int column) verb = "searched_case"; break; - case nod_limit: - verb = "limit"; - break; case nod_rows: verb = "rows"; break; @@ -8279,9 +8172,6 @@ void DSQL_pretty(const dsql_nod* node, int column) case nod_end_backup: verb = "end_backup"; break; - case nod_derived_table: - verb = "derived_table"; - break; case nod_breakleave: verb = "breakleave"; @@ -8302,40 +8192,6 @@ void DSQL_pretty(const dsql_nod* node, int column) (int)(IPTR)node->nod_arg[e_label_number]); return; - case nod_aggregate: - { - verb = "aggregate"; - trace_line("%s%s\n", buffer, verb.c_str()); - const dsql_ctx* context = (dsql_ctx*) node->nod_arg[e_agg_context]; - trace_line("%s context %d\n", buffer, context->ctx_context); - - trace_line("%s map\n", buffer); - if (context->ctx_map != NULL) - DSQL_pretty(context->ctx_map->map_node, column + 2); - - for (PartitionMap* const* partitionMap = context->ctx_win_maps.begin(); - partitionMap != context->ctx_win_maps.end(); - ++partitionMap) - { - trace_line("%s partitionMap\n", buffer); - - dsql_map* map = (*partitionMap)->map; - if (map != NULL) - trace_line("%s map\n", buffer); - - while (map) - { - trace_line("%s position %d\n", buffer, map->map_position); - DSQL_pretty(map->map_node, column + 2); - map = map->map_next; - } - } - - DSQL_pretty(node->nod_arg[e_agg_group], column + 1); - DSQL_pretty(node->nod_arg[e_agg_rse], column + 1); - return; - } - case nod_field_name: trace_line("%sfield name: \"", buffer); string = (dsql_str*) node->nod_arg[e_fln_context]; @@ -8350,39 +8206,12 @@ void DSQL_pretty(const dsql_nod* node, int column) } return; - case nod_relation: - { - const dsql_ctx* context = (dsql_ctx*) node->nod_arg[e_rel_context]; - const dsql_rel* relation = context->ctx_relation; - const dsql_prc* procedure = context->ctx_procedure; - if ( relation != NULL ) - { - trace_line("%srelation %s, context %d\n", - buffer, relation->rel_name.c_str(), context->ctx_context); - } - else if ( procedure != NULL ) - { - trace_line("%sprocedure %s, context %d\n", - buffer, procedure->prc_name.toString().c_str(), context->ctx_context); - } - else - { - trace_line("%sUNKNOWN DB OBJECT, context %d\n", - buffer, context->ctx_context); - } - return; - } - case nod_var_name: trace_line("%svariable name: \"", buffer); string = (dsql_str*) node->nod_arg[e_vrn_name]; trace_line("%s\"\n", string->str_data); return; - case nod_query_spec: - verb = "query_spec"; - break; - case nod_mod_udf: verb = "mod_udf"; break; diff --git a/src/jrd/RecordSourceNodes.cpp b/src/jrd/RecordSourceNodes.cpp index 867353fe1d..3552f0dc05 100644 --- a/src/jrd/RecordSourceNodes.cpp +++ b/src/jrd/RecordSourceNodes.cpp @@ -28,12 +28,16 @@ #include "../dsql/BoolNodes.h" #include "../dsql/ExprNodes.h" #include "../dsql/StmtNodes.h" +#include "../dsql/dsql.h" #include "../jrd/btr_proto.h" #include "../jrd/cmp_proto.h" #include "../common/dsc_proto.h" #include "../jrd/met_proto.h" #include "../jrd/opt_proto.h" #include "../jrd/par_proto.h" +#include "../dsql/ddl_proto.h" +#include "../dsql/gen_proto.h" +#include "../dsql/pass1_proto.h" using namespace Firebird; using namespace Jrd; @@ -251,6 +255,130 @@ RelationSourceNode* RelationSourceNode::parse(thread_db* tdbb, CompilerScratch* return node; } +bool RelationSourceNode::dsqlAggregateFinder(AggregateFinder& visitor) +{ + // Check if relation is a procedure. + if (dsqlContext->ctx_procedure) + { + // Check if a aggregate is buried inside the input parameters. + return visitor.visit(&dsqlContext->ctx_proc_inputs); + } + + return false; +} + +bool RelationSourceNode::dsqlAggregate2Finder(Aggregate2Finder& visitor) +{ + return false; +} + +bool RelationSourceNode::dsqlInvalidReferenceFinder(InvalidReferenceFinder& visitor) +{ + // If relation is a procedure, check if the parameters are valid. + if (dsqlContext->ctx_procedure) + return visitor.visit(&dsqlContext->ctx_proc_inputs); + + return false; +} + +bool RelationSourceNode::dsqlSubSelectFinder(SubSelectFinder& visitor) +{ + return false; +} + +bool RelationSourceNode::dsqlFieldFinder(FieldFinder& visitor) +{ + return false; +} + +bool RelationSourceNode::dsqlFieldRemapper(FieldRemapper& visitor) +{ + // Check if relation is a procedure. + if (dsqlContext->ctx_procedure) + visitor.visit(&dsqlContext->ctx_proc_inputs); // Remap the input parameters. + + return false; +} + +bool RelationSourceNode::dsqlMatch(const ExprNode* other, bool ignoreMapCast) const +{ + const RelationSourceNode* o = other->as(); + return o && dsqlContext == o->dsqlContext; +} + +void RelationSourceNode::genBlr(DsqlCompilerScratch* dsqlScratch) +{ + genRelation(dsqlScratch, dsqlContext); +} + +// Generate blr for a relation reference. +void RelationSourceNode::genRelation(DsqlCompilerScratch* dsqlScratch, dsql_ctx* context) +{ + const dsql_rel* relation = context->ctx_relation; + const dsql_prc* procedure = context->ctx_procedure; + + // if this is a trigger or procedure, don't want relation id used + if (relation) + { + if (DDL_ids(dsqlScratch)) + { + dsqlScratch->appendUChar(context->ctx_alias ? blr_rid2 : blr_rid); + dsqlScratch->appendUShort(relation->rel_id); + } + else + { + dsqlScratch->appendUChar(context->ctx_alias ? blr_relation2 : blr_relation); + dsqlScratch->appendMetaString(relation->rel_name.c_str()); + } + + if (context->ctx_alias) + dsqlScratch->appendMetaString(context->ctx_alias); + + GEN_stuff_context(dsqlScratch, context); + } + else if (procedure) + { + if (DDL_ids(dsqlScratch)) + { + dsqlScratch->appendUChar(context->ctx_alias ? blr_pid2 : blr_pid); + dsqlScratch->appendUShort(procedure->prc_id); + } + else + { + if (procedure->prc_name.package.hasData()) + { + dsqlScratch->appendUChar(context->ctx_alias ? blr_procedure4 : blr_procedure3); + dsqlScratch->appendMetaString(procedure->prc_name.package.c_str()); + dsqlScratch->appendMetaString(procedure->prc_name.identifier.c_str()); + } + else + { + dsqlScratch->appendUChar(context->ctx_alias ? blr_procedure2 : blr_procedure); + dsqlScratch->appendMetaString(procedure->prc_name.identifier.c_str()); + } + } + + if (context->ctx_alias) + dsqlScratch->appendMetaString(context->ctx_alias); + + GEN_stuff_context(dsqlScratch, context); + + dsql_nod* inputs = context->ctx_proc_inputs; + + if (inputs) + { + dsqlScratch->appendUShort(inputs->nod_count); + + dsql_nod* const* ptr = inputs->nod_arg; + + for (const dsql_nod* const* const end = ptr + inputs->nod_count; ptr < end; ptr++) + GEN_expr(dsqlScratch, *ptr); + } + else + dsqlScratch->appendUShort(0); + } +} + RelationSourceNode* RelationSourceNode::copy(thread_db* tdbb, NodeCopier& copier) { if (!copier.remap) @@ -801,6 +929,140 @@ AggregateSourceNode* AggregateSourceNode::parse(thread_db* tdbb, CompilerScratch return node; } +bool AggregateSourceNode::dsqlAggregateFinder(AggregateFinder& visitor) +{ + return !visitor.ignoreSubSelects && visitor.visit(&dsqlRse); +} + +bool AggregateSourceNode::dsqlAggregate2Finder(Aggregate2Finder& visitor) +{ + // Pass only dsqlGroup. + return visitor.visit(&dsqlGroup); +} + +bool AggregateSourceNode::dsqlInvalidReferenceFinder(InvalidReferenceFinder& visitor) +{ + return visitor.visit(&dsqlRse); +} + +bool AggregateSourceNode::dsqlSubSelectFinder(SubSelectFinder& visitor) +{ + return false; +} + +bool AggregateSourceNode::dsqlFieldFinder(FieldFinder& visitor) +{ + // Pass only dsqlGroup. + return visitor.visit(&dsqlGroup); +} + +bool AggregateSourceNode::dsqlFieldRemapper(FieldRemapper& visitor) +{ + visitor.visit(&dsqlRse); + return false; +} + +bool AggregateSourceNode::dsqlMatch(const ExprNode* other, bool ignoreMapCast) const +{ + const AggregateSourceNode* o = other->as(); + + return o && dsqlContext == o->dsqlContext && + PASS1_node_match(dsqlGroup, o->dsqlGroup, ignoreMapCast) && + PASS1_node_match(dsqlRse, o->dsqlRse, ignoreMapCast); +} + +void AggregateSourceNode::genBlr(DsqlCompilerScratch* dsqlScratch) +{ + dsqlScratch->appendUChar((dsqlWindow ? blr_window : blr_aggregate)); + + if (!dsqlWindow) + GEN_stuff_context(dsqlScratch, dsqlContext); + + GEN_rse(dsqlScratch, dsqlRse); + + // Handle PARTITION BY and GROUP BY clause + + if (dsqlWindow) + { + fb_assert(dsqlContext->ctx_win_maps.hasData()); + dsqlScratch->appendUChar(dsqlContext->ctx_win_maps.getCount()); // number of windows + + for (Array::iterator i = dsqlContext->ctx_win_maps.begin(); + i != dsqlContext->ctx_win_maps.end(); + ++i) + { + dsqlScratch->appendUChar(blr_partition_by); + dsql_nod* partition = (*i)->partition; + dsql_nod* partitionRemapped = (*i)->partitionRemapped; + dsql_nod* order = (*i)->order; + + dsqlScratch->appendUChar((*i)->context); + + if (partition) + { + dsqlScratch->appendUChar(partition->nod_count); // partition by expression count + + dsql_nod** ptr = partition->nod_arg; + for (const dsql_nod* const* end = ptr + partition->nod_count; ptr < end; ++ptr) + GEN_expr(dsqlScratch, *ptr); + + ptr = partitionRemapped->nod_arg; + for (const dsql_nod* const* end = ptr + partitionRemapped->nod_count; ptr < end; ++ptr) + GEN_expr(dsqlScratch, *ptr); + } + else + dsqlScratch->appendUChar(0); // partition by expression count + + if (order) + GEN_sort(dsqlScratch, order); + else + { + dsqlScratch->appendUChar(blr_sort); + dsqlScratch->appendUChar(0); + } + + genMap(dsqlScratch, (*i)->map); + } + } + else + { + dsqlScratch->appendUChar(blr_group_by); + + dsql_nod* list = dsqlGroup; + + if (list != NULL) + { + dsqlScratch->appendUChar(list->nod_count); + dsql_nod** ptr = list->nod_arg; + + for (const dsql_nod* const* end = ptr + list->nod_count; ptr < end; ptr++) + GEN_expr(dsqlScratch, *ptr); + } + else + dsqlScratch->appendUChar(0); + + genMap(dsqlScratch, dsqlContext->ctx_map); + } +} + +// Generate a value map for a record selection expression. +void AggregateSourceNode::genMap(DsqlCompilerScratch* dsqlScratch, dsql_map* map) +{ + USHORT count = 0; + + for (dsql_map* temp = map; temp; temp = temp->map_next) + ++count; + + dsqlScratch->appendUChar(blr_map); + dsqlScratch->appendUShort(count); + + for (dsql_map* temp = map; temp; temp = temp->map_next) + { + dsqlScratch->appendUShort(temp->map_position); + GEN_expr(dsqlScratch, temp->map_node); + } +} + AggregateSourceNode* AggregateSourceNode::copy(thread_db* tdbb, NodeCopier& copier) { if (!copier.remap) @@ -1487,6 +1749,59 @@ void WindowSourceNode::findDependentFromStreams(const OptimizerRetrieval* optRet //-------------------- +bool RseNode::dsqlAggregateFinder(AggregateFinder& visitor) +{ + AutoSetRestore autoValidateExpr(&visitor.currentLevel, visitor.currentLevel + 1); + return visitor.visit(&dsqlStreams) | visitor.visit(&dsqlWhere) | visitor.visit(&dsqlSelectList); +} + +bool RseNode::dsqlAggregate2Finder(Aggregate2Finder& visitor) +{ + AutoSetRestore autoCurrentScopeLevelEqual(&visitor.currentScopeLevelEqual, false); + // Pass dsqlWhere and dsqlSelectList + return visitor.visit(&dsqlWhere) | visitor.visit(&dsqlSelectList); +} + +bool RseNode::dsqlInvalidReferenceFinder(InvalidReferenceFinder& visitor) +{ + return false; +} + +bool RseNode::dsqlSubSelectFinder(SubSelectFinder& visitor) +{ + return true; +} + +bool RseNode::dsqlFieldFinder(FieldFinder& visitor) +{ + // Pass dsqlWhere and dsqlSelectList + return visitor.visit(&dsqlWhere) | visitor.visit(&dsqlSelectList); +} + +bool RseNode::dsqlFieldRemapper(FieldRemapper& visitor) +{ + AutoSetRestore autoCurrentLevel(&visitor.currentLevel, visitor.currentLevel + 1); + + visitor.visit(&dsqlStreams); + visitor.visit(&dsqlWhere); + visitor.visit(&dsqlSelectList); + visitor.visit(&dsqlOrder); + + return false; +} + +bool RseNode::dsqlMatch(const ExprNode* other, bool ignoreMapCast) const +{ + const RseNode* o = other->as(); + + if (!o) + return false; + + fb_assert(dsqlContext && o->dsqlContext); + + return dsqlContext == o->dsqlContext; +} + RseNode* RseNode::copy(thread_db* tdbb, NodeCopier& copier) { RseNode* newSource = FB_NEW(*tdbb->getDefaultPool()) RseNode(*tdbb->getDefaultPool()); diff --git a/src/jrd/RecordSourceNodes.h b/src/jrd/RecordSourceNodes.h index a563078793..c538035055 100644 --- a/src/jrd/RecordSourceNodes.h +++ b/src/jrd/RecordSourceNodes.h @@ -269,6 +269,7 @@ class RelationSourceNode : public TypedNode(pool), + dsqlContext(NULL), relation(NULL), context(0), alias(NULL), @@ -279,6 +280,18 @@ public: static RelationSourceNode* parse(thread_db* tdbb, CompilerScratch* csb, SSHORT blrOp, bool parseContext); + static void genRelation(DsqlCompilerScratch* dsqlScratch, dsql_ctx* context); + + virtual bool dsqlAggregateFinder(AggregateFinder& visitor); + virtual bool dsqlAggregate2Finder(Aggregate2Finder& visitor); + virtual bool dsqlInvalidReferenceFinder(InvalidReferenceFinder& visitor); + virtual bool dsqlSubSelectFinder(SubSelectFinder& visitor); + virtual bool dsqlFieldFinder(FieldFinder& visitor); + virtual bool dsqlFieldRemapper(FieldRemapper& visitor); + + virtual bool dsqlMatch(const ExprNode* other, bool ignoreMapCast) const; + virtual void genBlr(DsqlCompilerScratch* dsqlScratch); + virtual RelationSourceNode* copy(thread_db* tdbb, NodeCopier& copier); virtual void ignoreDbKey(thread_db* tdbb, CompilerScratch* csb) const; @@ -322,6 +335,7 @@ public: virtual RecordSource* compile(thread_db* tdbb, OptimizerBlk* opt, bool innerSubStream); public: + dsql_ctx* dsqlContext; jrd_rel* relation; SSHORT context; // user-specified context number for the relation reference const char* alias; // SQL alias for the relation @@ -396,6 +410,10 @@ class AggregateSourceNode : public TypedNode(pool), + dsqlContext(NULL), + dsqlGroup(NULL), + dsqlRse(NULL), + dsqlWindow(false), group(NULL), map(NULL), rse(NULL) @@ -404,6 +422,16 @@ public: static AggregateSourceNode* parse(thread_db* tdbb, CompilerScratch* csb); + virtual bool dsqlAggregateFinder(AggregateFinder& visitor); + virtual bool dsqlAggregate2Finder(Aggregate2Finder& visitor); + virtual bool dsqlInvalidReferenceFinder(InvalidReferenceFinder& visitor); + virtual bool dsqlSubSelectFinder(SubSelectFinder& visitor); + virtual bool dsqlFieldFinder(FieldFinder& visitor); + virtual bool dsqlFieldRemapper(FieldRemapper& visitor); + + virtual bool dsqlMatch(const ExprNode* other, bool ignoreMapCast) const; + virtual void genBlr(DsqlCompilerScratch* dsqlScratch); + virtual AggregateSourceNode* copy(thread_db* tdbb, NodeCopier& copier); virtual void ignoreDbKey(thread_db* tdbb, CompilerScratch* csb) const; virtual RecordSourceNode* pass1(thread_db* tdbb, CompilerScratch* csb); @@ -424,10 +452,16 @@ public: virtual RecordSource* compile(thread_db* tdbb, OptimizerBlk* opt, bool innerSubStream); private: + void genMap(DsqlCompilerScratch* dsqlScratch, dsql_map* map); + RecordSource* generate(thread_db* tdbb, OptimizerBlk* opt, BoolExprNodeStack* parentStack, UCHAR shellStream); public: + dsql_ctx* dsqlContext; + dsql_nod* dsqlGroup; + dsql_nod* dsqlRse; + bool dsqlWindow; NestConst group; NestConst map; @@ -551,11 +585,31 @@ public: explicit RseNode(MemoryPool& pool) : TypedNode(pool), + dsqlFirst(NULL), + dsqlSkip(NULL), + dsqlDistinct(NULL), + dsqlSelectList(NULL), + dsqlFrom(NULL), + dsqlWhere(NULL), + dsqlGroup(NULL), + dsqlHaving(NULL), + dsqlOrder(NULL), + dsqlPlan(NULL), + dsqlStreams(NULL), + dsqlContext(NULL), rse_jointype(0), rse_invariants(NULL), rse_relations(pool), flags(0) { + addChildNode(dsqlStreams); + addChildNode(dsqlWhere); + addChildNode(dsqlOrder); + addChildNode(dsqlDistinct); + addChildNode(dsqlSelectList); + addChildNode(dsqlFirst); + addChildNode(dsqlSkip); + addChildNode(dsqlPlan); } RseNode* clone() @@ -581,6 +635,15 @@ public: { } + virtual bool dsqlAggregateFinder(AggregateFinder& visitor); + virtual bool dsqlAggregate2Finder(Aggregate2Finder& visitor); + virtual bool dsqlInvalidReferenceFinder(InvalidReferenceFinder& visitor); + virtual bool dsqlSubSelectFinder(SubSelectFinder& visitor); + virtual bool dsqlFieldFinder(FieldFinder& visitor); + virtual bool dsqlFieldRemapper(FieldRemapper& visitor); + + virtual bool dsqlMatch(const ExprNode* other, bool ignoreMapCast) const; + virtual RseNode* copy(thread_db* tdbb, NodeCopier& copier); virtual void ignoreDbKey(thread_db* tdbb, CompilerScratch* csb) const; virtual RseNode* pass1(thread_db* tdbb, CompilerScratch* csb); @@ -611,6 +674,18 @@ private: static void planSet(CompilerScratch* csb, PlanNode* plan); public: + dsql_nod* dsqlFirst; + dsql_nod* dsqlSkip; + dsql_nod* dsqlDistinct; + dsql_nod* dsqlSelectList; + dsql_nod* dsqlFrom; + dsql_nod* dsqlWhere; + dsql_nod* dsqlGroup; + dsql_nod* dsqlHaving; + dsql_nod* dsqlOrder; + dsql_nod* dsqlPlan; + dsql_nod* dsqlStreams; + dsql_ctx* dsqlContext; // derived table support USHORT rse_jointype; // inner, left, full NestConst rse_first; NestConst rse_skip;