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

Comments.

This commit is contained in:
robocop 2009-04-18 14:13:26 +00:00
parent cb80d0cd63
commit 74537636b9
7 changed files with 409 additions and 418 deletions

View File

@ -235,7 +235,7 @@ static const USHORT blr_dtypes[] =
blr_sql_date, // dtype_sql_date blr_sql_date, // dtype_sql_date
blr_sql_time, // dtype_sql_time blr_sql_time, // dtype_sql_time
blr_timestamp, // dtype_timestamp blr_timestamp, // dtype_timestamp
blr_blob, // dtype_blob // ASF: CAST use blr_blob2 because blr_blob don't fit in UCHAR blr_blob, // dtype_blob // ASF: CAST use blr_blob2 because blr_blob doesn't fit in UCHAR
blr_short, // dtype_array blr_short, // dtype_array
blr_int64 // dtype_int64 blr_int64 // dtype_int64
}; };
@ -666,10 +666,10 @@ void DDL_resolve_intl_type2(CompiledStatement* statement,
} }
else else
{ {
/* If field is not specified with NATIONAL, or CHARACTER SET // If field is not specified with NATIONAL, or CHARACTER SET
* treat it as a single-byte-per-character field of character set NONE. // treat it as a single-byte-per-character field of character set NONE.
*/
assign_field_length (field, 1); assign_field_length(field, 1);
field->fld_ttype = 0; field->fld_ttype = 0;
if (!collation_name) { if (!collation_name) {
return; return;
@ -687,7 +687,7 @@ void DDL_resolve_intl_type2(CompiledStatement* statement,
} }
// Find an intlsym for any specified character set name & collation name // Find an intlsym for any specified character set name & collation name
const dsql_intlsym* resolved_type = NULL; const dsql_intlsym* resolved_type = NULL;
if (charset_name) if (charset_name)
@ -1184,8 +1184,8 @@ static void define_constraint_trigger(CompiledStatement* statement, dsql_nod* no
* *
**************************************/ **************************************/
/* make the "define trigger" node the current statement ddl node so // make the "define trigger" node the current statement ddl node so
that generating of BLR will be appropriate for trigger */ // that generating of BLR will be appropriate for trigger
dsql_nod* const saved_ddl_node = statement->req_ddl_node; dsql_nod* const saved_ddl_node = statement->req_ddl_node;
@ -1232,10 +1232,10 @@ static void define_constraint_trigger(CompiledStatement* statement, dsql_nod* no
statement->begin_blr(isc_dyn_trg_blr); statement->begin_blr(isc_dyn_trg_blr);
statement->append_uchar(blr_begin); statement->append_uchar(blr_begin);
/* create the "OLD" and "NEW" contexts for the trigger -- // create the "OLD" and "NEW" contexts for the trigger --
the new one could be a dummy place holder to avoid resolving // the new one could be a dummy place holder to avoid resolving
fields to that context but prevent relations referenced in // fields to that context but prevent relations referenced in
the trigger actions from referencing the predefined "1" context */ // the trigger actions from referencing the predefined "1" context
reset_context_stack(statement); reset_context_stack(statement);
@ -1282,9 +1282,9 @@ static void define_constraint_trigger(CompiledStatement* statement, dsql_nod* no
statement->append_uchar(isc_dyn_end); statement->append_uchar(isc_dyn_end);
/* the statement type may have been set incorrectly when parsing // the statement type may have been set incorrectly when parsing
the trigger actions, so reset it to reflect the fact that this // the trigger actions, so reset it to reflect the fact that this
is a data definition statement; also reset the ddl node */ // is a data definition statement; also reset the ddl node
statement->req_type = REQ_DDL; statement->req_type = REQ_DDL;
statement->req_ddl_node = saved_ddl_node; statement->req_ddl_node = saved_ddl_node;
@ -1313,9 +1313,8 @@ static void define_database(CompiledStatement* statement)
const dsql_nod* ddl_node = statement->req_ddl_node; const dsql_nod* ddl_node = statement->req_ddl_node;
statement->append_uchar(isc_dyn_mod_database); statement->append_uchar(isc_dyn_mod_database);
/*
statement->append_number(isc_dyn_rel_sql_protection, 1); // statement->append_number(isc_dyn_rel_sql_protection, 1);
*/
const dsql_nod* elements = ddl_node->nod_arg[e_database_initial_desc]; const dsql_nod* elements = ddl_node->nod_arg[e_database_initial_desc];
@ -1516,23 +1515,23 @@ static void define_set_default_trg( CompiledStatement* statement,
statement->append_uchar(blr_assignment); statement->append_uchar(blr_assignment);
/* here stuff the default value as blr_literal .... or blr_null // here stuff the default value as blr_literal .... or blr_null
if this col. does not have an applicable default */ // if this col. does not have an applicable default
/* the default is determined in many cases: // the default is determined in many cases:
(1) the info. for the column is in memory. (This is because // (1) the info. for the column is in memory. (This is because
the column is being created in this ddl statement) // the column is being created in this ddl statement)
(1-a) the table has a column level default. We get this by // (1-a) the table has a column level default. We get this by
searching the dsql parse tree starting from the ddl node. // searching the dsql parse tree starting from the ddl node.
(1-b) the table does not have a column level default, but // (1-b) the table does not have a column level default, but
has a domain default. We get the domain name from the dsql // has a domain default. We get the domain name from the dsql
parse tree and call METD_get_domain_default to read the // parse tree and call METD_get_domain_default to read the
default from the system tables. // default from the system tables.
(2) The default-info for this column is not in memory (This is // (2) The default-info for this column is not in memory (This is
because this is an alter table ddl statement). The table // because this is an alter table ddl statement). The table
already exists; therefore we get the column and/or domain // already exists; therefore we get the column and/or domain
default value from the system tables by calling: // default value from the system tables by calling:
METD_get_col_default(). */ // METD_get_col_default().
bool found_default = false; bool found_default = false;
bool search_for_default = true; bool search_for_default = true;
@ -1581,8 +1580,8 @@ static void define_set_default_trg( CompiledStatement* statement,
break; break;
} }
/* case: (1-b): domain name is available. Column level default // case: (1-b): domain name is available. Column level default
is not declared. so get the domain default */ // is not declared. so get the domain default
const USHORT def_len = const USHORT def_len =
METD_get_domain_default(statement, domain_name, &found_default, METD_get_domain_default(statement, domain_name, &found_default,
default_val, sizeof(default_val)); default_val, sizeof(default_val));
@ -1780,15 +1779,15 @@ static void define_domain(CompiledStatement* statement)
set_nod_value_attributes(node1->nod_arg[e_cnstr_condition], field); set_nod_value_attributes(node1->nod_arg[e_cnstr_condition], field);
} }
/* Increment the context level for this statement, so // Increment the context level for this statement, so
that the context number for any RSE generated for a // that the context number for any RSE generated for a
SELECT within the CHECK clause will be greater than // SELECT within the CHECK clause will be greater than
0. In the environment of a domain check // 0. In the environment of a domain check
constraint, context number 0 is reserved for the // constraint, context number 0 is reserved for the
"blr_fid, 0, 0, 0," which is emitted for a // "blr_fid, 0, 0, 0," which is emitted for a
nod_dom_value, corresponding to an occurance of the // nod_dom_value, corresponding to an occurance of the
VALUE keyword in the body of the check constraint. // VALUE keyword in the body of the check constraint.
-- chrisj 1999-08-20 */ // -- chrisj 1999-08-20
statement->req_context_number++; statement->req_context_number++;
node = PASS1_node(statement, node1->nod_arg[e_cnstr_condition]); node = PASS1_node(statement, node1->nod_arg[e_cnstr_condition]);
@ -1869,7 +1868,7 @@ static void define_field(CompiledStatement* statement,
**************************************/ **************************************/
dsql_fld* field = (dsql_fld*) element->nod_arg[e_dfl_field]; dsql_fld* field = (dsql_fld*) element->nod_arg[e_dfl_field];
// add the field to the relation being defined for parsing purposes // add the field to the relation being defined for parsing purposes
bool permanent = false; bool permanent = false;
dsql_rel* relation = statement->req_relation; dsql_rel* relation = statement->req_relation;
@ -2284,8 +2283,8 @@ static void define_index(CompiledStatement* statement)
statement->append_cstring(isc_dyn_def_idx, index_name->str_data); statement->append_cstring(isc_dyn_def_idx, index_name->str_data);
statement->append_cstring(isc_dyn_rel_name, relation_name->str_data); statement->append_cstring(isc_dyn_rel_name, relation_name->str_data);
/* go through the fields list, making an index segment for each field, // go through the fields list, making an index segment for each field,
unless we have a computation, in which case generate an expression index */ // unless we have a computation, in which case generate an expression index
if (field_list->nod_type == nod_list) if (field_list->nod_type == nod_list)
{ {
@ -2299,7 +2298,7 @@ static void define_index(CompiledStatement* statement)
else if (field_list->nod_type == nod_def_computed) else if (field_list->nod_type == nod_def_computed)
define_computed(statement, relation_node, NULL, field_list); define_computed(statement, relation_node, NULL, field_list);
// check for a unique index // check for a unique index
if (ddl_node->nod_arg[e_idx_unique]) { if (ddl_node->nod_arg[e_idx_unique]) {
statement->append_number(isc_dyn_idx_unique, 1); statement->append_number(isc_dyn_idx_unique, 1);
@ -3066,8 +3065,8 @@ static void define_trigger(CompiledStatement* statement, NOD_TYPE op)
statement->append_string(isc_dyn_mod_trigger, trigger_name->str_data, trigger_name->str_length); statement->append_string(isc_dyn_mod_trigger, trigger_name->str_data, trigger_name->str_length);
if (trigger_node->nod_arg[e_trg_actions]) if (trigger_node->nod_arg[e_trg_actions])
{ {
/* Since we will be updating the body of the trigger, we need // Since we will be updating the body of the trigger, we need
to know what relation the trigger relates to. */ // to know what relation the trigger relates to.
dsql_str* relation_name = NULL; dsql_str* relation_name = NULL;
bool found = METD_get_trigger(statement, trigger_name, &relation_name, &trig_type); bool found = METD_get_trigger(statement, trigger_name, &relation_name, &trig_type);
@ -3128,10 +3127,10 @@ static void define_trigger(CompiledStatement* statement, NOD_TYPE op)
if (actions) if (actions)
{ {
/* create the "OLD" and "NEW" contexts for the trigger -- // create the "OLD" and "NEW" contexts for the trigger --
the new one could be a dummy place holder to avoid resolving // the new one could be a dummy place holder to avoid resolving
fields to that context but prevent relations referenced in // fields to that context but prevent relations referenced in
the trigger actions from referencing the predefined "1" context */ // the trigger actions from referencing the predefined "1" context
reset_context_stack(statement); reset_context_stack(statement);
@ -3191,9 +3190,9 @@ static void define_trigger(CompiledStatement* statement, NOD_TYPE op)
statement->append_uchar(blr_end); statement->append_uchar(blr_end);
statement->end_blr(); statement->end_blr();
/* the statement type may have been set incorrectly when parsing // the statement type may have been set incorrectly when parsing
the trigger actions, so reset it to reflect the fact that this // the trigger actions, so reset it to reflect the fact that this
is a data definition statement; also reset the ddl node */ // is a data definition statement; also reset the ddl node
statement->req_type = REQ_DDL; statement->req_type = REQ_DDL;
} }
@ -3244,8 +3243,8 @@ static void define_udf(CompiledStatement* statement)
post_607(Arg::Gds(isc_return_mode_err)); post_607(Arg::Gds(isc_return_mode_err));
} }
/* For functions returning a blob, coerce return argument position to // For functions returning a blob, coerce return argument position to
be the last parameter. */ // be the last parameter.
if (field->fld_dtype == dtype_blob) if (field->fld_dtype == dtype_blob)
{ {
@ -3299,20 +3298,19 @@ static void define_udf(CompiledStatement* statement)
position = 1; position = 1;
} }
// Now define all the arguments // Now define all the arguments
if (!position) if (!position)
{ {
/* CVC: This is case of "returns <type> [by value|reference]" */ // CVC: This is case of "returns <type> [by value|reference]"
if (field->fld_dtype == dtype_blob) if (field->fld_dtype == dtype_blob)
{ {
/* CVC: I need to test returning blobs by descriptor before allowing the // CVC: I need to test returning blobs by descriptor before allowing the
change there. For now, I ignore the return type specification. */ // change there. For now, I ignore the return type specification.
const bool free_it = ((SSHORT) ret_val_ptr[1]->getSlong() < 0); const bool free_it = ((SSHORT) ret_val_ptr[1]->getSlong() < 0);
statement->append_number(isc_dyn_def_function_arg, blob_position); statement->append_number(isc_dyn_def_function_arg, blob_position);
statement->append_number(isc_dyn_func_mechanism, statement->append_number(isc_dyn_func_mechanism,
(SSHORT)(SLONG) ((free_it ? -1 : 1) * FUN_blob_struct)); (SSHORT)(SLONG) ((free_it ? -1 : 1) * FUN_blob_struct));
/* if we have the free_it set then the blob has // if we have the free_it set then the blob has to be freed on return
to be freed on return */
} }
else else
{ {
@ -3329,7 +3327,7 @@ static void define_udf(CompiledStatement* statement)
fb_assert(position == 1); fb_assert(position == 1);
/* CVC: This for all params, including the case of "returns parameter <N>" */ // CVC: This for all params, including the case of "returns parameter <N>"
if (arguments) if (arguments)
{ {
@ -3343,7 +3341,7 @@ static void define_udf(CompiledStatement* statement)
post_607(Arg::Gds(isc_extern_func_err)); post_607(Arg::Gds(isc_extern_func_err));
} }
/*field = (dsql_fld*) *ptr; */ // field = (dsql_fld*) *ptr;
dsql_nod** param_node = (*ptr)->nod_arg; dsql_nod** param_node = (*ptr)->nod_arg;
field = (dsql_fld*) param_node[e_udf_param_field]; field = (dsql_fld*) param_node[e_udf_param_field];
@ -3390,7 +3388,7 @@ static void define_update_action(CompiledStatement* statement,
**************************************/ **************************************/
dsql_nod* ddl_node = statement->req_ddl_node; dsql_nod* ddl_node = statement->req_ddl_node;
// check whether this is an updatable view definition // check whether this is an updatable view definition
dsql_nod* select_node = NULL; dsql_nod* select_node = NULL;
dsql_nod* select_expr = NULL; dsql_nod* select_expr = NULL;
@ -3407,16 +3405,16 @@ static void define_update_action(CompiledStatement* statement,
fb_assert(false); fb_assert(false);
} }
// use the relation referenced in the select statement for rse // use the relation referenced in the select statement for rse
dsql_nod* relation_node = MAKE_node(nod_relation_name, (int) e_rln_count); dsql_nod* relation_node = MAKE_node(nod_relation_name, (int) e_rln_count);
relation_node->nod_arg[e_rln_name] = from_list->nod_arg[0]->nod_arg[e_rln_name]; relation_node->nod_arg[e_rln_name] = from_list->nod_arg[0]->nod_arg[e_rln_name];
relation_node->nod_arg[e_rln_alias] = (dsql_nod*) MAKE_cstring(TEMP_CONTEXT); relation_node->nod_arg[e_rln_alias] = (dsql_nod*) MAKE_cstring(TEMP_CONTEXT);
*base_relation = relation_node; *base_relation = relation_node;
/* get the list of values and fields to compare to -- if there is // get the list of values and fields to compare to -- if there is
no list of fields, get all fields in the base relation that // no list of fields, get all fields in the base relation that
are not computed */ // are not computed
dsql_nod* values_node = ddl_node->nod_arg[e_view_fields]; dsql_nod* values_node = ddl_node->nod_arg[e_view_fields];
dsql_nod* fields_node = select_expr->nod_arg[e_qry_list]; dsql_nod* fields_node = select_expr->nod_arg[e_qry_list];
@ -3436,7 +3434,7 @@ static void define_update_action(CompiledStatement* statement,
if (!values_node) if (!values_node)
values_node = fields_node; values_node = fields_node;
// generate the list of assignments to fields in the base relation // generate the list of assignments to fields in the base relation
dsql_nod** ptr = fields_node->nod_arg; dsql_nod** ptr = fields_node->nod_arg;
const dsql_nod* const* const end = ptr + fields_node->nod_count; const dsql_nod* const* const end = ptr + fields_node->nod_count;
@ -3943,8 +3941,8 @@ static void define_view_trigger(CompiledStatement* statement, dsql_nod* node, ds
select_expr = select_expr->nod_arg[e_sel_query_spec]; select_expr = select_expr->nod_arg[e_sel_query_spec];
dsql_nod* view_fields = saved_ddl_node->nod_arg[e_view_fields]; dsql_nod* view_fields = saved_ddl_node->nod_arg[e_view_fields];
/* make the "define trigger" node the current statement ddl node so // make the "define trigger" node the current statement ddl node so
that generating of BLR will be appropriate for trigger */ // that generating of BLR will be appropriate for trigger
statement->req_ddl_node = node; statement->req_ddl_node = node;
@ -3974,9 +3972,9 @@ static void define_view_trigger(CompiledStatement* statement, dsql_nod* node, ds
} }
else else
{ {
/* If we don't have a trigger type assigned, then this is just a template // If we don't have a trigger type assigned, then this is just a template
definition for use with domains. The real triggers are defined when // definition for use with domains. The real triggers are defined when
the domain is used. */ // the domain is used.
trig_type = 0; trig_type = 0;
} }
@ -3989,16 +3987,16 @@ static void define_view_trigger(CompiledStatement* statement, dsql_nod* node, ds
statement->begin_blr(isc_dyn_trg_blr); statement->begin_blr(isc_dyn_trg_blr);
statement->append_uchar(blr_begin); statement->append_uchar(blr_begin);
/* create the "OLD" and "NEW" contexts for the trigger -- // create the "OLD" and "NEW" contexts for the trigger --
the new one could be a dummy place holder to avoid resolving // the new one could be a dummy place holder to avoid resolving
fields to that context but prevent relations referenced in // fields to that context but prevent relations referenced in
the trigger actions from referencing the predefined "1" context */ // the trigger actions from referencing the predefined "1" context
dsql_ctx* sav_context = 0; dsql_ctx* sav_context = 0;
dsql_ctx* context = 0; dsql_ctx* context = 0;
if (statement->req_context_number) { if (statement->req_context_number) {
/* If an alias is specified for the single base table involved, // If an alias is specified for the single base table involved,
save and then add the context */ // save and then add the context
context = statement->req_context->object(); context = statement->req_context->object();
if (context->ctx_alias) { if (context->ctx_alias) {
@ -4185,7 +4183,8 @@ static void delete_relation_view (CompiledStatement* statement, dsql_nod* node,
post_607(Arg::Gds(isc_dsql_table_not_found) << Arg::Str(string->str_data)); post_607(Arg::Gds(isc_dsql_table_not_found) << Arg::Str(string->str_data));
} }
} }
else { /* node->nod_type == nod_del_view, nod_redef_view */ else {
// node->nod_type == nod_del_view, nod_redef_view
if (!relation && !silent_deletion || relation && !(relation->rel_flags & REL_view)) if (!relation && !silent_deletion || relation && !(relation->rel_flags & REL_view))
{ {
post_607(Arg::Gds(isc_dsql_view_not_found) << Arg::Str(string->str_data)); post_607(Arg::Gds(isc_dsql_view_not_found) << Arg::Str(string->str_data));
@ -4333,16 +4332,16 @@ static void foreign_key(CompiledStatement* statement, dsql_nod* element, const c
dsql_nod* relation2_node = element->nod_arg[e_for_reftable]; dsql_nod* relation2_node = element->nod_arg[e_for_reftable];
const dsql_str* relation2 = (dsql_str*) relation2_node->nod_arg[e_rln_name]; const dsql_str* relation2 = (dsql_str*) relation2_node->nod_arg[e_rln_name];
/* If there is a referenced table name but no referenced field names, the // If there is a referenced table name but no referenced field names, the
primary key of the referenced table designates the referenced fields. */ // primary key of the referenced table designates the referenced fields.
dsql_nod* columns2 = element->nod_arg[e_for_refcolumns]; dsql_nod* columns2 = element->nod_arg[e_for_refcolumns];
if (!columns2) if (!columns2)
{ {
element->nod_arg[e_for_refcolumns] = columns2 = METD_get_primary_key(statement, relation2); element->nod_arg[e_for_refcolumns] = columns2 = METD_get_primary_key(statement, relation2);
/* If there is NEITHER an explicitly referenced field name, NOR does // If there is NEITHER an explicitly referenced field name, NOR does
the referenced table have a primary key to serve as the implicitly // the referenced table have a primary key to serve as the implicitly
referenced field, fail. */ // referenced field, fail.
if (!columns2) if (!columns2)
{ {
// "REFERENCES table" without "(column)" requires PRIMARY // "REFERENCES table" without "(column)" requires PRIMARY
@ -4357,8 +4356,8 @@ static void foreign_key(CompiledStatement* statement, dsql_nod* element, const c
post_607(Arg::Gds(isc_key_field_count_err)); post_607(Arg::Gds(isc_key_field_count_err));
} }
/* define the foreign key index and the triggers that may be needed // define the foreign key index and the triggers that may be needed
for referential integrity action. */ // for referential integrity action.
make_index_trg_ref_int(statement, element, columns1, element->nod_arg[e_for_refcolumns], make_index_trg_ref_int(statement, element, columns1, element->nod_arg[e_for_refcolumns],
relation2->str_data, index_name); relation2->str_data, index_name);
@ -4821,9 +4820,9 @@ static void make_index( CompiledStatement* statement,
* *
**************************************/ **************************************/
/* stuff either user-defined name or // stuff either user-defined name or
zero-length name, indicating that an index name // zero-length name, indicating that an index name
should be generated */ // should be generated
fb_assert(element->nod_type != nod_foreign); fb_assert(element->nod_type != nod_foreign);
@ -4890,17 +4889,17 @@ static void make_index_trg_ref_int( CompiledStatement* statement,
fb_assert(element->nod_type == nod_foreign) fb_assert(element->nod_type == nod_foreign)
/* for_rel_name_str is the name of the relation // for_rel_name_str is the name of the relation
on which the ddl operation is being done, // on which the ddl operation is being done,
in this case the foreign key table */ // in this case the foreign key table
dsql_nod* ddl_node = statement->req_ddl_node; dsql_nod* ddl_node = statement->req_ddl_node;
dsql_nod* for_rel_node = ddl_node->nod_arg[e_drl_name]; dsql_nod* for_rel_node = ddl_node->nod_arg[e_drl_name];
const dsql_str* for_rel_name_str = (dsql_str*) for_rel_node->nod_arg[e_rln_name]; const dsql_str* for_rel_name_str = (dsql_str*) for_rel_node->nod_arg[e_rln_name];
/* stuff either user-defined name or // stuff either user-defined name or
zero-length name, indicating that an index name // zero-length name, indicating that an index name
should be generated */ // should be generated
dsql_nod* index = element->nod_arg[e_for_index]; dsql_nod* index = element->nod_arg[e_for_index];
fb_assert(index); fb_assert(index);
@ -5033,7 +5032,7 @@ static void modify_database( CompiledStatement* statement)
const dsql_nod* ddl_node = statement->req_ddl_node; const dsql_nod* ddl_node = statement->req_ddl_node;
statement->append_uchar(isc_dyn_mod_database); statement->append_uchar(isc_dyn_mod_database);
// statement->append_number(isc_dyn_rel_sql_protection, 1); // statement->append_number(isc_dyn_rel_sql_protection, 1);
bool drop_difference = false; bool drop_difference = false;
const dsql_nod* elements = ddl_node->nod_arg[e_adb_all]; const dsql_nod* elements = ddl_node->nod_arg[e_adb_all];
@ -5106,9 +5105,9 @@ static void modify_domain( CompiledStatement* statement)
dsql_str* string; dsql_str* string;
dsql_fld* field; dsql_fld* field;
dsql_fld local_field(statement->req_pool); dsql_fld local_field(statement->req_pool);
/* CVC: This array used with check_one_call to ensure each modification // CVC: This array used with check_one_call to ensure each modification
option is called only once. Enlarge it if the switch() below gets more // option is called only once. Enlarge it if the switch() below gets more
cases. */ // cases.
USHORT repetition_count[6]; USHORT repetition_count[6];
dsql_nod* ddl_node = statement->req_ddl_node; dsql_nod* ddl_node = statement->req_ddl_node;
@ -5118,8 +5117,8 @@ static void modify_domain( CompiledStatement* statement)
statement->append_cstring(isc_dyn_mod_global_fld, domain_name->str_data); statement->append_cstring(isc_dyn_mod_global_fld, domain_name->str_data);
/* Is MOVE_CLEAR enough for all platforms? // Is MOVE_CLEAR enough for all platforms?
MOVE_CLEAR (repetition_count, sizeof (repetition_count)); */ // MOVE_CLEAR (repetition_count, sizeof (repetition_count));
const USHORT rtop = FB_NELEM(repetition_count); const USHORT rtop = FB_NELEM(repetition_count);
USHORT* p = repetition_count; USHORT* p = repetition_count;
while (p < repetition_count + rtop) { while (p < repetition_count + rtop) {
@ -5143,9 +5142,9 @@ static void modify_domain( CompiledStatement* statement)
statement->append_uchar(isc_dyn_single_validation); statement->append_uchar(isc_dyn_single_validation);
statement->begin_blr(isc_dyn_fld_validation_blr); statement->begin_blr(isc_dyn_fld_validation_blr);
/* Get the attributes of the domain, and set any occurances of // Get the attributes of the domain, and set any occurances of
nod_dom_value (corresponding to the keyword VALUE) to the // nod_dom_value (corresponding to the keyword VALUE) to the
correct type, length, scale, etc. */ // correct type, length, scale, etc.
if (!METD_get_domain(statement, &local_field, domain_name->str_data)) if (!METD_get_domain(statement, &local_field, domain_name->str_data))
{ {
// Specified domain or source field does not exist // Specified domain or source field does not exist
@ -5155,14 +5154,14 @@ static void modify_domain( CompiledStatement* statement)
if (element->nod_arg[e_cnstr_condition]) if (element->nod_arg[e_cnstr_condition])
set_nod_value_attributes(element->nod_arg[e_cnstr_condition], &local_field); set_nod_value_attributes(element->nod_arg[e_cnstr_condition], &local_field);
/* Increment the context level for this statement, so that // Increment the context level for this statement, so that
the context number for any RSE generated for a SELECT // the context number for any RSE generated for a SELECT
within the CHECK clause will be greater than 0. In the // within the CHECK clause will be greater than 0. In the
environment of a domain check constraint, context // environment of a domain check constraint, context
number 0 is reserved for the "blr_fid, 0, 0, 0," which // number 0 is reserved for the "blr_fid, 0, 0, 0," which
is emitted for a nod_dom_value, corresponding to an // is emitted for a nod_dom_value, corresponding to an
occurance of the VALUE keyword in the body of the check // occurance of the VALUE keyword in the body of the check
constraint. -- chrisj 1999-08-20 */ // constraint. -- chrisj 1999-08-20
statement->req_context_number++; statement->req_context_number++;
{ {
@ -5289,9 +5288,9 @@ static void put_user_grant(CompiledStatement* statement, const dsql_nod* user)
break; break;
default: default:
/* CVC: Here we should complain: DYN doesn't check parameters // CVC: Here we should complain: DYN doesn't check parameters
and it will write trash in rdb$user_privileges. We probably // and it will write trash in rdb$user_privileges. We probably
should complain in most cases when "name" is blank, too. */ // should complain in most cases when "name" is blank, too.
break; break;
} }
} }
@ -5324,7 +5323,7 @@ static void modify_privilege(CompiledStatement* statement,
statement->append_uchar(isc_dyn_revoke); statement->append_uchar(isc_dyn_revoke);
} }
// stuff the privileges string // stuff the privileges string
SSHORT priv_count = 0; SSHORT priv_count = 0;
statement->append_ushort(0); statement->append_ushort(0);
@ -5486,9 +5485,8 @@ static void modify_relation(CompiledStatement* statement)
Arg::Gds(isc_random) << Arg::Str(linecol)); Arg::Gds(isc_random) << Arg::Str(linecol));
} }
/* need to handle error that occur in generating dyn string. // need to handle error that occur in generating dyn string.
* If there is an error, get rid of the cached data // If there is an error, get rid of the cached data
*/
try { try {
@ -5543,16 +5541,15 @@ static void modify_relation(CompiledStatement* statement)
case nod_del_field: case nod_del_field:
/* Fix for bug 8054: // Fix for bug 8054:
//
[CASCADE | RESTRICT] syntax is available in IB4.5, but not // [CASCADE | RESTRICT] syntax is available in IB4.5, but not
required until v5.0. // required until v5.0.
//
Option CASCADE causes an error : // Option CASCADE causes an error :
unsupported DSQL construct // unsupported DSQL construct
//
Option RESTRICT is default behaviour. // Option RESTRICT is default behaviour.
*/
field_node = element->nod_arg[0]; field_node = element->nod_arg[0];
field_name = (dsql_str*) field_node->nod_arg[e_fln_name]; field_name = (dsql_str*) field_node->nod_arg[e_fln_name];
@ -5847,7 +5844,7 @@ static void put_descriptor(CompiledStatement* statement, const dsc* desc)
static void put_dtype(CompiledStatement* statement, const dsql_fld* field, bool use_subtype) static void put_dtype(CompiledStatement* statement, const dsql_fld* field, bool use_subtype)
{ {
#ifdef DEV_BUILD #ifdef DEV_BUILD
// Check if the field describes a known datatype // Check if the field describes a known datatype
if (field->fld_dtype > FB_NELEM(blr_dtypes) || !blr_dtypes[field->fld_dtype]) if (field->fld_dtype > FB_NELEM(blr_dtypes) || !blr_dtypes[field->fld_dtype])
{ {
@ -6427,7 +6424,7 @@ static void stuff_matching_blr(CompiledStatement* statement, const dsql_nod* for
* *
**************************************/ **************************************/
// count of foreign key columns // count of foreign key columns
fb_assert(prim_columns->nod_count == for_columns->nod_count); fb_assert(prim_columns->nod_count == for_columns->nod_count);
fb_assert(prim_columns->nod_count != 0); fb_assert(prim_columns->nod_count != 0);
@ -6688,12 +6685,11 @@ static void set_nod_value_attributes( dsql_nod* node, const dsql_fld* field)
} }
else if ((nod_constant != child->nod_type) && (child->nod_count > 0)) else if ((nod_constant != child->nod_type) && (child->nod_count > 0))
{ {
/* A nod_constant can have nod_arg entries which are not really // A nod_constant can have nod_arg entries which are not really
pointers to other nodes, but rather integer values, so // pointers to other nodes, but rather integer values, so
it is not safe to scan through its children. Fortunately, // it is not safe to scan through its children. Fortunately,
it cannot have a nod_dom_value as a child in any case, so // it cannot have a nod_dom_value as a child in any case, so
we lose nothing by skipping it. // we lose nothing by skipping it.
*/
set_nod_value_attributes(child, field); set_nod_value_attributes(child, field);
} }
@ -6807,15 +6803,18 @@ void CompiledStatement::append_string(UCHAR verb, const char* string, USHORT len
append_uchar(length); append_uchar(length);
} }
/* CVC: I preserve this code but it's inconsistent: we first log the length // CVC: I preserve this code but it's inconsistent: we first log the length
then we check the null terminator. If we want this, we should recalculate the // then we check the null terminator. If we want this, we should recalculate the
length and log the correct length instead. // length and log the correct length instead.
if (string) { /*
if (string)
{
for (; length-- && *string; string++) { for (; length-- && *string; string++) {
append_uchar(*string); append_uchar(*string);
} }
} }
*/ */
if (string) if (string)
append_raw_string(string, length); append_raw_string(string, length);
} }
@ -6876,9 +6875,9 @@ void CompiledStatement::generate_unnamed_trigger_beginning(bool on_update_trigge
// the trigger blr // the trigger blr
begin_blr(isc_dyn_trg_blr); begin_blr(isc_dyn_trg_blr);
/* for ON UPDATE TRIGGER only: generate the trigger firing condition: // for ON UPDATE TRIGGER only: generate the trigger firing condition:
if prim_key.old_value != prim_key.new value. // if prim_key.old_value != prim_key.new value.
Note that the key could consist of multiple columns */ // Note that the key could consist of multiple columns
if (on_update_trigger) { if (on_update_trigger) {
stuff_trg_firing_cond(this, prim_columns); stuff_trg_firing_cond(this, prim_columns);

View File

@ -233,7 +233,7 @@ void DSQL_execute(thread_db* tdbb,
request->req_type = REQ_EMBED_SELECT; request->req_type = REQ_EMBED_SELECT;
} }
// Only allow NULL trans_handle if we're starting a transaction // Only allow NULL trans_handle if we're starting a transaction
if (!*tra_handle && request->req_type != REQ_START_TRANS) if (!*tra_handle && request->req_type != REQ_START_TRANS)
{ {
@ -241,8 +241,8 @@ void DSQL_execute(thread_db* tdbb,
Arg::Gds(isc_bad_trans_handle)); Arg::Gds(isc_bad_trans_handle));
} }
/* If the request is a SELECT or blob statement then this is an open. // If the request is a SELECT or blob statement then this is an open.
Make sure the cursor is not already open. */ // Make sure the cursor is not already open.
if (reqTypeWithCursor(request->req_type)) { if (reqTypeWithCursor(request->req_type)) {
if (request->req_flags & REQ_cursor_open) if (request->req_flags & REQ_cursor_open)
@ -252,7 +252,7 @@ void DSQL_execute(thread_db* tdbb,
} }
} }
// A select with a non zero output length is a singleton select // A select with a non zero output length is a singleton select
bool singleton; bool singleton;
if (request->req_type == REQ_SELECT && out_msg_length != 0) { if (request->req_type == REQ_SELECT && out_msg_length != 0) {
singleton = true; singleton = true;
@ -273,12 +273,12 @@ void DSQL_execute(thread_db* tdbb,
request->req_transaction = *tra_handle; request->req_transaction = *tra_handle;
} }
/* If the output message length is zero on a REQ_SELECT then we must // If the output message length is zero on a REQ_SELECT then we must
* be doing an OPEN cursor operation. // be doing an OPEN cursor operation.
* If we do have an output message length, then we're doing // If we do have an output message length, then we're doing
* a singleton SELECT. In that event, we don't add the cursor // a singleton SELECT. In that event, we don't add the cursor
* to the list of open cursors (it's not really open). // to the list of open cursors (it's not really open).
*/
if (reqTypeWithCursor(request->req_type) && !singleton) if (reqTypeWithCursor(request->req_type) && !singleton)
{ {
request->req_flags |= REQ_cursor_open; request->req_flags |= REQ_cursor_open;
@ -369,10 +369,10 @@ ISC_STATUS DSQL_fetch(thread_db* tdbb,
#ifdef SCROLLABLE_CURSORS #ifdef SCROLLABLE_CURSORS
/* check whether we need to send an asynchronous scrolling message // check whether we need to send an asynchronous scrolling message
to the engine; the engine will automatically advance one record // to the engine; the engine will automatically advance one record
in the same direction as before, so optimize out messages of that // in the same direction as before, so optimize out messages of that
type */ // type
if (request->req_type == REQ_SELECT && request->req_dbb->dbb_base_level >= 5) if (request->req_type == REQ_SELECT && request->req_dbb->dbb_base_level >= 5)
{ {
@ -474,8 +474,8 @@ ISC_STATUS DSQL_fetch(thread_db* tdbb,
Attachment* att = request->req_dbb->dbb_attachment; Attachment* att = request->req_dbb->dbb_attachment;
TraceDSQLFetch trace(att, request); TraceDSQLFetch trace(att, request);
/* Insure that the blr for the message is parsed, regardless of // Insure that the blr for the message is parsed, regardless of
whether anything is found by the call to receive. */ // whether anything is found by the call to receive.
if (blr_length) { if (blr_length) {
parse_blr(blr_length, blr, msg_length, message->msg_parameters); parse_blr(blr_length, blr, msg_length, message->msg_parameters);
@ -591,7 +591,7 @@ void DSQL_insert(thread_db* tdbb,
Arg::Gds(isc_bad_req_handle)); Arg::Gds(isc_bad_req_handle));
} }
// if the cursor isn't open, we've got a problem // if the cursor isn't open, we've got a problem
if (request->req_type == REQ_PUT_SEGMENT) if (request->req_type == REQ_PUT_SEGMENT)
{ {
@ -605,8 +605,8 @@ void DSQL_insert(thread_db* tdbb,
dsql_msg* message = (dsql_msg*) request->req_receive; dsql_msg* message = (dsql_msg*) request->req_receive;
/* Insure that the blr for the message is parsed, regardless of // Insure that the blr for the message is parsed, regardless of
whether anything is found by the call to receive. */ // whether anything is found by the call to receive.
if (blr_length) if (blr_length)
parse_blr(blr_length, blr, msg_length, message->msg_parameters); parse_blr(blr_length, blr, msg_length, message->msg_parameters);
@ -686,29 +686,28 @@ void DSQL_prepare(thread_db* tdbb,
try { try {
// Figure out which parser version to use // Figure out which parser version to use
/* Since the API to dsql8_prepare is public and can not be changed, there needs to // Since the API to dsql8_prepare is public and can not be changed, there needs to
* be a way to send the parser version to DSQL so that the parser can compare the keyword // be a way to send the parser version to DSQL so that the parser can compare the keyword
* version to the parser version. To accomplish this, the parser version is combined with // version to the parser version. To accomplish this, the parser version is combined with
* the client dialect and sent across that way. In dsql8_prepare_statement, the parser version // the client dialect and sent across that way. In dsql8_prepare_statement, the parser version
* and client dialect are separated and passed on to their final destinations. The information // and client dialect are separated and passed on to their final destinations. The information
* is combined as follows: // is combined as follows:
* Dialect * 10 + parser_version // Dialect * 10 + parser_version
* //
* and is extracted in dsql8_prepare_statement as follows: // and is extracted in dsql8_prepare_statement as follows:
* parser_version = ((dialect *10)+parser_version)%10 // parser_version = ((dialect *10)+parser_version)%10
* client_dialect = ((dialect *10)+parser_version)/10 // client_dialect = ((dialect *10)+parser_version)/10
* //
* For example, parser_version = 1 and client dialect = 1 // For example, parser_version = 1 and client dialect = 1
* //
* combined = (1 * 10) + 1 == 11 // combined = (1 * 10) + 1 == 11
* //
* parser = (combined) %10 == 1 // parser = (combined) %10 == 1
* dialect = (combined) / 19 == 1 // dialect = (combined) / 19 == 1
* //
* If the parser version is not part of the dialect, then assume that the // If the parser version is not part of the dialect, then assume that the
* connection being made is a local classic connection. // connection being made is a local classic connection.
*/
USHORT parser_version; USHORT parser_version;
if ((dialect / 10) == 0) if ((dialect / 10) == 0)
@ -1107,29 +1106,28 @@ static void execute_immediate(thread_db* tdbb,
try { try {
// Figure out which parser version to use // Figure out which parser version to use
/* Since the API to dsql8_execute_immediate is public and can not be changed, there needs to // Since the API to dsql8_execute_immediate is public and can not be changed, there needs to
* be a way to send the parser version to DSQL so that the parser can compare the keyword // be a way to send the parser version to DSQL so that the parser can compare the keyword
* version to the parser version. To accomplish this, the parser version is combined with // version to the parser version. To accomplish this, the parser version is combined with
* the client dialect and sent across that way. In dsql8_execute_immediate, the parser version // the client dialect and sent across that way. In dsql8_execute_immediate, the parser version
* and client dialect are separated and passed on to their final destinations. The information // and client dialect are separated and passed on to their final destinations. The information
* is combined as follows: // is combined as follows:
* Dialect * 10 + parser_version // Dialect * 10 + parser_version
* //
* and is extracted in dsql8_execute_immediate as follows: // and is extracted in dsql8_execute_immediate as follows:
* parser_version = ((dialect *10)+parser_version)%10 // parser_version = ((dialect *10)+parser_version)%10
* client_dialect = ((dialect *10)+parser_version)/10 // client_dialect = ((dialect *10)+parser_version)/10
* //
* For example, parser_version = 1 and client dialect = 1 // For example, parser_version = 1 and client dialect = 1
* //
* combined = (1 * 10) + 1 == 11 // combined = (1 * 10) + 1 == 11
* //
* parser = (combined) %10 == 1 // parser = (combined) %10 == 1
* dialect = (combined) / 19 == 1 // dialect = (combined) / 19 == 1
* //
* If the parser version is not part of the dialect, then assume that the // If the parser version is not part of the dialect, then assume that the
* connection being made is a local classic connection. // connection being made is a local classic connection.
*/
USHORT parser_version; USHORT parser_version;
if ((dialect / 10) == 0) if ((dialect / 10) == 0)
@ -1292,8 +1290,8 @@ static void execute_request(thread_db* tdbb,
char temp_buffer[FB_DOUBLE_ALIGN * 2]; char temp_buffer[FB_DOUBLE_ALIGN * 2];
dsql_msg temp_msg; dsql_msg temp_msg;
/* Insure that the blr for the message is parsed, regardless of // Insure that the blr for the message is parsed, regardless of
whether anything is found by the call to receive. */ // whether anything is found by the call to receive.
if (out_msg_length && out_blr_length) { if (out_msg_length && out_blr_length) {
parse_blr(out_blr_length, out_blr, out_msg_length, message->msg_parameters); parse_blr(out_blr_length, out_blr, out_msg_length, message->msg_parameters);
@ -1317,10 +1315,10 @@ static void execute_request(thread_db* tdbb,
{ {
USHORT counter; USHORT counter;
/* Create a temp message buffer and try two more receives. // Create a temp message buffer and try two more receives.
If both succeed then the first is the next record and the // If both succeed then the first is the next record and the
second is either another record or the end of record message. // second is either another record or the end of record message.
In either case, there's more than one record. */ // In either case, there's more than one record.
UCHAR* message_buffer = (UCHAR*) gds__alloc((ULONG) message->msg_length); UCHAR* message_buffer = (UCHAR*) gds__alloc((ULONG) message->msg_length);
@ -1344,9 +1342,9 @@ static void execute_request(thread_db* tdbb,
gds__free(message_buffer); gds__free(message_buffer);
/* two successful receives means more than one record // two successful receives means more than one record
a req_sync error on the first pass above means no records // a req_sync error on the first pass above means no records
a non-req_sync error on any of the passes above is an error */ // a non-req_sync error on any of the passes above is an error
if (!status) if (!status)
{ {
@ -1451,8 +1449,8 @@ static bool get_indices(SSHORT* explain_length_ptr, const SCHAR** explain_ptr,
SSHORT plan_length = *plan_length_ptr; SSHORT plan_length = *plan_length_ptr;
SCHAR* plan = *plan_ptr; SCHAR* plan = *plan_ptr;
/* go through the index tree information, just // go through the index tree information, just
extracting the indices used */ // extracting the indices used
explain_length--; explain_length--;
switch (*explain++) switch (*explain++)
@ -1573,8 +1571,8 @@ USHORT DSQL_get_plan_info(thread_db* tdbb,
plan = buffer_ptr; plan = buffer_ptr;
/* CVC: What if we need to do 2nd pass? Those variables were only initialized // CVC: What if we need to do 2nd pass? Those variables were only initialized
at the begining of the function hence they had trash the second time. */ // at the begining of the function hence they had trash the second time.
USHORT join_count = 0, level = 0; USHORT join_count = 0, level = 0;
// keep going until we reach the end of the explain info // keep going until we reach the end of the explain info
@ -1745,13 +1743,13 @@ static bool get_rsb_item(SSHORT* explain_length_ptr,
if (*level_ptr) { if (*level_ptr) {
(*level_ptr)--; (*level_ptr)--;
} }
/* else --*parent_join_count; ??? */ // else --*parent_join_count; ???
break; break;
case isc_info_rsb_relation: case isc_info_rsb_relation:
/* for the single relation case, initiate // for the single relation case, initiate
the relation with a parenthesis */ // the relation with a parenthesis
if (!*parent_join_count) { if (!*parent_join_count) {
if (--plan_length < 0) if (--plan_length < 0)
@ -1783,12 +1781,11 @@ static bool get_rsb_item(SSHORT* explain_length_ptr,
case isc_info_rsb_type: case isc_info_rsb_type:
explain_length--; explain_length--;
// for stream types which have multiple substreams, print out
// the stream type and recursively print out the substreams so
// we will know where to put the parentheses
switch (rsb_type = *explain++) switch (rsb_type = *explain++)
{ {
/* for stream types which have multiple substreams, print out
the stream type and recursively print out the substreams so
we will know where to put the parentheses */
case isc_info_rsb_union: case isc_info_rsb_union:
case isc_info_rsb_recursive: case isc_info_rsb_recursive:
@ -1812,8 +1809,8 @@ static bool get_rsb_item(SSHORT* explain_length_ptr,
break; break;
} }
/* for the rest of the members, start the level at 0 so each // for the rest of the members, start the level at 0 so each
gets its own "PLAN ... " line */ // gets its own "PLAN ... " line
while (union_count) while (union_count)
{ {
@ -1838,8 +1835,8 @@ static bool get_rsb_item(SSHORT* explain_length_ptr,
case isc_info_rsb_left_cross: case isc_info_rsb_left_cross:
case isc_info_rsb_merge: case isc_info_rsb_merge:
/* if this join is itself part of a join list, // if this join is itself part of a join list,
but not the first item, then put out a comma */ // but not the first item, then put out a comma
if (*parent_join_count && plan[-1] != '(') if (*parent_join_count && plan[-1] != '(')
{ {
@ -1962,10 +1959,10 @@ static bool get_rsb_item(SSHORT* explain_length_ptr,
case isc_info_rsb_sort: case isc_info_rsb_sort:
/* if this sort is on behalf of a union, don't bother to // if this sort is on behalf of a union, don't bother to
print out the sort, because unions handle the sort on all // print out the sort, because unions handle the sort on all
substreams at once, and a plan maps to each substream // substreams at once, and a plan maps to each substream
in the union, so the sort doesn't really apply to a particular plan */ // in the union, so the sort doesn't really apply to a particular plan
if (explain_length > 2 && (explain[0] == isc_info_rsb_begin) && if (explain_length > 2 && (explain[0] == isc_info_rsb_begin) &&
(explain[1] == isc_info_rsb_type) && (explain[2] == isc_info_rsb_union)) (explain[1] == isc_info_rsb_type) && (explain[2] == isc_info_rsb_union))
@ -1991,8 +1988,8 @@ static bool get_rsb_item(SSHORT* explain_length_ptr,
while (*p) while (*p)
*plan++ = *p++; *plan++ = *p++;
/* the rsb_sort should always be followed by a begin...end block, // the rsb_sort should always be followed by a begin...end block,
allowing us to include everything inside the sort in parentheses */ // allowing us to include everything inside the sort in parentheses
{ // scope to have save_level local. { // scope to have save_level local.
const USHORT save_level = *level_ptr; const USHORT save_level = *level_ptr;
@ -2222,8 +2219,8 @@ static void map_in_out( dsql_req* request,
} }
} }
/* If we got here because the loop was exited early or if part of the // If we got here because the loop was exited early or if part of the
message given to us hasn't been used, complain. */ // message given to us hasn't been used, complain.
if (parameter || count) if (parameter || count)
{ {
@ -2275,8 +2272,8 @@ static void map_in_out( dsql_req* request,
static USHORT parse_blr(USHORT blr_length, static USHORT parse_blr(USHORT blr_length,
const UCHAR* blr, const USHORT msg_length, dsql_par* parameters) const UCHAR* blr, const USHORT msg_length, dsql_par* parameters)
{ {
/* If there's no blr length, then the format of the current message buffer // If there's no blr length, then the format of the current message buffer
is identical to the format of the previous one. */ // is identical to the format of the previous one.
if (!blr_length) if (!blr_length)
{ {
@ -2500,7 +2497,7 @@ static dsql_req* prepare(thread_db* tdbb, dsql_dbb* database, jrd_tra* transacti
string_length = strlen(string); string_length = strlen(string);
} }
/* Get rid of the trailing ";" if there is one. */ // Get rid of the trailing ";" if there is one.
for (const TEXT* p = string + string_length; p-- > string;) for (const TEXT* p = string + string_length; p-- > string;)
{ {
@ -2553,8 +2550,8 @@ static dsql_req* prepare(thread_db* tdbb, dsql_dbb* database, jrd_tra* transacti
#ifdef SCROLLABLE_CURSORS #ifdef SCROLLABLE_CURSORS
if (statement->req_dbb->dbb_base_level >= 5) { if (statement->req_dbb->dbb_base_level >= 5) {
/* allocate a message in which to send scrolling information // allocate a message in which to send scrolling information
outside of the normal send/receive protocol */ // outside of the normal send/receive protocol
statement->req_async = message = FB_NEW(*tdsql->getDefaultPool()) dsql_msg; statement->req_async = message = FB_NEW(*tdsql->getDefaultPool()) dsql_msg;
message->msg_number = 2; message->msg_number = 2;
@ -2564,12 +2561,10 @@ static dsql_req* prepare(thread_db* tdbb, dsql_dbb* database, jrd_tra* transacti
statement->req_type = REQ_SELECT; statement->req_type = REQ_SELECT;
statement->req_flags &= ~REQ_cursor_open; statement->req_flags &= ~REQ_cursor_open;
/* // No work is done during pass1 for set transaction - like
* No work is done during pass1 for set transaction - like // checking for valid table names. This is because that will
* checking for valid table names. This is because that will // require a valid transaction handle.
* require a valid transaction handle. // Error will be caught at execute time.
* Error will be caught at execute time.
*/
node = PASS1_statement(statement, node); node = PASS1_statement(statement, node);
if (!node) if (!node)

View File

@ -219,7 +219,7 @@ static void internal_post(const ISC_STATUS* tmp_status)
{ {
ISC_STATUS* status_vector = JRD_get_thread_data()->tdbb_status_vector; ISC_STATUS* status_vector = JRD_get_thread_data()->tdbb_status_vector;
// calculate length of the status // calculate length of the status
int tmp_status_len = 0, warning_indx = 0; int tmp_status_len = 0, warning_indx = 0;
PARSE_STATUS(tmp_status, tmp_status_len, warning_indx); PARSE_STATUS(tmp_status, tmp_status_len, warning_indx);
fb_assert(warning_indx == 0); fb_assert(warning_indx == 0);
@ -309,16 +309,16 @@ void ERRD_punt(const ISC_STATUS* local)
{ {
thread_db* tdbb = JRD_get_thread_data(); thread_db* tdbb = JRD_get_thread_data();
// copy local status into user status // copy local status into user status
if (local) { if (local) {
UTLD_copy_status(local, tdbb->tdbb_status_vector); UTLD_copy_status(local, tdbb->tdbb_status_vector);
} }
// Save any strings in a permanent location // Save any strings in a permanent location
UTLD_save_status_strings(tdbb->tdbb_status_vector); UTLD_save_status_strings(tdbb->tdbb_status_vector);
// Give up whatever we were doing and return to the user. // Give up whatever we were doing and return to the user.
status_exception::raise(tdbb->tdbb_status_vector); status_exception::raise(tdbb->tdbb_status_vector);
} }

View File

@ -642,10 +642,10 @@ void GEN_expr(CompiledStatement* statement, dsql_nod* node)
GEN_expr(statement, *ptr); GEN_expr(statement, *ptr);
} }
/* Check whether the node we just processed is for a dialect 3 // Check whether the node we just processed is for a dialect 3
operation which gives a different result than the corresponding // operation which gives a different result than the corresponding
operation in dialect 1. If it is, and if the client dialect is 2, // operation in dialect 1. If it is, and if the client dialect is 2,
issue a warning about the difference. */ // issue a warning about the difference.
switch (node->nod_type) switch (node->nod_type)
{ {
@ -760,15 +760,14 @@ void GEN_port(CompiledStatement* statement, dsql_msg* message)
parameter->par_desc.setTextType(toCharSet); parameter->par_desc.setTextType(toCharSet);
} }
/* For older clients - generate an error should they try and // For older clients - generate an error should they try and
access data types which did not exist in the older dialect */ // access data types which did not exist in the older dialect
if (statement->req_client_dialect <= SQL_DIALECT_V5) if (statement->req_client_dialect <= SQL_DIALECT_V5)
switch (parameter->par_desc.dsc_dtype) switch (parameter->par_desc.dsc_dtype)
{ {
// In V6.0 - older clients, which we distinguish by
/* In V6.0 - older clients, which we distinguish by // their use of SQL DIALECT 0 or 1, are forbidden
their use of SQL DIALECT 0 or 1, are forbidden // from selecting values of new datatypes
from selecting values of new datatypes */
case dtype_sql_date: case dtype_sql_date:
case dtype_sql_time: case dtype_sql_time:
case dtype_int64: case dtype_int64:
@ -936,7 +935,7 @@ void GEN_start_transaction( CompiledStatement* statement, const dsql_nod* tran_n
sw_reserve = false, sw_lock_timeout = false; sw_reserve = false, sw_lock_timeout = false;
int misc_flags = 0; int misc_flags = 0;
// Stuff some version info. // Stuff some version info.
if (count = node->nod_count) if (count = node->nod_count)
stuff(statement, isc_tpb_version1); stuff(statement, isc_tpb_version1);
@ -1258,23 +1257,23 @@ void GEN_statement( CompiledStatement* statement, dsql_nod* node)
stuff(statement, blr_abort); stuff(statement, blr_abort);
string = (dsql_str*) node->nod_arg[e_xcps_name]; string = (dsql_str*) node->nod_arg[e_xcps_name];
temp = node->nod_arg[e_xcps_msg]; temp = node->nod_arg[e_xcps_msg];
/* if exception name is undefined, // if exception name is undefined,
it means we have re-initiate semantics here, // it means we have re-initiate semantics here,
so blr_raise verb should be generated */ // so blr_raise verb should be generated
if (!string) if (!string)
{ {
stuff(statement, blr_raise); stuff(statement, blr_raise);
return; return;
} }
/* if exception value is defined, // if exception value is defined,
it means we have user-defined exception message here, // it means we have user-defined exception message here,
so blr_exception_msg verb should be generated */ // so blr_exception_msg verb should be generated
if (temp) if (temp)
{ {
stuff(statement, blr_exception_msg); stuff(statement, blr_exception_msg);
} }
/* otherwise go usual way, // otherwise go usual way,
i.e. generate blr_exception */ // i.e. generate blr_exception
else else
{ {
stuff(statement, blr_exception); stuff(statement, blr_exception);
@ -1288,8 +1287,8 @@ void GEN_statement( CompiledStatement* statement, dsql_nod* node)
} }
} }
stuff_cstring(statement, string->str_data); stuff_cstring(statement, string->str_data);
/* if exception value is defined, // if exception value is defined,
generate appropriate BLR verbs */ // generate appropriate BLR verbs
if (temp) if (temp)
{ {
GEN_expr(statement, temp); GEN_expr(statement, temp);
@ -1406,7 +1405,7 @@ static void gen_aggregate( CompiledStatement* statement, const dsql_nod* node)
stuff_context(statement, context); stuff_context(statement, context);
gen_rse(statement, node->nod_arg[e_agg_rse]); gen_rse(statement, node->nod_arg[e_agg_rse]);
// Handle GROUP BY clause // Handle GROUP BY clause
stuff(statement, blr_group_by); stuff(statement, blr_group_by);
@ -1422,7 +1421,7 @@ static void gen_aggregate( CompiledStatement* statement, const dsql_nod* node)
else else
stuff(statement, 0); stuff(statement, 0);
// Generate value map // Generate value map
gen_map(statement, context->ctx_map); gen_map(statement, context->ctx_map);
} }
@ -1547,9 +1546,9 @@ static void gen_constant( CompiledStatement* statement, const dsc* desc, bool ne
case dtype_double: case dtype_double:
{ {
/* 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;
@ -1573,24 +1572,24 @@ static void gen_constant( CompiledStatement* statement, const dsc* desc, bool ne
i64value = -i64value; i64value = -i64value;
else if (i64value == MIN_SINT64) else if (i64value == MIN_SINT64)
{ {
/* UH OH! // UH OH!
* yylex correctly recognized the digits as the most-negative // yylex correctly recognized the digits as the most-negative
* possible INT64 value, but unfortunately, there was no // possible INT64 value, but unfortunately, there was no
* preceding '-' (a fact which the lexer could not know). // preceding '-' (a fact which the lexer could not know).
* The value is too big for a positive INT64 value, and it // The value is too big for a positive INT64 value, and it
* didn't contain an exponent so it's not a valid DOUBLE // didn't contain an exponent so it's not a valid DOUBLE
* PRECISION literal either, so we have to bounce it. // PRECISION literal either, so we have to bounce it.
*/
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
Arg::Gds(isc_arith_except) << Arg::Gds(isc_arith_except) <<
Arg::Gds(isc_numeric_out_of_range)); Arg::Gds(isc_numeric_out_of_range));
} }
/* We and the lexer both agree that this is an SINT64 constant, // We and the lexer both agree that this is an SINT64 constant,
* and if the value needed to be negated, it already has been. // and if the value needed to be negated, it already has been.
* If the value will fit into a 32-bit signed integer, generate // If the value will fit into a 32-bit signed integer, generate
* it that way, else as an INT64. // it that way, else as an INT64.
*/
if ((i64value >= (SINT64) MIN_SLONG) && (i64value <= (SINT64) MAX_SLONG)) if ((i64value >= (SINT64) MIN_SLONG) && (i64value <= (SINT64) MAX_SLONG))
{ {
@ -1924,8 +1923,8 @@ static void gen_exec_stmt(CompiledStatement* statement, const dsql_nod* node)
static void gen_field( CompiledStatement* statement, const dsql_ctx* context, static void gen_field( CompiledStatement* statement, const dsql_ctx* context,
const dsql_fld* field, dsql_nod* indices) const dsql_fld* field, dsql_nod* indices)
{ {
/* For older clients - generate an error should they try and // For older clients - generate an error should they try and
* access data types which did not exist in the older dialect */ // access data types which did not exist in the older dialect
if (statement->req_client_dialect <= SQL_DIALECT_V5) if (statement->req_client_dialect <= SQL_DIALECT_V5)
{ {
switch (field->fld_dtype) switch (field->fld_dtype)
@ -2183,7 +2182,7 @@ static void gen_parameter( CompiledStatement* statement, const dsql_par* paramet
**/ **/
static void gen_plan( CompiledStatement* statement, const dsql_nod* plan_expression) static void gen_plan( CompiledStatement* statement, const dsql_nod* plan_expression)
{ {
// stuff the join type // stuff the join type
const dsql_nod* list = plan_expression->nod_arg[1]; const dsql_nod* list = plan_expression->nod_arg[1];
if (list->nod_count > 1) { if (list->nod_count > 1) {
@ -2194,7 +2193,7 @@ static void gen_plan( CompiledStatement* statement, const dsql_nod* plan_express
stuff(statement, list->nod_count); stuff(statement, list->nod_count);
} }
// stuff one or more plan items // stuff one or more plan items
const dsql_nod* const* ptr = list->nod_arg; const dsql_nod* const* ptr = list->nod_arg;
for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end; ptr++) for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end; ptr++)
@ -2209,8 +2208,8 @@ static void gen_plan( CompiledStatement* statement, const dsql_nod* plan_express
stuff(statement, blr_retrieve); stuff(statement, blr_retrieve);
/* stuff the relation--the relation id itself is redundant except // stuff the relation--the relation id itself is redundant except
when there is a need to differentiate the base tables of views */ // when there is a need to differentiate the base tables of views
const dsql_nod* arg = node->nod_arg[0]; const dsql_nod* arg = node->nod_arg[0];
gen_relation(statement, (dsql_ctx*) arg->nod_arg[e_rel_context]); gen_relation(statement, (dsql_ctx*) arg->nod_arg[e_rel_context]);
@ -2404,7 +2403,7 @@ static void gen_rse( CompiledStatement* statement, const dsql_nod* rse)
dsql_nod* list = rse->nod_arg[e_rse_streams]; dsql_nod* list = rse->nod_arg[e_rse_streams];
// Handle source streams // Handle source streams
if (list->nod_type == nod_union) { if (list->nod_type == nod_union) {
stuff(statement, 1); stuff(statement, 1);
@ -2468,7 +2467,7 @@ static void gen_rse( CompiledStatement* statement, const dsql_nod* rse)
} }
} }
// if the user specified an access plan to use, add it here // if the user specified an access plan to use, add it here
if ((node = rse->nod_arg[e_rse_plan]) != NULL) { if ((node = rse->nod_arg[e_rse_plan]) != NULL) {
stuff(statement, blr_plan); stuff(statement, blr_plan);
@ -2476,11 +2475,11 @@ static void gen_rse( CompiledStatement* statement, const dsql_nod* rse)
} }
#ifdef SCROLLABLE_CURSORS #ifdef SCROLLABLE_CURSORS
/* generate a statement to be executed if the user scrolls // generate a statement to be executed if the user scrolls
in a direction other than forward; a message is sent outside // in a direction other than forward; a message is sent outside
the normal send/receive protocol to specify the direction // the normal send/receive protocol to specify the direction
and offset to scroll; note that we do this only on a SELECT // and offset to scroll; note that we do this only on a SELECT
type statement and only when talking to a 4.1 engine or greater */ // type statement and only when talking to a 4.1 engine or greater
if (statement->req_type == REQ_SELECT && statement->req_dbb->dbb_base_level >= 5) if (statement->req_type == REQ_SELECT && statement->req_dbb->dbb_base_level >= 5)
{ {
@ -2548,7 +2547,7 @@ static void gen_select( CompiledStatement* statement, dsql_nod* rse)
fb_assert(rse->nod_type == nod_rse); fb_assert(rse->nod_type == nod_rse);
// Set up parameter for things in the select list // Set up parameter for things in the select list
const dsql_nod* list = rse->nod_arg[e_rse_items]; const dsql_nod* list = rse->nod_arg[e_rse_items];
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; ptr < end; ptr++) for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end; ptr++)
@ -2558,7 +2557,7 @@ static void gen_select( CompiledStatement* statement, dsql_nod* rse)
MAKE_desc(statement, &parameter->par_desc, *ptr, NULL); MAKE_desc(statement, &parameter->par_desc, *ptr, NULL);
} }
// Set up parameter to handle EOF // Set up parameter to handle EOF
dsql_par* parameter_eof = MAKE_parameter(statement->req_receive, false, false, 0, NULL); dsql_par* parameter_eof = MAKE_parameter(statement->req_receive, false, false, 0, NULL);
statement->req_eof = parameter_eof; statement->req_eof = parameter_eof;
@ -2566,7 +2565,7 @@ static void gen_select( CompiledStatement* statement, dsql_nod* rse)
parameter_eof->par_desc.dsc_scale = 0; parameter_eof->par_desc.dsc_scale = 0;
parameter_eof->par_desc.dsc_length = sizeof(SSHORT); parameter_eof->par_desc.dsc_length = sizeof(SSHORT);
// Save DBKEYs for possible update later // Save DBKEYs for possible update later
list = rse->nod_arg[e_rse_streams]; list = rse->nod_arg[e_rse_streams];
@ -2601,8 +2600,8 @@ static void gen_select( CompiledStatement* statement, dsql_nod* rse)
} }
#ifdef SCROLLABLE_CURSORS #ifdef SCROLLABLE_CURSORS
/* define the parameters for the scrolling message--offset and direction, // define the parameters for the scrolling message--offset and direction,
in that order to make it easier to generate the statement */ // in that order to make it easier to generate the statement
if (statement->req_type == REQ_SELECT && statement->req_dbb->dbb_base_level >= 5) if (statement->req_type == REQ_SELECT && statement->req_dbb->dbb_base_level >= 5)
{ {
@ -2622,7 +2621,7 @@ static void gen_select( CompiledStatement* statement, dsql_nod* rse)
} }
#endif #endif
// Generate definitions for the messages // Generate definitions for the messages
GEN_port(statement, statement->req_receive); GEN_port(statement, statement->req_receive);
dsql_msg* message = statement->req_send; dsql_msg* message = statement->req_send;
@ -2635,14 +2634,14 @@ static void gen_select( CompiledStatement* statement, dsql_nod* rse)
GEN_port(statement, statement->req_async); GEN_port(statement, statement->req_async);
#endif #endif
// If there is a send message, build a RECEIVE // If there is a send message, build a RECEIVE
if ((message = statement->req_send) != NULL) { if ((message = statement->req_send) != NULL) {
stuff(statement, blr_receive); stuff(statement, blr_receive);
stuff(statement, message->msg_number); stuff(statement, message->msg_number);
} }
// Generate FOR loop // Generate FOR loop
message = statement->req_receive; message = statement->req_receive;
@ -2654,7 +2653,7 @@ static void gen_select( CompiledStatement* statement, dsql_nod* rse)
stuff(statement, message->msg_number); stuff(statement, message->msg_number);
stuff(statement, blr_begin); stuff(statement, blr_begin);
// Build body of FOR loop // Build body of FOR loop
SSHORT constant; SSHORT constant;
dsc constant_desc; dsc constant_desc;
@ -3089,7 +3088,7 @@ static void gen_union( CompiledStatement* statement, const dsql_nod* union_node)
stuff(statement, blr_union); stuff(statement, blr_union);
} }
// Obtain the context for UNION from the first dsql_map* node // Obtain the context for UNION from the first dsql_map* node
dsql_nod* items = union_node->nod_arg[e_rse_items]; dsql_nod* items = union_node->nod_arg[e_rse_items];
dsql_nod* map_item = items->nod_arg[0]; dsql_nod* map_item = items->nod_arg[0];
// AB: First item could be a virtual field generated by derived table. // AB: First item could be a virtual field generated by derived table.

View File

@ -230,9 +230,9 @@ dsql_sym* HSHD_lookup(const void* database,
symbol = symbol->sym_homonym; symbol = symbol->sym_homonym;
} }
/* If the symbol found was not part of the list of keywords for the // If the symbol found was not part of the list of keywords for the
* client connecting, then assume nothing was found // client connecting, then assume nothing was found
*/
if (symbol) if (symbol)
{ {
if (parser_version < symbol->sym_version && type == SYM_keyword) if (parser_version < symbol->sym_version && type == SYM_keyword)
@ -306,8 +306,8 @@ void HSHD_set_flag(const void* database,
SYM_TYPE type, SYM_TYPE type,
SSHORT flag) SSHORT flag)
{ {
/* as of now, there's no work to do if there is no database or if // as of now, there's no work to do if there is no database or if
the type is not a relation, procedure or function */ // the type is not a relation, procedure or function
if (!database) if (!database)
return; return;
@ -339,9 +339,9 @@ void HSHD_set_flag(const void* database,
{ {
// the homonym is of the correct type // the homonym is of the correct type
/* the next check is for the same relation or procedure ID, // the next check is for the same relation or procedure ID,
which indicates that it MAY be the same relation or // which indicates that it MAY be the same relation or
procedure */ // procedure
switch (type) switch (type)
{ {

View File

@ -407,12 +407,11 @@ static const TOK tokens[] =
{0, 0, 0, false} {0, 0, 0, false}
}; };
/* This method is currently used in isql/isql.epp to check if a // This method is currently used in isql/isql.epp to check if a
user field is a reserved word, and hence needs to be quoted. // user field is a reserved word, and hence needs to be quoted.
Obviously a hash table would make this a little quicker. // Obviously a hash table would make this a little quicker.
//
MOD 29-June-2002 // MOD 29-June-2002
*/
extern "C" { extern "C" {

View File

@ -68,10 +68,9 @@ using namespace Jrd;
using namespace Dsql; using namespace Dsql;
using namespace Firebird; using namespace Firebird;
/* Firebird provides transparent conversion from string to date in // Firebird provides transparent conversion from string to date in
* contexts where it makes sense. This macro checks a descriptor to // contexts where it makes sense. This macro checks a descriptor to
* see if it is something that *could* represent a date value // see if it is something that *could* represent a date value
*/
static inline bool could_be_date(const dsc& d) static inline bool could_be_date(const dsc& d)
{ {
return DTYPE_IS_DATE(d.dsc_dtype) || (d.dsc_dtype <= dtype_any_text); return DTYPE_IS_DATE(d.dsc_dtype) || (d.dsc_dtype <= dtype_any_text);
@ -146,12 +145,12 @@ dsql_nod* MAKE_constant(dsql_str* constant, dsql_constant_type numeric_flag)
case CONSTANT_DOUBLE: case CONSTANT_DOUBLE:
DEV_BLKCHK(constant, dsql_type_str); DEV_BLKCHK(constant, dsql_type_str);
/* This is a numeric value which is transported to the engine as // This is a numeric value which is transported to the engine as
* a string. The engine will convert it. Use dtype_double so that // a string. The engine will convert it. Use dtype_double so that
the engine can distinguish it from an actual string. // the engine can distinguish it from an actual string.
Note: Due to the size of dsc_scale we are limited to numeric // Note: Due to the size of dsc_scale we are limited to numeric
constants of less than 256 bytes. // constants of less than 256 bytes.
*/
node->nod_desc.dsc_dtype = dtype_double; node->nod_desc.dsc_dtype = dtype_double;
// Scale has no use for double // Scale has no use for double
node->nod_desc.dsc_scale = static_cast<signed char>(constant->str_length); node->nod_desc.dsc_scale = static_cast<signed char>(constant->str_length);
@ -352,7 +351,7 @@ dsql_nod* MAKE_str_constant(dsql_str* constant, SSHORT character_set)
node->nod_desc.dsc_length = static_cast<USHORT>(constant->str_length); node->nod_desc.dsc_length = static_cast<USHORT>(constant->str_length);
node->nod_desc.dsc_address = (UCHAR*) constant->str_data; node->nod_desc.dsc_address = (UCHAR*) constant->str_data;
node->nod_desc.dsc_ttype() = character_set; node->nod_desc.dsc_ttype() = character_set;
// carry a pointer to the constant to resolve character set in pass1 // carry a pointer to the constant to resolve character set in pass1
node->nod_arg[0] = (dsql_nod*) constant; node->nod_arg[0] = (dsql_nod*) constant;
return node; return node;
@ -426,9 +425,9 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
return; return;
case nod_agg_count: case nod_agg_count:
/* count2 // count2
case nod_agg_distinct: // case nod_agg_distinct:
*/
desc->dsc_dtype = dtype_long; desc->dsc_dtype = dtype_long;
desc->dsc_length = sizeof(SLONG); desc->dsc_length = sizeof(SLONG);
desc->dsc_sub_type = 0; desc->dsc_sub_type = 0;
@ -671,15 +670,15 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
{ {
// <any date> - <any date> // <any date> - <any date>
/* Legal permutations are: // Legal permutations are:
<timestamp> - <timestamp> // <timestamp> - <timestamp>
<timestamp> - <date> // <timestamp> - <date>
<date> - <date> // <date> - <date>
<date> - <timestamp> // <date> - <timestamp>
<time> - <time> // <time> - <time>
<timestamp> - <string> // <timestamp> - <string>
<string> - <timestamp> // <string> - <timestamp>
<string> - <string> */ // <string> - <string>
if (DTYPE_IS_TEXT(desc1.dsc_dtype)) if (DTYPE_IS_TEXT(desc1.dsc_dtype))
dtype = dtype_timestamp; dtype = dtype_timestamp;
@ -801,10 +800,10 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
Arg::Gds(isc_dsql_nostring_addsub_dial3)); Arg::Gds(isc_dsql_nostring_addsub_dial3));
} }
/* Determine the TYPE of arithmetic to perform, store it // Determine the TYPE of arithmetic to perform, store it
in dtype. Note: this is different from the result of // in dtype. Note: this is different from the result of
the operation, as <timestamp>-<timestamp> uses // the operation, as <timestamp>-<timestamp> uses
<timestamp> arithmetic, but returns a <double> */ // <timestamp> arithmetic, but returns a <double>
if (DTYPE_IS_EXACT(dtype1) && DTYPE_IS_EXACT(dtype2)) if (DTYPE_IS_EXACT(dtype1) && DTYPE_IS_EXACT(dtype2))
{ {
dtype = dtype_int64; dtype = dtype_int64;
@ -841,12 +840,12 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
if (node->nod_type == nod_subtract2) if (node->nod_type == nod_subtract2)
{ {
// <any date> - <any date> // <any date> - <any date>
/* Legal permutations are: // Legal permutations are:
<timestamp> - <timestamp> // <timestamp> - <timestamp>
<timestamp> - <date> // <timestamp> - <date>
<date> - <date> // <date> - <date>
<date> - <timestamp> // <date> - <timestamp>
<time> - <time> */ // <time> - <time>
if (dtype1 == dtype2) if (dtype1 == dtype2)
dtype = dtype1; dtype = dtype1;
@ -882,8 +881,8 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
} }
else if (is_date_and_time(desc1, desc2)) else if (is_date_and_time(desc1, desc2))
{ {
/* <date> + <time> */ // <date> + <time>
/* <time> + <date> */ // <time> + <date>
desc->dsc_dtype = dtype_timestamp; desc->dsc_dtype = dtype_timestamp;
desc->dsc_length = type_lengths[dtype_timestamp]; desc->dsc_length = type_lengths[dtype_timestamp];
desc->dsc_scale = 0; desc->dsc_scale = 0;
@ -909,7 +908,7 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
} }
else else
{ {
/* <non-date> - <date> */ // <non-date> - <date>
fb_assert(node->nod_type == nod_subtract2); fb_assert(node->nod_type == nod_subtract2);
ERRD_post(Arg::Gds(isc_expression_eval_err) << ERRD_post(Arg::Gds(isc_expression_eval_err) <<
Arg::Gds(isc_dsql_invalid_type_minus_date)); Arg::Gds(isc_dsql_invalid_type_minus_date));
@ -934,9 +933,9 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
desc->dsc_sub_type = 0; desc->dsc_sub_type = 0;
desc->dsc_length = sizeof(SINT64); desc->dsc_length = sizeof(SINT64);
/* The result type is int64 because both operands are // The result type is int64 because both operands are
exact numeric: hence we don't need the NUMERIC_SCALE // exact numeric: hence we don't need the NUMERIC_SCALE
macro here. */ // macro here.
fb_assert(desc1.dsc_dtype == dtype_unknown || DTYPE_IS_EXACT(desc1.dsc_dtype)); fb_assert(desc1.dsc_dtype == dtype_unknown || DTYPE_IS_EXACT(desc1.dsc_dtype));
fb_assert(desc2.dsc_dtype == dtype_unknown || DTYPE_IS_EXACT(desc2.dsc_dtype)); fb_assert(desc2.dsc_dtype == dtype_unknown || DTYPE_IS_EXACT(desc2.dsc_dtype));
@ -1204,9 +1203,9 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
desc->dsc_dtype = static_cast<UCHAR>(userFunc->udf_dtype); desc->dsc_dtype = static_cast<UCHAR>(userFunc->udf_dtype);
desc->dsc_length = userFunc->udf_length; desc->dsc_length = userFunc->udf_length;
desc->dsc_scale = static_cast<SCHAR>(userFunc->udf_scale); desc->dsc_scale = static_cast<SCHAR>(userFunc->udf_scale);
/* CVC: Setting flags to zero obviously impeded DSQL to acknowledge // CVC: Setting flags to zero obviously impeded DSQL to acknowledge
the fact that any UDF can return NULL simply returning a NULL // the fact that any UDF can return NULL simply returning a NULL
pointer. */ // pointer.
desc->dsc_flags = DSC_nullable; desc->dsc_flags = DSC_nullable;
if (desc->dsc_dtype <= dtype_any_text) { if (desc->dsc_dtype <= dtype_any_text) {
@ -1272,7 +1271,7 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
} }
desc->dsc_sub_type = 0; desc->dsc_sub_type = 0;
desc->dsc_scale = 0; desc->dsc_scale = 0;
desc->dsc_flags = 0; /* Can first/skip accept NULL in the future? */ desc->dsc_flags = 0; // Can first/skip accept NULL in the future?
return; return;
case nod_field: case nod_field:
@ -1360,12 +1359,13 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
return; return;
case nod_parameter: case nod_parameter:
/* We don't actually know the datatype of a parameter - // We don't actually know the datatype of a parameter -
we have to guess it based on the context that the // we have to guess it based on the context that the
parameter appears in. (This is done is pass1.c::set_parameter_type()) // parameter appears in. (This is done is pass1.c::set_parameter_type())
However, a parameter can appear as part of an expression. // However, a parameter can appear as part of an expression.
As MAKE_desc is used for both determination of parameter // As MAKE_desc is used for both determination of parameter
types and for expression type checking, we just continue. */ // types and for expression type checking, we just continue.
if (node->nod_desc.dsc_dtype) if (node->nod_desc.dsc_dtype)
{ {
*desc = node->nod_desc; *desc = node->nod_desc;
@ -1373,18 +1373,18 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
return; return;
case nod_null: case nod_null:
/* This occurs when SQL statement specifies a literal NULL, eg: // This occurs when SQL statement specifies a literal NULL, eg:
* SELECT NULL FROM TABLE1; // SELECT NULL FROM TABLE1;
* As we don't have a <dtype_null, SQL_NULL> datatype pairing, // As we don't have a <dtype_null, SQL_NULL> datatype pairing,
* we don't know how to map this NULL to a host-language // we don't know how to map this NULL to a host-language
* datatype. Therefore we now describe it as a // datatype. Therefore we now describe it as a
* CHAR(1) CHARACTER SET NONE type. // CHAR(1) CHARACTER SET NONE type.
* No value will ever be sent back, as the value of the select // No value will ever be sent back, as the value of the select
* will be NULL - this is only for purposes of DESCRIBING // will be NULL - this is only for purposes of DESCRIBING
* the statement. Note that this mapping could be done in dsql.cpp // the statement. Note that this mapping could be done in dsql.cpp
* as part of the DESCRIBE statement - but I suspect other areas // as part of the DESCRIBE statement - but I suspect other areas
* of the code would break if this is declared dtype_unknown. // of the code would break if this is declared dtype_unknown.
*/
if (null_replacement) if (null_replacement)
{ {
MAKE_desc(statement, desc, null_replacement, NULL); MAKE_desc(statement, desc, null_replacement, NULL);
@ -1396,13 +1396,12 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
case nod_via: case nod_via:
MAKE_desc(statement, desc, node->nod_arg[e_via_value_1], null_replacement); MAKE_desc(statement, desc, node->nod_arg[e_via_value_1], null_replacement);
/** // Set the descriptor flag as nullable. The
Set the descriptor flag as nullable. The // select expression may or may not return
select expression may or may not return // this row based on the WHERE clause. Setting this
this row based on the WHERE clause. Setting this // flag warns the client to expect null values.
flag warns the client to expect null values. // (bug 10379)
(bug 10379)
**/
desc->dsc_flags |= DSC_nullable; desc->dsc_flags |= DSC_nullable;
return; return;
@ -1414,11 +1413,11 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
fb_assert(false); // unexpected dsql_nod type fb_assert(false); // unexpected dsql_nod type
case nod_dom_value: // computed value not used case nod_dom_value: // computed value not used
/* By the time we get here, any nod_dom_value node should have had // By the time we get here, any nod_dom_value node should have had
* its descriptor set to the type of the domain being created, or // its descriptor set to the type of the domain being created, or
* to the type of the existing domain to which a CHECK constraint // to the type of the existing domain to which a CHECK constraint
* is being added. // is being added.
*/
fb_assert(node->nod_desc.dsc_dtype != dtype_unknown); fb_assert(node->nod_desc.dsc_dtype != dtype_unknown);
if (desc != &node->nod_desc) if (desc != &node->nod_desc)
*desc = node->nod_desc; *desc = node->nod_desc;
@ -1528,10 +1527,10 @@ dsql_nod* MAKE_field(dsql_ctx* context, dsql_fld* field, dsql_nod* indices)
MAKE_desc_from_field(&node->nod_desc, field); MAKE_desc_from_field(&node->nod_desc, field);
node->nod_desc.dsc_dtype = static_cast<UCHAR>(field->fld_element_dtype); node->nod_desc.dsc_dtype = static_cast<UCHAR>(field->fld_element_dtype);
node->nod_desc.dsc_length = field->fld_element_length; node->nod_desc.dsc_length = field->fld_element_length;
/*
node->nod_desc.dsc_scale = field->fld_scale; // node->nod_desc.dsc_scale = field->fld_scale;
node->nod_desc.dsc_sub_type = field->fld_sub_type; // node->nod_desc.dsc_sub_type = field->fld_sub_type;
*/
} }
else else
{ {
@ -1693,7 +1692,7 @@ dsql_par* MAKE_parameter(dsql_msg* message, bool sqlda_flag, bool null_flag,
make_parameter_names(parameter, node); make_parameter_names(parameter, node);
} }
// If the parameter is used declared, set SQLDA index // If the parameter is used declared, set SQLDA index
if (sqlda_flag) if (sqlda_flag)
{ {
if (sqlda_index) { if (sqlda_index) {
@ -1706,7 +1705,7 @@ dsql_par* MAKE_parameter(dsql_msg* message, bool sqlda_flag, bool null_flag,
} }
} }
// If a null handing has been requested, set up a null flag // If a null handing has been requested, set up a null flag
if (null_flag) { if (null_flag) {
dsql_par* null = MAKE_parameter(message, false, false, 0, NULL); dsql_par* null = MAKE_parameter(message, false, false, 0, NULL);