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

Fixed invariants handling in independent subqueries (seems to be related to CORE-4497).

This commit is contained in:
dimitr 2015-08-31 15:11:06 +00:00
parent 74eeb4bbfa
commit fe24642bc2
8 changed files with 109 additions and 35 deletions

View File

@ -27,6 +27,7 @@
#include "../jrd/blr.h"
#include "../jrd/tra.h"
#include "../jrd/recsrc/RecordSource.h"
#include "../jrd/recsrc/Cursor.h"
#include "../jrd/Optimizer.h"
#include "../jrd/blb_proto.h"
#include "../jrd/cmp_proto.h"
@ -1636,7 +1637,7 @@ RseBoolNode::RseBoolNode(MemoryPool& pool, UCHAR aBlrOp, RecordSourceNode* aDsql
ownSavepoint(true),
dsqlRse(aDsqlRse),
rse(NULL),
rsb(NULL)
subQuery(NULL)
{
addChildNode(dsqlRse, rse);
}
@ -1663,7 +1664,7 @@ string RseBoolNode::internalPrint(NodePrinter& printer) const
NODE_PRINT(printer, ownSavepoint);
NODE_PRINT(printer, dsqlRse);
NODE_PRINT(printer, rse);
NODE_PRINT(printer, rsb);
NODE_PRINT(printer, subQuery);
return "RseBoolNode";
}
@ -1792,7 +1793,7 @@ void RseBoolNode::pass2Boolean2(thread_db* tdbb, CompilerScratch* csb)
if (nodFlags & FLAG_INVARIANT)
impureOffset = CMP_impure(csb, sizeof(impure_value));
rsb = CMP_post_rse(tdbb, csb, rse);
RecordSource* const rsb = CMP_post_rse(tdbb, csb, rse);
// for ansi ANY clauses (and ALL's, which are negated ANY's)
// the unoptimized boolean expression must be used, since the
@ -1806,6 +1807,8 @@ void RseBoolNode::pass2Boolean2(thread_db* tdbb, CompilerScratch* csb)
}
csb->csb_fors.add(rsb);
subQuery = FB_NEW(*tdbb->getDefaultPool()) SubQuery(rsb, rse->rse_invariants);
}
bool RseBoolNode::execute(thread_db* tdbb, jrd_req* request) const
@ -1833,13 +1836,13 @@ bool RseBoolNode::execute(thread_db* tdbb, jrd_req* request) const
StableCursorSavePoint savePoint(tdbb, request->req_transaction, ownSavepoint);
rsb->open(tdbb);
bool value = rsb->getRecord(tdbb);
subQuery->open(tdbb);
bool value = subQuery->fetch(tdbb);
if (blrOp == blr_unique && value)
value = !rsb->getRecord(tdbb);
value = !subQuery->fetch(tdbb);
rsb->close(tdbb);
subQuery->close(tdbb);
if (blrOp == blr_any || blrOp == blr_unique)
request->req_flags &= ~req_null;

View File

@ -28,7 +28,7 @@
namespace Jrd {
class RecordSource;
class SubQuery;
class BinaryBoolNode : public TypedNode<BoolExprNode, ExprNode::TYPE_BINARY_BOOL>
@ -207,7 +207,7 @@ public:
bool ownSavepoint;
NestConst<RecordSourceNode> dsqlRse;
NestConst<RseNode> rse;
NestConst<RecordSource> rsb;
NestConst<SubQuery> subQuery;
};

View File

@ -32,6 +32,7 @@
#include "../jrd/Function.h"
#include "../jrd/SysFunction.h"
#include "../jrd/recsrc/RecordSource.h"
#include "../jrd/recsrc/Cursor.h"
#include "../jrd/Optimizer.h"
#include "../jrd/recsrc/Cursor.h"
#include "../jrd/blb_proto.h"
@ -9105,7 +9106,7 @@ SubQueryNode::SubQueryNode(MemoryPool& pool, UCHAR aBlrOp, RecordSourceNode* aDs
dsqlRse(aDsqlRse),
value1(aValue1),
value2(aValue2),
rsb(NULL)
subQuery(NULL)
{
addChildNode(dsqlRse, rse);
addChildNode(value1, value1);
@ -9143,7 +9144,7 @@ string SubQueryNode::internalPrint(NodePrinter& printer) const
NODE_PRINT(printer, rse);
NODE_PRINT(printer, value1);
NODE_PRINT(printer, value2);
NODE_PRINT(printer, rsb);
NODE_PRINT(printer, subQuery);
return "SubQueryNode";
}
@ -9397,9 +9398,11 @@ ValueExprNode* SubQueryNode::pass2(thread_db* tdbb, CompilerScratch* csb)
// Finish up processing of record selection expressions.
rsb = CMP_post_rse(tdbb, csb, rse);
RecordSource* const rsb = CMP_post_rse(tdbb, csb, rse);
csb->csb_fors.add(rsb);
subQuery = FB_NEW(*tdbb->getDefaultPool()) SubQuery(rsb, rse->rse_invariants);
return this;
}
@ -9441,7 +9444,7 @@ dsc* SubQueryNode::execute(thread_db* tdbb, jrd_req* request) const
StableCursorSavePoint savePoint(tdbb, request->req_transaction,
blrOp == blr_via && ownSavepoint);
rsb->open(tdbb);
subQuery->open(tdbb);
SLONG count = 0;
double d;
@ -9451,13 +9454,13 @@ dsc* SubQueryNode::execute(thread_db* tdbb, jrd_req* request) const
{
case blr_count:
flag = 0;
while (rsb->getRecord(tdbb))
while (subQuery->fetch(tdbb))
++impure->vlu_misc.vlu_long;
break;
case blr_minimum:
case blr_maximum:
while (rsb->getRecord(tdbb))
while (subQuery->fetch(tdbb))
{
dsc* value = EVL_expr(tdbb, request, value1);
if (request->req_flags & req_null)
@ -9476,7 +9479,7 @@ dsc* SubQueryNode::execute(thread_db* tdbb, jrd_req* request) const
case blr_average: // total or average with dialect-1 semantics
case blr_total:
while (rsb->getRecord(tdbb))
while (subQuery->fetch(tdbb))
{
desc = EVL_expr(tdbb, request, value1);
if (request->req_flags & req_null)
@ -9511,7 +9514,7 @@ dsc* SubQueryNode::execute(thread_db* tdbb, jrd_req* request) const
break;
case blr_via:
if (rsb->getRecord(tdbb))
if (subQuery->fetch(tdbb))
desc = EVL_expr(tdbb, request, value1);
else
{
@ -9533,7 +9536,7 @@ dsc* SubQueryNode::execute(thread_db* tdbb, jrd_req* request) const
// Close stream, ignoring any error during it to keep the original error.
try
{
rsb->close(tdbb);
subQuery->close(tdbb);
request->req_flags &= ~req_null;
request->req_flags |= flag;
}
@ -9546,7 +9549,7 @@ dsc* SubQueryNode::execute(thread_db* tdbb, jrd_req* request) const
// Close stream and return value.
rsb->close(tdbb);
subQuery->close(tdbb);
request->req_flags &= ~req_null;
request->req_flags |= flag;

View File

@ -34,7 +34,7 @@ namespace Jrd {
class ItemInfo;
class DeclareVariableNode;
class RecordSource;
class SubQuery;
class RelationSourceNode;
class ValueListNode;
@ -1357,7 +1357,7 @@ public:
NestConst<RseNode> rse;
NestConst<ValueExprNode> value1;
NestConst<ValueExprNode> value2;
NestConst<RecordSource> rsb;
NestConst<SubQuery> subQuery;
};

View File

@ -213,6 +213,11 @@ public:
//// FIXME-PRINT:
}
void print(const Firebird::string&, const SubQuery&)
{
//// FIXME-PRINT:
}
void print(const Firebird::string&, const Cursor&)
{
//// FIXME-PRINT:

View File

@ -33,6 +33,7 @@ namespace Jrd {
class AggregateSort;
class CompilerScratch;
class SubQuery;
class Cursor;
class Node;
class NodePrinter;

View File

@ -31,6 +31,64 @@
using namespace Firebird;
using namespace Jrd;
namespace
{
bool validate(thread_db* tdbb)
{
const jrd_req* const request = tdbb->getRequest();
if (request->req_flags & req_abort)
return false;
if (!request->req_transaction)
return false;
return true;
}
}
// ---------------------
// SubQuery implementation
// ---------------------
SubQuery::SubQuery(const RecordSource* rsb, const VarInvariantArray* invariants)
: m_top(rsb), m_invariants(invariants)
{
fb_assert(m_top);
}
void SubQuery::open(thread_db* tdbb) const
{
// Initialize dependent invariants
if (m_invariants)
{
jrd_req* const request = tdbb->getRequest();
for (const ULONG* iter = m_invariants->begin(); iter < m_invariants->end(); iter++)
{
impure_value* const invariantImpure = request->getImpure<impure_value>(*iter);
invariantImpure->vlu_flags = 0;
}
}
m_top->open(tdbb);
}
void SubQuery::close(thread_db* tdbb) const
{
m_top->close(tdbb);
}
bool SubQuery::fetch(thread_db* tdbb) const
{
if (!validate(tdbb))
return false;
return m_top->getRecord(tdbb);
}
// ---------------------
// Cursor implementation
// ---------------------
@ -53,6 +111,7 @@ void Cursor::open(thread_db* tdbb) const
impure->irsb_state = BOS;
// Initialize dependent invariants
if (m_invariants)
{
for (const ULONG* iter = m_invariants->begin(); iter < m_invariants->end(); iter++)

View File

@ -24,6 +24,7 @@
#define JRD_CURSOR_H
#include "../common/classes/array.h"
#include "../common/classes/MetaName.h"
namespace Jrd
{
@ -31,6 +32,22 @@ namespace Jrd
class CompilerScratch;
class RecordSource;
// SubQuery class (simplified forward-only cursor)
class SubQuery
{
public:
SubQuery(const RecordSource* rsb, const VarInvariantArray* invariants);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool fetch(thread_db* tdbb) const;
private:
const RecordSource* const m_top;
const VarInvariantArray* const m_invariants;
};
// Cursor class (wrapper around the whole access tree)
class Cursor
@ -66,20 +83,6 @@ namespace Jrd
return m_top;
}
private:
bool validate(thread_db* tdbb) const
{
const jrd_req* const request = tdbb->getRequest();
if (request->req_flags & req_abort)
return false;
if (!request->req_transaction)
return false;
return true;
}
public:
Firebird::MetaName name; // optional name for explicit PSQL cursors