8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 22:43:03 +01:00

Refactor nod_aggregate, nod_relation, nod_rse, nod_derived_table, nod_query_spec and nod_limit

This commit is contained in:
asfernandes 2011-01-09 21:58:56 +00:00
parent 3c662a48c4
commit 123aa675ab
14 changed files with 1143 additions and 1135 deletions

View File

@ -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<dsql_nod*>(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<RseNode>(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<dsql_nod*>(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;
}

View File

@ -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<RseNode>(rse)->dsqlSelectList;
dsql_nod** itemsPtr = items->nod_arg;
SortedArray<dsql_fld*> 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<RseNode>(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<dsql_nod*>(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<bool> 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<RseNode>(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<RseNode>(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<RseNode>(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<dsql_nod*>(andNode);

View File

@ -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<RseNode>(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<RseNode>(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<dsql_nod*>(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);

View File

@ -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<dsql_nod*>(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<dsql_nod*>(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<dsql_ctx*>(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<RelationSourceNode>(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<RelationSourceNode>(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<RseNode>(dsqlRse)->dsqlSelectList->nod_arg[0];
return false;
}

View File

@ -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"

View File

@ -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<RseNode>(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<RseNode>(dsqlSelect)->dsqlSelectList;
if (dsqlInto)
{

View File

@ -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<ExprNode*>(node->nod_arg[0]);
if (exprNode->is<RseNode>())
{
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<RseNode>(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<PartitionMap*>::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<RelationSourceNode>(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<RseNode>(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<RseNode>(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<NonPooled<dsql_par*, dsql_ctx*> > 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<RelationSourceNode>(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<RelationSourceNode>(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<RelationSourceNode>(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<RelationSourceNode>(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<RelationSourceNode>(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<RseNode>(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<RseNode>(sub_rse)->dsqlSelectList;
dsqlScratch->appendUChar(blr_map);
dsqlScratch->appendUShort(items->nod_count);
USHORT count = 0;

View File

@ -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<Jrd::dsql_nod*>& 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*);

View File

@ -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<RseNode>(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:

View File

@ -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

View File

@ -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<RseNode>();
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

File diff suppressed because it is too large Load Diff

View File

@ -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<RelationSourceNode>();
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<AggregateSourceNode>();
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<PartitionMap*>::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<USHORT> autoValidateExpr(&visitor.currentLevel, visitor.currentLevel + 1);
return visitor.visit(&dsqlStreams) | visitor.visit(&dsqlWhere) | visitor.visit(&dsqlSelectList);
}
bool RseNode::dsqlAggregate2Finder(Aggregate2Finder& visitor)
{
AutoSetRestore<bool> 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<USHORT> 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<RseNode>();
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());

View File

@ -269,6 +269,7 @@ class RelationSourceNode : public TypedNode<RecordSourceNode, RecordSourceNode::
public:
explicit RelationSourceNode(MemoryPool& pool)
: TypedNode<RecordSourceNode, RecordSourceNode::TYPE_RELATION>(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<RecordSourceNode, RecordSourceNode:
public:
explicit AggregateSourceNode(MemoryPool& pool)
: TypedNode<RecordSourceNode, RecordSourceNode::TYPE_AGGREGATE_SOURCE>(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<SortNode> group;
NestConst<MapNode> map;
@ -551,11 +585,31 @@ public:
explicit RseNode(MemoryPool& pool)
: TypedNode<RecordSourceNode, RecordSourceNode::TYPE_RSE>(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<ValueExprNode> rse_first;
NestConst<ValueExprNode> rse_skip;