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

Refactored the DSQL support of cursor statements, execute procedure and execute statement

This commit is contained in:
asfernandes 2010-12-23 18:42:06 +00:00
parent 6d92010735
commit 0b1fa97b4a
9 changed files with 608 additions and 827 deletions

View File

@ -48,6 +48,7 @@
#include "../jrd/rlck_proto.h"
#include "../jrd/tra_proto.h"
#include "../dsql/ddl_proto.h"
#include "../dsql/metd_proto.h"
#include "../jrd/vio_proto.h"
#include "../dsql/errd_proto.h"
#include "../dsql/gen_proto.h"
@ -704,9 +705,7 @@ static RegisterNode<CursorStmtNode> regCursorStmtNode(blr_cursor_stmt);
DmlNode* CursorStmtNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR /*blrOp*/)
{
CursorStmtNode* node = FB_NEW(pool) CursorStmtNode(pool);
node->cursorOp = csb->csb_blr_reader.getByte();
CursorStmtNode* node = FB_NEW(pool) CursorStmtNode(pool, csb->csb_blr_reader.getByte());
node->cursorNumber = csb->csb_blr_reader.getWord();
switch (node->cursorOp)
@ -735,6 +734,43 @@ DmlNode* CursorStmtNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratc
CursorStmtNode* CursorStmtNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
// Verify if we're in an autonomous transaction.
if (dsqlScratch->flags & DsqlCompilerScratch::FLAG_IN_AUTO_TRANS_BLOCK)
{
const char* stmt = NULL;
switch (cursorOp)
{
case blr_cursor_open:
stmt = "OPEN CURSOR";
break;
case blr_cursor_close:
stmt = "CLOSE CURSOR";
break;
case blr_cursor_fetch:
case blr_cursor_fetch_scroll:
stmt = "FETCH CURSOR";
break;
}
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-901) <<
Arg::Gds(isc_dsql_unsupported_in_auto_trans) << Arg::Str(stmt));
}
// Resolve the cursor.
cursorNumber = (USHORT)(IPTR) PASS1_cursor_name(dsqlScratch, dsqlName, NOD_CURSOR_EXPLICIT,
true)->nod_arg[Dsql::e_cur_number];
// Process a scroll node, if exists.
if (dsqlScrollExpr)
dsqlScrollExpr = PASS1_node(dsqlScratch, dsqlScrollExpr);
// Process an assignment node, if exists.
if (dsqlIntoStmt)
dsqlIntoStmt = PASS1_node(dsqlScratch, dsqlIntoStmt);
return this;
}
@ -745,6 +781,57 @@ void CursorStmtNode::print(string& text, Array<dsql_nod*>& /*nodes*/) const
void CursorStmtNode::genBlr(DsqlCompilerScratch* dsqlScratch)
{
dsqlScratch->appendUChar(blr_cursor_stmt);
dsqlScratch->appendUChar(cursorOp); // open, close, fetch [scroll]
dsqlScratch->appendUShort(cursorNumber);
if (cursorOp == blr_cursor_fetch_scroll)
{
dsqlScratch->appendUChar(scrollOp);
if (dsqlScrollExpr)
GEN_expr(dsqlScratch, dsqlScrollExpr);
else
dsqlScratch->appendUChar(blr_null);
}
dsql_nod* cursor = NULL;
for (DsqlNodStack::iterator itr(dsqlScratch->cursors); !cursor && itr.hasData(); ++itr)
{
if ((USHORT)(IPTR) itr.object()->nod_arg[Dsql::e_cur_number] == cursorNumber)
cursor = itr.object();
}
fb_assert(cursor);
// Assignment.
dsql_nod* listInto = dsqlIntoStmt;
if (listInto)
{
dsql_nod* list = cursor->nod_arg[Dsql::e_cur_rse]->nod_arg[Dsql::e_rse_items];
if (list->nod_count != listInto->nod_count)
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-313) <<
Arg::Gds(isc_dsql_count_mismatch));
}
dsqlScratch->appendUChar(blr_begin);
dsql_nod** ptr = list->nod_arg;
dsql_nod** end = ptr + list->nod_count;
dsql_nod** ptr_to = listInto->nod_arg;
while (ptr < end)
{
dsqlScratch->appendUChar(blr_assignment);
GEN_expr(dsqlScratch, *ptr++);
GEN_expr(dsqlScratch, *ptr_to++);
}
dsqlScratch->appendUChar(blr_end);
}
}
CursorStmtNode* CursorStmtNode::pass1(thread_db* tdbb, CompilerScratch* csb)
@ -1500,7 +1587,112 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr
ExecProcedureNode* ExecProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
return this;
dsql_prc* procedure = METD_get_procedure(dsqlScratch->getTransaction(), dsqlScratch, dsqlName);
if (!procedure)
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
Arg::Gds(isc_dsql_procedure_err) <<
Arg::Gds(isc_random) <<
Arg::Str(dsqlName.toString()));
}
if (!dsqlScratch->isPsql())
{
dsqlScratch->procedure = procedure;
dsqlScratch->getStatement()->setType(DsqlCompiledStatement::TYPE_EXEC_PROCEDURE);
}
ExecProcedureNode* node = FB_NEW(getPool()) ExecProcedureNode(getPool(), dsqlName);
if (node->dsqlName.package.isEmpty() && procedure->prc_name.package.hasData())
node->dsqlName.package = procedure->prc_name.package;
// Handle input parameters.
const USHORT count = dsqlInputs ? dsqlInputs->nod_count : 0;
if (count > procedure->prc_in_count || count < procedure->prc_in_count - procedure->prc_def_count)
ERRD_post(Arg::Gds(isc_prcmismat) << Arg::Str(dsqlName.toString()));
node->dsqlInputs = PASS1_node(dsqlScratch, dsqlInputs);
if (count)
{
// Initialize this stack variable, and make it look like a node.
AutoPtr<dsql_nod> desc_node(FB_NEW_RPT(*getDefaultMemoryPool(), 0) dsql_nod);
dsql_nod* const* ptr = node->dsqlInputs->nod_arg;
for (const dsql_fld* field = procedure->prc_inputs; *ptr; ++ptr, field = field->fld_next)
{
DEV_BLKCHK(field, dsql_type_fld);
DEV_BLKCHK(*ptr, dsql_type_nod);
MAKE_desc_from_field(&desc_node->nod_desc, field);
// PASS1_set_parameter_type(*ptr, &desc_node, false);
PASS1_set_parameter_type(dsqlScratch, *ptr, desc_node, false);
}
}
// Handle output parameters.
if (dsqlScratch->isPsql())
{
const USHORT outCount = dsqlOutputs ? dsqlOutputs->nod_count : 0;
if (outCount != procedure->prc_out_count)
ERRD_post(Arg::Gds(isc_prc_out_param_mismatch) << Arg::Str(dsqlName.toString()));
node->dsqlOutputs = PASS1_node(dsqlScratch, dsqlOutputs);
}
else
{
if (dsqlOutputs)
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
// Token unknown
Arg::Gds(isc_token_err) <<
Arg::Gds(isc_random) << Arg::Str("RETURNING_VALUES"));
}
node->dsqlOutputs = explodeOutputs(dsqlScratch, dsqlScratch->procedure);
}
return node;
}
// Generate a parameter list to correspond to procedure outputs.
dsql_nod* ExecProcedureNode::explodeOutputs(DsqlCompilerScratch* dsqlScratch, const dsql_prc* procedure)
{
DEV_BLKCHK(dsqlScratch, dsql_type_req);
DEV_BLKCHK(procedure, dsql_type_prc);
const SSHORT count = procedure->prc_out_count;
dsql_nod* node = MAKE_node(Dsql::nod_list, count);
dsql_nod** ptr = node->nod_arg;
for (const dsql_fld* field = procedure->prc_outputs; field; field = field->fld_next, ++ptr)
{
DEV_BLKCHK(field, dsql_type_fld);
DEV_BLKCHK(*ptr, dsql_type_nod);
ParameterNode* paramNode = FB_NEW(getPool()) ParameterNode(getPool());
dsql_nod* p_node = MAKE_node(Dsql::nod_class_exprnode, 1);
p_node->nod_count = 0;
p_node->nod_arg[0] = reinterpret_cast<dsql_nod*>(paramNode);
*ptr = p_node;
dsql_par* parameter = paramNode->dsqlParameter = MAKE_parameter(
dsqlScratch->getStatement()->getReceiveMsg(), true, true, 0, NULL);
paramNode->dsqlParameterIndex = parameter->par_index;
MAKE_desc_from_field(&parameter->par_desc, field);
parameter->par_name = parameter->par_alias = field->fld_name.c_str();
parameter->par_rel_name = procedure->prc_name.identifier.c_str();
parameter->par_owner_name = procedure->prc_owner.c_str();
}
return node;
}
void ExecProcedureNode::print(string& text, Array<dsql_nod*>& nodes) const
@ -1510,6 +1702,56 @@ void ExecProcedureNode::print(string& text, Array<dsql_nod*>& nodes) const
void ExecProcedureNode::genBlr(DsqlCompilerScratch* dsqlScratch)
{
const dsql_msg* message = NULL;
if (dsqlScratch->getStatement()->getType() == DsqlCompiledStatement::TYPE_EXEC_PROCEDURE)
{
if ((message = dsqlScratch->getStatement()->getReceiveMsg()))
{
dsqlScratch->appendUChar(blr_begin);
dsqlScratch->appendUChar(blr_send);
dsqlScratch->appendUChar(message->msg_number);
}
}
if (dsqlName.package.hasData())
{
dsqlScratch->appendUChar(blr_exec_proc2);
dsqlScratch->appendMetaString(dsqlName.package.c_str());
}
else
dsqlScratch->appendUChar(blr_exec_proc);
dsqlScratch->appendMetaString(dsqlName.identifier.c_str());
// Input parameters.
if (dsqlInputs)
{
dsqlScratch->appendUShort(dsqlInputs->nod_count);
dsql_nod** ptr = dsqlInputs->nod_arg;
const dsql_nod* const* end = ptr + dsqlInputs->nod_count;
while (ptr < end)
GEN_expr(dsqlScratch, *ptr++);
}
else
dsqlScratch->appendUShort(0);
// Output parameters.
if (dsqlOutputs)
{
dsqlScratch->appendUShort(dsqlOutputs->nod_count);
dsql_nod** ptr = dsqlOutputs->nod_arg;
const dsql_nod* const* end = ptr + dsqlOutputs->nod_count;
while (ptr < end)
GEN_expr(dsqlScratch, *ptr++);
}
else
dsqlScratch->appendUShort(0);
if (message)
dsqlScratch->appendUChar(blr_end);
}
ExecProcedureNode* ExecProcedureNode::pass1(thread_db* tdbb, CompilerScratch* csb)
@ -1677,6 +1919,7 @@ static RegisterNode<ExecStatementNode> regExecStatementStmt(blr_exec_stmt);
DmlNode* ExecStatementNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp)
{
ExecStatementNode* node = FB_NEW(pool) ExecStatementNode(pool);
node->traScope = EDS::traCommon;
switch (blrOp)
{
@ -1809,9 +2052,57 @@ DmlNode* ExecStatementNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr
return node;
}
ExecStatementNode* ExecStatementNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
StmtNode* ExecStatementNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
return this;
ExecStatementNode* node = FB_NEW(getPool()) ExecStatementNode(getPool());
node->dsqlSql = PASS1_node(dsqlScratch, dsqlSql);
node->dsqlInputs = PASS1_node(dsqlScratch, dsqlInputs);
node->inputNames = inputNames;
// Check params names uniqueness, if present.
if (node->inputNames)
{
const size_t count = node->inputNames->getCount();
StrArray names(*getDefaultMemoryPool(), count);
for (size_t i = 0; i != count; ++i)
{
const string* name = (*node->inputNames)[i];
size_t pos;
if (names.find(name->c_str(), pos))
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-637) <<
Arg::Gds(isc_dsql_duplicate_spec) << *name);
}
names.insert(pos, name->c_str());
}
}
node->dsqlOutputs = PASS1_node(dsqlScratch, dsqlOutputs);
if (dsqlInnerStmt)
{
++dsqlScratch->loopLevel;
node->dsqlLabel = PASS1_label2(dsqlScratch, NULL, dsqlLabel);
node->dsqlInnerStmt = PASS1_statement(dsqlScratch, dsqlInnerStmt);
--dsqlScratch->loopLevel;
dsqlScratch->labels.pop();
}
// Process various optional arguments.
node->dsqlDataSource = PASS1_node(dsqlScratch, dsqlDataSource);
node->dsqlUserName = PASS1_node(dsqlScratch, dsqlUserName);
node->dsqlPassword = PASS1_node(dsqlScratch, dsqlPassword);
node->dsqlRole = PASS1_node(dsqlScratch, dsqlRole);
node->traScope = traScope;
node->useCallerPrivs = useCallerPrivs;
return SavepointEncloseNode::make(getPool(), dsqlScratch, node);
}
void ExecStatementNode::print(string& text, Array<dsql_nod*>& nodes) const
@ -1821,6 +2112,127 @@ void ExecStatementNode::print(string& text, Array<dsql_nod*>& nodes) const
void ExecStatementNode::genBlr(DsqlCompilerScratch* dsqlScratch)
{
if (dsqlInnerStmt)
{
dsqlScratch->appendUChar(blr_label);
dsqlScratch->appendUChar((int)(IPTR) dsqlLabel->nod_arg[Dsql::e_label_number]);
}
// If no new features of EXECUTE STATEMENT is used, lets generate old BLR.
if (!dsqlDataSource && !dsqlUserName && !dsqlPassword && !dsqlRole && !useCallerPrivs &&
!dsqlInputs && !traScope)
{
if (dsqlOutputs)
{
dsqlScratch->appendUChar(blr_exec_into);
dsqlScratch->appendUShort(dsqlOutputs->nod_count);
GEN_expr(dsqlScratch, dsqlSql);
if (dsqlInnerStmt)
{
dsqlScratch->appendUChar(0); // Non-singleton.
GEN_statement(dsqlScratch, dsqlInnerStmt);
}
else
dsqlScratch->appendUChar(1); // Singleton.
for (size_t i = 0; i < dsqlOutputs->nod_count; ++i)
GEN_expr(dsqlScratch, dsqlOutputs->nod_arg[i]);
}
else
{
dsqlScratch->appendUChar(blr_exec_sql);
GEN_expr(dsqlScratch, dsqlSql);
}
}
else
{
dsqlScratch->appendUChar(blr_exec_stmt);
// Counts of input and output parameters.
if (dsqlInputs)
{
dsqlScratch->appendUChar(blr_exec_stmt_inputs);
dsqlScratch->appendUShort(dsqlInputs->nod_count);
}
if (dsqlOutputs)
{
dsqlScratch->appendUChar(blr_exec_stmt_outputs);
dsqlScratch->appendUShort(dsqlOutputs->nod_count);
}
// Query expression.
dsqlScratch->appendUChar(blr_exec_stmt_sql);
GEN_expr(dsqlScratch, dsqlSql);
// Proc block body.
if (dsqlInnerStmt)
{
dsqlScratch->appendUChar(blr_exec_stmt_proc_block);
GEN_statement(dsqlScratch, dsqlInnerStmt);
}
// External data source, user, password and role.
genOptionalExpr(dsqlScratch, blr_exec_stmt_data_src, dsqlDataSource);
genOptionalExpr(dsqlScratch, blr_exec_stmt_user, dsqlUserName);
genOptionalExpr(dsqlScratch, blr_exec_stmt_pwd, dsqlPassword);
genOptionalExpr(dsqlScratch, blr_exec_stmt_role, dsqlRole);
// dsqlScratch's transaction behavior.
if (traScope)
{
// Transaction parameters equal to current transaction.
dsqlScratch->appendUChar(blr_exec_stmt_tran_clone);
dsqlScratch->appendUChar(UCHAR(traScope));
}
// Inherit caller's privileges?
if (useCallerPrivs)
dsqlScratch->appendUChar(blr_exec_stmt_privs);
// Inputs.
if (dsqlInputs)
{
if (inputNames)
dsqlScratch->appendUChar(blr_exec_stmt_in_params2);
else
dsqlScratch->appendUChar(blr_exec_stmt_in_params);
dsql_nod* const* ptr = dsqlInputs->nod_arg;
string* const* name = inputNames ? inputNames->begin() : NULL;
for (const dsql_nod* const* end = ptr + dsqlInputs->nod_count; ptr != end; ++ptr, ++name)
{
if (inputNames)
dsqlScratch->appendNullString((*name)->c_str());
GEN_expr(dsqlScratch, *ptr);
}
}
// Outputs.
if (dsqlOutputs)
{
dsqlScratch->appendUChar(blr_exec_stmt_out_params);
for (size_t i = 0; i < dsqlOutputs->nod_count; ++i)
GEN_expr(dsqlScratch, dsqlOutputs->nod_arg[i]);
}
dsqlScratch->appendUChar(blr_end);
}
}
void ExecStatementNode::genOptionalExpr(DsqlCompilerScratch* dsqlScratch, const UCHAR code,
dsql_nod* node)
{
if (node)
{
dsqlScratch->appendUChar(code);
GEN_expr(dsqlScratch, node);
}
}
ExecStatementNode* ExecStatementNode::pass1(thread_db* tdbb, CompilerScratch* csb)
@ -2948,7 +3360,7 @@ StmtNode* ForNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
if (dsqlCursor)
{
fb_assert(dsqlCursor->nod_flags > 0);
PASS1_cursor_name(dsqlScratch, (dsql_str*) dsqlCursor->nod_arg[Dsql::e_cur_name],
PASS1_cursor_name(dsqlScratch, ((dsql_str*) dsqlCursor->nod_arg[Dsql::e_cur_name])->str_data,
NOD_CURSOR_ALL, false);
dsqlCursor->nod_arg[Dsql::e_cur_rse] = node->dsqlSelect;
dsqlCursor->nod_arg[Dsql::e_cur_number] = (dsql_nod*) (IPTR) dsqlScratch->cursorNumber++;

View File

@ -171,9 +171,13 @@ public:
class CursorStmtNode : public TypedNode<StmtNode, StmtNode::TYPE_CURSOR_STMT>
{
public:
explicit CursorStmtNode(MemoryPool& pool)
explicit CursorStmtNode(MemoryPool& pool, UCHAR aCursorOp, const Firebird::MetaName& aDsqlName = "",
dsql_nod* aDsqlIntoStmt = NULL)
: TypedNode<StmtNode, StmtNode::TYPE_CURSOR_STMT>(pool),
cursorOp(0),
dsqlName(pool, aDsqlName),
dsqlIntoStmt(aDsqlIntoStmt),
dsqlScrollExpr(NULL),
cursorOp(aCursorOp),
cursorNumber(0),
scrollOp(0),
scrollExpr(NULL),
@ -192,6 +196,9 @@ public:
virtual const StmtNode* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
public:
Firebird::MetaName dsqlName;
dsql_nod* dsqlIntoStmt;
dsql_nod* dsqlScrollExpr;
UCHAR cursorOp;
USHORT cursorNumber;
UCHAR scrollOp;
@ -318,8 +325,13 @@ public:
class ExecProcedureNode : public TypedNode<StmtNode, StmtNode::TYPE_EXEC_PROCEDURE>
{
public:
explicit ExecProcedureNode(MemoryPool& pool)
explicit ExecProcedureNode(MemoryPool& pool,
const Firebird::QualifiedName& aDsqlName = Firebird::QualifiedName(),
dsql_nod* aDsqlInputs = NULL, dsql_nod* aDsqlOutputs = NULL)
: TypedNode<StmtNode, StmtNode::TYPE_EXEC_PROCEDURE>(pool),
dsqlName(pool, aDsqlName),
dsqlInputs(aDsqlInputs),
dsqlOutputs(aDsqlOutputs),
inputSources(NULL),
inputTargets(NULL),
inputMessage(NULL),
@ -341,9 +353,13 @@ public:
virtual const StmtNode* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
private:
dsql_nod* explodeOutputs(DsqlCompilerScratch* dsqlScratch, const dsql_prc* procedure);
void executeProcedure(thread_db* tdbb, jrd_req* request) const;
public:
Firebird::QualifiedName dsqlName;
dsql_nod* dsqlInputs;
dsql_nod* dsqlOutputs;
NestConst<ValueListNode> inputSources;
NestConst<ValueListNode> inputTargets;
NestConst<MessageNode> inputMessage;
@ -359,6 +375,15 @@ class ExecStatementNode : public TypedNode<StmtNode, StmtNode::TYPE_EXEC_STATEME
public:
explicit ExecStatementNode(MemoryPool& pool)
: TypedNode<StmtNode, StmtNode::TYPE_EXEC_STATEMENT>(pool),
dsqlSql(NULL),
dsqlDataSource(NULL),
dsqlUserName(NULL),
dsqlPassword(NULL),
dsqlRole(NULL),
dsqlInnerStmt(NULL),
dsqlInputs(NULL),
dsqlOutputs(NULL),
dsqlLabel(NULL),
sql(NULL),
dataSource(NULL),
userName(NULL),
@ -368,7 +393,7 @@ public:
inputs(NULL),
outputs(NULL),
useCallerPrivs(false),
traScope(EDS::traCommon),
traScope(EDS::TraScope(0)), // not defined
inputNames(NULL)
{
}
@ -377,17 +402,28 @@ public:
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
virtual ExecStatementNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
virtual StmtNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
virtual ExecStatementNode* pass1(thread_db* tdbb, CompilerScratch* csb);
virtual ExecStatementNode* pass2(thread_db* tdbb, CompilerScratch* csb);
virtual const StmtNode* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
private:
static void genOptionalExpr(DsqlCompilerScratch* dsqlScratch, const UCHAR code, dsql_nod* node);
void getString(thread_db* tdbb, jrd_req* request, const ValueExprNode* node,
Firebird::string& str) const;
public:
dsql_nod* dsqlSql;
dsql_nod* dsqlDataSource;
dsql_nod* dsqlUserName;
dsql_nod* dsqlPassword;
dsql_nod* dsqlRole;
dsql_nod* dsqlInnerStmt;
dsql_nod* dsqlInputs;
dsql_nod* dsqlOutputs;
dsql_nod* dsqlLabel;
NestConst<ValueExprNode> sql;
NestConst<ValueExprNode> dataSource;
NestConst<ValueExprNode> userName;

View File

@ -66,10 +66,8 @@ using namespace Firebird;
static void gen_aggregate(DsqlCompilerScratch*, const dsql_nod*);
static void gen_coalesce(DsqlCompilerScratch*, const dsql_nod*);
static void gen_error_condition(DsqlCompilerScratch*, const dsql_nod*);
static void gen_exec_stmt(DsqlCompilerScratch* dsqlScratch, const dsql_nod* node);
static void gen_join_rse(DsqlCompilerScratch*, const dsql_nod*);
static void gen_map(DsqlCompilerScratch*, dsql_map*);
static inline void gen_optional_expr(DsqlCompilerScratch*, const UCHAR code, dsql_nod*);
static void gen_plan(DsqlCompilerScratch*, const dsql_nod*);
static void gen_relation(DsqlCompilerScratch*, dsql_ctx*);
static void gen_searched_case(DsqlCompilerScratch*, const dsql_nod*);
@ -675,7 +673,6 @@ void GEN_statement( DsqlCompilerScratch* dsqlScratch, dsql_nod* node)
case nod_modify:
case nod_modify_current:
case nod_store:
case nod_exec_procedure:
gen_statement(dsqlScratch, node);
return;
@ -690,39 +687,6 @@ void GEN_statement( DsqlCompilerScratch* dsqlScratch, dsql_nod* node)
GEN_statement(dsqlScratch, node->nod_arg[e_err_action]);
return;
case nod_exec_sql:
dsqlScratch->appendUChar(blr_exec_sql);
GEN_expr(dsqlScratch, node->nod_arg[e_exec_sql_stmnt]);
return;
case nod_exec_into:
if (node->nod_arg[e_exec_into_block])
{
dsqlScratch->appendUChar(blr_label);
dsqlScratch->appendUChar((int) (IPTR) node->nod_arg[e_exec_into_label]->nod_arg[e_label_number]);
}
dsqlScratch->appendUChar(blr_exec_into);
temp = node->nod_arg[e_exec_into_list];
dsqlScratch->appendUShort(temp->nod_count);
GEN_expr(dsqlScratch, node->nod_arg[e_exec_into_stmnt]);
if (node->nod_arg[e_exec_into_block])
{
dsqlScratch->appendUChar(0); // Non-singleton
GEN_statement(dsqlScratch, node->nod_arg[e_exec_into_block]);
}
else
dsqlScratch->appendUChar(1); // Singleton
for (ptr = temp->nod_arg, end = ptr + temp->nod_count; ptr < end; ptr++)
{
GEN_expr(dsqlScratch, *ptr);
}
return;
case nod_exec_stmt:
gen_exec_stmt(dsqlScratch, node);
return;
case nod_breakleave:
dsqlScratch->appendUChar(blr_leave);
dsqlScratch->appendUChar((int)(IPTR) node->nod_arg[e_breakleave_label]->nod_arg[e_label_number]);
@ -777,59 +741,6 @@ void GEN_statement( DsqlCompilerScratch* dsqlScratch, dsql_nod* node)
}
return;
case nod_cursor_open:
case nod_cursor_close:
case nod_cursor_fetch:
{
const dsql_nod* scroll = node->nod_arg[e_cur_stmt_scroll];
// op-code
dsqlScratch->appendUChar(blr_cursor_stmt);
if (node->nod_type == nod_cursor_open)
dsqlScratch->appendUChar(blr_cursor_open);
else if (node->nod_type == nod_cursor_close)
dsqlScratch->appendUChar(blr_cursor_close);
else if (scroll)
dsqlScratch->appendUChar(blr_cursor_fetch_scroll);
else
dsqlScratch->appendUChar(blr_cursor_fetch);
// cursor reference
dsql_nod* cursor = node->nod_arg[e_cur_stmt_id];
dsqlScratch->appendUShort((int) (IPTR) cursor->nod_arg[e_cur_number]);
// scrolling
if (scroll)
{
dsqlScratch->appendUChar(ExprNode::as<LiteralNode>(scroll->nod_arg[0])->getSlong());
if (scroll->nod_arg[1])
GEN_expr(dsqlScratch, scroll->nod_arg[1]);
else
dsqlScratch->appendUChar(blr_null);
}
// assignment
dsql_nod* list_into = node->nod_arg[e_cur_stmt_into];
if (list_into)
{
dsql_nod* list = cursor->nod_arg[e_cur_rse]->nod_arg[e_rse_items];
if (list->nod_count != list_into->nod_count)
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-313) <<
Arg::Gds(isc_dsql_count_mismatch));
}
dsqlScratch->appendUChar(blr_begin);
ptr = list->nod_arg;
end = ptr + list->nod_count;
dsql_nod** ptr_to = list_into->nod_arg;
while (ptr < end)
{
dsqlScratch->appendUChar(blr_assignment);
GEN_expr(dsqlScratch, *ptr++);
GEN_expr(dsqlScratch, *ptr_to++);
}
dsqlScratch->appendUChar(blr_end);
}
}
return;
case nod_src_info:
dsqlScratch->putDebugSrcInfo(node->nod_line, node->nod_column);
GEN_statement(dsqlScratch, node->nod_arg[e_src_info_stmt]);
@ -1131,109 +1042,6 @@ static void gen_error_condition( DsqlCompilerScratch* dsqlScratch, const dsql_no
}
/**
gen_exec_stmt
@brief Generate blr for the EXECUTE STATEMENT clause
@param dsqlScratch
@param node
**/
static void gen_exec_stmt(DsqlCompilerScratch* dsqlScratch, const dsql_nod* node)
{
if (node->nod_arg[e_exec_stmt_proc_block])
{
dsqlScratch->appendUChar(blr_label);
dsqlScratch->appendUChar((int)(IPTR) node->nod_arg[e_exec_stmt_label]->nod_arg[e_label_number]);
}
dsqlScratch->appendUChar(blr_exec_stmt);
// counts of input and output parameters
const dsql_nod* temp = node->nod_arg[e_exec_stmt_inputs];
if (temp)
{
dsqlScratch->appendUChar(blr_exec_stmt_inputs);
dsqlScratch->appendUShort(temp->nod_count);
}
temp = node->nod_arg[e_exec_stmt_outputs];
if (temp)
{
dsqlScratch->appendUChar(blr_exec_stmt_outputs);
dsqlScratch->appendUShort(temp->nod_count);
}
// query expression
dsqlScratch->appendUChar(blr_exec_stmt_sql);
GEN_expr(dsqlScratch, node->nod_arg[e_exec_stmt_sql]);
// proc block body
dsql_nod* temp2 = node->nod_arg[e_exec_stmt_proc_block];
if (temp2)
{
dsqlScratch->appendUChar(blr_exec_stmt_proc_block);
GEN_statement(dsqlScratch, temp2);
}
// external data source, user, password and role
gen_optional_expr(dsqlScratch, blr_exec_stmt_data_src, node->nod_arg[e_exec_stmt_data_src]);
gen_optional_expr(dsqlScratch, blr_exec_stmt_user, node->nod_arg[e_exec_stmt_user]);
gen_optional_expr(dsqlScratch, blr_exec_stmt_pwd, node->nod_arg[e_exec_stmt_pwd]);
gen_optional_expr(dsqlScratch, blr_exec_stmt_role, node->nod_arg[e_exec_stmt_role]);
// dsqlScratch's transaction behavior
temp = node->nod_arg[e_exec_stmt_tran];
if (temp)
{
dsqlScratch->appendUChar(blr_exec_stmt_tran_clone); // transaction parameters equal to current transaction
dsqlScratch->appendUChar((UCHAR)(IPTR) temp->nod_flags);
}
// inherit caller's privileges ?
if (node->nod_arg[e_exec_stmt_privs]) {
dsqlScratch->appendUChar(blr_exec_stmt_privs);
}
// inputs
temp = node->nod_arg[e_exec_stmt_inputs];
if (temp)
{
const dsql_nod* const* ptr = temp->nod_arg;
const bool haveNames = ((*ptr)->nod_arg[e_named_param_name] != 0);
if (haveNames)
dsqlScratch->appendUChar(blr_exec_stmt_in_params2);
else
dsqlScratch->appendUChar(blr_exec_stmt_in_params);
for (const dsql_nod* const* end = ptr + temp->nod_count; ptr < end; ptr++)
{
if (haveNames)
{
const dsql_str* name = (dsql_str*) (*ptr)->nod_arg[e_named_param_name];
dsqlScratch->appendNullString(name->str_data);
}
GEN_expr(dsqlScratch, (*ptr)->nod_arg[e_named_param_expr]);
}
}
// outputs
temp = node->nod_arg[e_exec_stmt_outputs];
if (temp)
{
dsqlScratch->appendUChar(blr_exec_stmt_out_params);
for (size_t i = 0; i < temp->nod_count; ++i) {
GEN_expr(dsqlScratch, temp->nod_arg[i]);
}
}
dsqlScratch->appendUChar(blr_end);
}
/**
gen_join_rse
@ -1304,15 +1112,6 @@ static void gen_map( DsqlCompilerScratch* dsqlScratch, dsql_map* map)
}
}
static void gen_optional_expr(DsqlCompilerScratch* dsqlScratch, const UCHAR code, dsql_nod* node)
{
if (node)
{
dsqlScratch->appendUChar(code);
GEN_expr(dsqlScratch, node);
}
}
// Generate a parameter reference.
void GEN_parameter( DsqlCompilerScratch* dsqlScratch, const dsql_par* parameter)
{
@ -2028,48 +1827,6 @@ static void gen_statement(DsqlCompilerScratch* dsqlScratch, const dsql_nod* node
}
break;
case nod_exec_procedure:
if (node->nod_arg[e_exe_package])
{
dsqlScratch->appendUChar(blr_exec_proc2);
dsqlScratch->appendMetaString(((dsql_str*) node->nod_arg[e_exe_package])->str_data);
}
else
dsqlScratch->appendUChar(blr_exec_proc);
name = (dsql_str*) node->nod_arg[e_exe_procedure];
dsqlScratch->appendMetaString(name->str_data);
// Input parameters
if ( (temp = node->nod_arg[e_exe_inputs]) )
{
dsqlScratch->appendUShort(temp->nod_count);
dsql_nod** ptr = temp->nod_arg;
const dsql_nod* const* end = ptr + temp->nod_count;
while (ptr < end)
{
GEN_expr(dsqlScratch, *ptr++);
}
}
else {
dsqlScratch->appendUShort(0);
}
// Output parameters
if ( ( temp = node->nod_arg[e_exe_outputs]) )
{
dsqlScratch->appendUShort(temp->nod_count);
dsql_nod** ptr = temp->nod_arg;
const dsql_nod* const* end = ptr + temp->nod_count;
while (ptr < end)
{
GEN_expr(dsqlScratch, *ptr++);
}
}
else {
dsqlScratch->appendUShort(0);
}
break;
default:
fb_assert(false);
}

View File

@ -1097,7 +1097,7 @@ dsql_nod* METD_get_primary_key(jrd_tra* transaction, const dsql_str* relation_na
dsql_prc* METD_get_procedure(jrd_tra* transaction, DsqlCompilerScratch* dsqlScratch,
const dsql_str* name, const dsql_str* package)
const QualifiedName& name)
{
/**************************************
*
@ -1116,8 +1116,6 @@ dsql_prc* METD_get_procedure(jrd_tra* transaction, DsqlCompilerScratch* dsqlScra
validateTransaction(transaction);
dsql_dbb* dbb = transaction->getDsqlAttachment();
QualifiedName metaName(MetaName(name->str_data, name->str_length),
(package ? MetaName(package->str_data, package->str_length) : ""));
// ASF: I've removed the code where we verify if the procedure being looked up is the one being
// defined (dsqlScratch->procedure). This code is totally incorrect, not considering
@ -1153,6 +1151,8 @@ dsql_prc* METD_get_procedure(jrd_tra* transaction, DsqlCompilerScratch* dsqlScra
//
// I hope for a solution, involving savepoint logic.
QualifiedName metaName(name);
bool maybeUnqualified = dsqlScratch->package.hasData() && metaName.package.isEmpty();
if (maybeUnqualified)
metaName.package = dsqlScratch->package;
@ -1182,7 +1182,7 @@ dsql_prc* METD_get_procedure(jrd_tra* transaction, DsqlCompilerScratch* dsqlScra
FOR(REQUEST_HANDLE handle1 TRANSACTION_HANDLE transaction)
X IN RDB$PROCEDURES
WITH X.RDB$PROCEDURE_NAME EQ name->str_data AND
WITH X.RDB$PROCEDURE_NAME EQ metaName.identifier.c_str() AND
X.RDB$PACKAGE_NAME EQUIV NULLIF(metaName.package.c_str(), '')
{
fb_utils::exact_name(X.RDB$OWNER_NAME);
@ -1221,7 +1221,7 @@ dsql_prc* METD_get_procedure(jrd_tra* transaction, DsqlCompilerScratch* dsqlScra
PR IN RDB$PROCEDURE_PARAMETERS
CROSS FLD IN RDB$FIELDS
WITH FLD.RDB$FIELD_NAME EQ PR.RDB$FIELD_SOURCE AND
PR.RDB$PROCEDURE_NAME EQ name->str_data AND
PR.RDB$PROCEDURE_NAME EQ metaName.identifier.c_str() AND
PR.RDB$PARAMETER_TYPE = type AND
PR.RDB$PACKAGE_NAME EQUIV NULLIF(metaName.package.c_str(), '')
SORTED BY DESCENDING PR.RDB$PARAMETER_NUMBER

View File

@ -64,8 +64,8 @@ bool METD_get_exception(Jrd::jrd_tra*, const Jrd::dsql_str*);
Jrd::dsql_udf* METD_get_function(Jrd::jrd_tra*, Jrd::DsqlCompilerScratch*,
const Firebird::QualifiedName&);
Jrd::dsql_nod* METD_get_primary_key(Jrd::jrd_tra*, const Jrd::dsql_str*);
Jrd::dsql_prc* METD_get_procedure(Jrd::jrd_tra*, Jrd::DsqlCompilerScratch*, const Jrd::dsql_str*,
const Jrd::dsql_str*);
Jrd::dsql_prc* METD_get_procedure(Jrd::jrd_tra*, Jrd::DsqlCompilerScratch*,
const Firebird::QualifiedName&);
Jrd::dsql_rel* METD_get_relation(Jrd::jrd_tra*, Jrd::DsqlCompilerScratch*, const Firebird::MetaName&);
bool METD_get_type(Jrd::jrd_tra*, const Jrd::dsql_str*, const char*, SSHORT*);
Jrd::dsql_rel* METD_get_view_base(Jrd::jrd_tra*, Jrd::DsqlCompilerScratch*, const char* view_name,

View File

@ -97,7 +97,6 @@ enum nod_t
nod_modify,
nod_erase,
nod_assign,
nod_exec_procedure,
nod_while,
nod_erase_current,
nod_modify_current,
@ -179,22 +178,16 @@ enum nod_t
nod_breakleave,
nod_udf_param, // there should be a way to signal a param by descriptor!
nod_limit, // limit support
nod_exec_sql, // EXECUTE STATEMENT
nod_searched_case, // searched CASE function
nod_simple_case, // simple CASE function
nod_coalesce, // COALESCE function
nod_for_update, // FOR UPDATE clause
nod_label, // label support
nod_exec_into, // EXECUTE STATEMENT INTO
nod_difference_file,
nod_drop_difference,
nod_begin_backup,
nod_end_backup,
nod_derived_table, // Derived table support
nod_cursor_open,
nod_cursor_fetch,
nod_cursor_close,
nod_fetch_scroll,
nod_rows, // ROWS support
nod_query_spec,
nod_mod_udf,
@ -213,15 +206,6 @@ enum nod_t
nod_add_user,
nod_mod_user,
nod_del_user,
nod_exec_stmt,
nod_exec_stmt_inputs,
nod_exec_stmt_datasrc,
nod_exec_stmt_user,
nod_exec_stmt_pwd,
nod_exec_stmt_role,
nod_exec_stmt_privs,
nod_tran_params,
nod_named_param,
nod_dfl_collate,
nod_trg_act,
nod_trg_ext,
@ -266,37 +250,6 @@ enum node_args {
e_err_action,
e_err_count,
e_exec_sql_stmnt = 0, // nod_exec_sql
e_exec_sql_count,
e_exec_into_stmnt = 0, // nod_exec_into
e_exec_into_block,
e_exec_into_list,
e_exec_into_label,
e_exec_into_count,
e_exec_stmt_sql = 0, // nod_exec_stmt
e_exec_stmt_inputs,
e_exec_stmt_outputs,
e_exec_stmt_proc_block,
e_exec_stmt_label,
e_exec_stmt_options,
e_exec_stmt_data_src,
e_exec_stmt_user,
e_exec_stmt_pwd,
e_exec_stmt_role,
e_exec_stmt_tran,
e_exec_stmt_privs,
e_exec_stmt_count,
e_exec_stmt_inputs_sql = 0, // nod_exec_stmt_inputs
e_exec_stmt_inputs_params,
e_exec_stmt_inputs_count,
e_named_param_name = 0, // nod_named_param
e_named_param_expr,
e_named_param_count,
e_vrn_name = 0, // nod_variable_name
e_vrn_count,
@ -337,12 +290,6 @@ enum node_args {
e_cur_number,
e_cur_count,
e_exe_procedure = 0, // nod_exec_procedure
e_exe_inputs,
e_exe_outputs,
e_exe_package,
e_exe_count,
e_sel_query_spec = 0, // nod_select_expr
e_sel_order,
e_sel_rows,
@ -664,11 +611,6 @@ enum node_args {
e_derived_table_context, // Context for derived table
e_derived_table_count,
e_cur_stmt_id = 0,
e_cur_stmt_scroll,
e_cur_stmt_into,
e_cur_stmt_count,
e_mod_udf_name = 0, // nod_mod_udf
e_mod_udf_entry_pt,
e_mod_udf_module,
@ -785,11 +727,6 @@ enum nod_flags_vals {
NOD_DT_IGNORE_COLUMN_CHECK = 1, // nod_cursor, see pass1_cursor_name
NOD_DT_CTE_USED = 2, // nod_derived_table
NOD_TRAN_AUTONOMOUS = 1, // nod_exec_stmt
NOD_TRAN_COMMON = 2,
NOD_TRAN_2PC = 3,
NOD_TRAN_DEFAULT = NOD_TRAN_COMMON,
NOD_AGG_WINDOW = 1 // nod_aggregate
};

View File

@ -649,6 +649,8 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
Jrd::ExecBlockNode* execBlockNode;
Jrd::AggNode* aggNode;
Jrd::SysFuncCallNode* sysFuncCallNode;
Jrd::CursorStmtNode* cursorStmtNode;
Jrd::ExecStatementNode* execStatementNode;
}
%type <legacyNode> access_mode access_type alias_list
@ -697,19 +699,23 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
%type <legacyNode> end_default err errors event_argument_opt exception_clause
%type <legacyNode> excp_hndl_statement excp_hndl_statements
%type <legacyNode> exec_function exec_into exec_procedure exec_sql exec_stmt_inputs
%type <legacyNode> exec_stmt_option exec_stmt_options exec_stmt_options_list
%type <legacyNode> ext_datasrc ext_privs ext_pwd ext_role ext_tran ext_user extra_indices_opt
%type <legacyNode> exec_function exec_procedure
%type <legacyNode> extra_indices_opt
%type <legacyNode> execute_privilege
%type <legacyStr> end_trigger entry_op
%type <pathNamePtr> external_file
%type <execStatementNode> exec_into exec_sql
%type exec_stmt_option(<execStatementNode>) exec_stmt_options(<execStatementNode>)
%type exec_stmt_options_list(<execStatementNode>) exec_stmt_inputs(<execStatementNode>)
%type <legacyNode> fetch_cursor fetch_opt fetch_scroll_opt file1 file_clause file_desc file_desc1
%type <legacyNode> fetch_cursor file1 file_clause file_desc file_desc1
%type <legacyNode> filter_clause_io filter_decl_clause first_clause
%type <legacyNode> float_type for_exec_into for_select for_update_clause for_update_list from_clause
%type <legacyNode> float_type for_select for_update_clause for_update_list from_clause
%type <legacyNode> from_list full_proc_block full_proc_block_body
%type <legacyStr> firstname_opt
%type fetch_scroll(<cursorStmtNode>)
%type <int32Val> first_file_length
%type <execStatementNode> for_exec_into
%type <legacyNode> generated_always_clause grant grant_option granted_by granted_by_text grantee grantee_list
%type <legacyNode> grantor group_by_item group_by_list group_clause gtt_recreate_clause
@ -739,13 +745,15 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
%type <legacyNode> merge_when_clause merge_when_matched_clause merge_when_not_matched_clause
%type <legacyStr> middlename_opt module_op
%type <legacyNode> named_columns_join named_param named_params_list national_character_keyword
%type <legacyNode> named_columns_join national_character_keyword
%type <legacyNode> national_character_type natural_join
%type <legacyNode> non_array_type
%type <legacyNode> non_charset_simple_type non_reserved_word non_role_grantee_list
%type <legacyNode> not_named_param not_named_params_list null_constraint
%type <legacyNode> null_constraint
%type <legacyNode> nulls_clause nulls_placement numeric_type
%type <int32Val> neg_short_integer nonneg_short_integer
%type named_param(<execStatementNode>) named_params_list(<execStatementNode>)
%type not_named_param(<execStatementNode>) not_named_params_list(<execStatementNode>)
%type <legacyNode> open_cursor opt_snapshot optional_retain
%type <legacyNode> optional_savepoint optional_work order_clause order_direction order_item order_list
@ -2337,7 +2345,9 @@ simple_proc_statement : assignment
| singleton_select
| exec_procedure
| exec_sql
{ $$ = makeClassNode($1); }
| exec_into
{ $$ = makeClassNode($1); }
| exec_function
| excp_statement
{ $$ = makeClassNode($1); }
@ -2363,6 +2373,7 @@ complex_proc_statement
| while
| for_select
| for_exec_into
{ $$ = makeClassNode($1); }
;
in_autonomous_transaction
@ -2402,121 +2413,119 @@ for_select
;
exec_sql
: EXECUTE STATEMENT exec_stmt_inputs exec_stmt_options
: EXECUTE STATEMENT
{ $<execStatementNode>$ = newNode<ExecStatementNode>(); }
exec_stmt_inputs($<execStatementNode>3) exec_stmt_options($<execStatementNode>3)
{
$$ = make_node (nod_exec_stmt, int (e_exec_stmt_count),
($3)->nod_arg[0], ($3)->nod_arg[1], NULL, NULL, NULL, make_list($4),
NULL, NULL, NULL, NULL, NULL, NULL);
$$ = $<execStatementNode>3;
}
;
exec_into
: EXECUTE STATEMENT exec_stmt_inputs exec_stmt_options
INTO variable_list
: exec_sql INTO variable_list
{
$$ = make_node (nod_exec_stmt, int (e_exec_stmt_count),
($3)->nod_arg[0], ($3)->nod_arg[1], make_list($6), NULL, NULL, make_list($4),
NULL, NULL, NULL, NULL, NULL, NULL);
$$ = $<execStatementNode>1;
$$->dsqlOutputs = make_list($3);
}
;
for_exec_into
: label_opt FOR EXECUTE STATEMENT exec_stmt_inputs exec_stmt_options
INTO variable_list
DO proc_block
: label_opt FOR exec_into DO proc_block
{
$$ = make_node (nod_exec_stmt, int (e_exec_stmt_count),
($5)->nod_arg[0], ($5)->nod_arg[1], make_list($8), $10, $1, make_list($6),
NULL, NULL, NULL, NULL, NULL, NULL);
$$ = $<execStatementNode>3;
$$->dsqlLabel = $1;
$$->dsqlInnerStmt = $5;
}
;
exec_stmt_inputs
exec_stmt_inputs($execStatementNode)
: value
{ $$ = make_node (nod_exec_stmt_inputs, e_exec_stmt_inputs_count, $1, NULL); }
| '(' value ')' '(' named_params_list ')'
{ $$ = make_node (nod_exec_stmt_inputs, e_exec_stmt_inputs_count, $2, make_list ($5)); }
| '(' value ')' '(' not_named_params_list ')'
{ $$ = make_node (nod_exec_stmt_inputs, e_exec_stmt_inputs_count, $2, make_list ($5)); }
{ $execStatementNode->dsqlSql = $1; }
| '(' value ')' '(' named_params_list($execStatementNode) ')'
{
$execStatementNode->dsqlSql = $2;
$execStatementNode->dsqlInputs = make_list($execStatementNode->dsqlInputs);
}
| '(' value ')' '(' not_named_params_list($execStatementNode) ')'
{
$execStatementNode->dsqlSql = $2;
$execStatementNode->dsqlInputs = make_list($execStatementNode->dsqlInputs);
}
;
named_params_list
: named_param
| named_params_list ',' named_param
{ $$ = make_node (nod_list, 2, $1, $3); }
named_params_list($execStatementNode)
: named_param($execStatementNode)
| named_params_list ',' named_param($execStatementNode)
;
named_param
named_param($execStatementNode)
: symbol_variable_name BIND_PARAM value
{ $$ = make_node (nod_named_param, e_named_param_count, $1, $3); }
{
if (!$execStatementNode->inputNames)
$execStatementNode->inputNames = FB_NEW(getPool()) EDS::ParamNames(getPool());
$execStatementNode->inputNames->add(
FB_NEW(getPool()) string(getPool(), toString((dsql_str*) $1)));
if ($execStatementNode->dsqlInputs)
{
$execStatementNode->dsqlInputs = make_node(nod_list, 2,
$execStatementNode->dsqlInputs, $3);
}
else
$execStatementNode->dsqlInputs = $3;
}
;
not_named_params_list
: not_named_param
| not_named_params_list ',' not_named_param
{ $$ = make_node (nod_list, 2, $1, $3); }
not_named_params_list($execStatementNode)
: not_named_param($execStatementNode)
| not_named_params_list ',' not_named_param($execStatementNode)
;
not_named_param
not_named_param($execStatementNode)
: value
{ $$ = make_node (nod_named_param, e_named_param_count, NULL, $1); }
{
if ($execStatementNode->dsqlInputs)
{
$execStatementNode->dsqlInputs = make_node(nod_list, 2,
$execStatementNode->dsqlInputs, $1);
}
else
$execStatementNode->dsqlInputs = $1;
}
;
exec_stmt_options
: exec_stmt_options_list
|
{ $$ = NULL; }
exec_stmt_options($execStatementNode)
:
| exec_stmt_options_list($execStatementNode)
;
exec_stmt_options_list
: exec_stmt_options_list exec_stmt_option
{ $$ = make_node (nod_list, 2, $1, $2); }
| exec_stmt_option
exec_stmt_options_list($execStatementNode)
: exec_stmt_options_list exec_stmt_option($execStatementNode)
| exec_stmt_option($execStatementNode)
;
exec_stmt_option
: ext_datasrc
| ext_user
| ext_pwd
| ext_role
| ext_tran
| ext_privs
;
ext_datasrc
exec_stmt_option($execStatementNode)
: ON EXTERNAL DATA SOURCE value
{ $$ = make_node (nod_exec_stmt_datasrc, 1, $5); }
{ setClause($execStatementNode->dsqlDataSource, "EXTERNAL DATA SOURCE", $5); }
| ON EXTERNAL value
{ $$ = make_node (nod_exec_stmt_datasrc, 1, $3); }
;
ext_user
: AS USER value
{ $$ = make_node (nod_exec_stmt_user, 1, $3); }
;
ext_pwd
: PASSWORD value
{ $$ = make_node (nod_exec_stmt_pwd, 1, $2); }
;
ext_role
: ROLE value
{ $$ = make_node (nod_exec_stmt_role, 1, $2); }
;
ext_tran
: WITH AUTONOMOUS TRANSACTION
{ $$ = make_flag_node(nod_tran_params, NOD_TRAN_AUTONOMOUS, 1, NULL); }
{ setClause($execStatementNode->dsqlDataSource, "EXTERNAL DATA SOURCE", $3); }
| AS USER value
{ setClause($execStatementNode->dsqlUserName, "USER", $3); }
| PASSWORD value
{ setClause($execStatementNode->dsqlPassword, "PASSWORD", $2); }
| ROLE value
{ setClause($execStatementNode->dsqlRole, "ROLE", $2); }
| WITH AUTONOMOUS TRANSACTION
{ setClause($execStatementNode->traScope, "TRANSACTION", EDS::traAutonomous); }
| WITH COMMON TRANSACTION
{ $$ = make_flag_node(nod_tran_params, NOD_TRAN_COMMON, 1, NULL); }
// | WITH TWO_PHASE TRANSACTION
// { $$ = make_flag_node(nod_tran_params, NOD_TRAN_2PC, 1, NULL); }
;
ext_privs
: WITH CALLER PRIVILEGES
{ $$ = make_node (nod_exec_stmt_privs, 1, NULL); }
{ setClause($execStatementNode->traScope, "TRANSACTION", EDS::traCommon); }
| WITH CALLER PRIVILEGES
{ setClause($execStatementNode->useCallerPrivs, "CALLER PRIVILEGES"); }
/*
| WITH TWO_PHASE TRANSACTION
{ setClause($execStatementNode->traScope, "TRANSACTION", EDS::traTwoPhase); }
*/
;
if_then_else
@ -2641,44 +2650,49 @@ cursor_statement : open_cursor
| close_cursor
;
open_cursor : OPEN symbol_cursor_name
{ $$ = make_node (nod_cursor_open, (int) e_cur_stmt_count, $2, NULL, NULL); }
open_cursor
: OPEN symbol_cursor_name
{ $$ = makeClassNode(newNode<CursorStmtNode>(blr_cursor_open, toName($2))); }
;
close_cursor : CLOSE symbol_cursor_name
{ $$ = make_node (nod_cursor_close, (int) e_cur_stmt_count, $2, NULL, NULL); }
close_cursor
: CLOSE symbol_cursor_name
{ $$ = makeClassNode(newNode<CursorStmtNode>(blr_cursor_close, toName($2))); }
;
fetch_cursor : FETCH fetch_opt symbol_cursor_name INTO variable_list
{ $$ = make_node (nod_cursor_fetch, (int) e_cur_stmt_count, $3, $2, make_list ($5)); }
fetch_cursor
: FETCH
{ $<cursorStmtNode>$ = newNode<CursorStmtNode>(blr_cursor_fetch_scroll); }
fetch_scroll($<cursorStmtNode>2) FROM symbol_cursor_name INTO variable_list
{
CursorStmtNode* cursorStmt = $<cursorStmtNode>2;
cursorStmt->dsqlName = toName($5);
cursorStmt->dsqlIntoStmt = make_list($7);
$$ = makeClassNode(cursorStmt);
}
| FETCH symbol_cursor_name INTO variable_list
{ $$ = makeClassNode(newNode<CursorStmtNode>(blr_cursor_fetch, toName($2), make_list($4))); }
;
fetch_opt
: fetch_scroll_opt FROM
{ $$ = $1; }
|
{ $$ = NULL; }
;
fetch_scroll_opt
fetch_scroll($cursorStmtNode)
: FIRST
{ $$ = make_node (nod_fetch_scroll, 2,
MAKE_const_slong (blr_scroll_bof), NULL); }
{ $cursorStmtNode->scrollOp = blr_scroll_bof; }
| LAST
{ $$ = make_node (nod_fetch_scroll, 2,
MAKE_const_slong (blr_scroll_eof), NULL); }
{ $cursorStmtNode->scrollOp = blr_scroll_eof; }
| PRIOR
{ $$ = make_node (nod_fetch_scroll, 2,
MAKE_const_slong (blr_scroll_backward), NULL); }
{ $cursorStmtNode->scrollOp = blr_scroll_backward; }
| NEXT
{ $$ = make_node (nod_fetch_scroll, 2,
MAKE_const_slong (blr_scroll_forward), NULL); }
{ $cursorStmtNode->scrollOp = blr_scroll_forward; }
| KW_ABSOLUTE value
{ $$ = make_node (nod_fetch_scroll, 2,
MAKE_const_slong (blr_scroll_absolute), $2); }
{
$cursorStmtNode->scrollOp = blr_scroll_absolute;
$cursorStmtNode->dsqlScrollExpr = $2;
}
| KW_RELATIVE value
{ $$ = make_node (nod_fetch_scroll, 2,
MAKE_const_slong (blr_scroll_relative), $2); }
{
$cursorStmtNode->scrollOp = blr_scroll_relative;
$cursorStmtNode->dsqlScrollExpr = $2;
}
;
@ -2686,9 +2700,9 @@ fetch_scroll_opt
exec_procedure
: EXECUTE PROCEDURE symbol_procedure_name proc_inputs proc_outputs_opt
{ $$ = make_node (nod_exec_procedure, (int) e_exe_count, $3, $4, $5, NULL); }
{ $$ = makeClassNode(newNode<ExecProcedureNode>(QualifiedName(toName($3)), $4, $5)); }
| EXECUTE PROCEDURE symbol_package_name '.' symbol_procedure_name proc_inputs proc_outputs_opt
{ $$ = make_node (nod_exec_procedure, (int) e_exe_count, $5, $6, $7, $3); }
{ $$ = makeClassNode(newNode<ExecProcedureNode>(QualifiedName(toName($5), toName($3)), $6, $7)); }
;
proc_inputs : value_list

View File

@ -186,7 +186,6 @@ static void DSQL_pretty(const dsql_nod*, int);
static void assign_fld_dtype_from_dsc(dsql_fld*, const dsc*);
static dsql_nod* explode_fields(dsql_rel*);
static dsql_nod* explode_outputs(DsqlCompilerScratch*, const dsql_prc*);
static void field_appears_once(const dsql_nod*, const dsql_nod*, const bool, const char*);
static void field_duplication(const TEXT*, const TEXT*, const dsql_nod*, const char*);
static dsql_par* find_dbkey(const dsql_req*, const dsql_nod*);
@ -758,7 +757,7 @@ dsql_ctx* PASS1_make_context(DsqlCompilerScratch* dsqlScratch, const dsql_nod* r
relation_node->nod_arg[e_rpn_inputs]))
{
procedure = METD_get_procedure(dsqlScratch->getTransaction(), dsqlScratch,
relation_name, package);
QualifiedName(relation_name->str_data, (package ? package->str_data : NULL)));
if (!procedure)
{
@ -783,7 +782,7 @@ dsql_ctx* PASS1_make_context(DsqlCompilerScratch* dsqlScratch, const dsql_nod* r
if (!relation && (relation_node->nod_type == nod_rel_proc_name))
{
procedure = METD_get_procedure(dsqlScratch->getTransaction(), dsqlScratch,
relation_name, NULL);
QualifiedName(relation_name->str_data));
}
if (!relation && !procedure)
@ -1171,18 +1170,6 @@ dsql_nod* PASS1_node(DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
case nod_returning:
return pass1_returning(dsqlScratch, input);
case nod_tran_params:
return input;
case nod_exec_stmt_privs:
return input;
case nod_named_param:
node = MAKE_node(input->nod_type, input->nod_count);
node->nod_arg[e_named_param_name] = input->nod_arg[e_named_param_name];
node->nod_arg[e_named_param_expr] = PASS1_node(dsqlScratch, input->nod_arg[e_named_param_expr]);
return node;
default:
break;
}
@ -1362,95 +1349,6 @@ dsql_nod* PASS1_statement(DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
node = pass1_savepoint(dsqlScratch, pass1_delete(dsqlScratch, input));
break;
case nod_exec_procedure:
{
const dsql_str* name = (dsql_str*) input->nod_arg[e_exe_procedure];
const dsql_str* package = (dsql_str*) input->nod_arg[e_exe_package];
DEV_BLKCHK(name, dsql_type_str);
dsql_prc* procedure = METD_get_procedure(dsqlScratch->getTransaction(), dsqlScratch,
name, package);
if (!procedure)
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
Arg::Gds(isc_dsql_procedure_err) <<
Arg::Gds(isc_random) <<
Arg::Str(QualifiedName(name->str_data,
package ? package->str_data : NULL).toString()));
}
if (!dsqlScratch->isPsql())
{
dsqlScratch->procedure = procedure;
dsqlScratch->getStatement()->setType(DsqlCompiledStatement::TYPE_EXEC_PROCEDURE);
}
node = MAKE_node(input->nod_type, input->nod_count);
node->nod_arg[e_exe_procedure] = input->nod_arg[e_exe_procedure];
node->nod_arg[e_exe_package] = input->nod_arg[e_exe_package];
if (!node->nod_arg[e_exe_package] && procedure->prc_name.package.hasData())
{
node->nod_arg[e_exe_package] = (dsql_nod*) MAKE_string(
procedure->prc_name.package.c_str(), procedure->prc_name.package.length());
}
// handle input parameters
const USHORT count = input->nod_arg[e_exe_inputs] ?
input->nod_arg[e_exe_inputs]->nod_count : 0;
if (count > procedure->prc_in_count ||
count < procedure->prc_in_count - procedure->prc_def_count)
{
ERRD_post(Arg::Gds(isc_prcmismat) << Arg::Str(name->str_data));
}
node->nod_arg[e_exe_inputs] = PASS1_node(dsqlScratch, input->nod_arg[e_exe_inputs]);
if (count)
{
// Initialize this stack variable, and make it look like a node
Firebird::AutoPtr<dsql_nod> desc_node(FB_NEW_RPT(*getDefaultMemoryPool(), 0) dsql_nod);
dsql_nod* const* ptr = node->nod_arg[e_exe_inputs]->nod_arg;
for (const dsql_fld* field = procedure->prc_inputs; *ptr;
ptr++, field = field->fld_next)
{
DEV_BLKCHK(field, dsql_type_fld);
DEV_BLKCHK(*ptr, dsql_type_nod);
MAKE_desc_from_field(&desc_node->nod_desc, field);
// PASS1_set_parameter_type(*ptr, &desc_node, false);
PASS1_set_parameter_type(dsqlScratch, *ptr, desc_node, false);
}
}
// handle output parameters
dsql_nod* temp = input->nod_arg[e_exe_outputs];
if (dsqlScratch->isPsql())
{
const USHORT ocount = temp ? temp->nod_count : 0;
if (ocount != procedure->prc_out_count)
{
ERRD_post(Arg::Gds(isc_prc_out_param_mismatch) << Arg::Str(name->str_data));
}
node->nod_arg[e_exe_outputs] = PASS1_node(dsqlScratch, temp);
}
else
{
if (temp)
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
// Token unknown
Arg::Gds(isc_token_err) <<
Arg::Gds(isc_random) << Arg::Str("RETURNING_VALUES"));
}
node->nod_arg[e_exe_outputs] = explode_outputs(dsqlScratch, dsqlScratch->procedure);
}
}
break;
case nod_get_segment:
case nod_put_segment:
pass1_blob(dsqlScratch, input);
@ -1504,158 +1402,6 @@ dsql_nod* PASS1_statement(DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
node->nod_arg[e_err_action] = PASS1_statement(dsqlScratch, input->nod_arg[e_err_action]);
return node;
case nod_exec_sql:
node = MAKE_node(input->nod_type, input->nod_count);
node->nod_arg[e_exec_sql_stmnt] = PASS1_node(dsqlScratch, input->nod_arg[e_exec_sql_stmnt]);
return pass1_savepoint(dsqlScratch, node);
case nod_exec_into:
node = MAKE_node(input->nod_type, input->nod_count);
node->nod_arg[e_exec_into_stmnt] = PASS1_node(dsqlScratch, input->nod_arg[e_exec_into_stmnt]);
if (input->nod_arg[e_exec_into_block])
{
dsqlScratch->loopLevel++;
node->nod_arg[e_exec_into_label] = PASS1_label(dsqlScratch, input);
node->nod_arg[e_exec_into_block] =
PASS1_statement(dsqlScratch, input->nod_arg[e_exec_into_block]);
dsqlScratch->loopLevel--;
dsqlScratch->labels.pop();
}
node->nod_arg[e_exec_into_list] = PASS1_node(dsqlScratch, input->nod_arg[e_exec_into_list]);
return pass1_savepoint(dsqlScratch, node);
case nod_exec_stmt:
// if no new features of EXECUTE STATEMENT is used, lets generate old BLR
if (!input->nod_arg[e_exec_stmt_inputs] && !input->nod_arg[e_exec_stmt_options])
{
if (!input->nod_arg[e_exec_stmt_outputs])
{
node = MAKE_node(nod_exec_sql, e_exec_sql_count);
node->nod_arg[e_exec_sql_stmnt] = input->nod_arg[e_exec_stmt_sql];
}
else
{
node = MAKE_node(nod_exec_into, e_exec_into_count);
node->nod_arg[e_exec_into_stmnt] = input->nod_arg[e_exec_stmt_sql];
node->nod_arg[e_exec_into_block] = input->nod_arg[e_exec_stmt_proc_block];
node->nod_arg[e_exec_into_list] = input->nod_arg[e_exec_stmt_outputs];
node->nod_arg[e_exec_into_label] = input->nod_arg[e_exec_stmt_label];
}
return PASS1_statement(dsqlScratch, node);
}
node = MAKE_node(input->nod_type, input->nod_count);
node->nod_arg[e_exec_stmt_sql] = PASS1_node(dsqlScratch, input->nod_arg[e_exec_stmt_sql]);
node->nod_arg[e_exec_stmt_inputs] = PASS1_node(dsqlScratch, input->nod_arg[e_exec_stmt_inputs]);
// check params names uniqueness, if present
if (node->nod_arg[e_exec_stmt_inputs])
{
const int cnt = node->nod_arg[e_exec_stmt_inputs]->nod_count;
StrArray names(*getDefaultMemoryPool(), cnt);
const dsql_nod* const* prm = node->nod_arg[e_exec_stmt_inputs]->nod_arg;
if (prm[0]->nod_arg[e_named_param_name])
{
for (int i = 0; i < cnt; i++)
{
const dsql_str* name = (dsql_str*) prm[i]->nod_arg[e_named_param_name];
size_t pos;
if (names.find(name->str_data, pos))
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-637) <<
Arg::Gds(isc_dsql_duplicate_spec) << Arg::Str(name->str_data));
}
names.insert(pos, name->str_data);
}
}
}
node->nod_arg[e_exec_stmt_outputs] = PASS1_node(dsqlScratch, input->nod_arg[e_exec_stmt_outputs]);
if (input->nod_arg[e_exec_stmt_proc_block])
{
dsqlScratch->loopLevel++;
node->nod_arg[e_exec_stmt_label] = PASS1_label(dsqlScratch, input);
node->nod_arg[e_exec_stmt_proc_block] =
PASS1_statement(dsqlScratch, input->nod_arg[e_exec_stmt_proc_block]);
dsqlScratch->loopLevel--;
dsqlScratch->labels.pop();
}
// process various optional arguments
if (input->nod_arg[e_exec_stmt_options])
{
dsql_nod* list = input->nod_arg[e_exec_stmt_options];
fb_assert(list->nod_type == nod_list);
const dsql_nod* const* end = list->nod_arg + list->nod_count;
for (dsql_nod** ptr = list->nod_arg; ptr < end; ptr++)
{
const char* dupClause = NULL;
dsql_nod* opt = *ptr;
switch (opt->nod_type)
{
case nod_exec_stmt_datasrc:
if (node->nod_arg[e_exec_stmt_data_src])
dupClause = "EXTERNAL DATA SOURCE";
else
node->nod_arg[e_exec_stmt_data_src] = PASS1_node(dsqlScratch, opt->nod_arg[0]);
break;
case nod_exec_stmt_user:
if (node->nod_arg[e_exec_stmt_user])
dupClause = "USER";
else
node->nod_arg[e_exec_stmt_user] = PASS1_node(dsqlScratch, opt->nod_arg[0]);
break;
case nod_exec_stmt_pwd:
if (node->nod_arg[e_exec_stmt_pwd])
dupClause = "PASSWORD";
else
node->nod_arg[e_exec_stmt_pwd] = PASS1_node(dsqlScratch, opt->nod_arg[0]);
break;
case nod_exec_stmt_role:
if (node->nod_arg[e_exec_stmt_role])
dupClause = "ROLE";
else
node->nod_arg[e_exec_stmt_role] = PASS1_node(dsqlScratch, opt->nod_arg[0]);
break;
case nod_tran_params:
if (node->nod_arg[e_exec_stmt_tran])
dupClause = "TRANSACTION";
else
node->nod_arg[e_exec_stmt_tran] = PASS1_node(dsqlScratch, opt);
break;
case nod_exec_stmt_privs:
if (node->nod_arg[e_exec_stmt_privs])
dupClause = "CALLER PRIVILEGES";
else
node->nod_arg[e_exec_stmt_privs] = PASS1_node(dsqlScratch, opt);
break;
default:
fb_assert(false);
}
if (dupClause)
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-637) <<
Arg::Gds(isc_dsql_duplicate_spec) << Arg::Str(dupClause));
}
}
}
return pass1_savepoint(dsqlScratch, node);
case nod_breakleave:
if (!dsqlScratch->loopLevel)
{
@ -1755,7 +1501,8 @@ dsql_nod* PASS1_statement(DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
{
fb_assert(input->nod_flags > 0);
// make sure the cursor doesn't exist
PASS1_cursor_name(dsqlScratch, (dsql_str*) input->nod_arg[e_cur_name], NOD_CURSOR_ALL, false);
PASS1_cursor_name(dsqlScratch, ((dsql_str*) input->nod_arg[e_cur_name])->str_data,
NOD_CURSOR_ALL, false);
// temporarily hide unnecessary contexts and process our RSE
DsqlContextStack* const base_context = dsqlScratch->context;
DsqlContextStack temp;
@ -1771,45 +1518,6 @@ dsql_nod* PASS1_statement(DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
}
return input;
case nod_cursor_open:
case nod_cursor_close:
case nod_cursor_fetch:
// Verify if we're in an autonomous transaction.
if (dsqlScratch->flags & DsqlCompilerScratch::FLAG_IN_AUTO_TRANS_BLOCK)
{
const char* stmt = NULL;
switch (input->nod_type)
{
case nod_cursor_open:
stmt = "OPEN CURSOR";
break;
case nod_cursor_close:
stmt = "CLOSE CURSOR";
break;
case nod_cursor_fetch:
stmt = "FETCH CURSOR";
break;
}
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-901) <<
Arg::Gds(isc_dsql_unsupported_in_auto_trans) << Arg::Str(stmt));
}
// resolve the cursor
input->nod_arg[e_cur_stmt_id] =
PASS1_cursor_name(dsqlScratch, (dsql_str*) input->nod_arg[e_cur_stmt_id],
NOD_CURSOR_EXPLICIT, true);
// process a scroll node, if exists
if (input->nod_arg[e_cur_stmt_scroll]) {
input->nod_arg[e_cur_stmt_scroll] = PASS1_node(dsqlScratch, input->nod_arg[e_cur_stmt_scroll]);
}
// process an assignment node, if exists
if (input->nod_arg[e_cur_stmt_into]) {
input->nod_arg[e_cur_stmt_into] = PASS1_node(dsqlScratch, input->nod_arg[e_cur_stmt_into]);
}
return input;
case nod_src_info:
{
input->nod_line = (USHORT) (IPTR) input->nod_arg[e_src_info_line];
@ -2066,55 +1774,6 @@ static dsql_nod* explode_fields(dsql_rel* relation)
}
/**
explode_outputs
@brief Generate a parameter list to correspond to procedure outputs.
@param dsqlScratch
@param procedure
**/
static dsql_nod* explode_outputs( DsqlCompilerScratch* dsqlScratch, const dsql_prc* procedure)
{
thread_db* tdbb = JRD_get_thread_data();
DEV_BLKCHK(dsqlScratch, dsql_type_req);
DEV_BLKCHK(procedure, dsql_type_prc);
const SSHORT count = procedure->prc_out_count;
dsql_nod* node = MAKE_node(nod_list, count);
dsql_nod** ptr = node->nod_arg;
for (const dsql_fld* field = procedure->prc_outputs; field; field = field->fld_next, ptr++)
{
DEV_BLKCHK(field, dsql_type_fld);
DEV_BLKCHK(*ptr, dsql_type_nod);
ParameterNode* paramNode = FB_NEW(*tdbb->getDefaultPool()) ParameterNode(
*tdbb->getDefaultPool());
dsql_nod* p_node = MAKE_node(nod_class_exprnode, 1);
p_node->nod_count = 0;
p_node->nod_arg[0] = reinterpret_cast<dsql_nod*>(paramNode);
*ptr = p_node;
dsql_par* parameter = paramNode->dsqlParameter = MAKE_parameter(
dsqlScratch->getStatement()->getReceiveMsg(),
true, true, 0, NULL);
paramNode->dsqlParameterIndex = parameter->par_index;
MAKE_desc_from_field(&parameter->par_desc, field);
parameter->par_name = parameter->par_alias = field->fld_name.c_str();
parameter->par_rel_name = procedure->prc_name.identifier.c_str();
parameter->par_owner_name = procedure->prc_owner.c_str();
}
return node;
}
/**
field_appears_once
@ -2864,7 +2523,7 @@ static dsql_ctx* pass1_cursor_context( DsqlCompilerScratch* dsqlScratch, const d
DEV_BLKCHK(string, dsql_type_str);
// this function must throw an error if no cursor was found
const dsql_nod* node = PASS1_cursor_name(dsqlScratch, string, NOD_CURSOR_ALL, true);
const dsql_nod* node = PASS1_cursor_name(dsqlScratch, string->str_data, NOD_CURSOR_ALL, true);
fb_assert(node);
const dsql_nod* rse = node->nod_arg[e_cur_rse];
@ -2939,13 +2598,13 @@ static dsql_ctx* pass1_cursor_context( DsqlCompilerScratch* dsqlScratch, const d
@param existence_flag
**/
dsql_nod* PASS1_cursor_name(DsqlCompilerScratch* dsqlScratch, const dsql_str* string,
dsql_nod* PASS1_cursor_name(DsqlCompilerScratch* dsqlScratch, const MetaName& string,
USHORT mask, bool existence_flag)
{
DEV_BLKCHK(string, dsql_type_str);
dsql_nod* cursor = NULL;
if (!strlen(string->str_data))
if (string.isEmpty())
{
if (existence_flag)
{
@ -2965,7 +2624,7 @@ dsql_nod* PASS1_cursor_name(DsqlCompilerScratch* dsqlScratch, const dsql_str* st
{
cursor = itr.object();
const dsql_str* cname = (dsql_str*) cursor->nod_arg[e_cur_name];
if (!strcmp(string->str_data, cname->str_data) && (cursor->nod_flags & mask))
if (strcmp(string.c_str(), cname->str_data) == 0 && (cursor->nod_flags & mask))
break;
cursor = NULL;
}
@ -2974,13 +2633,13 @@ dsql_nod* PASS1_cursor_name(DsqlCompilerScratch* dsqlScratch, const dsql_str* st
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-504) <<
Arg::Gds(isc_dsql_cursor_err) <<
Arg::Gds(isc_dsql_cursor_not_found) << Arg::Str(string->str_data));
Arg::Gds(isc_dsql_cursor_not_found) << Arg::Str(string.c_str()));
}
else if (cursor && !existence_flag)
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-502) <<
Arg::Gds(isc_dsql_decl_err) <<
Arg::Gds(isc_dsql_cursor_exists) << Arg::Str(string->str_data));
Arg::Gds(isc_dsql_cursor_exists) << Arg::Str(string.c_str()));
}
return cursor;
@ -4648,12 +4307,6 @@ dsql_nod* PASS1_label(DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
case nod_continue:
label = input->nod_arg[e_continue_label];
break;
case nod_exec_into:
label = input->nod_arg[e_exec_into_label];
break;
case nod_exec_stmt:
label = input->nod_arg[e_exec_stmt_label];
break;
case nod_while:
label = input->nod_arg[e_while_label];
break;
@ -8282,9 +7935,6 @@ void DSQL_pretty(const dsql_nod* node, int column)
case nod_execute:
verb = "execute";
break;
case nod_exec_procedure:
verb = "execute procedure";
break;
case nod_flag:
verb = "flag";
break;
@ -8614,9 +8264,6 @@ void DSQL_pretty(const dsql_nod* node, int column)
case nod_udf_param:
verb = "udf_param";
break;
case nod_exec_sql:
verb = "exec_sql";
break;
case nod_for_update:
verb = "for_update";
break;
@ -8636,11 +8283,6 @@ void DSQL_pretty(const dsql_nod* node, int column)
verb = "derived_table";
break;
// CVC: This node seems obsolete.
case nod_exec_into:
verb = "exec_into";
break;
case nod_breakleave:
verb = "breakleave";
break;
@ -8737,19 +8379,6 @@ void DSQL_pretty(const dsql_nod* node, int column)
trace_line("%s\"\n", string->str_data);
return;
case nod_cursor_open:
verb = "cursor_open";
break;
case nod_cursor_fetch:
verb = "cursor_fetch";
break;
case nod_cursor_close:
verb = "cursor_close";
break;
case nod_fetch_scroll:
verb = "fetch_scroll";
break;
case nod_query_spec:
verb = "query_spec";
break;
@ -8823,10 +8452,6 @@ void DSQL_pretty(const dsql_nod* node, int column)
verb = "del_user";
break;
case nod_exec_stmt:
verb = "exec_stmt";
break;
case nod_class_exprnode:
case nod_class_stmtnode:
reinterpret_cast<Node*>(node->nod_arg[0])->print(verb, subNodes);

View File

@ -32,7 +32,7 @@ namespace Jrd
void PASS1_ambiguity_check(Jrd::DsqlCompilerScratch*, const Jrd::dsql_str*, const Jrd::DsqlContextStack&);
void PASS1_check_unique_fields_names(Jrd::StrArray& names, const Jrd::dsql_nod* fields);
Jrd::dsql_nod* PASS1_compose(Jrd::dsql_nod*, Jrd::dsql_nod*, UCHAR);
Jrd::dsql_nod* PASS1_cursor_name(Jrd::DsqlCompilerScratch*, const Jrd::dsql_str*, USHORT, bool);
Jrd::dsql_nod* PASS1_cursor_name(Jrd::DsqlCompilerScratch*, const Firebird::MetaName&, USHORT, bool);
void PASS1_field_unknown(const TEXT*, const TEXT*, const Jrd::dsql_nod*);
Jrd::dsql_nod* PASS1_label(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*);
Jrd::dsql_nod* PASS1_label2(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*, Jrd::dsql_nod*);