8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 20:03:02 +01:00

Rename REPLACE to UPDATE OR INSERT

This commit is contained in:
asfernandes 2006-11-26 15:40:10 +00:00
parent c964124a20
commit 5e818bd4a9
14 changed files with 298 additions and 305 deletions

View File

@ -1,5 +1,5 @@
-----------------
REPLACE statement
UPDATE OR INSERT statement
-----------------
Function:
@ -9,7 +9,7 @@ REPLACE statement
Adriano dos Santos Fernandes <adrianosf@uol.com.br>
Syntax rules:
REPLACE INTO <table or view> [(<column_list>)]
UPDATE OR INSERT INTO <table or view> [(<column_list>)]
VALUES (<value_list>)
[MATCHING <column_list>]
[RETURNING <column_list> [INTO <variable_list>]]
@ -18,9 +18,9 @@ REPLACE statement
DSQL, PSQL
Examples:
1. REPLACE INTO T1 (F1, F2) VALUES (:F1, :F2);
2. REPLACE INTO EMPLOYEE (ID, NAME) VALUES (:ID, :NAME) RETURNING ID;
3. REPLACE INTO T1 (F1, F2) VALUES (:F1, :F2) MATCHING (F1);
1. UPDATE OR INSERT INTO T1 (F1, F2) VALUES (:F1, :F2);
2. UPDATE OR INSERT INTO EMPLOYEE (ID, NAME) VALUES (:ID, :NAME) RETURNING ID;
3. UPDATE OR INSERT INTO T1 (F1, F2) VALUES (:F1, :F2) MATCHING (F1);
Notes:
1. Views are only allowed if it's based on only one table (i.e. no joins or unions).

View File

@ -1270,12 +1270,12 @@ C --
PARAMETER (GDS__dsql_feature_not_supported_ods = 336003097)
INTEGER*4 GDS__primary_key_required
PARAMETER (GDS__primary_key_required = 336003098)
INTEGER*4 GDS__replace_doesnt_match_pk
PARAMETER (GDS__replace_doesnt_match_pk = 336003099)
INTEGER*4 GDS__replace_doesnt_match_matching
PARAMETER (GDS__replace_doesnt_match_matching = 336003100)
INTEGER*4 GDS__replace_with_complex_view
PARAMETER (GDS__replace_with_complex_view = 336003101)
INTEGER*4 GDS__upd_ins_doesnt_match_pk
PARAMETER (GDS__upd_ins_doesnt_match_pk = 336003099)
INTEGER*4 GDS__upd_ins_doesnt_match_matching
PARAMETER (GDS__upd_ins_doesnt_match_matching = 336003100)
INTEGER*4 GDS__upd_ins_with_complex_view
PARAMETER (GDS__upd_ins_with_complex_view = 336003101)
INTEGER*4 GDS__dsql_incompatible_trigger_type
PARAMETER (GDS__dsql_incompatible_trigger_type = 336003102)
INTEGER*4 GDS__dsql_db_trigger_type_cant_change

View File

@ -642,9 +642,9 @@ const
gds_dsql_type_not_supp_ext_tab = 336003096;
gds_dsql_feature_not_supported_ods = 336003097;
gds_primary_key_required = 336003098;
gds_replace_doesnt_match_pk = 336003099;
gds_replace_doesnt_match_matching = 336003100;
gds_replace_with_complex_view = 336003101;
gds_upd_ins_doesnt_match_pk = 336003099;
gds_upd_ins_doesnt_match_matching = 336003100;
gds_upd_ins_with_complex_view = 336003101;
gds_dsql_incompatible_trigger_type = 336003102;
gds_dsql_db_trigger_type_cant_change = 336003103;
gds_dyn_role_does_not_exist = 336068796;

View File

@ -2834,10 +2834,6 @@ void DSQL_pretty(const dsql_nod* node, int column)
verb = "with";
break;
case nod_replace:
verb = "replace";
break;
default:
sprintf(s, "unknown type %d", node->nod_type);
verb = s;

View File

@ -246,7 +246,6 @@ static const TOK tokens[] =
{RECURSIVE, "RECURSIVE", 2, false},
{REFERENCES, "REFERENCES", 1, false},
{RELEASE, "RELEASE", 2, false},
{REPLACE, "REPLACE", 2, false},
{REQUESTS, "REQUESTS", 2, true},
{RESERVING, "RESERV", 1, false}, // Alias of RESERVING
{RESERVING, "RESERVING", 1, false},

View File

@ -347,7 +347,7 @@ enum nod_t
nod_agg_list,
nod_src_info,
nod_with,
nod_replace,
nod_update_or_insert,
nod_merge,
nod_merge_when, // 280
nod_merge_update,
@ -633,12 +633,12 @@ enum node_args {
e_sto_return,
e_sto_count,
e_rep_relation = 0, // nod_replace
e_rep_fields,
e_rep_values,
e_rep_matching,
e_rep_return,
e_rep_count,
e_upi_relation = 0, // nod_update_or_insert
e_upi_fields,
e_upi_values,
e_upi_matching,
e_upi_return,
e_upi_count,
e_del_relation = 0, // nod_delete
e_del_boolean,

View File

@ -523,7 +523,6 @@ static LexerState lex;
%token PAD
%token PRESERVE
%token RECURSIVE
%token REPLACE
%token SENSITIVE
%token SPACE
%token START
@ -578,13 +577,13 @@ statement : alter
| exec_procedure
| exec_block
| recreate
| replace
| revoke
| rollback
| savepoint
| select
| set
| update
| update_or_insert
| KW_DEBUG signed_short_integer
{ prepare_console_debug ((IPTR) $2, &yydebug);
$$ = make_node (nod_null, (int) 0, NULL); }
@ -1626,8 +1625,8 @@ stmt_start_column :
simple_proc_statement : assignment
| insert
| merge
| replace
| update
| update_or_insert
| delete
| singleton_select
| exec_procedure
@ -3579,20 +3578,20 @@ update_positioned : UPDATE table_name SET assignments cursor_clause
;
/* REPLACE statement */
/* UPDATE OR INSERT statement */
replace
: REPLACE INTO simple_table_name ins_column_parens_opt
update_or_insert
: UPDATE OR INSERT INTO simple_table_name ins_column_parens_opt
VALUES '(' value_list ')'
replace_matching_opt
update_or_insert_matching_opt
returning_clause
{
$$ = make_node (nod_replace, (int) e_rep_count,
$3, make_list ($4), make_list ($7), $9, $10);
$$ = make_node (nod_update_or_insert, (int) e_upi_count,
$5, make_list ($6), make_list ($9), $11, $12);
}
;
replace_matching_opt
update_or_insert_matching_opt
: MATCHING ins_column_parens
{ $$ = $2; }
|
@ -4549,7 +4548,6 @@ non_reserved_word :
| MATCHING
| PAD
| PRESERVE
| REPLACE
| SPACE
| TEMPORARY
;

View File

@ -235,7 +235,6 @@ static dsql_nod* pass1_merge(dsql_req*, dsql_nod*, bool);
static dsql_nod* pass1_not(dsql_req*, const dsql_nod*, bool, bool);
static void pass1_put_args_on_stack(dsql_req*, dsql_nod*, DsqlNodStack&, bool);
static dsql_nod* pass1_relation(dsql_req*, dsql_nod*);
static dsql_nod* pass1_replace(dsql_req*, dsql_nod*, bool);
static dsql_nod* pass1_returning(dsql_req*, const dsql_nod*, bool);
static dsql_nod* pass1_rse(dsql_req*, dsql_nod*, dsql_nod*, dsql_nod*, dsql_nod*, USHORT);
static dsql_nod* pass1_rse_impl(dsql_req*, dsql_nod*, dsql_nod*, dsql_nod*, dsql_nod*, USHORT);
@ -250,6 +249,7 @@ static dsql_nod* pass1_union(dsql_req*, dsql_nod*, dsql_nod*, dsql_nod*, USHORT)
static void pass1_union_auto_cast(dsql_nod*, const dsc&, SSHORT,
bool in_select_list = false);
static dsql_nod* pass1_update(dsql_req*, dsql_nod*, bool);
static dsql_nod* pass1_update_or_insert(dsql_req*, dsql_nod*, bool);
static dsql_nod* pass1_variable(dsql_req*, dsql_nod*);
static dsql_nod* post_map(dsql_nod*, dsql_ctx*);
static dsql_nod* remap_field(dsql_req*, dsql_nod*, dsql_ctx*, USHORT);
@ -661,7 +661,7 @@ dsql_nod* PASS1_node(dsql_req* request, dsql_nod* input, bool proc_flag)
case nod_delete:
case nod_insert:
case nod_merge:
case nod_replace:
case nod_update_or_insert:
case nod_order:
case nod_select:
case nod_with:
@ -1840,8 +1840,8 @@ dsql_nod* PASS1_statement(dsql_req* request, dsql_nod* input, bool proc_flag)
return input;
}
case nod_replace:
node = pass1_savepoint(request, pass1_replace(request, input, proc_flag));
case nod_update_or_insert:
node = pass1_savepoint(request, pass1_update_or_insert(request, input, proc_flag));
break;
default:
@ -6951,249 +6951,6 @@ static dsql_rel* pass1_base_table( dsql_req* request, const dsql_rel* relation,
}
/**
pass1_replace
@brief Process REPLACE statement.
@param request
@param input
@param proc_flag
**/
static dsql_nod* pass1_replace(dsql_req* request, dsql_nod* input, bool proc_flag)
{
DEV_BLKCHK(request, dsql_type_req);
DEV_BLKCHK(input, dsql_type_nod);
dsql_str* relation_name =
(dsql_str*) input->nod_arg[e_rep_relation]->nod_arg[e_rpn_name];
dsql_str* base_name = relation_name;
dsql_nod* values = input->nod_arg[e_rep_values];
// build the INSERT node
dsql_nod* insert = MAKE_node(nod_insert, e_ins_count);
insert->nod_arg[e_ins_relation] = input->nod_arg[e_rep_relation];
insert->nod_arg[e_ins_fields] = input->nod_arg[e_rep_fields];
insert->nod_arg[e_ins_values] = values;
insert->nod_arg[e_ins_return] = input->nod_arg[e_rep_return];
insert = pass1_insert(request, insert, proc_flag);
// PASS1_statement will transform nod_insert to nod_store
fb_assert(insert->nod_type == nod_store);
dsql_ctx* context = (dsql_ctx*) insert->nod_arg[e_sto_relation]->nod_arg[e_rel_context];
DEV_BLKCHK(context, dsql_type_ctx);
dsql_rel* relation = context->ctx_relation;
dsql_nod* fields = input->nod_arg[e_rep_fields];
// if a field list isn't present, build one using the same
// rules of INSERT INTO table VALUES ...
if (!fields)
fields = explode_fields(relation);
// maintain a pair of view's field name / base field name
MetaNamePairMap view_fields;
if ((relation->rel_flags & REL_view) && !input->nod_arg[e_rep_matching])
{
dsql_rel* base_rel =
METD_get_view_base(request, relation_name->str_data, view_fields);
// get the base table name if there is only one
if (base_rel)
base_name = MAKE_cstring(base_rel->rel_name);
else
ERRD_post(isc_replace_with_complex_view, 0);
}
dsql_nod* matching = input->nod_arg[e_rep_matching];
if (matching)
{
request->req_context->push(context);
request->req_scope_level++;
dsql_nod* matching_fields = PASS1_node(request, matching, false);
request->req_scope_level--;
request->req_context->pop();
field_appears_once(matching_fields, matching, true, "REPLACE");
}
else
{
matching = METD_get_primary_key(request, base_name);
if (!matching)
{
ERRD_post(isc_primary_key_required,
isc_arg_string, base_name->str_data,
0);
}
}
// build a boolean to use in the UPDATE statement
dsql_nod* match = NULL;
USHORT match_count = 0;
DsqlNodStack stack;
dsql_nod** field_ptr = fields->nod_arg;
dsql_nod** value_ptr = values->nod_arg;
for (const dsql_nod* const* const field_end = field_ptr + fields->nod_count;
field_ptr < field_end; field_ptr++, value_ptr++)
{
DEV_BLKCHK(*field_ptr, dsql_type_nod);
DEV_BLKCHK(*value_ptr, dsql_type_nod);
dsql_nod* temp = MAKE_node(nod_assign, e_asgn_count);
temp->nod_arg[e_asgn_value] = *value_ptr;
temp->nod_arg[e_asgn_field] = *field_ptr;
stack.push(temp);
temp = *value_ptr;
dsql_nod* temp2 = insert->nod_arg[e_sto_statement]->nod_arg[field_ptr - fields->nod_arg]->nod_arg[1];
set_parameter_type(request, temp, temp2, false);
fb_assert((*field_ptr)->nod_type == nod_field_name);
// When relation is a view and MATCHING was not specified, field_name
// stores the base field name that is what we should find in the primary
// key of base table.
Firebird::MetaName field_name;
if ((relation->rel_flags & REL_view) && !input->nod_arg[e_rep_matching])
{
view_fields.get(
Firebird::MetaName(((dsql_str*) (*field_ptr)->nod_arg[e_fln_name])->str_data),
field_name);
}
else
field_name = ((dsql_str*) (*field_ptr)->nod_arg[e_fln_name])->str_data;
if (field_name.hasData())
{
dsql_nod** matching_ptr = matching->nod_arg;
for (const dsql_nod* const* const matching_end = matching_ptr + matching->nod_count;
matching_ptr < matching_end; matching_ptr++)
{
DEV_BLKCHK(*matching_ptr, dsql_type_nod);
fb_assert((*matching_ptr)->nod_type == nod_field_name);
if (Firebird::MetaName(((dsql_str*)
(*matching_ptr)->nod_arg[e_fln_name])->str_data) ==
field_name)
{
++match_count;
dsql_nod* eql = MAKE_node(nod_eql, 2);
eql->nod_arg[0] = *field_ptr;
eql->nod_arg[1] = *value_ptr;
if (match)
{
// It's a composed MATCHING. Build an AND.
dsql_nod* and_node = MAKE_node(nod_and, 2);
and_node->nod_arg[0] = match;
and_node->nod_arg[1] = eql;
match = and_node;
}
else
match = eql;
}
}
}
}
// check if implicit or explicit MATCHING is valid
if (match_count != matching->nod_count)
{
if (input->nod_arg[e_rep_matching])
ERRD_post(isc_replace_doesnt_match_matching, 0);
else
{
ERRD_post(isc_replace_doesnt_match_pk,
isc_arg_string, base_name->str_data,
0);
}
}
// build the UPDATE node
dsql_nod* update = MAKE_node(nod_update, e_upd_count);
update->nod_arg[e_upd_relation] = input->nod_arg[e_rep_relation];
update->nod_arg[e_upd_statement] = MAKE_list(stack);
update->nod_arg[e_upd_boolean] = match;
if (input->nod_arg[e_rep_return])
{
update->nod_arg[e_upd_rse_flags] = (dsql_nod*) NOD_SELECT_EXPR_SINGLETON;
dsql_nod* store_ret = insert->nod_arg[e_sto_return];
// nod_returning was already processed
fb_assert(store_ret->nod_type == nod_list);
// And we create an already processed RETURNING, because
// nod_returning creates parameters and they're already
// created by the INSERT statement.
dsql_nod* update_ret = update->nod_arg[e_upd_return] =
MAKE_node(nod_list, store_ret->nod_count);
dsql_nod** src_ptr = input->nod_arg[e_rep_return]->nod_arg[e_ret_source]->nod_arg;
dsql_nod** dst_ptr = store_ret->nod_arg;
dsql_nod** ptr = update_ret->nod_arg;
for (const dsql_nod* const* const end = ptr + update_ret->nod_count;
ptr < end; src_ptr++, dst_ptr++, ptr++)
{
dsql_nod* temp = MAKE_node(nod_assign, e_asgn_count);
temp->nod_arg[e_asgn_value] = *src_ptr;
temp->nod_arg[e_asgn_field] = (*dst_ptr)->nod_arg[1];
*ptr = temp;
}
}
update = pass1_update(request, update, proc_flag);
// PASS1_statement will transform nod_update to nod_modify
fb_assert(update->nod_type == nod_modify);
// test if ROW_COUNT = 0
dsql_nod* eql = MAKE_node(nod_eql, 2);
eql->nod_arg[0] = MAKE_node(nod_internal_info, e_internal_info_count);
eql->nod_arg[0]->nod_arg[e_internal_info] =
MAKE_constant((dsql_str*) internal_rows_affected, CONSTANT_SLONG);
eql->nod_arg[1] = MAKE_constant((dsql_str*) 0, CONSTANT_SLONG);
USHORT req_flags = request->req_flags;
request->req_flags |= REQ_block; // to compile ROW_COUNT
eql = PASS1_node(request, eql, proc_flag);
request->req_flags = req_flags;
// if (ROW_COUNT = 0) then INSERT
dsql_nod* if_nod = MAKE_node(nod_if, e_if_count);
if_nod->nod_arg[e_if_condition] = eql;
if_nod->nod_arg[e_if_true] = insert;
// build the UPDATE / IF nodes
dsql_nod* list = MAKE_node(nod_list, 2);
list->nod_arg[0] = update;
list->nod_arg[1] = if_nod;
// if RETURNING is present, req_type is already REQ_EXEC_PROCEDURE
if (!input->nod_arg[e_rep_return])
request->req_type = REQ_INSERT;
return list;
}
/**
pass1_returning
@ -8684,6 +8441,249 @@ static dsql_nod* pass1_update( dsql_req* request, dsql_nod* input, bool proc_fla
}
/**
pass1_update_or_insert
@brief Process UPDATE OR INSERT statement.
@param request
@param input
@param proc_flag
**/
static dsql_nod* pass1_update_or_insert(dsql_req* request, dsql_nod* input, bool proc_flag)
{
DEV_BLKCHK(request, dsql_type_req);
DEV_BLKCHK(input, dsql_type_nod);
dsql_str* relation_name =
(dsql_str*) input->nod_arg[e_upi_relation]->nod_arg[e_rpn_name];
dsql_str* base_name = relation_name;
dsql_nod* values = input->nod_arg[e_upi_values];
// build the INSERT node
dsql_nod* insert = MAKE_node(nod_insert, e_ins_count);
insert->nod_arg[e_ins_relation] = input->nod_arg[e_upi_relation];
insert->nod_arg[e_ins_fields] = input->nod_arg[e_upi_fields];
insert->nod_arg[e_ins_values] = values;
insert->nod_arg[e_ins_return] = input->nod_arg[e_upi_return];
insert = pass1_insert(request, insert, proc_flag);
// PASS1_statement will transform nod_insert to nod_store
fb_assert(insert->nod_type == nod_store);
dsql_ctx* context = (dsql_ctx*) insert->nod_arg[e_sto_relation]->nod_arg[e_rel_context];
DEV_BLKCHK(context, dsql_type_ctx);
dsql_rel* relation = context->ctx_relation;
dsql_nod* fields = input->nod_arg[e_upi_fields];
// if a field list isn't present, build one using the same
// rules of INSERT INTO table VALUES ...
if (!fields)
fields = explode_fields(relation);
// maintain a pair of view's field name / base field name
MetaNamePairMap view_fields;
if ((relation->rel_flags & REL_view) && !input->nod_arg[e_upi_matching])
{
dsql_rel* base_rel =
METD_get_view_base(request, relation_name->str_data, view_fields);
// get the base table name if there is only one
if (base_rel)
base_name = MAKE_cstring(base_rel->rel_name);
else
ERRD_post(isc_upd_ins_with_complex_view, 0);
}
dsql_nod* matching = input->nod_arg[e_upi_matching];
if (matching)
{
request->req_context->push(context);
request->req_scope_level++;
dsql_nod* matching_fields = PASS1_node(request, matching, false);
request->req_scope_level--;
request->req_context->pop();
field_appears_once(matching_fields, matching, true, "UPDATE OR INSERT");
}
else
{
matching = METD_get_primary_key(request, base_name);
if (!matching)
{
ERRD_post(isc_primary_key_required,
isc_arg_string, base_name->str_data,
0);
}
}
// build a boolean to use in the UPDATE statement
dsql_nod* match = NULL;
USHORT match_count = 0;
DsqlNodStack stack;
dsql_nod** field_ptr = fields->nod_arg;
dsql_nod** value_ptr = values->nod_arg;
for (const dsql_nod* const* const field_end = field_ptr + fields->nod_count;
field_ptr < field_end; field_ptr++, value_ptr++)
{
DEV_BLKCHK(*field_ptr, dsql_type_nod);
DEV_BLKCHK(*value_ptr, dsql_type_nod);
dsql_nod* temp = MAKE_node(nod_assign, e_asgn_count);
temp->nod_arg[e_asgn_value] = *value_ptr;
temp->nod_arg[e_asgn_field] = *field_ptr;
stack.push(temp);
temp = *value_ptr;
dsql_nod* temp2 = insert->nod_arg[e_sto_statement]->nod_arg[field_ptr - fields->nod_arg]->nod_arg[1];
set_parameter_type(request, temp, temp2, false);
fb_assert((*field_ptr)->nod_type == nod_field_name);
// When relation is a view and MATCHING was not specified, field_name
// stores the base field name that is what we should find in the primary
// key of base table.
Firebird::MetaName field_name;
if ((relation->rel_flags & REL_view) && !input->nod_arg[e_upi_matching])
{
view_fields.get(
Firebird::MetaName(((dsql_str*) (*field_ptr)->nod_arg[e_fln_name])->str_data),
field_name);
}
else
field_name = ((dsql_str*) (*field_ptr)->nod_arg[e_fln_name])->str_data;
if (field_name.hasData())
{
dsql_nod** matching_ptr = matching->nod_arg;
for (const dsql_nod* const* const matching_end = matching_ptr + matching->nod_count;
matching_ptr < matching_end; matching_ptr++)
{
DEV_BLKCHK(*matching_ptr, dsql_type_nod);
fb_assert((*matching_ptr)->nod_type == nod_field_name);
if (Firebird::MetaName(((dsql_str*)
(*matching_ptr)->nod_arg[e_fln_name])->str_data) ==
field_name)
{
++match_count;
dsql_nod* eql = MAKE_node(nod_eql, 2);
eql->nod_arg[0] = *field_ptr;
eql->nod_arg[1] = *value_ptr;
if (match)
{
// It's a composed MATCHING. Build an AND.
dsql_nod* and_node = MAKE_node(nod_and, 2);
and_node->nod_arg[0] = match;
and_node->nod_arg[1] = eql;
match = and_node;
}
else
match = eql;
}
}
}
}
// check if implicit or explicit MATCHING is valid
if (match_count != matching->nod_count)
{
if (input->nod_arg[e_upi_matching])
ERRD_post(isc_upd_ins_doesnt_match_matching, 0);
else
{
ERRD_post(isc_upd_ins_doesnt_match_pk,
isc_arg_string, base_name->str_data,
0);
}
}
// build the UPDATE node
dsql_nod* update = MAKE_node(nod_update, e_upd_count);
update->nod_arg[e_upd_relation] = input->nod_arg[e_upi_relation];
update->nod_arg[e_upd_statement] = MAKE_list(stack);
update->nod_arg[e_upd_boolean] = match;
if (input->nod_arg[e_upi_return])
{
update->nod_arg[e_upd_rse_flags] = (dsql_nod*) NOD_SELECT_EXPR_SINGLETON;
dsql_nod* store_ret = insert->nod_arg[e_sto_return];
// nod_returning was already processed
fb_assert(store_ret->nod_type == nod_list);
// And we create an already processed RETURNING, because
// nod_returning creates parameters and they're already
// created by the INSERT statement.
dsql_nod* update_ret = update->nod_arg[e_upd_return] =
MAKE_node(nod_list, store_ret->nod_count);
dsql_nod** src_ptr = input->nod_arg[e_upi_return]->nod_arg[e_ret_source]->nod_arg;
dsql_nod** dst_ptr = store_ret->nod_arg;
dsql_nod** ptr = update_ret->nod_arg;
for (const dsql_nod* const* const end = ptr + update_ret->nod_count;
ptr < end; src_ptr++, dst_ptr++, ptr++)
{
dsql_nod* temp = MAKE_node(nod_assign, e_asgn_count);
temp->nod_arg[e_asgn_value] = *src_ptr;
temp->nod_arg[e_asgn_field] = (*dst_ptr)->nod_arg[1];
*ptr = temp;
}
}
update = pass1_update(request, update, proc_flag);
// PASS1_statement will transform nod_update to nod_modify
fb_assert(update->nod_type == nod_modify);
// test if ROW_COUNT = 0
dsql_nod* eql = MAKE_node(nod_eql, 2);
eql->nod_arg[0] = MAKE_node(nod_internal_info, e_internal_info_count);
eql->nod_arg[0]->nod_arg[e_internal_info] =
MAKE_constant((dsql_str*) internal_rows_affected, CONSTANT_SLONG);
eql->nod_arg[1] = MAKE_constant((dsql_str*) 0, CONSTANT_SLONG);
USHORT req_flags = request->req_flags;
request->req_flags |= REQ_block; // to compile ROW_COUNT
eql = PASS1_node(request, eql, proc_flag);
request->req_flags = req_flags;
// if (ROW_COUNT = 0) then INSERT
dsql_nod* if_nod = MAKE_node(nod_if, e_if_count);
if_nod->nod_arg[e_if_condition] = eql;
if_nod->nod_arg[e_if_true] = insert;
// build the UPDATE / IF nodes
dsql_nod* list = MAKE_node(nod_list, 2);
list->nod_arg[0] = update;
list->nod_arg[1] = if_nod;
// if RETURNING is present, req_type is already REQ_EXEC_PROCEDURE
if (!input->nod_arg[e_upi_return])
request->req_type = REQ_INSERT;
return list;
}
/**
resolve_variable_name

View File

@ -631,9 +631,9 @@ static const struct {
{"dsql_type_not_supp_ext_tab", 336003096},
{"dsql_feature_not_supported_ods", 336003097},
{"primary_key_required", 336003098},
{"replace_doesnt_match_pk", 336003099},
{"replace_doesnt_match_matching", 336003100},
{"replace_with_complex_view", 336003101},
{"upd_ins_doesnt_match_pk", 336003099},
{"upd_ins_doesnt_match_matching", 336003100},
{"upd_ins_with_complex_view", 336003101},
{"dsql_incompatible_trigger_type", 336003102},
{"dsql_db_trigger_type_cant_change", 336003103},
{"dyn_role_does_not_exist", 336068796},

View File

@ -664,9 +664,9 @@ const ISC_LONG isc_dsql_cursor_not_open = 336003095L;
const ISC_LONG isc_dsql_type_not_supp_ext_tab = 336003096L;
const ISC_LONG isc_dsql_feature_not_supported_ods = 336003097L;
const ISC_LONG isc_primary_key_required = 336003098L;
const ISC_LONG isc_replace_doesnt_match_pk = 336003099L;
const ISC_LONG isc_replace_doesnt_match_matching = 336003100L;
const ISC_LONG isc_replace_with_complex_view = 336003101L;
const ISC_LONG isc_upd_ins_doesnt_match_pk = 336003099L;
const ISC_LONG isc_upd_ins_doesnt_match_matching = 336003100L;
const ISC_LONG isc_upd_ins_with_complex_view = 336003101L;
const ISC_LONG isc_dsql_incompatible_trigger_type = 336003102L;
const ISC_LONG isc_dsql_db_trigger_type_cant_change = 336003103L;
const ISC_LONG isc_dyn_role_does_not_exist = 336068796L;
@ -1494,9 +1494,9 @@ const ISC_LONG isc_err_max = 805;
#define isc_dsql_type_not_supp_ext_tab 336003096L
#define isc_dsql_feature_not_supported_ods 336003097L
#define isc_primary_key_required 336003098L
#define isc_replace_doesnt_match_pk 336003099L
#define isc_replace_doesnt_match_matching 336003100L
#define isc_replace_with_complex_view 336003101L
#define isc_upd_ins_doesnt_match_pk 336003099L
#define isc_upd_ins_doesnt_match_matching 336003100L
#define isc_upd_ins_with_complex_view 336003101L
#define isc_dsql_incompatible_trigger_type 336003102L
#define isc_dsql_db_trigger_type_cant_change 336003103L
#define isc_dyn_role_does_not_exist 336068796L

View File

@ -631,9 +631,9 @@ static const struct {
{336003096, "Data type %s is not supported for EXTERNAL TABLES. Relation '%s', field '%s'"}, /* 607, dsql_type_not_supp_ext_tab */
{336003097, "Feature not supported on ODS version older than %d.%d"}, /* 608, dsql_feature_not_supported_ods */
{336003098, "Primary key required on table %s"}, /* 609, primary_key_required */
{336003099, "REPLACE field list does not match primary key of table %s"}, /* 610, replace_doesnt_match_pk */
{336003100, "REPLACE field list does not match MATCHING clause"}, /* 611, replace_doesnt_match_matching */
{336003101, "REPLACE without MATCHING could not be used with views based on more than one table"}, /* 612, replace_with_complex_view */
{336003099, "REPLACE field list does not match primary key of table %s"}, /* 610, upd_ins_doesnt_match_pk */
{336003100, "REPLACE field list does not match MATCHING clause"}, /* 611, upd_ins_doesnt_match_matching */
{336003101, "REPLACE without MATCHING could not be used with views based on more than one table"}, /* 612, upd_ins_with_complex_view */
{336003102, "Incompatible trigger type"}, /* 613, dsql_incompatible_trigger_type */
{336003103, "Database trigger type can't be changed"}, /* 614, dsql_db_trigger_type_cant_change */
{336068796, "SQL role %s does not exist"}, /* 615, dyn_role_does_not_exist */

View File

@ -630,9 +630,9 @@ static const struct {
{336003096, -607}, /* 24 dsql_type_not_supp_ext_tab */
{336003097, -804}, /* 25 dsql_feature_not_supported_ods */
{336003098, -660}, /* 26 primary_key_required */
{336003099, -313}, /* 27 replace_doesnt_match_pk */
{336003100, -313}, /* 28 replace_doesnt_match_matching */
{336003101, -817}, /* 29 replace_with_complex_view */
{336003099, -313}, /* 27 upd_ins_doesnt_match_pk */
{336003100, -313}, /* 28 upd_ins_doesnt_match_matching */
{336003101, -817}, /* 29 upd_ins_with_complex_view */
{336003102, -817}, /* 30 dsql_incompatible_trigger_type */
{336003103, -817}, /* 31 dsql_db_trigger_type_cant_change */
{336068796, -901}, /* 188 dyn_role_does_not_exist */

View File

@ -3064,9 +3064,9 @@ INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FL
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('dsql_implicit_domain_name', 'define_domain', 'ddl.cpp', NULL, 13, 925, NULL, 'Implicit domain name %s not allowed in user created domain', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('MSG_COLLATIONS', 'SHOW_metadata', 'show.epp', NULL, 17, 150, NULL, 'Collations:', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('primary_key_required', 'pass1_replace', 'pass1.cpp', NULL, 7, 26, NULL, 'Primary key required on table %s', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('replace_doesnt_match_pk', 'pass1_replace', 'pass1.cpp', NULL, 7, 27, NULL, 'REPLACE field list does not match primary key of table %s', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('replace_doesnt_match_matching', 'pass1_replace', 'pass1.cpp', NULL, 7, 28, NULL, 'REPLACE field list does not match MATCHING clause', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('replace_with_complex_view', 'pass1_replace', 'pass1.cpp', NULL, 7, 29, NULL, 'REPLACE without MATCHING could not be used with views based on more than one table', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('upd_ins_doesnt_match_pk', 'pass1_replace', 'pass1.cpp', NULL, 7, 27, NULL, 'REPLACE field list does not match primary key of table %s', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('upd_ins_doesnt_match_matching', 'pass1_replace', 'pass1.cpp', NULL, 7, 28, NULL, 'REPLACE field list does not match MATCHING clause', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('upd_ins_with_complex_view', 'pass1_replace', 'pass1.cpp', NULL, 7, 29, NULL, 'REPLACE without MATCHING could not be used with views based on more than one table', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES (NULL, 'DYN_define_index', 'dyn_def.epp', NULL, 8, 240, NULL, 'Field %s cannot be used twice in index %s', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('NO_SECCLASS', 'SHOW_metadata', 'show.epp', NULL, 17, 151, NULL, 'There are no security classes for %s', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('NO_DB_WIDE_SECCLASS', 'SHOW_metadata', 'show.epp', NULL, 17, 152, NULL, 'There is no database-wide security class', NULL, NULL);

View File

@ -774,9 +774,9 @@ INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, NUMBER, FAC_CODE,
INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, NUMBER, FAC_CODE, VMS_CODE, GDS_SYMBOL, SEVERITY, SEVERITY_TEXT) VALUES (-804, NULL, NULL, 25, 7, NULL, 'dsql_feature_not_supported_ods', NULL, NULL);
INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, NUMBER, FAC_CODE, VMS_CODE, GDS_SYMBOL, SEVERITY, SEVERITY_TEXT) VALUES (-637, NULL, NULL, 925, 13, NULL, 'dsql_implicit_domain_name', NULL, NULL);
INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, NUMBER, FAC_CODE, VMS_CODE, GDS_SYMBOL, SEVERITY, SEVERITY_TEXT) VALUES (-660, NULL, NULL, 26, 7, NULL, 'primary_key_required', NULL, NULL);
INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, NUMBER, FAC_CODE, VMS_CODE, GDS_SYMBOL, SEVERITY, SEVERITY_TEXT) VALUES (-313, NULL, NULL, 27, 7, NULL, 'replace_doesnt_match_pk', NULL, NULL);
INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, NUMBER, FAC_CODE, VMS_CODE, GDS_SYMBOL, SEVERITY, SEVERITY_TEXT) VALUES (-313, NULL, NULL, 28, 7, NULL, 'replace_doesnt_match_matching', NULL, NULL);
INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, NUMBER, FAC_CODE, VMS_CODE, GDS_SYMBOL, SEVERITY, SEVERITY_TEXT) VALUES (-817, NULL, NULL, 29, 7, NULL, 'replace_with_complex_view', NULL, NULL);
INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, NUMBER, FAC_CODE, VMS_CODE, GDS_SYMBOL, SEVERITY, SEVERITY_TEXT) VALUES (-313, NULL, NULL, 27, 7, NULL, 'upd_ins_doesnt_match_pk', NULL, NULL);
INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, NUMBER, FAC_CODE, VMS_CODE, GDS_SYMBOL, SEVERITY, SEVERITY_TEXT) VALUES (-313, NULL, NULL, 28, 7, NULL, 'upd_ins_doesnt_match_matching', NULL, NULL);
INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, NUMBER, FAC_CODE, VMS_CODE, GDS_SYMBOL, SEVERITY, SEVERITY_TEXT) VALUES (-817, NULL, NULL, 29, 7, NULL, 'upd_ins_with_complex_view', NULL, NULL);
INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, NUMBER, FAC_CODE, VMS_CODE, GDS_SYMBOL, SEVERITY, SEVERITY_TEXT) VALUES (-171, NULL, NULL, 553, 0, NULL, 'array_max_dimensions', NULL, NULL);
INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, NUMBER, FAC_CODE, VMS_CODE, GDS_SYMBOL, SEVERITY, SEVERITY_TEXT) VALUES (-607, NULL, NULL, 926, 13, NULL, 'dsql_only_can_subscript_array', NULL, NULL);
INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, NUMBER, FAC_CODE, VMS_CODE, GDS_SYMBOL, SEVERITY, SEVERITY_TEXT) VALUES (-104, NULL, NULL, 927, 13, NULL, 'dsql_max_sort_items', NULL, NULL);