8
0
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:
alexpeshkoff 2013-02-19 11:20:49 +00:00
parent 7d58701c38
commit ba9413b26a
11 changed files with 139 additions and 9 deletions

View File

@ -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:
{

View File

@ -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;
};

View File

@ -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())
{

View File

@ -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
{

View File

@ -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)

View File

@ -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 */

View File

@ -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;

View File

@ -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

View File

@ -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)
{

View File

@ -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;

View File

@ -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