mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 00:03:02 +01:00
Add IStatement::getFlags() to help user make a solution what to do with SQL statement
This commit is contained in:
parent
7d58701c38
commit
ba9413b26a
@ -64,6 +64,9 @@ unsigned StatementMetadata::buildInfoItems(Array<UCHAR>& items, unsigned flags)
|
||||
if (flags & IStatement::PREPARE_PREFETCH_TYPE)
|
||||
items.add(isc_info_sql_stmt_type);
|
||||
|
||||
if (flags & IStatement::PREPARE_PREFETCH_FLAGS)
|
||||
items.add(isc_info_sql_stmt_flags);
|
||||
|
||||
if (flags & IStatement::PREPARE_PREFETCH_INPUT_PARAMETERS)
|
||||
{
|
||||
items.add(isc_info_sql_bind);
|
||||
@ -100,6 +103,10 @@ unsigned StatementMetadata::buildInfoFlags(unsigned itemsLength, const UCHAR* it
|
||||
flags |= IStatement::PREPARE_PREFETCH_TYPE;
|
||||
break;
|
||||
|
||||
case isc_info_sql_stmt_flags:
|
||||
flags |= IStatement::PREPARE_PREFETCH_FLAGS;
|
||||
break;
|
||||
|
||||
case isc_info_sql_get_plan:
|
||||
flags |= IStatement::PREPARE_PREFETCH_LEGACY_PLAN;
|
||||
break;
|
||||
@ -137,6 +144,21 @@ unsigned StatementMetadata::getType()
|
||||
return type.value;
|
||||
}
|
||||
|
||||
unsigned StatementMetadata::getFlags()
|
||||
{
|
||||
if (!flags.specified)
|
||||
{
|
||||
UCHAR info[] = {isc_info_sql_stmt_flags};
|
||||
UCHAR result[16];
|
||||
|
||||
getAndParse(sizeof(info), info, sizeof(result), result);
|
||||
|
||||
fb_assert(flags.specified);
|
||||
}
|
||||
|
||||
return flags.value;
|
||||
}
|
||||
|
||||
// Get statement plan.
|
||||
const char* StatementMetadata::getPlan(bool detailed)
|
||||
{
|
||||
@ -227,6 +249,10 @@ void StatementMetadata::parse(unsigned bufferLength, const UCHAR* buffer)
|
||||
type = getNumericInfo(&buffer);
|
||||
break;
|
||||
|
||||
case isc_info_sql_stmt_flags:
|
||||
flags = getNumericInfo(&buffer);
|
||||
break;
|
||||
|
||||
case isc_info_sql_get_plan:
|
||||
case isc_info_sql_explain_plan:
|
||||
{
|
||||
|
@ -66,6 +66,7 @@ public:
|
||||
static unsigned buildInfoFlags(unsigned itemsLength, const UCHAR* items);
|
||||
|
||||
unsigned getType();
|
||||
unsigned getFlags();
|
||||
const char* getPlan(bool detailed);
|
||||
IMessageMetadata* getInputMetadata();
|
||||
IMessageMetadata* getOutputMetadata();
|
||||
@ -81,7 +82,7 @@ private:
|
||||
|
||||
private:
|
||||
IStatement* statement;
|
||||
Nullable<unsigned> type;
|
||||
Nullable<unsigned> type, flags;
|
||||
string legacyPlan, detailedPlan;
|
||||
RefPtr<Parameters> inputParameters, outputParameters;
|
||||
};
|
||||
|
@ -1713,6 +1713,7 @@ static void sql_info(thread_db* tdbb,
|
||||
{
|
||||
ULONG length;
|
||||
USHORT number;
|
||||
ULONG value;
|
||||
const UCHAR item = *items++;
|
||||
|
||||
switch (item)
|
||||
@ -1730,6 +1731,26 @@ static void sql_info(thread_db* tdbb,
|
||||
*info++ = item;
|
||||
break;
|
||||
|
||||
case isc_info_sql_stmt_flags:
|
||||
value = IStatement::STATEMENT_REPEAT_EXECUTE;
|
||||
switch (statement->getType())
|
||||
{
|
||||
case DsqlCompiledStatement::TYPE_CREATE_DB:
|
||||
case DsqlCompiledStatement::TYPE_DDL:
|
||||
value &= ~IStatement::STATEMENT_REPEAT_EXECUTE;
|
||||
break;
|
||||
case DsqlCompiledStatement::TYPE_SELECT:
|
||||
case DsqlCompiledStatement::TYPE_SELECT_UPD:
|
||||
case DsqlCompiledStatement::TYPE_SELECT_BLOCK:
|
||||
value |= IStatement::STATEMENT_HAS_CURSOR;
|
||||
break;
|
||||
}
|
||||
length = put_vax_long(buffer, value);
|
||||
info = put_item(item, length, buffer, info, end_info);
|
||||
if (!info)
|
||||
return;
|
||||
break;
|
||||
|
||||
case isc_info_sql_stmt_type:
|
||||
switch (statement->getType())
|
||||
{
|
||||
|
@ -151,12 +151,18 @@ public:
|
||||
static const unsigned PREPARE_PREFETCH_LEGACY_PLAN = 0x08;
|
||||
static const unsigned PREPARE_PREFETCH_DETAILED_PLAN = 0x10;
|
||||
static const unsigned PREPARE_PREFETCH_AFFECTED_RECORDS = 0x20; // not used yet
|
||||
static const unsigned PREPARE_PREFETCH_FLAGS = 0x40;
|
||||
static const unsigned PREPARE_PREFETCH_METADATA =
|
||||
PREPARE_PREFETCH_TYPE | PREPARE_PREFETCH_INPUT_PARAMETERS | PREPARE_PREFETCH_OUTPUT_PARAMETERS;
|
||||
PREPARE_PREFETCH_TYPE | PREPARE_PREFETCH_FLAGS |
|
||||
PREPARE_PREFETCH_INPUT_PARAMETERS | PREPARE_PREFETCH_OUTPUT_PARAMETERS;
|
||||
static const unsigned PREPARE_PREFETCH_ALL =
|
||||
PREPARE_PREFETCH_METADATA | PREPARE_PREFETCH_LEGACY_PLAN | PREPARE_PREFETCH_DETAILED_PLAN |
|
||||
PREPARE_PREFETCH_AFFECTED_RECORDS;
|
||||
|
||||
// Statement flags.
|
||||
static const unsigned STATEMENT_HAS_CURSOR = 0x01;
|
||||
static const unsigned STATEMENT_REPEAT_EXECUTE = 0x02;
|
||||
|
||||
virtual void FB_CARG getInfo(IStatus* status,
|
||||
unsigned int itemsLength, const unsigned char* items,
|
||||
unsigned int bufferLength, unsigned char* buffer) = 0;
|
||||
@ -171,8 +177,9 @@ public:
|
||||
FbMessage* in, IMessageMetadata* out) = 0;
|
||||
virtual void FB_CARG setCursorName(IStatus* status, const char* name) = 0;
|
||||
virtual void FB_CARG free(IStatus* status) = 0;
|
||||
virtual unsigned FB_CARG getFlags(IStatus* status) = 0;
|
||||
};
|
||||
#define FB_STATEMENT_VERSION (FB_REFCOUNTED_VERSION + 10)
|
||||
#define FB_STATEMENT_VERSION (FB_REFCOUNTED_VERSION + 11)
|
||||
|
||||
class IRequest : public IRefCounted
|
||||
{
|
||||
|
@ -190,6 +190,7 @@ public:
|
||||
virtual JResultSet* FB_CARG openCursor(Firebird::IStatus* status,
|
||||
Firebird::ITransaction* transaction, Firebird::FbMessage* in, Firebird::IMessageMetadata* out);
|
||||
virtual void FB_CARG setCursorName(Firebird::IStatus* status, const char* name);
|
||||
virtual unsigned FB_CARG getFlags(Firebird::IStatus* status);
|
||||
|
||||
public:
|
||||
JStatement(dsql_req* handle, JAttachment* ja, Firebird::Array<UCHAR>& meta)
|
||||
|
@ -390,6 +390,7 @@ enum info_db_provider
|
||||
#define isc_info_sql_batch_fetch 24
|
||||
#define isc_info_sql_relation_alias 25
|
||||
#define isc_info_sql_explain_plan 26
|
||||
#define isc_info_sql_stmt_flags 27
|
||||
|
||||
/*********************************/
|
||||
/* SQL information return values */
|
||||
|
@ -4573,6 +4573,37 @@ unsigned JStatement::getType(IStatus* userStatus)
|
||||
}
|
||||
|
||||
|
||||
unsigned JStatement::getFlags(IStatus* userStatus)
|
||||
{
|
||||
unsigned ret = 0;
|
||||
|
||||
try
|
||||
{
|
||||
EngineContextHolder tdbb(userStatus, this, FB_FUNCTION);
|
||||
check_database(tdbb);
|
||||
|
||||
try
|
||||
{
|
||||
ret = metadata.getFlags();
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
transliterateException(tdbb, ex, userStatus, "JStatement::getFlags");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
ex.stuffException(userStatus);
|
||||
return ret;
|
||||
}
|
||||
|
||||
successful_completion(userStatus);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
const char* JStatement::getPlan(IStatus* userStatus, FB_BOOLEAN detailed)
|
||||
{
|
||||
const char* ret = NULL;
|
||||
|
@ -291,6 +291,7 @@ public:
|
||||
FbMessage* inMsgBuffer, IMessageMetadata* outFormat);
|
||||
virtual void FB_CARG setCursorName(IStatus* status, const char* name);
|
||||
virtual void FB_CARG free(IStatus* status);
|
||||
virtual unsigned FB_CARG getFlags(IStatus* status);
|
||||
|
||||
public:
|
||||
Statement(Rsr* handle, Attachment* a, unsigned aDialect)
|
||||
@ -2405,6 +2406,32 @@ unsigned Statement::getType(IStatus* status)
|
||||
}
|
||||
|
||||
|
||||
unsigned Statement::getFlags(IStatus* status)
|
||||
{
|
||||
try
|
||||
{
|
||||
reset(status);
|
||||
|
||||
// Check and validate handles, etc.
|
||||
|
||||
CHECK_HANDLE(statement, isc_bad_req_handle);
|
||||
Rdb* rdb = statement->rsr_rdb;
|
||||
rem_port* port = rdb->rdb_port;
|
||||
RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
|
||||
|
||||
statement->raiseException();
|
||||
|
||||
return metadata.getFlags();
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
ex.stuffException(status);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const char* Statement::getPlan(IStatus* status, FB_BOOLEAN detailed)
|
||||
{
|
||||
try
|
||||
|
@ -2921,14 +2921,13 @@ ISC_STATUS rem_port::execute_statement(P_OP op, P_SQLDATA* sqldata, PACKET* send
|
||||
InternalMessageBuffer oMsgBuffer(out_blr_length, out_blr, out_msg_length, out_msg);
|
||||
ITransaction* newTra = tra;
|
||||
|
||||
unsigned type = statement->rsr_iface->getType(&status_vector);
|
||||
unsigned flags = statement->rsr_iface->getFlags(&status_vector);
|
||||
if (!status_vector.isSuccess())
|
||||
{
|
||||
status_exception::raise(status_vector.get());
|
||||
}
|
||||
|
||||
if ((type == isc_info_sql_stmt_select || type == isc_info_sql_stmt_select_for_upd) &&
|
||||
out_msg_length == 0)
|
||||
if ((flags & IStatement::STATEMENT_HAS_CURSOR) && (out_msg_length == 0))
|
||||
{
|
||||
if (out_blr_length)
|
||||
{
|
||||
|
@ -325,6 +325,7 @@ public:
|
||||
Firebird::FbMessage* in, Firebird::IMessageMetadata* out);
|
||||
virtual void FB_CARG setCursorName(Firebird::IStatus* status, const char* name);
|
||||
virtual void FB_CARG free(Firebird::IStatus* status);
|
||||
virtual unsigned FB_CARG getFlags(Firebird::IStatus* status);
|
||||
|
||||
public:
|
||||
Firebird::Mutex cursorMutex;
|
||||
|
@ -1961,14 +1961,13 @@ ISC_STATUS API_ROUTINE isc_dsql_execute2_m(ISC_STATUS* userStatus, FB_API_HANDLE
|
||||
Arg::Gds(isc_dsql_cursor_open_err)).raise();
|
||||
}
|
||||
|
||||
unsigned type = statement->statement->getType(&status);
|
||||
unsigned flags = statement->statement->getFlags(&status);
|
||||
if (!status.isSuccess())
|
||||
{
|
||||
return status[1];
|
||||
}
|
||||
|
||||
if ((type == isc_info_sql_stmt_select || type == isc_info_sql_stmt_select_for_upd) &&
|
||||
outMsgLength == 0)
|
||||
if ((flags & IStatement::STATEMENT_HAS_CURSOR) && (outMsgLength == 0))
|
||||
{
|
||||
if (outBlrLength)
|
||||
{
|
||||
@ -3852,6 +3851,22 @@ unsigned YStatement::getType(IStatus* status)
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned YStatement::getFlags(IStatus* status)
|
||||
{
|
||||
try
|
||||
{
|
||||
YEntry<YStatement> entry(status, this);
|
||||
|
||||
return entry.next()->getFlags(status);
|
||||
}
|
||||
catch (const Exception& e)
|
||||
{
|
||||
e.stuffException(status);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* YStatement::getPlan(IStatus* status, FB_BOOLEAN detailed)
|
||||
{
|
||||
try
|
||||
|
Loading…
Reference in New Issue
Block a user