mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 06:43:04 +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)
|
if (flags & IStatement::PREPARE_PREFETCH_TYPE)
|
||||||
items.add(isc_info_sql_stmt_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)
|
if (flags & IStatement::PREPARE_PREFETCH_INPUT_PARAMETERS)
|
||||||
{
|
{
|
||||||
items.add(isc_info_sql_bind);
|
items.add(isc_info_sql_bind);
|
||||||
@ -100,6 +103,10 @@ unsigned StatementMetadata::buildInfoFlags(unsigned itemsLength, const UCHAR* it
|
|||||||
flags |= IStatement::PREPARE_PREFETCH_TYPE;
|
flags |= IStatement::PREPARE_PREFETCH_TYPE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case isc_info_sql_stmt_flags:
|
||||||
|
flags |= IStatement::PREPARE_PREFETCH_FLAGS;
|
||||||
|
break;
|
||||||
|
|
||||||
case isc_info_sql_get_plan:
|
case isc_info_sql_get_plan:
|
||||||
flags |= IStatement::PREPARE_PREFETCH_LEGACY_PLAN;
|
flags |= IStatement::PREPARE_PREFETCH_LEGACY_PLAN;
|
||||||
break;
|
break;
|
||||||
@ -137,6 +144,21 @@ unsigned StatementMetadata::getType()
|
|||||||
return type.value;
|
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.
|
// Get statement plan.
|
||||||
const char* StatementMetadata::getPlan(bool detailed)
|
const char* StatementMetadata::getPlan(bool detailed)
|
||||||
{
|
{
|
||||||
@ -227,6 +249,10 @@ void StatementMetadata::parse(unsigned bufferLength, const UCHAR* buffer)
|
|||||||
type = getNumericInfo(&buffer);
|
type = getNumericInfo(&buffer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case isc_info_sql_stmt_flags:
|
||||||
|
flags = getNumericInfo(&buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
case isc_info_sql_get_plan:
|
case isc_info_sql_get_plan:
|
||||||
case isc_info_sql_explain_plan:
|
case isc_info_sql_explain_plan:
|
||||||
{
|
{
|
||||||
|
@ -66,6 +66,7 @@ public:
|
|||||||
static unsigned buildInfoFlags(unsigned itemsLength, const UCHAR* items);
|
static unsigned buildInfoFlags(unsigned itemsLength, const UCHAR* items);
|
||||||
|
|
||||||
unsigned getType();
|
unsigned getType();
|
||||||
|
unsigned getFlags();
|
||||||
const char* getPlan(bool detailed);
|
const char* getPlan(bool detailed);
|
||||||
IMessageMetadata* getInputMetadata();
|
IMessageMetadata* getInputMetadata();
|
||||||
IMessageMetadata* getOutputMetadata();
|
IMessageMetadata* getOutputMetadata();
|
||||||
@ -81,7 +82,7 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
IStatement* statement;
|
IStatement* statement;
|
||||||
Nullable<unsigned> type;
|
Nullable<unsigned> type, flags;
|
||||||
string legacyPlan, detailedPlan;
|
string legacyPlan, detailedPlan;
|
||||||
RefPtr<Parameters> inputParameters, outputParameters;
|
RefPtr<Parameters> inputParameters, outputParameters;
|
||||||
};
|
};
|
||||||
|
@ -1713,6 +1713,7 @@ static void sql_info(thread_db* tdbb,
|
|||||||
{
|
{
|
||||||
ULONG length;
|
ULONG length;
|
||||||
USHORT number;
|
USHORT number;
|
||||||
|
ULONG value;
|
||||||
const UCHAR item = *items++;
|
const UCHAR item = *items++;
|
||||||
|
|
||||||
switch (item)
|
switch (item)
|
||||||
@ -1730,6 +1731,26 @@ static void sql_info(thread_db* tdbb,
|
|||||||
*info++ = item;
|
*info++ = item;
|
||||||
break;
|
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:
|
case isc_info_sql_stmt_type:
|
||||||
switch (statement->getType())
|
switch (statement->getType())
|
||||||
{
|
{
|
||||||
|
@ -151,12 +151,18 @@ public:
|
|||||||
static const unsigned PREPARE_PREFETCH_LEGACY_PLAN = 0x08;
|
static const unsigned PREPARE_PREFETCH_LEGACY_PLAN = 0x08;
|
||||||
static const unsigned PREPARE_PREFETCH_DETAILED_PLAN = 0x10;
|
static const unsigned PREPARE_PREFETCH_DETAILED_PLAN = 0x10;
|
||||||
static const unsigned PREPARE_PREFETCH_AFFECTED_RECORDS = 0x20; // not used yet
|
static const unsigned PREPARE_PREFETCH_AFFECTED_RECORDS = 0x20; // not used yet
|
||||||
|
static const unsigned PREPARE_PREFETCH_FLAGS = 0x40;
|
||||||
static const unsigned PREPARE_PREFETCH_METADATA =
|
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 =
|
static const unsigned PREPARE_PREFETCH_ALL =
|
||||||
PREPARE_PREFETCH_METADATA | PREPARE_PREFETCH_LEGACY_PLAN | PREPARE_PREFETCH_DETAILED_PLAN |
|
PREPARE_PREFETCH_METADATA | PREPARE_PREFETCH_LEGACY_PLAN | PREPARE_PREFETCH_DETAILED_PLAN |
|
||||||
PREPARE_PREFETCH_AFFECTED_RECORDS;
|
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,
|
virtual void FB_CARG getInfo(IStatus* status,
|
||||||
unsigned int itemsLength, const unsigned char* items,
|
unsigned int itemsLength, const unsigned char* items,
|
||||||
unsigned int bufferLength, unsigned char* buffer) = 0;
|
unsigned int bufferLength, unsigned char* buffer) = 0;
|
||||||
@ -171,8 +177,9 @@ public:
|
|||||||
FbMessage* in, IMessageMetadata* out) = 0;
|
FbMessage* in, IMessageMetadata* out) = 0;
|
||||||
virtual void FB_CARG setCursorName(IStatus* status, const char* name) = 0;
|
virtual void FB_CARG setCursorName(IStatus* status, const char* name) = 0;
|
||||||
virtual void FB_CARG free(IStatus* status) = 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
|
class IRequest : public IRefCounted
|
||||||
{
|
{
|
||||||
|
@ -190,6 +190,7 @@ public:
|
|||||||
virtual JResultSet* FB_CARG openCursor(Firebird::IStatus* status,
|
virtual JResultSet* FB_CARG openCursor(Firebird::IStatus* status,
|
||||||
Firebird::ITransaction* transaction, Firebird::FbMessage* in, Firebird::IMessageMetadata* out);
|
Firebird::ITransaction* transaction, Firebird::FbMessage* in, Firebird::IMessageMetadata* out);
|
||||||
virtual void FB_CARG setCursorName(Firebird::IStatus* status, const char* name);
|
virtual void FB_CARG setCursorName(Firebird::IStatus* status, const char* name);
|
||||||
|
virtual unsigned FB_CARG getFlags(Firebird::IStatus* status);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JStatement(dsql_req* handle, JAttachment* ja, Firebird::Array<UCHAR>& meta)
|
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_batch_fetch 24
|
||||||
#define isc_info_sql_relation_alias 25
|
#define isc_info_sql_relation_alias 25
|
||||||
#define isc_info_sql_explain_plan 26
|
#define isc_info_sql_explain_plan 26
|
||||||
|
#define isc_info_sql_stmt_flags 27
|
||||||
|
|
||||||
/*********************************/
|
/*********************************/
|
||||||
/* SQL information return values */
|
/* 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* JStatement::getPlan(IStatus* userStatus, FB_BOOLEAN detailed)
|
||||||
{
|
{
|
||||||
const char* ret = NULL;
|
const char* ret = NULL;
|
||||||
|
@ -291,6 +291,7 @@ public:
|
|||||||
FbMessage* inMsgBuffer, IMessageMetadata* outFormat);
|
FbMessage* inMsgBuffer, IMessageMetadata* outFormat);
|
||||||
virtual void FB_CARG setCursorName(IStatus* status, const char* name);
|
virtual void FB_CARG setCursorName(IStatus* status, const char* name);
|
||||||
virtual void FB_CARG free(IStatus* status);
|
virtual void FB_CARG free(IStatus* status);
|
||||||
|
virtual unsigned FB_CARG getFlags(IStatus* status);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Statement(Rsr* handle, Attachment* a, unsigned aDialect)
|
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)
|
const char* Statement::getPlan(IStatus* status, FB_BOOLEAN detailed)
|
||||||
{
|
{
|
||||||
try
|
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);
|
InternalMessageBuffer oMsgBuffer(out_blr_length, out_blr, out_msg_length, out_msg);
|
||||||
ITransaction* newTra = tra;
|
ITransaction* newTra = tra;
|
||||||
|
|
||||||
unsigned type = statement->rsr_iface->getType(&status_vector);
|
unsigned flags = statement->rsr_iface->getFlags(&status_vector);
|
||||||
if (!status_vector.isSuccess())
|
if (!status_vector.isSuccess())
|
||||||
{
|
{
|
||||||
status_exception::raise(status_vector.get());
|
status_exception::raise(status_vector.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((type == isc_info_sql_stmt_select || type == isc_info_sql_stmt_select_for_upd) &&
|
if ((flags & IStatement::STATEMENT_HAS_CURSOR) && (out_msg_length == 0))
|
||||||
out_msg_length == 0)
|
|
||||||
{
|
{
|
||||||
if (out_blr_length)
|
if (out_blr_length)
|
||||||
{
|
{
|
||||||
|
@ -325,6 +325,7 @@ public:
|
|||||||
Firebird::FbMessage* in, Firebird::IMessageMetadata* out);
|
Firebird::FbMessage* in, Firebird::IMessageMetadata* out);
|
||||||
virtual void FB_CARG setCursorName(Firebird::IStatus* status, const char* name);
|
virtual void FB_CARG setCursorName(Firebird::IStatus* status, const char* name);
|
||||||
virtual void FB_CARG free(Firebird::IStatus* status);
|
virtual void FB_CARG free(Firebird::IStatus* status);
|
||||||
|
virtual unsigned FB_CARG getFlags(Firebird::IStatus* status);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Firebird::Mutex cursorMutex;
|
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();
|
Arg::Gds(isc_dsql_cursor_open_err)).raise();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned type = statement->statement->getType(&status);
|
unsigned flags = statement->statement->getFlags(&status);
|
||||||
if (!status.isSuccess())
|
if (!status.isSuccess())
|
||||||
{
|
{
|
||||||
return status[1];
|
return status[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((type == isc_info_sql_stmt_select || type == isc_info_sql_stmt_select_for_upd) &&
|
if ((flags & IStatement::STATEMENT_HAS_CURSOR) && (outMsgLength == 0))
|
||||||
outMsgLength == 0)
|
|
||||||
{
|
{
|
||||||
if (outBlrLength)
|
if (outBlrLength)
|
||||||
{
|
{
|
||||||
@ -3852,6 +3851,22 @@ unsigned YStatement::getType(IStatus* status)
|
|||||||
return 0;
|
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)
|
const char* YStatement::getPlan(IStatus* status, FB_BOOLEAN detailed)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
Loading…
Reference in New Issue
Block a user