mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 07:23:04 +01:00
1. BIGINT is now the only keyword for the 64-bit exact numerics and it's available
in dialect 3 only. 2. BREAK statement has been disabled in triggers (like EXIT) because of the known BLR limitations. I hope it can be safely used in stored procedures though, hence I'd prefer to have it officially documented. 3. More complete implementation of the GROUP BY clause. You can group by internal functions and have ability to use more complex grouping conditions than before. By Arno Brinkman. 4. Allowed declaring and defining local variables at the same time. By Claudio Valderrama. Syntax: declare [variable] <var_name> <var_type> [{= | default} <default_value>] 5. Allowed ordinals to be used in the GROUP BY clause (like ORDER BY). By Arno Brinkman. Example: select extract(month from order_date), sum(order_sum) from orders group by 1 6. The first approach to the ALTER VIEW statement. Only high-level implementation so far. A lot of work in dfw.epp, metd.epp, etc. still required. By Dmitry Yemanov.
This commit is contained in:
parent
fd63bb8fd6
commit
7922269845
@ -20,7 +20,7 @@
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*
|
||||
* $Id: ddl.cpp,v 1.10 2002-07-02 12:17:44 dimitr Exp $
|
||||
* $Id: ddl.cpp,v 1.11 2002-08-11 08:04:52 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;
|
||||
*
|
||||
@ -59,8 +59,8 @@
|
||||
* 2001.10.26 Claudio Valderrama: added a call to the new METD_drop_function()
|
||||
* in DDL_execute() so the metadata cache for udfs can be refreshed.
|
||||
* 2001.12.06 Claudio Valderrama: DDL_resolve_intl_type should calculate field length
|
||||
*
|
||||
*
|
||||
* 2002.08.04 Claudio Valderrama: allow declaring and defining variables at the same time
|
||||
* 2002.08.04 Dmitry Yemanov: ALTER VIEW
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
@ -125,7 +125,7 @@ static void define_trigger(REQ, NOD);
|
||||
static void define_udf(REQ);
|
||||
static void define_update_action(REQ, NOD *, NOD *);
|
||||
static void define_upd_cascade_trg(REQ, NOD, NOD, NOD, TEXT *, TEXT *);
|
||||
static void define_view(REQ);
|
||||
static void define_view(REQ, NOD_TYPE);
|
||||
static void define_view_trigger(REQ, NOD, NOD, NOD);
|
||||
static void delete_procedure(REQ, NOD, BOOLEAN);
|
||||
static void delete_relation_view(REQ, NOD, BOOLEAN);
|
||||
@ -139,13 +139,13 @@ static void modify_domain(REQ);
|
||||
static void modify_field(REQ, NOD, SSHORT, STR);
|
||||
static void modify_index(REQ);
|
||||
static void modify_privilege(REQ, NOD_TYPE, SSHORT, UCHAR *, NOD, NOD, STR);
|
||||
static void process_role_nm_list(REQ, SSHORT, NOD, NOD, NOD_TYPE);
|
||||
static SCHAR modify_privileges(REQ, NOD_TYPE, SSHORT, NOD, NOD, NOD);
|
||||
static void modify_relation(REQ);
|
||||
static void process_role_nm_list(REQ, SSHORT, NOD, NOD, NOD_TYPE);
|
||||
static void put_descriptor(REQ, DSC *);
|
||||
static void put_dtype(REQ, FLD, USHORT);
|
||||
static void put_field(REQ, FLD, BOOLEAN);
|
||||
static void put_local_variable(REQ, VAR);
|
||||
static void put_local_variable(REQ, VAR, NOD);
|
||||
static SSHORT put_local_variables(REQ, NOD, SSHORT);
|
||||
static void put_msg_field(REQ, FLD);
|
||||
static NOD replace_field_names(NOD, NOD, NOD, SSHORT);
|
||||
@ -450,7 +450,6 @@ void DDL_resolve_intl_type2(REQ request,
|
||||
**************************************/
|
||||
|
||||
INTLSYM resolved_type;
|
||||
ULONG field_length;
|
||||
|
||||
if ((field->fld_dtype > dtype_any_text) && field->fld_dtype != dtype_blob)
|
||||
{
|
||||
@ -2324,6 +2323,7 @@ static void define_procedure( REQ request, NOD_TYPE op)
|
||||
request->append_cstring(gds_dyn_def_parameter, field->fld_name);
|
||||
request->append_number(gds_dyn_prm_number, position);
|
||||
request->append_number(gds_dyn_prm_type, 0);
|
||||
|
||||
DDL_resolve_intl_type(request, field, NULL);
|
||||
put_field(request, field, FALSE);
|
||||
|
||||
@ -2432,7 +2432,7 @@ static void define_procedure( REQ request, NOD_TYPE op)
|
||||
{
|
||||
parameter = *ptr;
|
||||
variable = (VAR) parameter->nod_arg[e_var_variable];
|
||||
put_local_variable(request, variable);
|
||||
put_local_variable(request, variable, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3267,7 +3267,7 @@ static void define_upd_cascade_trg( REQ request,
|
||||
}
|
||||
|
||||
|
||||
static void define_view( REQ request)
|
||||
static void define_view( REQ request, NOD_TYPE op)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -3294,10 +3294,39 @@ static void define_view( REQ request)
|
||||
|
||||
node = request->req_ddl_node;
|
||||
view_name = (STR) node->nod_arg[e_view_name];
|
||||
request->append_cstring(gds_dyn_def_view,
|
||||
reinterpret_cast<char*>(view_name->str_data));
|
||||
save_relation(request, view_name);
|
||||
request->append_number(gds_dyn_rel_sql_protection, 1);
|
||||
|
||||
if (op == nod_def_view)
|
||||
{
|
||||
request->append_cstring(gds_dyn_def_view,
|
||||
reinterpret_cast<char*>(view_name->str_data));
|
||||
request->append_number(gds_dyn_rel_sql_protection, 1);
|
||||
save_relation(request, view_name);
|
||||
}
|
||||
else // nod_mod_view
|
||||
{
|
||||
request->append_cstring(gds_dyn_mod_view,
|
||||
reinterpret_cast<char*>(view_name->str_data));
|
||||
relation = METD_get_relation(request, view_name);
|
||||
if (relation)
|
||||
{
|
||||
for (field = relation->rel_fields; field;
|
||||
field = field->fld_next)
|
||||
{
|
||||
request->append_cstring(gds_dyn_delete_local_fld,
|
||||
field->fld_name);
|
||||
request->append_uchar(gds_dyn_end);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) -607,
|
||||
/* gds_arg_gds, gds__dsql_command_err,
|
||||
gds_arg_gds, gds__dsql_view_not_found, */
|
||||
gds_arg_gds, 336068783L,
|
||||
gds_arg_string, view_name->str_data,
|
||||
gds_arg_end);
|
||||
}
|
||||
}
|
||||
|
||||
/* compile the SELECT statement into a record selection expression,
|
||||
making sure to bump the context number since view contexts start
|
||||
@ -3952,7 +3981,8 @@ static void generate_dyn( REQ request, NOD node)
|
||||
break;
|
||||
|
||||
case nod_def_view:
|
||||
define_view(request);
|
||||
case nod_mod_view:
|
||||
define_view(request, node->nod_type);
|
||||
break;
|
||||
|
||||
case nod_def_exception:
|
||||
@ -5265,7 +5295,7 @@ static void put_field( REQ request, FLD field, BOOLEAN udf_flag)
|
||||
}
|
||||
|
||||
|
||||
static void put_local_variable( REQ request, VAR variable)
|
||||
static void put_local_variable( REQ request, VAR variable, NOD host_param)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -5293,10 +5323,20 @@ static void put_local_variable( REQ request, VAR variable)
|
||||
put_dtype(request, field, TRUE);
|
||||
field->fld_dtype = dtype;
|
||||
|
||||
// Initialize variable to NULL
|
||||
/* Check for a default value, borrowed from define_domain */
|
||||
|
||||
request->append_uchar(blr_assignment);
|
||||
request->append_uchar(blr_null);
|
||||
NOD node = (host_param) ? host_param->nod_arg[e_dfl_default] : 0;
|
||||
if (node)
|
||||
{
|
||||
node = PASS1_node(request, node, 0);
|
||||
GEN_expr(request, node);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Initialize variable to NULL
|
||||
request->append_uchar(blr_null);
|
||||
}
|
||||
request->append_uchar(blr_variable);
|
||||
request->append_ushort(variable->var_variable_number);
|
||||
}
|
||||
@ -5339,7 +5379,7 @@ static SSHORT put_local_variables(REQ request, NOD parameters, SSHORT locals)
|
||||
locals);
|
||||
*ptr = var_node;
|
||||
VAR variable = (VAR) var_node->nod_arg[e_var_variable];
|
||||
put_local_variable(request, variable);
|
||||
put_local_variable(request, variable, parameter);
|
||||
locals++;
|
||||
}
|
||||
}
|
||||
|
@ -239,8 +239,7 @@
|
||||
#define SKIP 495
|
||||
#define CONNECTION_ID 496
|
||||
#define TRANSACTION_ID 497
|
||||
#define LARGEINT 498
|
||||
#define KW_INT64 499
|
||||
#define CASE 500
|
||||
#define NULLIF 501
|
||||
#define COALESCE 502
|
||||
#define BIGINT 498
|
||||
#define CASE 499
|
||||
#define NULLIF 500
|
||||
#define COALESCE 501
|
||||
|
@ -28,7 +28,7 @@
|
||||
* Contributor(s):
|
||||
*
|
||||
*
|
||||
* $Id: keywords.cpp,v 1.4 2002-08-03 15:27:20 dimitr Exp $
|
||||
* $Id: keywords.cpp,v 1.5 2002-08-11 08:04:53 dimitr Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@ -74,6 +74,7 @@ static CONST TOK tokens [] = {
|
||||
{BEFORE, "BEFORE", 1},
|
||||
{BEGIN, "BEGIN", 1},
|
||||
{BETWEEN, "BETWEEN", 1},
|
||||
{BIGINT, "BIGINT", 2},
|
||||
{BLOB, "BLOB", 1},
|
||||
{KW_BREAK, "BREAK", 2},
|
||||
{BY, "BY", 1},
|
||||
@ -158,14 +159,12 @@ static CONST TOK tokens [] = {
|
||||
{INPUT_TYPE, "INPUT_TYPE", 1},
|
||||
{INSERT, "INSERT", 1},
|
||||
{KW_INT, "INT", 1},
|
||||
{KW_INT64, "INT64", 2},
|
||||
{INTEGER, "INTEGER", 1},
|
||||
{INTO, "INTO", 1},
|
||||
{IS, "IS", 1},
|
||||
{ISOLATION, "ISOLATION", 1},
|
||||
{JOIN, "JOIN", 1},
|
||||
{KEY, "KEY", 1},
|
||||
{LARGEINT, "LARGEINT", 2},
|
||||
{LEFT, "LEFT", 1},
|
||||
{LENGTH, "LENGTH", 1},
|
||||
{LEVEL, "LEVEL", 1},
|
||||
|
@ -1099,7 +1099,7 @@ void MAKE_desc_from_list( DSC * desc, NOD node)
|
||||
{
|
||||
/* ignore NULL value from walking */
|
||||
tnod = *arg;
|
||||
if (tnod->nod_type == nod_null)
|
||||
if (tnod->nod_type == nod_null || tnod->nod_type == nod_parameter)
|
||||
continue;
|
||||
MAKE_desc(&desc1, *arg);
|
||||
if (firstarg)
|
||||
@ -1227,12 +1227,11 @@ void MAKE_desc_from_list( DSC * desc, NOD node)
|
||||
}
|
||||
}
|
||||
|
||||
/* If we haven't had a type at all then all values are NULL nodes */
|
||||
/* If we haven't had a type at all then all values are NULL and/or parameter nodes */
|
||||
if (firstarg)
|
||||
{
|
||||
maxtextlength = desc1.dsc_length;
|
||||
text_in_list = 1;
|
||||
firstarg = 0;
|
||||
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 804,
|
||||
gds_arg_gds, gds_dsql_datatype_err, 0);
|
||||
}
|
||||
|
||||
desc->dsc_flags = DSC_nullable;
|
||||
|
@ -27,6 +27,7 @@
|
||||
* 2002.07.30 Arno Brinkman:
|
||||
* 2002.07.30 Added nod_searched_case, nod_simple_case, nod_coalesce
|
||||
* 2002.07.30 and constants for arguments
|
||||
* 2002.08.04 Dmitry Yemanov: ALTER VIEW
|
||||
*/
|
||||
|
||||
#ifndef _DSQL_NODE_H_
|
||||
@ -316,7 +317,8 @@ typedef ENUM nod_t
|
||||
nod_internal_info, /* internal engine info */
|
||||
nod_searched_case, /* searched CASE function */
|
||||
nod_simple_case, /* simple CASE function */
|
||||
nod_coalesce /* COALESCE function */
|
||||
nod_coalesce, /* COALESCE function */
|
||||
nod_mod_view /* ALTER VIEW */
|
||||
} NOD_TYPE;
|
||||
|
||||
|
||||
|
6044
src/dsql/parse.cpp
6044
src/dsql/parse.cpp
File diff suppressed because it is too large
Load Diff
@ -43,8 +43,12 @@
|
||||
* 2002.07.30 tokens CASE, NULLIF, COALESCE added
|
||||
* 2002.07.30 See block < CASE expression > what is added to value as case_expression
|
||||
* 2002.07.30 function is split up into aggregate_function, numeric_value_function, string_value_function, generate_value_function
|
||||
* 2002.07.30 new group_by_function and added to grp_column_elem. (TODO: allow these functions in select_group_by_list inside the engine)
|
||||
* 2002.07.30 new group_by_function and added to grp_column_elem
|
||||
* 2002.07.30 cast removed from function and added as cast_specification to value
|
||||
* 2002.08.04 Claudio Valderrama: allow declaring and defining variables at the same time
|
||||
* 2002.08.04 Dmitry Yemanov: ALTER VIEW
|
||||
* 2002.08.06 Arno Brinkman: ordinal added to grp_column_elem for using positions in group by
|
||||
* 2002.08.07 Dmitry Yemanov: INT64/LARGEINT are replaced with BIGINT and available in dialect 3 only
|
||||
*/
|
||||
|
||||
|
||||
@ -395,8 +399,7 @@ static void yyerror (TEXT *);
|
||||
|
||||
%token CONNECTION_ID
|
||||
%token TRANSACTION_ID
|
||||
%token LARGEINT
|
||||
%token KW_INT64
|
||||
%token BIGINT
|
||||
%token CASE
|
||||
%token NULLIF
|
||||
%token COALESCE
|
||||
@ -1369,9 +1372,21 @@ var_declarations : var_declaration
|
||||
{ $$ = make_node (nod_list, 2, $1, $2); }
|
||||
;
|
||||
|
||||
var_declaration : DECLARE VARIABLE column_def_name non_array_type ';'
|
||||
var_declaration : DECLARE var_decl_opt column_def_name non_array_type var_init_opt ';'
|
||||
{ $$ = make_node (nod_def_field, (int) e_dfl_count,
|
||||
$3, NULL, NULL, NULL, NULL, NULL, NULL); }
|
||||
$3, $5, NULL, NULL, NULL, NULL, NULL); }
|
||||
;
|
||||
|
||||
var_decl_opt : VARIABLE
|
||||
{ $$ = NULL; }
|
||||
|
|
||||
{ $$ = NULL; }
|
||||
;
|
||||
|
||||
var_init_opt : '=' default_value
|
||||
{ $$ = $2; }
|
||||
| default_opt
|
||||
{ $$ = $1; }
|
||||
;
|
||||
|
||||
proc_block : proc_statement
|
||||
@ -1555,6 +1570,12 @@ rview_clause : symbol_view_name column_parens_opt AS begin_string union_view
|
||||
;
|
||||
*/
|
||||
|
||||
alter_view_clause : symbol_view_name column_parens_opt AS begin_string union_view
|
||||
end_string
|
||||
{ $$ = make_node (nod_mod_view, (int) e_view_count,
|
||||
$1, $2, $5, NULL, $6); }
|
||||
;
|
||||
|
||||
union_view : union_view_expr
|
||||
{ $$ = make_node (nod_select, (int) 2, $1, NULL); }
|
||||
;
|
||||
@ -1716,6 +1737,8 @@ alter_clause : EXCEPTION symbol_exception_name sql_string
|
||||
| TABLE simple_table_name alter_ops
|
||||
{ $$ = make_node (nod_mod_relation, (int) e_alt_count,
|
||||
$2, make_list ($3)); }
|
||||
| VIEW alter_view_clause
|
||||
{ $$ = $2; }
|
||||
| TRIGGER alter_trigger_clause
|
||||
{ $$ = $2; }
|
||||
| PROCEDURE alter_procedure_clause
|
||||
@ -1999,8 +2022,20 @@ simple_type : non_charset_simple_type
|
||||
non_charset_simple_type : national_character_type
|
||||
| numeric_type
|
||||
| float_type
|
||||
| largeint_keyword
|
||||
| BIGINT
|
||||
{
|
||||
if (client_dialect < SQL_DIALECT_V6_TRANSITION)
|
||||
ERRD_post (gds_sqlerr, gds_arg_number, (SLONG) -104,
|
||||
gds_arg_gds, isc_sql_dialect_datatype_unsupport,
|
||||
gds_arg_number, client_dialect,
|
||||
gds_arg_string, "BIGINT",
|
||||
0);
|
||||
if (db_dialect < SQL_DIALECT_V6_TRANSITION)
|
||||
ERRD_post (gds_sqlerr, gds_arg_number, (SLONG) -104,
|
||||
gds_arg_gds, isc_sql_db_dialect_dtype_unsupport,
|
||||
gds_arg_number, db_dialect,
|
||||
gds_arg_string, "BIGINT",
|
||||
0);
|
||||
g_field->fld_dtype = dtype_int64;
|
||||
g_field->fld_length = sizeof (SINT64);
|
||||
}
|
||||
@ -2057,10 +2092,6 @@ non_charset_simple_type : national_character_type
|
||||
}
|
||||
;
|
||||
|
||||
largeint_keyword : LARGEINT
|
||||
| KW_INT64
|
||||
;
|
||||
|
||||
integer_keyword : INTEGER
|
||||
| KW_INT
|
||||
;
|
||||
@ -2736,6 +2767,7 @@ grp_column_list : grp_column_elem
|
||||
;
|
||||
|
||||
grp_column_elem : column_name
|
||||
| ordinal
|
||||
| udf
|
||||
| group_by_function
|
||||
| column_name COLLATE symbol_collation_name
|
||||
|
@ -86,6 +86,15 @@
|
||||
*
|
||||
* 2002.07.30 Arno Brinkman: Added pass1_coalesce, pass1_simple_case, pass1_searched_case
|
||||
* and pass1_put_args_on_stack
|
||||
*
|
||||
* 2002.08.04 Arno Brinkman: Added ignore_cast as parameter to node_match,
|
||||
* Changed invalid_reference procedure for allow EXTRACT, SUBSTRING, CASE,
|
||||
* COALESCE and NULLIF functions in GROUP BY and as select_items.
|
||||
* Removed aggregate_in_list procedure.
|
||||
*
|
||||
* 2002.08.07 Dmitry Yemanov: Disabled BREAK statement in triggers
|
||||
*
|
||||
* 2002.08.10 Dmitry Yemanov: ALTER VIEW
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
@ -117,7 +126,6 @@
|
||||
ASSERT_FILENAME /* Define things assert() needs */
|
||||
static BOOLEAN aggregate_found(REQ, NOD, NOD *);
|
||||
static BOOLEAN aggregate_found2(REQ, NOD, NOD *, BOOLEAN *);
|
||||
static BOOLEAN aggregate_in_list (NOD, BOOLEAN *, NOD);
|
||||
static NOD ambiguity_check (NOD, REQ, FLD, DLLS, DLLS);
|
||||
static void assign_fld_dtype_from_dsc(FLD, DSC *);
|
||||
static NOD compose(NOD, NOD, NOD_TYPE);
|
||||
@ -128,9 +136,9 @@ static NOD explode_outputs(REQ, PRC);
|
||||
static void field_error(TEXT *, TEXT *, NOD);
|
||||
static PAR find_dbkey(REQ, NOD);
|
||||
static PAR find_record_version(REQ, NOD);
|
||||
static BOOLEAN invalid_reference(NOD, NOD);
|
||||
static BOOLEAN invalid_reference(REQ, NOD, NOD, BOOLEAN);
|
||||
static void mark_ctx_outer_join(NOD);
|
||||
static BOOLEAN node_match(NOD, NOD);
|
||||
static BOOLEAN node_match(NOD, NOD, BOOLEAN);
|
||||
static NOD pass1_alias_list(REQ, NOD);
|
||||
static CTX pass1_alias(REQ, STR);
|
||||
static NOD pass1_any(REQ, NOD, NOD_TYPE);
|
||||
@ -925,6 +933,7 @@ NOD PASS1_statement(REQ request, NOD input, USHORT proc_flag)
|
||||
case nod_def_constraint:
|
||||
case nod_def_exception:
|
||||
case nod_mod_relation:
|
||||
case nod_mod_view:
|
||||
case nod_mod_exception:
|
||||
case nod_del_relation:
|
||||
case nod_del_view:
|
||||
@ -1239,6 +1248,9 @@ NOD PASS1_statement(REQ request, NOD input, USHORT proc_flag)
|
||||
return input;
|
||||
|
||||
case nod_breakleave:
|
||||
if (request->req_flags & REQ_trigger)
|
||||
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 104, gds_arg_gds, gds_token_err, /* Token unknown */
|
||||
gds_arg_gds, gds_random, gds_arg_string, "BREAK", 0);
|
||||
input->nod_arg [e_break_number] = (NOD) (request->req_loop_number - 1);
|
||||
return input;
|
||||
|
||||
@ -1478,93 +1490,6 @@ static BOOLEAN aggregate_found2(
|
||||
}
|
||||
|
||||
|
||||
static BOOLEAN aggregate_in_list (NOD sub, BOOLEAN *field, NOD list)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* a g g r e g a t e _ i n _ l i s t
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Check for an aggregate expression in a
|
||||
* node or list/chain of nodes.
|
||||
*
|
||||
**************************************/
|
||||
BOOLEAN aggregate;
|
||||
NOD *ptr, *end;
|
||||
|
||||
DEV_BLKCHK (sub, dsql_type_nod);
|
||||
|
||||
switch (sub->nod_type) {
|
||||
|
||||
/* handle the simple case of a straightforward aggregate */
|
||||
|
||||
case nod_agg_average:
|
||||
case nod_agg_average2:
|
||||
case nod_agg_total2:
|
||||
case nod_agg_max:
|
||||
case nod_agg_min:
|
||||
case nod_agg_total:
|
||||
case nod_agg_count:
|
||||
case nod_aggregate:
|
||||
case nod_map:
|
||||
return TRUE;
|
||||
|
||||
case nod_field:
|
||||
/* field is only ok if it also appears in group by */
|
||||
*field = invalid_reference (sub, list);
|
||||
return FALSE;
|
||||
case nod_constant:
|
||||
return FALSE;
|
||||
|
||||
/* for expressions in which an aggregate might
|
||||
be buried, recursively check for one */
|
||||
|
||||
case nod_add:
|
||||
case nod_concatenate:
|
||||
case nod_divide:
|
||||
case nod_multiply:
|
||||
case nod_negate:
|
||||
case nod_substr:
|
||||
case nod_subtract:
|
||||
case nod_add2:
|
||||
case nod_divide2:
|
||||
case nod_multiply2:
|
||||
case nod_subtract2:
|
||||
case nod_upcase:
|
||||
case nod_extract:
|
||||
case nod_coalesce:
|
||||
case nod_simple_case:
|
||||
case nod_searched_case:
|
||||
case nod_list:
|
||||
aggregate = FALSE;
|
||||
for (ptr = sub->nod_arg, end = ptr + sub->nod_count; ptr < end; ptr++)
|
||||
{
|
||||
DEV_BLKCHK (*ptr, dsql_type_nod);
|
||||
aggregate |= aggregate_in_list (*ptr,field,list);
|
||||
}
|
||||
return aggregate;
|
||||
|
||||
case nod_cast:
|
||||
case nod_udf:
|
||||
case nod_gen_id:
|
||||
case nod_gen_id2:
|
||||
if (sub->nod_count == 2)
|
||||
return (aggregate_in_list (sub->nod_arg[1],field,list));
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
case nod_via:
|
||||
/* Allow sub-selects - no validation in context of group by */
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static NOD ambiguity_check (NOD node, REQ request, FLD field,
|
||||
DLLS relations,DLLS procedures)
|
||||
{
|
||||
@ -1756,6 +1681,60 @@ static NOD copy_field( NOD field, CTX context)
|
||||
temp->nod_arg[e_alias_alias] = (NOD) alias;
|
||||
return temp;
|
||||
|
||||
/*-- Added for allowing EXTRACT, SUBSTRING, CASE, ... functions in GROUP BY CLAUSE --*/
|
||||
|
||||
case nod_via:
|
||||
return post_map(field, context);
|
||||
|
||||
case nod_rse:
|
||||
temp = MAKE_node(field->nod_type, field->nod_count);
|
||||
ptr2 = temp->nod_arg;
|
||||
for (ptr = field->nod_arg, end = ptr + field->nod_count; ptr < end;
|
||||
ptr++) *ptr2++ = *ptr;
|
||||
return temp;
|
||||
|
||||
case nod_coalesce:
|
||||
case nod_simple_case:
|
||||
case nod_searched_case:
|
||||
temp = MAKE_node(field->nod_type, field->nod_count);
|
||||
temp->nod_desc = field->nod_desc;
|
||||
ptr2 = temp->nod_arg;
|
||||
for (ptr = field->nod_arg, end = ptr + field->nod_count; ptr < end;
|
||||
ptr++)
|
||||
*ptr2++ = copy_field(*ptr, context);
|
||||
return temp;
|
||||
|
||||
case nod_relation:
|
||||
case nod_or:
|
||||
case nod_and:
|
||||
case nod_not:
|
||||
case nod_eql:
|
||||
case nod_neq:
|
||||
case nod_gtr:
|
||||
case nod_geq:
|
||||
case nod_lss:
|
||||
case nod_leq:
|
||||
case nod_eql_any:
|
||||
case nod_neq_any:
|
||||
case nod_gtr_any:
|
||||
case nod_geq_any:
|
||||
case nod_lss_any:
|
||||
case nod_leq_any:
|
||||
case nod_eql_all:
|
||||
case nod_neq_all:
|
||||
case nod_gtr_all:
|
||||
case nod_geq_all:
|
||||
case nod_lss_all:
|
||||
case nod_leq_all:
|
||||
case nod_between:
|
||||
case nod_like:
|
||||
case nod_containing:
|
||||
case nod_starting:
|
||||
case nod_exists:
|
||||
case nod_singular:
|
||||
case nod_missing:
|
||||
/*--- ---*/
|
||||
|
||||
case nod_add:
|
||||
case nod_add2:
|
||||
case nod_concatenate:
|
||||
@ -1770,9 +1749,6 @@ static NOD copy_field( NOD field, CTX context)
|
||||
case nod_upcase:
|
||||
case nod_internal_info:
|
||||
case nod_extract:
|
||||
case nod_coalesce:
|
||||
case nod_simple_case:
|
||||
case nod_searched_case:
|
||||
case nod_list:
|
||||
temp = MAKE_node(field->nod_type, field->nod_count);
|
||||
ptr2 = temp->nod_arg;
|
||||
@ -1857,15 +1833,15 @@ static void explode_asterisk( NOD node, NOD aggregate, DLLS * stack)
|
||||
node = MAKE_field(context, field, 0);
|
||||
if (aggregate) {
|
||||
if (invalid_reference
|
||||
(node,
|
||||
(NULL, node,
|
||||
aggregate->
|
||||
nod_arg[e_agg_group])) ERRD_post(gds_sqlerr,
|
||||
gds_arg_number,
|
||||
(SLONG) - 104,
|
||||
gds_arg_gds,
|
||||
gds_field_ref_err,
|
||||
/* invalid field reference */
|
||||
0);
|
||||
nod_arg[e_agg_group], FALSE)) ERRD_post(gds_sqlerr,
|
||||
gds_arg_number,
|
||||
(SLONG) - 104,
|
||||
gds_arg_gds,
|
||||
gds_field_ref_err,
|
||||
/* invalid field reference */
|
||||
0);
|
||||
}
|
||||
LLS_PUSH(MAKE_field(context, field, 0), stack);
|
||||
}
|
||||
@ -1875,15 +1851,15 @@ static void explode_asterisk( NOD node, NOD aggregate, DLLS * stack)
|
||||
node = MAKE_field(context, field, 0);
|
||||
if (aggregate) {
|
||||
if (invalid_reference
|
||||
(node,
|
||||
(NULL, node,
|
||||
aggregate->
|
||||
nod_arg[e_agg_group])) ERRD_post(gds_sqlerr,
|
||||
gds_arg_number,
|
||||
(SLONG) - 104,
|
||||
gds_arg_gds,
|
||||
gds_field_ref_err,
|
||||
/* invalid field reference */
|
||||
0);
|
||||
nod_arg[e_agg_group], FALSE)) ERRD_post(gds_sqlerr,
|
||||
gds_arg_number,
|
||||
(SLONG) - 104,
|
||||
gds_arg_gds,
|
||||
gds_field_ref_err,
|
||||
/* invalid field reference */
|
||||
0);
|
||||
}
|
||||
LLS_PUSH(MAKE_field(context, field, 0), stack);
|
||||
}
|
||||
@ -2064,7 +2040,7 @@ static PAR find_record_version( REQ request, NOD relation_name)
|
||||
}
|
||||
|
||||
|
||||
static BOOLEAN invalid_reference( NOD node, NOD list)
|
||||
static BOOLEAN invalid_reference(REQ request, NOD node, NOD list, BOOLEAN exact_field)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -2088,6 +2064,7 @@ static BOOLEAN invalid_reference( NOD node, NOD list)
|
||||
**************************************/
|
||||
NOD *ptr, *end;
|
||||
BOOLEAN invalid;
|
||||
CTX field_context;
|
||||
|
||||
DEV_BLKCHK(node, dsql_type_nod);
|
||||
DEV_BLKCHK(list, dsql_type_nod);
|
||||
@ -2099,139 +2076,18 @@ static BOOLEAN invalid_reference( NOD node, NOD list)
|
||||
|
||||
invalid = FALSE;
|
||||
|
||||
if (node->nod_type == nod_field)
|
||||
if (list)
|
||||
{
|
||||
FLD field;
|
||||
CTX context;
|
||||
NOD reference;
|
||||
|
||||
if (!list)
|
||||
return TRUE;
|
||||
field = (FLD) node->nod_arg[e_fld_field];
|
||||
context = (CTX) node->nod_arg[e_fld_context];
|
||||
|
||||
DEV_BLKCHK(field, dsql_type_fld);
|
||||
DEV_BLKCHK(context, dsql_type_ctx);
|
||||
|
||||
for (ptr = list->nod_arg, end = ptr + list->nod_count; ptr < end;
|
||||
ptr++)
|
||||
/* Check if this node (with ignoring of CASTs) appear also
|
||||
in the list of group by. If yes then it's allowed */
|
||||
for (ptr = list->nod_arg, end = ptr + list->nod_count; ptr < end; ptr++)
|
||||
{
|
||||
DEV_BLKCHK(*ptr, dsql_type_nod);
|
||||
reference = *ptr;
|
||||
if ((*ptr)->nod_type == nod_cast)
|
||||
{
|
||||
reference = (*ptr)->nod_arg[e_cast_source];
|
||||
}
|
||||
DEV_BLKCHK(reference, dsql_type_nod);
|
||||
if (reference->nod_type == nod_field &&
|
||||
field == (FLD) reference->nod_arg[e_fld_field] &&
|
||||
context == (CTX) reference->nod_arg[e_fld_context])
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (reference->nod_type == nod_udf )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
else if (node->nod_type == nod_dbkey)
|
||||
{
|
||||
CTX context;
|
||||
NOD reference, rel_node;
|
||||
|
||||
if (!list)
|
||||
return TRUE;
|
||||
rel_node = (NOD) node->nod_arg[0];
|
||||
context = (CTX) rel_node->nod_arg[0];
|
||||
|
||||
DEV_BLKCHK(context, dsql_type_ctx);
|
||||
|
||||
for (ptr = list->nod_arg, end = ptr + list->nod_count; ptr < end;
|
||||
ptr++)
|
||||
{
|
||||
DEV_BLKCHK(*ptr, dsql_type_nod);
|
||||
reference = *ptr;
|
||||
if ((*ptr)->nod_type == nod_cast)
|
||||
{
|
||||
reference = (*ptr)->nod_arg[e_cast_source];
|
||||
}
|
||||
DEV_BLKCHK(reference, dsql_type_nod);
|
||||
if (reference->nod_type == nod_dbkey &&
|
||||
rel_node == (NOD) reference->nod_arg[0] &&
|
||||
context == (CTX) rel_node->nod_arg[0])
|
||||
if (node_match(node, *ptr, TRUE))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((node->nod_type == nod_gen_id) ||
|
||||
(node->nod_type == nod_gen_id2) ||
|
||||
(node->nod_type == nod_cast)) {
|
||||
if (node->nod_count == 2)
|
||||
invalid |= invalid_reference(node->nod_arg[1], list);
|
||||
}
|
||||
else if (node->nod_type == nod_udf) {
|
||||
|
||||
NOD reference;
|
||||
BOOLEAN non_agg_field;
|
||||
|
||||
if (!list) { /* validating select element with no group by */
|
||||
if (node->nod_count == 2)
|
||||
invalid = invalid_reference (node->nod_arg [1], list);
|
||||
return invalid;
|
||||
}
|
||||
|
||||
/* does this udf appear in list of group by */
|
||||
for (ptr = list->nod_arg, end = ptr + list->nod_count; ptr < end; ptr++) {
|
||||
DEV_BLKCHK(*ptr, dsql_type_nod);
|
||||
reference = *ptr;
|
||||
if ((*ptr)->nod_type == nod_cast) {
|
||||
reference = (*ptr)->nod_arg[e_cast_source];
|
||||
}
|
||||
DEV_BLKCHK(reference, dsql_type_nod);
|
||||
if (reference->nod_type == nod_udf) {
|
||||
if (node_match (node, reference) == TRUE) {
|
||||
/* select item exists in group by */
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if we have got here this udf element is not in group by
|
||||
but it may still be valid if it has aggregate functions
|
||||
as parameters in which case it points to a list to be traversed
|
||||
if it doesn't then it is invalid
|
||||
*/
|
||||
|
||||
if (node->nod_count == 2) {
|
||||
if(aggregate_in_list (node->nod_arg [1], &non_agg_field,list) == TRUE) {
|
||||
/* abs(trunc(sum(total)+field)) is not valid in select list
|
||||
unless it also appears in the group by clause when its
|
||||
value is then known
|
||||
*/
|
||||
if (non_agg_field == TRUE) {
|
||||
invalid = TRUE;
|
||||
}
|
||||
else {
|
||||
invalid = FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
invalid = TRUE;
|
||||
}
|
||||
return invalid;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef CHECK_HAVING
|
||||
/*
|
||||
@ -2241,19 +2097,77 @@ static BOOLEAN invalid_reference( NOD node, NOD list)
|
||||
|
||||
******************************************************
|
||||
*/
|
||||
else if (node->nod_type == nod_map)
|
||||
{
|
||||
MAP map;
|
||||
map = (MAP) node->nod_arg[e_map_map];
|
||||
DEV_BLKCHK(map, dsql_type_map);
|
||||
invalid |= invalid_reference(map->map_node, list);
|
||||
}
|
||||
if (node->nod_type == nod_map)
|
||||
{
|
||||
MAP map;
|
||||
map = (MAP) node->nod_arg[e_map_map];
|
||||
DEV_BLKCHK(map, dsql_type_map);
|
||||
invalid |= invalid_reference(map->map_node, list);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
else
|
||||
switch (node->nod_type) {
|
||||
switch (node->nod_type) {
|
||||
default:
|
||||
ASSERT_FAIL;
|
||||
/* FALLINTO */
|
||||
|
||||
case nod_field:
|
||||
|
||||
/* Wouldn't it be better to call a error from this
|
||||
point where return is TRUE. Then we could give
|
||||
the fieldname that's making the trouble */
|
||||
if (!exact_field || !request)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* If we come here then this Field is used inside a
|
||||
sub-select, singular- or exists-predicate.
|
||||
The ctx_scope_level gives the info how deep the
|
||||
context is inside the request.
|
||||
So if the context-scope-level from the field is
|
||||
lower as the scope-level from the request then
|
||||
it is an invalid field */
|
||||
field_context = (CTX) node->nod_arg[e_fld_context];
|
||||
|
||||
DEV_BLKCHK(field_context, dsql_type_ctx);
|
||||
|
||||
if (field_context->ctx_scope_level <= request->req_scope_level)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case nod_gen_id:
|
||||
case nod_gen_id2:
|
||||
case nod_cast:
|
||||
case nod_udf:
|
||||
/* If there are no arguments given to the UDF then it's always valid */
|
||||
if (node->nod_count == 2)
|
||||
{
|
||||
invalid |= invalid_reference(request, node->nod_arg [1], list, exact_field);
|
||||
}
|
||||
break;
|
||||
|
||||
case nod_via:
|
||||
case nod_exists:
|
||||
case nod_singular:
|
||||
//return FALSE;
|
||||
for (ptr = node->nod_arg, end = ptr + node->nod_count;
|
||||
ptr < end; ptr++)
|
||||
{
|
||||
invalid |= invalid_reference(request, *ptr, list, TRUE);
|
||||
}
|
||||
break;
|
||||
|
||||
case nod_parameter:
|
||||
return FALSE;
|
||||
|
||||
case nod_coalesce:
|
||||
case nod_simple_case:
|
||||
case nod_searched_case:
|
||||
|
||||
case nod_add:
|
||||
case nod_concatenate:
|
||||
case nod_divide:
|
||||
@ -2263,9 +2177,6 @@ static BOOLEAN invalid_reference( NOD node, NOD list)
|
||||
case nod_subtract:
|
||||
case nod_upcase:
|
||||
case nod_extract:
|
||||
case nod_coalesce:
|
||||
case nod_simple_case:
|
||||
case nod_searched_case:
|
||||
case nod_add2:
|
||||
case nod_divide2:
|
||||
case nod_multiply2:
|
||||
@ -2302,15 +2213,14 @@ static BOOLEAN invalid_reference( NOD node, NOD list)
|
||||
case nod_starting:
|
||||
case nod_rse:
|
||||
case nod_list:
|
||||
case nod_via:
|
||||
for (ptr = node->nod_arg, end = ptr + node->nod_count;
|
||||
ptr < end; ptr++)
|
||||
invalid |= invalid_reference(*ptr, list);
|
||||
invalid |= invalid_reference(request, *ptr, list, exact_field);
|
||||
break;
|
||||
|
||||
case nod_alias:
|
||||
invalid |=
|
||||
invalid_reference(node->nod_arg[e_alias_value], list);
|
||||
invalid_reference(request, node->nod_arg[e_alias_value], list, exact_field);
|
||||
break;
|
||||
|
||||
/* An embedded aggregate, even of an expression, is OK */
|
||||
@ -2337,8 +2247,7 @@ static BOOLEAN invalid_reference( NOD node, NOD list)
|
||||
case nod_current_role:
|
||||
case nod_internal_info:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return invalid;
|
||||
}
|
||||
@ -2390,7 +2299,7 @@ static void mark_ctx_outer_join( NOD node)
|
||||
}
|
||||
|
||||
|
||||
static BOOLEAN node_match( NOD node1, NOD node2)
|
||||
static BOOLEAN node_match( NOD node1, NOD node2, BOOLEAN ignore_cast)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -2401,6 +2310,14 @@ static BOOLEAN node_match( NOD node1, NOD node2)
|
||||
* Functional description
|
||||
* Compare two nodes for equality of value.
|
||||
*
|
||||
* [2002-08-04]--- Arno Brinkman
|
||||
* If ignore_cast is TRUE and the node1 is of
|
||||
* type nod_cast then node_match is calling
|
||||
* itselfs again with the node1 CASTs source.
|
||||
* This is for allow CAST to other datatypes
|
||||
* without complaining that it's an unknown
|
||||
* column reference. (Aggeregate functions)
|
||||
*
|
||||
**************************************/
|
||||
NOD *ptr1, *ptr2, *end;
|
||||
MAP map1, map2;
|
||||
@ -2411,11 +2328,37 @@ static BOOLEAN node_match( NOD node1, NOD node2)
|
||||
DEV_BLKCHK(node2, dsql_type_nod);
|
||||
|
||||
if ((!node1) && (!node2))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ((!node1) || (!node2) || (node1->nod_type != node2->nod_type)
|
||||
|| (node1->nod_count != node2->nod_count))
|
||||
if ((!node1) || (!node2))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (ignore_cast && node1->nod_type == nod_cast)
|
||||
{
|
||||
/* If node2 is also cast and same type continue with both sources */
|
||||
if (node2->nod_type == nod_cast &&
|
||||
node1->nod_desc.dsc_dtype == node2->nod_desc.dsc_dtype &&
|
||||
node1->nod_desc.dsc_scale == node2->nod_desc.dsc_scale &&
|
||||
node1->nod_desc.dsc_length == node2->nod_desc.dsc_length &&
|
||||
node1->nod_desc.dsc_sub_type == node2->nod_desc.dsc_sub_type
|
||||
)
|
||||
{
|
||||
return node_match(node1->nod_arg[e_cast_source], node2->nod_arg[e_cast_source], ignore_cast);
|
||||
}
|
||||
else
|
||||
{
|
||||
return node_match(node1->nod_arg[e_cast_source], node2, ignore_cast);
|
||||
}
|
||||
}
|
||||
|
||||
if ((node1->nod_type != node2->nod_type) || (node1->nod_count != node2->nod_count))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* This is to get rid of assertion failures when trying
|
||||
to node_match nod_aggregate's children. This was happening because not
|
||||
@ -2436,17 +2379,28 @@ static BOOLEAN node_match( NOD node1, NOD node2)
|
||||
}
|
||||
|
||||
return node_match( node1->nod_arg[e_agg_group],
|
||||
node2->nod_arg[e_agg_group]) &&
|
||||
node2->nod_arg[e_agg_group], ignore_cast) &&
|
||||
node_match( node1->nod_arg[e_agg_rse],
|
||||
node2->nod_arg[e_agg_rse]);
|
||||
node2->nod_arg[e_agg_rse], ignore_cast);
|
||||
}
|
||||
|
||||
if (node1->nod_type == nod_alias) {
|
||||
return node_match(node1->nod_arg[e_alias_value], node2);
|
||||
if (node1->nod_type == nod_alias)
|
||||
{
|
||||
return node_match(node1->nod_arg[e_alias_value], node2, ignore_cast);
|
||||
}
|
||||
|
||||
if (node2->nod_type == nod_alias) {
|
||||
return node_match(node1, node2->nod_arg[e_alias_value]);
|
||||
if (node2->nod_type == nod_alias)
|
||||
{
|
||||
return node_match(node1, node2->nod_arg[e_alias_value], ignore_cast);
|
||||
}
|
||||
|
||||
if (node1->nod_type == nod_relation)
|
||||
{
|
||||
if (node1->nod_arg[e_rel_context] != node2->nod_arg[e_rel_context])
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (node1->nod_type == nod_field)
|
||||
@ -2459,7 +2413,7 @@ static BOOLEAN node_match( NOD node1, NOD node2)
|
||||
if (node1->nod_arg[e_fld_indices] || node2->nod_arg[e_fld_indices])
|
||||
{
|
||||
return node_match(node1->nod_arg[e_fld_indices],
|
||||
node2->nod_arg[e_fld_indices]);
|
||||
node2->nod_arg[e_fld_indices], ignore_cast);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@ -2488,7 +2442,7 @@ static BOOLEAN node_match( NOD node1, NOD node2)
|
||||
map2 = (MAP)node2->nod_arg[e_map_map];
|
||||
DEV_BLKCHK(map1, dsql_type_map);
|
||||
DEV_BLKCHK(map2, dsql_type_map);
|
||||
return node_match(map1->map_node, map2->map_node);
|
||||
return node_match(map1->map_node, map2->map_node, ignore_cast);
|
||||
}
|
||||
|
||||
if ((node1->nod_type == nod_gen_id) ||
|
||||
@ -2500,7 +2454,7 @@ static BOOLEAN node_match( NOD node1, NOD node2)
|
||||
return FALSE;
|
||||
}
|
||||
if (node1->nod_count == 2) {
|
||||
return node_match(node1->nod_arg[1], node2->nod_arg[1]);
|
||||
return node_match(node1->nod_arg[1], node2->nod_arg[1], ignore_cast);
|
||||
} else {
|
||||
return TRUE;
|
||||
}
|
||||
@ -2543,7 +2497,7 @@ static BOOLEAN node_match( NOD node1, NOD node2)
|
||||
ptr2 = node2->nod_arg;
|
||||
|
||||
for (end = ptr1 + node1->nod_count; ptr1 < end; ptr1++, ptr2++)
|
||||
if (!node_match(*ptr1, *ptr2))
|
||||
if (!node_match(*ptr1, *ptr2, ignore_cast))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
@ -2697,7 +2651,7 @@ static NOD pass1_coalesce( REQ request, NOD input, USHORT proc_flag)
|
||||
* Handle a reference to a coalesce function.
|
||||
*
|
||||
**************************************/
|
||||
NOD node;
|
||||
NOD node, *ptr, *end;
|
||||
DLLS stack;
|
||||
|
||||
DEV_BLKCHK(request, dsql_type_req);
|
||||
@ -2715,6 +2669,13 @@ static NOD pass1_coalesce( REQ request, NOD input, USHORT proc_flag)
|
||||
/* Set describer for output node */
|
||||
MAKE_desc(&node->nod_desc, node);
|
||||
|
||||
/* Set parameter-types if parameters are there */
|
||||
for (ptr = node->nod_arg[0]->nod_arg, end = ptr + node->nod_arg[0]->nod_count;
|
||||
ptr < end; ptr++)
|
||||
{
|
||||
set_parameter_type(*ptr, node, FALSE);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -3704,10 +3665,11 @@ static NOD pass1_rse( REQ request, NOD input, NOD order)
|
||||
*
|
||||
**************************************/
|
||||
NOD rse, parent_rse, target_rse, aggregate, node, list, sub, *ptr, *end,
|
||||
proj;
|
||||
proj, slist_node, *ptr2;
|
||||
DLLS stack;
|
||||
CTX parent_context;
|
||||
TSQL tdsql;
|
||||
ULONG position;
|
||||
|
||||
DEV_BLKCHK(request, dsql_type_req);
|
||||
DEV_BLKCHK(input, dsql_type_nod);
|
||||
@ -3797,8 +3759,37 @@ static NOD pass1_rse( REQ request, NOD input, NOD order)
|
||||
|
||||
/* Process GROUP BY clause, if any */
|
||||
|
||||
if (node = input->nod_arg[e_sel_group]) {
|
||||
aggregate->nod_arg[e_agg_group] = PASS1_node(request, node, 0);
|
||||
if (node = input->nod_arg[e_sel_group])
|
||||
{
|
||||
/* if there are positions in the group by clause then replace them
|
||||
by the (newly pass) items from the select_list */
|
||||
aggregate->nod_arg[e_agg_group] = MAKE_node(node->nod_type,node->nod_count);
|
||||
ptr2 = aggregate->nod_arg[e_agg_group]->nod_arg;
|
||||
for (ptr = node->nod_arg, end = ptr + node->nod_count; ptr < end; ptr++, ptr2++)
|
||||
{
|
||||
sub = *ptr;
|
||||
if (sub->nod_type == nod_position)
|
||||
{
|
||||
if ((slist_node = input->nod_arg[e_sel_list]) &&
|
||||
(slist_node->nod_type == nod_list))
|
||||
{
|
||||
/* an select list is there */
|
||||
position = (ULONG) (sub->nod_arg[0]);
|
||||
if ((position < 1) || (position > (ULONG) slist_node->nod_count))
|
||||
{
|
||||
/* !! This error should be replaced by an good GROUP BY clause error !! */
|
||||
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 104,
|
||||
gds_arg_gds, gds_dsql_command_err,
|
||||
gds_arg_gds, gds_field_aggregate_err, 0);
|
||||
}
|
||||
*ptr2 = PASS1_node(request, slist_node->nod_arg[position - 1], 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr2 = PASS1_node(request, sub, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (parent_context)
|
||||
@ -3819,7 +3810,7 @@ static NOD pass1_rse( REQ request, NOD input, NOD order)
|
||||
if (aggregate)
|
||||
for (ptr = list->nod_arg, end = ptr + list->nod_count; ptr < end;
|
||||
ptr++)
|
||||
if (invalid_reference(*ptr, aggregate->nod_arg[e_agg_group]))
|
||||
if (invalid_reference(request, *ptr, aggregate->nod_arg[e_agg_group], FALSE))
|
||||
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 104,
|
||||
gds_arg_gds, gds_field_ref_err,
|
||||
/* invalid field reference */
|
||||
@ -3922,7 +3913,7 @@ static NOD pass1_searched_case( REQ request, NOD input, USHORT proc_flag)
|
||||
DEV_BLKCHK(input, dsql_type_nod);
|
||||
DEV_BLKCHK(input->nod_arg[0], dsql_type_nod);
|
||||
|
||||
node = MAKE_node(nod_searched_case, 3);
|
||||
node = MAKE_node(nod_searched_case, 2);
|
||||
|
||||
list = input->nod_arg[0];
|
||||
|
||||
@ -3947,6 +3938,14 @@ static NOD pass1_searched_case( REQ request, NOD input, USHORT proc_flag)
|
||||
/* Set describer for output node */
|
||||
MAKE_desc(&node->nod_desc, node);
|
||||
|
||||
/* Set parameter-types if parameters are there */
|
||||
for (ptr = node->nod_arg[e_searched_case_search_conditions]->nod_arg,
|
||||
end = ptr + node->nod_arg[e_searched_case_search_conditions]->nod_count;
|
||||
ptr < end; ptr++)
|
||||
{
|
||||
set_parameter_type(*ptr, node, FALSE);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -4046,6 +4045,15 @@ static NOD pass1_simple_case( REQ request, NOD input, USHORT proc_flag)
|
||||
/* Set describer for output node */
|
||||
MAKE_desc(&node->nod_desc, node);
|
||||
|
||||
/* Set parameter-types if parameters are there */
|
||||
set_parameter_type(node->nod_arg[e_simple_case_case_operand], node, FALSE);
|
||||
for (ptr = node->nod_arg[e_simple_case_results]->nod_arg,
|
||||
end = ptr + node->nod_arg[e_simple_case_results]->nod_count;
|
||||
ptr < end; ptr++)
|
||||
{
|
||||
set_parameter_type(*ptr, node, FALSE);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -4545,7 +4553,7 @@ static NOD post_map( NOD node, CTX context)
|
||||
/* Check to see if the item has already been posted */
|
||||
|
||||
for (map_ = context->ctx_map, count = 0; map_; map_ = map_->map_next, count++)
|
||||
if (node_match(node, map_->map_node))
|
||||
if (node_match(node, map_->map_node, FALSE))
|
||||
break;
|
||||
|
||||
if (!map_) {
|
||||
|
@ -19,7 +19,7 @@
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
* $Id: show.epp,v 1.5 2002-06-29 13:39:11 skywalker Exp $
|
||||
* $Id: show.epp,v 1.6 2002-08-11 08:04:54 dimitr Exp $
|
||||
* Revision 1.2 2000/11/19 07:02:49 fsg
|
||||
* Change in show.e to use CHARACTER_LENGTH instead of FIELD_LENGTH in
|
||||
* SHOW PROCEDURE
|
||||
@ -135,7 +135,7 @@ extern "C" CONST SQLTYPES Column_types[] = {
|
||||
{blr_sql_time, "TIME"}, /* NTX: keyword */
|
||||
{blr_sql_date, "DATE"}, /* NTX: keyword */
|
||||
{blr_timestamp, "TIMESTAMP"}, /* NTX: keyword */
|
||||
{blr_int64, "INT64"}, /* NTX: keyword */
|
||||
{blr_int64, "BIGINT"}, /* NTX: keyword */
|
||||
{0, ""}
|
||||
};
|
||||
|
||||
|
@ -31,6 +31,8 @@
|
||||
* and complain if the grantee ROLE doesn't exist.
|
||||
* 2001.10.06 Claudio Valderrama: Forbid "NONE" from role-related operations.
|
||||
* Honor explicit USER keyword in GRANTs and REVOKEs.
|
||||
*
|
||||
* 2002.08.10 Dmitry Yemanov: ALTER VIEW
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
@ -409,6 +411,10 @@ TEXT * function_name, TEXT * procedure_name)
|
||||
DYN_modify_relation(gbl, ptr);
|
||||
break;
|
||||
|
||||
case gds_dyn_mod_view:
|
||||
DYN_modify_view(gbl, ptr);
|
||||
break;
|
||||
|
||||
case gds_dyn_delete_rel:
|
||||
DYN_delete_relation(gbl, ptr, relation_name);
|
||||
break;
|
||||
|
@ -30,7 +30,7 @@
|
||||
* indexes that support unique constraints or primary keys.
|
||||
* 26-Sep-2001 Paul Beach - External File Directory Config. Parameter
|
||||
* 2002-02-24 Sean Leyne - Code Cleanup of old Win 3.1 port (WINDOWS_ONLY)
|
||||
*
|
||||
* 2002.08.10 Dmitry Yemanov: ALTER VIEW
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
@ -4171,8 +4171,9 @@ void DYN_define_view_relation( GBL gbl, UCHAR ** ptr, TEXT * view)
|
||||
TDBB tdbb = GET_THREAD_DATA;
|
||||
DBB dbb = tdbb->tdbb_database;
|
||||
|
||||
VOLATILE BLK request;
|
||||
VOLATILE BLK request, old_request;
|
||||
UCHAR verb;
|
||||
VOLATILE SSHORT id, old_id;
|
||||
|
||||
MET_exact_name(view);
|
||||
if (!view[0])
|
||||
@ -4180,11 +4181,31 @@ void DYN_define_view_relation( GBL gbl, UCHAR ** ptr, TEXT * view)
|
||||
/* msg 212: "Zero length identifiers not allowed" */
|
||||
|
||||
request = (BLK) CMP_find_request(tdbb, drq_s_view_rels, DYN_REQUESTS);
|
||||
id = drq_s_view_rels;
|
||||
|
||||
bool b_ending_store = false;
|
||||
|
||||
try {
|
||||
|
||||
old_request = request, old_id = id;
|
||||
|
||||
request = (BLK) CMP_find_request(tdbb, drq_e_view_rels, DYN_REQUESTS);
|
||||
id = drq_e_view_rels;
|
||||
|
||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
|
||||
VRL IN RDB$VIEW_RELATIONS WITH VRL.RDB$VIEW_NAME EQ view
|
||||
|
||||
if (!DYN_REQUEST(drq_e_view_rels))
|
||||
DYN_REQUEST(drq_e_view_rels) = request;
|
||||
|
||||
ERASE VRL;
|
||||
END_FOR;
|
||||
|
||||
if (!DYN_REQUEST(drq_e_view_rels))
|
||||
DYN_REQUEST(drq_e_view_rels) = request;
|
||||
|
||||
request = old_request, id = old_id;
|
||||
|
||||
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
|
||||
VRL IN RDB$VIEW_RELATIONS
|
||||
strcpy(VRL.RDB$VIEW_NAME, view);
|
||||
@ -4221,9 +4242,17 @@ void DYN_define_view_relation( GBL gbl, UCHAR ** ptr, TEXT * view)
|
||||
}
|
||||
catch (std::exception&) {
|
||||
if (b_ending_store) {
|
||||
DYN_rundown_request(request, drq_s_view_rels);
|
||||
DYN_error_punt(TRUE, 34, NULL, NULL, NULL, NULL, NULL);
|
||||
/* msg 34: "STORE RDB$VIEW_RELATIONS failed" */
|
||||
DYN_rundown_request(request, id);
|
||||
if (id == drq_s_view_rels)
|
||||
{
|
||||
DYN_error_punt(TRUE, 34, NULL, NULL, NULL, NULL, NULL);
|
||||
/* msg 34: "STORE RDB$VIEW_RELATIONS failed" */
|
||||
}
|
||||
else if (id == drq_e_view_rels)
|
||||
{
|
||||
DYN_error_punt(TRUE, 59, NULL, NULL, NULL, NULL, NULL);
|
||||
/* msg 59: "ERASE RDB$VIEW_RELATIONS failed" */
|
||||
}
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ extern void DYN_modify_relation(GBL, UCHAR **);
|
||||
extern void DYN_modify_trigger(GBL, UCHAR **);
|
||||
extern void DYN_modify_trigger_msg(GBL, UCHAR **, TEXT *);
|
||||
extern void DYN_modify_sql_field(GBL, UCHAR**, TEXT*, TEXT*);
|
||||
extern void DYN_modify_view(GBL, UCHAR **);
|
||||
|
||||
|
||||
#endif /* _JRD_DYN_MD_PROTO_H_ */
|
||||
|
@ -33,7 +33,7 @@
|
||||
* 2001.10.08 Claudio Valderrama: put a comment with suggested code to hide
|
||||
* special non-system triggers from user manipulation.
|
||||
* 2002-02-24 Sean Leyne - Code Cleanup of old Win 3.1 port (WINDOWS_ONLY)
|
||||
*
|
||||
* 2002.08.10 Dmitry Yemanov: ALTER VIEW
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
@ -1750,6 +1750,111 @@ void DYN_modify_trigger_msg( GBL gbl, UCHAR ** ptr, TEXT * trigger_name)
|
||||
}
|
||||
|
||||
|
||||
void DYN_modify_view( GBL gbl, UCHAR ** ptr)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* D Y N _ m o d i f y _ v i e w
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Execute a dynamic ddl statement.
|
||||
*
|
||||
**************************************/
|
||||
TDBB tdbb;
|
||||
DBB dbb;
|
||||
BLK request;
|
||||
UCHAR verb;
|
||||
USHORT found;
|
||||
TEXT view_name[32];
|
||||
|
||||
tdbb = GET_THREAD_DATA;
|
||||
dbb = tdbb->tdbb_database;
|
||||
|
||||
view_name[0] = 0;
|
||||
GET_STRING(ptr, view_name);
|
||||
|
||||
MET_exact_name(view_name);
|
||||
if (!view_name[0])
|
||||
DYN_error_punt(FALSE, 212, NULL, NULL, NULL, NULL, NULL);
|
||||
/* msg 212: "Zero length identifiers not allowed" */
|
||||
|
||||
try {
|
||||
|
||||
request = (BLK) CMP_find_request(tdbb, drq_m_relation, DYN_REQUESTS);
|
||||
|
||||
found = FALSE;
|
||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
|
||||
VRL IN RDB$VIEW_RELATIONS CROSS REL IN RDB$RELATIONS
|
||||
WITH VRL.RDB$VIEW_NAME EQ REL.RDB$RELATION_NAME AND
|
||||
VRL.RDB$VIEW_NAME EQ view_name
|
||||
|
||||
if (!DYN_REQUEST(drq_m_relation))
|
||||
DYN_REQUEST(drq_m_relation) = request;
|
||||
|
||||
found = TRUE;
|
||||
MODIFY REL
|
||||
REL.RDB$SYSTEM_FLAG.NULL = TRUE;
|
||||
REL.RDB$VIEW_BLR.NULL = TRUE;
|
||||
REL.RDB$VIEW_SOURCE.NULL = TRUE;
|
||||
REL.RDB$SECURITY_CLASS.NULL = TRUE;
|
||||
|
||||
while ((verb = *(*ptr)++) != gds_dyn_end)
|
||||
switch (verb)
|
||||
{
|
||||
case gds_dyn_system_flag:
|
||||
REL.RDB$SYSTEM_FLAG = DYN_get_number(ptr);
|
||||
REL.RDB$SYSTEM_FLAG.NULL = FALSE;
|
||||
break;
|
||||
|
||||
case gds_dyn_view_blr:
|
||||
DYN_put_blr_blob(gbl, ptr, &REL.RDB$VIEW_BLR);
|
||||
REL.RDB$VIEW_BLR.NULL = FALSE;
|
||||
break;
|
||||
|
||||
case gds_dyn_view_source:
|
||||
DYN_put_text_blob(gbl, ptr, &REL.RDB$VIEW_SOURCE);
|
||||
REL.RDB$VIEW_SOURCE.NULL = FALSE;
|
||||
break;
|
||||
|
||||
#if (defined JPN_SJIS || defined JPN_EUC)
|
||||
case gds_dyn_view_source2:
|
||||
DYN_put_text_blob2(gbl, ptr, &REL.RDB$VIEW_SOURCE);
|
||||
REL.RDB$VIEW_SOURCE.NULL = FALSE;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case gds_dyn_security_class:
|
||||
GET_STRING(ptr, REL.RDB$SECURITY_CLASS);
|
||||
REL.RDB$SECURITY_CLASS.NULL = FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
--(*ptr);
|
||||
DYN_execute(gbl, ptr, REL.RDB$RELATION_NAME, (TEXT*)NULL_PTR,
|
||||
(TEXT*)NULL_PTR, (TEXT*)NULL_PTR, (TEXT*)NULL_PTR);
|
||||
}
|
||||
END_MODIFY;
|
||||
END_FOR;
|
||||
|
||||
if (!DYN_REQUEST(drq_m_relation))
|
||||
DYN_REQUEST(drq_m_relation) = request;
|
||||
|
||||
}
|
||||
catch (...) {
|
||||
DYN_rundown_request(request, -1);
|
||||
DYN_error_punt(TRUE, 99, NULL, NULL, NULL, NULL, NULL);
|
||||
/* msg 99: "MODIFY RDB$RELATIONS failed" */
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
DYN_error_punt(FALSE, 61, NULL, NULL, NULL, NULL, NULL);
|
||||
/* msg 61: "Relation not found" */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void drop_cache( GBL gbl)
|
||||
{
|
||||
/**************************************
|
||||
|
Loading…
Reference in New Issue
Block a user