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

Refactor nod_rse, nod_relation, nod_procedure, nod_union, nod_aggregate and nod_window.

This commit is contained in:
asfernandes 2010-08-24 03:25:01 +00:00
parent 77fa416d04
commit 48d83b8fef
36 changed files with 3454 additions and 3177 deletions

View File

@ -42,7 +42,7 @@ JRD_ServerFiles= blob_filter.cpp cvt.cpp dpm.epp dyn.epp dyn_def.epp \
svc.cpp SysFunction.cpp TempSpace.cpp tpc.cpp tra.cpp validation.cpp \
ValueImpl.cpp ValuesImpl.cpp vio.cpp \
nodebug.cpp nbak.cpp $(Physical_IO_Module) TextType.cpp \
unicode_util.cpp RuntimeStatistics.cpp DebugInterface.cpp \
unicode_util.cpp RecordSourceNodes.cpp RuntimeStatistics.cpp DebugInterface.cpp \
extds/ExtDS.cpp extds/InternalDS.cpp extds/IscDS.cpp \
trace/TraceConfigStorage.cpp trace/TraceLog.cpp \
trace/TraceManager.cpp trace/TraceObjects.cpp \

View File

@ -221,6 +221,7 @@
<ClCompile Include="..\..\..\src\jrd\PreparedStatement.cpp" />
<ClCompile Include="..\..\..\src\jrd\RandomGenerator.cpp" />
<ClCompile Include="..\..\..\src\jrd\RecordBuffer.cpp" />
<ClCompile Include="..\..\..\src\jrd\RecordSourceNodes.cpp" />
<ClCompile Include="..\..\..\src\jrd\Relation.cpp" />
<ClCompile Include="..\..\..\src\jrd\ResultSet.cpp" />
<ClCompile Include="..\..\..\src\jrd\rlck.cpp" />
@ -427,6 +428,7 @@
<ClInclude Include="..\..\..\src\jrd\que.h" />
<ClInclude Include="..\..\..\src\jrd\RandomGenerator.h" />
<ClInclude Include="..\..\..\src\jrd\RecordBuffer.h" />
<ClInclude Include="..\..\..\src\jrd\RecordSourceNodes.h" />
<ClInclude Include="..\..\..\src\jrd\recsrc\RecordSource.h" />
<ClInclude Include="..\..\..\src\jrd\Relation.h" />
<ClInclude Include="..\..\..\src\jrd\relations.h" />

View File

@ -240,6 +240,9 @@
<ClCompile Include="..\..\..\src\jrd\RecordBuffer.cpp">
<Filter>JRD files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jrd\RecordSourceNodes.cpp">
<Filter>JRD files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jrd\Relation.cpp">
<Filter>JRD files</Filter>
</ClCompile>
@ -854,6 +857,9 @@
<ClInclude Include="..\..\..\src\jrd\RecordBuffer.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\jrd\RecordSourceNodes.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\jrd\recsrc\RecordSource.h">
<Filter>Header files</Filter>
</ClInclude>

View File

@ -221,6 +221,7 @@
<ClCompile Include="..\..\..\src\jrd\PreparedStatement.cpp" />
<ClCompile Include="..\..\..\src\jrd\RandomGenerator.cpp" />
<ClCompile Include="..\..\..\src\jrd\RecordBuffer.cpp" />
<ClCompile Include="..\..\..\src\jrd\RecordSourceNodes.cpp" />
<ClCompile Include="..\..\..\src\jrd\Relation.cpp" />
<ClCompile Include="..\..\..\src\jrd\ResultSet.cpp" />
<ClCompile Include="..\..\..\src\jrd\rlck.cpp" />
@ -427,6 +428,7 @@
<ClInclude Include="..\..\..\src\jrd\que.h" />
<ClInclude Include="..\..\..\src\jrd\RandomGenerator.h" />
<ClInclude Include="..\..\..\src\jrd\RecordBuffer.h" />
<ClInclude Include="..\..\..\src\jrd\RecordSourceNodes.h" />
<ClInclude Include="..\..\..\src\jrd\recsrc\RecordSource.h" />
<ClInclude Include="..\..\..\src\jrd\Relation.h" />
<ClInclude Include="..\..\..\src\jrd\relations.h" />

View File

@ -240,6 +240,9 @@
<ClCompile Include="..\..\..\src\jrd\RecordBuffer.cpp">
<Filter>JRD files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jrd\RecordSourceNodes.cpp">
<Filter>JRD files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jrd\Relation.cpp">
<Filter>JRD files</Filter>
</ClCompile>
@ -854,6 +857,9 @@
<ClInclude Include="..\..\..\src\jrd\RecordBuffer.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\jrd\RecordSourceNodes.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\jrd\recsrc\RecordSource.h">
<Filter>Header files</Filter>
</ClInclude>

View File

@ -221,6 +221,7 @@
<ClCompile Include="..\..\..\src\jrd\PreparedStatement.cpp" />
<ClCompile Include="..\..\..\src\jrd\RandomGenerator.cpp" />
<ClCompile Include="..\..\..\src\jrd\RecordBuffer.cpp" />
<ClCompile Include="..\..\..\src\jrd\RecordSourceNodes.cpp" />
<ClCompile Include="..\..\..\src\jrd\Relation.cpp" />
<ClCompile Include="..\..\..\src\jrd\ResultSet.cpp" />
<ClCompile Include="..\..\..\src\jrd\rlck.cpp" />
@ -427,6 +428,7 @@
<ClInclude Include="..\..\..\src\jrd\que.h" />
<ClInclude Include="..\..\..\src\jrd\RandomGenerator.h" />
<ClInclude Include="..\..\..\src\jrd\RecordBuffer.h" />
<ClInclude Include="..\..\..\src\jrd\RecordSourceNodes.h" />
<ClInclude Include="..\..\..\src\jrd\recsrc\RecordSource.h" />
<ClInclude Include="..\..\..\src\jrd\Relation.h" />
<ClInclude Include="..\..\..\src\jrd\relations.h" />

View File

@ -240,6 +240,9 @@
<ClCompile Include="..\..\..\src\jrd\RecordBuffer.cpp">
<Filter>JRD files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jrd\RecordSourceNodes.cpp">
<Filter>JRD files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jrd\Relation.cpp">
<Filter>JRD files</Filter>
</ClCompile>
@ -857,6 +860,9 @@
<ClInclude Include="..\..\..\src\jrd\recsrc\RecordSource.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\jrd\RecordSourceNodes.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\jrd\Relation.h">
<Filter>Header files</Filter>
</ClInclude>

View File

@ -571,6 +571,10 @@
RelativePath="..\..\..\src\jrd\RecordBuffer.cpp"
>
</File>
<File
RelativePath="..\..\..\src\jrd\RecordSourceNodes.cpp"
>
</File>
<File
RelativePath="..\..\..\src\jrd\Relation.cpp"
>
@ -1391,6 +1395,10 @@
RelativePath="..\..\..\src\jrd\RecordBuffer.h"
>
</File>
<File
RelativePath="..\..\..\src\jrd\RecordSourceNodes.h"
>
</File>
<File
RelativePath="..\..\..\src\jrd\recsrc\RecordSource.h"
>

View File

@ -571,6 +571,10 @@
RelativePath="..\..\..\src\jrd\RecordBuffer.cpp"
>
</File>
<File
RelativePath="..\..\..\src\jrd\RecordSourceNodes.cpp"
>
</File>
<File
RelativePath="..\..\..\src\jrd\Relation.cpp"
>
@ -1391,6 +1395,10 @@
RelativePath="..\..\..\src\jrd\RecordBuffer.h"
>
</File>
<File
RelativePath="..\..\..\src\jrd\RecordSourceNodes.h"
>
</File>
<File
RelativePath="..\..\..\src\jrd\recsrc\RecordSource.h"
>

View File

@ -571,6 +571,10 @@
RelativePath="..\..\..\src\jrd\RecordBuffer.cpp"
>
</File>
<File
RelativePath="..\..\..\src\jrd\RecordSourceNodes.cpp"
>
</File>
<File
RelativePath="..\..\..\src\jrd\Relation.cpp"
>
@ -1391,6 +1395,10 @@
RelativePath="..\..\..\src\jrd\RecordBuffer.h"
>
</File>
<File
RelativePath="..\..\..\src\jrd\RecordSourceNodes.h"
>
</File>
<File
RelativePath="..\..\..\src\jrd\recsrc\RecordSource.h"
>

View File

@ -709,7 +709,7 @@ ExprNode* SubstringSimilarNode::pass1(thread_db* tdbb, CompilerScratch* csb)
// We need to take care of invariantness expressions to be able to pre-compile the pattern.
node->nod_flags |= nod_invariant;
csb->csb_current_nodes.push(node);
csb->csb_current_nodes.push(node.getObject());
pattern = CMP_pass1(tdbb, csb, pattern);
escape = CMP_pass1(tdbb, csb, escape);
@ -721,11 +721,11 @@ ExprNode* SubstringSimilarNode::pass1(thread_db* tdbb, CompilerScratch* csb)
if ((node->nod_flags & nod_invariant) &&
(pattern->nod_type != nod_literal || escape->nod_type != nod_literal))
{
const jrd_node_base* const* ctx_node, *const *end;
const LegacyNodeOrRseNode* ctx_node, *end;
for (ctx_node = csb->csb_current_nodes.begin(), end = csb->csb_current_nodes.end();
ctx_node < end; ctx_node++)
ctx_node != end; ++ctx_node)
{
if ((*ctx_node)->nod_type == nod_rse)
if (ctx_node->rseNode)
break;
}

View File

@ -38,7 +38,7 @@ class Cursor;
class dsql_nod;
class ExprNode;
class jrd_nod;
class RecordSelExpr;
class RseNode;
class SlidingWindow;
class TypeClause;
@ -550,7 +550,7 @@ public:
}
public:
virtual void pass2Cursor(RecordSelExpr*& /*rsePtr*/, Cursor**& /*cursorPtr*/)
virtual void pass2Cursor(RseNode*& /*rsePtr*/, Cursor**& /*cursorPtr*/)
{
}

View File

@ -26,6 +26,7 @@
#include "../dsql/node.h"
#include "../jrd/blr.h"
#include "../jrd/tra.h"
#include "../jrd/RecordSourceNodes.h"
#include "../jrd/recsrc/Cursor.h"
#include "../jrd/cmp_proto.h"
#include "../jrd/dfw_proto.h"
@ -1291,10 +1292,10 @@ DmlNode* ForNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb,
csb->csb_blr_reader.peekByte() == (UCHAR) blr_singular ||
csb->csb_blr_reader.peekByte() == (UCHAR) blr_scrollable)
{
node->rse = PAR_parse_node(tdbb, csb, TYPE_RSE);
node->rse = RseNode::getFrom(PAR_parse_node(tdbb, csb, TYPE_RSE));
}
else
node->rse = PAR_rse(tdbb, csb, blrOp);
node->rse = RseNode::getFrom(PAR_rse(tdbb, csb, blrOp));
node->statement = PAR_parse_node(tdbb, csb, STATEMENT);
@ -1414,7 +1415,7 @@ void ForNode::genBlr()
StmtNode* ForNode::pass1(thread_db* tdbb, CompilerScratch* csb)
{
stall = CMP_pass1(tdbb, csb, stall);
rse = CMP_pass1(tdbb, csb, rse);
rse->pass1(tdbb, csb, csb->csb_view);
statement = CMP_pass1(tdbb, csb, statement);
return this;
}
@ -1422,7 +1423,7 @@ StmtNode* ForNode::pass1(thread_db* tdbb, CompilerScratch* csb)
StmtNode* ForNode::pass2(thread_db* tdbb, CompilerScratch* csb)
{
stall = CMP_pass2(tdbb, csb, stall, node);
rse = CMP_pass2(tdbb, csb, rse, node);
rse->pass2(tdbb, csb);
statement = CMP_pass2(tdbb, csb, statement, node);
return this;
}

View File

@ -220,9 +220,9 @@ public:
virtual StmtNode* pass1(thread_db* tdbb, CompilerScratch* csb);
virtual StmtNode* pass2(thread_db* tdbb, CompilerScratch* csb);
virtual void pass2Cursor(RecordSelExpr*& rsePtr, Cursor**& cursorPtr)
virtual void pass2Cursor(RseNode*& rsePtr, Cursor**& cursorPtr)
{
rsePtr = reinterpret_cast<RecordSelExpr*>(static_cast<jrd_nod*>(rse));
rsePtr = rse;
cursorPtr = cursor.getAddress();
}
@ -236,7 +236,7 @@ public:
dsql_nod* dsqlLabel;
bool dsqlForceSingular;
NestConst<jrd_nod> stall;
NestConst<jrd_nod> rse;
NestConst<RseNode> rse;
NestConst<jrd_nod> statement;
NestConst<Cursor> cursor;
};

View File

@ -427,7 +427,7 @@ protected:
virtual USHORT getFieldId(jrd_nod* input);
protected:
public:
CompilerScratch* csb;
UCHAR* remap;
jrd_nod* message;

View File

@ -65,7 +65,6 @@ namespace Jrd
class IndexLock;
class ArrayField;
struct sort_context;
class RecordSelExpr;
class vcl;
class TextType;
class Parameter;

View File

@ -36,6 +36,7 @@
#include "../jrd/rse.h"
#include "../jrd/ods.h"
#include "../jrd/Optimizer.h"
#include "../jrd/RecordSourceNodes.h"
#include "../jrd/recsrc/RecordSource.h"
#include "../dsql/ExprNodes.h"
#include "../dsql/StmtNodes.h"
@ -89,43 +90,16 @@ bool OPT_computable(CompilerScratch* csb, jrd_nod* node, SSHORT stream,
DEV_BLKCHK(csb, type_csb);
DEV_BLKCHK(node, type_nod);
if (node->nod_flags & nod_deoptimize) {
if (node->nod_flags & nod_deoptimize)
return false;
}
// Recurse thru interesting sub-nodes
switch (node->nod_type)
{
case nod_procedure:
{
jrd_nod* inputs = node->nod_arg[e_prc_inputs];
if (inputs)
{
fb_assert(inputs->nod_type == nod_asn_list);
jrd_nod* const* ptr = inputs->nod_arg;
for (const jrd_nod* const* const end = ptr + inputs->nod_count; ptr < end; ptr++)
{
if (!OPT_computable(csb, *ptr, stream, idx_use, allowOnlyCurrentStream)) {
return false;
}
}
}
break;
}
case nod_union:
{
jrd_nod* clauses = node->nod_arg[e_uni_clauses];
jrd_nod* const* ptr = clauses->nod_arg;
for (const jrd_nod* const* const end = ptr + clauses->nod_count; ptr < end; ptr += 2)
{
if (!OPT_computable(csb, *ptr, stream, idx_use, allowOnlyCurrentStream)) {
return false;
}
}
break;
}
case nod_class_recsrcnode_jrd:
return reinterpret_cast<RecordSourceNode*>(node->nod_arg[0])->computable(
csb, stream, idx_use, allowOnlyCurrentStream, NULL);
case nod_class_exprnode_jrd:
{
@ -146,17 +120,13 @@ bool OPT_computable(CompilerScratch* csb, jrd_nod* node, SSHORT stream,
jrd_nod* const* ptr = node->nod_arg;
for (const jrd_nod* const* const end = ptr + node->nod_count; ptr < end; ptr++)
{
if (!OPT_computable(csb, *ptr, stream, idx_use, allowOnlyCurrentStream)) {
if (!OPT_computable(csb, *ptr, stream, idx_use, allowOnlyCurrentStream))
return false;
}
}
break;
}
}
RecordSelExpr* rse;
jrd_nod* sub;
jrd_nod* value;
USHORT n;
switch (node->nod_type)
@ -166,15 +136,12 @@ bool OPT_computable(CompilerScratch* csb, jrd_nod* node, SSHORT stream,
if (allowOnlyCurrentStream)
{
if (n != stream && !(csb->csb_rpt[n].csb_flags & csb_sub_stream))
{
return false;
}
}
else
{
if (n == stream) {
if (n == stream)
return false;
}
}
return csb->csb_rpt[n].csb_flags & csb_active;
@ -225,115 +192,24 @@ bool OPT_computable(CompilerScratch* csb, jrd_nod* node, SSHORT stream,
case nod_total:
case nod_count:
case nod_from:
if ((sub = node->nod_arg[e_stat_default]) &&
!OPT_computable(csb, sub, stream, idx_use, allowOnlyCurrentStream))
{
return false;
}
rse = (RecordSelExpr*) node->nod_arg[e_stat_rse];
value = node->nod_arg[e_stat_value];
break;
jrd_nod* sub;
case nod_rse:
rse = (RecordSelExpr*) node;
value = NULL;
break;
case nod_aggregate:
rse = (RecordSelExpr*) node->nod_arg[e_agg_rse];
rse->rse_sorted = node->nod_arg[e_agg_group];
value = NULL;
break;
case nod_window:
rse = (RecordSelExpr*) node->nod_arg[e_win_rse];
value = NULL;
break;
default:
return true;
}
// Node is a record selection expression.
bool result = true;
if ((sub = rse->rse_first) && !OPT_computable(csb, sub, stream, idx_use, allowOnlyCurrentStream)) {
return false;
}
if ((sub = rse->rse_skip) && !OPT_computable(csb, sub, stream, idx_use, allowOnlyCurrentStream)) {
return false;
}
// Set sub-streams of rse active
jrd_nod* const* ptr;
const jrd_nod* const* end;
for (ptr = rse->rse_relation, end = ptr + rse->rse_count; ptr < end; ptr++)
{
const jrd_nod* const node = *ptr;
if (node->nod_type == nod_window)
{
const jrd_nod* windows = node->nod_arg[e_win_windows];
for (unsigned i = 0; i < windows->nod_count; ++i)
if ((sub = node->nod_arg[e_stat_default]) &&
!OPT_computable(csb, sub, stream, idx_use, allowOnlyCurrentStream))
{
n = (USHORT)(IPTR) windows->nod_arg[i]->nod_arg[e_part_stream];
csb->csb_rpt[n].csb_flags |= (csb_active | csb_sub_stream);
return false;
}
}
else if (node->nod_type != nod_rse)
{
n = (USHORT)(IPTR) node->nod_arg[STREAM_INDEX(node)];
csb->csb_rpt[n].csb_flags |= (csb_active | csb_sub_stream);
fb_assert(node->nod_arg[e_stat_rse]->nod_type == nod_class_recsrcnode_jrd);
RseNode* rse = reinterpret_cast<RseNode*>(node->nod_arg[e_stat_rse]->nod_arg[0]);
return rse->computable(csb, stream, idx_use, allowOnlyCurrentStream,
node->nod_arg[e_stat_value]);
}
}
// Check sub-stream
if (((sub = rse->rse_boolean) && !OPT_computable(csb, sub, stream, idx_use, allowOnlyCurrentStream)) ||
((sub = rse->rse_sorted) && !OPT_computable(csb, sub, stream, idx_use, allowOnlyCurrentStream)) ||
((sub = rse->rse_projection) && !OPT_computable(csb, sub, stream, idx_use, allowOnlyCurrentStream)))
{
result = false;
}
for (ptr = rse->rse_relation, end = ptr + rse->rse_count; ptr < end && result; ptr++)
{
if (!OPT_computable(csb, (*ptr), stream, idx_use, allowOnlyCurrentStream))
{
result = false;
}
}
// Check value expression, if any
if (result && value && !OPT_computable(csb, value, stream, idx_use, allowOnlyCurrentStream)) {
result = false;
}
// Reset streams inactive
for (ptr = rse->rse_relation, end = ptr + rse->rse_count; ptr < end; ptr++)
{
const jrd_nod* const node = *ptr;
if (node->nod_type == nod_window)
{
const jrd_nod* windows = node->nod_arg[e_win_windows];
for (unsigned i = 0; i < windows->nod_count; ++i)
{
n = (USHORT)(IPTR) windows->nod_arg[i]->nod_arg[e_part_stream];
csb->csb_rpt[n].csb_flags &= ~(csb_active | csb_sub_stream);
}
}
else if (node->nod_type != nod_rse)
{
n = (USHORT)(IPTR) (*ptr)->nod_arg[STREAM_INDEX((*ptr))];
csb->csb_rpt[n].csb_flags &= ~(csb_active | csb_sub_stream);
}
}
return result;
return true;
}
@ -1067,6 +943,7 @@ jrd_nod* OptimizerRetrieval::composeInversion(jrd_nod* node1, jrd_nod* node2,
return OPT_make_binary_node(node_type, node1, node2, false);
}
void OptimizerRetrieval::findDependentFromStreams(jrd_nod* node, SortedStreamList* streamList) const
{
/**************************************
@ -1081,29 +958,7 @@ void OptimizerRetrieval::findDependentFromStreams(jrd_nod* node, SortedStreamLis
// Recurse thru interesting sub-nodes
if (node->nod_type == nod_procedure)
{
jrd_nod* const inputs = node->nod_arg[e_prc_inputs];
if (inputs)
{
fb_assert(inputs->nod_type == nod_asn_list);
jrd_nod* const* ptr = inputs->nod_arg;
for (const jrd_nod* const* const end = ptr + inputs->nod_count; ptr < end; ptr++)
{
findDependentFromStreams(*ptr, streamList);
}
}
}
else if (node->nod_type == nod_union)
{
jrd_nod* const clauses = node->nod_arg[e_uni_clauses];
jrd_nod* const* ptr = clauses->nod_arg;
for (const jrd_nod* const* const end = ptr + clauses->nod_count; ptr < end; ptr += 2)
{
findDependentFromStreams(*ptr, streamList);
}
}
else if (node->nod_type == nod_class_exprnode_jrd)
if (node->nod_type == nod_class_exprnode_jrd)
{
ExprNode* exprNode = reinterpret_cast<ExprNode*>(node->nod_arg[0]);
@ -1113,18 +968,18 @@ void OptimizerRetrieval::findDependentFromStreams(jrd_nod* node, SortedStreamLis
findDependentFromStreams(**i, streamList);
}
}
else if (node->nod_type == nod_class_recsrcnode_jrd)
{
reinterpret_cast<RecordSourceNode*>(node->nod_arg[0])->findDependentFromStreams(
this, streamList);
}
else
{
jrd_nod* const* ptr = node->nod_arg;
for (const jrd_nod* const* const end = ptr + node->nod_count; ptr < end; ptr++)
{
findDependentFromStreams(*ptr, streamList);
}
}
RecordSelExpr* rse;
jrd_nod* sub;
jrd_nod* value;
for (const jrd_nod* const* const end = ptr + node->nod_count; ptr < end; ptr++)
findDependentFromStreams(*ptr, streamList);
}
switch (node->nod_type)
{
@ -1136,9 +991,8 @@ void OptimizerRetrieval::findDependentFromStreams(jrd_nod* node, SortedStreamLis
(csb->csb_rpt[fieldStream].csb_flags & csb_active) &&
!(csb->csb_rpt[fieldStream].csb_flags & csb_trigger))
{
if (!streamList->exist(fieldStream)) {
if (!streamList->exist(fieldStream))
streamList->add(fieldStream);
}
}
return;
}
@ -1180,67 +1034,26 @@ void OptimizerRetrieval::findDependentFromStreams(jrd_nod* node, SortedStreamLis
case nod_total:
case nod_count:
case nod_from:
if (sub = node->nod_arg[e_stat_default]) {
{
jrd_nod* sub;
if (sub = node->nod_arg[e_stat_default])
findDependentFromStreams(sub, streamList);
}
rse = (RecordSelExpr*) node->nod_arg[e_stat_rse];
value = node->nod_arg[e_stat_value];
fb_assert(node->nod_arg[e_stat_rse]->nod_type == nod_class_recsrcnode_jrd);
RseNode* rse = reinterpret_cast<RseNode*>(node->nod_arg[e_stat_rse]->nod_arg[0]);
rse->findDependentFromStreams(this, streamList);
jrd_nod* value = node->nod_arg[e_stat_value];
// Check value expression, if any
if (value)
findDependentFromStreams(value, streamList);
break;
case nod_rse:
rse = (RecordSelExpr*) node;
value = NULL;
break;
case nod_aggregate:
rse = (RecordSelExpr*) node->nod_arg[e_agg_rse];
rse->rse_sorted = node->nod_arg[e_agg_group];
value = NULL;
break;
case nod_window:
rse = (RecordSelExpr*) node->nod_arg[e_win_rse];
value = NULL;
break;
default:
return;
}
}
// Node is a record selection expression.
if (sub = rse->rse_first) {
findDependentFromStreams(sub, streamList);
}
if (sub = rse->rse_skip) {
findDependentFromStreams(sub, streamList);
}
if (sub = rse->rse_boolean) {
findDependentFromStreams(sub, streamList);
}
if (sub = rse->rse_sorted) {
findDependentFromStreams(sub, streamList);
}
if (sub = rse->rse_projection) {
findDependentFromStreams(sub, streamList);
}
jrd_nod* const* ptr;
const jrd_nod* const* end;
for (ptr = rse->rse_relation, end = ptr + rse->rse_count; ptr < end; ptr++)
{
findDependentFromStreams(*ptr, streamList);
}
// Check value expression, if any
if (value) {
findDependentFromStreams(value, streamList);
}
return;
}
const string& OptimizerRetrieval::getAlias()

View File

@ -80,24 +80,6 @@ double OPT_getRelationCardinality(thread_db*, jrd_rel*, const Format*);
Firebird::string OPT_make_alias(thread_db*, const CompilerScratch*, const CompilerScratch::csb_repeat*);
jrd_nod* OPT_make_binary_node(nod_t, jrd_nod*, jrd_nod*, bool);
inline int STREAM_INDEX(const jrd_nod* node)
{
switch (node->nod_type)
{
case nod_relation:
return e_rel_stream;
case nod_procedure:
return e_prc_stream;
case nod_union:
return e_uni_stream;
case nod_aggregate:
return e_agg_stream;
default:
fb_assert(false);
return 0; // silence compiler warning.
}
}
enum segmentScanType {
segmentScanNone,
segmentScanGreater,
@ -146,8 +128,6 @@ public:
Firebird::Array<IndexScratchSegment*> segments;
};
typedef Firebird::SortedArray<int> SortedStreamList;
class InversionCandidate
{
public:
@ -182,9 +162,10 @@ public:
InversionCandidate* getCost();
InversionCandidate* getInversion(IndexTableScan** rsb);
void findDependentFromStreams(jrd_nod* node, SortedStreamList* streamList) const;
protected:
jrd_nod* composeInversion(jrd_nod* node1, jrd_nod* node2, nod_t node_type) const;
void findDependentFromStreams(jrd_nod* node, SortedStreamList* streamList) const;
const Firebird::string& getAlias();
InversionCandidate* generateInversion(IndexTableScan** rsb);
IndexTableScan* generateNavigation();

File diff suppressed because it is too large Load Diff

463
src/jrd/RecordSourceNodes.h Normal file
View File

@ -0,0 +1,463 @@
/*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
* Adriano dos Santos Fernandes
*/
#include "../jrd/common.h"
#include "../common/classes/alloc.h"
#include "../common/classes/array.h"
#include "../common/classes/NestConst.h"
#include "../jrd/jrd.h"
#include "../jrd/exe.h"
#include "../dsql/Visitors.h"
namespace Jrd {
class OptimizerRetrieval;
class ProcedureScan;
class RseNode;
class RecordSourceNode : public Firebird::PermanentStorage
{
public:
enum Type
{
TYPE_RELATION,
TYPE_PROCEDURE,
TYPE_AGGREGATE,
TYPE_UNION,
TYPE_WINDOW,
TYPE_RSE
};
RecordSourceNode(Type aType, MemoryPool& pool)
: PermanentStorage(pool),
type(aType)
{
}
virtual USHORT getStream() const
{
return stream;
}
void setStream(USHORT value)
{
stream = value;
}
// Identify the streams that make up an RseNode.
virtual void getStreams(StreamsArray& list) const
{
list.add(getStream());
}
virtual RecordSourceNode* copy(thread_db* tdbb, NodeCopier& copier) = 0;
virtual void ignoreDbKey(thread_db* tdbb, CompilerScratch* csb, const jrd_rel* view) const = 0;
virtual void pass1(thread_db* tdbb, CompilerScratch* csb, jrd_rel* view) = 0;
virtual void pass1Source(thread_db* tdbb, CompilerScratch* csb, RseNode* rse,
jrd_nod** boolean, RecordSourceNodeStack& stack) = 0;
virtual void pass2(thread_db* tdbb, CompilerScratch* csb) = 0;
virtual void pass2Rse(thread_db* tdbb, CompilerScratch* csb) = 0;
virtual bool containsStream(USHORT checkStream) const = 0;
// Identify all of the streams for which a dbkey may need to be carried through a sort.
virtual void computeDbKeyStreams(UCHAR* streams) const = 0;
virtual bool computable(CompilerScratch* csb, SSHORT stream, bool idx_use,
bool allowOnlyCurrentStream, jrd_nod* value) = 0;
virtual void findDependentFromStreams(const OptimizerRetrieval* optRet,
SortedStreamList* streamList) = 0;
virtual RecordSource* compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt,
RseNode* rse, NodeStack* parent_stack, stream_array_t& beds, stream_array_t& key_streams,
stream_array_t& local_streams, NodeStack& conjunct_stack, stream_array_t& streams,
jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunct_count,
bool innerSubStream) = 0;
public:
const Type type;
protected:
USHORT stream;
};
class RelationSourceNode : public TypedNode<RecordSourceNode, RecordSourceNode::TYPE_RELATION>
{
public:
explicit RelationSourceNode(MemoryPool& pool)
: TypedNode<RecordSourceNode, RecordSourceNode::TYPE_RELATION>(pool),
relation(NULL),
context(NULL),
alias(NULL),
view(NULL)
{
}
static RelationSourceNode* parse(thread_db* tdbb, CompilerScratch* csb, SSHORT blrOp,
bool parseContext);
virtual RelationSourceNode* copy(thread_db* tdbb, NodeCopier& copier);
virtual void ignoreDbKey(thread_db* tdbb, CompilerScratch* csb, const jrd_rel* view) const;
virtual void pass1(thread_db* tdbb, CompilerScratch* csb, jrd_rel* view)
{
}
virtual void pass1Source(thread_db* tdbb, CompilerScratch* csb, RseNode* rse,
jrd_nod** boolean, RecordSourceNodeStack& stack);
virtual void pass2(thread_db* tdbb, CompilerScratch* csb)
{
}
virtual void pass2Rse(thread_db* tdbb, CompilerScratch* csb);
virtual bool containsStream(USHORT checkStream) const
{
return checkStream == stream;
}
virtual void computeDbKeyStreams(UCHAR* streams) const
{
fb_assert(streams[0] < MAX_STREAMS && streams[0] < MAX_UCHAR);
streams[++streams[0]] = getStream();
}
virtual bool computable(CompilerScratch* csb, SSHORT stream, bool idx_use,
bool allowOnlyCurrentStream, jrd_nod* value)
{
return true;
}
virtual void findDependentFromStreams(const OptimizerRetrieval* optRet,
SortedStreamList* streamList)
{
}
virtual RecordSource* compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt,
RseNode* rse, NodeStack* parent_stack, stream_array_t& beds, stream_array_t& key_streams,
stream_array_t& local_streams, NodeStack& conjunct_stack, stream_array_t& streams,
jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunct_count,
bool innerSubStream);
public:
jrd_rel* relation;
SSHORT context; // user-specified context number for the relation reference
const char* alias; // SQL alias for the relation
private:
jrd_rel* view; // parent view for posting access
};
class ProcedureSourceNode : public TypedNode<RecordSourceNode, RecordSourceNode::TYPE_PROCEDURE>
{
public:
explicit ProcedureSourceNode(MemoryPool& pool)
: TypedNode<RecordSourceNode, RecordSourceNode::TYPE_PROCEDURE>(pool),
inputs(NULL),
in_msg(NULL),
procedure(NULL),
view(NULL),
context(NULL)
{
}
static ProcedureSourceNode* parse(thread_db* tdbb, CompilerScratch* csb, SSHORT blrOp);
virtual ProcedureSourceNode* copy(thread_db* tdbb, NodeCopier& copier);
virtual void ignoreDbKey(thread_db* tdbb, CompilerScratch* csb, const jrd_rel* view) const
{
}
virtual void pass1(thread_db* tdbb, CompilerScratch* csb, jrd_rel* view);
virtual void pass1Source(thread_db* tdbb, CompilerScratch* csb, RseNode* rse,
jrd_nod** boolean, RecordSourceNodeStack& stack);
virtual void pass2(thread_db* tdbb, CompilerScratch* csb);
virtual void pass2Rse(thread_db* tdbb, CompilerScratch* csb);
virtual bool containsStream(USHORT checkStream) const
{
return false;
}
virtual void computeDbKeyStreams(UCHAR* streams) const
{
}
virtual bool computable(CompilerScratch* csb, SSHORT stream, bool idx_use,
bool allowOnlyCurrentStream, jrd_nod* value);
virtual void findDependentFromStreams(const OptimizerRetrieval* optRet,
SortedStreamList* streamList);
virtual RecordSource* compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt,
RseNode* rse, NodeStack* parent_stack, stream_array_t& beds, stream_array_t& key_streams,
stream_array_t& local_streams, NodeStack& conjunct_stack, stream_array_t& streams,
jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunct_count,
bool innerSubStream);
private:
ProcedureScan* generate(thread_db* tdbb, OptimizerBlk* opt);
public:
NestConst<jrd_nod> inputs;
private:
NestConst<jrd_nod> in_msg;
USHORT procedure;
jrd_rel* view;
SSHORT context;
};
class AggregateSourceNode : public TypedNode<RecordSourceNode, RecordSourceNode::TYPE_AGGREGATE>
{
public:
explicit AggregateSourceNode(MemoryPool& pool)
: TypedNode<RecordSourceNode, RecordSourceNode::TYPE_AGGREGATE>(pool),
group(NULL),
map(NULL),
rse(NULL)
{
}
static AggregateSourceNode* parse(thread_db* tdbb, CompilerScratch* csb);
virtual AggregateSourceNode* copy(thread_db* tdbb, NodeCopier& copier);
virtual void ignoreDbKey(thread_db* tdbb, CompilerScratch* csb, const jrd_rel* view) const;
virtual void pass1(thread_db* tdbb, CompilerScratch* csb, jrd_rel* view);
virtual void pass1Source(thread_db* tdbb, CompilerScratch* csb, RseNode* rse,
jrd_nod** boolean, RecordSourceNodeStack& stack);
virtual void pass2(thread_db* tdbb, CompilerScratch* csb);
virtual void pass2Rse(thread_db* tdbb, CompilerScratch* csb);
virtual bool containsStream(USHORT checkStream) const;
virtual void computeDbKeyStreams(UCHAR* streams) const
{
}
virtual bool computable(CompilerScratch* csb, SSHORT stream, bool idx_use,
bool allowOnlyCurrentStream, jrd_nod* value);
virtual void findDependentFromStreams(const OptimizerRetrieval* optRet,
SortedStreamList* streamList);
virtual RecordSource* compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt,
RseNode* rse, NodeStack* parent_stack, stream_array_t& beds, stream_array_t& key_streams,
stream_array_t& local_streams, NodeStack& conjunct_stack, stream_array_t& streams,
jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunct_count,
bool innerSubStream);
private:
RecordSource* generate(thread_db* tdbb, OptimizerBlk* opt, NodeStack* parent_stack,
UCHAR shellStream);
public:
NestConst<jrd_nod> group;
NestConst<jrd_nod> map;
private:
NestConst<RseNode> rse;
};
class UnionSourceNode : public TypedNode<RecordSourceNode, RecordSourceNode::TYPE_UNION>
{
public:
explicit UnionSourceNode(MemoryPool& pool)
: TypedNode<RecordSourceNode, RecordSourceNode::TYPE_UNION>(pool),
clauses(pool),
maps(pool),
mapStream(NULL),
recursive(false)
{
}
static UnionSourceNode* parse(thread_db* tdbb, CompilerScratch* csb, SSHORT blrOp);
virtual UnionSourceNode* copy(thread_db* tdbb, NodeCopier& copier);
virtual void ignoreDbKey(thread_db* tdbb, CompilerScratch* csb, const jrd_rel* view) const;
virtual void pass1(thread_db* tdbb, CompilerScratch* csb, jrd_rel* view)
{
}
virtual void pass1Source(thread_db* tdbb, CompilerScratch* csb, RseNode* rse,
jrd_nod** boolean, RecordSourceNodeStack& stack);
virtual void pass2(thread_db* tdbb, CompilerScratch* csb);
virtual void pass2Rse(thread_db* tdbb, CompilerScratch* csb);
virtual bool containsStream(USHORT checkStream) const;
virtual void computeDbKeyStreams(UCHAR* streams) const;
virtual bool computable(CompilerScratch* csb, SSHORT stream, bool idx_use,
bool allowOnlyCurrentStream, jrd_nod* value);
virtual void findDependentFromStreams(const OptimizerRetrieval* optRet,
SortedStreamList* streamList);
virtual RecordSource* compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt,
RseNode* rse, NodeStack* parent_stack, stream_array_t& beds, stream_array_t& key_streams,
stream_array_t& local_streams, NodeStack& conjunct_stack, stream_array_t& streams,
jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunct_count,
bool innerSubStream);
private:
RecordSource* generate(thread_db* tdbb, OptimizerBlk* opt, UCHAR* streams, USHORT nstreams,
NodeStack* parent_stack, UCHAR shellStream);
private:
Firebird::Array<NestConst<RseNode> > clauses; // RseNode's for union
Firebird::Array<NestConst<jrd_nod> > maps; // RseNode's maps
USHORT mapStream; // stream for next level record of recursive union
bool recursive; // union node is a recursive union
};
class WindowSourceNode : public TypedNode<RecordSourceNode, RecordSourceNode::TYPE_WINDOW>
{
public:
explicit WindowSourceNode(MemoryPool& pool)
: TypedNode<RecordSourceNode, RecordSourceNode::TYPE_WINDOW>(pool),
rse(NULL),
windows(NULL)
{
}
static WindowSourceNode* parse(thread_db* tdbb, CompilerScratch* csb);
private:
static jrd_nod* parsePartitionBy(thread_db* tdbb, CompilerScratch* csb);
public:
virtual USHORT getStream() const
{
fb_assert(false);
return 0;
}
virtual void getStreams(StreamsArray& list) const;
virtual WindowSourceNode* copy(thread_db* tdbb, NodeCopier& copier);
virtual void ignoreDbKey(thread_db* tdbb, CompilerScratch* csb, const jrd_rel* view) const;
virtual void pass1(thread_db* tdbb, CompilerScratch* csb, jrd_rel* view);
virtual void pass1Source(thread_db* tdbb, CompilerScratch* csb, RseNode* rse,
jrd_nod** boolean, RecordSourceNodeStack& stack);
virtual void pass2(thread_db* tdbb, CompilerScratch* csb);
virtual void pass2Rse(thread_db* tdbb, CompilerScratch* csb);
virtual bool containsStream(USHORT checkStream) const;
virtual void computeDbKeyStreams(UCHAR* streams) const
{
}
virtual bool computable(CompilerScratch* csb, SSHORT stream, bool idx_use,
bool allowOnlyCurrentStream, jrd_nod* value);
virtual void findDependentFromStreams(const OptimizerRetrieval* optRet,
SortedStreamList* streamList);
virtual RecordSource* compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt,
RseNode* rse, NodeStack* parent_stack, stream_array_t& beds, stream_array_t& key_streams,
stream_array_t& local_streams, NodeStack& conjunct_stack, stream_array_t& streams,
jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunct_count,
bool innerSubStream);
private:
NestConst<RseNode> rse;
NestConst<jrd_nod> windows;
};
class RseNode : public TypedNode<RecordSourceNode, RecordSourceNode::TYPE_RSE>
{
public:
static const unsigned FLAG_VARIANT = 0x1; // variant (not invariant?)
static const unsigned FLAG_SINGULAR = 0x2; // singleton select
static const unsigned FLAG_WRITELOCK = 0x4; // locked for write
static const unsigned FLAG_SCROLLABLE = 0x8; // scrollable cursor
explicit RseNode(MemoryPool& pool)
: TypedNode<RecordSourceNode, RecordSourceNode::TYPE_RSE>(pool),
rse_jointype(0),
rse_invariants(NULL),
rse_relations(pool),
flags(0)
{
}
static RseNode* getFrom(jrd_nod* node)
{
fb_assert(node->nod_type == nod_class_recsrcnode_jrd);
return reinterpret_cast<RseNode*>(node->nod_arg[0]);
}
RseNode* clone()
{
RseNode* obj = FB_NEW(getPool()) RseNode(getPool());
obj->rse_jointype = rse_jointype;
obj->rse_first = rse_first;
obj->rse_skip = rse_skip;
obj->rse_boolean = rse_boolean;
obj->rse_sorted = rse_sorted;
obj->rse_projection = rse_projection;
obj->rse_aggregate = rse_aggregate;
obj->rse_plan = rse_plan;
obj->rse_invariants = rse_invariants;
obj->flags = flags;
obj->rse_relations = rse_relations;
return obj;
}
virtual void getStreams(StreamsArray& list) const
{
}
virtual RseNode* copy(thread_db* tdbb, NodeCopier& copier);
virtual void ignoreDbKey(thread_db* tdbb, CompilerScratch* csb, const jrd_rel* view) const;
virtual void pass1(thread_db* tdbb, CompilerScratch* csb, jrd_rel* view);
virtual void pass1Source(thread_db* tdbb, CompilerScratch* csb, RseNode* rse,
jrd_nod** boolean, RecordSourceNodeStack& stack);
virtual void pass2(thread_db* tdbb, CompilerScratch* csb)
{
}
virtual void pass2Rse(thread_db* tdbb, CompilerScratch* csb);
virtual bool containsStream(USHORT checkStream) const;
virtual void computeDbKeyStreams(UCHAR* streams) const;
virtual bool computable(CompilerScratch* csb, SSHORT stream, bool idx_use,
bool allowOnlyCurrentStream, jrd_nod* value);
virtual void findDependentFromStreams(const OptimizerRetrieval* optRet,
SortedStreamList* streamList);
virtual RecordSource* compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt,
RseNode* rse, NodeStack* parent_stack, stream_array_t& beds, stream_array_t& key_streams,
stream_array_t& local_streams, NodeStack& conjunct_stack, stream_array_t& streams,
jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunct_count,
bool innerSubStream);
private:
void computeRseStreams(const CompilerScratch* csb, UCHAR* streams) const;
void planCheck(const CompilerScratch* csb) const;
static void planSet(CompilerScratch* csb, jrd_nod* plan);
public:
USHORT rse_jointype; // inner, left, full
NestConst<jrd_nod> rse_first;
NestConst<jrd_nod> rse_skip;
NestConst<jrd_nod> rse_boolean;
NestConst<jrd_nod> rse_sorted;
NestConst<jrd_nod> rse_projection;
NestConst<jrd_nod> rse_aggregate; // singleton aggregate for optimizing to index
NestConst<jrd_nod> rse_plan; // user-specified access plan
NestConst<VarInvariantArray> rse_invariants; // Invariant nodes bound to top-level RSE
Firebird::Array<NestConst<RecordSourceNode> > rse_relations;
unsigned flags;
};
} //namespace Jrd

View File

@ -29,6 +29,8 @@
namespace Jrd
{
class RseNode;
// view context block to cache view aliases
class ViewContext
@ -184,7 +186,7 @@ public:
Firebird::MetaName rel_owner_name; // ascii owner
vec<jrd_fld*>* rel_fields; // vector of field blocks
RecordSelExpr* rel_view_rse; // view record select expression
RseNode* rel_view_rse; // view record select expression
ViewContexts rel_view_contexts; // sorted array of view contexts
Firebird::MetaName rel_security_name; // security class name for relation

File diff suppressed because it is too large Load Diff

View File

@ -28,6 +28,7 @@
// req.h includes exe.h => Jrd::CompilerScratch and Jrd::CompilerScratch::csb_repeat.
#include "../jrd/scl.h"
UCHAR* CMP_alloc_map(Jrd::thread_db*, Jrd::CompilerScratch*, USHORT);
Jrd::jrd_nod* CMP_clone_node_opt(Jrd::thread_db*, Jrd::CompilerScratch*, Jrd::jrd_nod*);
Jrd::jrd_nod* CMP_clone_node(Jrd::thread_db*, Jrd::CompilerScratch*, Jrd::jrd_nod*);
Jrd::jrd_req* CMP_compile2(Jrd::thread_db*, const UCHAR* blr, ULONG blr_length, bool internal_flag,
@ -59,6 +60,7 @@ inline void CMP_post_access(Jrd::thread_db* tdbb,
CMP_post_access(tdbb, csb, security_name, view_id, mask, type_name, name, "");
}
void CMP_post_procedure_access(Jrd::thread_db*, Jrd::CompilerScratch*, Jrd::jrd_prc*);
void CMP_post_resource(Jrd::ResourceList*, void*, Jrd::Resource::rsc_s, USHORT);
void CMP_release(Jrd::thread_db*, Jrd::jrd_req*);
void CMP_shutdown_database(Jrd::thread_db*);

View File

@ -102,6 +102,7 @@
#include "../jrd/execute_statement.h"
#include "../dsql/dsql_proto.h"
#include "../jrd/rpb_chain.h"
#include "../jrd/RecordSourceNodes.h"
#include "../jrd/VirtualTable.h"
#include "../jrd/trace/TraceManager.h"
#include "../jrd/trace/TraceJrdHelpers.h"
@ -3377,7 +3378,13 @@ static const jrd_nod* store(thread_db* tdbb, const jrd_nod* node, SSHORT which_t
jrd_req* request = tdbb->getRequest();
jrd_tra* transaction = request->req_transaction;
impure_state* impure = request->getImpure<impure_state>(node->nod_impure);
SSHORT stream = (USHORT)(IPTR) node->nod_arg[e_sto_relation]->nod_arg[e_rel_stream];
fb_assert(node->nod_arg[e_sto_relation]->nod_type == nod_class_recsrcnode_jrd);
const RelationSourceNode* recSource = reinterpret_cast<const RelationSourceNode*>(
node->nod_arg[e_sto_relation]->nod_arg[0]);
fb_assert(recSource->type == RelationSourceNode::TYPE);
SSHORT stream = recSource->getStream();
record_param* rpb = &request->req_rpb[stream];
jrd_rel* relation = rpb->rpb_relation;

View File

@ -50,6 +50,8 @@
#include "../jrd/DebugInterface.h"
#include "../jrd/BlrReader.h"
#include "../dsql/Nodes.h"
#include "../dsql/Visitors.h"
// This macro enables DSQL tracing code
//#define CMP_DEBUG
@ -142,37 +144,9 @@ const int nod_value = 16; // full value area required in impure space
const int nod_deoptimize = 32; // boolean which requires deoptimization
const int nod_agg_dbkey = 64; // dbkey of an aggregate
const int nod_invariant = 128; // node is recognized as being invariant
const int nod_recurse = 256; // union node is a recursive union
const int nod_unique_sort = 512; // sorts using unique key - for distinct and group by
const int nod_ansi_not = 1024; // ANY/ALL predicate is prefixed with a NOT one
// Special RecordSelExpr node
class RecordSelExpr : public jrd_node_base
{
public:
USHORT rse_count;
USHORT rse_jointype; // inner, left, full
NestConst<jrd_nod> rse_first;
NestConst<jrd_nod> rse_skip;
NestConst<jrd_nod> rse_boolean;
NestConst<jrd_nod> rse_sorted;
NestConst<jrd_nod> rse_projection;
NestConst<jrd_nod> rse_aggregate; // singleton aggregate for optimizing to index
NestConst<jrd_nod> rse_plan; // user-specified access plan
VarInvariantArray* rse_invariants; // Invariant nodes bound to top-level RSE
jrd_nod* rse_relation[1];
};
const int rse_variant = 1; // variant (not invariant?)
const int rse_singular = 2; // singleton select
const int rse_writelock = 4; // locked for write
const int rse_scrollable = 8; // scrollable cursor
// Number of nodes may fit into nod_arg of normal node to get to rse_relation
const size_t rse_delta = (sizeof(RecordSelExpr) - sizeof(jrd_nod)) / sizeof(jrd_nod::blk_repeat_type);
// Types of nulls placement for each column in sort order
const int rse_nulls_default = 0;
const int rse_nulls_first = 1;
@ -282,13 +256,6 @@ const int e_asgn_missing = 2; // Value for comparison for missing
const int e_asgn_missing2 = 3; // Value for substitute for missing
const int e_asgn_length = 4;
const int e_rel_stream = 0;
const int e_rel_relation = 1;
const int e_rel_view = 2; // parent view for posting access
const int e_rel_alias = 3; // SQL alias for the relation
const int e_rel_context = 4; // user-specified context number for the relation reference
const int e_rel_length = 5;
const int e_idx_retrieval = 0;
const int e_idx_length = 1;
@ -304,21 +271,6 @@ const int e_val_boolean = 0;
const int e_val_value = 1;
const int e_val_length = 2;
const int e_uni_stream = 0; // Stream for union
const int e_uni_clauses = 1; // RecordSelExpr's for union
const int e_uni_map_stream = 2; // stream for next level record of recursive union
const int e_uni_length = 3;
const int e_agg_stream = 0;
const int e_agg_rse = 1;
const int e_agg_group = 2;
const int e_agg_map = 3;
const int e_agg_length = 4;
const int e_win_rse = 0;
const int e_win_windows = 1;
const int e_win_length = 2;
// Statistical expressions
const int e_stat_rse = 0;
@ -336,16 +288,6 @@ const int e_esp_out_msg = 3;
const int e_esp_procedure = 4;
const int e_esp_length = 5;
// Stored procedure view
const int e_prc_inputs = 0;
const int e_prc_in_msg = 1;
const int e_prc_stream = 2;
const int e_prc_procedure = 3;
const int e_prc_view = 4;
const int e_prc_context = 5;
const int e_prc_length = 6;
// Generate id
const int e_gen_value = 0;
@ -727,6 +669,24 @@ struct ItemInfo
bool fullDomain;
};
struct LegacyNodeOrRseNode
{
LegacyNodeOrRseNode(jrd_nod* aLegacyNode)
: legacyNode(aLegacyNode),
rseNode(NULL)
{
}
LegacyNodeOrRseNode(RseNode* aRseNode)
: legacyNode(NULL),
rseNode(aRseNode)
{
}
jrd_nod* legacyNode;
RseNode* rseNode;
};
typedef Firebird::GenericMap<Firebird::Pair<Firebird::Left<Firebird::MetaNamePair, FieldInfo> > >
MapFieldInfo;
typedef Firebird::GenericMap<Firebird::Pair<Firebird::Right<Item, ItemInfo> > > MapItemInfo;
@ -829,7 +789,7 @@ public:
Firebird::Array<const RecordSource*> csb_fors; // record sources
Firebird::Array<jrd_nod*> csb_exec_sta; // Array of exec_into nodes
Firebird::Array<jrd_nod*> csb_invariants; // stack of invariant nodes
Firebird::Array<jrd_node_base*> csb_current_nodes; // RecordSelExpr's and other invariant
Firebird::Array<LegacyNodeOrRseNode> csb_current_nodes; // RseNode's and other invariant
// candidates within whose scope we are
USHORT csb_n_stream; // Next available stream
USHORT csb_msg_number; // Highest used message number
@ -958,6 +918,10 @@ public:
// declared as varchar
const int XCP_MESSAGE_LENGTH = 1023 - sizeof(USHORT);
} //namespace Jrd
typedef Firebird::HalfStaticArray<UCHAR, OPT_STATIC_ITEMS> StreamsArray;
typedef Firebird::SortedArray<int> SortedStreamList;
typedef UCHAR stream_array_t[MAX_STREAMS + 1];
} // namespace Jrd
#endif // JRD_EXE_H

View File

@ -130,7 +130,6 @@ class IndexBlock;
class IndexLock;
class ArrayField;
struct sort_context;
class RecordSelExpr;
class vcl;
class TextType;
class Parameter;

View File

@ -28,8 +28,11 @@
namespace Jrd {
class Record;
class jrd_nod;
class RecordSourceNode;
typedef Firebird::Stack<Record*> RecordStack;
typedef Firebird::Stack<jrd_nod*> NodeStack;
typedef Firebird::Stack<RecordSourceNode*> RecordSourceNodeStack;
typedef Firebird::Stack<SLONG> PageStack;
typedef Firebird::Stack<UCHAR*> UCharStack;
}

View File

@ -90,6 +90,7 @@
#include "../common/utils_proto.h"
#include "../jrd/PreparedStatement.h"
#include "../jrd/RecordSourceNodes.h"
#include "../jrd/DebugInterface.h"
#include "../common/classes/MsgPrint.h"
#include "../jrd/Function.h"
@ -3570,20 +3571,25 @@ void MET_scan_relation(thread_db* tdbb, jrd_rel* relation)
{
// parse the view blr, getting dependencies on relations, etc. at the same time
jrd_nod* rseNode;
if (dependencies)
{
const MetaName depName(REL.RDB$RELATION_NAME);
relation->rel_view_rse =
(RecordSelExpr*) MET_get_dependencies(tdbb, relation, NULL, 0, NULL,
&REL.RDB$VIEW_BLR, NULL,
&csb, depName, obj_view, 0, depTrans);
rseNode = MET_get_dependencies(tdbb, relation, NULL, 0, NULL, &REL.RDB$VIEW_BLR,
NULL, &csb, depName, obj_view, 0, depTrans);
}
else
rseNode = MET_parse_blob(tdbb, relation, &REL.RDB$VIEW_BLR, &csb, NULL, false);
if (rseNode)
{
relation->rel_view_rse =
(RecordSelExpr*) MET_parse_blob(tdbb, relation,
&REL.RDB$VIEW_BLR, &csb, NULL, false);
fb_assert(rseNode->nod_type == nod_class_recsrcnode_jrd);
relation->rel_view_rse = reinterpret_cast<RseNode*>(rseNode->nod_arg[0]);
fb_assert(relation->rel_view_rse->type == RseNode::TYPE);
}
else
relation->rel_view_rse = NULL;
// retrieve the view context names

View File

@ -92,14 +92,9 @@ NODE(nod_asn_list, asn_list, "")
NODE(nod_not, not, " NOT ")
NODE(nod_validate, validate, "")
NODE(nod_relation, relation, "")
NODE(nod_rse, RecordSelExpr, "")
NODE(nod_sort, sort, "")
NODE(nod_union, union, "")
NODE(nod_aggregate, aggregate, "")
NODE(nod_map, map, "")
NODE(nod_exec_proc, exec_proc, "")
NODE(nod_procedure, procedure, "")
NODE(nod_block, block, "")
NODE(nod_error_handler, error_handler, "")
NODE(nod_cast, cast, "CAST")
@ -115,9 +110,6 @@ NODE(nod_asn_list, asn_list, "")
NODE(nod_indices, indices, "INDICES")
NODE(nod_retrieve, retrieve, "RETRIEVE")
NODE(nod_relation2, relation2, "RELATION2")
NODE(nod_rid2, rid2, "RID2")
NODE(nod_set_generator, set_generator, "")
/* Required for NULL handling */
@ -170,7 +162,7 @@ NODE(nod_asn_list, asn_list, "")
NODE(nod_domain_validation, domain_validation, "")
NODE(nod_class_exprnode_jrd, class_exprnode_jrd, "class_exprnode_jrd")
NODE(nod_class_stmtnode_jrd, class_stmtnode_jrd, "class_stmtnode_jrd")
NODE(nod_class_recsrcnode_jrd, class_recsrcnode_jrd, "class_recsrcnode_jrd")
NODE(nod_stmt_expr, stmt_expr, "stmt_expr")
NODE(nod_derived_expr, derived_expr, "derived_expr")
NODE(nod_continue_loop, continue_loop, "")
NODE(nod_window, window, "")

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,6 @@ namespace Jrd {
class jrd_req;
class jrd_rel;
class jrd_nod;
class RecordSelExpr;
class RecordSource;
struct index_desc;
class CompilerScratch;
@ -43,7 +42,7 @@ namespace Jrd {
bool OPT_access_path(const Jrd::jrd_req*, UCHAR*, SLONG, ULONG*);
Jrd::RecordSource* OPT_compile(Jrd::thread_db*, Jrd::CompilerScratch*,
Jrd::RecordSelExpr*, Jrd::NodeStack*);
Jrd::RseNode*, Jrd::NodeStack*);
void OPT_gen_aggregate_distincts(Jrd::thread_db*, Jrd::CompilerScratch*, Jrd::jrd_nod*);
Jrd::SortedStream* OPT_gen_sort(Jrd::thread_db*, Jrd::CompilerScratch*, const UCHAR*,
const UCHAR*, Jrd::RecordSource*, Jrd::jrd_nod*, bool);

View File

@ -62,6 +62,7 @@
#include "../jrd/met_proto.h"
#include "../jrd/par_proto.h"
#include "../common/utils_proto.h"
#include "../jrd/RecordSourceNodes.h"
#include "../jrd/SysFunction.h"
#include "../jrd/BlrReader.h"
#include "../jrd/Function.h"
@ -86,22 +87,13 @@ static NodeParseFunc blr_parsers[256] = {NULL};
static SSHORT find_proc_field(const jrd_prc*, const Firebird::MetaName&);
static jrd_nod* par_cast(thread_db*, CompilerScratch*);
static PsqlException* par_conditions(thread_db*, CompilerScratch*);
static SSHORT par_context(CompilerScratch*, SSHORT *);
static void par_dependency(thread_db*, CompilerScratch*, SSHORT, SSHORT, const Firebird::MetaName&);
static jrd_nod* par_exec_proc(thread_db*, CompilerScratch*, SSHORT);
static jrd_nod* par_fetch(thread_db*, CompilerScratch*, jrd_nod*);
static jrd_nod* par_field(thread_db*, CompilerScratch*, SSHORT);
static jrd_nod* par_literal(thread_db*, CompilerScratch*);
static jrd_nod* par_map(thread_db*, CompilerScratch*, USHORT);
static jrd_nod* par_message(thread_db*, CompilerScratch*);
static jrd_nod* par_modify(thread_db*, CompilerScratch*, SSHORT);
static jrd_nod* par_partition_by(thread_db*, CompilerScratch*);
static jrd_nod* par_plan(thread_db*, CompilerScratch*);
static jrd_nod* par_procedure(thread_db*, CompilerScratch*, SSHORT);
static void par_procedure_parms(thread_db*, CompilerScratch*, jrd_prc*, jrd_nod**, jrd_nod**, bool);
static jrd_nod* par_relation(thread_db*, CompilerScratch*, SSHORT, bool);
static jrd_nod* par_sort(thread_db*, CompilerScratch*, bool, bool);
static jrd_nod* par_union(thread_db*, CompilerScratch*, bool);
jrd_nod* PAR_blr(thread_db* tdbb, jrd_rel* relation, const UCHAR* blr, ULONG blr_length,
@ -169,7 +161,7 @@ jrd_nod* PAR_blr(thread_db* tdbb, jrd_rel* relation, const UCHAR* blr, ULONG blr
CompilerScratch::rpt_itr ptr = view_csb->csb_rpt.begin();
// AB: csb_n_stream replaced by view_csb->csb_rpt.getCount(), because there could
// be more then just csb_n_stream-numbers that hold data.
// Certainly csb_stream (see par_context where the context is retrieved)
// Certainly csb_stream (see PAR_context where the context is retrieved)
const CompilerScratch::rpt_const_itr end = view_csb->csb_rpt.end();
for (SSHORT stream = 0; ptr != end; ++ptr, ++stream)
{
@ -588,7 +580,7 @@ jrd_nod* PAR_make_field(thread_db* tdbb, CompilerScratch* csb,
}
if (csb->csb_g_flags & csb_get_dependencies) {
par_dependency(tdbb, csb, stream, id, base_field);
PAR_dependency(tdbb, csb, stream, id, base_field);
}
jrd_nod* temp_node = PAR_gen_field(tdbb, stream, id);
@ -961,11 +953,11 @@ static PsqlException* par_conditions(thread_db* tdbb, CompilerScratch* csb)
}
static SSHORT par_context(CompilerScratch* csb, SSHORT* context_ptr)
SSHORT PAR_context(CompilerScratch* csb, SSHORT* context_ptr)
{
/**************************************
*
* p a r _ c o n t e x t
* P A R _ c o n t e x t
*
**************************************
*
@ -1007,15 +999,12 @@ static SSHORT par_context(CompilerScratch* csb, SSHORT* context_ptr)
}
static void par_dependency(thread_db* tdbb,
CompilerScratch* csb,
SSHORT stream,
SSHORT id,
const Firebird::MetaName& field_name)
void PAR_dependency(thread_db* tdbb, CompilerScratch* csb, SSHORT stream, SSHORT id,
const MetaName& field_name)
{
/**************************************
*
* p a r _ d e p e n d e n c y
* P A R _ d e p e n d e n c y
*
**************************************
*
@ -1094,10 +1083,10 @@ static jrd_nod* par_exec_proc(thread_db* tdbb, CompilerScratch* csb, SSHORT blr_
node->nod_count = count_table[blr_exec_proc];
node->nod_arg[e_esp_procedure] = (jrd_nod*) procedure;
par_procedure_parms(tdbb, csb, procedure, &node->nod_arg[e_esp_in_msg],
&node->nod_arg[e_esp_inputs], true);
par_procedure_parms(tdbb, csb, procedure, &node->nod_arg[e_esp_out_msg],
&node->nod_arg[e_esp_outputs], false);
PAR_procedure_parms(tdbb, csb, procedure, &node->nod_arg[e_esp_in_msg],
&node->nod_arg[e_esp_inputs], true);
PAR_procedure_parms(tdbb, csb, procedure, &node->nod_arg[e_esp_out_msg],
&node->nod_arg[e_esp_outputs], false);
CompilerScratch::Dependency dependency(obj_procedure);
dependency.procedure = procedure;
@ -1125,15 +1114,19 @@ static jrd_nod* par_fetch(thread_db* tdbb, CompilerScratch* csb, jrd_nod* node)
ForNode* forNode = reinterpret_cast<ForNode*>(node->nod_arg[0]);
// Fake RecordSelExpr
// Fake RseNode
forNode->rse = PAR_make_node(tdbb, 1 + rse_delta + 2);
RecordSelExpr* rse = reinterpret_cast<RecordSelExpr*>(static_cast<jrd_nod*>(forNode->rse));
rse->nod_type = nod_rse;
rse->nod_count = 0;
rse->rse_count = 1;
jrd_nod* relation = PAR_parse_node(tdbb, csb, RELATION);
rse->rse_relation[0] = relation;
RseNode* rse = forNode->rse = FB_NEW(*tdbb->getDefaultPool()) RseNode(
*tdbb->getDefaultPool());
jrd_nod* relationNode = PAR_parse_node(tdbb, csb, RELATION);
fb_assert(relationNode->nod_type == nod_class_recsrcnode_jrd);
RelationSourceNode* relationSource = reinterpret_cast<RelationSourceNode*>(
relationNode->nod_arg[0]);
fb_assert(relationSource->type == RelationSourceNode::TYPE);
rse->rse_relations.add(relationSource);
// Fake boolean
@ -1145,7 +1138,7 @@ static jrd_nod* par_fetch(thread_db* tdbb, CompilerScratch* csb, jrd_nod* node)
booleanNode = booleanNode->nod_arg[0];
booleanNode->nod_type = nod_dbkey;
booleanNode->nod_count = 0;
booleanNode->nod_arg[0] = relation->nod_arg[e_rel_stream];
booleanNode->nod_arg[0] = (jrd_nod*)(IPTR) relationSource->getStream();
// Pick up statement
@ -1303,9 +1296,9 @@ static jrd_nod* par_field(thread_db* tdbb, CompilerScratch* csb, SSHORT blr_oper
if (csb->csb_g_flags & csb_get_dependencies)
{
if (blr_operator == blr_fid)
par_dependency(tdbb, csb, stream, id, "");
PAR_dependency(tdbb, csb, stream, id, "");
else
par_dependency(tdbb, csb, stream, id, name);
PAR_dependency(tdbb, csb, stream, id, name);
}
jrd_nod* node = PAR_gen_field(tdbb, stream, id);
@ -1434,43 +1427,6 @@ static jrd_nod* par_literal(thread_db* tdbb, CompilerScratch* csb)
}
static jrd_nod* par_map(thread_db* tdbb, CompilerScratch* csb, USHORT stream)
{
/**************************************
*
* p a r _ m a p
*
**************************************
*
* Functional description
* Parse a MAP clause for a union or global aggregate expression.
*
**************************************/
SET_TDBB(tdbb);
if (csb->csb_blr_reader.getByte() != blr_map)
PAR_syntax_error(csb, "blr_map");
SSHORT count = csb->csb_blr_reader.getWord();
NodeStack map;
while (--count >= 0)
{
jrd_nod* assignment = PAR_make_node(tdbb, e_asgn_length);
assignment->nod_type = nod_assignment;
assignment->nod_count = e_asgn_length;
assignment->nod_arg[e_asgn_to] = PAR_gen_field(tdbb, stream, csb->csb_blr_reader.getWord());
assignment->nod_arg[e_asgn_from] = PAR_parse_node(tdbb, csb, VALUE);
map.push(assignment);
}
jrd_nod* node = PAR_make_list(tdbb, map);
node->nod_type = nod_map;
return node;
}
static jrd_nod* par_message(thread_db* tdbb, CompilerScratch* csb)
{
/**************************************
@ -1651,64 +1607,6 @@ size_t PAR_name(CompilerScratch* csb, Firebird::string& name)
}
static jrd_nod* par_partition_by(thread_db* tdbb, CompilerScratch* csb)
{
/**************************************
*
* p a r _ p a r t i t i o n _ b y
*
**************************************
*
* Functional description
* Parse PARTITION BY subclauses of window functions.
*
**************************************/
SET_TDBB(tdbb);
if (csb->csb_blr_reader.getByte() != blr_partition_by)
PAR_syntax_error(csb, "blr_partition_by");
SSHORT context;
SSHORT partitionStream;
partitionStream = par_context(csb, &context);
jrd_nod* list = PAR_make_node(tdbb, e_part_length);
list->nod_type = nod_list;
list->nod_count = e_part_count;
const UCHAR count = csb->csb_blr_reader.getByte();
if (count != 0)
{
jrd_nod*& groupNode = list->nod_arg[e_part_group];
jrd_nod*& regroupNode = list->nod_arg[e_part_regroup];
groupNode = PAR_args(tdbb, csb, VALUE, count, count * 3);
regroupNode = PAR_args(tdbb, csb, VALUE, count, count);
// We have allocated groupNode with bigger length than expressions. This is to use in
// OPT_gen_sort. Now fill that info.
groupNode->nod_type = nod_sort;
for (unsigned i = 0; i < count; ++i)
{
groupNode->nod_arg[count + i] = (jrd_nod*)(IPTR) false; // ascending
groupNode->nod_arg[count * 2 + i] = (jrd_nod*)(IPTR) rse_nulls_first;
}
}
if (csb->csb_blr_reader.getByte() != blr_sort)
PAR_syntax_error(csb, "blr_sort");
list->nod_arg[e_part_order] = par_sort(tdbb, csb, true, true);
list->nod_arg[e_part_map] = par_map(tdbb, csb, partitionStream);
list->nod_arg[e_part_stream] = (jrd_nod*)(IPTR) partitionStream;
return list;
}
static jrd_nod* par_plan(thread_db* tdbb, CompilerScratch* csb)
{
/**************************************
@ -1762,17 +1660,23 @@ static jrd_nod* par_plan(thread_db* tdbb, CompilerScratch* csb)
// this would add a new context; while this is a reference to
// an existing context
jrd_nod* relation_node = par_relation(tdbb, csb, n, false);
RelationSourceNode* recSource = RelationSourceNode::parse(tdbb, csb, n, false);
jrd_nod* relation_node = PAR_make_node(tdbb, 1);
relation_node->nod_type = nod_class_recsrcnode_jrd;
relation_node->nod_count = 0;
relation_node->nod_arg[0] = (jrd_nod*) recSource;
plan->nod_arg[e_retrieve_relation] = relation_node;
jrd_rel* relation = (jrd_rel*) relation_node->nod_arg[e_rel_relation];
jrd_rel* relation = (jrd_rel*) recSource->relation;
n = csb->csb_blr_reader.getByte();
if (n >= csb->csb_rpt.getCount() || !(csb->csb_rpt[n].csb_flags & csb_used))
PAR_error(csb, Arg::Gds(isc_ctxnotdef));
const SSHORT stream = csb->csb_rpt[n].csb_stream;
relation_node->nod_arg[e_rel_stream] = (jrd_nod*) (IPTR) stream;
relation_node->nod_arg[e_rel_context] = (jrd_nod*) (IPTR) n;
recSource->setStream(stream);
recSource->context = n;
// Access plan types (sequential is default)
@ -1913,123 +1817,12 @@ static jrd_nod* par_plan(thread_db* tdbb, CompilerScratch* csb)
}
static jrd_nod* par_procedure(thread_db* tdbb, CompilerScratch* csb, SSHORT blr_operator)
void PAR_procedure_parms(thread_db* tdbb, CompilerScratch* csb, jrd_prc* procedure,
jrd_nod** message_ptr, jrd_nod** parameter_ptr, bool input_flag)
{
/**************************************
*
* p a r _ p r o c e d u r e
*
**************************************
*
* Functional description
* Parse an procedural view reference.
*
**************************************/
SET_TDBB(tdbb);
jrd_prc* procedure = NULL;
Firebird::string* alias_string = NULL;
QualifiedName name;
switch (blr_operator)
{
case blr_pid:
case blr_pid2:
{
const SSHORT pid = csb->csb_blr_reader.getWord();
if (blr_operator == blr_pid2)
{
alias_string = FB_NEW(csb->csb_pool) Firebird::string(csb->csb_pool);
PAR_name(csb, *alias_string);
}
if (!(procedure = MET_lookup_procedure_id(tdbb, pid, false, false, 0)))
{
name.identifier.printf("id %d", pid);
}
}
break;
case blr_procedure:
case blr_procedure2:
case blr_procedure3:
case blr_procedure4:
{
if (blr_operator == blr_procedure3 || blr_operator == blr_procedure4)
{
PAR_name(csb, name.package);
}
PAR_name(csb, name.identifier);
if (blr_operator == blr_procedure2 || blr_operator == blr_procedure4)
{
alias_string = FB_NEW(csb->csb_pool) Firebird::string(csb->csb_pool);
PAR_name(csb, *alias_string);
}
procedure = MET_lookup_procedure(tdbb, name, false);
}
break;
default:
fb_assert(false);
}
if (!procedure)
{
PAR_error(csb, Arg::Gds(isc_prcnotdef) << Arg::Str(name.toString()));
}
if (procedure->prc_type == prc_executable)
{
const string name = procedure->getName().toString();
if (tdbb->getAttachment()->att_flags & ATT_gbak_attachment)
{
PAR_warning(Arg::Warning(isc_illegal_prc_type) << Arg::Str(name));
}
else
{
PAR_error(csb, Arg::Gds(isc_illegal_prc_type) << Arg::Str(name));
}
}
jrd_nod* const node = PAR_make_node(tdbb, e_prc_length);
node->nod_type = nod_procedure;
node->nod_count = count_table[blr_procedure];
node->nod_arg[e_prc_procedure] = (jrd_nod*)(IPTR) procedure->getId();
SSHORT context;
const SSHORT stream = par_context(csb, &context);
node->nod_arg[e_prc_stream] = (jrd_nod*)(IPTR) stream;
node->nod_arg[e_prc_context] = (jrd_nod*)(IPTR) context;
csb->csb_rpt[stream].csb_procedure = procedure;
csb->csb_rpt[stream].csb_alias = alias_string;
par_procedure_parms(tdbb, csb, procedure, &node->nod_arg[e_prc_in_msg],
&node->nod_arg[e_prc_inputs], true);
if (csb->csb_g_flags & csb_get_dependencies)
{
par_dependency(tdbb, csb, stream, (SSHORT) -1, "");
}
return node;
}
static void par_procedure_parms(thread_db* tdbb,
CompilerScratch* csb,
jrd_prc* procedure,
jrd_nod** message_ptr,
jrd_nod** parameter_ptr, bool input_flag)
{
/**************************************
*
* p a r _ p r o c e d u r e _ p a r m s
* P A R _ p r o c e d u r e _ p a r m s
*
**************************************
*
@ -2138,125 +1931,6 @@ static void par_procedure_parms(thread_db* tdbb,
}
static jrd_nod* par_relation(thread_db* tdbb,
CompilerScratch* csb, SSHORT blr_operator, bool parse_context)
{
/**************************************
*
* p a r _ r e l a t i o n
*
**************************************
*
* Functional description
* Parse a relation reference.
*
**************************************/
SET_TDBB(tdbb);
// Find relation either by id or by name
jrd_rel* relation = NULL;
Firebird::string* alias_string = NULL;
Firebird::MetaName name;
switch (blr_operator)
{
case blr_rid:
case blr_rid2:
{
const SSHORT id = csb->csb_blr_reader.getWord();
if (blr_operator == blr_rid2)
{
alias_string = FB_NEW(csb->csb_pool) Firebird::string(csb->csb_pool);
PAR_name(csb, *alias_string);
}
if (!(relation = MET_lookup_relation_id(tdbb, id, false)))
{
name.printf("id %d", id);
}
}
break;
case blr_relation:
case blr_relation2:
{
PAR_name(csb, name);
if (blr_operator == blr_relation2)
{
alias_string = FB_NEW(csb->csb_pool) Firebird::string(csb->csb_pool);
PAR_name(csb, *alias_string);
}
relation = MET_lookup_relation(tdbb, name);
}
break;
default:
fb_assert(false);
}
if (!relation)
{
PAR_error(csb, Arg::Gds(isc_relnotdef) << Arg::Str(name), false);
}
// Make a relation reference node
jrd_nod* const node = PAR_make_node(tdbb, e_rel_length);
node->nod_count = 0;
// if an alias was passed, store with the relation
if (alias_string)
{
node->nod_arg[e_rel_alias] =
(jrd_nod*) stringDup(*tdbb->getDefaultPool(), *alias_string);
}
// Scan the relation if it hasn't already been scanned for meta data
if ((!(relation->rel_flags & REL_scanned) || (relation->rel_flags & REL_being_scanned)) &&
((relation->rel_flags & REL_force_scan) || !(csb->csb_g_flags & csb_internal)))
{
relation->rel_flags &= ~REL_force_scan;
MET_scan_relation(tdbb, relation);
}
else if (relation->rel_flags & REL_sys_triggers)
{
MET_parse_sys_trigger(tdbb, relation);
}
// generate a stream for the relation reference, assuming it is a real reference
if (parse_context)
{
SSHORT context;
const SSHORT stream = par_context(csb, &context);
fb_assert(stream <= MAX_STREAMS);
node->nod_arg[e_rel_stream] = (jrd_nod*) (IPTR) stream;
node->nod_arg[e_rel_context] = (jrd_nod*) (IPTR) context;
csb->csb_rpt[stream].csb_relation = relation;
csb->csb_rpt[stream].csb_alias = alias_string;
if (csb->csb_g_flags & csb_get_dependencies)
{
par_dependency(tdbb, csb, stream, (SSHORT) -1, "");
}
}
else
{
delete alias_string;
}
node->nod_arg[e_rel_relation] = (jrd_nod*) relation;
return node;
}
jrd_nod* PAR_rse(thread_db* tdbb, CompilerScratch* csb, SSHORT rse_op)
{
/**************************************
@ -2272,21 +1946,20 @@ jrd_nod* PAR_rse(thread_db* tdbb, CompilerScratch* csb, SSHORT rse_op)
SET_TDBB(tdbb);
SSHORT count = (unsigned int) csb->csb_blr_reader.getByte();
RecordSelExpr* rse = (RecordSelExpr*) PAR_make_node(tdbb, count + rse_delta + 2);
rse->nod_count = 0;
rse->rse_count = count;
jrd_nod** ptr = rse->rse_relation;
RseNode* rse = FB_NEW(*tdbb->getDefaultPool()) RseNode(*tdbb->getDefaultPool());
while (--count >= 0)
{
// AB: Added TYPE_RSE for derived table support
*ptr++ = PAR_parse_node(tdbb, csb, RELATION); // TYPE_RSE);
//*ptr++ = PAR_parse_node(tdbb, csb, RELATION);
jrd_nod* node = PAR_parse_node(tdbb, csb, RELATION); // TYPE_RSE;
fb_assert(node->nod_type == nod_class_recsrcnode_jrd);
rse->rse_relations.add(reinterpret_cast<RecordSourceNode*>(node->nod_arg[0]));
}
while (true)
{
const UCHAR op = csb->csb_blr_reader.getByte();
switch (op)
{
case blr_boolean:
@ -2308,13 +1981,13 @@ jrd_nod* PAR_rse(thread_db* tdbb, CompilerScratch* csb, SSHORT rse_op)
case blr_sort:
if (rse_op == blr_rs_stream)
PAR_syntax_error(csb, "RecordSelExpr stream clause");
rse->rse_sorted = par_sort(tdbb, csb, true, false);
rse->rse_sorted = PAR_sort(tdbb, csb, true, false);
break;
case blr_project:
if (rse_op == blr_rs_stream)
PAR_syntax_error(csb, "RecordSelExpr stream clause");
rse->rse_projection = par_sort(tdbb, csb, false, false);
rse->rse_projection = PAR_sort(tdbb, csb, false, false);
break;
case blr_join_type:
@ -2336,7 +2009,7 @@ jrd_nod* PAR_rse(thread_db* tdbb, CompilerScratch* csb, SSHORT rse_op)
break;
case blr_writelock:
rse->nod_flags |= rse_writelock;
rse->flags |= RseNode::FLAG_WRITELOCK;
break;
default:
@ -2345,22 +2018,29 @@ jrd_nod* PAR_rse(thread_db* tdbb, CompilerScratch* csb, SSHORT rse_op)
// An outer join is only allowed when the stream count is 2
// and a boolean expression has been supplied
if (!rse->rse_jointype || (rse->rse_count == 2 && rse->rse_boolean))
if (!rse->rse_jointype || (rse->rse_relations.getCount() == 2 && rse->rse_boolean))
{
// Convert right outer joins to left joins to avoid
// RIGHT JOIN handling at lower engine levels
if (rse->rse_jointype == blr_right)
{
// Swap sub-streams
jrd_nod* temp = rse->rse_relation[0];
rse->rse_relation[0] = rse->rse_relation[1];
rse->rse_relation[1] = temp;
RecordSourceNode* temp = rse->rse_relations[0];
rse->rse_relations[0] = rse->rse_relations[1];
rse->rse_relations[1] = temp;
rse->rse_jointype = blr_left;
}
return (jrd_nod*) rse;
jrd_nod* node = PAR_make_node(tdbb, 1);
node->nod_type = nod_class_recsrcnode_jrd;
node->nod_count = 0;
node->nod_arg[0] = reinterpret_cast<jrd_nod*>(rse);
return node;
}
}
PAR_syntax_error(csb, (TEXT*)((rse_op == blr_rs_stream) ?
"RecordSelExpr stream clause" :
"record selection expression clause"));
@ -2369,11 +2049,11 @@ jrd_nod* PAR_rse(thread_db* tdbb, CompilerScratch* csb, SSHORT rse_op)
}
static jrd_nod* par_sort(thread_db* tdbb, CompilerScratch* csb, bool flag, bool nullForEmpty)
jrd_nod* PAR_sort(thread_db* tdbb, CompilerScratch* csb, bool flag, bool nullForEmpty)
{
/**************************************
*
* p a r _ s o r t
* P A R _ s o r t
*
**************************************
*
@ -2419,6 +2099,7 @@ static jrd_nod* par_sort(thread_db* tdbb, CompilerScratch* csb, bool flag, bool
*ptr2++ = (jrd_nod*) (IPTR) ((code == blr_descending) ? TRUE : FALSE);
}
*ptr++ = PAR_parse_node(tdbb, csb, VALUE);
}
@ -2426,55 +2107,6 @@ static jrd_nod* par_sort(thread_db* tdbb, CompilerScratch* csb, bool flag, bool
}
static jrd_nod* par_union(thread_db* tdbb, CompilerScratch* csb, bool recursive)
{
/**************************************
*
* p a r _ u n i o n
*
**************************************
*
* Functional description
* Parse a union reference.
*
**************************************/
SET_TDBB(tdbb);
// Make the node, parse the context number, get a stream assigned,
// and get the number of sub-RecordSelExpr's.
jrd_nod* node = PAR_make_node(tdbb, e_uni_length);
node->nod_count = 3;
const USHORT stream = par_context(csb, 0);
node->nod_arg[e_uni_stream] = (jrd_nod*) (IPTR) stream;
// assign separate context for mapped record if union is recursive
USHORT map_stream = stream;
if (recursive)
{
node->nod_flags |= nod_recurse;
map_stream = par_context(csb, 0);
node->nod_arg[e_uni_map_stream] = (jrd_nod*) (IPTR) map_stream;
}
SSHORT count = (unsigned int) csb->csb_blr_reader.getByte();
// Pick up the sub-RecordSelExpr's and maps
NodeStack clauses;
while (--count >= 0)
{
clauses.push(PAR_parse_node(tdbb, csb, TYPE_RSE));
clauses.push(par_map(tdbb, csb, map_stream));
}
node->nod_arg[e_uni_clauses] = PAR_make_list(tdbb, clauses);
return node;
}
jrd_nod* PAR_parse_node(thread_db* tdbb, CompilerScratch* csb, USHORT expected)
{
/**************************************
@ -2856,8 +2488,7 @@ jrd_nod* PAR_parse_node(thread_db* tdbb, CompilerScratch* csb, USHORT expected)
case blr_procedure2:
case blr_procedure3:
case blr_procedure4:
node = par_procedure(tdbb, csb, blr_operator);
set_type = false;
node->nod_arg[0] = (jrd_nod*) ProcedureSourceNode::parse(tdbb, csb, blr_operator);
break;
case blr_index:
@ -2909,56 +2540,38 @@ jrd_nod* PAR_parse_node(thread_db* tdbb, CompilerScratch* csb, USHORT expected)
case blr_singular:
node = PAR_parse_node(tdbb, csb, TYPE_RSE);
((RecordSelExpr*) node)->nod_flags |= rse_singular;
fb_assert(node->nod_type == nod_class_recsrcnode_jrd);
reinterpret_cast<RseNode*>(node->nod_arg[0])->flags |= RseNode::FLAG_SINGULAR;
break;
case blr_scrollable:
node = PAR_parse_node(tdbb, csb, TYPE_RSE);
((RecordSelExpr*) node)->nod_flags |= rse_scrollable;
fb_assert(node->nod_type == nod_class_recsrcnode_jrd);
reinterpret_cast<RseNode*>(node->nod_arg[0])->flags |= RseNode::FLAG_SCROLLABLE;
break;
case blr_relation:
case blr_rid:
case blr_relation2:
case blr_rid2:
node = par_relation(tdbb, csb, blr_operator, true);
node->nod_arg[0] = (jrd_nod*) RelationSourceNode::parse(tdbb, csb, blr_operator, true);
break;
case blr_union:
node = par_union(tdbb, csb, false);
break;
case blr_recurse:
node = par_union(tdbb, csb, true);
node->nod_arg[0] = (jrd_nod*) UnionSourceNode::parse(tdbb, csb, blr_operator);
break;
case blr_window:
{
node->nod_arg[e_win_rse] = PAR_parse_node(tdbb, csb, TYPE_RSE);
unsigned partitionCount = csb->csb_blr_reader.getByte();
NodeStack stack;
for (unsigned i = 0; i < partitionCount; ++i)
stack.push(par_partition_by(tdbb, csb));
node->nod_arg[e_win_windows] = PAR_make_list(tdbb, stack);
}
node->nod_arg[0] = (jrd_nod*) WindowSourceNode::parse(tdbb, csb);
break;
case blr_aggregate:
{
const USHORT stream = par_context(csb, NULL);
fb_assert(stream <= MAX_STREAMS);
node->nod_arg[e_agg_stream] = (jrd_nod*) (IPTR) stream;
node->nod_arg[e_agg_rse] = PAR_parse_node(tdbb, csb, TYPE_RSE);
node->nod_arg[e_agg_group] = PAR_parse_node(tdbb, csb, OTHER);
node->nod_arg[e_agg_map] = par_map(tdbb, csb, stream);
}
node->nod_arg[0] = (jrd_nod*) AggregateSourceNode::parse(tdbb, csb);
break;
case blr_group_by:
node = par_sort(tdbb, csb, false, false);
node = PAR_sort(tdbb, csb, false, false);
return node->nod_count ? node : NULL;
case blr_field:

View File

@ -52,6 +52,9 @@ Jrd::jrd_nod* PAR_args(Jrd::thread_db*, Jrd::CompilerScratch*, USHORT);
Jrd::jrd_nod* PAR_blr(Jrd::thread_db*, Jrd::jrd_rel*, const UCHAR*, ULONG blr_length,
Jrd::CompilerScratch*, Jrd::CompilerScratch**, Jrd::JrdStatement**, const bool,
USHORT);
SSHORT PAR_context(Jrd::CompilerScratch*, SSHORT*);
void PAR_dependency(Jrd::thread_db*, Jrd::CompilerScratch*, SSHORT, SSHORT,
const Firebird::MetaName&);
USHORT PAR_desc(Jrd::thread_db*, Jrd::CompilerScratch*, dsc*, Jrd::ItemInfo* = NULL);
void PAR_error(Jrd::CompilerScratch*, const Firebird::Arg::StatusVector&, bool isSyntaxError = true);
Jrd::jrd_nod* PAR_gen_field(Jrd::thread_db*, USHORT, USHORT);
@ -63,7 +66,10 @@ size_t PAR_name(Jrd::CompilerScratch* csb, Firebird::string& name);
Jrd::CompilerScratch* PAR_parse(Jrd::thread_db*, const UCHAR* blr, ULONG blr_length,
bool internal_flag, USHORT = 0, const UCHAR* = NULL);
void PAR_procedure_parms(Jrd::thread_db*, Jrd::CompilerScratch*, Jrd::jrd_prc*,
Jrd::jrd_nod**, Jrd::jrd_nod**, bool);
Jrd::jrd_nod* PAR_rse(Jrd::thread_db*, Jrd::CompilerScratch*, SSHORT);
Jrd::jrd_nod* PAR_sort(Jrd::thread_db*, Jrd::CompilerScratch*, bool, bool);
SLONG PAR_symbol_to_gdscode(const Firebird::string&);
typedef Jrd::DmlNode* (*NodeParseFunc)(Jrd::thread_db* tdbb, MemoryPool& pool,

View File

@ -47,8 +47,6 @@ namespace Jrd
class BaseBufferedStream;
class BufferedStream;
typedef Firebird::HalfStaticArray<UCHAR, OPT_STATIC_ITEMS> StreamsArray;
// Abstract base class
class RecordSource
@ -900,7 +898,7 @@ namespace Jrd
public:
Union(CompilerScratch* csb, UCHAR stream,
size_t argCount, RecordSource* const* args, jrd_nod* const* maps,
size_t argCount, RecordSource* const* args, NestConst<jrd_nod>* maps,
size_t streamCount, const UCHAR* streams);
void open(thread_db* tdbb) const;

View File

@ -35,7 +35,7 @@ using namespace Jrd;
// --------------------------
Union::Union(CompilerScratch* csb, UCHAR stream,
size_t argCount, RecordSource* const* args, jrd_nod* const* maps,
size_t argCount, RecordSource* const* args, NestConst<jrd_nod>* maps,
size_t streamCount, const UCHAR* streams)
: RecordStream(csb, stream), m_args(csb->csb_pool), m_maps(csb->csb_pool),
m_streams(csb->csb_pool)

View File

@ -163,25 +163,29 @@ static const VERB verbs[] =
PAIR(nod_and, blr_and, 2, 2, TYPE_BOOL, TYPE_BOOL),
PAIR(nod_or, blr_or, 2, 2, TYPE_BOOL, TYPE_BOOL),
PAIR(nod_not, blr_not, 1, 1, TYPE_BOOL, TYPE_BOOL),
PAIR(nod_rse, blr_rse, 0, 0, TYPE_RSE, OTHER),
PAIR(nod_class_recsrcnode_jrd, blr_rse, 0, 0, TYPE_RSE, OTHER),
PAIR(nod_map, blr_map, 0, 0, OTHER, OTHER),
PAIR(nod_union, blr_union, 0, 0, RELATION, OTHER),
PAIR(nod_union, blr_recurse, 0, 0, RELATION, OTHER),
PAIR(nod_aggregate, blr_aggregate, e_agg_length, 0, RELATION, OTHER),
PAIR(nod_relation, blr_relation, 0, 0, RELATION, OTHER),
PAIR(nod_relation, blr_rid, 0, 0, RELATION, OTHER),
PAIR(nod_rse, blr_rs_stream, 0, 0, RELATION, OTHER),
PAIR(nod_class_recsrcnode_jrd, blr_union, 1, 0, RELATION, OTHER),
PAIR(nod_class_recsrcnode_jrd, blr_recurse, 1, 0, RELATION, OTHER),
PAIR(nod_class_recsrcnode_jrd, blr_aggregate, 1, 0, RELATION, OTHER),
PAIR(nod_class_recsrcnode_jrd, blr_relation, 1, 0, RELATION, OTHER),
PAIR(nod_class_recsrcnode_jrd, blr_rid, 1, 0, RELATION, OTHER),
PAIR(nod_class_recsrcnode_jrd, blr_rs_stream, 0, 0, RELATION, OTHER),
PAIR(nod_exec_proc, blr_exec_proc, e_esp_length, 4, STATEMENT, OTHER),
PAIR(nod_procedure, blr_procedure, e_prc_length, 2, RELATION, OTHER),
PAIR(nod_procedure, blr_pid, e_prc_length, 2, RELATION, OTHER),
PAIR(nod_class_recsrcnode_jrd, blr_procedure, 1, 0, RELATION, OTHER),
PAIR(nod_class_recsrcnode_jrd, blr_procedure2, 1, 0, RELATION, OTHER),
PAIR(nod_class_recsrcnode_jrd, blr_procedure3, 1, 0, RELATION, OTHER),
PAIR(nod_class_recsrcnode_jrd, blr_procedure4, 1, 0, RELATION, OTHER),
PAIR(nod_class_recsrcnode_jrd, blr_pid, 1, 0, RELATION, OTHER),
PAIR(nod_class_recsrcnode_jrd, blr_pid2, 1, 0, RELATION, OTHER),
PAIR(nod_exec_proc, blr_exec_pid, e_esp_length, 4, STATEMENT, OTHER),
PAIR(nod_block, blr_block, e_blk_length, e_blk_length, STATEMENT, STATEMENT),
PAIR(nod_error_handler, blr_error_handler, e_err_length, 1, STATEMENT, OTHER),
PAIR(nod_class_stmtnode_jrd, blr_abort, 1, 0, STATEMENT, OTHER),
PAIR(nod_cast, blr_cast, e_cast_length, 1, VALUE, VALUE),
PAIR(nod_rse, blr_singular, 0, 0, TYPE_RSE, OTHER),
PAIR(nod_rse, blr_scrollable, 0, 0, TYPE_RSE, OTHER),
PAIR(nod_class_recsrcnode_jrd, blr_singular, 0, 0, TYPE_RSE, OTHER),
PAIR(nod_class_recsrcnode_jrd, blr_scrollable, 0, 0, TYPE_RSE, OTHER),
PAIR(nod_start_savepoint, blr_start_savepoint, 1, 0, STATEMENT, OTHER),
PAIR(nod_end_savepoint, blr_end_savepoint, 1, 0, STATEMENT, OTHER),
@ -193,8 +197,8 @@ static const VERB verbs[] =
PAIR(nod_indices, blr_indices, 1, 0, ACCESS_TYPE, VALUE),
PAIR(nod_retrieve, blr_retrieve, 2, 0, ACCESS_TYPE, VALUE),
PAIR(nod_relation, blr_relation2, 0, 0, RELATION, OTHER),
PAIR(nod_relation, blr_rid2, 0, 0, RELATION, OTHER),
PAIR(nod_class_recsrcnode_jrd, blr_relation2, 1, 0, RELATION, OTHER),
PAIR(nod_class_recsrcnode_jrd, blr_rid2, 1, 0, RELATION, OTHER),
PAIR2(nod_set_generator, blr_set_generator, e_gen_length, 1, STATEMENT, VALUE),
PAIR(nod_ansi_any, blr_ansi_any, e_any_length, 1, TYPE_BOOL, TYPE_RSE),
PAIR(nod_exists, blr_exists, e_any_length, 1, TYPE_BOOL, TYPE_RSE),
@ -222,7 +226,7 @@ static const VERB verbs[] =
PAIR(nod_similar, blr_similar, 3, 3, TYPE_BOOL, VALUE),
PAIR(nod_stmt_expr, blr_stmt_expr, e_stmt_expr_length, 2, VALUE, OTHER),
PAIR(nod_derived_expr, blr_derived_expr, e_derived_expr_length, e_derived_expr_count, VALUE, VALUE),
PAIR(nod_window, blr_window, e_agg_length, 0, RELATION, OTHER),
PAIR(nod_class_recsrcnode_jrd, blr_window, 1, 0, RELATION, OTHER),
PAIR(nod_continue_loop, blr_continue_loop, 1, 0, STATEMENT, OTHER),
PAIR(nod_class_exprnode_jrd, blr_agg_function, 1, 0, VALUE, VALUE),
PAIR(nod_class_exprnode_jrd, blr_substring_similar, 1, 0, VALUE, VALUE),