mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 22:03:03 +01:00
Add SET DEBUG OPTION DSQL_KEEP_BLR and remove Statement::PREPARE_KEEP_EXEC_PATH flag.
Make ISQL' SET EXEC_PATH_DISPLAY persistent between connections.
This commit is contained in:
parent
ee53a7c46b
commit
32c3cf573b
@ -169,6 +169,7 @@ static const TOK tokens[] =
|
||||
{TOK_DATEDIFF, "DATEDIFF", true},
|
||||
{TOK_DAY, "DAY", false},
|
||||
{TOK_DDL, "DDL", true},
|
||||
{TOK_DEBUG, "DEBUG", true},
|
||||
{TOK_DEC, "DEC", false},
|
||||
{TOK_DECFLOAT, "DECFLOAT", false},
|
||||
{TOK_DECIMAL, "DECIMAL", false},
|
||||
|
@ -76,7 +76,6 @@ public:
|
||||
transaction(aTransaction),
|
||||
statement(aStatement),
|
||||
flags(0),
|
||||
prepareFlags(0),
|
||||
nestingLevel(0),
|
||||
ports(p),
|
||||
relation(NULL),
|
||||
@ -268,7 +267,6 @@ private:
|
||||
|
||||
public:
|
||||
unsigned flags; // flags
|
||||
unsigned prepareFlags; // prepare flags (IStatement::PREPARE*)
|
||||
unsigned nestingLevel; // begin...end nesting level
|
||||
Firebird::Array<dsql_msg*> ports; // Port messages
|
||||
dsql_rel* relation; // relation created by this request (for DDL)
|
||||
|
@ -229,7 +229,6 @@ DdlNode* CreateAlterPackageNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
|
||||
itemScratch->clientDialect = dsqlScratch->clientDialect;
|
||||
itemScratch->flags |= DsqlCompilerScratch::FLAG_DDL;
|
||||
itemScratch->prepareFlags = dsqlScratch->prepareFlags;
|
||||
itemScratch->package = name;
|
||||
|
||||
switch ((*items)[i].type)
|
||||
@ -625,7 +624,6 @@ DdlNode* CreatePackageBodyNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
|
||||
itemScratch->clientDialect = dsqlScratch->clientDialect;
|
||||
itemScratch->flags |= DsqlCompilerScratch::FLAG_DDL;
|
||||
itemScratch->prepareFlags = dsqlScratch->prepareFlags;
|
||||
itemScratch->package = name;
|
||||
|
||||
switch ((*arrays[i])[j].type)
|
||||
|
@ -1725,7 +1725,6 @@ DeclareSubFuncNode* DeclareSubFuncNode::dsqlPass(DsqlCompilerScratch* dsqlScratc
|
||||
DsqlCompilerScratch::FLAG_FUNCTION |
|
||||
DsqlCompilerScratch::FLAG_SUB_ROUTINE |
|
||||
(dsqlScratch->flags & DsqlCompilerScratch::FLAG_DDL);
|
||||
blockScratch->prepareFlags = dsqlScratch->prepareFlags;
|
||||
|
||||
dsqlBlock = dsqlBlock->dsqlPass(blockScratch);
|
||||
|
||||
@ -2069,7 +2068,6 @@ DeclareSubProcNode* DeclareSubProcNode::dsqlPass(DsqlCompilerScratch* dsqlScratc
|
||||
DsqlCompilerScratch::FLAG_PROCEDURE |
|
||||
DsqlCompilerScratch::FLAG_SUB_ROUTINE |
|
||||
(dsqlScratch->flags & DsqlCompilerScratch::FLAG_DDL);
|
||||
blockScratch->prepareFlags = dsqlScratch->prepareFlags;
|
||||
|
||||
dsqlBlock = dsqlBlock->dsqlPass(blockScratch);
|
||||
|
||||
@ -8587,6 +8585,39 @@ void SetRoleNode::execute(thread_db* tdbb, dsql_req* request, jrd_tra** /*traHan
|
||||
//--------------------
|
||||
|
||||
|
||||
SetDebugOptionNode::SetDebugOptionNode(MemoryPool& pool, MetaName* aName, ExprNode* aValue)
|
||||
: SessionManagementNode(pool),
|
||||
name(pool, *aName),
|
||||
value(aValue)
|
||||
{
|
||||
}
|
||||
|
||||
void SetDebugOptionNode::execute(thread_db* tdbb, dsql_req* /*request*/, jrd_tra** /*traHandle*/) const
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
auto& debugOptions = tdbb->getAttachment()->getDebugOptions();
|
||||
|
||||
const auto literal = nodeAs<LiteralNode>(value);
|
||||
|
||||
if (!literal)
|
||||
{
|
||||
// This currently can happen with negative numbers.
|
||||
// Since it's not relevant for DSQL_KEEP_BLR, let's throw an error.
|
||||
ERR_post(Arg::Gds(isc_random) << "Invalid DEBUG option value");
|
||||
}
|
||||
|
||||
const auto litDesc = &literal->litDesc;
|
||||
|
||||
if (name == "DSQL_KEEP_BLR")
|
||||
debugOptions.setDsqlKeepBlr(MOV_get_boolean(litDesc));
|
||||
else
|
||||
ERR_post(Arg::Gds(isc_random) << "Invalid DEBUG option");
|
||||
}
|
||||
|
||||
|
||||
//--------------------
|
||||
|
||||
|
||||
SetDecFloatRoundNode::SetDecFloatRoundNode(MemoryPool& pool, MetaName* name)
|
||||
: SessionManagementNode(pool)
|
||||
{
|
||||
|
@ -1725,6 +1725,30 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class SetDebugOptionNode : public SessionManagementNode
|
||||
{
|
||||
public:
|
||||
SetDebugOptionNode(MemoryPool& pool, MetaName* aName, ExprNode* aValue);
|
||||
|
||||
public:
|
||||
virtual Firebird::string internalPrint(NodePrinter& printer) const
|
||||
{
|
||||
SessionManagementNode::internalPrint(printer);
|
||||
|
||||
NODE_PRINT(printer, name);
|
||||
NODE_PRINT(printer, value);
|
||||
|
||||
return "SetDebugOptionNode";
|
||||
}
|
||||
|
||||
virtual void execute(thread_db* tdbb, dsql_req* request, jrd_tra** traHandle) const;
|
||||
|
||||
private:
|
||||
MetaName name;
|
||||
ExprNode* value;
|
||||
};
|
||||
|
||||
|
||||
class SetDecFloatRoundNode : public SessionManagementNode
|
||||
{
|
||||
public:
|
||||
|
@ -82,8 +82,8 @@ using namespace Firebird;
|
||||
|
||||
static ULONG get_request_info(thread_db*, dsql_req*, ULONG, UCHAR*);
|
||||
static dsql_dbb* init(Jrd::thread_db*, Jrd::Attachment*);
|
||||
static dsql_req* prepareRequest(thread_db*, dsql_dbb*, jrd_tra*, ULONG, const TEXT*, USHORT, unsigned, bool);
|
||||
static dsql_req* prepareStatement(thread_db*, dsql_dbb*, jrd_tra*, ULONG, const TEXT*, USHORT, unsigned, bool);
|
||||
static dsql_req* prepareRequest(thread_db*, dsql_dbb*, jrd_tra*, ULONG, const TEXT*, USHORT, bool);
|
||||
static dsql_req* prepareStatement(thread_db*, dsql_dbb*, jrd_tra*, ULONG, const TEXT*, USHORT, bool);
|
||||
static UCHAR* put_item(UCHAR, const USHORT, const UCHAR*, UCHAR*, const UCHAR* const);
|
||||
static void release_statement(DsqlCompiledStatement* statement);
|
||||
static void sql_info(thread_db*, dsql_req*, ULONG, const UCHAR*, ULONG, UCHAR*);
|
||||
@ -406,7 +406,7 @@ dsql_req* DSQL_prepare(thread_db* tdbb,
|
||||
// Allocate a new request block and then prepare the request.
|
||||
|
||||
request = prepareRequest(tdbb, database, transaction, length, string, dialect,
|
||||
prepareFlags, isInternalRequest);
|
||||
isInternalRequest);
|
||||
|
||||
// Can not prepare a CREATE DATABASE/SCHEMA statement
|
||||
|
||||
@ -557,7 +557,7 @@ void DSQL_execute_immediate(thread_db* tdbb, Jrd::Attachment* attachment, jrd_tr
|
||||
try
|
||||
{
|
||||
request = prepareRequest(tdbb, database, *tra_handle, length, string, dialect,
|
||||
0, isInternalRequest);
|
||||
isInternalRequest);
|
||||
|
||||
const DsqlCompiledStatement* statement = request->getStatement();
|
||||
|
||||
@ -659,8 +659,7 @@ void DsqlDmlRequest::dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch, boo
|
||||
scratch->getBlrData().getCount(), scratch->getBlrData().begin(),
|
||||
statement->getSqlText(),
|
||||
scratch->getDebugData().getCount(), scratch->getDebugData().begin(),
|
||||
(scratch->flags & DsqlCompilerScratch::FLAG_INTERNAL_REQUEST),
|
||||
(scratch->prepareFlags & IStatement::PREPARE_KEEP_EXEC_PATH));
|
||||
(scratch->flags & DsqlCompilerScratch::FLAG_INTERNAL_REQUEST));
|
||||
}
|
||||
catch (const Exception&)
|
||||
{
|
||||
@ -1478,17 +1477,16 @@ static void checkD(IStatus* st)
|
||||
// Prepare a request for execution. Return SQL status code.
|
||||
// Note: caller is responsible for pool handling.
|
||||
static dsql_req* prepareRequest(thread_db* tdbb, dsql_dbb* database, jrd_tra* transaction,
|
||||
ULONG textLength, const TEXT* text, USHORT clientDialect, unsigned prepareFlags, bool isInternalRequest)
|
||||
ULONG textLength, const TEXT* text, USHORT clientDialect, bool isInternalRequest)
|
||||
{
|
||||
return prepareStatement(tdbb, database, transaction, textLength, text, clientDialect,
|
||||
prepareFlags, isInternalRequest);
|
||||
return prepareStatement(tdbb, database, transaction, textLength, text, clientDialect, isInternalRequest);
|
||||
}
|
||||
|
||||
|
||||
// Prepare a statement for execution. Return SQL status code.
|
||||
// Note: caller is responsible for pool handling.
|
||||
static dsql_req* prepareStatement(thread_db* tdbb, dsql_dbb* database, jrd_tra* transaction,
|
||||
ULONG textLength, const TEXT* text, USHORT clientDialect, unsigned prepareFlags, bool isInternalRequest)
|
||||
ULONG textLength, const TEXT* text, USHORT clientDialect, bool isInternalRequest)
|
||||
{
|
||||
Database* const dbb = tdbb->getDatabase();
|
||||
|
||||
@ -1548,7 +1546,6 @@ static dsql_req* prepareStatement(thread_db* tdbb, dsql_dbb* database, jrd_tra*
|
||||
|
||||
DsqlCompilerScratch* scratch = FB_NEW_POOL(*scratchPool) DsqlCompilerScratch(*scratchPool, database,
|
||||
transaction, statement);
|
||||
scratch->prepareFlags = prepareFlags;
|
||||
scratch->clientDialect = clientDialect;
|
||||
|
||||
if (isInternalRequest)
|
||||
|
@ -677,6 +677,10 @@ using namespace Firebird;
|
||||
%token <metaNamePtr> CLEAR
|
||||
%token <metaNamePtr> OLDEST
|
||||
|
||||
// tokens added for Firebird 4.0.1
|
||||
|
||||
%token <metaNamePtr> DEBUG
|
||||
|
||||
// precedence declarations for expression evaluation
|
||||
|
||||
%left OR
|
||||
@ -884,7 +888,8 @@ tra_statement
|
||||
|
||||
%type <mngNode> mng_statement
|
||||
mng_statement
|
||||
: set_decfloat_round { $$ = $1; }
|
||||
: set_debug_option { $$ = $1; }
|
||||
| set_decfloat_round { $$ = $1; }
|
||||
| set_decfloat_traps { $$ = $1; }
|
||||
| session_statement { $$ = $1; }
|
||||
| set_role { $$ = $1; }
|
||||
@ -5348,6 +5353,12 @@ set_role
|
||||
{ $$ = newNode<SetRoleNode>(); }
|
||||
;
|
||||
|
||||
%type <mngNode> set_debug_option
|
||||
set_debug_option
|
||||
: SET DEBUG OPTION valid_symbol_name '=' constant
|
||||
{ $$ = newNode<SetDebugOptionNode>($4, $6); }
|
||||
;
|
||||
|
||||
%type <setDecFloatRoundNode> set_decfloat_round
|
||||
set_decfloat_round
|
||||
: SET DECFLOAT ROUND valid_symbol_name
|
||||
@ -9040,6 +9051,7 @@ non_reserved_word
|
||||
| TOTALORDER
|
||||
| TRAPS
|
||||
| ZONE
|
||||
| DEBUG // added in FB 4.0.1
|
||||
;
|
||||
|
||||
%%
|
||||
|
@ -452,11 +452,6 @@ interface Statement : ReferenceCounted
|
||||
PREPARE_PREFETCH_METADATA | PREPARE_PREFETCH_LEGACY_PLAN | PREPARE_PREFETCH_DETAILED_PLAN |
|
||||
PREPARE_PREFETCH_AFFECTED_RECORDS;
|
||||
|
||||
// Keep the execution path information to be retrieved with getInfo and isc_info_sql_exec_path_*
|
||||
// Warning: this feature is very tied to engine internals and its usage is discouraged if you do
|
||||
// not understand very well how these internals are subject to change between versions.
|
||||
const uint PREPARE_KEEP_EXEC_PATH = 0x80;
|
||||
|
||||
// Statement flags.
|
||||
const uint FLAG_HAS_CURSOR = 0x01;
|
||||
const uint FLAG_REPEAT_EXECUTE = 0x02;
|
||||
|
@ -1718,7 +1718,6 @@ namespace Firebird
|
||||
static const unsigned PREPARE_PREFETCH_FLAGS = 0x40;
|
||||
static const unsigned PREPARE_PREFETCH_METADATA = IStatement::PREPARE_PREFETCH_TYPE | IStatement::PREPARE_PREFETCH_FLAGS | IStatement::PREPARE_PREFETCH_INPUT_PARAMETERS | IStatement::PREPARE_PREFETCH_OUTPUT_PARAMETERS;
|
||||
static const unsigned PREPARE_PREFETCH_ALL = IStatement::PREPARE_PREFETCH_METADATA | IStatement::PREPARE_PREFETCH_LEGACY_PLAN | IStatement::PREPARE_PREFETCH_DETAILED_PLAN | IStatement::PREPARE_PREFETCH_AFFECTED_RECORDS;
|
||||
static const unsigned PREPARE_KEEP_EXEC_PATH = 0x80;
|
||||
static const unsigned FLAG_HAS_CURSOR = 0x1;
|
||||
static const unsigned FLAG_REPEAT_EXECUTE = 0x2;
|
||||
static const unsigned CURSOR_TYPE_SCROLLABLE = 0x1;
|
||||
|
@ -1457,7 +1457,6 @@ type
|
||||
const PREPARE_PREFETCH_FLAGS = Cardinal($40);
|
||||
const PREPARE_PREFETCH_METADATA = Cardinal(IStatement.PREPARE_PREFETCH_TYPE or IStatement.PREPARE_PREFETCH_FLAGS or IStatement.PREPARE_PREFETCH_INPUT_PARAMETERS or IStatement.PREPARE_PREFETCH_OUTPUT_PARAMETERS);
|
||||
const PREPARE_PREFETCH_ALL = Cardinal(IStatement.PREPARE_PREFETCH_METADATA or IStatement.PREPARE_PREFETCH_LEGACY_PLAN or IStatement.PREPARE_PREFETCH_DETAILED_PLAN or IStatement.PREPARE_PREFETCH_AFFECTED_RECORDS);
|
||||
const PREPARE_KEEP_EXEC_PATH = Cardinal($80);
|
||||
const FLAG_HAS_CURSOR = Cardinal($1);
|
||||
const FLAG_REPEAT_EXECUTE = Cardinal($2);
|
||||
const CURSOR_TYPE_SCROLLABLE = Cardinal($1);
|
||||
|
@ -368,6 +368,7 @@ static processing_state drop_db();
|
||||
static processing_state edit(const TEXT* const*);
|
||||
static processing_state end_trans();
|
||||
static processing_state escape(const TEXT*);
|
||||
static processing_state execSetDebugCommand();
|
||||
static processing_state frontend(const TEXT*);
|
||||
static processing_state frontend_set(const char* cmd, const char* const* parms,
|
||||
const char* const* lparms, char* const bad_dialect_buf, bool& bad_dialect);
|
||||
@ -4790,6 +4791,27 @@ static processing_state escape(const TEXT* cmd)
|
||||
}
|
||||
|
||||
|
||||
static processing_state execSetDebugCommand()
|
||||
{
|
||||
if (!DB)
|
||||
return SKIP;
|
||||
|
||||
const char* stmt = setValues.ExecPathDisplay[0] ?
|
||||
"set debug option dsql_keep_blr = true" :
|
||||
"set debug option dsql_keep_blr = false";
|
||||
|
||||
DB->execute(fbStatus, nullptr, 0, stmt, isqlGlob.SQL_dialect, nullptr, nullptr, nullptr, nullptr);
|
||||
|
||||
if (setValues.ExecPathDisplay[0] && (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS))
|
||||
{
|
||||
STDERROUT("SET EXEC_PATH_DISPLAY is not supported in this connection.");
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
return SKIP;
|
||||
}
|
||||
|
||||
|
||||
static processing_state frontend(const TEXT* statement)
|
||||
{
|
||||
/**************************************
|
||||
@ -5357,7 +5379,10 @@ static processing_state frontend_set(const char* cmd, const char* const* parms,
|
||||
|
||||
case SetOptions::exec_path_display:
|
||||
ret = SKIP;
|
||||
if (strcmp(parms[2], "OFF") == 0)
|
||||
|
||||
if (!*parms[2])
|
||||
ret = ps_ERR;
|
||||
else if (strcmp(parms[2], "OFF") == 0)
|
||||
setValues.ExecPathDisplay[0] = 0;
|
||||
else
|
||||
{
|
||||
@ -5396,6 +5421,10 @@ static processing_state frontend_set(const char* cmd, const char* const* parms,
|
||||
ret = ps_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != ps_ERR)
|
||||
ret = execSetDebugCommand();
|
||||
|
||||
break;
|
||||
|
||||
case SetOptions::sql:
|
||||
@ -6100,6 +6129,9 @@ void ISQL_get_version(bool call_by_create_db)
|
||||
isqlGlob.db_SQL_dialect = global_dialect_spoken;
|
||||
else
|
||||
isqlGlob.db_SQL_dialect = SQL_DIALECT_V5;
|
||||
|
||||
if (setValues.ExecPathDisplay[0])
|
||||
execSetDebugCommand();
|
||||
}
|
||||
|
||||
|
||||
@ -6761,6 +6793,9 @@ static processing_state newdb(TEXT* dbname,
|
||||
}
|
||||
}
|
||||
|
||||
if (setValues.ExecPathDisplay[0])
|
||||
execSetDebugCommand();
|
||||
|
||||
global_Stmt = NULL;
|
||||
|
||||
return SKIP;
|
||||
@ -8852,8 +8887,7 @@ static processing_state process_statement(const TEXT* str2)
|
||||
}
|
||||
|
||||
global_Stmt = DB->prepare(fbStatus, prepare_trans, 0, str2, isqlGlob.SQL_dialect,
|
||||
Firebird::IStatement::PREPARE_PREFETCH_METADATA |
|
||||
(setValues.ExecPathDisplay[0] ? Firebird::IStatement::PREPARE_KEEP_EXEC_PATH : 0));
|
||||
Firebird::IStatement::PREPARE_PREFETCH_METADATA);
|
||||
if (failed())
|
||||
{
|
||||
if (isqlGlob.SQL_dialect == SQL_DIALECT_V6_TRANSITION && Input_file)
|
||||
|
@ -401,6 +401,23 @@ public:
|
||||
USHORT originalTimeZone = Firebird::TimeZoneUtil::GMT_ZONE;
|
||||
};
|
||||
|
||||
class DebugOptions
|
||||
{
|
||||
public:
|
||||
bool getDsqlKeepBlr() const
|
||||
{
|
||||
return dsqlKeepBlr;
|
||||
}
|
||||
|
||||
void setDsqlKeepBlr(bool value)
|
||||
{
|
||||
dsqlKeepBlr = value;
|
||||
}
|
||||
|
||||
private:
|
||||
bool dsqlKeepBlr = false;
|
||||
};
|
||||
|
||||
public:
|
||||
static Attachment* create(Database* dbb, JProvider* provider);
|
||||
static void destroy(Attachment* const attachment);
|
||||
@ -656,6 +673,11 @@ public:
|
||||
return att_initial_options.getBindings();
|
||||
}
|
||||
|
||||
DebugOptions& getDebugOptions()
|
||||
{
|
||||
return att_debug_options;
|
||||
}
|
||||
|
||||
void checkReplSetLock(thread_db* tdbb);
|
||||
void invalidateReplSet(thread_db* tdbb, bool broadcast);
|
||||
|
||||
@ -677,6 +699,7 @@ private:
|
||||
|
||||
Firebird::Array<JBatch*> att_batches;
|
||||
InitialOptions att_initial_options; // Initial session options
|
||||
DebugOptions att_debug_options;
|
||||
|
||||
Lock* att_repl_lock; // Replication set lock
|
||||
JProvider* att_provider; // Provider which created this attachment
|
||||
|
@ -2646,7 +2646,7 @@ JRequest* JAttachment::compileRequest(CheckStatusWrapper* user_status,
|
||||
try
|
||||
{
|
||||
jrd_req* request = NULL;
|
||||
JRD_compile(tdbb, getHandle(), &request, blr_length, blr, RefStrPtr(), 0, NULL, false, false);
|
||||
JRD_compile(tdbb, getHandle(), &request, blr_length, blr, RefStrPtr(), 0, NULL, false);
|
||||
stmt = request->getStatement();
|
||||
|
||||
trace.finish(request, ITracePlugin::RESULT_SUCCESS);
|
||||
@ -9189,8 +9189,7 @@ void JRD_compile(thread_db* tdbb,
|
||||
RefStrPtr ref_str,
|
||||
ULONG dbginfo_length,
|
||||
const UCHAR* dbginfo,
|
||||
bool isInternalRequest,
|
||||
bool preserveBlrData)
|
||||
bool isInternalRequest)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -9216,7 +9215,7 @@ void JRD_compile(thread_db* tdbb,
|
||||
|
||||
fb_assert(statement->blr.isEmpty());
|
||||
|
||||
if (preserveBlrData)
|
||||
if (attachment->getDebugOptions().getDsqlKeepBlr())
|
||||
statement->blr.insert(0, blr, blr_length);
|
||||
|
||||
*req_handle = request;
|
||||
|
@ -73,7 +73,7 @@ void JRD_start_transaction(Jrd::thread_db* tdbb, Jrd::jrd_tra** transaction,
|
||||
void JRD_unwind_request(Jrd::thread_db* tdbb, Jrd::jrd_req* request);
|
||||
void JRD_compile(Jrd::thread_db* tdbb, Jrd::Attachment* attachment, Jrd::jrd_req** req_handle,
|
||||
ULONG blr_length, const UCHAR* blr, Firebird::RefStrPtr,
|
||||
ULONG dbginfo_length, const UCHAR* dbginfo, bool isInternalRequest, bool preserveBlrData);
|
||||
ULONG dbginfo_length, const UCHAR* dbginfo, bool isInternalRequest);
|
||||
bool JRD_verify_database_access(const Firebird::PathName&);
|
||||
void JRD_shutdown_attachment(Jrd::Attachment* attachment);
|
||||
void JRD_shutdown_attachments(Jrd::Database* dbb);
|
||||
|
Loading…
Reference in New Issue
Block a user