mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 23:23:04 +01:00
Fixed CORE-2041 - update or insert with gen_id() with wrong generator value
This commit is contained in:
parent
28209cb815
commit
5d4084d30c
@ -2640,14 +2640,18 @@ static void define_procedure(CompiledStatement* statement, NOD_TYPE op)
|
|||||||
|
|
||||||
put_local_variables(statement, procedure_node->nod_arg[e_prc_dcls], locals);
|
put_local_variables(statement, procedure_node->nod_arg[e_prc_dcls], locals);
|
||||||
|
|
||||||
|
statement->req_loop_level = 0;
|
||||||
|
statement->req_cursor_number = 0;
|
||||||
|
|
||||||
|
dsql_nod* stmtNode = PASS1_statement(statement, procedure_node->nod_arg[e_prc_body]);
|
||||||
|
GEN_hidden_variables(statement);
|
||||||
|
|
||||||
statement->append_uchar(blr_stall);
|
statement->append_uchar(blr_stall);
|
||||||
// put a label before body of procedure,
|
// put a label before body of procedure,
|
||||||
// so that any EXIT statement can get out
|
// so that any EXIT statement can get out
|
||||||
statement->append_uchar(blr_label);
|
statement->append_uchar(blr_label);
|
||||||
statement->append_uchar(0);
|
statement->append_uchar(0);
|
||||||
statement->req_loop_level = 0;
|
GEN_statement(statement, stmtNode);
|
||||||
statement->req_cursor_number = 0;
|
|
||||||
GEN_statement(statement, PASS1_statement(statement, procedure_node->nod_arg[e_prc_body]));
|
|
||||||
statement->req_type = REQ_DDL;
|
statement->req_type = REQ_DDL;
|
||||||
statement->append_uchar(blr_end);
|
statement->append_uchar(blr_end);
|
||||||
GEN_return(statement, procedure_node->nod_arg[e_prc_outputs], true);
|
GEN_return(statement, procedure_node->nod_arg[e_prc_outputs], true);
|
||||||
@ -2789,13 +2793,17 @@ void DDL_gen_block(CompiledStatement* statement, dsql_nod* node)
|
|||||||
|
|
||||||
put_local_variables(statement, node->nod_arg[e_exe_blk_dcls], locals);
|
put_local_variables(statement, node->nod_arg[e_exe_blk_dcls], locals);
|
||||||
|
|
||||||
|
statement->req_loop_level = 0;
|
||||||
|
|
||||||
|
dsql_nod* stmtNode = PASS1_statement(statement, node->nod_arg[e_exe_blk_body]);
|
||||||
|
GEN_hidden_variables(statement);
|
||||||
|
|
||||||
statement->append_uchar(blr_stall);
|
statement->append_uchar(blr_stall);
|
||||||
// Put a label before body of procedure, so that
|
// Put a label before body of procedure, so that
|
||||||
// any exit statement can get out
|
// any exit statement can get out
|
||||||
statement->append_uchar(blr_label);
|
statement->append_uchar(blr_label);
|
||||||
statement->append_uchar(0);
|
statement->append_uchar(0);
|
||||||
statement->req_loop_level = 0;
|
GEN_statement(statement, stmtNode);
|
||||||
GEN_statement(statement, PASS1_statement(statement, node->nod_arg[e_exe_blk_body]));
|
|
||||||
if (outputs)
|
if (outputs)
|
||||||
statement->req_type = REQ_SELECT_BLOCK;
|
statement->req_type = REQ_SELECT_BLOCK;
|
||||||
else
|
else
|
||||||
@ -3238,6 +3246,9 @@ static void define_trigger(CompiledStatement* statement, NOD_TYPE op)
|
|||||||
trigger_node->nod_arg[e_trg_actions]->nod_arg[e_trg_act_dcls], 0);
|
trigger_node->nod_arg[e_trg_actions]->nod_arg[e_trg_act_dcls], 0);
|
||||||
|
|
||||||
statement->req_scope_level++;
|
statement->req_scope_level++;
|
||||||
|
statement->req_loop_level = 0;
|
||||||
|
statement->req_cursor_number = 0;
|
||||||
|
actions = PASS1_statement(statement, actions);
|
||||||
// dimitr: I see no reason to deny EXIT command in triggers,
|
// dimitr: I see no reason to deny EXIT command in triggers,
|
||||||
// hence I've added zero label at the beginning.
|
// hence I've added zero label at the beginning.
|
||||||
// My first suspicion regarding an obvious conflict
|
// My first suspicion regarding an obvious conflict
|
||||||
@ -3247,9 +3258,8 @@ static void define_trigger(CompiledStatement* statement, NOD_TYPE op)
|
|||||||
// Hopefully, system triggers are never recompiled.
|
// Hopefully, system triggers are never recompiled.
|
||||||
statement->append_uchar(blr_label);
|
statement->append_uchar(blr_label);
|
||||||
statement->append_uchar(0);
|
statement->append_uchar(0);
|
||||||
statement->req_loop_level = 0;
|
GEN_hidden_variables(statement);
|
||||||
statement->req_cursor_number = 0;
|
GEN_statement(statement, actions);
|
||||||
GEN_statement(statement, PASS1_statement(statement, actions));
|
|
||||||
statement->req_scope_level--;
|
statement->req_scope_level--;
|
||||||
statement->append_uchar(blr_end);
|
statement->append_uchar(blr_end);
|
||||||
statement->end_blr();
|
statement->end_blr();
|
||||||
@ -6209,6 +6219,8 @@ static void put_local_variable( CompiledStatement* statement, dsql_var* variable
|
|||||||
|
|
||||||
statement->put_debug_variable(variable->var_variable_number,
|
statement->put_debug_variable(variable->var_variable_number,
|
||||||
variable->var_name);
|
variable->var_name);
|
||||||
|
|
||||||
|
++statement->req_hidden_vars_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -433,6 +433,7 @@ public:
|
|||||||
req_dt_context(p),
|
req_dt_context(p),
|
||||||
req_labels(p),
|
req_labels(p),
|
||||||
req_cursors(p),
|
req_cursors(p),
|
||||||
|
req_hidden_vars(p),
|
||||||
req_curr_ctes(p),
|
req_curr_ctes(p),
|
||||||
req_ctes(p),
|
req_ctes(p),
|
||||||
req_cte_aliases(p)
|
req_cte_aliases(p)
|
||||||
@ -539,6 +540,8 @@ public:
|
|||||||
USHORT req_client_dialect; //!< dialect passed into the API call
|
USHORT req_client_dialect; //!< dialect passed into the API call
|
||||||
USHORT req_in_outer_join; //!< processing inside outer-join part
|
USHORT req_in_outer_join; //!< processing inside outer-join part
|
||||||
dsql_str* req_alias_relation_prefix; //!< prefix for every relation-alias.
|
dsql_str* req_alias_relation_prefix; //!< prefix for every relation-alias.
|
||||||
|
DsqlNodStack req_hidden_vars; // hidden variables
|
||||||
|
USHORT req_hidden_vars_number; // next hidden variable number
|
||||||
|
|
||||||
DsqlNodStack req_curr_ctes; // current processing CTE's
|
DsqlNodStack req_curr_ctes; // current processing CTE's
|
||||||
class dsql_ctx* req_recursive_ctx; // context of recursive CTE
|
class dsql_ctx* req_recursive_ctx; // context of recursive CTE
|
||||||
|
@ -67,7 +67,6 @@ static void gen_cast(CompiledStatement*, const dsql_nod*);
|
|||||||
static void gen_coalesce(CompiledStatement*, const dsql_nod*);
|
static void gen_coalesce(CompiledStatement*, const dsql_nod*);
|
||||||
static void gen_constant(CompiledStatement*, const dsc*, bool);
|
static void gen_constant(CompiledStatement*, const dsc*, bool);
|
||||||
static void gen_constant(CompiledStatement*, dsql_nod*, bool);
|
static void gen_constant(CompiledStatement*, dsql_nod*, bool);
|
||||||
static void gen_descriptor(CompiledStatement*, const dsc*, bool);
|
|
||||||
static void gen_error_condition(CompiledStatement*, const dsql_nod*);
|
static void gen_error_condition(CompiledStatement*, const dsql_nod*);
|
||||||
static void gen_exec_stmt(CompiledStatement* statement, const dsql_nod* node);
|
static void gen_exec_stmt(CompiledStatement* statement, const dsql_nod* node);
|
||||||
static void gen_field(CompiledStatement*, const dsql_ctx*, const dsql_fld*, dsql_nod*);
|
static void gen_field(CompiledStatement*, const dsql_ctx*, const dsql_fld*, dsql_nod*);
|
||||||
@ -103,6 +102,29 @@ const bool NEGATE_VALUE = true;
|
|||||||
const bool USE_VALUE = false;
|
const bool USE_VALUE = false;
|
||||||
|
|
||||||
|
|
||||||
|
void GEN_hidden_variables(CompiledStatement* statement)
|
||||||
|
{
|
||||||
|
/**************************************
|
||||||
|
*
|
||||||
|
* G E N _ h i d d e n _ v a r i a b l e s
|
||||||
|
*
|
||||||
|
**************************************
|
||||||
|
*
|
||||||
|
* Function
|
||||||
|
* Emit BLR for hidden variables.
|
||||||
|
*
|
||||||
|
**************************************/
|
||||||
|
for (DsqlNodStack::const_iterator i(statement->req_hidden_vars);
|
||||||
|
i.hasData(); ++i)
|
||||||
|
{
|
||||||
|
dsql_var* var = ((dsql_var*) i.object()->nod_arg[e_var_variable]);
|
||||||
|
statement->append_uchar(blr_dcl_variable);
|
||||||
|
statement->append_ushort(var->var_variable_number);
|
||||||
|
GEN_descriptor(statement, &i.object()->nod_desc, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
GEN_expr
|
GEN_expr
|
||||||
@ -694,7 +716,7 @@ void GEN_port(CompiledStatement* statement, dsql_msg* message)
|
|||||||
parameter->par_desc.dsc_address = (UCHAR*)(IPTR) offset;
|
parameter->par_desc.dsc_address = (UCHAR*)(IPTR) offset;
|
||||||
offset += parameter->par_desc.dsc_length;
|
offset += parameter->par_desc.dsc_length;
|
||||||
// if (statement->req_blr_string)
|
// if (statement->req_blr_string)
|
||||||
gen_descriptor(statement, ¶meter->par_desc, false);
|
GEN_descriptor(statement, ¶meter->par_desc, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset > MAX_FORMAT_SIZE) {
|
if (offset > MAX_FORMAT_SIZE) {
|
||||||
@ -758,6 +780,8 @@ void GEN_request( CompiledStatement* statement, dsql_nod* node)
|
|||||||
{
|
{
|
||||||
stuff(statement, blr_begin);
|
stuff(statement, blr_begin);
|
||||||
|
|
||||||
|
GEN_hidden_variables(statement);
|
||||||
|
|
||||||
switch (statement->req_type)
|
switch (statement->req_type)
|
||||||
{
|
{
|
||||||
case REQ_SELECT:
|
case REQ_SELECT:
|
||||||
@ -1033,13 +1057,15 @@ void GEN_statement( CompiledStatement* statement, dsql_nod* node)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case nod_list:
|
case nod_list:
|
||||||
stuff(statement, blr_begin);
|
if (!(node->nod_flags & NOD_SIMPLE_LIST))
|
||||||
|
stuff(statement, blr_begin);
|
||||||
for (ptr = node->nod_arg, end = ptr + node->nod_count; ptr < end;
|
for (ptr = node->nod_arg, end = ptr + node->nod_count; ptr < end;
|
||||||
ptr++)
|
ptr++)
|
||||||
{
|
{
|
||||||
GEN_statement(statement, *ptr);
|
GEN_statement(statement, *ptr);
|
||||||
}
|
}
|
||||||
stuff(statement, blr_end);
|
if (!(node->nod_flags & NOD_SIMPLE_LIST))
|
||||||
|
stuff(statement, blr_end);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case nod_erase:
|
case nod_erase:
|
||||||
@ -1382,7 +1408,7 @@ static void gen_coalesce( CompiledStatement* statement, const dsql_nod* node)
|
|||||||
// blr_value_if is used for building the coalesce function
|
// blr_value_if is used for building the coalesce function
|
||||||
dsql_nod* list = node->nod_arg[0];
|
dsql_nod* list = node->nod_arg[0];
|
||||||
stuff(statement, blr_cast);
|
stuff(statement, blr_cast);
|
||||||
gen_descriptor(statement, &node->nod_desc, true);
|
GEN_descriptor(statement, &node->nod_desc, true);
|
||||||
dsql_nod* const* ptr = list->nod_arg;
|
dsql_nod* const* ptr = list->nod_arg;
|
||||||
for (const dsql_nod* const* const end = ptr + (list->nod_count - 1);
|
for (const dsql_nod* const* const end = ptr + (list->nod_count - 1);
|
||||||
ptr < end; ptr++)
|
ptr < end; ptr++)
|
||||||
@ -1427,7 +1453,7 @@ static void gen_constant( CompiledStatement* statement, const dsc* desc, bool ne
|
|||||||
|
|
||||||
switch (desc->dsc_dtype) {
|
switch (desc->dsc_dtype) {
|
||||||
case dtype_short:
|
case dtype_short:
|
||||||
gen_descriptor(statement, desc, true);
|
GEN_descriptor(statement, desc, true);
|
||||||
value = *(SSHORT *) p;
|
value = *(SSHORT *) p;
|
||||||
if (negate_value)
|
if (negate_value)
|
||||||
value = -value;
|
value = -value;
|
||||||
@ -1435,7 +1461,7 @@ static void gen_constant( CompiledStatement* statement, const dsc* desc, bool ne
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_long:
|
case dtype_long:
|
||||||
gen_descriptor(statement, desc, true);
|
GEN_descriptor(statement, desc, true);
|
||||||
value = *(SLONG *) p;
|
value = *(SLONG *) p;
|
||||||
if (negate_value)
|
if (negate_value)
|
||||||
value = -value;
|
value = -value;
|
||||||
@ -1446,7 +1472,7 @@ static void gen_constant( CompiledStatement* statement, const dsc* desc, bool ne
|
|||||||
|
|
||||||
case dtype_sql_time:
|
case dtype_sql_time:
|
||||||
case dtype_sql_date:
|
case dtype_sql_date:
|
||||||
gen_descriptor(statement, desc, true);
|
GEN_descriptor(statement, desc, true);
|
||||||
value = *(SLONG *) p;
|
value = *(SLONG *) p;
|
||||||
stuff_word(statement, value);
|
stuff_word(statement, value);
|
||||||
stuff_word(statement, value >> 16);
|
stuff_word(statement, value >> 16);
|
||||||
@ -1457,7 +1483,7 @@ static void gen_constant( CompiledStatement* statement, const dsc* desc, bool ne
|
|||||||
/* this is used for approximate/large numeric literal
|
/* this is used for approximate/large numeric literal
|
||||||
which is transmitted to the engine as a string.
|
which is transmitted to the engine as a string.
|
||||||
*/
|
*/
|
||||||
gen_descriptor(statement, desc, true);
|
GEN_descriptor(statement, desc, true);
|
||||||
// Length of string literal, cast because it could be > 127 bytes.
|
// Length of string literal, cast because it could be > 127 bytes.
|
||||||
const USHORT l = (USHORT)(UCHAR) desc->dsc_scale;
|
const USHORT l = (USHORT)(UCHAR) desc->dsc_scale;
|
||||||
if (negate_value) {
|
if (negate_value) {
|
||||||
@ -1521,7 +1547,7 @@ static void gen_constant( CompiledStatement* statement, const dsc* desc, bool ne
|
|||||||
case dtype_blob:
|
case dtype_blob:
|
||||||
case dtype_array:
|
case dtype_array:
|
||||||
case dtype_timestamp:
|
case dtype_timestamp:
|
||||||
gen_descriptor(statement, desc, true);
|
GEN_descriptor(statement, desc, true);
|
||||||
value = *(SLONG *) p;
|
value = *(SLONG *) p;
|
||||||
stuff_word(statement, value);
|
stuff_word(statement, value);
|
||||||
stuff_word(statement, value >> 16);
|
stuff_word(statement, value >> 16);
|
||||||
@ -1534,7 +1560,7 @@ static void gen_constant( CompiledStatement* statement, const dsc* desc, bool ne
|
|||||||
{
|
{
|
||||||
const USHORT length = desc->dsc_length;
|
const USHORT length = desc->dsc_length;
|
||||||
|
|
||||||
gen_descriptor(statement, desc, true);
|
GEN_descriptor(statement, desc, true);
|
||||||
if (length)
|
if (length)
|
||||||
statement->append_raw_string(p, length);
|
statement->append_raw_string(p, length);
|
||||||
}
|
}
|
||||||
@ -1571,7 +1597,7 @@ static void gen_constant( CompiledStatement* statement, dsql_nod* node, bool neg
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
gen_descriptor
|
GEN_descriptor
|
||||||
|
|
||||||
@brief Generate a blr descriptor from an internal descriptor.
|
@brief Generate a blr descriptor from an internal descriptor.
|
||||||
|
|
||||||
@ -1581,7 +1607,7 @@ static void gen_constant( CompiledStatement* statement, dsql_nod* node, bool neg
|
|||||||
@param texttype
|
@param texttype
|
||||||
|
|
||||||
**/
|
**/
|
||||||
static void gen_descriptor( CompiledStatement* statement, const dsc* desc, bool texttype)
|
void GEN_descriptor( CompiledStatement* statement, const dsc* desc, bool texttype)
|
||||||
{
|
{
|
||||||
switch (desc->dsc_dtype) {
|
switch (desc->dsc_dtype) {
|
||||||
case dtype_text:
|
case dtype_text:
|
||||||
@ -2417,7 +2443,7 @@ static void gen_searched_case( CompiledStatement* statement, const dsql_nod* nod
|
|||||||
// blr_value_if is used for building the case expression
|
// blr_value_if is used for building the case expression
|
||||||
|
|
||||||
stuff(statement, blr_cast);
|
stuff(statement, blr_cast);
|
||||||
gen_descriptor(statement, &node->nod_desc, true);
|
GEN_descriptor(statement, &node->nod_desc, true);
|
||||||
const SSHORT count =
|
const SSHORT count =
|
||||||
node->nod_arg[e_searched_case_search_conditions]->nod_count;
|
node->nod_arg[e_searched_case_search_conditions]->nod_count;
|
||||||
dsql_nod* boolean_list = node->nod_arg[e_searched_case_search_conditions];
|
dsql_nod* boolean_list = node->nod_arg[e_searched_case_search_conditions];
|
||||||
@ -2637,7 +2663,7 @@ static void gen_simple_case( CompiledStatement* statement, const dsql_nod* node)
|
|||||||
// blr_value_if is used for building the case expression
|
// blr_value_if is used for building the case expression
|
||||||
|
|
||||||
stuff(statement, blr_cast);
|
stuff(statement, blr_cast);
|
||||||
gen_descriptor(statement, &node->nod_desc, true);
|
GEN_descriptor(statement, &node->nod_desc, true);
|
||||||
SSHORT count = node->nod_arg[e_simple_case_when_operands]->nod_count;
|
SSHORT count = node->nod_arg[e_simple_case_when_operands]->nod_count;
|
||||||
dsql_nod* when_list = node->nod_arg[e_simple_case_when_operands];
|
dsql_nod* when_list = node->nod_arg[e_simple_case_when_operands];
|
||||||
dsql_nod* results_list = node->nod_arg[e_simple_case_results];
|
dsql_nod* results_list = node->nod_arg[e_simple_case_results];
|
||||||
|
@ -24,7 +24,9 @@
|
|||||||
#ifndef DSQL_GEN_PROTO_H
|
#ifndef DSQL_GEN_PROTO_H
|
||||||
#define DSQL_GEN_PROTO_H
|
#define DSQL_GEN_PROTO_H
|
||||||
|
|
||||||
|
void GEN_descriptor(Jrd::CompiledStatement* statement, const dsc* desc, bool texttype);
|
||||||
void GEN_expr(Jrd::CompiledStatement*, Jrd::dsql_nod*);
|
void GEN_expr(Jrd::CompiledStatement*, Jrd::dsql_nod*);
|
||||||
|
void GEN_hidden_variables(Jrd::CompiledStatement* statement);
|
||||||
void GEN_port(Jrd::CompiledStatement*, Jrd::dsql_msg*);
|
void GEN_port(Jrd::CompiledStatement*, Jrd::dsql_msg*);
|
||||||
void GEN_request(Jrd::CompiledStatement*, Jrd::dsql_nod*);
|
void GEN_request(Jrd::CompiledStatement*, Jrd::dsql_nod*);
|
||||||
void GEN_return(Jrd::CompiledStatement*, const Jrd::dsql_nod*, bool);
|
void GEN_return(Jrd::CompiledStatement*, const Jrd::dsql_nod*, bool);
|
||||||
|
@ -1836,7 +1836,8 @@ dsql_nod* MAKE_variable(dsql_fld* field, const TEXT* name, const dsql_var_type t
|
|||||||
strcpy(variable->var_name, name);
|
strcpy(variable->var_name, name);
|
||||||
//variable->var_flags = 0;
|
//variable->var_flags = 0;
|
||||||
variable->var_type = type;
|
variable->var_type = type;
|
||||||
MAKE_desc_from_field(&node->nod_desc, field);
|
if (field)
|
||||||
|
MAKE_desc_from_field(&node->nod_desc, field);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@ -2006,7 +2007,8 @@ static void make_parameter_names(dsql_par* parameter, const dsql_nod* item)
|
|||||||
case nod_variable:
|
case nod_variable:
|
||||||
{
|
{
|
||||||
dsql_var* variable = (dsql_var*) item->nod_arg[e_var_variable];
|
dsql_var* variable = (dsql_var*) item->nod_arg[e_var_variable];
|
||||||
name_alias = variable->var_field->fld_name.c_str();
|
if (variable->var_field)
|
||||||
|
name_alias = variable->var_field->fld_name.c_str();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case nod_udf:
|
case nod_udf:
|
||||||
|
@ -1043,6 +1043,7 @@ enum nod_flags_vals {
|
|||||||
|
|
||||||
NOD_UNION_ALL = 1, // nod_list
|
NOD_UNION_ALL = 1, // nod_list
|
||||||
NOD_UNION_RECURSIVE = 2,
|
NOD_UNION_RECURSIVE = 2,
|
||||||
|
NOD_SIMPLE_LIST = 4, // no need to enclose with blr_begin ... blr_end
|
||||||
|
|
||||||
NOD_READ_ONLY = 1, // nod_access
|
NOD_READ_ONLY = 1, // nod_access
|
||||||
NOD_READ_WRITE = 2,
|
NOD_READ_WRITE = 2,
|
||||||
|
@ -241,6 +241,7 @@ static bool pass1_found_aggregate(const dsql_nod*, USHORT, USHORT, bool);
|
|||||||
static bool pass1_found_field(const dsql_nod*, USHORT, USHORT, bool*);
|
static bool pass1_found_field(const dsql_nod*, USHORT, USHORT, bool*);
|
||||||
static bool pass1_found_sub_select(const dsql_nod*);
|
static bool pass1_found_sub_select(const dsql_nod*);
|
||||||
static dsql_nod* pass1_group_by_list(CompiledStatement*, dsql_nod*, dsql_nod*);
|
static dsql_nod* pass1_group_by_list(CompiledStatement*, dsql_nod*, dsql_nod*);
|
||||||
|
static dsql_nod* pass1_hidden_variable(CompiledStatement* statement, dsql_nod* value);
|
||||||
static dsql_nod* pass1_insert(CompiledStatement*, dsql_nod*, bool);
|
static dsql_nod* pass1_insert(CompiledStatement*, dsql_nod*, bool);
|
||||||
static dsql_nod* pass1_join(CompiledStatement*, dsql_nod*);
|
static dsql_nod* pass1_join(CompiledStatement*, dsql_nod*);
|
||||||
static dsql_nod* pass1_label(CompiledStatement*, dsql_nod*);
|
static dsql_nod* pass1_label(CompiledStatement*, dsql_nod*);
|
||||||
@ -6155,6 +6156,30 @@ static dsql_nod* pass1_group_by_list(CompiledStatement* statement, dsql_nod* inp
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Create (if necessary) a hidden variable to store a temporary value.
|
||||||
|
static dsql_nod* pass1_hidden_variable(CompiledStatement* statement, dsql_nod* value)
|
||||||
|
{
|
||||||
|
// For some node types, it's better to not create temporary value.
|
||||||
|
switch (value->nod_type)
|
||||||
|
{
|
||||||
|
case nod_constant:
|
||||||
|
case nod_dbkey:
|
||||||
|
case nod_field:
|
||||||
|
case nod_parameter:
|
||||||
|
case nod_user_name:
|
||||||
|
case nod_variable:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dsql_nod* var = MAKE_variable(NULL, "", VAR_local, 0, 0, statement->req_hidden_vars_number++);
|
||||||
|
MAKE_desc(statement, &var->nod_desc, value, NULL);
|
||||||
|
|
||||||
|
statement->req_hidden_vars.push(var);
|
||||||
|
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
pass1_insert
|
pass1_insert
|
||||||
@ -9286,6 +9311,8 @@ static dsql_nod* pass1_update_or_insert(CompiledStatement* statement, dsql_nod*
|
|||||||
dsql_nod* match = NULL;
|
dsql_nod* match = NULL;
|
||||||
USHORT match_count = 0;
|
USHORT match_count = 0;
|
||||||
|
|
||||||
|
DsqlNodStack varStack;
|
||||||
|
|
||||||
DsqlNodStack stack;
|
DsqlNodStack stack;
|
||||||
dsql_nod** field_ptr = fields->nod_arg;
|
dsql_nod** field_ptr = fields->nod_arg;
|
||||||
dsql_nod** value_ptr = values->nod_arg;
|
dsql_nod** value_ptr = values->nod_arg;
|
||||||
@ -9296,12 +9323,12 @@ static dsql_nod* pass1_update_or_insert(CompiledStatement* statement, dsql_nod*
|
|||||||
DEV_BLKCHK(*field_ptr, dsql_type_nod);
|
DEV_BLKCHK(*field_ptr, dsql_type_nod);
|
||||||
DEV_BLKCHK(*value_ptr, dsql_type_nod);
|
DEV_BLKCHK(*value_ptr, dsql_type_nod);
|
||||||
|
|
||||||
dsql_nod* temp = MAKE_node(nod_assign, e_asgn_count);
|
dsql_nod* assign = MAKE_node(nod_assign, e_asgn_count);
|
||||||
temp->nod_arg[e_asgn_value] = *value_ptr;
|
assign->nod_arg[e_asgn_value] = *value_ptr;
|
||||||
temp->nod_arg[e_asgn_field] = *field_ptr;
|
assign->nod_arg[e_asgn_field] = *field_ptr;
|
||||||
stack.push(temp);
|
stack.push(assign);
|
||||||
|
|
||||||
temp = *value_ptr;
|
dsql_nod* temp = *value_ptr;
|
||||||
dsql_nod* temp2 = insert->nod_arg[e_sto_statement]->nod_arg[field_ptr - fields->nod_arg]->nod_arg[1];
|
dsql_nod* temp2 = insert->nod_arg[e_sto_statement]->nod_arg[field_ptr - fields->nod_arg]->nod_arg[1];
|
||||||
set_parameter_type(statement, temp, temp2, false);
|
set_parameter_type(statement, temp, temp2, false);
|
||||||
|
|
||||||
@ -9337,9 +9364,25 @@ static dsql_nod* pass1_update_or_insert(CompiledStatement* statement, dsql_nod*
|
|||||||
{
|
{
|
||||||
++match_count;
|
++match_count;
|
||||||
|
|
||||||
|
dsql_nod*& expr = insert->nod_arg[e_sto_statement]->nod_arg[
|
||||||
|
field_ptr - fields->nod_arg]->nod_arg[0];
|
||||||
|
dsql_nod* var = pass1_hidden_variable(statement, expr);
|
||||||
|
|
||||||
|
if (var)
|
||||||
|
{
|
||||||
|
temp = MAKE_node(nod_assign, e_asgn_count);
|
||||||
|
temp->nod_arg[e_asgn_value] = expr;
|
||||||
|
temp->nod_arg[e_asgn_field] = var;
|
||||||
|
varStack.push(temp);
|
||||||
|
|
||||||
|
assign->nod_arg[e_asgn_value] = expr = var;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
var = *value_ptr;
|
||||||
|
|
||||||
dsql_nod* eql = MAKE_node(equality_type, 2);
|
dsql_nod* eql = MAKE_node(equality_type, 2);
|
||||||
eql->nod_arg[0] = *field_ptr;
|
eql->nod_arg[0] = *field_ptr;
|
||||||
eql->nod_arg[1] = *value_ptr;
|
eql->nod_arg[1] = var;
|
||||||
|
|
||||||
if (match)
|
if (match)
|
||||||
{
|
{
|
||||||
@ -9424,9 +9467,11 @@ static dsql_nod* pass1_update_or_insert(CompiledStatement* statement, dsql_nod*
|
|||||||
if_nod->nod_arg[e_if_true] = insert;
|
if_nod->nod_arg[e_if_true] = insert;
|
||||||
|
|
||||||
// build the UPDATE / IF nodes
|
// build the UPDATE / IF nodes
|
||||||
dsql_nod* list = MAKE_node(nod_list, 2);
|
dsql_nod* list = MAKE_node(nod_list, 3);
|
||||||
list->nod_arg[0] = update;
|
list->nod_arg[0] = MAKE_list(varStack);
|
||||||
list->nod_arg[1] = if_nod;
|
list->nod_arg[0]->nod_flags |= NOD_SIMPLE_LIST;
|
||||||
|
list->nod_arg[1] = update;
|
||||||
|
list->nod_arg[2] = if_nod;
|
||||||
|
|
||||||
// if RETURNING is present, req_type is already REQ_EXEC_PROCEDURE
|
// if RETURNING is present, req_type is already REQ_EXEC_PROCEDURE
|
||||||
if (!input->nod_arg[e_upi_return])
|
if (!input->nod_arg[e_upi_return])
|
||||||
|
Loading…
Reference in New Issue
Block a user