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:
parent
74eeb4bbfa
commit
fe24642bc2
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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:
|
||||
|
@ -33,6 +33,7 @@ namespace Jrd {
|
||||
|
||||
class AggregateSort;
|
||||
class CompilerScratch;
|
||||
class SubQuery;
|
||||
class Cursor;
|
||||
class Node;
|
||||
class NodePrinter;
|
||||
|
@ -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++)
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user