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

Refactor SELECT.

This commit is contained in:
asfernandes 2012-02-10 03:06:57 +00:00
parent ae1563fa2e
commit 6b5a322e8b
7 changed files with 248 additions and 325 deletions

View File

@ -1166,8 +1166,7 @@ DeclareCursorNode* DeclareCursorNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
DsqlContextStack* const baseContext = dsqlScratch->context;
DsqlContextStack temp;
dsqlScratch->context = &temp;
const dsql_nod* select = dsqlRse;
dsqlRse = PASS1_rse(dsqlScratch, select->nod_arg[Dsql::e_select_expr], select->nod_arg[Dsql::e_select_lock]);
dsqlRse = PASS1_rse(dsqlScratch, dsqlSelect->dsqlExpr, dsqlSelect->dsqlWithLock);
dsqlScratch->context->clear();
dsqlScratch->context = baseContext;
@ -4295,14 +4294,14 @@ ForNode* ForNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
ForNode* node = FB_NEW(getPool()) ForNode(getPool());
node->dsqlCursor = dsqlCursor;
node->dsqlSelect = PASS1_statement(dsqlScratch, dsqlSelect);
node->dsqlSelect = dsqlSelect->dsqlPass(dsqlScratch);
if (dsqlCursor)
{
DeclareCursorNode* cursor = StmtNode::as<DeclareCursorNode>(dsqlCursor);
fb_assert(cursor->dsqlCursorType != DeclareCursorNode::CUR_TYPE_NONE);
PASS1_cursor_name(dsqlScratch, cursor->dsqlName, DeclareCursorNode::CUR_TYPE_ALL, false);
cursor->dsqlRse = node->dsqlSelect;
cursor->dsqlSelect = node->dsqlSelect;
cursor->cursorNumber = dsqlScratch->cursorNumber++;
dsqlScratch->cursors.push(cursor);
}
@ -4332,7 +4331,6 @@ ForNode* ForNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
void ForNode::print(string& text, Array<dsql_nod*>& nodes) const
{
text = "ForNode";
nodes.add(dsqlSelect);
nodes.add(dsqlCursor);
nodes.add(dsqlLabel);
}
@ -4354,12 +4352,12 @@ void ForNode::genBlr(DsqlCompilerScratch* dsqlScratch)
if (!statement || dsqlForceSingular)
dsqlScratch->appendUChar(blr_singular);
GEN_rse(dsqlScratch, dsqlSelect);
GEN_rse(dsqlScratch, dsqlSelect->dsqlRse);
dsqlScratch->appendUChar(blr_begin);
// Build body of FOR loop
dsql_nod* list = ExprNode::as<RseNode>(dsqlSelect)->dsqlSelectList;
dsql_nod* list = ExprNode::as<RseNode>(dsqlSelect->dsqlRse)->dsqlSelectList;
if (dsqlInto)
{
@ -4859,12 +4857,10 @@ StmtNode* MergeNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
dsql_nod* select_expr = MAKE_node(Dsql::nod_select_expr, Dsql::e_sel_count);
select_expr->nod_arg[Dsql::e_sel_query_spec] = querySpecNod;
dsql_nod* select = MAKE_node(Dsql::nod_select, Dsql::e_select_count);
select->nod_arg[Dsql::e_select_expr] = select_expr;
// build a FOR SELECT node
ForNode* forNode = FB_NEW(pool) ForNode(pool);
forNode->dsqlSelect = select;
forNode->dsqlSelect = FB_NEW(pool) SelectNode(pool);
forNode->dsqlSelect->dsqlExpr = select_expr;
forNode->statement = FB_NEW(pool) CompoundStmtNode(pool);
forNode = forNode->dsqlPass(dsqlScratch);
@ -4874,9 +4870,9 @@ StmtNode* MergeNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
// Get the already processed relations.
source = ExprNode::as<RseNode>(ExprNode::as<RseNode>(
forNode->dsqlSelect)->dsqlStreams->nod_arg[0])->dsqlStreams->nod_arg[0];
forNode->dsqlSelect->dsqlRse)->dsqlStreams->nod_arg[0])->dsqlStreams->nod_arg[0];
target = ExprNode::as<RseNode>(ExprNode::as<RseNode>(
forNode->dsqlSelect)->dsqlStreams->nod_arg[0])->dsqlStreams->nod_arg[1];
forNode->dsqlSelect->dsqlRse)->dsqlStreams->nod_arg[0])->dsqlStreams->nod_arg[1];
DsqlContextStack usingCtxs;
dsqlGetContexts(usingCtxs, source);
@ -6987,9 +6983,35 @@ DmlNode* SelectNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* c
return node;
}
SelectNode* SelectNode::dsqlPass(DsqlCompilerScratch* /*dsqlScratch*/)
SelectNode* SelectNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
return this;
SelectNode* node = FB_NEW(getPool()) SelectNode(getPool());
const DsqlContextStack::iterator base(*dsqlScratch->context);
node->dsqlRse = PASS1_rse(dsqlScratch, dsqlExpr, dsqlWithLock);
dsqlScratch->context->clear(base);
if (dsqlForUpdate)
{
dsqlScratch->getStatement()->setType(DsqlCompiledStatement::TYPE_SELECT_UPD);
dsqlScratch->getStatement()->addFlags(DsqlCompiledStatement::FLAG_NO_BATCH);
}
else
{
// If there is a union without ALL or order by or a select distinct buffering is OK even if
// stored procedure occurs in the select list. In these cases all of stored procedure is
// executed under savepoint for open cursor.
RseNode* rseNode = ExprNode::as<RseNode>(node->dsqlRse);
if (rseNode->dsqlOrder || rseNode->dsqlDistinct)
{
dsqlScratch->getStatement()->setFlags(
dsqlScratch->getStatement()->getFlags() & ~DsqlCompiledStatement::FLAG_NO_BATCH);
}
}
return node;
}
void SelectNode::print(string& text, Array<dsql_nod*>& /*nodes*/) const
@ -6997,8 +7019,155 @@ void SelectNode::print(string& text, Array<dsql_nod*>& /*nodes*/) const
text = "SelectNode";
}
void SelectNode::genBlr(DsqlCompilerScratch* /*dsqlScratch*/)
// Generate BLR for a SELECT statement.
void SelectNode::genBlr(DsqlCompilerScratch* dsqlScratch)
{
RseNode* const rse = ExprNode::as<RseNode>(dsqlRse);
fb_assert(rse);
DsqlCompiledStatement* const statement = dsqlScratch->getStatement();
// Set up parameter for things in the select list.
const dsql_nod* list = rse->dsqlSelectList;
dsql_nod* const* ptr = list->nod_arg;
for (const dsql_nod* const* const end = ptr + list->nod_count; ptr != end; ++ptr)
{
dsql_par* parameter = MAKE_parameter(statement->getReceiveMsg(), true, true, 0, *ptr);
parameter->par_node = *ptr;
MAKE_desc(dsqlScratch, &parameter->par_desc, *ptr);
}
// Set up parameter to handle EOF.
dsql_par* const parameterEof = MAKE_parameter(statement->getReceiveMsg(), false, false, 0, NULL);
statement->setEof(parameterEof);
parameterEof->par_desc.dsc_dtype = dtype_short;
parameterEof->par_desc.dsc_scale = 0;
parameterEof->par_desc.dsc_length = sizeof(SSHORT);
// Save DBKEYs for possible update later.
GenericMap<NonPooled<dsql_par*, dsql_ctx*> > paramContexts(*getDefaultMemoryPool());
dsql_ctx* context;
if (statement->getType() == DsqlCompiledStatement::TYPE_SELECT_UPD && !rse->dsqlDistinct)
{
list = rse->dsqlStreams;
dsql_nod* const* ptr2 = list->nod_arg;
for (const dsql_nod* const* const end2 = ptr2 + list->nod_count; ptr2 != end2; ++ptr2)
{
dsql_nod* const item = *ptr2;
RelationSourceNode* relNode;
if (item && (relNode = ExprNode::as<RelationSourceNode>(item)))
{
context = relNode->dsqlContext;
const dsql_rel* const relation = context->ctx_relation;
if (relation)
{
// Set up dbkey.
dsql_par* parameter = MAKE_parameter(
statement->getReceiveMsg(), false, false, 0, NULL);
parameter->par_dbkey_relname = relation->rel_name;
paramContexts.put(parameter, context);
parameter->par_desc.dsc_dtype = dtype_text;
parameter->par_desc.dsc_ttype() = ttype_binary;
parameter->par_desc.dsc_length = relation->rel_dbkey_length;
// Set up record version - for post v33 databases.
parameter = MAKE_parameter(statement->getReceiveMsg(), false, false, 0, NULL);
parameter->par_rec_version_relname = relation->rel_name;
paramContexts.put(parameter, context);
parameter->par_desc.dsc_dtype = dtype_text;
parameter->par_desc.dsc_ttype() = ttype_binary;
parameter->par_desc.dsc_length = relation->rel_dbkey_length / 2;
}
}
}
}
// Generate definitions for the messages.
GEN_port(dsqlScratch, statement->getReceiveMsg());
dsql_msg* message = statement->getSendMsg();
if (message->msg_parameter)
GEN_port(dsqlScratch, message);
else
statement->setSendMsg(NULL);
// If there is a send message, build a RECEIVE.
if ((message = statement->getSendMsg()) != NULL)
{
dsqlScratch->appendUChar(blr_receive);
dsqlScratch->appendUChar(message->msg_number);
}
// Generate FOR loop.
message = statement->getReceiveMsg();
dsqlScratch->appendUChar(blr_for);
dsqlScratch->appendUChar(blr_stall);
GEN_rse(dsqlScratch, dsqlRse);
dsqlScratch->appendUChar(blr_send);
dsqlScratch->appendUChar(message->msg_number);
dsqlScratch->appendUChar(blr_begin);
// Build body of FOR loop.
SSHORT constant;
dsc constant_desc;
constant_desc.makeShort(0, &constant);
// Add invalid usage here.
dsqlScratch->appendUChar(blr_assignment);
constant = 1;
LiteralNode::genConstant(dsqlScratch, &constant_desc, false);
GEN_parameter(dsqlScratch, statement->getEof());
for (size_t i = 0; i < message->msg_parameters.getCount(); ++i)
{
dsql_par* const parameter = message->msg_parameters[i];
if (parameter->par_node)
{
dsqlScratch->appendUChar(blr_assignment);
GEN_expr(dsqlScratch, parameter->par_node);
GEN_parameter(dsqlScratch, parameter);
}
if (parameter->par_dbkey_relname.hasData() && paramContexts.get(parameter, context))
{
dsqlScratch->appendUChar(blr_assignment);
dsqlScratch->appendUChar(blr_dbkey);
GEN_stuff_context(dsqlScratch, context);
GEN_parameter(dsqlScratch, parameter);
}
if (parameter->par_rec_version_relname.hasData() && paramContexts.get(parameter, context))
{
dsqlScratch->appendUChar(blr_assignment);
dsqlScratch->appendUChar(blr_record_version);
GEN_stuff_context(dsqlScratch, context);
GEN_parameter(dsqlScratch, parameter);
}
}
dsqlScratch->appendUChar(blr_end);
dsqlScratch->appendUChar(blr_send);
dsqlScratch->appendUChar(message->msg_number);
dsqlScratch->appendUChar(blr_assignment);
constant = 0;
LiteralNode::genConstant(dsqlScratch, &constant_desc, false);
GEN_parameter(dsqlScratch, statement->getEof());
}
SelectNode* SelectNode::pass1(thread_db* tdbb, CompilerScratch* csb)

View File

@ -36,6 +36,7 @@ namespace Jrd {
class CompoundStmtNode;
class ExecBlockNode;
class RelationSourceNode;
class SelectNode;
typedef Firebird::Pair<Firebird::NonPooled<dsql_nod*, Firebird::Array<dsql_nod*>*> > ReturningClause;
@ -327,6 +328,7 @@ public:
dsqlCursorType(aDsqlCursorType),
dsqlScroll(false),
dsqlName(aDsqlName),
dsqlSelect(NULL),
dsqlRse(NULL),
rse(NULL),
refs(NULL),
@ -349,6 +351,7 @@ public:
USHORT dsqlCursorType;
bool dsqlScroll;
Firebird::MetaName dsqlName;
SelectNode* dsqlSelect;
dsql_nod* dsqlRse;
NestConst<RseNode> rse;
NestConst<ValueListNode> refs;
@ -874,7 +877,7 @@ public:
virtual const StmtNode* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
public:
dsql_nod* dsqlSelect;
SelectNode* dsqlSelect;
Firebird::Array<dsql_nod*>* dsqlInto;
dsql_nod* dsqlCursor;
dsql_nod* dsqlLabel;
@ -1274,6 +1277,10 @@ class SelectNode : public TypedNode<StmtNode, StmtNode::TYPE_SELECT>
public:
explicit SelectNode(MemoryPool& pool)
: TypedNode<StmtNode, StmtNode::TYPE_SELECT>(pool),
dsqlExpr(NULL),
dsqlForUpdate(false),
dsqlWithLock(false),
dsqlRse(NULL),
statements(pool)
{
}
@ -1289,6 +1296,10 @@ public:
virtual const StmtNode* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
public:
dsql_nod* dsqlExpr;
bool dsqlForUpdate;
bool dsqlWithLock;
dsql_nod* dsqlRse;
Firebird::Array<NestConst<StmtNode> > statements;
};

View File

@ -65,7 +65,6 @@ using namespace Dsql;
using namespace Firebird;
static void gen_plan(DsqlCompilerScratch*, const dsql_nod*);
static void gen_select(DsqlCompilerScratch*, dsql_nod*);
static void gen_union(DsqlCompilerScratch*, const dsql_nod*);
@ -323,8 +322,6 @@ void GEN_request(DsqlCompilerScratch* scratch, dsql_nod* node)
{
case DsqlCompiledStatement::TYPE_SELECT:
case DsqlCompiledStatement::TYPE_SELECT_UPD:
gen_select(scratch, node);
break;
case DsqlCompiledStatement::TYPE_EXEC_BLOCK:
case DsqlCompiledStatement::TYPE_SELECT_BLOCK:
GEN_statement(scratch, node);
@ -724,170 +721,6 @@ void GEN_rse( DsqlCompilerScratch* dsqlScratch, const dsql_nod* rseNod)
}
/**
gen_select
@brief Generate BLR for a SELECT statement.
@param dsqlScratch
@param rse
**/
static void gen_select(DsqlCompilerScratch* dsqlScratch, dsql_nod* rseNod)
{
dsql_ctx* context;
RseNode* const rse = ExprNode::as<RseNode>(rseNod);
fb_assert(rse);
DsqlCompiledStatement* const statement = dsqlScratch->getStatement();
// Set up parameter for things in the select list
const dsql_nod* list = rse->dsqlSelectList;
dsql_nod* const* ptr = list->nod_arg;
for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end; ptr++)
{
dsql_par* parameter = MAKE_parameter(statement->getReceiveMsg(), true, true, 0, *ptr);
parameter->par_node = *ptr;
MAKE_desc(dsqlScratch, &parameter->par_desc, *ptr);
}
// Set up parameter to handle EOF
dsql_par* const parameter_eof =
MAKE_parameter(statement->getReceiveMsg(), false, false, 0, NULL);
statement->setEof(parameter_eof);
parameter_eof->par_desc.dsc_dtype = dtype_short;
parameter_eof->par_desc.dsc_scale = 0;
parameter_eof->par_desc.dsc_length = sizeof(SSHORT);
// Save DBKEYs for possible update later
GenericMap<NonPooled<dsql_par*, dsql_ctx*> > paramContexts(*getDefaultMemoryPool());
if (statement->getType() == DsqlCompiledStatement::TYPE_SELECT_UPD && !rse->dsqlDistinct)
{
list = rse->dsqlStreams;
dsql_nod* const* ptr2 = list->nod_arg;
for (const dsql_nod* const* const end2 = ptr2 + list->nod_count; ptr2 < end2; ptr2++)
{
dsql_nod* const item = *ptr2;
RelationSourceNode* relNode;
if (item && (relNode = ExprNode::as<RelationSourceNode>(item)))
{
context = relNode->dsqlContext;
const dsql_rel* const relation = context->ctx_relation;
if (relation)
{
// Set up dbkey
dsql_par* parameter =
MAKE_parameter(statement->getReceiveMsg(), false, false, 0, NULL);
parameter->par_dbkey_relname = relation->rel_name;
paramContexts.put(parameter, context);
parameter->par_desc.dsc_dtype = dtype_text;
parameter->par_desc.dsc_ttype() = ttype_binary;
parameter->par_desc.dsc_length = relation->rel_dbkey_length;
// Set up record version - for post v33 databases
parameter = MAKE_parameter(statement->getReceiveMsg(), false, false, 0, NULL);
parameter->par_rec_version_relname = relation->rel_name;
paramContexts.put(parameter, context);
parameter->par_desc.dsc_dtype = dtype_text;
parameter->par_desc.dsc_ttype() = ttype_binary;
parameter->par_desc.dsc_length = relation->rel_dbkey_length / 2;
}
}
}
}
// Generate definitions for the messages
GEN_port(dsqlScratch, statement->getReceiveMsg());
dsql_msg* message = statement->getSendMsg();
if (message->msg_parameter)
GEN_port(dsqlScratch, message);
else
statement->setSendMsg(NULL);
// If there is a send message, build a RECEIVE
if ((message = statement->getSendMsg()) != NULL)
{
dsqlScratch->appendUChar(blr_receive);
dsqlScratch->appendUChar(message->msg_number);
}
// Generate FOR loop
message = statement->getReceiveMsg();
dsqlScratch->appendUChar(blr_for);
dsqlScratch->appendUChar(blr_stall);
GEN_rse(dsqlScratch, rseNod);
dsqlScratch->appendUChar(blr_send);
dsqlScratch->appendUChar(message->msg_number);
dsqlScratch->appendUChar(blr_begin);
// Build body of FOR loop
SSHORT constant;
dsc constant_desc;
constant_desc.makeShort(0, &constant);
// Add invalid usage here
dsqlScratch->appendUChar(blr_assignment);
constant = 1;
LiteralNode::genConstant(dsqlScratch, &constant_desc, false);
GEN_parameter(dsqlScratch, statement->getEof());
for (size_t i = 0; i < message->msg_parameters.getCount(); ++i)
{
dsql_par* const parameter = message->msg_parameters[i];
if (parameter->par_node)
{
dsqlScratch->appendUChar(blr_assignment);
GEN_expr(dsqlScratch, parameter->par_node);
GEN_parameter(dsqlScratch, parameter);
}
if (parameter->par_dbkey_relname.hasData() && paramContexts.get(parameter, context))
{
dsqlScratch->appendUChar(blr_assignment);
dsqlScratch->appendUChar(blr_dbkey);
GEN_stuff_context(dsqlScratch, context);
GEN_parameter(dsqlScratch, parameter);
}
if (parameter->par_rec_version_relname.hasData() && paramContexts.get(parameter, context))
{
dsqlScratch->appendUChar(blr_assignment);
dsqlScratch->appendUChar(blr_record_version);
GEN_stuff_context(dsqlScratch, context);
GEN_parameter(dsqlScratch, parameter);
}
}
dsqlScratch->appendUChar(blr_end);
dsqlScratch->appendUChar(blr_send);
dsqlScratch->appendUChar(message->msg_number);
dsqlScratch->appendUChar(blr_assignment);
constant = 0;
LiteralNode::genConstant(dsqlScratch, &constant_desc, false);
GEN_parameter(dsqlScratch, statement->getEof());
}
// Generate a sort clause.
void GEN_sort(DsqlCompilerScratch* dsqlScratch, dsql_nod* list)
{

View File

@ -109,7 +109,6 @@ enum nod_t
nod_mod_field_name,
nod_mod_field_type,
nod_mod_field_pos,
nod_for_update, // FOR UPDATE clause
nod_label, // label support
nod_rows, // ROWS support
nod_with,
@ -132,14 +131,6 @@ enum nod_t
* entries. These include nod_udf and nod_collate.
*/
enum node_args {
e_select_expr = 0, // nod_select
e_select_update,
e_select_lock,
e_select_count,
e_fpd_list = 0, // nod_for_update
e_fpd_count,
e_ary_array = 0, // nod_array
e_ary_indices,
e_ary_count,

View File

@ -670,6 +670,7 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
Jrd::ErrorHandlerNode* errorHandlerNode;
Jrd::ExecStatementNode* execStatementNode;
Jrd::MergeNode* mergeNode;
Jrd::SelectNode* selectNode;
Jrd::SetTransactionNode* setTransactionNode;
Jrd::DeclareSubProcNode* declareSubProcNode;
Jrd::DeclareSubFuncNode* declareSubFuncNode;
@ -756,7 +757,8 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
%type <stmtNode> fetch_cursor
%type <legacyNode> first_clause
%type <legacyNode> float_type for_update_clause for_update_list from_clause
%type <legacyNode> float_type for_update_list from_clause
%type <boolVal> for_update_clause
%type <legacyNode> from_list
%type <ddlNode> filter_decl_clause
%type <stmtNode> for_select full_proc_block full_proc_block_body
@ -790,7 +792,8 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
%type <legacyNode> label_opt limit_clause
%type <stmtNode> local_declaration local_declaration_item
%type <compoundStmtNode> local_declaration_list local_declarations
%type <legacyNode> lock_clause lock_mode lock_type
%type <boolVal> lock_clause
%type <legacyNode> lock_mode lock_type
%type <stringPtr> lastname_opt
%type <int32Val> long_integer
@ -854,11 +857,12 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
%type <legacyNode> scroll_opt search_condition searched_case
%type <valueIfNode> searched_when_clause
%type sec_shadow_files(<dbFilesClause>)
%type <legacyNode> select select_expr
%type <legacyNode> select_expr
%type <legacyNode> select_expr_body select_item select_items select_list
%type <createShadowNode> shadow_clause
%type <legacyNode> simple_case simple_UDF_name
%type <legacyNode> simple_column_name simple_package_name simple_proc_name simple_table_name
%type <selectNode> select
%type <stmtNode> set_generator simple_proc_statement singleton_select
%type <setTransactionNode> set_transaction
%type <ddlNode> set_statistics
@ -1017,7 +1021,7 @@ statement
| revoke
| rollback { $$ = makeClassNode($1); }
| savepoint { $$ = makeClassNode($1); }
| select
| select { $$ = makeClassNode($1); }
| set_transaction { $$ = makeClassNode($1); }
| set_generator { $$ = makeClassNode($1); }
| set_statistics { $$ = makeClassNode($1); }
@ -2422,7 +2426,7 @@ cursor_declaration_item
DeclareCursorNode* node = newNode<DeclareCursorNode>(toName($1),
DeclareCursorNode::CUR_TYPE_EXPLICIT);
node->dsqlScroll = $2 != NULL;
node->dsqlRse = $6;
node->dsqlSelect = $6;
$$ = node;
}
;
@ -4320,22 +4324,28 @@ ddl_desc
select
: select_expr for_update_clause lock_clause
{ $$ = make_node(nod_select, (int) e_select_count, $1, $2, $3); }
{
SelectNode* node = newNode<SelectNode>();
node->dsqlExpr = $1;
node->dsqlForUpdate = $2;
node->dsqlWithLock = $3;
$$ = node;
}
;
for_update_clause
: /* nothing */ { $$ = NULL; }
| FOR UPDATE for_update_list { $$ = make_node(nod_for_update, (int) e_fpd_count, $3); }
: /* nothing */ { $$ = false; }
| FOR UPDATE for_update_list { $$ = true; /* for_update_list is ignored */ }
;
for_update_list
: /* nothing */ { $$ = make_node(nod_flag, 0, NULL); }
: /* nothing */ { $$ = NULL; }
| OF column_list { $$ = $2; }
;
lock_clause
: /* nothing */ { $$ = NULL; }
| WITH LOCK { $$ = make_node(nod_flag, 0, NULL); }
: /* nothing */ { $$ = false; }
| WITH LOCK { $$ = true; }
;

View File

@ -196,10 +196,10 @@ static dsql_nod* pass1_expand_select_list(DsqlCompilerScratch*, dsql_nod*, dsql_
static dsql_nod* pass1_field(DsqlCompilerScratch*, dsql_nod*, const bool, dsql_nod*);
static dsql_nod* pass1_group_by_list(DsqlCompilerScratch*, dsql_nod*, dsql_nod*);
static dsql_nod* pass1_make_derived_field(DsqlCompilerScratch*, thread_db*, dsql_nod*);
static dsql_nod* pass1_rse(DsqlCompilerScratch*, dsql_nod*, dsql_nod*, dsql_nod*, dsql_nod*, USHORT);
static dsql_nod* pass1_rse_impl(DsqlCompilerScratch*, dsql_nod*, dsql_nod*, dsql_nod*, dsql_nod*, USHORT);
static dsql_nod* pass1_rse(DsqlCompilerScratch*, dsql_nod*, dsql_nod*, dsql_nod*, bool, USHORT);
static dsql_nod* pass1_rse_impl(DsqlCompilerScratch*, dsql_nod*, dsql_nod*, dsql_nod*, bool, USHORT);
static dsql_nod* pass1_sel_list(DsqlCompilerScratch*, dsql_nod*, bool);
static dsql_nod* pass1_union(DsqlCompilerScratch*, dsql_nod*, dsql_nod*, dsql_nod*, dsql_nod*, USHORT);
static dsql_nod* pass1_union(DsqlCompilerScratch*, dsql_nod*, dsql_nod*, dsql_nod*, bool, USHORT);
static void pass1_union_auto_cast(DsqlCompilerScratch*, dsql_nod*, const dsc&, SSHORT,
bool in_select_list = false);
static dsql_nod* pass1_variable(DsqlCompilerScratch*, dsql_nod*);
@ -724,7 +724,7 @@ dsql_nod* PASS1_node(DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
const DsqlContextStack::iterator base(*dsqlScratch->context);
dsql_nod* rseNod = PASS1_rse(dsqlScratch, input, NULL);
dsql_nod* rseNod = PASS1_rse(dsqlScratch, input, false);
RseNode* rse = ExprNode::as<RseNode>(rseNod);
SubQueryNode* subQueryNode = FB_NEW(*tdbb->getDefaultPool()) SubQueryNode(*tdbb->getDefaultPool(),
@ -825,31 +825,17 @@ dsql_nod* PASS1_node(DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
}
/**
PASS1_rse
@brief Compile a record selection expression,
bumping up the statement scope level
everytime an rse is seen. The scope
level controls parsing of aliases.
@param dsqlScratch
@param input
@param update_lock
**/
dsql_nod* PASS1_rse(DsqlCompilerScratch* dsqlScratch, dsql_nod* input, dsql_nod* update_lock)
// Compile a record selection expression, bumping up the statement scope level everytime an rse is
// seen. The scope level controls parsing of aliases.
dsql_nod* PASS1_rse(DsqlCompilerScratch* dsqlScratch, dsql_nod* input, bool updateLock)
{
DEV_BLKCHK(dsqlScratch, dsql_type_req);
DEV_BLKCHK(input, dsql_type_nod);
DEV_BLKCHK(update_lock, dsql_type_nod);
fb_assert(input->nod_type == nod_select_expr);
dsqlScratch->scopeLevel++;
dsql_nod* node = pass1_rse(dsqlScratch, input, NULL, NULL, update_lock, 0);
dsql_nod* node = pass1_rse(dsqlScratch, input, NULL, NULL, updateLock, 0);
dsqlScratch->scopeLevel--;
return node;
@ -922,32 +908,6 @@ dsql_nod* PASS1_statement(DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
return node;
}
case nod_select:
{
node = PASS1_rse(dsqlScratch, input->nod_arg[e_select_expr], input->nod_arg[e_select_lock]);
if (input->nod_arg[e_select_update])
{
dsqlScratch->getStatement()->setType(DsqlCompiledStatement::TYPE_SELECT_UPD);
dsqlScratch->getStatement()->addFlags(DsqlCompiledStatement::FLAG_NO_BATCH);
break;
}
// If there is a union without ALL or order by or a select distinct
// buffering is OK even if stored procedure occurs in the select
// list. In these cases all of stored procedure is executed under
// savepoint for open cursor.
RseNode* rseNode = ExprNode::as<RseNode>(node);
if (rseNode->dsqlOrder || rseNode->dsqlDistinct)
{
dsqlScratch->getStatement()->setFlags(dsqlScratch->getStatement()->getFlags() &
~DsqlCompiledStatement::FLAG_NO_BATCH);
}
}
break;
default:
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-901) <<
Arg::Gds(isc_dsql_command_err) <<
@ -1596,7 +1556,7 @@ static dsql_nod* pass1_derived_table(DsqlCompilerScratch* dsqlScratch, dsql_nod*
rse = pass1_union(dsqlScratch, union_expr, NULL, NULL, NULL, 0);
}
else
rse = PASS1_rse(dsqlScratch, input, NULL);
rse = PASS1_rse(dsqlScratch, input, false);
USHORT minOuterJoin = MAX_USHORT;
@ -1783,7 +1743,7 @@ static dsql_nod* pass1_derived_table(DsqlCompilerScratch* dsqlScratch, dsql_nod*
dsqlScratch->resetCTEAlias(alias->str_data);
rse = PASS1_rse(dsqlScratch, input, NULL);
rse = PASS1_rse(dsqlScratch, input, false);
// Finish off by cleaning up contexts and put them into derivedContext
// so create view (ddl) can deal with it.
@ -3020,24 +2980,9 @@ static dsql_rel* pass1_base_table( DsqlCompilerScratch* dsqlScratch, const dsql_
}
/**
pass1_rse
@brief wrapper for pass1_rse_impl
substitute recursive CTE alias (if needed)
and call pass1_rse_impl
@param dsqlScratch
@param input
@param order
@param rows
@param update_lock
@param flags
**/
// Wrapper for pass1_rse_impl. Substitute recursive CTE alias (if needed) and call pass1_rse_impl.
static dsql_nod* pass1_rse( DsqlCompilerScratch* dsqlScratch, dsql_nod* input, dsql_nod* order,
dsql_nod* rows, dsql_nod* update_lock, USHORT flags)
dsql_nod* rows, bool updateLock, USHORT flags)
{
string save_alias;
const bool isRecursive = (input->nod_flags & NOD_SELECT_EXPR_RECURSIVE);
@ -3050,7 +2995,7 @@ static dsql_nod* pass1_rse( DsqlCompilerScratch* dsqlScratch, dsql_nod* input, d
dsqlScratch->recursiveCtx->ctx_alias = *dsqlScratch->getNextCTEAlias();
}
dsql_nod* ret = pass1_rse_impl(dsqlScratch, input, order, rows, update_lock, flags);
dsql_nod* ret = pass1_rse_impl(dsqlScratch, input, order, rows, updateLock, flags);
if (isRecursive)
dsqlScratch->recursiveCtx->ctx_alias = save_alias;
@ -3059,25 +3004,10 @@ static dsql_nod* pass1_rse( DsqlCompilerScratch* dsqlScratch, dsql_nod* input, d
}
/**
pass1_rse_impl
@brief Compile a record selection expression.
The input node may either be a "select_expression"
or a "list" (an implicit union) or a "query specification".
@param dsqlScratch
@param input
@param order
@param rows
@param update_lock
@param flags
**/
// Compile a record selection expression. The input node may either be a "select_expression"
// or a "list" (an implicit union) or a "query specification".
static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* input, dsql_nod* order,
dsql_nod* rows, dsql_nod* update_lock, USHORT flags)
dsql_nod* rows, bool updateLock, USHORT flags)
{
DEV_BLKCHK(dsqlScratch, dsql_type_req);
DEV_BLKCHK(input, dsql_type_nod);
@ -3099,10 +3029,8 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp
if (node_with)
dsqlScratch->addCTEs(node_with);
dsql_nod* ret =
pass1_rse(dsqlScratch, input->nod_arg[e_sel_query_spec],
input->nod_arg[e_sel_order], input->nod_arg[e_sel_rows],
update_lock, viewFlags);
dsql_nod* ret = pass1_rse(dsqlScratch, input->nod_arg[e_sel_query_spec],
input->nod_arg[e_sel_order], input->nod_arg[e_sel_rows], updateLock, viewFlags);
if (node_with)
{
@ -3122,7 +3050,7 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp
else if (input->nod_type == nod_list)
{
fb_assert(input->nod_count > 1);
return pass1_union(dsqlScratch, input, order, rows, update_lock, flags);
return pass1_union(dsqlScratch, input, order, rows, updateLock, flags);
}
RseNode* inputRse = ExprNode::as<RseNode>(input);
@ -3136,7 +3064,7 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp
dsql_nod* rseNod = MAKE_node(nod_class_exprnode, 1);
rseNod->nod_arg[0] = reinterpret_cast<dsql_nod*>(rse);
if (update_lock)
if (updateLock)
rse->flags |= RseNode::FLAG_WRITELOCK;
dsql_nod* list = rse->dsqlStreams = PASS1_node_psql(dsqlScratch, inputRse->dsqlFrom, false);
@ -3145,7 +3073,7 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp
RelationSourceNode* relNode;
const dsql_rel* relation;
if (update_lock &&
if (updateLock &&
(list->nod_count != 1 || !(relNode = ExprNode::as<RelationSourceNode>(list->nod_arg[0])) ||
!(relation = relNode->dsqlContext->ctx_relation) ||
(relation->rel_flags & REL_view) || (relation->rel_flags & REL_external)))
@ -3237,7 +3165,7 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp
(rse->dsqlOrder && AggregateFinder::find(dsqlScratch, false, rse->dsqlOrder)))
{
// dimitr: don't allow WITH LOCK for aggregates
if (update_lock)
if (updateLock)
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
// Token unknown
@ -3308,7 +3236,7 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp
// sub-selects a new context number should be generated
if (inputRse->dsqlDistinct)
{
if (update_lock)
if (updateLock)
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
// Token unknown
@ -3677,26 +3605,10 @@ dsql_nod* PASS1_sort( DsqlCompilerScratch* dsqlScratch, dsql_nod* input, dsql_no
}
/**
pass1_union
@brief Handle a UNION of substreams, generating
a mapping of all the fields and adding an
implicit PROJECT clause to ensure that all
the records returned are unique.
@param dsqlScratch
@param input
@param order_list
@param rows
@param update_lock
@param flags
**/
// Handle a UNION of substreams, generating a mapping of all the fields and adding an implicit
// PROJECT clause to ensure that all the records returned are unique.
static dsql_nod* pass1_union( DsqlCompilerScratch* dsqlScratch, dsql_nod* input, dsql_nod* order_list,
dsql_nod* rows, dsql_nod* update_lock, USHORT flags)
dsql_nod* rows, bool updateLock, USHORT flags)
{
DEV_BLKCHK(dsqlScratch, dsql_type_req);
DEV_BLKCHK(input, dsql_type_nod);
@ -3741,7 +3653,7 @@ static dsql_nod* pass1_union( DsqlCompilerScratch* dsqlScratch, dsql_nod* input,
for (const dsql_nod* const* const end = ptr + input->nod_count; ptr < end; ++ptr, ++uptr)
{
dsqlScratch->scopeLevel++;
*uptr = pass1_rse(dsqlScratch, *ptr, NULL, NULL, NULL, 0);
*uptr = pass1_rse(dsqlScratch, *ptr, NULL, NULL, false, 0);
dsqlScratch->scopeLevel--;
while (*(dsqlScratch->context) != base)
@ -3911,7 +3823,7 @@ static dsql_nod* pass1_union( DsqlCompilerScratch* dsqlScratch, dsql_nod* input,
// PROJECT on all the select items unless UNION ALL was specified.
if (!(input->nod_flags & NOD_UNION_ALL))
{
if (update_lock)
if (updateLock)
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
// Token unknown
@ -3922,7 +3834,7 @@ static dsql_nod* pass1_union( DsqlCompilerScratch* dsqlScratch, dsql_nod* input,
unionRse->dsqlDistinct = union_items;
}
if (update_lock)
if (updateLock)
unionRse->flags |= RseNode::FLAG_WRITELOCK;
dsql_nod* unionRseNod = MAKE_node(nod_class_exprnode, 1);
@ -4765,9 +4677,6 @@ void DSQL_pretty(const dsql_nod* node, int column)
case nod_mod_field_pos:
verb = "mod_field_pos";
break;
case nod_for_update:
verb = "for_update";
break;
case nod_label:
verb = "label";

View File

@ -50,7 +50,7 @@ Jrd::dsql_nod* PASS1_post_map(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*, Jrd::ds
Jrd::dsql_nod*, Jrd::dsql_nod*);
void PASS1_put_args_on_stack(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*, Jrd::DsqlNodStack&);
Jrd::dsql_nod* PASS1_relation(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*);
Jrd::dsql_nod* PASS1_rse(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*, Jrd::dsql_nod*);
Jrd::dsql_nod* PASS1_rse(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*, bool);
bool PASS1_set_parameter_type(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*, Jrd::dsql_nod*, bool);
Jrd::dsql_nod* PASS1_sort(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*, Jrd::dsql_nod*);
Jrd::dsql_nod* PASS1_statement(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*);