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:
parent
46397f0744
commit
a1bbad7ccf
@ -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));
|
||||
|
@ -258,3 +258,4 @@
|
||||
#define BLOCK 514
|
||||
#define IIF 515
|
||||
#define SCALAR_ARRAY 516
|
||||
#define CROSS 517
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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},
|
||||
|
@ -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,
|
||||
|
8360
src/dsql/parse.cpp
8360
src/dsql/parse.cpp
File diff suppressed because it is too large
Load Diff
351
src/dsql/parse.y
351
src/dsql/parse.y
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user