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

The entire RSE handling in the parser is slightly rewritten. New join syntax is introduced.

Notes:
1) Some features are disabled (via isc_wish_list) yet due to their incomplete implementation.
2) The parser may become unstable or cause regressions. It will be fixed ASAP.
This commit is contained in:
dimitr 2004-10-13 18:37:53 +00:00
parent 46397f0744
commit a1bbad7ccf
9 changed files with 4592 additions and 4614 deletions

View File

@ -20,7 +20,7 @@
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
* $Id: ddl.cpp,v 1.116 2004-10-04 08:14:49 robocop Exp $
* $Id: ddl.cpp,v 1.117 2004-10-13 18:37:31 dimitr Exp $
* 2001.5.20 Claudio Valderrama: Stop null pointer that leads to a crash,
* caused by incomplete yacc syntax that allows ALTER DOMAIN dom SET;
*
@ -2173,11 +2173,7 @@ static dsql_nod* define_insert_action( dsql_req* request)
if ((ddl_node->nod_type != nod_def_view && ddl_node->nod_type != nod_redef_view) ||
!(select_node = ddl_node->nod_arg[e_view_select]) ||
/*
Handle VIEWS with UNION : nod_select now points to nod_list
which in turn points to nod_select_expr
*/
!(select_expr = select_node->nod_arg[0]->nod_arg[0]) ||
!(select_expr = select_node->nod_arg[e_sel_query_spec]->nod_arg[0]) ||
!(from_list = select_expr->nod_arg[e_sel_from]) ||
from_list->nod_count != 1)
return NULL;
@ -3307,17 +3303,13 @@ static void define_update_action(
// check whether this is an updatable view definition
dsql_nod* select_node = 0;
dsql_nod* select_expr = 0;
dsql_nod* from_list = 0;
dsql_nod* select_node = NULL;
dsql_nod* select_expr = NULL;
dsql_nod* from_list = NULL;
if ((ddl_node->nod_type != nod_def_view && ddl_node->nod_type != nod_redef_view) ||
!(select_node = ddl_node->nod_arg[e_view_select]) ||
/*
Handle VIEWS with UNION : nod_select now points to nod_list
which in turn points to nod_select_expr
*/
!(select_expr = select_node->nod_arg[0]->nod_arg[0]) ||
!(from_list = select_expr->nod_arg[e_sel_from]) ||
!(select_expr = select_node->nod_arg[e_sel_query_spec]->nod_arg[0]) ||
!(from_list = select_expr->nod_arg[e_qry_from]) ||
from_list->nod_count != 1)
{
return;
@ -3336,7 +3328,7 @@ static void define_update_action(
are not computed */
dsql_nod* values_node = ddl_node->nod_arg[e_view_fields];
dsql_nod* fields_node = select_expr->nod_arg[e_sel_list];
dsql_nod* fields_node = select_expr->nod_arg[e_qry_list];
if (!fields_node)
{
const dsql_str* rel_name =
@ -3418,12 +3410,12 @@ static void define_update_action(
}
if (and_arg <= 1)
and_node->nod_arg[and_arg] = select_expr->nod_arg[e_sel_where];
and_node->nod_arg[and_arg] = select_expr->nod_arg[e_qry_where];
else {
dsql_nod* old_and = and_node;
and_node = MAKE_node(nod_and, (int) 2);
and_node->nod_arg[0] = old_and;
and_node->nod_arg[1] = select_expr->nod_arg[e_sel_where];
and_node->nod_arg[1] = select_expr->nod_arg[e_qry_where];
}
*base_and_node = and_node;
}
@ -3566,11 +3558,8 @@ static void define_view( dsql_req* request, NOD_TYPE op)
if (request->req_context_number)
reset_context_stack(request);
request->req_context_number++;
dsql_nod* select = node->nod_arg[e_view_select];
dsql_nod* select_expr = select->nod_arg[0];
dsql_nod* rse =
PASS1_rse(request, select_expr, select->nod_arg[e_select_order],
select->nod_arg[e_select_rows], NULL);
dsql_nod* select_expr = node->nod_arg[e_view_select];
dsql_nod* rse = PASS1_rse(request, select_expr, NULL);
// store the blr and source string for the view definition
@ -3604,13 +3593,19 @@ static void define_view( dsql_req* request, NOD_TYPE op)
{
const dsql_ctx* context = temp.object();
const dsql_rel* relation = context->ctx_relation;
if (relation)
const dsql_prc* procedure = context->ctx_procedure;
if (relation || procedure)
{
request->append_cstring(isc_dyn_view_relation, relation->rel_name);
if (procedure)
{
// Disallow procedure-based views
ERRD_post(isc_wish_list, 0);
}
const char* name = relation ? relation->rel_name : procedure->prc_name;
request->append_cstring(isc_dyn_view_relation, name);
request->append_number(isc_dyn_view_context, context->ctx_context);
request->append_cstring(isc_dyn_view_context_name,
context->ctx_alias ? context->ctx_alias : relation->
rel_name);
context->ctx_alias ? context->ctx_alias : name);
request->append_uchar(isc_dyn_end);
}
}
@ -3734,6 +3729,9 @@ static void define_view( dsql_req* request, NOD_TYPE op)
0);
}
// change this node to nod_list
select_expr = select_expr->nod_arg[e_sel_query_spec];
if (select_expr->nod_count != 1)
{
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) -607,
@ -3742,11 +3740,11 @@ static void define_view( dsql_req* request, NOD_TYPE op)
// Only one table allowed for VIEW WITH CHECK OPTION
0);
}
/*
Handle VIEWS with UNION : nod_select now points to nod_list
which in turn points to nod_select_expr
*/
else if (select_expr->nod_arg[0]->nod_arg[e_sel_from]->nod_count != 1)
// change this node to nod_query_spec
select_expr = select_expr->nod_arg[0];
if (select_expr->nod_arg[e_qry_from]->nod_count != 1)
{
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) -607,
isc_arg_gds, isc_dsql_command_err,
@ -3755,12 +3753,7 @@ static void define_view( dsql_req* request, NOD_TYPE op)
0);
}
/*
Handle VIEWS with UNION : nod_select now points to nod_list
which in turn points to nod_select_expr
*/
select_expr = select_expr->nod_arg[0];
if (!(select_expr->nod_arg[e_sel_where]))
if (!(select_expr->nod_arg[e_qry_where]))
{
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) -607,
isc_arg_gds, isc_dsql_command_err,
@ -3769,9 +3762,9 @@ static void define_view( dsql_req* request, NOD_TYPE op)
0);
}
if (select_expr->nod_arg[e_sel_distinct] ||
select_expr->nod_arg[e_sel_group] ||
select_expr->nod_arg[e_sel_having])
if (select_expr->nod_arg[e_qry_distinct] ||
select_expr->nod_arg[e_qry_group] ||
select_expr->nod_arg[e_qry_having])
{
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) -607,
isc_arg_gds, isc_dsql_command_err,
@ -3791,9 +3784,9 @@ static void define_view( dsql_req* request, NOD_TYPE op)
criteria for the view, suitably fixed up so that the fields in
the view are referenced */
check->nod_arg[e_cnstr_condition] = select_expr->nod_arg[e_sel_where];
check->nod_arg[e_cnstr_condition] = select_expr->nod_arg[e_qry_where];
// Define the triggers
// Define the triggers
create_view_triggers(request, check, rse->nod_arg[e_rse_items]);
}
@ -3820,12 +3813,8 @@ static void define_view_trigger( dsql_req* request, dsql_nod* node, dsql_nod* rs
dsql_nod* ddl_node = request->req_ddl_node;
dsql_nod* select = ddl_node->nod_arg[e_view_select];
/*
Handle VIEWS with UNION : nod_select now points to nod_list
which in turn points to nod_select_expr
*/
dsql_nod* select_expr = select->nod_arg[0]->nod_arg[0];
dsql_nod* select_expr = ddl_node->nod_arg[e_view_select];
select_expr = select_expr->nod_arg[e_sel_query_spec]->nod_arg[0];
dsql_nod* view_fields = ddl_node->nod_arg[e_view_fields];
/* make the "define trigger" node the current request ddl node so
@ -3938,7 +3927,7 @@ static void define_view_trigger( dsql_req* request, dsql_nod* node, dsql_nod* rs
dsql_nod* condition = MAKE_node(nod_not, 1);
condition->nod_arg[0] =
replace_field_names(select_expr->nod_arg[e_sel_where], items,
replace_field_names(select_expr->nod_arg[e_qry_where], items,
view_fields, false);
request->append_uchar(blr_begin);
request->append_uchar(blr_if);
@ -3950,7 +3939,7 @@ static void define_view_trigger( dsql_req* request, dsql_nod* node, dsql_nod* rs
if (trig_type == PRE_STORE_TRIGGER) {
dsql_nod* condition = MAKE_node(nod_not, 1);
condition->nod_arg[0] =
replace_field_names(select_expr->nod_arg[e_sel_where], items,
replace_field_names(select_expr->nod_arg[e_qry_where], items,
view_fields, true);
request->append_uchar(blr_if);
GEN_expr(request, PASS1_node(request, condition->nod_arg[0], false));

View File

@ -258,3 +258,4 @@
#define BLOCK 514
#define IIF 515
#define SCALAR_ARRAY 516
#define CROSS 517

View File

@ -1801,8 +1801,11 @@ static void gen_join_rse( dsql_req* request, const dsql_nod* rse)
stuff(request, blr_full);
}
stuff(request, blr_boolean);
GEN_expr(request, rse->nod_arg[e_join_boolean]);
if (rse->nod_arg[e_join_boolean])
{
stuff(request, blr_boolean);
GEN_expr(request, rse->nod_arg[e_join_boolean]);
}
stuff(request, blr_end);
}
@ -2091,7 +2094,7 @@ void GEN_return( dsql_req* request, const dsql_nod* parameters, bool eos_flag)
**/
static void gen_rse( dsql_req* request, const dsql_nod* rse)
{
if (rse->nod_arg[e_rse_singleton]
if ((rse->nod_flags & NOD_SELECT_EXPR_SINGLETON)
&& !(request->req_dbb->dbb_flags & DBB_v3))
{
stuff(request, blr_singular);
@ -2115,7 +2118,8 @@ static void gen_rse( dsql_req* request, const dsql_nod* rse)
{
dsql_nod* node = *ptr;
if (node->nod_type == nod_relation ||
node->nod_type == nod_aggregate || node->nod_type == nod_join)
node->nod_type == nod_aggregate ||
node->nod_type == nod_join)
{
GEN_expr(request, node);
}

View File

@ -28,7 +28,7 @@
* Contributor(s):
*
*
* $Id: keywords.cpp,v 1.33 2004-10-03 04:48:37 robocop Exp $
* $Id: keywords.cpp,v 1.34 2004-10-13 18:37:32 dimitr Exp $
*
*/
@ -100,6 +100,7 @@ static const TOK tokens[] = {
{CONTAINING, "CONTAINING", 1},
{COUNT, "COUNT", 1},
{CREATE, "CREATE", 1},
{CROSS, "CROSS", 2},
{CSTRING, "CSTRING", 1},
{CURRENT, "CURRENT", 1},
{CURRENT_CONNECTION, "CURRENT_CONNECTION", 2},

View File

@ -211,6 +211,7 @@ enum nod_t
nod_join_left,
nod_join_right,
nod_join_full,
nod_join_cross,
// sql transaction support
nod_access,
nod_wait,
@ -331,7 +332,8 @@ enum nod_t
nod_fetch_seek,
nod_exec_block, // EXECUTE BLOCK support
nod_param_val, // default value for SP parameters support
nod_rows // ROWS support
nod_rows, // ROWS support
nod_query_spec
};
typedef nod_t NOD_TYPE;
@ -388,7 +390,10 @@ enum nod_flags_vals {
REF_ACTION_NONE = 8,
// Node flag indicates that this node has a different type or result
// depending on the SQL dialect.
NOD_COMP_DIALECT = 16
NOD_COMP_DIALECT = 16,
NOD_SELECT_EXPR_SINGLETON = 1,
NOD_SELECT_EXPR_VALUE = 2
};
// Parameters to MAKE_constant
@ -415,8 +420,6 @@ enum dsql_constant_type {
*/
enum node_args {
e_select_expr = 0, // nod_select
e_select_order,
e_select_rows,
e_select_update,
e_select_lock,
e_select_count,
@ -495,7 +498,6 @@ enum node_args {
e_rse_reduced,
e_rse_items,
e_rse_first,
e_rse_singleton,
e_rse_plan,
e_rse_skip,
e_rse_lock,
@ -552,19 +554,21 @@ enum node_args {
e_msg_text,
e_msg_count,
e_sel_limit = 0, // nod_select_expr
e_sel_distinct,
e_sel_list,
e_sel_from,
e_sel_where,
e_sel_group,
e_sel_having,
e_sel_plan,
e_sel_query_spec = 0, // nod_select_expr
e_sel_order,
e_sel_rows,
e_sel_singleton,
e_sel_count,
e_qry_limit = 0, // nod_query_spec
e_qry_distinct,
e_qry_list,
e_qry_from,
e_qry_where,
e_qry_group,
e_qry_having,
e_qry_plan,
e_qry_count,
e_ins_relation = 0, // nod_insert
e_ins_fields,
e_ins_values,

File diff suppressed because it is too large Load Diff

View File

@ -506,6 +506,7 @@ static LexerState lex;
%token BLOCK
%token IIF
%token SCALAR_ARRAY
%token CROSS
/* precedence declarations for expression evaluation */
@ -1575,7 +1576,7 @@ var_init_opt : '=' default_value
{ $$ = $1; }
;
cursor_declaration_item : symbol_cursor_name CURSOR FOR '(' ordered_select_expr ')'
cursor_declaration_item : symbol_cursor_name CURSOR FOR '(' select ')'
{ $$ = make_node (nod_cursor, (int) e_cur_count,
$1, $5, NULL, NULL); }
;
@ -1847,80 +1848,33 @@ block_parameter : proc_parameter '=' parameter
/* CREATE VIEW */
view_clause : symbol_view_name column_parens_opt AS begin_string union_view
view_clause : symbol_view_name column_parens_opt AS begin_string select_expr
check_opt end_string
{ $$ = make_node (nod_def_view, (int) e_view_count,
$1, $2, $5, $6, $7); }
;
rview_clause : symbol_view_name column_parens_opt AS begin_string union_view
rview_clause : symbol_view_name column_parens_opt AS begin_string select_expr
check_opt end_string
{ $$ = make_node (nod_redef_view, (int) e_view_count,
$1, $2, $5, $6, $7); }
;
/*
replace_view_clause : symbol_view_name column_parens_opt AS begin_string union_view
replace_view_clause : symbol_view_name column_parens_opt AS begin_string select_expr
check_opt end_string
{ $$ = make_node (nod_replace_view, (int) e_view_count,
$1, $2, $5, $6, $7); }
;
alter_view_clause : symbol_view_name column_parens_opt AS begin_string union_view
alter_view_clause : symbol_view_name column_parens_opt AS begin_string select_expr
check_opt end_string
{ $$ = make_node (nod_mod_view, (int) e_view_count,
$1, $2, $5, $6, $7); }
;
*/
union_view : union_view_expr
{ $$ = make_node (nod_select, (int) e_select_count, $1, NULL, NULL, NULL, NULL); }
;
union_view_expr : select_view_expr
{ $$ = make_node (nod_list, (int) 1, $1); }
| union_view_expr UNION distinct_noise select_view_expr
{ $$ = make_node (nod_list, 2, $1, $4); }
| union_view_expr UNION ALL select_view_expr
{ $$ = make_flag_node (nod_list, NOD_UNION_ALL, 2, $1, $4); }
;
select_view_expr: SELECT
distinct_clause
select_list
from_view_clause
where_clause
group_clause
having_clause
{ $$ = make_node (nod_select_expr, (int) e_sel_count,
NULL, $2, $3, $4, $5, $6, $7, NULL, NULL, NULL, NULL); }
;
from_view_clause : FROM from_view_list
{ $$ = make_list ($2); }
;
from_view_list : view_table
| from_view_list ',' view_table
{ $$ = make_node (nod_list, 2, $1, $3); }
;
view_table : joined_view_table
| table_name
/* AB: Temporary disable derived tables in VIEWS
a derived table could hold a selectable SP for example, which by default isn't
allowed in VIEWs.
| derived_table
*/
;
joined_view_table : view_table join_type JOIN view_table ON search_condition
{ $$ = make_node (nod_join, (int) e_join_count,
$1, $2, $4, $6); }
| '(' joined_view_table ')'
{ $$ = $2; }
;
/* these rules will capture the input string for storage in metadata */
@ -2170,6 +2124,8 @@ keyword_or_column : valid_symbol_name
| CLOSE
| FETCH
| ROWS
| USING
| CROSS
;
col_opt : ALTER
@ -2916,72 +2872,14 @@ set_statistics : SET STATISTICS INDEX symbol_index_name
/* SELECT statement */
select : union_expr order_clause rows_clause for_update_clause lock_clause
{ $$ = make_node (nod_select, (int) e_select_count, $1, $2, $3, $4, $5); }
;
union_expr : select_expr
{ $$ = make_node (nod_list, 1, $1); }
| union_expr UNION distinct_noise select_expr
{ $$ = make_node (nod_list, 2, $1, $4); }
| union_expr UNION ALL select_expr
{ $$ = make_flag_node (nod_list, NOD_UNION_ALL, 2, $1, $4); }
;
order_clause : ORDER BY order_list
{ $$ = make_list ($3); }
|
{ $$ = 0; }
;
order_list : order_item
| order_list ',' order_item
{ $$ = make_node (nod_list, 2, $1, $3); }
;
order_item : value order_direction nulls_clause
{ $$ = make_node (nod_order, (int) e_order_count, $1, $2, $3); }
;
order_direction : ASC
{ $$ = 0; }
| DESC
{ $$ = make_node (nod_flag, 0, NULL); }
|
{ $$ = 0; }
;
nulls_placement : FIRST
{ $$ = MAKE_constant((dsql_str*) NOD_NULLS_FIRST, CONSTANT_SLONG); }
| LAST
{ $$ = MAKE_constant((dsql_str*) NOD_NULLS_LAST, CONSTANT_SLONG); }
;
nulls_clause : NULLS begin_first nulls_placement end_first
{ $$ = $3; }
|
{ $$ = 0; }
;
rows_clause : ROWS value
/* equivalent to FIRST value */
{ $$ = make_node (nod_rows, (int) e_rows_count, NULL, $2); }
| ROWS value TO value
/* equivalent to FIRST (upper_value - lower_value + 1) SKIP (lower_value - 1) */
{ $$ = make_node (nod_rows, (int) e_rows_count,
make_node (nod_subtract, 2, $2,
MAKE_constant ((dsql_str*) 1, CONSTANT_SLONG)),
make_node (nod_add, 2,
make_node (nod_subtract, 2, $4, $2),
MAKE_constant ((dsql_str*) 1, CONSTANT_SLONG))); }
|
{ $$ = NULL; }
select : select_expr for_update_clause lock_clause
{ $$ = make_node (nod_select, (int) e_select_count, $1, $2, $3); }
;
for_update_clause : FOR UPDATE for_update_list
{ $$ = make_node (nod_for_update, 1, $3); }
|
{ $$ = 0; }
{ $$ = NULL; }
;
for_update_list : OF column_list
@ -2993,25 +2891,38 @@ for_update_list : OF column_list
lock_clause : WITH LOCK
{ $$ = make_node (nod_flag, 0, NULL); }
|
{ $$ = 0; }
{ $$ = NULL; }
;
/* SELECT expression */
select_expr : SELECT limit_clause
distinct_clause
select_list
from_clause
where_clause
group_clause
having_clause
plan_clause
{ $$ = make_node (nod_select_expr, (int) e_sel_count,
$2, $3, $4, $5, $6, $7, $8, $9, NULL, NULL, NULL); }
;
select_expr : select_expr_body order_clause rows_clause
{ $$ = make_node (nod_select_expr, (int) e_sel_count, $1, $2, $3); }
;
ordered_select_expr : SELECT limit_clause
column_select : select_expr_body order_clause rows_clause
{ $$ = make_flag_node (nod_select_expr, NOD_SELECT_EXPR_VALUE,
(int) e_sel_count, $1, $2, $3); }
;
column_singleton : select_expr_body order_clause rows_clause
{ $$ = make_flag_node (nod_select_expr, NOD_SELECT_EXPR_VALUE | NOD_SELECT_EXPR_SINGLETON,
(int) e_sel_count, $1, $2, $3); }
;
select_expr_body : query_term
{ $$ = make_node (nod_list, 1, $1); }
| select_expr_body UNION distinct_noise query_term
{ $$ = make_node (nod_list, 2, $1, $4); }
| select_expr_body UNION ALL query_term
{ $$ = make_flag_node (nod_list, NOD_UNION_ALL, 2, $1, $4); }
;
query_term : query_spec
;
query_spec : SELECT limit_clause
distinct_clause
select_list
from_clause
@ -3019,10 +2930,8 @@ ordered_select_expr : SELECT limit_clause
group_clause
having_clause
plan_clause
order_clause
rows_clause
{ $$ = make_node (nod_select_expr, (int) e_sel_count,
$2, $3, $4, $5, $6, $7, $8, $9, $10, $11, NULL); }
{ $$ = make_node (nod_query_spec, (int) e_qry_count,
$2, $3, $4, $5, $6, $7, $8, $9); }
;
begin_limit :
@ -3105,13 +3014,18 @@ from_list : table_reference
;
table_reference : joined_table
| table_proc
| table_primary
;
table_primary : table_proc
| derived_table
| '(' joined_table ')'
{ $$ = $2; }
;
/* AB: derived table support */
derived_table :
'(' select ')' as_noise correlation_name derived_column_list
'(' select_expr ')' as_noise correlation_name derived_column_list
{ $$ = make_node(nod_derived_table, (int) e_derived_table_count, $2, $5, $6); }
;
@ -3131,12 +3045,37 @@ alias_list : symbol_item_alias_name
{ $$ = make_node (nod_list, 2, $1, $3); }
;
joined_table : table_reference join_type JOIN table_reference ON search_condition
{ $$ = make_node (nod_join, (int) e_join_count, $1, $2, $4, $6); }
| '(' joined_table ')'
joined_table : cross_join
| natural_join
| qualified_join
;
cross_join : table_reference CROSS JOIN table_primary
{ $$ = make_node (nod_join, (int) e_join_count, $1,
make_node (nod_join_inner, (int) 0, NULL), $4, NULL); }
;
natural_join : table_reference NATURAL join_type JOIN table_primary
{ $$ = make_node (nod_join, (int) e_join_count, $1, $3, $5,
make_node (nod_flag, 0, NULL)); }
;
qualified_join : table_reference join_type JOIN table_reference join_specification
{ $$ = make_node (nod_join, (int) e_join_count, $1, $2, $4, $5); }
;
join_specification : join_condition
| named_columns_join
;
join_condition : ON search_condition
{ $$ = $2; }
;
named_columns_join : USING '(' column_list ')'
{ $$ = make_list ($3); }
;
table_proc : symbol_procedure_name table_proc_inputs as_noise symbol_table_alias_name
{ $$ = make_node (nod_rel_proc_name,
(int) e_rpn_count, $1, $4, $2); }
@ -3164,29 +3103,27 @@ simple_table_name: symbol_table_name
join_type : INNER
{ $$ = make_node (nod_join_inner, (int) 0, NULL); }
| LEFT
| LEFT outer_noise
{ $$ = make_node (nod_join_left, (int) 0, NULL); }
| LEFT OUTER
{ $$ = make_node (nod_join_left, (int) 0, NULL); }
| RIGHT
| RIGHT outer_noise
{ $$ = make_node (nod_join_right, (int) 0, NULL); }
| RIGHT OUTER
{ $$ = make_node (nod_join_right, (int) 0, NULL); }
| FULL
{ $$ = make_node (nod_join_full, (int) 0, NULL); }
| FULL OUTER
| FULL outer_noise
{ $$ = make_node (nod_join_full, (int) 0, NULL); }
|
{ $$ = make_node (nod_join_inner, (int) 0, NULL); }
;
outer_noise : OUTER
|
;
/* other clauses in the select expression */
group_clause : GROUP BY group_by_list
{ $$ = make_list ($3); }
|
{ $$ = 0; }
{ $$ = NULL; }
;
group_by_list : group_by_item
@ -3202,13 +3139,13 @@ group_by_item : value
having_clause : HAVING search_condition
{ $$ = $2; }
|
{ $$ = 0; }
{ $$ = NULL; }
;
where_clause : WHERE search_condition
{ $$ = $2; }
|
{ $$ = 0; }
{ $$ = NULL; }
;
@ -3217,7 +3154,7 @@ where_clause : WHERE search_condition
plan_clause : PLAN plan_expression
{ $$ = $2; }
|
{ $$ = 0; }
{ $$ = NULL; }
;
plan_expression : plan_type '(' plan_item_list ')'
@ -3274,13 +3211,67 @@ extra_indices_opt : INDEX '(' index_list ')'
{ $$ = 0; }
;
/* ORDER BY clause */
order_clause : ORDER BY order_list
{ $$ = make_list ($3); }
|
{ $$ = 0; }
;
order_list : order_item
| order_list ',' order_item
{ $$ = make_node (nod_list, 2, $1, $3); }
;
order_item : value order_direction nulls_clause
{ $$ = make_node (nod_order, (int) e_order_count, $1, $2, $3); }
;
order_direction : ASC
{ $$ = 0; }
| DESC
{ $$ = make_node (nod_flag, 0, NULL); }
|
{ $$ = 0; }
;
nulls_placement : FIRST
{ $$ = MAKE_constant((dsql_str*) NOD_NULLS_FIRST, CONSTANT_SLONG); }
| LAST
{ $$ = MAKE_constant((dsql_str*) NOD_NULLS_LAST, CONSTANT_SLONG); }
;
nulls_clause : NULLS begin_first nulls_placement end_first
{ $$ = $3; }
|
{ $$ = 0; }
;
/* ROWS clause */
rows_clause : ROWS value
/* equivalent to FIRST value */
{ $$ = make_node (nod_rows, (int) e_rows_count, NULL, $2); }
| ROWS value TO value
/* equivalent to FIRST (upper_value - lower_value + 1) SKIP (lower_value - 1) */
{ $$ = make_node (nod_rows, (int) e_rows_count,
make_node (nod_subtract, 2, $2,
MAKE_constant ((dsql_str*) 1, CONSTANT_SLONG)),
make_node (nod_add, 2,
make_node (nod_subtract, 2, $4, $2),
MAKE_constant ((dsql_str*) 1, CONSTANT_SLONG))); }
|
{ $$ = NULL; }
;
/* INSERT statement */
/* IBO hack: replace column_parens_opt by ins_column_parens_opt. */
insert : INSERT INTO simple_table_name ins_column_parens_opt VALUES '(' value_list ')'
{ $$ = make_node (nod_insert, (int) e_ins_count,
$3, make_list ($4), make_list ($7), NULL); }
| INSERT INTO simple_table_name ins_column_parens_opt ordered_select_expr
| INSERT INTO simple_table_name ins_column_parens_opt select_expr
{ $$ = make_node (nod_insert, (int) e_ins_count, $3, $4, NULL, $5); }
;
@ -3461,7 +3452,7 @@ predicate : comparison_predicate
| exists_predicate
| containing_predicate
| starting_predicate
| unique_predicate;
| singular_predicate;
/* comparisons */
@ -3521,9 +3512,9 @@ quantified_predicate : value '=' ALL '(' column_select ')'
{ $$ = make_node (nod_neq_any, 2, $1, $5); }
;
some : SOME
| ANY
;
some : SOME
| ANY
;
/* other predicates */
@ -3533,7 +3524,7 @@ between_predicate : value BETWEEN value AND value
| value NOT BETWEEN value AND value
{ $$ = make_node (nod_not, 1, make_node (nod_between,
3, $1, $4, $6)); }
;
;
like_predicate : value LIKE value
{ $$ = make_node (nod_like, 2, $1, $3); }
@ -3544,19 +3535,19 @@ like_predicate : value LIKE value
| value NOT LIKE value ESCAPE value
{ $$ = make_node (nod_not, 1, make_node (nod_like,
3, $1, $4, $6)); }
;
;
in_predicate : value KW_IN in_predicate_value
{ $$ = make_node (nod_eql_any, 2, $1, $3); }
| value NOT KW_IN in_predicate_value
{ $$ = make_node (nod_not, 1, make_node (nod_eql_any, 2, $1, $4)); }
;
;
containing_predicate : value CONTAINING value
{ $$ = make_node (nod_containing, 2, $1, $3); }
| value NOT CONTAINING value
{ $$ = make_node (nod_not, 1, make_node (nod_containing, 2, $1, $4)); }
;
;
starting_predicate : value STARTING value
{ $$ = make_node (nod_starting, 2, $1, $3); }
@ -3566,15 +3557,15 @@ starting_predicate : value STARTING value
{ $$ = make_node (nod_starting, 2, $1, $4); }
| value NOT STARTING WITH value
{ $$ = make_node (nod_not, 1, make_node (nod_starting, 2, $1, $5)); }
;
;
exists_predicate : EXISTS '(' ordered_select_expr ')'
exists_predicate : EXISTS '(' select_expr ')'
{ $$ = make_node (nod_exists, 1, $3); }
;
;
unique_predicate : SINGULAR '(' ordered_select_expr ')'
singular_predicate : SINGULAR '(' select_expr ')'
{ $$ = make_node (nod_singular, 1, $3); }
;
;
null_predicate : value IS KW_NULL
{ $$ = make_node (nod_missing, 1, $1); }
@ -3619,43 +3610,14 @@ special_trigger_action_predicate : KW_INSERTING
/* set values */
in_predicate_value : table_subquery
| '(' value_list ')'
{ $$ = make_list ($2); }
;
| '(' value_list ')'
{ $$ = make_list ($2); }
;
table_subquery : '(' column_select ')'
{ $$ = $2; }
;
column_select : SELECT limit_clause
distinct_clause
value
from_clause
where_clause
group_clause
having_clause
plan_clause
order_clause
rows_clause
{ $$ = make_node (nod_select_expr, (int) e_sel_count,
$2, $3, make_list ($4), $5, $6, $7, $8, $9, $10, $11, NULL); }
;
column_singleton : SELECT limit_clause
distinct_clause
value
from_clause
where_clause
group_clause
having_clause
plan_clause
order_clause
rows_clause
{ $$ = make_node (nod_select_expr, (int) e_sel_count,
$2, $3, make_list ($4), $5, $6, $7, $8, $9, $10, $11,
MAKE_constant ((dsql_str*) 1, CONSTANT_SLONG)); }
;
/* value types */
@ -4188,7 +4150,6 @@ non_reserved_word :
| NULLIF
| NULLS
| STATEMENT
| USING
| INSERTING
| UPDATING
| DELETING

View File

@ -220,7 +220,7 @@ static dsql_nod* pass1_label(dsql_req*, dsql_nod*);
static dsql_nod* pass1_make_derived_field(dsql_req*, tsql*, dsql_nod*);
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_rse(dsql_req*, dsql_nod*, dsql_nod*, dsql_nod*, dsql_nod*);
static dsql_nod* pass1_rse(dsql_req*, dsql_nod*, dsql_nod*, dsql_nod*, dsql_nod*, USHORT);
static dsql_nod* pass1_searched_case(dsql_req*, dsql_nod*, bool);
static dsql_nod* pass1_sel_list(dsql_req*, dsql_nod*);
static dsql_nod* pass1_simple_case(dsql_req*, dsql_nod*, bool);
@ -228,7 +228,7 @@ static dsql_nod* pass1_sort(dsql_req*, dsql_nod*, dsql_nod*);
static dsql_nod* pass1_udf(dsql_req*, dsql_nod*, bool);
static void pass1_udf_args(dsql_req*, dsql_nod*, dsql_udf*, USHORT&, DsqlNodStack&,
bool);
static dsql_nod* pass1_union(dsql_req*, dsql_nod*, dsql_nod*, dsql_nod*);
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*);
@ -635,8 +635,7 @@ dsql_nod* PASS1_node(dsql_req* request, dsql_nod* input, bool proc_flag)
const DsqlContextStack::iterator base(*request->req_context);
node = MAKE_node(nod_via, e_via_count);
dsql_nod* rse = PASS1_rse(request, input, input->nod_arg[e_sel_order],
input->nod_arg[e_sel_rows], NULL);
dsql_nod* rse = PASS1_rse(request, input, NULL);
node->nod_arg[e_via_rse] = rse;
node->nod_arg[e_via_value_1] = rse->nod_arg[e_rse_items]->nod_arg[0];
node->nod_arg[e_via_value_2] = MAKE_node(nod_null, (int) 0);
@ -651,9 +650,7 @@ dsql_nod* PASS1_node(dsql_req* request, dsql_nod* input, bool proc_flag)
const DsqlContextStack::iterator base(*request->req_context);
node = MAKE_node(input->nod_type, 1);
input = input->nod_arg[0];
node->nod_arg[0] =
PASS1_rse(request, input, input->nod_arg[e_sel_order],
input->nod_arg[e_sel_rows], NULL);
node->nod_arg[0] = PASS1_rse(request, input, NULL);
// Finish off by cleaning up contexts
@ -780,14 +777,13 @@ dsql_nod* PASS1_node(dsql_req* request, dsql_nod* input, bool proc_flag)
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 206,
isc_arg_gds, isc_dsql_subselect_err, 0);
if (sub2->nod_arg[e_sel_singleton]) {
if (sub2->nod_flags & NOD_SELECT_EXPR_SINGLETON) {
const DsqlContextStack::iterator base(*request->req_context);
node = MAKE_node(input->nod_type, 2);
node->nod_arg[0] = PASS1_node(request, input->nod_arg[0], false);
dsql_nod* temp = MAKE_node(nod_via, e_via_count);
node->nod_arg[1] = temp;
dsql_nod* rse = PASS1_rse(request, sub2, sub2->nod_arg[e_sel_order],
sub2->nod_arg[e_sel_rows], NULL);
dsql_nod* rse = PASS1_rse(request, sub2, NULL);
temp->nod_arg[e_via_rse] = rse;
temp->nod_arg[e_via_value_1] =
rse->nod_arg[e_rse_items]->nod_arg[0];
@ -1004,19 +1000,19 @@ dsql_nod* PASS1_node(dsql_req* request, dsql_nod* input, bool proc_flag)
@param request
@param input
@param order
@param update_lock
**/
dsql_nod* PASS1_rse(dsql_req* request, dsql_nod* input, dsql_nod* order,
dsql_nod* rows, dsql_nod* update_lock)
dsql_nod* PASS1_rse(dsql_req* request, dsql_nod* input, dsql_nod* update_lock)
{
DEV_BLKCHK(request, dsql_type_req);
DEV_BLKCHK(input, dsql_type_nod);
DEV_BLKCHK(order, dsql_type_nod);
DEV_BLKCHK(update_lock, dsql_type_nod);
fb_assert(input->nod_type == nod_select_expr);
request->req_scope_level++;
dsql_nod* node = pass1_rse(request, input, order, rows, update_lock);
dsql_nod* node = pass1_rse(request, input, NULL, NULL, update_lock, 0);
request->req_scope_level--;
return node;
@ -1461,8 +1457,8 @@ dsql_nod* PASS1_statement(dsql_req* request, dsql_nod* input, bool proc_flag)
case nod_select:
{
node = PASS1_rse(request, input->nod_arg[e_select_expr], input->nod_arg[e_select_order],
input->nod_arg[e_select_rows], input->nod_arg[e_select_lock]);
node = PASS1_rse(request, input->nod_arg[e_select_expr],
input->nod_arg[e_select_lock]);
if (input->nod_arg[e_select_update]) {
request->req_type = REQ_SELECT_UPD;
@ -1572,10 +1568,10 @@ dsql_nod* PASS1_statement(dsql_req* request, dsql_nod* input, bool proc_flag)
DsqlContextStack* const base_context = request->req_context;
DsqlContextStack temp;
request->req_context = &temp;
dsql_nod* select = input->nod_arg[e_cur_rse];
input->nod_arg[e_cur_rse] =
PASS1_rse(request, input->nod_arg[e_cur_rse],
input->nod_arg[e_cur_rse]->nod_arg[e_sel_order],
input->nod_arg[e_cur_rse]->nod_arg[e_sel_rows], NULL);
PASS1_rse(request, select->nod_arg[e_select_expr],
select->nod_arg[e_select_lock]);
request->req_context->clear();
request->req_context = base_context;
// assign number and store in the request stack
@ -2902,7 +2898,7 @@ static dsql_nod* pass1_any( dsql_req* request, dsql_nod* input, NOD_TYPE ntype)
DEV_BLKCHK(request, dsql_type_req);
DEV_BLKCHK(input, dsql_type_nod);
dsql_nod* select = input->nod_arg[1];
dsql_nod* select_expr = input->nod_arg[1];
const DsqlContextStack::iterator base(*request->req_context);
dsql_nod* node = MAKE_node(ntype, 1);
@ -2910,18 +2906,22 @@ static dsql_nod* pass1_any( dsql_req* request, dsql_nod* input, NOD_TYPE ntype)
// Build first the node from our base-context so that the right context is
// used while parsing the nodes
temp->nod_arg[0] = PASS1_node(request, input->nod_arg[0], false);
dsql_nod* rse =
PASS1_rse(request, select, select->nod_arg[e_sel_order],
select->nod_arg[e_sel_rows], NULL);
dsql_nod* rse = PASS1_rse(request, select_expr, NULL);
node->nod_arg[0] = rse;
const dsql_nod* const query_spec = select_expr->nod_arg[e_sel_query_spec];
if (query_spec->nod_count > 1)
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104, isc_arg_gds,
isc_token_err, // Token unknown
isc_arg_gds, isc_random, isc_arg_string, "UNION", 0);
// adjust the scope level back to the sub-rse, so that
// the fields in the select list will be properly recognized
request->req_scope_level++;
request->req_in_select_list++;
temp->nod_arg[1] =
PASS1_node(request, select->nod_arg[e_sel_list]->nod_arg[0], false);
dsql_nod* const column =
query_spec->nod_arg[0]->nod_arg[e_qry_list]->nod_arg[0];
temp->nod_arg[1] = PASS1_node(request, column, false);
request->req_in_select_list--;
request->req_scope_level--;
@ -3592,17 +3592,9 @@ static dsql_nod* pass1_derived_table(dsql_req* request, dsql_nod* input, bool pr
request->req_dt_base_context : &temp;
request->req_alias_relation_prefix = pass1_alias_concat(req_alias_relation_prefix, alias);
// Calling pass1_rse (for nod_select) which will call internally PASS1_rse.
// nod_select can contain ORDER BY information.
// We need to keep scope_level on the same level and because PASS1_rse
// increments scope_level with 1 we decrease it first.
request->req_scope_level--;
dsql_nod* const select = input->nod_arg[e_derived_table_rse];
dsql_nod* rse =
pass1_rse(request, select->nod_arg[e_select_expr], select->nod_arg[e_select_order],
select->nod_arg[e_select_rows], NULL);
dsql_nod* const select_expr = input->nod_arg[e_derived_table_rse];
dsql_nod* rse = PASS1_rse(request, select_expr, NULL);
context->ctx_rse = node->nod_arg[e_derived_table_rse] = rse;
request->req_scope_level++;
// Finish off by cleaning up contexts and put them into req_dt_context
// so create view (ddl) can deal with it.
@ -3844,8 +3836,8 @@ static dsql_nod* pass1_field( dsql_req* request, dsql_nod* input, const bool lis
if there is an alias, check only against the first matching */
DsqlContextStack ambiguous_ctx_stack;
dsql_nod* node = 0; // This var must be initialized.
dsql_nod* node = NULL; // This var must be initialized.
// AB: Loop through the scope_levels starting by its own.
bool done = false;
USHORT current_scope_level = request->req_scope_level + 1;
@ -4552,20 +4544,18 @@ static dsql_nod* pass1_insert( dsql_req* request, dsql_nod* input)
request->req_type = REQ_INSERT;
dsql_nod* node = MAKE_node(nod_store, e_sto_count);
// Process SELECT expression, if present
// Process SELECT expression, if present
dsql_nod* values;
dsql_nod* rse = input->nod_arg[e_ins_select];
if (rse) {
node->nod_arg[e_sto_rse] = rse =
PASS1_rse(request, rse, rse->nod_arg[e_sel_order],
rse->nod_arg[e_sel_rows], NULL);
node->nod_arg[e_sto_rse] = rse = PASS1_rse(request, rse, NULL);
values = rse->nod_arg[e_rse_items];
}
else
values = PASS1_node(request, input->nod_arg[e_ins_values], false);
// Process relation
// Process relation
dsql_nod* temp_rel = pass1_relation(request, input->nod_arg[e_ins_relation]);
node->nod_arg[e_sto_relation] = temp_rel;
@ -4573,13 +4563,13 @@ static dsql_nod* pass1_insert( dsql_req* request, dsql_nod* input)
DEV_BLKCHK(context, dsql_type_ctx);
dsql_rel* relation = context->ctx_relation;
// If there isn't a field list, generate one
// If there isn't a field list, generate one
dsql_nod* fields = input->nod_arg[e_ins_fields];
if (fields) {
fields = PASS1_node(request, fields, false);
// begin IBO hack
// 02-May-2004, Nickolay Samofatov. Do not constify ptr further e.g. to
// 02-May-2004, Nickolay Samofatov. Do not constify ptr further e.g. to
// const dsql_nod* const* .... etc. It chokes GCC 3.4.0
dsql_nod** ptr = fields->nod_arg;
for (const dsql_nod* const* const end = ptr + fields->nod_count;
@ -4604,7 +4594,7 @@ static dsql_nod* pass1_insert( dsql_req* request, dsql_nod* input)
input->nod_arg[e_ins_fields]->nod_arg[ptr - fields->nod_arg]);
}
}
// end IBO hack
// end IBO hack
}
else {
// CVC: Ann Harrison requested to skip COMPUTED fields in INSERT w/o field list.
@ -4620,7 +4610,7 @@ static dsql_nod* pass1_insert( dsql_req* request, dsql_nod* input)
fields = MAKE_list(stack);
}
// Match field fields and values
// Match field fields and values
if (fields->nod_count != values->nod_count) {
// count of column list and value list don't match
@ -4673,10 +4663,14 @@ static dsql_nod* pass1_join(dsql_req* request, dsql_nod* input, bool proc_flag)
DEV_BLKCHK(input, dsql_type_nod);
dsql_nod* node = MAKE_node(input->nod_type, input->nod_count);
// First process type.
// First process type
node->nod_arg[e_join_type] =
PASS1_node(request, input->nod_arg[e_join_type], proc_flag);
// Process relations.
// Process relations
switch (node->nod_arg[e_join_type]->nod_type) {
case nod_join_inner:
node->nod_arg[e_join_left_rel] =
@ -4710,12 +4704,22 @@ static dsql_nod* pass1_join(dsql_req* request, dsql_nod* input, bool proc_flag)
break;
default:
fb_assert(false); // join type expected.
fb_assert(false); // join type expected
break;
}
// Process boolean (ON clause).
// Process boolean
dsql_nod* boolean = input->nod_arg[e_join_boolean];
if (boolean && (boolean->nod_type == nod_flag || boolean->nod_type == nod_list))
{
// Process NATURAL JOIN or USING clause
ERRD_post(isc_wish_list, 0);
}
node->nod_arg[e_join_boolean] =
PASS1_node(request, input->nod_arg[e_join_boolean], proc_flag);
return node;
}
@ -5255,7 +5259,7 @@ static dsql_rel* pass1_base_table( dsql_req* request, const dsql_rel* relation,
@brief Compile a record selection expression.
The input node may either be a "select_expression"
or a "list" (an implicit union).
or a "list" (an implicit union) or a "query specification".
@param request
@ -5263,10 +5267,11 @@ static dsql_rel* pass1_base_table( dsql_req* request, const dsql_rel* relation,
@param order
@param rows
@param update_lock
@param flags
**/
static dsql_nod* pass1_rse( dsql_req* request, dsql_nod* input, dsql_nod* order,
dsql_nod* rows, dsql_nod* update_lock)
dsql_nod* rows, dsql_nod* update_lock, USHORT flags)
{
DEV_BLKCHK(request, dsql_type_req);
DEV_BLKCHK(input, dsql_type_nod);
@ -5274,19 +5279,33 @@ static dsql_nod* pass1_rse( dsql_req* request, dsql_nod* input, dsql_nod* order,
tsql* tdsql = DSQL_get_thread_data();
// Handle implicit union case first. Maybe it's not a union
if (input->nod_type == nod_list) {
if (input->nod_type == nod_select_expr)
{
return pass1_rse(request, input->nod_arg[e_sel_query_spec],
input->nod_arg[e_sel_order], input->nod_arg[e_sel_rows],
update_lock, input->nod_flags);
}
else if (input->nod_type == nod_list)
{
if (input->nod_count == 1)
return PASS1_rse(request, input->nod_arg[0], order, rows, update_lock);
else {
{
return pass1_rse(request, input->nod_arg[0], order, rows,
update_lock, flags);
}
else
{
if (update_lock)
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104, isc_arg_gds,
isc_token_err, // Token unknown
isc_arg_gds, isc_random, isc_arg_string, "WITH LOCK", 0);
return pass1_union(request, input, order, rows);
return pass1_union(request, input, order, rows, flags);
}
}
else
{
fb_assert(input->nod_type == nod_query_spec);
}
// Save the original base of the context stack and process relations
@ -5299,7 +5318,7 @@ static dsql_nod* pass1_rse( dsql_req* request, dsql_nod* input, dsql_nod* order,
request->req_dt_base_context = request->req_context;
dsql_nod* list = rse->nod_arg[e_rse_streams] =
PASS1_node(request, input->nod_arg[e_sel_from], false);
PASS1_node(request, input->nod_arg[e_qry_from], false);
// Save new current context for derived tables, because in other
// elements a reference to outer context is allowed.
@ -5318,7 +5337,8 @@ static dsql_nod* pass1_rse( dsql_req* request, dsql_nod* input, dsql_nod* order,
} // end scope block
// Process LIMIT and/or ROWS, if any
dsql_nod* node = input->nod_arg[e_sel_limit];
dsql_nod* node = input->nod_arg[e_qry_limit];
if (node && rows) {
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
isc_arg_gds, isc_token_err, // Token unknown
@ -5346,7 +5366,7 @@ static dsql_nod* pass1_rse( dsql_req* request, dsql_nod* input, dsql_nod* order,
// Process boolean, if any
if (node = input->nod_arg[e_sel_where]) {
if ( (node = input->nod_arg[e_qry_where]) ) {
++request->req_in_where_clause;
rse->nod_arg[e_rse_boolean] = PASS1_node(request, node, false);
--request->req_in_where_clause;
@ -5369,7 +5389,17 @@ static dsql_nod* pass1_rse( dsql_req* request, dsql_nod* input, dsql_nod* order,
// Process select list, if any. If not, generate one
if (node = input->nod_arg[e_sel_list]) {
node = input->nod_arg[e_qry_list];
if ((flags & NOD_SELECT_EXPR_VALUE) && (!node || node->nod_count > 1))
{
// More than one column (or asterisk) is specified in column_singleton
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
isc_arg_gds, isc_dsql_command_err,
isc_arg_gds, isc_dsql_count_mismatch, 0);
}
if (node) {
++request->req_in_select_list;
rse->nod_arg[e_rse_items] = pass1_sel_list(request, node);
--request->req_in_select_list;
@ -5409,7 +5439,7 @@ static dsql_nod* pass1_rse( dsql_req* request, dsql_nod* input, dsql_nod* order,
if (order) {
++request->req_in_order_by_clause;
rse->nod_arg[e_rse_sort] = pass1_sort(request, order, input->nod_arg[e_sel_list]);
rse->nod_arg[e_rse_sort] = pass1_sort(request, order, input->nod_arg[e_qry_list]);
--request->req_in_order_by_clause;
}
@ -5419,8 +5449,8 @@ static dsql_nod* pass1_rse( dsql_req* request, dsql_nod* input, dsql_nod* order,
dsql_nod* parent_rse = NULL;
dsql_nod* aggregate = NULL;
if (input->nod_arg[e_sel_group] ||
input->nod_arg[e_sel_having] ||
if (input->nod_arg[e_qry_group] ||
input->nod_arg[e_qry_having] ||
(rse->nod_arg[e_rse_items] && aggregate_found(request, rse->nod_arg[e_rse_items])) ||
(rse->nod_arg[e_rse_sort] && aggregate_found(request, rse->nod_arg[e_rse_sort])))
{
@ -5460,13 +5490,13 @@ static dsql_nod* pass1_rse( dsql_req* request, dsql_nod* input, dsql_nod* order,
// Process GROUP BY clause, if any
if (node = input->nod_arg[e_sel_group])
if ( (node = input->nod_arg[e_qry_group]) )
{
/* if there are positions in the group by clause then replace them
by the (newly pass) items from the select_list */
++request->req_in_group_by_clause;
aggregate->nod_arg[e_agg_group] =
pass1_group_by_list(request, input->nod_arg[e_sel_group], input->nod_arg[e_sel_list]);
pass1_group_by_list(request, input->nod_arg[e_qry_group], input->nod_arg[e_qry_list]);
--request->req_in_group_by_clause;
/* AB: An field pointing to another parent_context isn't
@ -5485,33 +5515,18 @@ static dsql_nod* pass1_rse( dsql_req* request, dsql_nod* input, dsql_nod* order,
// parse a user-specified access plan
if (node = input->nod_arg[e_sel_plan]) {
/* disallow plans in a trigger for the short term,
until we can figure out why they don't work: bug #6057 */
/* dimitr: I've commented out the following protection, because it's proven
by Ignacio J. Ortega and myself that now triggers work
with indexes in plans as expected, so it seems that the reason
for the mentioned bug #6057 is already fixed (2002-10-25)
if (request->req_flags & REQ_trigger)
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104, isc_arg_gds, isc_token_err,
isc_arg_gds, isc_random, isc_arg_string, "PLAN", 0);
*/
rse->nod_arg[e_rse_plan] = PASS1_node(request, node, false);
}
rse->nod_arg[e_rse_plan] =
PASS1_node(request, input->nod_arg[e_qry_plan], false);
// AB: Pass select-items for distinct operation again, because for
// sub-selects a new contextnumber should be generated
if (input->nod_arg[e_sel_distinct]) {
if (input->nod_arg[e_qry_distinct]) {
if (update_lock) {
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
isc_arg_gds, isc_token_err, // Token unknown
isc_arg_gds, isc_random, isc_arg_string, "WITH LOCK", 0);
}
if (node = input->nod_arg[e_sel_list]) {
if ( (node = input->nod_arg[e_qry_list]) ) {
++request->req_in_select_list;
target_rse->nod_arg[e_rse_reduced] = pass1_sel_list(request, node);
--request->req_in_select_list;
@ -5529,45 +5544,17 @@ static dsql_nod* pass1_rse( dsql_req* request, dsql_nod* input, dsql_nod* order,
}
}
// Unless there was a parent, we're done
if (!parent_context) {
rse->nod_arg[e_rse_singleton] = input->nod_arg[e_sel_singleton];
return rse;
}
// Reset context of select items to point to the parent stream
parent_rse->nod_arg[e_rse_items] =
remap_fields(request, rse->nod_arg[e_rse_items], parent_context);
rse->nod_arg[e_rse_items] = NULL;
// AB: Check for invalid contructions inside selected-items list
list = parent_rse->nod_arg[e_rse_items];
{ // scope block
const dsql_nod* const* ptr = list->nod_arg;
for (const dsql_nod* const* const end = ptr + list->nod_count;
ptr < end; ptr++)
if (parent_context)
{
if (invalid_reference(parent_context, *ptr,
aggregate->nod_arg[e_agg_group], false, false))
{
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
isc_arg_gds, isc_dsql_agg_column_err,
isc_arg_string, "select list", 0);
// Invalid expression in the select list
// (not contained in either an aggregate or the GROUP BY clause)
}
}
} // end scope block
// Reset context of select items to point to the parent stream
// Reset context of order items to point to the parent stream
if (order) {
parent_rse->nod_arg[e_rse_sort] =
remap_fields(request, rse->nod_arg[e_rse_sort], parent_context);
rse->nod_arg[e_rse_sort] = NULL;
parent_rse->nod_arg[e_rse_items] =
remap_fields(request, rse->nod_arg[e_rse_items], parent_context);
rse->nod_arg[e_rse_items] = NULL;
// AB: Check for invalid contructions inside the ORDER BY clause
list = target_rse->nod_arg[e_rse_sort];
// AB: Check for invalid contructions inside selected-items list
list = parent_rse->nod_arg[e_rse_items];
{ // scope block
const dsql_nod* const* ptr = list->nod_arg;
for (const dsql_nod* const* const end = ptr + list->nod_count;
ptr < end; ptr++)
@ -5577,60 +5564,90 @@ static dsql_nod* pass1_rse( dsql_req* request, dsql_nod* input, dsql_nod* order,
{
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
isc_arg_gds, isc_dsql_agg_column_err,
isc_arg_string, "ORDER BY clause", 0);
// Invalid expression in the ORDER BY clause
isc_arg_string, "select list", 0);
// Invalid expression in the select list
// (not contained in either an aggregate or the GROUP BY clause)
}
}
}
} // end scope block
// And, of course, reduction clauses must also apply to the parent
if (input->nod_arg[e_sel_distinct]) {
parent_rse->nod_arg[e_rse_reduced] =
remap_fields(request, parent_rse->nod_arg[e_rse_reduced], parent_context);
}
// Reset context of order items to point to the parent stream
// Process HAVING clause, if any
if (order) {
parent_rse->nod_arg[e_rse_sort] =
remap_fields(request, rse->nod_arg[e_rse_sort], parent_context);
rse->nod_arg[e_rse_sort] = NULL;
if (node = input->nod_arg[e_sel_having]) {
++request->req_in_having_clause;
parent_rse->nod_arg[e_rse_boolean] = PASS1_node(request, node, false);
--request->req_in_having_clause;
parent_rse->nod_arg[e_rse_boolean] =
remap_fields(request, parent_rse->nod_arg[e_rse_boolean], parent_context);
// AB: Check for invalid contructions inside the HAVING clause
list = parent_rse->nod_arg[e_rse_boolean];
dsql_nod** ptr = list->nod_arg;
for (const dsql_nod* const* const end = ptr + list->nod_count;
ptr < end; ptr++)
{
if (invalid_reference(parent_context, *ptr,
aggregate->nod_arg[e_agg_group], false, false))
// AB: Check for invalid contructions inside the ORDER BY clause
list = target_rse->nod_arg[e_rse_sort];
const dsql_nod* const* ptr = list->nod_arg;
for (const dsql_nod* const* const end = ptr + list->nod_count;
ptr < end; ptr++)
{
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
isc_arg_gds, isc_dsql_agg_having_err,
isc_arg_string, "HAVING clause", 0);
// Invalid expression in the HAVING clause
// (neither an aggregate nor contained in the GROUP BY clause)
if (invalid_reference(parent_context, *ptr,
aggregate->nod_arg[e_agg_group], false, false))
{
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
isc_arg_gds, isc_dsql_agg_column_err,
isc_arg_string, "ORDER BY clause", 0);
// Invalid expression in the ORDER BY clause
// (not contained in either an aggregate or the GROUP BY clause)
}
}
}
#ifdef CHECK_HAVING
if (aggregate)
if (invalid_reference(parent_rse->nod_arg[e_rse_boolean],
aggregate->nod_arg[e_agg_group]))
// And, of course, reduction clauses must also apply to the parent
if (input->nod_arg[e_qry_distinct]) {
parent_rse->nod_arg[e_rse_reduced] =
remap_fields(request, parent_rse->nod_arg[e_rse_reduced], parent_context);
}
// Process HAVING clause, if any
if ( (node = input->nod_arg[e_qry_having]) ) {
++request->req_in_having_clause;
parent_rse->nod_arg[e_rse_boolean] = PASS1_node(request, node, false);
--request->req_in_having_clause;
parent_rse->nod_arg[e_rse_boolean] =
remap_fields(request, parent_rse->nod_arg[e_rse_boolean], parent_context);
// AB: Check for invalid contructions inside the HAVING clause
list = parent_rse->nod_arg[e_rse_boolean];
dsql_nod** ptr = list->nod_arg;
for (const dsql_nod* const* const end = ptr + list->nod_count;
ptr < end; ptr++)
{
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
isc_arg_gds, isc_field_ref_err, 0);
// invalid field reference
if (invalid_reference(parent_context, *ptr,
aggregate->nod_arg[e_agg_group], false, false))
{
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
isc_arg_gds, isc_dsql_agg_having_err,
isc_arg_string, "HAVING clause", 0);
// Invalid expression in the HAVING clause
// (neither an aggregate nor contained in the GROUP BY clause)
}
}
#ifdef CHECK_HAVING
if (aggregate)
{
if (invalid_reference(parent_rse->nod_arg[e_rse_boolean],
aggregate->nod_arg[e_agg_group]))
{
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
isc_arg_gds, isc_field_ref_err, 0);
// invalid field reference
}
}
#endif
}
rse = parent_rse;
}
parent_rse->nod_arg[e_rse_singleton] = input->nod_arg[e_sel_singleton];
return parent_rse;
rse->nod_flags = flags;
return rse;
}
@ -5921,7 +5938,9 @@ static dsql_nod* pass1_sort( dsql_req* request, dsql_nod* input, dsql_nod* s_lis
node1 = node1->nod_arg[e_coll_source];
}
if (node1->nod_type == nod_constant && node1->nod_desc.dsc_dtype == dtype_long) {
if (node1->nod_type == nod_constant &&
node1->nod_desc.dsc_dtype == dtype_long)
{
const ULONG position = (IPTR) (node1->nod_arg[0]);
if ((position < 1) || !s_list ||
(position > (ULONG) s_list->nod_count))
@ -6055,7 +6074,7 @@ static void pass1_udf_args(dsql_req* request, dsql_nod* input,
**/
static dsql_nod* pass1_union( dsql_req* request, dsql_nod* input,
dsql_nod* order_list, dsql_nod* rows)
dsql_nod* order_list, dsql_nod* rows, USHORT flags)
{
DEV_BLKCHK(request, dsql_type_req);
DEV_BLKCHK(input, dsql_type_nod);
@ -6076,7 +6095,9 @@ static dsql_nod* pass1_union( dsql_req* request, dsql_nod* input,
for (const dsql_nod* const* const end = ptr + input->nod_count; ptr < end;
++ptr, ++uptr)
{
*uptr = PASS1_rse(request, *ptr, NULL, NULL, NULL);
request->req_scope_level++;
*uptr = pass1_rse(request, *ptr, NULL, NULL, NULL, 0);
request->req_scope_level--;
while (*(request->req_context) != base)
{
request->req_union_context.push(request->req_context->pop());
@ -6241,6 +6262,7 @@ static dsql_nod* pass1_union( dsql_req* request, dsql_nod* input,
union_rse->nod_arg[e_rse_reduced] = union_items;
}
union_rse->nod_flags = flags;
return union_rse;
}
@ -6967,7 +6989,7 @@ static void remap_streams_to_parent_context( dsql_nod* input, dsql_ctx* parent_c
ptr < end; ptr++)
{
remap_streams_to_parent_context(*ptr, parent_context);
}
}
break;
}

View File

@ -26,7 +26,7 @@
dsql_ctx* PASS1_make_context(dsql_req*, dsql_nod*);
dsql_nod* PASS1_node(dsql_req*, dsql_nod*, bool);
dsql_nod* PASS1_rse(dsql_req*, dsql_nod*, dsql_nod*, dsql_nod*, dsql_nod*);
dsql_nod* PASS1_rse(dsql_req*, dsql_nod*, dsql_nod*);
dsql_nod* PASS1_statement(dsql_req*, dsql_nod*, bool);
#endif // DSQL_PASS1_PROTO_H