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:
parent
3c662a48c4
commit
123aa675ab
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
343
src/dsql/gen.cpp
343
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<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;
|
||||
|
@ -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*);
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
176
src/dsql/parse.y
176
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<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
|
||||
|
1055
src/dsql/pass1.cpp
1055
src/dsql/pass1.cpp
File diff suppressed because it is too large
Load Diff
@ -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());
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user