mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-02-02 10:00:38 +01:00
Fix #7696 - select from external procedure validates output parameters even when fetch method returns false.
This commit is contained in:
parent
04928a467a
commit
f628e52bb5
@ -279,8 +279,10 @@ namespace
|
||||
class MessageMoverNode : public CompoundStmtNode
|
||||
{
|
||||
public:
|
||||
MessageMoverNode(MemoryPool& pool, MessageNode* fromMessage, MessageNode* toMessage)
|
||||
: CompoundStmtNode(pool)
|
||||
MessageMoverNode(MemoryPool& pool, MessageNode* fromMessage, MessageNode* toMessage,
|
||||
MessageNode* aCheckMessageEof = nullptr)
|
||||
: CompoundStmtNode(pool),
|
||||
checkMessageEof(aCheckMessageEof)
|
||||
{
|
||||
// Iterate over the format items, except the EOF item.
|
||||
for (USHORT i = 0; i < (fromMessage->format->fmt_count / 2) * 2; i += 2)
|
||||
@ -314,6 +316,25 @@ namespace
|
||||
assign->asgnTo = param;
|
||||
}
|
||||
}
|
||||
|
||||
const StmtNode* execute(thread_db* tdbb, Request* request, ExeState* exeState) const override
|
||||
{
|
||||
if (checkMessageEof &&
|
||||
request->req_operation == Request::req_evaluate &&
|
||||
(request->req_flags & req_proc_select))
|
||||
{
|
||||
const auto msg = request->getImpure<UCHAR>(checkMessageEof->impureOffset);
|
||||
const auto eof = (SSHORT*) (msg + (IPTR) checkMessageEof->format->fmt_desc.back().dsc_address);
|
||||
|
||||
if (!*eof)
|
||||
request->req_operation = Request::req_return;
|
||||
}
|
||||
|
||||
return CompoundStmtNode::execute(tdbb, request, exeState);
|
||||
}
|
||||
|
||||
private:
|
||||
MessageNode* checkMessageEof;
|
||||
};
|
||||
|
||||
// External function node.
|
||||
@ -362,7 +383,8 @@ namespace
|
||||
{
|
||||
SuspendNode* suspend = FB_NEW_POOL(pool) SuspendNode(pool);
|
||||
suspend->message = intOutMessageNode;
|
||||
suspend->statement = FB_NEW_POOL(pool) MessageMoverNode(pool, extOutMessageNode, intOutMessageNode);
|
||||
suspend->statement = FB_NEW_POOL(pool) MessageMoverNode(pool,
|
||||
extOutMessageNode, intOutMessageNode, intOutMessageNode);
|
||||
|
||||
statements.add(suspend);
|
||||
statements.add(FB_NEW_POOL(pool) StallNode(pool));
|
||||
@ -381,34 +403,37 @@ namespace
|
||||
switch (request->req_operation)
|
||||
{
|
||||
case Request::req_evaluate:
|
||||
impure->sta_state = 0;
|
||||
*eof = 0;
|
||||
|
||||
fb_assert(!resultSet);
|
||||
resultSet = procedure->open(tdbb, extInMsg, extOutMsg);
|
||||
|
||||
if (!resultSet)
|
||||
{
|
||||
*eof = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
*eof = -1;
|
||||
// fall into
|
||||
|
||||
case Request::req_proceed:
|
||||
case Request::req_sync:
|
||||
*eof = 0;
|
||||
if (resultSet)
|
||||
{
|
||||
if (resultSet->fetch(tdbb) && (request->req_flags & req_proc_fetch))
|
||||
*eof = -1;
|
||||
else
|
||||
{
|
||||
*eof = 0;
|
||||
delete resultSet;
|
||||
resultSet = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
impure->sta_state = 0; // suspend node
|
||||
request->req_operation = Request::req_sync;
|
||||
|
||||
if (!*eof)
|
||||
request->req_operation = Request::req_return;
|
||||
else
|
||||
request->req_operation = Request::req_sync;
|
||||
|
||||
break;
|
||||
|
||||
case Request::req_unwind:
|
||||
|
@ -111,8 +111,8 @@ void ProcedureScan::internalOpen(thread_db* tdbb) const
|
||||
|
||||
// req_proc_fetch flag used only when fetching rows, so
|
||||
// is set at end of open()
|
||||
|
||||
proc_request->req_flags &= ~req_proc_fetch;
|
||||
AutoSetRestoreFlag<ULONG> autoSetReqProcSelect(&proc_request->req_flags, req_proc_select, true);
|
||||
|
||||
try
|
||||
{
|
||||
@ -197,6 +197,7 @@ bool ProcedureScan::internalGetRecord(thread_db* tdbb) const
|
||||
|
||||
TraceProcFetch trace(tdbb, proc_request);
|
||||
|
||||
AutoSetRestoreFlag<ULONG> autoSetReqProcSelect(&proc_request->req_flags, req_proc_select, true);
|
||||
AutoSetRestore<USHORT> autoOriginalTimeZone(
|
||||
&tdbb->getAttachment()->att_original_timezone,
|
||||
tdbb->getAttachment()->att_current_timezone);
|
||||
|
@ -537,10 +537,11 @@ const ULONG req_warning = 0x40L;
|
||||
const ULONG req_in_use = 0x80L;
|
||||
const ULONG req_continue_loop = 0x100L; // PSQL continue statement
|
||||
const ULONG req_proc_fetch = 0x200L; // Fetch from procedure in progress
|
||||
const ULONG req_same_tx_upd = 0x400L; // record was updated by same transaction
|
||||
const ULONG req_reserved = 0x800L; // Request reserved for client
|
||||
const ULONG req_update_conflict = 0x1000L; // We need to restart request due to update conflict
|
||||
const ULONG req_restart_ready = 0x2000L; // Request is ready to restart in case of update conflict
|
||||
const ULONG req_proc_select = 0x400L; // Select from procedure in progress
|
||||
const ULONG req_same_tx_upd = 0x800L; // record was updated by same transaction
|
||||
const ULONG req_reserved = 0x1000L; // Request reserved for client
|
||||
const ULONG req_update_conflict = 0x2000L; // We need to restart request due to update conflict
|
||||
const ULONG req_restart_ready = 0x4000L; // Request is ready to restart in case of update conflict
|
||||
|
||||
|
||||
// Index lock block
|
||||
|
Loading…
Reference in New Issue
Block a user