8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 17:23:04 +01:00

Do the same kind of cleanup in jrd/pass1 as done for "proc_flag" in dsql/pass1 - recursive passing the same parameters that is changed in specific situations makes difficult to understand the logic.

This commit is contained in:
asfernandes 2008-05-18 01:02:35 +00:00
parent e33e2f6834
commit 4343cbfeba
3 changed files with 105 additions and 88 deletions

View File

@ -110,6 +110,32 @@ private:
void operator=(AutoPtr<Where, Clear>&); void operator=(AutoPtr<Where, Clear>&);
}; };
template <typename T>
class AutoSetRestore
{
public:
AutoSetRestore(T* aValue, T newValue)
: value(aValue),
oldValue(*aValue)
{
*value = newValue;
}
~AutoSetRestore()
{
*value = oldValue;
}
private:
// copying is prohibited
AutoSetRestore(const AutoSetRestore&);
AutoSetRestore& operator =(const AutoSetRestore&);
T* value;
T oldValue;
};
} //namespace Firebird } //namespace Firebird
#endif // CLASSES_AUTO_PTR_H #endif // CLASSES_AUTO_PTR_H

View File

@ -85,8 +85,12 @@
/* Pick up relation ids */ /* Pick up relation ids */
#include "../jrd/ini.h" #include "../jrd/ini.h"
#include "../common/classes/auto.h"
#include "../common/utils_proto.h" #include "../common/utils_proto.h"
using Firebird::AutoSetRestore;
/* Firebird provides transparent conversion from string to date in /* Firebird provides transparent conversion from string to date in
* contexts where it makes sense. This macro checks a descriptor to * contexts where it makes sense. This macro checks a descriptor to
* see if it is something that *could* represent a date value * see if it is something that *could* represent a date value
@ -127,12 +131,12 @@ static void expand_view_nodes(thread_db*, CompilerScratch*, USHORT, NodeStack&,
static void ignore_dbkey(thread_db*, CompilerScratch*, RecordSelExpr*, const jrd_rel*); static void ignore_dbkey(thread_db*, CompilerScratch*, RecordSelExpr*, const jrd_rel*);
static jrd_nod* make_defaults(thread_db*, CompilerScratch*, USHORT, jrd_nod*); static jrd_nod* make_defaults(thread_db*, CompilerScratch*, USHORT, jrd_nod*);
static jrd_nod* make_validation(thread_db*, CompilerScratch*, USHORT); static jrd_nod* make_validation(thread_db*, CompilerScratch*, USHORT);
static jrd_nod* pass1(thread_db*, CompilerScratch*, jrd_nod*, jrd_rel*, USHORT, bool); static jrd_nod* pass1(thread_db*, CompilerScratch*, jrd_nod*);
static void pass1_erase(thread_db*, CompilerScratch*, jrd_nod*); static void pass1_erase(thread_db*, CompilerScratch*, jrd_nod*);
static jrd_nod* pass1_expand_view(thread_db*, CompilerScratch*, USHORT, USHORT, bool); static jrd_nod* pass1_expand_view(thread_db*, CompilerScratch*, USHORT, USHORT, bool);
static void pass1_modify(thread_db*, CompilerScratch*, jrd_nod*); static void pass1_modify(thread_db*, CompilerScratch*, jrd_nod*);
static RecordSelExpr* pass1_rse(thread_db*, CompilerScratch*, RecordSelExpr*, jrd_rel*, USHORT); static RecordSelExpr* pass1_rse(thread_db*, CompilerScratch*, RecordSelExpr*);
static void pass1_source(thread_db*, CompilerScratch*, RecordSelExpr*, jrd_nod*, jrd_nod**, NodeStack&, jrd_rel*, USHORT); static void pass1_source(thread_db*, CompilerScratch*, RecordSelExpr*, jrd_nod*, jrd_nod**, NodeStack&);
static bool pass1_store(thread_db*, CompilerScratch*, jrd_nod*); static bool pass1_store(thread_db*, CompilerScratch*, jrd_nod*);
static jrd_nod* pass1_update(thread_db*, CompilerScratch*, jrd_rel*, const trig_vec*, USHORT, USHORT, static jrd_nod* pass1_update(thread_db*, CompilerScratch*, jrd_rel*, const trig_vec*, USHORT, USHORT,
SecurityClass::flags_t, jrd_rel*, USHORT); SecurityClass::flags_t, jrd_rel*, USHORT);
@ -2005,7 +2009,7 @@ jrd_req* CMP_make_request(thread_db* tdbb, CompilerScratch* csb, bool internal_f
// optimizations can be performed here. // optimizations can be performed here.
DEBUG; DEBUG;
csb->csb_node = pass1(tdbb, csb, csb->csb_node, 0, 0, false); csb->csb_node = pass1(tdbb, csb, csb->csb_node);
// Copy and compile (pass1) domains DEFAULT and constraints. // Copy and compile (pass1) domains DEFAULT and constraints.
bool found = csb->csb_map_field_info.getFirst(); bool found = csb->csb_map_field_info.getFirst();
@ -2019,8 +2023,8 @@ jrd_req* CMP_make_request(thread_db* tdbb, CompilerScratch* csb, bool internal_f
fieldInfo.validation = fieldInfo.validation =
copy(tdbb, csb, fieldInfo.validation, local_map, 0, NULL, false); copy(tdbb, csb, fieldInfo.validation, local_map, 0, NULL, false);
fieldInfo.defaultValue = pass1(tdbb, csb, fieldInfo.defaultValue, 0, 0, false); fieldInfo.defaultValue = pass1(tdbb, csb, fieldInfo.defaultValue);
fieldInfo.validation = pass1(tdbb, csb, fieldInfo.validation, 0, 0, false); fieldInfo.validation = pass1(tdbb, csb, fieldInfo.validation);
found = csb->csb_map_field_info.getNext(); found = csb->csb_map_field_info.getNext();
} }
@ -3260,10 +3264,7 @@ static jrd_nod* make_validation(thread_db* tdbb, CompilerScratch* csb, USHORT st
static jrd_nod* pass1(thread_db* tdbb, static jrd_nod* pass1(thread_db* tdbb,
CompilerScratch* csb, CompilerScratch* csb,
jrd_nod* node, jrd_nod* node)
jrd_rel* view,
USHORT view_stream,
bool validate_expr)
{ {
/************************************** /**************************************
* *
@ -3275,12 +3276,12 @@ static jrd_nod* pass1(thread_db* tdbb,
* Merge missing values, computed values, validation expressions, * Merge missing values, computed values, validation expressions,
* and views into a parsed request. * and views into a parsed request.
* *
* The argument validate_expr is true if an ancestor of the * The csb->csb_validate_expr becomes true if an ancestor of the
* current node (the one being passed in) in the parse tree has nod_type * current node (the one being passed in) in the parse tree has nod_type
* == nod_validate. "ancestor" does not include the current node * == nod_validate. "ancestor" does not include the current node
* being passed in as an argument. * being passed in as an argument.
* If we are in a "validate subtree" (as determined by the * If we are in a "validate subtree" (as determined by the
* validate_expr), we must not post update access to the fields involved * csb->csb_validate_expr), we must not post update access to the fields involved
* in the validation clause. (see the call for CMP_post_access in this * in the validation clause. (see the call for CMP_post_access in this
* function.) * function.)
* *
@ -3300,7 +3301,10 @@ static jrd_nod* pass1(thread_db* tdbb,
if (!node) if (!node)
return node; return node;
validate_expr = validate_expr || (node->nod_type == nod_validate); AutoSetRestore<bool> autoValidateExpr(&csb->csb_validate_expr,
csb->csb_validate_expr || node->nod_type == nod_validate);
jrd_rel* const view = csb->csb_view;
// if there is processing to be done before sub expressions, do it here // if there is processing to be done before sub expressions, do it here
@ -3308,15 +3312,15 @@ static jrd_nod* pass1(thread_db* tdbb,
case nod_like: case nod_like:
case nod_similar: case nod_similar:
ptr = node->nod_arg; ptr = node->nod_arg;
ptr[0] = pass1(tdbb, csb, ptr[0], view, view_stream, validate_expr); ptr[0] = pass1(tdbb, csb, ptr[0]);
// We need to take care of invariantness of like/similar pattern expression to be // We need to take care of invariantness of like/similar pattern expression to be
// able to pre-compile its pattern // able to pre-compile its pattern
node->nod_flags |= nod_invariant; node->nod_flags |= nod_invariant;
csb->csb_current_nodes.push(node); csb->csb_current_nodes.push(node);
ptr[1] = pass1(tdbb, csb, ptr[1], view, view_stream, validate_expr); ptr[1] = pass1(tdbb, csb, ptr[1]);
if (node->nod_count == 3) { if (node->nod_count == 3) {
// escape symbol also needs to be taken care of // escape symbol also needs to be taken care of
ptr[2] = pass1(tdbb, csb, ptr[2], view, view_stream, validate_expr); ptr[2] = pass1(tdbb, csb, ptr[2]);
} }
csb->csb_current_nodes.pop(); csb->csb_current_nodes.pop();
@ -3343,12 +3347,12 @@ static jrd_nod* pass1(thread_db* tdbb,
case nod_contains: case nod_contains:
case nod_starts: case nod_starts:
ptr = node->nod_arg; ptr = node->nod_arg;
ptr[0] = pass1(tdbb, csb, ptr[0], view, view_stream, validate_expr); ptr[0] = pass1(tdbb, csb, ptr[0]);
// We need to take care of invariantness of contains and starts // We need to take care of invariantness of contains and starts
// expression to be able to pre-compile it for searching // expression to be able to pre-compile it for searching
node->nod_flags |= nod_invariant; node->nod_flags |= nod_invariant;
csb->csb_current_nodes.push(node); csb->csb_current_nodes.push(node);
ptr[1] = pass1(tdbb, csb, ptr[1], view, view_stream, validate_expr); ptr[1] = pass1(tdbb, csb, ptr[1]);
csb->csb_current_nodes.pop(); csb->csb_current_nodes.pop();
// If there is no top-level RSE present and patterns are not constant, // If there is no top-level RSE present and patterns are not constant,
@ -3480,7 +3484,7 @@ static jrd_nod* pass1(thread_db* tdbb,
// clause only, the subtree is a validate_subtree in our notation. // clause only, the subtree is a validate_subtree in our notation.
if (tail->csb_flags & csb_modify) { if (tail->csb_flags & csb_modify) {
if (!validate_expr) { if (!csb->csb_validate_expr) {
CMP_post_access(tdbb, csb, relation->rel_security_name, CMP_post_access(tdbb, csb, relation->rel_security_name,
(tail->csb_view) ? tail->csb_view->rel_id : (tail->csb_view) ? tail->csb_view->rel_id :
(view ? view->rel_id : 0), (view ? view->rel_id : 0),
@ -3566,11 +3570,13 @@ static jrd_nod* pass1(thread_db* tdbb,
// dimitr: if we reference view columns, we need to pass them // dimitr: if we reference view columns, we need to pass them
// as belonging to a view (in order to compute the access // as belonging to a view (in order to compute the access
// permissions properly). // permissions properly).
view = relation; AutoSetRestore<jrd_rel*> autoView(&csb->csb_view, relation);
view_stream = stream; AutoSetRestore<USHORT> autoViewStream(&csb->csb_view_stream, stream);
}
return pass1(tdbb, csb, sub, view, view_stream, validate_expr); return pass1(tdbb, csb, sub); // note: scope of AutoSetRestore
}
else
return pass1(tdbb, csb, sub);
} }
case nod_assignment: case nod_assignment:
@ -3628,16 +3634,14 @@ static jrd_nod* pass1(thread_db* tdbb,
break; break;
case nod_rse: case nod_rse:
return (jrd_nod*) pass1_rse(tdbb, csb, (RecordSelExpr*) node, view, view_stream); return (jrd_nod*) pass1_rse(tdbb, csb, (RecordSelExpr*) node);
case nod_cursor_stmt: case nod_cursor_stmt:
if ((UCHAR) (IPTR) node->nod_arg[e_cursor_stmt_op] == blr_cursor_fetch) { if ((UCHAR) (IPTR) node->nod_arg[e_cursor_stmt_op] == blr_cursor_fetch) {
node->nod_arg[e_cursor_stmt_seek] = node->nod_arg[e_cursor_stmt_seek] =
pass1(tdbb, csb, node->nod_arg[e_cursor_stmt_seek], view, view_stream, pass1(tdbb, csb, node->nod_arg[e_cursor_stmt_seek]);
validate_expr);
node->nod_arg[e_cursor_stmt_into] = node->nod_arg[e_cursor_stmt_into] =
pass1(tdbb, csb, node->nod_arg[e_cursor_stmt_into], view, view_stream, pass1(tdbb, csb, node->nod_arg[e_cursor_stmt_into]);
validate_expr);
} }
break; break;
@ -3656,22 +3660,14 @@ static jrd_nod* pass1(thread_db* tdbb,
csb->csb_rpt[(USHORT)(IPTR) node->nod_arg[e_agg_stream]].csb_flags |= csb->csb_rpt[(USHORT)(IPTR) node->nod_arg[e_agg_stream]].csb_flags |=
csb_no_dbkey; csb_no_dbkey;
ignore_dbkey(tdbb, csb, (RecordSelExpr*) node->nod_arg[e_agg_rse], view); ignore_dbkey(tdbb, csb, (RecordSelExpr*) node->nod_arg[e_agg_rse], view);
node->nod_arg[e_agg_rse] = node->nod_arg[e_agg_rse] = pass1(tdbb, csb, node->nod_arg[e_agg_rse]);
pass1(tdbb, csb, node->nod_arg[e_agg_rse], view, view_stream, node->nod_arg[e_agg_map] = pass1(tdbb, csb, node->nod_arg[e_agg_map]);
validate_expr); node->nod_arg[e_agg_group] = pass1(tdbb, csb, node->nod_arg[e_agg_group]);
node->nod_arg[e_agg_map] =
pass1(tdbb, csb, node->nod_arg[e_agg_map], view, view_stream,
validate_expr);
node->nod_arg[e_agg_group] =
pass1(tdbb, csb, node->nod_arg[e_agg_group], view, view_stream,
validate_expr);
break; break;
case nod_gen_id: case nod_gen_id:
case nod_gen_id2: case nod_gen_id2:
node->nod_arg[e_gen_value] = node->nod_arg[e_gen_value] = pass1(tdbb, csb, node->nod_arg[e_gen_value]);
pass1(tdbb, csb, node->nod_arg[e_gen_value], view, view_stream,
validate_expr);
return node; return node;
case nod_rec_version: case nod_rec_version:
@ -3787,8 +3783,7 @@ static jrd_nod* pass1(thread_db* tdbb,
} }
case nod_abort: case nod_abort:
pass1(tdbb, csb, node->nod_arg[e_xcp_msg], view, view_stream, pass1(tdbb, csb, node->nod_arg[e_xcp_msg]);
validate_expr);
break; break;
case nod_not: case nod_not:
@ -3828,8 +3823,7 @@ static jrd_nod* pass1(thread_db* tdbb,
break; break;
case nod_src_info: case nod_src_info:
node->nod_arg[e_src_info_node] = node->nod_arg[e_src_info_node] = pass1(tdbb, csb, node->nod_arg[e_src_info_node]);
pass1(tdbb, csb, node->nod_arg[e_src_info_node], view, view_stream, validate_expr);
return node; return node;
default: default:
@ -3842,7 +3836,7 @@ static jrd_nod* pass1(thread_db* tdbb,
ptr = node->nod_arg; ptr = node->nod_arg;
for (const jrd_nod* const* const end = ptr + node->nod_count; ptr < end; ptr++) { for (const jrd_nod* const* const end = ptr + node->nod_count; ptr < end; ptr++) {
*ptr = pass1(tdbb, csb, *ptr, view, view_stream, validate_expr); *ptr = pass1(tdbb, csb, *ptr);
} }
// perform any post-processing here // perform any post-processing here
@ -4218,9 +4212,7 @@ static void pass1_modify(thread_db* tdbb, CompilerScratch* csb, jrd_nod* node)
static RecordSelExpr* pass1_rse(thread_db* tdbb, static RecordSelExpr* pass1_rse(thread_db* tdbb,
CompilerScratch* csb, CompilerScratch* csb,
RecordSelExpr* rse, RecordSelExpr* rse)
jrd_rel* view,
USHORT view_stream)
{ {
/************************************** /**************************************
* *
@ -4276,8 +4268,7 @@ static RecordSelExpr* pass1_rse(thread_db* tdbb,
for (const jrd_nod* const* const end = arg + rse->rse_count; for (const jrd_nod* const* const end = arg + rse->rse_count;
arg < end; arg++) arg < end; arg++)
{ {
pass1_source(tdbb, csb, rse, *arg, &boolean, stack, view, pass1_source(tdbb, csb, rse, *arg, &boolean, stack);
view_stream);
} }
// Now, rebuild the RecordSelExpr block. If possible, re-use the old block, // Now, rebuild the RecordSelExpr block. If possible, re-use the old block,
@ -4307,13 +4298,15 @@ static RecordSelExpr* pass1_rse(thread_db* tdbb,
*--arg = stack.pop(); *--arg = stack.pop();
} }
AutoSetRestore<bool> autoValidateExpr(&csb->csb_validate_expr, false);
// finish of by processing other clauses // finish of by processing other clauses
if (first) { if (first) {
rse->rse_first = pass1(tdbb, csb, first, view, view_stream, false); rse->rse_first = pass1(tdbb, csb, first);
} }
if (skip) { if (skip) {
rse->rse_skip = pass1(tdbb, csb, skip, view, view_stream, false); rse->rse_skip = pass1(tdbb, csb, skip);
} }
if (boolean) { if (boolean) {
@ -4321,27 +4314,21 @@ static RecordSelExpr* pass1_rse(thread_db* tdbb,
jrd_nod* additional = PAR_make_node(tdbb, 2); jrd_nod* additional = PAR_make_node(tdbb, 2);
additional->nod_type = nod_and; additional->nod_type = nod_and;
additional->nod_arg[0] = boolean; additional->nod_arg[0] = boolean;
additional->nod_arg[1] = additional->nod_arg[1] = pass1(tdbb, csb, rse->rse_boolean);
pass1(tdbb, csb, rse->rse_boolean, view, view_stream, false);
rse->rse_boolean = additional; rse->rse_boolean = additional;
} }
else { else {
rse->rse_boolean = boolean; rse->rse_boolean = boolean;
} }
} }
else { else
rse->rse_boolean = rse->rse_boolean = pass1(tdbb, csb, rse->rse_boolean);
pass1(tdbb, csb, rse->rse_boolean, view, view_stream, false);
}
if (sort) { if (sort)
rse->rse_sorted = pass1(tdbb, csb, sort, view, view_stream, false); rse->rse_sorted = pass1(tdbb, csb, sort);
}
if (project) { if (project)
rse->rse_projection = rse->rse_projection = pass1(tdbb, csb, project);
pass1(tdbb, csb, project, view, view_stream, false);
}
if (plan) { if (plan) {
rse->rse_plan = plan; rse->rse_plan = plan;
@ -4351,8 +4338,7 @@ static RecordSelExpr* pass1_rse(thread_db* tdbb,
#ifdef SCROLLABLE_CURSORS #ifdef SCROLLABLE_CURSORS
if (async_message) { if (async_message) {
rse->rse_async_message = rse->rse_async_message = pass1(tdbb, csb, async_message);
pass1(tdbb, csb, async_message, view, view_stream, false);
csb->csb_async_message = rse->rse_async_message; csb->csb_async_message = rse->rse_async_message;
} }
#endif #endif
@ -4370,9 +4356,7 @@ static void pass1_source(thread_db* tdbb,
RecordSelExpr* rse, RecordSelExpr* rse,
jrd_nod* source, jrd_nod* source,
jrd_nod** boolean, jrd_nod** boolean,
NodeStack& stack, NodeStack& stack)
jrd_rel* parent_view,
USHORT view_stream)
{ {
/************************************** /**************************************
* *
@ -4396,6 +4380,8 @@ static void pass1_source(thread_db* tdbb,
Database* dbb = tdbb->getDatabase(); Database* dbb = tdbb->getDatabase();
CHECK_DBB(dbb); CHECK_DBB(dbb);
AutoSetRestore<bool> autoValidateExpr(&csb->csb_validate_expr, false);
// in the case of an RecordSelExpr, it is possible that a new RecordSelExpr will be generated, // in the case of an RecordSelExpr, it is possible that a new RecordSelExpr will be generated,
// so wait to process the source before we push it on the stack (bug 8039) // so wait to process the source before we push it on the stack (bug 8039)
@ -4416,15 +4402,14 @@ static void pass1_source(thread_db* tdbb,
for (const jrd_nod* const* const end = arg + sub_rse->rse_count; for (const jrd_nod* const* const end = arg + sub_rse->rse_count;
arg < end; arg++) arg < end; arg++)
{ {
pass1_source(tdbb, csb, rse, *arg, boolean, stack, pass1_source(tdbb, csb, rse, *arg, boolean, stack);
parent_view, view_stream);
} }
// fold in the boolean for this inner join with the one for the parent // fold in the boolean for this inner join with the one for the parent
if (sub_rse->rse_boolean) { if (sub_rse->rse_boolean) {
jrd_nod* node =
pass1(tdbb, csb, sub_rse->rse_boolean, parent_view, jrd_nod* node = pass1(tdbb, csb, sub_rse->rse_boolean);
view_stream, false);
if (*boolean) { if (*boolean) {
jrd_nod* additional = PAR_make_node(tdbb, 2); jrd_nod* additional = PAR_make_node(tdbb, 2);
additional->nod_type = nod_and; additional->nod_type = nod_and;
@ -4440,7 +4425,7 @@ static void pass1_source(thread_db* tdbb,
return; return;
} }
source = pass1(tdbb, csb, source, parent_view, view_stream, false); source = pass1(tdbb, csb, source);
stack.push(source); stack.push(source);
return; return;
} }
@ -4452,7 +4437,7 @@ static void pass1_source(thread_db* tdbb,
// special case: procedure // special case: procedure
if (source->nod_type == nod_procedure) { if (source->nod_type == nod_procedure) {
pass1(tdbb, csb, source, parent_view, view_stream, false); pass1(tdbb, csb, source);
jrd_prc* procedure = MET_lookup_procedure_id(tdbb, jrd_prc* procedure = MET_lookup_procedure_id(tdbb,
(SSHORT)(IPTR) source->nod_arg[e_prc_procedure], false, false, 0); (SSHORT)(IPTR) source->nod_arg[e_prc_procedure], false, false, 0);
post_procedure_access(tdbb, csb, procedure); post_procedure_access(tdbb, csb, procedure);
@ -4464,8 +4449,7 @@ static void pass1_source(thread_db* tdbb,
// special case: union // special case: union
if (source->nod_type == nod_union) { if (source->nod_type == nod_union) {
pass1(tdbb, csb, source->nod_arg[e_uni_clauses], parent_view, pass1(tdbb, csb, source->nod_arg[e_uni_clauses]);
view_stream, false);
return; return;
} }
@ -4473,7 +4457,7 @@ static void pass1_source(thread_db* tdbb,
if (source->nod_type == nod_aggregate) { if (source->nod_type == nod_aggregate) {
fb_assert((int) (IPTR) source->nod_arg[e_agg_stream] <= MAX_STREAMS); fb_assert((int) (IPTR) source->nod_arg[e_agg_stream] <= MAX_STREAMS);
pass1(tdbb, csb, source, parent_view, view_stream, false); pass1(tdbb, csb, source);
return; return;
} }
@ -4481,6 +4465,9 @@ static void pass1_source(thread_db* tdbb,
// prepare to check protection of relation when a field in the stream of the // prepare to check protection of relation when a field in the stream of the
// relation is accessed. // relation is accessed.
jrd_rel* const parent_view = csb->csb_view;
const USHORT view_stream = csb->csb_view_stream;
jrd_rel* view = (jrd_rel*) source->nod_arg[e_rel_relation]; jrd_rel* view = (jrd_rel*) source->nod_arg[e_rel_relation];
CMP_post_resource(&csb->csb_resources, view, Resource::rsc_relation, CMP_post_resource(&csb->csb_resources, view, Resource::rsc_relation,
view->rel_id); view->rel_id);
@ -4517,6 +4504,9 @@ static void pass1_source(thread_db* tdbb,
stack.pop(); stack.pop();
UCHAR* map = alloc_map(tdbb, csb, stream); UCHAR* map = alloc_map(tdbb, csb, stream);
AutoSetRestore<jrd_rel*> autoView(&csb->csb_view, view);
AutoSetRestore<USHORT> autoViewStream(&csb->csb_view_stream, stream);
// We don't expand the view in two cases: // We don't expand the view in two cases:
// 1) If the view has a projection, sort, first/skip or explicit plan. // 1) If the view has a projection, sort, first/skip or explicit plan.
// 2) If it's part of an outer join. // 2) If it's part of an outer join.
@ -4528,7 +4518,7 @@ static void pass1_source(thread_db* tdbb,
{ {
jrd_nod* node = copy(tdbb, csb, (jrd_nod*) view_rse, map, 0, NULL, false); jrd_nod* node = copy(tdbb, csb, (jrd_nod*) view_rse, map, 0, NULL, false);
DEBUG; DEBUG;
stack.push(pass1(tdbb, csb, node, view, stream, false)); stack.push(pass1(tdbb, csb, node));
DEBUG; DEBUG;
return; return;
} }
@ -4556,7 +4546,7 @@ static void pass1_source(thread_db* tdbb,
// Now go out and process the base table itself. This table might also be a view, // Now go out and process the base table itself. This table might also be a view,
// in which case we will continue the process by recursion. // in which case we will continue the process by recursion.
pass1_source(tdbb, csb, rse, node, boolean, stack, view, stream); pass1_source(tdbb, csb, rse, node, boolean, stack);
} }
// When there is a projection in the view, copy the projection up to the query RecordSelExpr. // When there is a projection in the view, copy the projection up to the query RecordSelExpr.
@ -4569,9 +4559,7 @@ static void pass1_source(thread_db* tdbb,
if (view_rse->rse_projection) { if (view_rse->rse_projection) {
rse->rse_projection = rse->rse_projection =
pass1(tdbb, csb, pass1(tdbb, csb, copy(tdbb, csb, view_rse->rse_projection, map, 0, NULL, false));
copy(tdbb, csb, view_rse->rse_projection, map, 0, NULL, false),
view, stream, false);
} }
// if we encounter a boolean, copy it and retain it by ANDing it in with the // if we encounter a boolean, copy it and retain it by ANDing it in with the
@ -4579,9 +4567,7 @@ static void pass1_source(thread_db* tdbb,
if (view_rse->rse_boolean) { if (view_rse->rse_boolean) {
jrd_nod* node = jrd_nod* node =
pass1(tdbb, csb, pass1(tdbb, csb, copy(tdbb, csb, view_rse->rse_boolean, map, 0, NULL, false));
copy(tdbb, csb, view_rse->rse_boolean, map, 0, NULL, false),
view, stream, false);
if (*boolean) { if (*boolean) {
// The order of the nodes here is important! The // The order of the nodes here is important! The
// boolean from the view must appear first so that // boolean from the view must appear first so that

View File

@ -865,6 +865,11 @@ public:
MapItemInfo csb_map_item_info; // Map item to item info MapItemInfo csb_map_item_info; // Map item to item info
Firebird::MetaName csb_domain_validation; // Parsing domain constraint in PSQL Firebird::MetaName csb_domain_validation; // Parsing domain constraint in PSQL
// used in cmp.cpp/pass1
jrd_rel* csb_view;
USHORT csb_view_stream;
bool csb_validate_expr;
struct csb_repeat struct csb_repeat
{ {
// We must zero-initialize this one // We must zero-initialize this one