mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 19:23:03 +01:00
Fix derived table issues with NEW/OLD contexts (Triggers/check-constraints)
Also adjust IN predicate behaviour to derived table. PLAN parsing for derived tables will be fixed later.
This commit is contained in:
parent
67b12093cf
commit
22ac7c9cdc
@ -1166,9 +1166,11 @@ static void define_constraint_trigger(dsql_req* request, dsql_nod* node)
|
|||||||
// record for fetch operation".
|
// record for fetch operation".
|
||||||
|
|
||||||
relation_node->nod_arg[e_rln_alias] = (dsql_nod*) MAKE_cstring(OLD_CONTEXT);
|
relation_node->nod_arg[e_rln_alias] = (dsql_nod*) MAKE_cstring(OLD_CONTEXT);
|
||||||
PASS1_make_context(request, relation_node);
|
dsql_ctx* oldContext = PASS1_make_context(request, relation_node);
|
||||||
|
oldContext->ctx_flags |= CTX_system;
|
||||||
relation_node->nod_arg[e_rln_alias] = (dsql_nod*) MAKE_cstring(NEW_CONTEXT);
|
relation_node->nod_arg[e_rln_alias] = (dsql_nod*) MAKE_cstring(NEW_CONTEXT);
|
||||||
PASS1_make_context(request, relation_node);
|
dsql_ctx* newContext = PASS1_make_context(request, relation_node);
|
||||||
|
newContext->ctx_flags |= CTX_system;
|
||||||
|
|
||||||
// generate the condition for firing the trigger
|
// generate the condition for firing the trigger
|
||||||
|
|
||||||
@ -3109,7 +3111,8 @@ static void define_trigger( dsql_req* request, dsql_nod* node)
|
|||||||
{
|
{
|
||||||
relation_node->nod_arg[e_rln_alias] =
|
relation_node->nod_arg[e_rln_alias] =
|
||||||
(dsql_nod*) MAKE_cstring(OLD_CONTEXT);
|
(dsql_nod*) MAKE_cstring(OLD_CONTEXT);
|
||||||
PASS1_make_context(request, relation_node);
|
dsql_ctx* oldContext = PASS1_make_context(request, relation_node);
|
||||||
|
oldContext->ctx_flags |= CTX_system;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -3120,7 +3123,8 @@ static void define_trigger( dsql_req* request, dsql_nod* node)
|
|||||||
{
|
{
|
||||||
relation_node->nod_arg[e_rln_alias] =
|
relation_node->nod_arg[e_rln_alias] =
|
||||||
(dsql_nod*) MAKE_cstring(NEW_CONTEXT);
|
(dsql_nod*) MAKE_cstring(NEW_CONTEXT);
|
||||||
PASS1_make_context(request, relation_node);
|
dsql_ctx* newContext = PASS1_make_context(request, relation_node);
|
||||||
|
newContext->ctx_flags |= CTX_system;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -4010,9 +4014,11 @@ static void define_view_trigger( dsql_req* request, dsql_nod* node, dsql_nod* rs
|
|||||||
reset_context_stack(request);
|
reset_context_stack(request);
|
||||||
dsql_nod* temp_alias = relation_node->nod_arg[e_rln_alias];
|
dsql_nod* temp_alias = relation_node->nod_arg[e_rln_alias];
|
||||||
relation_node->nod_arg[e_rln_alias] = (dsql_nod*) MAKE_cstring(OLD_CONTEXT);
|
relation_node->nod_arg[e_rln_alias] = (dsql_nod*) MAKE_cstring(OLD_CONTEXT);
|
||||||
PASS1_make_context(request, relation_node);
|
dsql_ctx* oldContext = PASS1_make_context(request, relation_node);
|
||||||
|
oldContext->ctx_flags |= CTX_system;
|
||||||
relation_node->nod_arg[e_rln_alias] = (dsql_nod*) MAKE_cstring(NEW_CONTEXT);
|
relation_node->nod_arg[e_rln_alias] = (dsql_nod*) MAKE_cstring(NEW_CONTEXT);
|
||||||
PASS1_make_context(request, relation_node);
|
dsql_ctx* newContext = PASS1_make_context(request, relation_node);
|
||||||
|
newContext->ctx_flags |= CTX_system;
|
||||||
relation_node->nod_arg[e_rln_alias] = temp_alias;
|
relation_node->nod_arg[e_rln_alias] = temp_alias;
|
||||||
|
|
||||||
if (sav_context) {
|
if (sav_context) {
|
||||||
|
@ -532,6 +532,7 @@ public:
|
|||||||
dsql_nod* ctx_rse; //!< Sub-rse for aggregates
|
dsql_nod* ctx_rse; //!< Sub-rse for aggregates
|
||||||
dsql_ctx* ctx_parent; //!< Parent context for aggregates
|
dsql_ctx* ctx_parent; //!< Parent context for aggregates
|
||||||
TEXT* ctx_alias; //!< Context alias
|
TEXT* ctx_alias; //!< Context alias
|
||||||
|
TEXT* ctx_internal_alias; //!< Alias as specified in query
|
||||||
USHORT ctx_context; //!< Context id
|
USHORT ctx_context; //!< Context id
|
||||||
USHORT ctx_scope_level; //!< Subquery level within this request
|
USHORT ctx_scope_level; //!< Subquery level within this request
|
||||||
USHORT ctx_flags; //!< Various flag values
|
USHORT ctx_flags; //!< Various flag values
|
||||||
@ -559,6 +560,7 @@ public:
|
|||||||
// Flag values for ctx_flags
|
// Flag values for ctx_flags
|
||||||
|
|
||||||
const USHORT CTX_outer_join = 0x01; // reference is part of an outer join
|
const USHORT CTX_outer_join = 0x01; // reference is part of an outer join
|
||||||
|
const USHORT CTX_system = 0x02; // Context generated by system (NEW/OLD in triggers,check-constraint)
|
||||||
|
|
||||||
//! Aggregate/union map block to map virtual fields to their base
|
//! Aggregate/union map block to map virtual fields to their base
|
||||||
//! TMN: NOTE! This datatype should definitely be renamed!
|
//! TMN: NOTE! This datatype should definitely be renamed!
|
||||||
|
@ -404,7 +404,8 @@ enum nod_flags_vals {
|
|||||||
NOD_CURSOR_FOR = 2,
|
NOD_CURSOR_FOR = 2,
|
||||||
NOD_CURSOR_ALL = USHORT(-1U),
|
NOD_CURSOR_ALL = USHORT(-1U),
|
||||||
|
|
||||||
NOD_DT_IGNORE_COLUMN_CHECK = 1
|
NOD_DT_IGNORE_COLUMN_CHECK = 1,
|
||||||
|
NOD_DT_ALLOW_OUTER_REFERENCE = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parameters to MAKE_constant
|
// Parameters to MAKE_constant
|
||||||
|
@ -395,6 +395,11 @@ dsql_ctx* PASS1_make_context(dsql_req* request, dsql_nod* relation_node)
|
|||||||
string = (dsql_str*) relation_node->nod_arg[e_rln_alias];
|
string = (dsql_str*) relation_node->nod_arg[e_rln_alias];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (string)
|
||||||
|
{
|
||||||
|
context->ctx_internal_alias = (TEXT*) string->str_data;
|
||||||
|
}
|
||||||
|
|
||||||
DEV_BLKCHK(string, dsql_type_str);
|
DEV_BLKCHK(string, dsql_type_str);
|
||||||
if (request->req_alias_relation_prefix && !(relation_node->nod_type == nod_derived_table))
|
if (request->req_alias_relation_prefix && !(relation_node->nod_type == nod_derived_table))
|
||||||
{
|
{
|
||||||
@ -2928,7 +2933,7 @@ static dsql_nod* pass1_any( dsql_req* request, dsql_nod* input, NOD_TYPE ntype)
|
|||||||
// create a derived table representing our subquery
|
// create a derived table representing our subquery
|
||||||
dsql_nod* dt = MAKE_node(nod_derived_table, e_derived_table_count);
|
dsql_nod* dt = MAKE_node(nod_derived_table, e_derived_table_count);
|
||||||
// Ignore validation for columnames that must exist for "user" derived tables.
|
// Ignore validation for columnames that must exist for "user" derived tables.
|
||||||
dt->nod_flags |= NOD_DT_IGNORE_COLUMN_CHECK;
|
dt->nod_flags |= (NOD_DT_IGNORE_COLUMN_CHECK | NOD_DT_ALLOW_OUTER_REFERENCE);
|
||||||
dt->nod_arg[e_derived_table_rse] = input->nod_arg[1];
|
dt->nod_arg[e_derived_table_rse] = input->nod_arg[1];
|
||||||
dsql_nod* from = MAKE_node(nod_list, 1);
|
dsql_nod* from = MAKE_node(nod_list, 1);
|
||||||
from->nod_arg[0] = dt;
|
from->nod_arg[0] = dt;
|
||||||
@ -3658,8 +3663,21 @@ static dsql_nod* pass1_derived_table(dsql_req* request, dsql_nod* input, bool pr
|
|||||||
|
|
||||||
// Change req_context, because when we are processing the derived table rse
|
// Change req_context, because when we are processing the derived table rse
|
||||||
// it may not reference to other streams in the same scope_level.
|
// it may not reference to other streams in the same scope_level.
|
||||||
|
const bool allowOuterReference = (input->nod_flags & NOD_DT_ALLOW_OUTER_REFERENCE);
|
||||||
DsqlContextStack temp;
|
DsqlContextStack temp;
|
||||||
request->req_context = &temp;
|
if (!allowOuterReference)
|
||||||
|
{
|
||||||
|
// Put special contexts (NEW/OLD) also on the stack
|
||||||
|
for (DsqlContextStack::iterator stack(*request->req_context); stack.hasData(); ++stack)
|
||||||
|
{
|
||||||
|
dsql_ctx* context = stack.object();
|
||||||
|
if (context->ctx_flags & CTX_system)
|
||||||
|
{
|
||||||
|
temp.push(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
request->req_context = &temp;
|
||||||
|
}
|
||||||
request->req_alias_relation_prefix = pass1_alias_concat(req_alias_relation_prefix, alias);
|
request->req_alias_relation_prefix = pass1_alias_concat(req_alias_relation_prefix, alias);
|
||||||
|
|
||||||
// AB: 2005-01-06
|
// AB: 2005-01-06
|
||||||
@ -3695,7 +3713,7 @@ static dsql_nod* pass1_derived_table(dsql_req* request, dsql_nod* input, bool pr
|
|||||||
// Finish off by cleaning up contexts and put them into req_dt_context
|
// Finish off by cleaning up contexts and put them into req_dt_context
|
||||||
// so create view (ddl) can deal with it.
|
// so create view (ddl) can deal with it.
|
||||||
// Also add the used contexts into the childs stack.
|
// Also add the used contexts into the childs stack.
|
||||||
while (request->req_context->hasData())
|
while (request->req_context->hasData() && (request->req_context != req_base))
|
||||||
{
|
{
|
||||||
request->req_dt_context.push(request->req_context->object());
|
request->req_dt_context.push(request->req_context->object());
|
||||||
context->ctx_childs_derived_table.push(request->req_context->pop());
|
context->ctx_childs_derived_table.push(request->req_context->pop());
|
||||||
@ -4100,15 +4118,15 @@ static dsql_nod* pass1_field( dsql_req* request, dsql_nod* input,
|
|||||||
}
|
}
|
||||||
|
|
||||||
dsql_fld* field;
|
dsql_fld* field;
|
||||||
if (request->req_alias_relation_prefix && qualifier) {
|
//if (request->req_alias_relation_prefix && qualifier) {
|
||||||
dsql_str* req_qualifier =
|
//dsql_str* req_qualifier =
|
||||||
pass1_alias_concat(request->req_alias_relation_prefix, qualifier);
|
// pass1_alias_concat(request->req_alias_relation_prefix, qualifier);
|
||||||
field = resolve_context(request, req_qualifier, context, is_check_constraint);
|
// field = resolve_context(request, qualifier, context, is_check_constraint);
|
||||||
delete req_qualifier;
|
//delete req_qualifier;
|
||||||
}
|
//}
|
||||||
else {
|
//else {
|
||||||
field = resolve_context(request, qualifier, context, is_check_constraint);
|
field = resolve_context(request, qualifier, context, is_check_constraint);
|
||||||
}
|
//}
|
||||||
// AB: When there's no relation and no procedure then we have a derived table.
|
// AB: When there's no relation and no procedure then we have a derived table.
|
||||||
const bool is_derived_table =
|
const bool is_derived_table =
|
||||||
(!context->ctx_procedure && !context->ctx_relation && context->ctx_rse);
|
(!context->ctx_procedure && !context->ctx_relation && context->ctx_rse);
|
||||||
@ -5716,15 +5734,17 @@ static dsql_nod* pass1_alias_list(dsql_req* request, dsql_nod* alias_list)
|
|||||||
|
|
||||||
// Is this context a derived table.
|
// Is this context a derived table.
|
||||||
if (!context->ctx_relation && !context->ctx_procedure && context->ctx_rse) {
|
if (!context->ctx_relation && !context->ctx_procedure && context->ctx_rse) {
|
||||||
dsql_str* tmp_qualifier = (dsql_str*) *arg;
|
//dsql_str* tmp_qualifier = (dsql_str*) *arg;
|
||||||
arg++;
|
arg++;
|
||||||
tmp_qualifier = pass1_alias_concat(tmp_qualifier, (dsql_str*) *arg);
|
//tmp_qualifier = pass1_alias_concat(tmp_qualifier, (dsql_str*) *arg);
|
||||||
|
request->req_scope_level++;
|
||||||
|
//dsql_ctx* dt_context =
|
||||||
|
// pass1_alias(request, context->ctx_childs_derived_table, tmp_qualifier);
|
||||||
|
//if (!dt_context) {
|
||||||
dsql_ctx* dt_context =
|
dsql_ctx* dt_context =
|
||||||
pass1_alias(request, context->ctx_childs_derived_table, tmp_qualifier);
|
|
||||||
if (!dt_context) {
|
|
||||||
dt_context =
|
|
||||||
pass1_alias(request, context->ctx_childs_derived_table, (dsql_str*) *arg);
|
pass1_alias(request, context->ctx_childs_derived_table, (dsql_str*) *arg);
|
||||||
}
|
//}
|
||||||
|
request->req_scope_level--;
|
||||||
|
|
||||||
if (!dt_context) {
|
if (!dt_context) {
|
||||||
// there is no alias or table named %s at this scope level.
|
// there is no alias or table named %s at this scope level.
|
||||||
@ -5821,8 +5841,8 @@ static dsql_ctx* pass1_alias(dsql_req* request, DsqlContextStack& stack, dsql_st
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check for matching alias.
|
// check for matching alias.
|
||||||
if (context->ctx_alias) {
|
if (context->ctx_internal_alias) {
|
||||||
if (!strcmp(context->ctx_alias,
|
if (!strcmp(context->ctx_internal_alias,
|
||||||
reinterpret_cast<const char*>(alias->str_data)))
|
reinterpret_cast<const char*>(alias->str_data)))
|
||||||
{
|
{
|
||||||
return context;
|
return context;
|
||||||
@ -7803,8 +7823,8 @@ static dsql_fld* resolve_context( dsql_req* request, const dsql_str* qualifier,
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
TEXT* table_name = NULL;
|
TEXT* table_name = NULL;
|
||||||
if (context->ctx_alias) {
|
if (context->ctx_internal_alias) {
|
||||||
table_name = context->ctx_alias;
|
table_name = context->ctx_internal_alias;
|
||||||
}
|
}
|
||||||
// AB: For a check constraint we should ignore the alias if the alias
|
// AB: For a check constraint we should ignore the alias if the alias
|
||||||
// contains the "NEW" alias. This is because it is possible
|
// contains the "NEW" alias. This is because it is possible
|
||||||
|
Loading…
Reference in New Issue
Block a user