8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 12:43:03 +01:00

1) Make a new kind of Node (TransactionNode).

2) Make main parser statement return requests instead of nodes.
3) Some related cleanup (ddlData, ddlScratch).
4) Added dsqlPass to dsql_req and children, to get rid of ugly logic in prepareStatement.
This commit is contained in:
asfernandes 2012-02-25 19:56:37 +00:00
parent 1198014fcf
commit 8f46d9300e
9 changed files with 359 additions and 354 deletions

View File

@ -46,17 +46,19 @@ class VariableNode;
class DsqlCompilerScratch : public BlrWriter
{
public:
static const unsigned FLAG_IN_AUTO_TRANS_BLOCK = 0x001;
static const unsigned FLAG_RETURNING_INTO = 0x002;
static const unsigned FLAG_METADATA_SAVED = 0x004;
static const unsigned FLAG_PROCEDURE = 0x008;
static const unsigned FLAG_TRIGGER = 0x010;
static const unsigned FLAG_BLOCK = 0x020;
static const unsigned FLAG_RECURSIVE_CTE = 0x040;
static const unsigned FLAG_UPDATE_OR_INSERT = 0x080;
static const unsigned FLAG_MERGE = 0x100;
static const unsigned FLAG_FUNCTION = 0x200;
static const unsigned FLAG_SUB_ROUTINE = 0x400;
static const unsigned FLAG_IN_AUTO_TRANS_BLOCK = 0x0001;
static const unsigned FLAG_RETURNING_INTO = 0x0002;
static const unsigned FLAG_METADATA_SAVED = 0x0004;
static const unsigned FLAG_PROCEDURE = 0x0008;
static const unsigned FLAG_TRIGGER = 0x0010;
static const unsigned FLAG_BLOCK = 0x0020;
static const unsigned FLAG_RECURSIVE_CTE = 0x0040;
static const unsigned FLAG_UPDATE_OR_INSERT = 0x0080;
static const unsigned FLAG_MERGE = 0x0100;
static const unsigned FLAG_FUNCTION = 0x0200;
static const unsigned FLAG_SUB_ROUTINE = 0x0400;
static const unsigned FLAG_INTERNAL_REQUEST = 0x0800;
static const unsigned FLAG_AMBIGUOUS_STMT = 0x1000;
public:
DsqlCompilerScratch(MemoryPool& p, dsql_dbb* aDbb, jrd_tra* aTransaction,

View File

@ -225,6 +225,25 @@ public:
};
class TransactionNode : public Node
{
public:
explicit TransactionNode(MemoryPool& pool)
: Node(pool)
{
}
public:
virtual TransactionNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
Node::dsqlPass(dsqlScratch);
return this;
}
virtual void execute(thread_db* tdbb, dsql_req* request, jrd_tra** transaction) const = 0;
};
class DmlNode : public Node
{
public:
@ -239,7 +258,7 @@ public:
explicit DmlNode(MemoryPool& pool, Kind aKind)
: Node(pool),
kind(aKind)
kind(aKind)
{
}
@ -851,7 +870,6 @@ public:
{
TYPE_ASSIGNMENT,
TYPE_BLOCK,
TYPE_COMMIT_ROLLBACK,
TYPE_COMPOUND_STMT,
TYPE_CONTINUE_LEAVE,
TYPE_CURSOR_STMT,
@ -885,7 +903,6 @@ public:
TYPE_SAVEPOINT_ENCLOSE,
TYPE_SELECT,
TYPE_SET_GENERATOR,
TYPE_SET_TRANSACTION,
TYPE_STALL,
TYPE_STORE,
TYPE_SUSPEND,

View File

@ -91,10 +91,13 @@ Parser::~Parser()
}
Node* Parser::parse()
dsql_req* Parser::parse()
{
if (parseAux() != 0)
{
fb_assert(false);
return NULL;
}
transformString(lex.start, lex.end - lex.start, transformedString);

View File

@ -128,7 +128,7 @@ public:
~Parser();
public:
Node* parse();
dsql_req* parse();
const Firebird::string& getTransformedString() const
{
@ -283,7 +283,7 @@ private:
Firebird::string transformedString;
Firebird::GenericMap<Firebird::NonPooled<dsql_str*, StrMark> > strMarks;
bool stmt_ambiguous;
Node* DSQL_parse;
dsql_req* DSQL_parse;
// These value/posn are taken from the lexer
YYSTYPE yylval;

View File

@ -6776,42 +6776,8 @@ DmlNode* UserSavepointNode::parse(thread_db* /*tdbb*/, MemoryPool& pool, Compile
UserSavepointNode* UserSavepointNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
// ASF: It should never enter in this IF, because the grammar does not allow it.
if (dsqlScratch->flags & DsqlCompilerScratch::FLAG_BLOCK) // blocks, procedures and triggers
{
const char* cmd = NULL;
switch (command)
{
//case CMD_NOTHING:
case CMD_SET:
cmd = "SAVEPOINT";
break;
case CMD_RELEASE:
cmd = "RELEASE";
break;
case CMD_RELEASE_ONLY:
cmd = "RELEASE ONLY";
break;
case CMD_ROLLBACK:
cmd = "ROLLBACK";
break;
default:
cmd = "UNKNOWN";
fb_assert(false);
}
ERRD_post(
Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
// Token unknown
Arg::Gds(isc_token_err) <<
Arg::Gds(isc_random) << Arg::Str(cmd));
}
statement->setType(DsqlCompiledStatement::TYPE_SAVEPOINT);
fb_assert(!(dsqlScratch->flags & DsqlCompilerScratch::FLAG_BLOCK));
dsqlScratch->getStatement()->setType(DsqlCompiledStatement::TYPE_SAVEPOINT);
return this;
}
@ -7616,14 +7582,18 @@ SetTransactionNode* SetTransactionNode::dsqlPass(DsqlCompilerScratch* dsqlScratc
}
if (dsqlScratch->getBlrData().getCount() > 1) // 1 -> isc_tpb_version1
{
// Store DYN data in the statement.
dsqlScratch->getStatement()->setDdlData(dsqlScratch->getBlrData());
}
tpb.add(dsqlScratch->getBlrData().begin(), dsqlScratch->getBlrData().getCount());
return this;
}
void SetTransactionNode::execute(thread_db* tdbb, dsql_req* request, jrd_tra** transaction) const
{
JRD_start_transaction(tdbb, &request->req_transaction, request->req_dbb->dbb_attachment,
tpb.getCount(), tpb.begin());
*transaction = request->req_transaction;
}
// Generate tpb for table lock.
// If lock level is specified, it overrrides the transaction lock level.
void SetTransactionNode::genTableLock(DsqlCompilerScratch* dsqlScratch, const dsql_nod* tblLock,

View File

@ -159,7 +159,7 @@ public:
};
class CommitRollbackNode : public TypedNode<DsqlOnlyStmtNode, StmtNode::TYPE_COMMIT_ROLLBACK>
class CommitRollbackNode : public TransactionNode
{
public:
enum Command
@ -170,7 +170,7 @@ public:
public:
explicit CommitRollbackNode(MemoryPool& pool, Command aCommand, bool aRetain)
: TypedNode<DsqlOnlyStmtNode, StmtNode::TYPE_COMMIT_ROLLBACK>(pool),
: TransactionNode(pool),
command(aCommand),
retain(aRetain)
{
@ -200,8 +200,36 @@ public:
return this;
}
virtual void genBlr(DsqlCompilerScratch* dsqlScratch)
virtual void execute(thread_db* tdbb, dsql_req* request, jrd_tra** transaction) const
{
if (retain)
{
switch (command)
{
case CMD_COMMIT:
JRD_commit_retaining(tdbb, request->req_transaction);
break;
case CMD_ROLLBACK:
JRD_rollback_retaining(tdbb, request->req_transaction);
break;
}
}
else
{
switch (command)
{
case CMD_COMMIT:
JRD_commit_transaction(tdbb, request->req_transaction);
break;
case CMD_ROLLBACK:
JRD_rollback_transaction(tdbb, request->req_transaction);
break;
}
*transaction = NULL;
}
}
private:
@ -1432,7 +1460,7 @@ public:
};
class SetTransactionNode : public TypedNode<DsqlOnlyStmtNode, StmtNode::TYPE_SET_TRANSACTION>
class SetTransactionNode : public TransactionNode
{
public:
enum
@ -1445,7 +1473,8 @@ public:
public:
explicit SetTransactionNode(MemoryPool& pool)
: TypedNode<DsqlOnlyStmtNode, StmtNode::TYPE_SET_TRANSACTION>(pool)
: TransactionNode(pool),
tpb(pool)
{
}
@ -1457,9 +1486,7 @@ public:
virtual SetTransactionNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
virtual void genBlr(DsqlCompilerScratch* dsqlScratch)
{
}
virtual void execute(thread_db* tdbb, dsql_req* request, jrd_tra** transaction) const;
private:
void genTableLock(DsqlCompilerScratch* dsqlScratch, const dsql_nod* tblLock, USHORT lockLevel);
@ -1473,6 +1500,7 @@ public:
Nullable<bool> restartRequests;
Nullable<USHORT> lockTimeout;
Nullable<dsql_nod*> reserveList;
Firebird::UCharBuffer tpb;
};

View File

@ -115,57 +115,6 @@ namespace
isc_info_req_update_count, isc_info_req_delete_count,
isc_info_req_select_count, isc_info_req_insert_count
};
class DsqlDmlRequest : public dsql_req
{
public:
explicit DsqlDmlRequest(DsqlCompilerScratch* scratch)
: dsql_req(scratch)
{
}
virtual void execute(thread_db* tdbb, jrd_tra** traHandle,
ULONG inBlrLength, const UCHAR* inBlr, ULONG inMsgLength, const UCHAR* inMsg,
ULONG outBlrLength, const UCHAR* const outBlr, ULONG outMsgLength, UCHAR* outMsg,
bool singleton);
virtual void setCursor(thread_db* tdbb, const TEXT* name);
virtual ISC_STATUS fetch(thread_db* tdbb, ULONG blrLength, const UCHAR* blr,
ULONG msgLength, UCHAR* msgBuffer);
};
class DsqlDdlRequest : public dsql_req
{
public:
explicit DsqlDdlRequest(DsqlCompilerScratch* scratch, DdlNode* aNode)
: dsql_req(scratch),
node(aNode)
{
}
virtual void execute(thread_db* tdbb, jrd_tra** traHandle,
ULONG inBlrLength, const UCHAR* inBlr, ULONG inMsgLength, const UCHAR* inMsg,
ULONG outBlrLength, const UCHAR* const outBlr, ULONG outMsgLength, UCHAR* outMsg,
bool singleton);
private:
DdlNode* node;
};
class DsqlTransactionRequest : public dsql_req
{
public:
explicit DsqlTransactionRequest(DsqlCompilerScratch* scratch)
: dsql_req(scratch)
{
}
virtual void execute(thread_db* tdbb, jrd_tra** traHandle,
ULONG inBlrLength, const UCHAR* inBlr, ULONG inMsgLength, const UCHAR* inMsg,
ULONG outBlrLength, const UCHAR* const outBlr, ULONG outMsgLength, UCHAR* outMsg,
bool singleton);
};
} // namespace
@ -204,8 +153,10 @@ dsql_req* DSQL_allocate_statement(thread_db* tdbb, Jrd::Attachment* attachment)
DsqlCompilerScratch* scratch = FB_NEW(pool) DsqlCompilerScratch(pool, database,
NULL, statement);
dsql_req* const request = FB_NEW(pool) DsqlDmlRequest(scratch);
dsql_req* const request = FB_NEW(pool) DsqlDmlRequest(pool, NULL);
request->req_dbb = database;
request->req_transaction = scratch->getTransaction();
request->statement = scratch->getStatement();
return request;
}
@ -754,14 +705,108 @@ void DSQL_execute_immediate(thread_db* tdbb, Jrd::Attachment* attachment, jrd_tr
}
void DsqlDmlRequest::dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch,
ntrace_result_t* traceResult)
{
node = Node::doDsqlPass(scratch, node);
if (scratch->clientDialect > SQL_DIALECT_V5)
scratch->getStatement()->addFlags(DsqlCompiledStatement::FLAG_BLR_VERSION5);
else
scratch->getStatement()->addFlags(DsqlCompiledStatement::FLAG_BLR_VERSION4);
GEN_request(scratch, node);
// Create the messages buffers
for (size_t i = 0; i < scratch->ports.getCount(); ++i)
{
dsql_msg* message = scratch->ports[i];
// Allocate buffer for message
const ULONG newLen = message->msg_length + FB_DOUBLE_ALIGN - 1;
message->msg_buffer_number = req_msg_buffers.getCount();
req_msg_buffers.grow(message->msg_buffer_number + 1);
UCHAR*& msgBuffer = req_msg_buffers[message->msg_buffer_number];
fb_assert(!msgBuffer);
msgBuffer = FB_NEW(*tdbb->getDefaultPool()) UCHAR[newLen];
msgBuffer = (UCHAR*) FB_ALIGN((U_IPTR) msgBuffer, FB_DOUBLE_ALIGN);
}
// have the access method compile the statement
#ifdef DSQL_DEBUG
if (DSQL_debug & 64)
{
dsql_trace("Resulting BLR code for DSQL:");
gds__trace_raw("Statement:\n");
gds__trace_raw(statement->getSqlText()->c_str(), statement->getSqlText()->length());
gds__trace_raw("\nBLR:\n");
fb_print_blr(scratch->getBlrData().begin(),
(ULONG) scratch->getBlrData().getCount(),
gds__trace_printer, 0, 0);
}
#endif
ISC_STATUS_ARRAY localStatus;
MOVE_CLEAR(localStatus, sizeof(localStatus));
// check for warnings
if (tdbb->tdbb_status_vector[2] == isc_arg_warning)
{
// save a status vector
memcpy(localStatus, tdbb->tdbb_status_vector, sizeof(ISC_STATUS_ARRAY));
}
ISC_STATUS status = FB_SUCCESS;
try
{
JRD_compile(tdbb, scratch->getAttachment()->dbb_attachment, &req_request,
scratch->getBlrData().getCount(), scratch->getBlrData().begin(),
statement->getSqlText(),
scratch->getDebugData().getCount(), scratch->getDebugData().begin(),
(scratch->flags & DsqlCompilerScratch::FLAG_INTERNAL_REQUEST));
}
catch (const Exception&)
{
status = tdbb->tdbb_status_vector[1];
*traceResult = (status == isc_no_priv ? res_unauthorized : res_failed);
}
// restore warnings (if there are any)
if (localStatus[2] == isc_arg_warning)
{
size_t indx, len, warning;
// find end of a status vector
PARSE_STATUS(tdbb->tdbb_status_vector, indx, warning);
if (indx)
--indx;
// calculate length of saved warnings
PARSE_STATUS(localStatus, len, warning);
len -= 2;
if ((len + indx - 1) < ISC_STATUS_LENGTH)
memcpy(&tdbb->tdbb_status_vector[indx], &localStatus[2], sizeof(ISC_STATUS) * len);
}
// free blr memory
scratch->getBlrData().free();
if (status)
status_exception::raise(tdbb->tdbb_status_vector);
}
// Execute a dynamic SQL statement.
void DsqlDmlRequest::execute(thread_db* tdbb, jrd_tra** traHandle,
ULONG inBlrLength, const UCHAR* inBlr, ULONG inMsgLength, const UCHAR* inMsg,
ULONG outBlrLength, const UCHAR* const outBlr, ULONG outMsgLength, UCHAR* outMsg,
bool singleton)
{
const DsqlCompiledStatement* statement = getStatement();
// If there is no data required, just start the request
const dsql_msg* message = statement->getSendMsg();
@ -894,6 +939,30 @@ void DsqlDmlRequest::execute(thread_db* tdbb, jrd_tra** traHandle,
trace.finish(have_cursor, res_successful);
}
void DsqlDdlRequest::dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch,
ntrace_result_t* traceResult)
{
this->scratch = scratch;
node = Node::doDsqlPass(scratch, node);
if (scratch->getAttachment()->dbb_read_only)
ERRD_post(Arg::Gds(isc_read_only_database));
if ((scratch->flags & DsqlCompilerScratch::FLAG_AMBIGUOUS_STMT) &&
scratch->getAttachment()->dbb_db_SQL_dialect != scratch->clientDialect)
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-817) <<
Arg::Gds(isc_ddl_not_allowed_by_db_sql_dial) <<
Arg::Num(scratch->getAttachment()->dbb_db_SQL_dialect));
}
if (scratch->clientDialect > SQL_DIALECT_V5)
scratch->getStatement()->addFlags(DsqlCompiledStatement::FLAG_BLR_VERSION5);
else
scratch->getStatement()->addFlags(DsqlCompiledStatement::FLAG_BLR_VERSION4);
}
// Execute a dynamic SQL statement.
void DsqlDdlRequest::execute(thread_db* tdbb, jrd_tra** traHandle,
ULONG inBlrLength, const UCHAR* inBlr, ULONG inMsgLength, const UCHAR* inMsg,
@ -902,14 +971,12 @@ void DsqlDdlRequest::execute(thread_db* tdbb, jrd_tra** traHandle,
{
TraceDSQLExecute trace(req_dbb->dbb_attachment, this);
const DsqlCompiledStatement* statement = getStatement();
fb_utils::init_status(tdbb->tdbb_status_vector);
// run all statements under savepoint control
{ // scope
AutoSavePoint savePoint(tdbb, req_transaction);
node->executeDdl(tdbb, statement->getDdlScratch(), req_transaction);
node->executeDdl(tdbb, scratch, req_transaction);
savePoint.release(); // everything is ok
}
@ -918,43 +985,20 @@ void DsqlDdlRequest::execute(thread_db* tdbb, jrd_tra** traHandle,
trace.finish(false, res_successful);
}
void DsqlTransactionRequest::dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch,
ntrace_result_t* /*traceResult*/)
{
node = Node::doDsqlPass(scratch, node);
}
// Execute a dynamic SQL statement.
void DsqlTransactionRequest::execute(thread_db* tdbb, jrd_tra** traHandle,
ULONG inBlrLength, const UCHAR* inBlr, ULONG inMsgLength, const UCHAR* inMsg,
ULONG outBlrLength, const UCHAR* const outBlr, ULONG outMsgLength, UCHAR* outMsg,
bool singleton)
{
const DsqlCompiledStatement* statement = getStatement();
switch (statement->getType())
{
case DsqlCompiledStatement::TYPE_START_TRANS:
JRD_start_transaction(tdbb, &req_transaction, req_dbb->dbb_attachment,
statement->getDdlData().getCount(), statement->getDdlData().begin());
*traHandle = req_transaction;
break;
case DsqlCompiledStatement::TYPE_COMMIT:
JRD_commit_transaction(tdbb, req_transaction);
*traHandle = NULL;
break;
case DsqlCompiledStatement::TYPE_COMMIT_RETAIN:
JRD_commit_retaining(tdbb, req_transaction);
break;
case DsqlCompiledStatement::TYPE_ROLLBACK:
JRD_rollback_transaction(tdbb, req_transaction);
*traHandle = NULL;
break;
case DsqlCompiledStatement::TYPE_ROLLBACK_RETAIN:
JRD_rollback_retaining(tdbb, req_transaction);
break;
default:
fb_assert(false);
}
node->execute(tdbb, this, traHandle);
}
@ -1535,6 +1579,9 @@ static dsql_req* prepareStatement(thread_db* tdbb, dsql_dbb* database, jrd_tra*
transaction, statement);
scratch->clientDialect = clientDialect;
if (isInternalRequest)
scratch->flags |= DsqlCompilerScratch::FLAG_INTERNAL_REQUEST;
dsql_req* request = NULL;
try
@ -1545,17 +1592,10 @@ static dsql_req* prepareStatement(thread_db* tdbb, dsql_dbb* database, jrd_tra*
scratch->getAttachment()->dbb_db_SQL_dialect, parserVersion, text, textLength,
tdbb->getAttachment()->att_charset);
Node* node = parser.parse();
request = parser.parse();
if (!node)
{
// CVC: Apparently, Parser::parse won't return if the command is incomplete,
// because yyerror() will call ERRD_post().
// This may be a special case, but we don't know about positions here.
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
// Unexpected end of command
Arg::Gds(isc_command_end_err));
}
if (parser.isStmtAmbiguous())
scratch->flags |= DsqlCompilerScratch::FLAG_AMBIGUOUS_STMT;
string transformedText = parser.getTransformedString();
SSHORT charSetId = database->dbb_attachment->att_charset;
@ -1602,161 +1642,24 @@ static dsql_req* prepareStatement(thread_db* tdbb, dsql_dbb* database, jrd_tra*
statement->setType(DsqlCompiledStatement::TYPE_SELECT);
node = Node::doDsqlPass(scratch, node);
fb_assert(node);
const DsqlCompiledStatement::Type statementType = statement->getType();
switch (statementType)
{
case DsqlCompiledStatement::TYPE_COMMIT:
case DsqlCompiledStatement::TYPE_COMMIT_RETAIN:
case DsqlCompiledStatement::TYPE_ROLLBACK:
case DsqlCompiledStatement::TYPE_ROLLBACK_RETAIN:
case DsqlCompiledStatement::TYPE_START_TRANS:
request = FB_NEW(statement->getPool()) DsqlTransactionRequest(scratch);
request->req_traced = false;
trace.setStatement(request);
return request; // Stop here for statements not requiring code generation.
case DsqlCompiledStatement::TYPE_CREATE_DB:
case DsqlCompiledStatement::TYPE_DDL:
if (scratch->getAttachment()->dbb_read_only)
ERRD_post(Arg::Gds(isc_read_only_database));
request = FB_NEW(statement->getPool()) DsqlDdlRequest(scratch,
static_cast<DdlNode*>(node));
break;
default:
request = FB_NEW(statement->getPool()) DsqlDmlRequest(scratch);
break;
}
request->req_traced = true;
trace.setStatement(request);
if (statementType == DsqlCompiledStatement::TYPE_DDL)
{
if (parser.isStmtAmbiguous() &&
scratch->getAttachment()->dbb_db_SQL_dialect != clientDialect)
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-817) <<
Arg::Gds(isc_ddl_not_allowed_by_db_sql_dial) <<
Arg::Num(scratch->getAttachment()->dbb_db_SQL_dialect));
}
statement->setDdlScratch(scratch);
}
if (clientDialect > SQL_DIALECT_V5)
statement->addFlags(DsqlCompiledStatement::FLAG_BLR_VERSION5);
else
statement->addFlags(DsqlCompiledStatement::FLAG_BLR_VERSION4);
if (!statement->isDdl())
GEN_request(scratch, static_cast<DmlNode*>(node));
// Create the messages buffers
for (size_t i = 0; i < scratch->ports.getCount(); ++i)
{
dsql_msg* message = scratch->ports[i];
// Allocate buffer for message
const ULONG newLen = message->msg_length + FB_DOUBLE_ALIGN - 1;
message->msg_buffer_number = request->req_msg_buffers.getCount();
request->req_msg_buffers.grow(message->msg_buffer_number + 1);
UCHAR*& msgBuffer = request->req_msg_buffers[message->msg_buffer_number];
fb_assert(!msgBuffer);
msgBuffer = FB_NEW(*tdbb->getDefaultPool()) UCHAR[newLen];
msgBuffer = (UCHAR*) FB_ALIGN((U_IPTR) msgBuffer, FB_DOUBLE_ALIGN);
}
// stop here for ddl statements
if (statementType == DsqlCompiledStatement::TYPE_CREATE_DB ||
statementType == DsqlCompiledStatement::TYPE_DDL)
{
// Notify Trace API manager about new DDL request cooked.
trace.prepare(res_successful);
return request;
}
// have the access method compile the statement
#ifdef DSQL_DEBUG
if (DSQL_debug & 64)
{
dsql_trace("Resulting BLR code for DSQL:");
gds__trace_raw("Statement:\n");
gds__trace_raw(text, textLength);
gds__trace_raw("\nBLR:\n");
fb_print_blr(scratch->getBlrData().begin(),
(ULONG) scratch->getBlrData().getCount(),
gds__trace_printer, 0, 0);
}
#endif
ISC_STATUS_ARRAY localStatus;
MOVE_CLEAR(localStatus, sizeof(localStatus));
// check for warnings
if (tdbb->tdbb_status_vector[2] == isc_arg_warning)
{
// save a status vector
memcpy(localStatus, tdbb->tdbb_status_vector, sizeof(ISC_STATUS_ARRAY));
}
ISC_STATUS status = FB_SUCCESS;
if (request->req_traced)
trace.setStatement(request);
ntrace_result_t traceResult = res_successful;
try
{
JRD_compile(tdbb,
scratch->getAttachment()->dbb_attachment,
&request->req_request,
scratch->getBlrData().getCount(),
scratch->getBlrData().begin(),
statement->getSqlText(),
scratch->getDebugData().getCount(),
scratch->getDebugData().begin(),
isInternalRequest);
request->req_dbb = scratch->getAttachment();
request->req_transaction = scratch->getTransaction();
request->statement = scratch->getStatement();
request->dsqlPass(tdbb, scratch, &traceResult);
}
catch (const Firebird::Exception&)
catch (const Exception&)
{
status = tdbb->tdbb_status_vector[1];
trace.prepare(status == isc_no_priv ? res_unauthorized : res_failed);
trace.prepare(traceResult);
throw;
}
// restore warnings (if there are any)
if (localStatus[2] == isc_arg_warning)
{
size_t indx, len, warning;
// find end of a status vector
PARSE_STATUS(tdbb->tdbb_status_vector, indx, warning);
if (indx)
--indx;
// calculate length of saved warnings
PARSE_STATUS(localStatus, len, warning);
len -= 2;
if ((len + indx - 1) < ISC_STATUS_LENGTH)
memcpy(&tdbb->tdbb_status_vector[indx], &localStatus[2], sizeof(ISC_STATUS) * len);
}
// free blr memory
scratch->getBlrData().free();
if (status)
Firebird::status_exception::raise(tdbb->tdbb_status_vector);
// Notify Trace API manager about new request cooked.
trace.prepare(res_successful);
trace.prepare(traceResult);
return request;
}
@ -1830,16 +1733,15 @@ static void release_statement(DsqlCompiledStatement* statement)
}
statement->setSqlText(NULL);
statement->getDdlData().free(); // free blr memory
}
dsql_req::dsql_req(DsqlCompilerScratch* scratch)
: req_pool(scratch->getStatement()->getPool()),
statement(scratch->getStatement()),
dsql_req::dsql_req(MemoryPool& pool)
: req_pool(pool),
statement(NULL),
cursors(req_pool),
req_dbb(scratch->getAttachment()),
req_transaction(scratch->getTransaction()),
req_dbb(NULL),
req_transaction(NULL),
req_msg_buffers(req_pool),
req_cursor(req_pool),
req_user_descs(req_pool),

View File

@ -71,6 +71,9 @@ namespace Jrd
class Attachment;
class Database;
class DsqlCompilerScratch;
class DdlNode;
class StmtNode;
class TransactionNode;
class jrd_tra;
class jrd_req;
class blb;
@ -427,7 +430,6 @@ public:
: PermanentStorage(p),
type(TYPE_SELECT),
flags(0),
ddlData(p),
sendMsg(NULL),
receiveMsg(NULL),
eof(NULL),
@ -435,8 +437,7 @@ public:
recVersion(NULL),
parentRecVersion(NULL),
parentDbKey(NULL),
parentRequest(NULL),
ddlScratch(NULL)
parentRequest(NULL)
{
}
@ -454,10 +455,6 @@ public:
const Firebird::RefStrPtr& getSqlText() const { return sqlText; }
void setSqlText(Firebird::RefString* value) { sqlText = value; }
Firebird::HalfStaticArray<UCHAR, 1024>& getDdlData() { return ddlData; }
const Firebird::HalfStaticArray<UCHAR, 1024>& getDdlData() const { return ddlData; }
void setDdlData(Firebird::HalfStaticArray<UCHAR, 1024>& value) { ddlData = value; }
bool isDdl() const
{
return type == TYPE_DDL || type == TYPE_CREATE_DB;
@ -494,14 +491,10 @@ public:
dsql_req* getParentRequest() const { return parentRequest; }
void setParentRequest(dsql_req* value) { parentRequest = value; }
DsqlCompilerScratch* getDdlScratch() const { return ddlScratch; }
void setDdlScratch(DsqlCompilerScratch* value) { ddlScratch = value; }
private:
Type type; // Type of statement
ULONG flags; // generic flag
Firebird::RefStrPtr sqlText;
Firebird::HalfStaticArray<UCHAR, 1024> ddlData;
dsql_msg* sendMsg; // Message to be sent to start request
dsql_msg* receiveMsg; // Per record message to be received
dsql_par* eof; // End of file parameter
@ -510,7 +503,6 @@ private:
dsql_par* parentRecVersion; // parent record version
dsql_par* parentDbKey; // Parent database key for current of
dsql_req* parentRequest; // Source request, if cursor update
DsqlCompilerScratch* ddlScratch; // DSQL scratch for DDL statements
};
class dsql_req : public pool_alloc<dsql_type_req>
@ -520,7 +512,7 @@ public:
static const unsigned FLAG_EMBEDDED = 0x02;
public:
explicit dsql_req(DsqlCompilerScratch* scratch);
explicit dsql_req(MemoryPool& pool);
public:
MemoryPool& getPool()
@ -538,6 +530,9 @@ public:
return statement;
}
virtual void dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch,
ntrace_result_t* traceResult) = 0;
virtual void execute(thread_db* tdbb, jrd_tra** traHandle,
ULONG inBlrLength, const UCHAR* inBlr, ULONG inMsgLength, const UCHAR* inMsg,
ULONG outBlrLength, const UCHAR* const outBlr, ULONG outMsgLength, UCHAR* outMsg,
@ -552,9 +547,9 @@ public:
private:
MemoryPool& req_pool;
const DsqlCompiledStatement* statement;
public:
const DsqlCompiledStatement* statement;
Firebird::Array<DsqlCompiledStatement*> cursors; // Cursor update statements
dsql_dbb* req_dbb; // DSQL attachment
@ -584,6 +579,79 @@ protected:
friend class Firebird::MemoryPool;
};
class DsqlDmlRequest : public dsql_req
{
public:
explicit DsqlDmlRequest(MemoryPool& pool, StmtNode* aNode)
: dsql_req(pool),
node(aNode)
{
req_traced = true;
}
virtual void dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch,
ntrace_result_t* traceResult);
virtual void execute(thread_db* tdbb, jrd_tra** traHandle,
ULONG inBlrLength, const UCHAR* inBlr, ULONG inMsgLength, const UCHAR* inMsg,
ULONG outBlrLength, const UCHAR* const outBlr, ULONG outMsgLength, UCHAR* outMsg,
bool singleton);
virtual void setCursor(thread_db* tdbb, const TEXT* name);
virtual ISC_STATUS fetch(thread_db* tdbb, ULONG blrLength, const UCHAR* blr,
ULONG msgLength, UCHAR* msgBuffer);
private:
StmtNode* node;
};
class DsqlDdlRequest : public dsql_req
{
public:
explicit DsqlDdlRequest(MemoryPool& pool, DdlNode* aNode)
: dsql_req(pool),
node(aNode),
scratch(NULL)
{
req_traced = true;
}
virtual void dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch,
ntrace_result_t* traceResult);
virtual void execute(thread_db* tdbb, jrd_tra** traHandle,
ULONG inBlrLength, const UCHAR* inBlr, ULONG inMsgLength, const UCHAR* inMsg,
ULONG outBlrLength, const UCHAR* const outBlr, ULONG outMsgLength, UCHAR* outMsg,
bool singleton);
private:
DdlNode* node;
DsqlCompilerScratch* scratch;
};
class DsqlTransactionRequest : public dsql_req
{
public:
explicit DsqlTransactionRequest(MemoryPool& pool, TransactionNode* aNode)
: dsql_req(pool),
node(aNode)
{
req_traced = false;
}
virtual void dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch,
ntrace_result_t* traceResult);
virtual void execute(thread_db* tdbb, jrd_tra** traHandle,
ULONG inBlrLength, const UCHAR* inBlr, ULONG inMsgLength, const UCHAR* inMsg,
ULONG outBlrLength, const UCHAR* const outBlr, ULONG outMsgLength, UCHAR* outMsg,
bool singleton);
private:
TransactionNode* node;
};
//! Implicit (NATURAL and USING) joins
class ImplicitJoin : public pool_alloc<dsql_type_imp_join>
{

View File

@ -645,6 +645,7 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
Jrd::BoolExprNode* boolExprNode;
Jrd::StmtNode* stmtNode;
Jrd::DdlNode* ddlNode;
Jrd::TransactionNode* traNode;
Jrd::CreateCollationNode* createCollationNode;
Jrd::CreateDomainNode* createDomainNode;
Jrd::AlterDomainNode* alterDomainNode;
@ -676,6 +677,7 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
Jrd::SetTransactionNode* setTransactionNode;
Jrd::DeclareSubProcNode* declareSubProcNode;
Jrd::DeclareSubFuncNode* declareSubFuncNode;
Jrd::dsql_req* dsqlReq;
}
%type <legacyNode> access_type alias_list
@ -712,10 +714,10 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
%type <legacyNode> column_constraint column_constraint_clause
%type <legacyNode> column_constraint_def column_constraint_list column_def
%type <boolVal> check_opt
%type <legacyNode> column_list column_name column_parens column_parens_opt column_select
%type <legacyNode> column_singleton
%type <stmtNode> commit complex_proc_statement
%type <traNode> commit
%type <stmtNode> complex_proc_statement
%type <legacyNode> computed_by computed_clause constant constraint_index_opt
%type <boolVal> conditional
%type <legacyNode> constraint_name_opt correlation_name
@ -744,6 +746,8 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
%type <ddlNode> declare declare_clause drop drop_clause
%type <legacyStr> db_name ddl_desc
%type db_alter_clause(<alterDatabaseNode>)
%type <ddlNode> ddl_statement
%type <stmtNode> dml_statement
%type <legacyNode> event_argument_opt
%type <ddlNode> exception_clause
@ -851,7 +855,7 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
%type <ddlNode> revoke rexception_clause
%type <legacyNode> role_admin_option role_grantee role_grantee_list
%type <legacyNode> role_name role_name_list rows_clause
%type <stmtNode> rollback
%type <traNode> rollback
%type <ddlNode> role_clause rtable_clause
%type <ddlNode> rview_clause
%type <nullableIntVal> revoke_admin
@ -871,7 +875,7 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
%type <ddlNode> set_statistics
%type <legacyNode> simple_type simple_when_clause skip_clause
%type <uintVal> snap_shot
%type <node> statement
%type <dsqlReq> statement
%type <legacyNode> string_length_opt
%type <legacyNode> symbol_UDF_call_name symbol_UDF_name symbol_blob_subtype_name symbol_character_set_name
%type <legacyNode> symbol_collation_name symbol_column_name symbol_constraint_name symbol_cursor_name
@ -897,6 +901,7 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
%type tran_option(<setTransactionNode>) tran_option_list(<setTransactionNode>)
%type tran_option_list_opt(<setTransactionNode>)
%type <uintVal> time_precision_opt timestamp_precision_opt
%type <traNode> tra_statement
%type <legacyNode> u_constant u_numeric_constant udf_data_type
%type <createAlterFunctionNode> udf_decl_clause
@ -998,40 +1003,50 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
// list of possible statements
top
: statement
{ DSQL_parse = $1; }
| statement ';'
{ DSQL_parse = $1; }
: statement { DSQL_parse = $1; }
| statement ';' { DSQL_parse = $1; }
;
statement
: alter { $$ = $1; }
: dml_statement { $$ = newNode<DsqlDmlRequest>($1); }
| ddl_statement { $$ = newNode<DsqlDdlRequest>($1); }
| tra_statement { $$ = newNode<DsqlTransactionRequest>($1); }
;
dml_statement
// ASF: ALTER SEQUENCE is defined here cause it's treated as DML.
| ALTER SEQUENCE alter_sequence_clause { $$ = $3; }
| comment { $$ = $1; }
| commit { $$ = $1; }
| create { $$ = $1; }
| create_or_alter { $$ = $1; }
| declare { $$ = $1; }
: ALTER SEQUENCE alter_sequence_clause { $$ = $3; }
| delete { $$ = $1; }
| drop { $$ = $1; }
| grant { $$ = $1; }
| insert { $$ = $1; }
| merge { $$ = $1; }
| exec_procedure { $$ = $1; }
| exec_block { $$ = $1; }
| recreate { $$ = $1; }
| revoke { $$ = $1; }
| rollback { $$ = $1; }
| savepoint { $$ = $1; }
| select { $$ = $1; }
| set_transaction { $$ = $1; }
| set_generator { $$ = $1; }
| set_statistics { $$ = $1; }
| update { $$ = $1; }
| update_or_insert { $$ = $1; }
;
ddl_statement
: alter { $$ = $1; }
| comment { $$ = $1; }
| create { $$ = $1; }
| create_or_alter { $$ = $1; }
| declare { $$ = $1; }
| drop { $$ = $1; }
| grant { $$ = $1; }
| recreate { $$ = $1; }
| revoke { $$ = $1; }
| set_statistics { $$ = $1; }
;
tra_statement
: set_transaction { $$ = $1; }
| commit { $$ = $1; }
| rollback { $$ = $1; }
;
// GRANT statement