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:
parent
6d92010735
commit
0b1fa97b4a
@ -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(¶meter->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++;
|
||||
|
@ -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;
|
||||
|
243
src/dsql/gen.cpp
243
src/dsql/gen.cpp
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
246
src/dsql/parse.y
246
src/dsql/parse.y
@ -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
|
||||
|
@ -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(¶meter->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);
|
||||
|
@ -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*);
|
||||
|
Loading…
Reference in New Issue
Block a user