1
//____________________________________________________________
3
// PROGRAM: C Preprocessor
5
// DESCRIPTION: SQL expression parser
7
// The contents of this file are subject to the Interbase Public
8
// License Version 1.0 (the "License"); you may not use this file
9
// except in compliance with the License. You may obtain a copy
10
// of the License at http://www.Inprise.com/IPL.html
12
// Software distributed under the License is distributed on an
13
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
14
// or implied. See the License for the specific language governing
15
// rights and limitations under the License.
17
// The Original Code was created by Inprise Corporation
18
// and its predecessors. Portions created by Inprise Corporation are
19
// Copyright (C) Inprise Corporation.
21
// All Rights Reserved.
22
// Contributor(s): ______________________________________.
23
// Revision 1.3 2000/11/16 15:54:29 fsg
24
// Added new switch -verbose to gpre that will dump
25
// parsed lines to stderr
27
// Fixed gpre bug in handling row names in WHERE clauses
28
// that are reserved words now (DATE etc)
29
// (this caused gpre to dump core when parsing tan.e)
31
// Fixed gpre bug in handling lower case table aliases
32
// in WHERE clauses for sql dialect 2 and 3.
33
// (cause a core dump in a test case from C.R. Zamana)
35
// TMN (Mike Nordell) 11.APR.2001 - Reduce compiler warnings
37
// 2006.10.12 Stephen W. Boyd - Added support for FOR UPDATE WITH LOCK
38
// 2007.05.23 Stephen W. Boyd - Added support for FIRST / SKIP clauses
39
// 2007.06.15 Stephen W. Boyd - Added support for CURRENT_CONNECTION, CURRENT_ROLE,
40
// CURRENT_TRANSACTION and CURRENT_USER context variables.
42
//____________________________________________________________
49
#include "../gpre/gpre.h"
50
#include "../gpre/parse.h"
51
#include "../gpre/cme_proto.h"
52
#include "../gpre/cmp_proto.h"
53
#include "../gpre/exp_proto.h"
54
#include "../gpre/gpre_proto.h"
55
#include "../gpre/hsh_proto.h"
56
#include "../gpre/gpre_meta.h"
57
#include "../gpre/msc_proto.h"
58
#include "../gpre/par_proto.h"
59
#include "../gpre/sqe_proto.h"
60
#include "../gpre/sql_proto.h"
61
#include "../common/utils_proto.h"
65
gpre_ctx* req_contexts;
66
USHORT req_scope_level; // scope level for SQL subquery parsing
67
USHORT req_in_aggregate; // now processing value expr for aggr
68
USHORT req_in_select_list; // processing select list
69
USHORT req_in_where_clause; // processing where clause
70
USHORT req_in_having_clause; // processing having clause
71
USHORT req_in_order_by_clause; // processing order by clause
72
USHORT req_in_subselect; // processing a subselect clause
75
static bool compare_expr(GPRE_NOD, GPRE_NOD);
76
static GPRE_NOD copy_fields(GPRE_NOD, map*);
77
static GPRE_NOD explode_asterisk(GPRE_NOD, int, gpre_rse*);
78
static GPRE_NOD explode_asterisk_all(GPRE_NOD, int, gpre_rse*, bool);
79
static gpre_fld* get_ref(GPRE_NOD);
80
static GPRE_NOD implicit_any(gpre_req*, GPRE_NOD, enum nod_t, enum nod_t);
81
static GPRE_NOD merge(GPRE_NOD, GPRE_NOD);
82
static GPRE_NOD merge_fields(GPRE_NOD, GPRE_NOD, int, bool);
83
static GPRE_NOD negate(GPRE_NOD);
84
static void pair(GPRE_NOD, GPRE_NOD);
85
static gpre_ctx* par_alias_list(gpre_req*, GPRE_NOD);
86
static gpre_ctx* par_alias(gpre_req*, const TEXT*);
87
static GPRE_NOD par_and(gpre_req*, USHORT *);
88
static gpre_rel* par_base_table(gpre_req*, const gpre_rel*, const TEXT*);
89
static GPRE_NOD par_collate(gpre_req*, GPRE_NOD);
90
static GPRE_NOD par_in(gpre_req*, GPRE_NOD);
91
static gpre_ctx* par_joined_relation(gpre_req*, gpre_ctx*);
92
static gpre_ctx* par_join_clause(gpre_req*, gpre_ctx*);
93
static NOD_T par_join_type(void);
94
static GPRE_NOD par_multiply(gpre_req*, bool, USHORT *, bool *);
95
static GPRE_NOD par_not(gpre_req*, USHORT *);
96
static void par_order(gpre_req*, gpre_rse*, bool, bool);
97
static GPRE_NOD par_plan(gpre_req*);
98
static GPRE_NOD par_plan_item(gpre_req*, bool, USHORT *, bool *);
99
static GPRE_NOD par_primitive_value(gpre_req*, bool, USHORT *, bool *);
100
static GPRE_NOD par_relational(gpre_req*, USHORT *);
101
static gpre_rse* par_rse(gpre_req*, GPRE_NOD, bool);
102
static gpre_rse* par_select(gpre_req*, gpre_rse*);
103
static GPRE_NOD par_stat(gpre_req*);
104
static GPRE_NOD par_subscript(gpre_req*);
105
static void par_terminating_parens(USHORT *, USHORT *);
106
static GPRE_NOD par_udf(gpre_req*);
107
static GPRE_NOD par_udf_or_field(gpre_req*, bool);
108
static GPRE_NOD par_udf_or_field_with_collate(gpre_req*, bool, USHORT *, bool *);
109
static void par_update(gpre_rse*, bool, bool);
110
static GPRE_NOD post_fields(GPRE_NOD, map*);
111
static GPRE_NOD post_map(GPRE_NOD, MAP);
112
static GPRE_NOD post_select_list(GPRE_NOD, map*);
113
static void pop_scope(gpre_req*, scope*);
114
static void push_scope(gpre_req*, scope*);
115
static gpre_fld* resolve(GPRE_NOD, gpre_ctx*, gpre_ctx**, act**);
116
static bool resolve_fields(GPRE_NOD& fields, gpre_req* request, gpre_rse* selection);
117
static gpre_ctx* resolve_asterisk(TOK, gpre_rse*);
118
static void set_ref(GPRE_NOD, gpre_fld*);
119
static char* upcase_string(const char*);
120
static bool validate_references(const gpre_nod*, const gpre_nod*);
128
enum nod_t rel_negation;
131
static const ops rel_ops[] =
133
{ nod_eq, KW_EQ, nod_ne },
134
{ nod_eq, KW_EQUALS, nod_ne },
135
{ nod_ne, KW_NE, nod_eq },
136
{ nod_gt, KW_GT, nod_le },
137
{ nod_ge, KW_GE, nod_lt },
138
{ nod_le, KW_LE, nod_gt },
139
{ nod_lt, KW_LT, nod_ge },
140
{ nod_containing, KW_CONTAINING, nod_any },
141
{ nod_starting, KW_STARTING, nod_any },
142
{ nod_matches, KW_MATCHES, nod_any },
143
{ nod_any, KW_none, nod_any },
144
{ nod_ansi_any, KW_none, nod_ansi_any },
145
{ nod_ansi_all, KW_none, nod_ansi_all }
148
#ifdef NOT_USED_OR_REPLACED
149
static const ops scalar_stat_ops[] = {
150
{ nod_count, KW_COUNT, nod_any },
151
{ nod_max, KW_MAX, nod_any },
152
{ nod_min, KW_MIN, nod_any },
153
{ nod_total, KW_TOTAL, nod_any },
154
{ nod_total, KW_SUM, nod_any },
155
{ nod_average, KW_AVERAGE, nod_any },
156
{ nod_via, KW_none, nod_any}
160
static const ops stat_ops[] = {
161
{ nod_agg_count, KW_COUNT, nod_any },
162
{ nod_agg_max, KW_MAX, nod_any },
163
{ nod_agg_min, KW_MIN, nod_any },
164
{ nod_agg_total, KW_TOTAL, nod_any },
165
{ nod_agg_total, KW_SUM, nod_any },
166
{ nod_agg_average, KW_AVERAGE, nod_any },
167
{ nod_any, KW_none, nod_any },
168
{ nod_ansi_any, KW_none, nod_ansi_any },
169
{ nod_ansi_all, KW_none, nod_ansi_all }
172
static const NOD_T relationals[] = {
173
nod_eq, nod_ne, nod_gt, nod_ge, nod_le, nod_lt, nod_containing,
174
nod_starting, nod_matches, nod_any, nod_missing, nod_between, nod_like,
175
nod_and, nod_or, nod_not, nod_ansi_any, nod_ansi_all, (NOD_T) 0
179
//____________________________________________________________
181
// Parse an OR boolean expression.
184
GPRE_NOD SQE_boolean( gpre_req* request, USHORT * paren_count)
188
assert_IS_REQ(request);
192
paren_count = &local_count;
195
gpre_nod* expr1 = par_and(request, paren_count);
197
if (!MSC_match(KW_OR) && !MSC_match(KW_OR1)) {
198
par_terminating_parens(paren_count, &local_count);
202
expr1 = MSC_binary(nod_or, expr1, SQE_boolean(request, paren_count));
203
par_terminating_parens(paren_count, &local_count);
209
//____________________________________________________________
211
// Parse a reference to a relation name
212
// and generate a context for it.
215
gpre_ctx* SQE_context(gpre_req* request)
217
SCHAR r_name[NAME_SIZE], db_name[NAME_SIZE], owner_name[NAME_SIZE];
218
SCHAR s[ERROR_LENGTH];
220
assert_IS_REQ(request);
222
gpre_ctx* context = MSC_context(request);
223
SQL_relation_name(r_name, db_name, owner_name);
225
if (!(context->ctx_relation =
226
SQL_relation(request, r_name, db_name, owner_name, false)))
228
// check for a procedure
229
gpre_prc* procedure = context->ctx_procedure =
230
SQL_procedure(request, r_name, db_name, owner_name, false);
233
if (procedure->prc_inputs) {
234
if (!MSC_match(KW_LEFT_PAREN))
235
CPR_s_error("( <procedure input parameters> )");
236
// parse input references
237
context->ctx_prc_inputs = SQE_list(SQE_value, request, false);
238
USHORT local_count = 1;
239
par_terminating_parens(&local_count, &local_count);
240
if (procedure->prc_in_count !=
241
context->ctx_prc_inputs->nod_count)
243
PAR_error("count of input values doesn't match count of parameters");
245
gpre_nod** input = context->ctx_prc_inputs->nod_arg;
246
for (gpre_fld* field = procedure->prc_inputs; field;
247
input++, field = field->fld_next)
249
SQE_post_field(*input, field);
255
sprintf(s, "table %s.%s not defined", owner_name, r_name);
257
sprintf(s, "table %s not defined", r_name);
263
// If the next token is recognized as a keyword, it can't be a SQL "alias".
264
// It may, however, be an "end of line" token. If so, trade it in on the
265
// next "real" token.
267
gpre_sym* symbol = gpreGlob.token_global.tok_symbol;
268
if (symbol && symbol->sym_type == SYM_keyword) {
269
if (!gpreGlob.token_global.tok_length)
274
// we have what we assume to be an alias; check to make sure that
275
// it does not conflict with any relation, procedure or context names
276
// at the same scoping level in this query
279
for (conflict = request->req_contexts; conflict;
280
conflict = conflict->ctx_next)
282
if ((symbol = conflict->ctx_symbol)
283
&& (symbol->sym_type == SYM_relation
284
|| symbol->sym_type == SYM_context
285
|| symbol->sym_type == SYM_procedure)
286
&& (!strcmp(symbol->sym_string, gpreGlob.token_global.tok_string))
287
&& (conflict->ctx_scope_level == request-> req_scope_level))
294
const char* error_type;
295
if (symbol->sym_type == SYM_relation)
296
error_type = "table";
297
else if (symbol->sym_type == SYM_procedure)
298
error_type = "procedure";
300
error_type = "context";
302
fb_utils::snprintf(s, sizeof(s),
303
"context %s conflicts with a %s in the same statement",
304
gpreGlob.token_global.tok_string, error_type);
308
symbol = MSC_symbol(SYM_context, gpreGlob.token_global.tok_string, gpreGlob.token_global.tok_length, 0);
309
symbol->sym_object = context;
310
context->ctx_symbol = symbol;
311
context->ctx_alias = symbol->sym_name;
320
//____________________________________________________________
322
// Parse an item is a select list. This is particularly nasty
323
// since neither the relations nor context variables have been
324
// processed yet. So, rather than generating a simple field
325
// reference, make up a more or less dummy block containing
326
// a pointer to a field system and possible a qualifier symbol.
327
// this will be turned into a reference later.
330
GPRE_NOD SQE_field(gpre_req* request,
336
assert_IS_REQ(request);
338
gpre_lls* upper_dim = NULL;
339
gpre_lls* lower_dim = NULL;
341
hold_token.tok_type = tok_t(0);
343
if (aster_ok && MSC_match(KW_ASTERISK)) {
344
node = MSC_node(nod_asterisk, 1);
348
// if the token isn't an identifier, complain
350
SQL_resolve_identifier("<column name>", NULL, NAME_SIZE);
352
// For domains we can't be resolving tokens to field names
353
// in the CHECK constraint.
355
TEXT s[ERROR_LENGTH];
359
request->req_type == REQ_ddl &&
360
(action = request->req_actions) &&
361
(action->act_type == ACT_create_domain ||
362
action->act_type == ACT_alter_domain))
364
fb_utils::snprintf(s, sizeof(s),
365
"Illegal use of identifier: %s in domain constraint",
366
gpreGlob.token_global.tok_string);
371
// Note: We *always* want to make a deferred name block - to handle
372
// scoping of alias names in subselects properly, when we haven't
373
// seen the list of relations (& aliases for them). This occurs
374
// during the select list, but by the time we see the having, group,
375
// order, or where we do know all aliases and should be able to
377
// Note that the case of request == NULL should never
378
// occur, and request->req_contexts == NULL should only
379
// occur for the very first select list in a request.
380
// 1994-October-03 David Schnepper
383
// if the request is null, make a deferred name block
385
if (!request || !request->req_contexts || request->req_in_select_list) {
386
node = MSC_node(nod_deferred, 3);
388
TOK f_token = (TOK) MSC_alloc(TOK_LEN);
389
node->nod_arg[0] = (GPRE_NOD) f_token;
390
f_token->tok_length = gpreGlob.token_global.tok_length;
391
SQL_resolve_identifier("<identifier>", f_token->tok_string, f_token->tok_length + 1);
394
if (MSC_match(KW_DOT)) {
395
if ((int) gpreGlob.token_global.tok_keyword == (int) KW_ASTERISK) {
397
node->nod_type = nod_asterisk;
399
PAR_error("* not allowed");
402
node->nod_arg[1] = node->nod_arg[0];
403
f_token = (TOK) MSC_alloc(TOK_LEN);
404
node->nod_arg[0] = (GPRE_NOD) f_token;
405
f_token->tok_length = gpreGlob.token_global.tok_length;
406
SQL_resolve_identifier("<identifier>", f_token->tok_string, f_token->tok_length + 1);
410
if (MSC_match(KW_L_BRCKET)) {
411
// We have a complete array or an array slice here
413
if (!MSC_match(KW_R_BRCKET)) {
414
slice_req = MSC_request(REQ_slice);
418
gpre_nod* tail = par_subscript(slice_req);
419
MSC_push(tail, &lower_dim);
420
if (MSC_match(KW_COLON)) {
421
// if (!MSC_match (KW_DOT))
422
// CPR_s_error ("<period>");
423
tail = par_subscript(slice_req);
424
MSC_push(tail, &upper_dim);
427
MSC_push(tail, &upper_dim);
428
} while (MSC_match(KW_COMMA));
430
if (!MSC_match(KW_R_BRCKET))
431
CPR_s_error("<right bracket>");
432
slc* slice = (slc*) MSC_alloc(SLC_LEN(count));
433
slice_req->req_slice = slice;
434
slc::slc_repeat* tail_ptr = &slice->slc_rpt[count];
435
slice->slc_dimensions = count;
436
slice->slc_parent_request = request;
439
tail_ptr->slc_lower = MSC_pop(&lower_dim);
440
tail_ptr->slc_upper = MSC_pop(&upper_dim);
442
node->nod_arg[2] = (GPRE_NOD) slice_req;
444
/* added this to assign the correct nod_count
445
The nod type is converted to nod_field in SQE_resolve()
446
The nod_count is check to confirm if the array slice
447
has been initialized in cmd.cpp
452
slice_req = (gpre_req*) MSC_alloc(REQ_LEN);
453
slice_req->req_type = REQ_slice;
454
node->nod_arg[2] = (GPRE_NOD) slice_req;
462
ref* reference = (REF) MSC_alloc(REF_LEN);
463
node = MSC_unary(nod_field, (GPRE_NOD) reference);
465
gpre_sym* symbol = gpreGlob.token_global.tok_symbol;
467
/* if there is a homonym which is a context, use the context;
468
otherwise we may match with a relation or procedure which
469
is not in the request, resulting in a bogus error */
471
if (symbol->sym_type != SYM_field) {
472
for (gpre_sym* temp_symbol = symbol; temp_symbol;
473
temp_symbol = temp_symbol->sym_homonym)
475
if (temp_symbol->sym_type == SYM_context) {
476
symbol = temp_symbol;
479
else if (temp_symbol->sym_type == SYM_relation) {
480
symbol = temp_symbol;
483
else if (temp_symbol->sym_type == SYM_procedure) {
484
if (symbol->sym_type == SYM_relation)
487
symbol = temp_symbol;
493
if (symbol->sym_type == SYM_context) {
494
context = symbol->sym_object;
496
if (!MSC_match(KW_DOT))
497
CPR_s_error("<period> in qualified column");
498
if (context->ctx_request != request)
499
PAR_error("context not part of this request");
500
SQL_resolve_identifier("<Column Name>", NULL, NAME_SIZE);
502
(reference->ref_field =
503
MET_context_field(context, gpreGlob.token_global.tok_string)))
505
sprintf(s, "column \"%s\" not in context",
506
gpreGlob.token_global.tok_string);
509
if (SQL_DIALECT_V5 == gpreGlob.sw_sql_dialect) {
510
const USHORT field_dtype = reference->ref_field->fld_dtype;
511
if ((dtype_sql_date == field_dtype) ||
512
(dtype_sql_time == field_dtype) ||
513
(dtype_int64 == field_dtype))
515
SQL_dialect1_bad_type(field_dtype);
518
reference->ref_context = context;
522
else if (symbol->sym_type == SYM_relation) {
523
const gpre_rel* relation = (gpre_rel*) symbol->sym_object;
524
if (relation->rel_database != request->req_database)
525
PAR_error("table not in appropriate database");
529
/* if we do not see a KW_DOT, perhaps what we think is a relation
530
** is actually a column with the same name as the relation in
531
** the HSH table. if so...skip down to the end of the routine
532
** and find out if we do have such a column. but first, since
533
** we just did a CPR_token, we have to move prior_token into
534
** current token, and hold the current token for later.
537
if (!MSC_match(KW_DOT)) {
538
hold_token = gpreGlob.token_global;
539
gpreGlob.token_global = gpreGlob.prior_token;
540
gpreGlob.token_global.tok_symbol = 0;
543
/** We've got the column name. resolve it **/
544
SQL_resolve_identifier("<Columnn Name>", NULL, NAME_SIZE);
545
for (context = request->req_contexts; context;
546
context = context->ctx_next)
548
if (context->ctx_relation == relation &&
549
(reference->ref_field =
550
MET_field(context->ctx_relation,
551
gpreGlob.token_global.tok_string)))
553
if (SQL_DIALECT_V5 == gpreGlob.sw_sql_dialect) {
554
const USHORT field_dtype = reference->ref_field->fld_dtype;
555
if ((dtype_sql_date == field_dtype) ||
556
(dtype_sql_time == field_dtype) ||
557
(dtype_int64 == field_dtype))
559
SQL_dialect1_bad_type(field_dtype);
562
reference->ref_context = context;
564
if (reference->ref_field->fld_array_info) {
566
EXP_array(request, reference->ref_field,
568
node->nod_arg[0] = (GPRE_NOD) reference;
574
fb_utils::snprintf(s, sizeof(s),
575
"column \"%s\" not in context",
576
gpreGlob.token_global.tok_string);
580
else if (symbol->sym_type == SYM_procedure) {
581
const gpre_prc* procedure = (gpre_prc*) symbol->sym_object;
582
if (procedure->prc_database != request->req_database)
583
PAR_error("procedure not in appropriate database");
585
if (!MSC_match(KW_DOT))
586
CPR_s_error("<period> in qualified column");
587
SQL_resolve_identifier("<Column Name>", NULL, NAME_SIZE);
588
for (context = request->req_contexts; context;
589
context = context->ctx_next)
591
if (context->ctx_procedure == procedure &&
592
(reference->ref_field =
593
MET_context_field(context, gpreGlob.token_global.tok_string)))
595
if (SQL_DIALECT_V5 == gpreGlob.sw_sql_dialect) {
596
const USHORT field_dtype = reference->ref_field->fld_dtype;
597
if ((dtype_sql_date == field_dtype) ||
598
(dtype_sql_time == field_dtype) ||
599
(dtype_int64 == field_dtype))
601
SQL_dialect1_bad_type(field_dtype);
604
reference->ref_context = context;
605
if (reference->ref_field->fld_array_info) {
607
EXP_array(request, reference->ref_field, true,
609
node->nod_arg[0] = (GPRE_NOD) reference;
616
fb_utils::snprintf(s, sizeof(s),
617
"column \"%s\" not in context", gpreGlob.token_global.tok_string);
623
// Hmmm. So it wasn't a qualified field. Try any field.
625
SQL_resolve_identifier("<Column Name>", NULL, NAME_SIZE);
626
for (context = request->req_contexts; context;
627
context = context->ctx_next)
629
if (reference->ref_field = MET_context_field(context,
630
gpreGlob.token_global.tok_string))
632
if (SQL_DIALECT_V5 == gpreGlob.sw_sql_dialect) {
633
const USHORT field_dtype = reference->ref_field->fld_dtype;
634
if ((dtype_sql_date == field_dtype) ||
635
(dtype_sql_time == field_dtype) ||
636
(dtype_int64 == field_dtype))
638
SQL_dialect1_bad_type(field_dtype);
641
reference->ref_context = context;
643
/* if we skipped down from the SYM_relation case above, we need to
644
** switch token and prior_token back to their original values to
647
if (hold_token.tok_type != 0) {
648
gpreGlob.prior_token = gpreGlob.token_global;
649
gpreGlob.token_global = hold_token;
653
if (reference->ref_field->fld_array_info) {
654
node = EXP_array(request, reference->ref_field, true, true);
655
node->nod_arg[0] = (GPRE_NOD) reference;
657
if (request->req_map)
658
return post_map(node, request->req_map);
663
CPR_s_error("<column name>");
664
return NULL; // silence compiler
668
//____________________________________________________________
670
// Parse a list of "things", separated by commas. Return the
671
// whole mess in a list node.
674
GPRE_NOD SQE_list(pfn_SQE_list_cb routine,
678
assert_IS_REQ(request);
680
gpre_lls* stack = NULL;
685
MSC_push((*routine) (request, aster_ok, NULL, NULL), &stack);
686
} while (MSC_match(KW_COMMA));
688
gpre_nod* list = MSC_node(nod_list, (SSHORT) count);
689
gpre_nod** ptr = &list->nod_arg[count];
692
*--ptr = (GPRE_NOD) MSC_pop(&stack);
698
//____________________________________________________________
700
// Parse procedure input parameters which are constants or
701
// host variable reference and, perhaps, a missing
702
// flag reference, which may be prefaced by the noiseword,
706
REF SQE_parameter(gpre_req* request,
712
assert_IS_REQ(request);
714
if (gpreGlob.token_global.tok_type == tok_number) {
715
reference = (REF) MSC_alloc(REF_LEN);
716
string = (TEXT *) MSC_alloc(gpreGlob.token_global.tok_length + 1);
717
MSC_copy(gpreGlob.token_global.tok_string, gpreGlob.token_global.tok_length, string);
718
reference->ref_value = string;
719
reference->ref_flags |= REF_literal;
724
if ((isQuoted(gpreGlob.token_global.tok_type) && gpreGlob.sw_sql_dialect == 1) ||
725
gpreGlob.token_global.tok_type == tok_sglquoted)
728
Since we have stripped the quotes, it is time now to put it back
729
so that the host language will interpret it correctly as a string
732
reference = (REF) MSC_alloc(REF_LEN);
733
string = (TEXT *) MSC_alloc(gpreGlob.token_global.tok_length + 3);
735
MSC_copy(gpreGlob.token_global.tok_string, gpreGlob.token_global.tok_length, string + 1);
736
string[gpreGlob.token_global.tok_length + 1] = '\"';
737
string[gpreGlob.token_global.tok_length + 2] = 0;
738
reference->ref_value = string;
739
reference->ref_flags |= REF_literal;
744
if (gpreGlob.token_global.tok_keyword == KW_PLUS || gpreGlob.token_global.tok_keyword == KW_MINUS)
747
if (gpreGlob.token_global.tok_keyword == KW_MINUS)
752
if (gpreGlob.token_global.tok_type != tok_number)
753
CPR_s_error("<host variable> or <constant>");
754
reference = (REF) MSC_alloc(REF_LEN);
755
char* s = string = (TEXT *) MSC_alloc(gpreGlob.token_global.tok_length + 1 + sign);
758
MSC_copy(gpreGlob.token_global.tok_string, gpreGlob.token_global.tok_length, s);
759
reference->ref_value = string;
760
reference->ref_flags |= REF_literal;
765
if (!MSC_match(KW_COLON))
766
CPR_s_error("<host variable> or <constant>");
768
if (gpreGlob.token_global.tok_type != tok_ident)
769
CPR_s_error("<host variable> or <constant>");
771
reference = (REF) MSC_alloc(REF_LEN);
773
for (gpre_sym* symbol = gpreGlob.token_global.tok_symbol; symbol;
774
symbol = symbol->sym_homonym)
776
if (symbol->sym_type == SYM_variable) {
777
reference->ref_field = (gpre_fld*) symbol->sym_object;
782
reference->ref_value = PAR_native_value(false, false);
784
MSC_match(KW_INDICATOR);
786
if (MSC_match(KW_COLON))
787
reference->ref_null_value = PAR_native_value(false, false);
793
//____________________________________________________________
795
// Given an expression node, for values that don't have a
796
// field, post the given field.
797
// Procedure called from EXP_array to post the "subscript field".
800
void SQE_post_field( GPRE_NOD input, gpre_fld* field)
802
if (!input || !field)
805
assert_IS_NOD(input);
807
switch (input->nod_type)
811
ref* reference = (REF) input->nod_arg[0];
812
if (!reference->ref_field) {
813
/* We're guessing that hostvar reference->ref_value matches
814
* the datatype of field->fld_dtype
816
reference->ref_field = field;
829
mel* element = (MEL) input->nod_arg[0];
830
gpre_nod* node = element->mel_expr;
831
SQE_post_field(node, field);
837
gpre_nod** ptr = input->nod_arg;
838
for (const gpre_nod* const* const end = ptr + input->nod_count;
841
SQE_post_field(*ptr, field);
849
//____________________________________________________________
851
// Post an external reference to a request. If the expression
852
// in question already exists, re-use it. If there isn't a field,
853
// generate a pseudo-field to hold datatype information. If there
854
// isn't a context, well, there isn't a context.
857
REF SQE_post_reference(gpre_req* request, gpre_fld* field, gpre_ctx* context,
862
assert_IS_REQ(request);
865
// If the beast is already a field reference, get component parts
867
if (node && node->nod_type == nod_field) {
868
reference = (REF) node->nod_arg[0];
869
field = reference->ref_field;
870
context = reference->ref_context;
873
// See if there is already a reference to this guy. If so, return it.
875
for (reference = request->req_references; reference;
876
reference = reference->ref_next)
878
if ((reference->ref_expr && compare_expr(node, reference->ref_expr))
879
|| (!reference->ref_expr && field == reference->ref_field
880
&& context == reference->ref_context))
886
// If there isn't a field given, make one up
889
field = (gpre_fld*) MSC_alloc(FLD_LEN);
890
CME_get_dtype(node, field);
891
if (field->fld_dtype && (field->fld_dtype <= dtype_any_text))
892
field->fld_flags |= FLD_text;
895
// No reference -- make one
897
reference = (REF) MSC_alloc(REF_LEN);
898
reference->ref_context = context;
899
reference->ref_field = field;
900
reference->ref_expr = node;
902
reference->ref_next = request->req_references;
903
request->req_references = reference;
909
//____________________________________________________________
911
// Resolve a kludgy field node build by par_s_item into
912
// a bona fide field reference. If a request
913
// is supplied, resolve the reference to any context available
914
// in the request. Otherwise resolve the field to a given
915
// record selection expression.
917
// If the expression contains a global aggregate, return true,
921
bool SQE_resolve(GPRE_NOD node,
926
act* slice_action = 0;
928
assert_IS_REQ(request);
931
switch (node->nod_type) {
939
case nod_concatenate:
942
gpre_nod** ptr = node->nod_arg;
943
const gpre_nod* const* const end = ptr + node->nod_count;
944
for (; ptr < end; ptr++)
945
result |= SQE_resolve(*ptr, request, selection);
952
case nod_agg_average:
954
if (node->nod_arg[0]) {
955
SQE_resolve(node->nod_arg[0], request, selection);
956
gpre_nod* node_arg = node->nod_arg[0];
957
const ref* reference = (REF) node_arg->nod_arg[0];
958
if (node_arg->nod_type == nod_field && reference &&
959
reference->ref_field && reference->ref_field->fld_array_info)
962
("Array columns not permitted in aggregate functions");
968
if (node->nod_arg[0]) {
969
gpre_nod** ptr = node->nod_arg[0]->nod_arg;
970
const gpre_nod* const* const end = ptr + node->nod_arg[0]->nod_count;
971
for (; ptr < end; ptr++)
972
result |= SQE_resolve(*ptr, request, selection);
977
return SQE_resolve(node->nod_arg[0], request, selection);
979
// ** Begin date/time/timestamp support *
981
result |= SQE_resolve(node->nod_arg[1], request, selection);
983
// ** End date/time/timestamp support *
992
TOK f_token = (TOK) node->nod_arg[0];
993
f_token->tok_symbol = HSH_lookup(f_token->tok_string);
994
TOK q_token = (TOK) node->nod_arg[1];
996
q_token->tok_symbol = HSH_lookup(q_token->tok_string);
998
gpre_fld* field = NULL;
1002
for (context = request->req_contexts; context;
1003
context = context->ctx_next)
1005
if (!context->ctx_stream
1006
&& (field = resolve(node, context, 0, &slice_action))) break;
1009
for (SSHORT i = 0; i < selection->rse_count; i++) {
1010
if (field = resolve(node, selection->rse_context[i], &context, &slice_action))
1015
SCHAR s[ERROR_LENGTH];
1017
fb_utils::snprintf(s, sizeof(s),
1018
"column \"%s.%s\" cannot be resolved",
1019
q_token->tok_string, f_token->tok_string);
1021
fb_utils::snprintf(s, sizeof(s),
1022
"column \"%s\" cannot be resolved",
1023
f_token->tok_string);
1027
// Make sure that a dialect-1 program isn't trying to select a
1028
// dialect-3-only field type.
1029
if ((SQL_DIALECT_V5 == gpreGlob.sw_sql_dialect) &&
1030
((dtype_sql_date == field->fld_dtype) ||
1031
(dtype_sql_time == field->fld_dtype) ||
1032
(dtype_int64 == field->fld_dtype)))
1034
SQL_dialect1_bad_type(field->fld_dtype);
1037
ref* reference = (REF) MSC_alloc(REF_LEN);
1038
reference->ref_field = field;
1039
reference->ref_context = context;
1040
reference->ref_slice = (slc*) slice_action;
1042
// donot reinit if this is a nod_deffered type
1043
if (node->nod_type != nod_deferred)
1044
node->nod_count = 0;
1047
node->nod_type = nod_field;
1048
node->nod_arg[0] = (GPRE_NOD) reference;
1054
//____________________________________________________________
1056
// Parse a SELECT (sans keyword) expression.
1059
gpre_rse* SQE_select(gpre_req* request,
1062
gpre_lls* context_stack = NULL;
1063
gpre_ctx* context = 0;
1064
bool have_union = false;
1066
assert_IS_REQ(request);
1068
map* const old_map = request->req_map;
1070
// Get components of union. Most likely there isn't one, so this is
1071
// probably wasted work.
1073
gpre_rse* select = NULL;
1074
gpre_rse* rse1 = NULL;
1075
select = rse1 = par_select(request, NULL);
1077
// "Look for ... the UNION label ... "
1078
while (MSC_match(KW_UNION)) {
1081
const bool union_all = MSC_match(KW_ALL);
1082
if (!MSC_match(KW_SELECT))
1083
CPR_s_error("SELECT");
1085
MSC_push((GPRE_NOD) request->req_contexts, &context_stack);
1086
request->req_contexts = NULL;
1087
request->req_map = NULL;
1088
gpre_rse* rse2 = par_select(request, rse1);
1090
/* We've got a bona fide union. Make a union node to hold sub-rse
1091
and then a new rse to point to it. */
1093
select = (gpre_rse*) MSC_alloc(RSE_LEN(1));
1094
select->rse_context[0] = context = MSC_context(request);
1095
gpre_nod* node = MSC_node(nod_union, 2);
1096
select->rse_union = node;
1097
node->nod_arg[0] = (GPRE_NOD) rse1;
1098
node->nod_arg[1] = (GPRE_NOD) rse2;
1100
map* new_map = (map*) MSC_alloc(sizeof(map));
1101
rse1->rse_map = new_map;
1102
new_map->map_context = context;
1103
select->rse_fields = post_select_list(rse1->rse_fields, new_map);
1105
rse2->rse_map = new_map = (map*) MSC_alloc(sizeof(map));
1106
new_map->map_context = context;
1107
post_select_list(rse2->rse_fields, new_map);
1109
select->rse_into = rse1->rse_into;
1111
select->rse_reduced = select->rse_fields;
1113
// Result of this UNION might be the left side of the NEXT UNION
1117
// Restore the context lists that were forgotten
1118
// <context> holds the most recently allocated context, which is
1119
// already linked into the request block
1121
while (context_stack) {
1122
while (context->ctx_next)
1123
context = context->ctx_next;
1124
context->ctx_next = (gpre_ctx*) MSC_pop(&context_stack);
1127
// Pick up any dangling ORDER clause
1129
++request->req_in_order_by_clause;
1130
par_order(request, select, have_union, view_flag);
1131
--request->req_in_order_by_clause;
1132
par_update(select, have_union, view_flag);
1133
request->req_map = old_map;
1139
//____________________________________________________________
1141
// Parse either of the low precedence operators + and -.
1144
GPRE_NOD SQE_value(gpre_req* request,
1146
USHORT * paren_count,
1152
assert_IS_REQ(request);
1156
paren_count = &local_count;
1160
bool_flag = &local_flag;
1164
gpre_nod* node = par_multiply(request, aster_ok, paren_count, bool_flag);
1165
assert_IS_NOD(node);
1166
if (node->nod_type == nod_asterisk) {
1167
par_terminating_parens(paren_count, &local_count);
1173
if (MSC_match(KW_PLUS))
1174
nod_type = nod_plus;
1175
else if (MSC_match(KW_MINUS))
1176
nod_type = nod_minus;
1177
else if (MSC_match(KW_OR1))
1178
nod_type = nod_concatenate;
1180
par_terminating_parens(paren_count, &local_count);
1183
gpre_nod* arg = node;
1184
node = MSC_binary(nod_type, arg,
1185
par_multiply(request, false, paren_count, bool_flag));
1190
//____________________________________________________________
1192
// Parse either a literal NULL expression or a value
1196
GPRE_NOD SQE_value_or_null(gpre_req* request,
1198
USHORT * paren_count,
1201
if (MSC_match(KW_NULL)) {
1202
return MSC_node(nod_null, 0);
1205
return SQE_value(request, aster_ok, paren_count, bool_flag);
1209
//____________________________________________________________
1211
// Parse host variable reference and, perhaps, a missing
1212
// flag reference, which may be prefaced by the noiseword,
1216
GPRE_NOD SQE_variable(gpre_req* request,
1218
USHORT * paren_count,
1221
assert_IS_REQ(request);
1223
if (!MSC_match(KW_COLON))
1224
CPR_s_error("<colon>");
1226
if (isQuoted(gpreGlob.token_global.tok_type))
1227
CPR_s_error("<host variable>");
1229
ref* reference = (REF) MSC_alloc(REF_LEN);
1231
for (gpre_sym* symbol = gpreGlob.token_global.tok_symbol; symbol;
1232
symbol = symbol->sym_homonym)
1234
if (symbol->sym_type == SYM_variable) {
1235
reference->ref_field = (gpre_fld*) symbol->sym_object;
1240
reference->ref_value = PAR_native_value(false, false);
1242
MSC_match(KW_INDICATOR);
1244
if (MSC_match(KW_COLON))
1245
reference->ref_null_value = PAR_native_value(false, false);
1247
return (GPRE_NOD) reference;
1251
//____________________________________________________________
1253
// Compare two expressions symbollically. If they're the same,
1254
// return TRUE, otherwise FALSE.
1257
static bool compare_expr(GPRE_NOD node1,
1262
assert_IS_NOD(node1);
1263
assert_IS_NOD(node2);
1265
if (node1->nod_type != node2->nod_type)
1268
switch (node1->nod_type) {
1270
ref1 = (REF) node1->nod_arg[0];
1271
ref2 = (REF) node2->nod_arg[0];
1272
if (ref1->ref_context != ref2->ref_context ||
1273
ref1->ref_field != ref2->ref_field ||
1274
ref1->ref_master != ref2->ref_master)
1281
if (node1->nod_arg[0] != node2->nod_arg[0])
1287
if (node1->nod_arg[0] != node2->nod_arg[0] ||
1288
node1->nod_arg[1] != node2->nod_arg[1])
1300
//____________________________________________________________
1302
// Copy a field list for a SELECT against an artificial context.
1305
static GPRE_NOD copy_fields( GPRE_NOD fields, map* fields_map)
1307
assert_IS_NOD(fields);
1309
gpre_nod* list = MSC_node(nod_list, fields->nod_count);
1311
for (USHORT i = 0; i < fields->nod_count; i++)
1312
list->nod_arg[i] = post_fields(fields->nod_arg[i], fields_map);
1318
//____________________________________________________________
1320
// Expand an '*' in a field list to the corresponding fields.
1323
static GPRE_NOD explode_asterisk( GPRE_NOD fields, int n, gpre_rse* selection)
1325
TEXT s[ERROR_LENGTH];
1327
assert_IS_NOD(fields);
1329
gpre_nod* node = fields->nod_arg[n];
1330
TOK q_token = (TOK) node->nod_arg[0];
1332
// expand for single relation
1333
gpre_ctx* context = resolve_asterisk(q_token, selection);
1335
fields = merge_fields(fields, MET_fields(context), n, true);
1337
sprintf(s, "columns \"%s.*\" cannot be resolved",
1338
q_token->tok_string);
1343
// expand for all relations in context list
1345
fields = explode_asterisk_all(fields, n, selection, true);
1352
//____________________________________________________________
1354
// Expand an '*' for all relations
1355
// in the context list.
1358
static GPRE_NOD explode_asterisk_all(GPRE_NOD fields,
1360
gpre_rse* selection,
1363
assert_IS_NOD(fields);
1365
for (int i = 0; i < selection->rse_count; i++) {
1366
gpre_ctx* context = selection->rse_context[i];
1367
const int old_count = fields->nod_count;
1368
if (context->ctx_stream)
1369
fields = explode_asterisk_all(fields, n, context->ctx_stream,
1372
fields = merge_fields(fields, MET_fields(context), n, replace);
1373
n += fields->nod_count - old_count;
1381
//____________________________________________________________
1383
// Get an element of an expression to act as a reference
1384
// field for determining the data type of a host variable.
1387
static gpre_fld* get_ref( GPRE_NOD expr)
1391
assert_IS_NOD(expr);
1393
if (expr->nod_type == nod_via || expr->nod_type == nod_cast) {
1394
field = (gpre_fld*) MSC_alloc(FLD_LEN);
1395
CME_get_dtype(expr, field);
1396
if (field->fld_dtype && (field->fld_dtype <= dtype_any_text))
1397
field->fld_flags |= FLD_text;
1403
switch (expr->nod_type) {
1405
reference = (ref*) expr->nod_arg[0];
1406
return reference->ref_field;
1410
reference = (ref*) expr->nod_arg[0];
1411
return reference->ref_field->fld_array;
1417
case nod_agg_average:
1425
case nod_concatenate:
1427
gpre_nod** ptr = expr->nod_arg;
1428
for (const gpre_nod* const* const end = ptr + expr->nod_count;
1431
if (field = get_ref(*ptr))
1437
// ** Begin date/time/timestamp support *
1439
if (field = get_ref(expr->nod_arg[1]))
1442
// ** End date/time/timestamp support *
1445
mel* element = (MEL) expr->nod_arg[0];
1446
gpre_nod* node = element->mel_expr;
1447
return get_ref(node);
1455
//____________________________________________________________
1457
// Finish off processing an implicit ANY clause. Assume that the word
1458
// "select" has already been recognized. If the outer thing is a group
1459
// by, so we're looking at a "having", re-resolve the input value to the
1463
static GPRE_NOD implicit_any(gpre_req* request,
1465
enum nod_t comparison,
1469
scope previous_scope;
1471
assert_IS_REQ(request);
1472
assert_IS_NOD(value);
1474
gpre_ctx* original = request->req_contexts;
1476
request->req_in_subselect++;
1477
push_scope(request, &previous_scope);
1479
if (!(original->ctx_relation || original->ctx_procedure) && request->req_map)
1480
value = post_fields(value, request->req_map);
1482
// Handle the ALL and DISTINCT options
1483
const bool distinct = (!MSC_match(KW_ALL) && MSC_match(KW_DISTINCT));
1485
request->req_in_select_list++;
1486
gpre_nod* value2 = SQE_value(request, false, NULL, NULL);
1487
request->req_in_select_list--;
1489
gpre_nod* field_list = MSC_node(nod_list, 1);
1490
field_list->nod_arg[0] = value2;
1492
gpre_rse* selection = par_rse(request, field_list, distinct);
1493
value2 = selection->rse_fields->nod_arg[0];
1495
gpre_rse* sub = selection->rse_aggregate;
1497
if (validate_references(value2, sub->rse_group_by))
1499
("simple column reference not allowed in aggregate context");
1500
if (sub->rse_group_by) {
1501
node = MSC_binary(comparison, value, value2);
1502
pair(node->nod_arg[0], node->nod_arg[1]);
1503
selection->rse_boolean = merge(selection->rse_boolean, node);
1504
if (any_all == nod_ansi_all)
1505
node = MSC_node(nod_ansi_all, 1);
1506
else if (!(request->req_database->dbb_flags & DBB_v3))
1507
node = MSC_node(nod_ansi_any, 1);
1509
node = MSC_node(nod_any, 1);
1510
node->nod_count = 0;
1511
node->nod_arg[0] = (GPRE_NOD) selection;
1514
gpre_nod* node2 = MSC_node(nod_via, 3);
1515
node2->nod_count = 0;
1516
node2->nod_arg[0] = (GPRE_NOD) selection;
1517
node2->nod_arg[2] = MSC_node(nod_null, 0);
1518
node2->nod_arg[1] = value2;
1519
node = MSC_binary(comparison, value, node2);
1520
pair(node->nod_arg[0], node->nod_arg[1]);
1524
node = MSC_binary(comparison, value, value2);
1525
pair(node->nod_arg[0], node->nod_arg[1]);
1526
selection->rse_boolean = merge(selection->rse_boolean, node);
1527
if (any_all == nod_ansi_all)
1528
node = MSC_node(nod_ansi_all, 1);
1529
else if (!(request->req_database->dbb_flags & DBB_v3))
1530
node = MSC_node(nod_ansi_any, 1);
1532
node = MSC_node(nod_any, 1);
1533
node->nod_count = 0;
1534
node->nod_arg[0] = (GPRE_NOD) selection;
1537
EXP_rse_cleanup(selection);
1539
pop_scope(request, &previous_scope);
1540
request->req_in_subselect--;
1546
//____________________________________________________________
1548
// Merge two (possibly null) booleans into a single conjunct.
1551
static GPRE_NOD merge( GPRE_NOD expr1, GPRE_NOD expr2)
1560
assert_IS_NOD(expr1);
1561
assert_IS_NOD(expr1);
1563
return MSC_binary(nod_and, expr1, expr2);
1567
//____________________________________________________________
1569
// Merge 2 field lists
1570
// 2nd list is added over nth entry in 1st list
1571
// if replace is TRUE, otherwise it is added
1572
// after the nth entry.
1575
static GPRE_NOD merge_fields(GPRE_NOD fields_1,
1582
assert_IS_NOD(fields_1);
1583
assert_IS_NOD(fields_2);
1585
int count = fields_1->nod_count + fields_2->nod_count;
1588
gpre_nod* fields = MSC_node(nod_list, (SSHORT) count);
1593
for (i = 0; i < count; i++)
1594
fields->nod_arg[i] = fields_1->nod_arg[i];
1596
for (i = 0; i < fields_2->nod_count; i++)
1597
fields->nod_arg[i + count] = fields_2->nod_arg[i];
1605
for (i = count; i < fields_1->nod_count; i++)
1606
fields->nod_arg[i + fields_2->nod_count - offset] =
1607
fields_1->nod_arg[i];
1613
//____________________________________________________________
1615
// Construct negation of expression.
1618
static GPRE_NOD negate( GPRE_NOD expr)
1621
assert_IS_NOD(expr);
1623
return MSC_unary(nod_not, expr);
1627
//____________________________________________________________
1629
// Given two value expressions associated in a relational
1630
// expression, see if one is a field reference and the other
1631
// is a host language variable.. If so, match the field to the
1632
// host language variable.
1635
static void pair( GPRE_NOD expr1, GPRE_NOD expr2)
1637
assert_IS_NOD(expr1);
1638
assert_IS_NOD(expr2);
1640
// Verify that an array field without subscripts is not
1641
// being used inappropriately
1643
if (expr1 && expr2) {
1644
if (expr1->nod_type == nod_array && !expr1->nod_arg[1])
1645
PAR_error("Invalid array column reference");
1646
if (expr2->nod_type == nod_array && !expr2->nod_arg[1])
1647
PAR_error("Invalid array column reference");
1650
gpre_fld* field = 0;
1652
field = get_ref(expr2);
1654
field = get_ref(expr1);
1659
set_ref(expr1, field);
1664
gpre_fld* temp = get_ref(expr1);
1668
set_ref(expr2, field);
1672
//____________________________________________________________
1674
// The passed alias list fully specifies a relation.
1675
// The first alias represents a relation specified in
1676
// the from list at this scope levels. Subsequent
1677
// contexts, if there are any, represent base relations
1678
// in a view stack. They are used to fully specify a
1679
// base relation of a view. The aliases used in the
1680
// view stack are those used in the view definition.
1683
static gpre_ctx* par_alias_list( gpre_req* request, GPRE_NOD alias_list)
1685
assert_IS_REQ(request);
1686
assert_IS_NOD(alias_list);
1688
gpre_nod** arg = alias_list->nod_arg;
1689
const gpre_nod* const* const end = alias_list->nod_arg + alias_list->nod_count;
1691
// check the first alias in the list with the relations
1692
// in the current context for a match
1694
gpre_rel* relation = 0; // unreliable test many lines below without initializing.
1695
gpre_ctx* context = par_alias(request, (const TEXT*) * arg);
1697
if (alias_list->nod_count == 1)
1699
relation = context->ctx_relation;
1702
SCHAR error_string[ERROR_LENGTH];
1704
// if the first alias didn't specify a table in the context stack,
1705
// look through all contexts to find one which might be a view with
1706
// a base table having a matching table name or alias
1709
for (context = request->req_contexts; context;
1710
context = context->ctx_next)
1712
if (context->ctx_scope_level != request->req_scope_level)
1714
if (!context->ctx_relation)
1717
par_base_table(request, context->ctx_relation,
1718
(const TEXT*) * arg))
1725
fb_utils::snprintf(error_string, sizeof(error_string),
1726
"there is no alias or table named %s at this scope level",
1728
PAR_error(error_string);
1731
// find the base table using the specified alias list, skipping the first one
1732
// since we already matched it to the context
1734
for (arg++; arg < end; arg++)
1735
if (!(relation = par_base_table(request, relation, (const TEXT*) * arg)))
1739
fb_utils::snprintf(error_string, sizeof(error_string),
1740
"there is no alias or table named %s at this scope level",
1742
PAR_error(error_string);
1745
// make up a dummy context to hold the resultant relation
1747
gpre_ctx* new_context = (gpre_ctx*) MSC_alloc(CTX_LEN);
1748
new_context->ctx_request = request;
1749
new_context->ctx_internal = context->ctx_internal;
1750
new_context->ctx_relation = relation;
1752
// concatenate all the contexts to form the alias name;
1753
// calculate the length leaving room for spaces and a null
1755
USHORT alias_length = alias_list->nod_count;
1756
for (arg = alias_list->nod_arg; arg < end; arg++)
1757
alias_length += strlen((TEXT *) * arg);
1759
TEXT* alias = (TEXT *) MSC_alloc(alias_length);
1761
// CVC: Warning: Using space as separator may conflict with dialect 3's embedded blanks;
1762
// but gpre is not much worried about dialects... except in this file!
1763
TEXT* p = new_context->ctx_alias = alias;
1764
for (arg = alias_list->nod_arg; arg < end; arg++) {
1765
for (const TEXT* q = (TEXT *) * arg; *q;)
1776
//____________________________________________________________
1778
// The passed relation or alias represents
1779
// a context which was previously specified
1780
// in the from list. Find and return the
1784
static gpre_ctx* par_alias( gpre_req* request, const TEXT* alias)
1786
SCHAR error_string[ERROR_LENGTH];
1788
assert_IS_REQ(request);
1790
// look through all contexts at this scope level
1791
// to find one that has a relation name or alias
1792
// name which matches the identifier passed
1794
gpre_ctx* relation_context = NULL;
1795
for (gpre_ctx* context = request->req_contexts; context;
1796
context = context->ctx_next)
1798
if (context->ctx_scope_level != request->req_scope_level)
1801
// check for matching alias
1803
if (context->ctx_alias) {
1804
const TEXT* p = context->ctx_alias;
1805
const TEXT* q = alias;
1806
for (; *p && *q; p++, q++)
1807
if (UPPER(*p) != UPPER(*q))
1813
/* check for matching relation name; aliases take priority so
1814
save the context in case there is an alias of the same name;
1815
also to check that there is no self-join in the query */
1817
if (context->ctx_relation &&
1818
!strcmp(context->ctx_relation->rel_symbol->sym_string, alias))
1820
if (relation_context) {
1821
fb_utils::snprintf(error_string, sizeof(error_string),
1822
"the table %s is referenced twice; use aliases to differentiate",
1824
PAR_error(error_string);
1826
relation_context = context;
1830
return relation_context;
1834
//____________________________________________________________
1836
// Check if the relation in the passed context
1837
// has a base table which matches the passed alias.
1840
static gpre_rel* par_base_table( gpre_req* request, const gpre_rel* relation,
1844
assert_IS_REQ(request);
1846
return MET_get_view_relation(request, relation->rel_symbol->sym_string,
1851
//____________________________________________________________
1853
// Parse an AND boolean expression.
1856
static GPRE_NOD par_and( gpre_req* request, USHORT * paren_count)
1858
assert_IS_REQ(request);
1860
gpre_nod* expr1 = par_not(request, paren_count);
1862
if (!MSC_match(KW_AND))
1865
return merge(expr1, par_and(request, paren_count));
1869
//____________________________________________________________
1873
static GPRE_NOD par_collate( gpre_req* request, GPRE_NOD arg)
1875
assert_IS_REQ(request);
1878
gpre_nod* node = MSC_node(nod_cast, 2);
1879
node->nod_count = 1;
1880
node->nod_arg[0] = arg;
1881
gpre_fld* field = (gpre_fld*) MSC_alloc(FLD_LEN);
1882
node->nod_arg[1] = (GPRE_NOD) field;
1883
CME_get_dtype(arg, field);
1884
if (field->fld_dtype > dtype_any_text) {
1885
// cast expression to VARYING with implementation-defined
1888
field->fld_dtype = dtype_varying;
1889
field->fld_char_length = 30;
1890
field->fld_length = 0; // calculated by SQL_adjust_field_dtype
1891
field->fld_scale = 0;
1892
field->fld_sub_type = 0;
1894
else if (field->fld_sub_type) {
1895
field->fld_character_set = MET_get_text_subtype(field->fld_sub_type);
1897
SQL_par_field_collate(request, field);
1898
SQL_adjust_field_dtype(field);
1904
//____________________________________________________________
1906
// Parse a SQL "IN" expression. This comes in two flavors:
1908
// <value> IN (<value_comma_list>)
1909
// <value> IN (SELECT <column> <from_nonsense>)
1912
static GPRE_NOD par_in( gpre_req* request, GPRE_NOD value)
1915
SCHAR s[ERROR_LENGTH];
1917
assert_IS_REQ(request);
1918
assert_IS_NOD(value);
1922
// If the next token isn't SELECT, we must have the comma list flavor.
1924
if (MSC_match(KW_SELECT))
1925
node = implicit_any(request, value, nod_eq, nod_ansi_any);
1929
gpre_nod* value2 = par_primitive_value(request, false, 0, NULL);
1930
if (value2->nod_type == nod_value) {
1931
ref* ref2 = (REF) value2->nod_arg[0];
1932
if (value->nod_type == nod_field) {
1933
ref* ref1 = (REF) value->nod_arg[0];
1934
ref2->ref_field = ref1->ref_field;
1937
fb_utils::snprintf(s, sizeof(s),
1938
"datatype of %s can not be determined",
1939
gpreGlob.token_global.tok_string);
1944
node = MSC_binary(nod_eq, value, value2);
1947
MSC_binary(nod_or, node,
1948
MSC_binary(nod_eq, value, value2));
1950
if (!(MSC_match(KW_COMMA)))
1955
if (!EXP_match_paren())
1962
//____________________________________________________________
1964
// Parse a join relation clause.
1967
static gpre_ctx* par_joined_relation( gpre_req* request, gpre_ctx* prior_context)
1971
assert_IS_REQ(request);
1973
if (MSC_match(KW_LEFT_PAREN)) {
1974
context1 = par_joined_relation(request, NULL);
1977
else if (!(context1 = SQE_context(request)))
1980
return par_join_clause(request, context1);
1984
//____________________________________________________________
1986
// Parse a join relation clause.
1989
static gpre_ctx* par_join_clause( gpre_req* request, gpre_ctx* context1)
1991
assert_IS_REQ(request);
1993
const NOD_T join_type = par_join_type();
1994
if (join_type == (NOD_T) 0)
1997
gpre_ctx* context2 = par_joined_relation(request, context1);
1999
CPR_s_error("<joined table clause>");
2001
if (!MSC_match(KW_ON))
2004
gpre_nod* node = SQE_boolean(request, NULL);
2006
gpre_rse* selection = (gpre_rse*) MSC_alloc(RSE_LEN(2));
2007
selection->rse_count = 2;
2008
selection->rse_context[0] = context1;
2009
selection->rse_context[1] = context2;
2010
selection->rse_boolean = node;
2011
selection->rse_join_type = join_type;
2013
context1 = MSC_context(request);
2014
context1->ctx_stream = selection;
2016
return par_join_clause(request, context1);
2020
//____________________________________________________________
2022
// Parse a join type.
2025
static NOD_T par_join_type(void)
2029
if (MSC_match(KW_INNER))
2030
nod_type = nod_join_inner;
2031
else if (MSC_match(KW_LEFT))
2032
nod_type = nod_join_left;
2033
else if (MSC_match(KW_RIGHT))
2034
nod_type = nod_join_right;
2035
else if (MSC_match(KW_FULL))
2036
nod_type = nod_join_full;
2037
else if (MSC_match(KW_JOIN))
2038
return nod_join_inner;
2042
if (nod_type != nod_join_inner)
2043
MSC_match(KW_OUTER);
2045
if (!MSC_match(KW_JOIN))
2046
CPR_s_error("JOIN");
2052
//____________________________________________________________
2054
// Parse either of the high precedence operators * and /.
2057
static GPRE_NOD par_multiply(gpre_req* request,
2059
USHORT * paren_count,
2062
assert_IS_REQ(request);
2063
gpre_nod* node = par_primitive_value(request, aster_ok, paren_count, bool_flag);
2064
if (node->nod_type == nod_asterisk)
2067
if (gpreGlob.token_global.tok_keyword == KW_COLLATE)
2068
return par_collate(request, node);
2071
enum nod_t nod_type;
2073
if (MSC_match(KW_ASTERISK))
2074
nod_type = nod_times;
2075
else if (MSC_match(KW_SLASH))
2076
nod_type = nod_divide;
2081
MSC_binary(nod_type, arg,
2082
par_primitive_value(request, false, paren_count,
2088
//____________________________________________________________
2090
// Parse an NOT boolean expression.
2093
static GPRE_NOD par_not( gpre_req* request, USHORT * paren_count)
2095
assert_IS_REQ(request);
2097
if (MSC_match(KW_NOT))
2098
return negate(par_not(request, paren_count));
2100
enum nod_t type = (enum nod_t) 0;
2102
if (MSC_match(KW_EXISTS))
2104
else if (MSC_match(KW_SINGULAR))
2106
if (type == nod_any || type == nod_unique) {
2108
push_scope(request, &saved_scope);
2111
if (!MSC_match(KW_SELECT))
2112
CPR_s_error("SELECT");
2114
request->req_in_select_list++;
2116
if (MSC_match(KW_ASTERISK))
2118
else if (!(field = par_udf(request)))
2119
field = SQE_field(request, false);
2120
request->req_in_select_list--;
2122
gpre_nod* node = MSC_node(type, 1);
2123
node->nod_count = 0;
2124
gpre_rse* selection = par_rse(request, 0, false);
2125
node->nod_arg[0] = (GPRE_NOD) selection;
2127
SQE_resolve(field, 0, selection);
2128
gpre_nod* expr = MSC_unary(nod_missing, field);
2129
selection->rse_boolean = merge(negate(expr), selection->rse_boolean);
2131
EXP_rse_cleanup((gpre_rse*) node->nod_arg[0]);
2132
pop_scope(request, &saved_scope);
2137
return par_relational(request, paren_count);
2141
//____________________________________________________________
2143
// Parse ORDER clause of SELECT expression. This is
2144
// particularly difficult since the ORDER clause can
2145
// refer to fields by position.
2148
static void par_order(gpre_req* request,
2157
assert_IS_REQ(request);
2159
if (!MSC_match(KW_ORDER))
2162
PAR_error("sort clause not allowed in a view definition");
2165
gpre_lls* items = NULL;
2166
gpre_lls* directions = NULL;
2167
int count = 0, direction = 0;
2168
gpre_nod* values = select->rse_fields;
2172
if (gpreGlob.token_global.tok_type == tok_number) {
2173
i = EXP_USHORT_ordinal(false);
2174
if (i < 1 || i > values->nod_count)
2175
CPR_s_error("<ordinal column position>");
2176
sort = values->nod_arg[i - 1];
2178
if (gpreGlob.token_global.tok_keyword == KW_COLLATE)
2179
sort = par_collate(request, sort);
2183
CPR_s_error("<column position in union>");
2184
sort = SQE_value(request, false, NULL, NULL);
2185
if (request && (request_map = request->req_map))
2186
sort = post_map(sort, request_map);
2188
if (MSC_match(KW_ASCENDING))
2190
else if (MSC_match(KW_DESCENDING))
2193
MSC_push((GPRE_NOD)(IPTR)direction, &directions);
2194
MSC_push(sort, &items);
2195
if (!MSC_match(KW_COMMA))
2199
select->rse_sort = sort = MSC_node(nod_sort, (SSHORT) (count * 2));
2200
sort->nod_count = count;
2201
gpre_nod** ptr = sort->nod_arg + count * 2;
2204
*--ptr = (GPRE_NOD) MSC_pop(&items);
2205
*--ptr = (GPRE_NOD) MSC_pop(&directions);
2210
//____________________________________________________________
2212
// Allow the user to specify the access plan
2213
// for a query as part of a select expression.
2216
static GPRE_NOD par_plan( gpre_req* request)
2218
assert_IS_REQ(request);
2220
// parse the join type
2223
if (MSC_match(KW_JOIN))
2224
nod_type = nod_join;
2225
else if (MSC_match(KW_MERGE))
2226
nod_type = nod_merge;
2227
else if (MSC_match(KW_SORT) && MSC_match(KW_MERGE))
2228
nod_type = nod_merge;
2230
nod_type = nod_join;
2232
// make up the plan expression node
2234
gpre_nod* plan_expression = MSC_node(nod_plan_expr, 2);
2236
if (nod_type != nod_join)
2237
plan_expression->nod_arg[0] = MSC_node(nod_type, 0);
2239
// parse the plan items at this level
2243
plan_expression->nod_arg[1] = SQE_list(par_plan_item, request, false);
2245
if (!EXP_match_paren())
2247
return plan_expression;
2251
//____________________________________________________________
2253
// Parse an individual plan item for an
2257
static GPRE_NOD par_plan_item(gpre_req* request,
2259
USHORT * paren_count,
2262
assert_IS_REQ(request);
2264
// check for a plan expression
2266
if (gpreGlob.token_global.tok_keyword == KW_JOIN || gpreGlob.token_global.tok_keyword == KW_SORT ||
2267
gpreGlob.token_global.tok_keyword == KW_MERGE || gpreGlob.token_global.tok_keyword == KW_LEFT_PAREN)
2269
return par_plan(request);
2272
// parse the list of one or more table names or
2273
// aliases (more than one is used when there is
2274
// a need to differentiate base tables of a view)
2277
gpre_lls* stack = NULL;
2278
for (count = 0; gpreGlob.token_global.tok_type == tok_ident; count++) {
2279
if (gpreGlob.token_global.tok_keyword == KW_NATURAL ||
2280
gpreGlob.token_global.tok_keyword == KW_ORDER ||
2281
gpreGlob.token_global.tok_keyword == KW_INDEX)
2286
MSC_push((GPRE_NOD) upcase_string(gpreGlob.token_global.tok_string), &stack);
2291
CPR_s_error("<table name> or <alias>");
2295
gpre_nod* alias_list = MSC_node(nod_list, (SSHORT) count);
2296
for (ptr = &alias_list->nod_arg[count]; stack;)
2297
*--ptr = (GPRE_NOD) MSC_pop(&stack);
2299
// lookup the contexts for the aliases
2301
gpre_ctx* context = par_alias_list(request, alias_list);
2303
// parse the access type
2305
gpre_nod* access_type;
2306
if (gpreGlob.token_global.tok_keyword == KW_NATURAL) {
2307
access_type = MSC_node(nod_natural, 0);
2310
else if (gpreGlob.token_global.tok_keyword == KW_ORDER) {
2311
access_type = MSC_node(nod_index_order, 1);
2312
access_type->nod_count = 0;
2315
if (gpreGlob.token_global.tok_type != tok_ident)
2316
CPR_s_error("<index name>");
2317
access_type->nod_arg[0] = (GPRE_NOD) upcase_string(gpreGlob.token_global.tok_string);
2320
else if (gpreGlob.token_global.tok_keyword == KW_INDEX) {
2321
access_type = MSC_node(nod_index, 1);
2322
access_type->nod_count = 0;
2328
for (count = 0; gpreGlob.token_global.tok_type == tok_ident;) {
2329
MSC_push((GPRE_NOD) upcase_string(gpreGlob.token_global.tok_string), &stack);
2334
if (!MSC_match(KW_COMMA))
2338
CPR_s_error("<table name> or <alias>");
2340
gpre_nod* index_list = MSC_node(nod_list, (SSHORT) count);
2341
access_type->nod_arg[0] = index_list;
2342
for (ptr = &index_list->nod_arg[count]; stack;)
2343
*--ptr = (GPRE_NOD) MSC_pop(&stack);
2345
if (!EXP_match_paren())
2349
CPR_s_error("NATURAL, ORDER, or INDEX");
2353
// generate the plan item node
2355
gpre_nod* plan_item = MSC_node(nod_plan_item, 3);
2356
plan_item->nod_count = 2;
2357
plan_item->nod_arg[0] = alias_list;
2358
plan_item->nod_arg[1] = access_type;
2359
plan_item->nod_arg[2] = (GPRE_NOD) context;
2365
//____________________________________________________________
2367
// Parse a value expression. The value could be any of the
2371
// _CHARSET"quoted string"
2377
// user defined function
2380
static GPRE_NOD par_primitive_value(gpre_req* request,
2382
USHORT * paren_count,
2387
assert_IS_REQ(request);
2393
paren_count = &local_count;
2396
if (MSC_match(KW_SELECT))
2397
return par_stat(request);
2399
if (MSC_match(KW_MINUS))
2400
return MSC_unary(nod_negate,
2401
par_primitive_value(request, false, paren_count, false));
2405
if (MSC_match(KW_USER)) {
2406
return MSC_node(nod_user_name, 0);
2409
if (MSC_match(KW_VALUE)) {
2410
/* If request is NULL we must be processing a subquery - and
2411
* without the request to refer to we're kinda hosed
2414
PAR_error("VALUE cannot be used in this context");
2415
const act* action = request->req_actions;
2416
if (request->req_type != REQ_ddl ||
2418
!(action->act_type == ACT_create_domain ||
2419
action->act_type == ACT_alter_domain))
2421
PAR_error("VALUE cannot be used in this context");
2424
return MSC_node(nod_dom_value, 0);
2427
if (MSC_match(KW_LEFT_PAREN)) {
2429
if (bool_flag && *bool_flag)
2430
node = SQE_boolean(request, paren_count);
2432
node = SQE_value(request, false, paren_count, bool_flag);
2438
// Check for an aggregate statistical expression. If we already have a
2439
// map defined for the request, we're part of either HAVING or a trailing
2440
// ORDER clause. In this case, post only the complete expression, and not
2441
// the sub-expressions.
2444
for (const ops *op = stat_ops; (int) op->rel_kw != (int) KW_none; op++) {
2446
if (MSC_match(op->rel_kw)) {
2447
if (request && (request->req_in_aggregate ||
2448
!(request->req_in_select_list ||
2449
request->req_in_having_clause ||
2450
request->req_in_order_by_clause)))
2452
/* either nested aggregate, or not part of a select
2453
list, having clause, or order by clause (in any subquery)
2455
PAR_error("Invalid aggregate reference");
2458
node = MSC_node(op->rel_op, 2);
2459
node->nod_count = 1;
2460
EXP_left_paren("left parenthesis in statistical function");
2461
const bool distinct = MSC_match(KW_DISTINCT);
2463
tmp_map = request->req_map;
2464
request->req_map = NULL;
2465
++request->req_in_aggregate;
2467
if (node->nod_type == nod_agg_count && MSC_match(KW_ASTERISK))
2468
node->nod_count = 0;
2470
node->nod_arg[0] = SQE_value(request, false, NULL, NULL);
2471
// Disallow arrays as arguments to aggregate functions
2472
const gpre_nod* node_arg = node->nod_arg[0];
2473
if (node_arg && node_arg->nod_type == nod_array)
2475
("Array columns not permitted in aggregate functions");
2479
node->nod_arg[1] = node->nod_arg[0];
2483
node = post_map(node, tmp_map);
2484
request->req_map = tmp_map;
2485
--request->req_in_aggregate;
2491
// If it's a number or a quoted string, it's a literal
2493
if (gpreGlob.token_global.tok_type == tok_number ||
2494
(isQuoted(gpreGlob.token_global.tok_type) && gpreGlob.sw_sql_dialect == 1) ||
2495
gpreGlob.token_global.tok_type == tok_sglquoted)
2497
node = EXP_literal();
2501
// moved this timestamp support down some lines, because it caused
2502
// gpre to segfault when it was done here.
2507
// If the next token is a colon, it is a variable reference
2509
if ((int) gpreGlob.token_global.tok_keyword == (int) KW_COLON) {
2511
/* We must be processing a subquery - and without the request to
2512
* post the :hostvar to we can't continue.
2513
* (core dump when de-refer of NULL request)
2515
PAR_error(":hostvar reference not supported in this context");
2518
ref* reference = (REF) SQE_variable(request, false, NULL, NULL);
2519
node = MSC_unary(nod_value, (GPRE_NOD) reference);
2520
reference->ref_next = request->req_values;
2521
request->req_values = reference;
2527
// Must be a field or a udf. If there is a map, post the field to it.
2528
node = par_udf_or_field(request, aster_ok);
2531
//if (request && (map = request->req_map))
2532
// return post_map (node, map);
2536
// I don't know what it's good for, but let's try it anyway if we haven't found
2537
// anything that makes sense until now
2539
// ** Begin date/time/timestamp support *
2540
const KWWORDS kw_word = gpreGlob.token_global.tok_keyword;
2542
if (MSC_match(KW_DATE) || MSC_match(KW_TIME) || MSC_match(KW_TIMESTAMP)) {
2543
gpreGlob.token_global.tok_keyword = kw_word;
2544
node = EXP_literal();
2548
// ** End date/time/timestamp support *
2556
//____________________________________________________________
2558
// Parse relational expression.
2561
static GPRE_NOD par_relational(gpre_req* request,
2562
USHORT * paren_count)
2564
assert_IS_REQ(request);
2566
bool local_flag = true;
2567
gpre_nod* expr1 = SQE_value(request, false, paren_count, &local_flag);
2568
if (gpreGlob.token_global.tok_keyword == KW_RIGHT_PAREN)
2570
if (gpreGlob.token_global.tok_keyword == KW_SEMI_COLON)
2572
for (const NOD_T* relational_ops = relationals; *relational_ops != (NOD_T) 0;
2575
if (expr1->nod_type == *relational_ops)
2580
bool negation = false;
2581
if (MSC_match(KW_NOT))
2584
// Check for one of the binary operators
2587
if (MSC_match(KW_IN))
2588
node = par_in(request, expr1);
2589
else if (MSC_match(KW_BETWEEN)) {
2590
node = MSC_node(nod_between, 3);
2591
node->nod_arg[0] = expr1;
2592
node->nod_arg[1] = SQE_value(request, false, NULL, NULL);
2594
node->nod_arg[2] = SQE_value(request, false, NULL, NULL);
2595
pair(node->nod_arg[0], node->nod_arg[1]);
2596
pair(node->nod_arg[0], node->nod_arg[2]);
2598
else if (MSC_match(KW_LIKE)) {
2599
node = MSC_node(nod_like, 3);
2600
node->nod_arg[0] = expr1;
2601
node->nod_arg[1] = SQE_value(request, false, NULL, NULL);
2602
pair(node->nod_arg[0], node->nod_arg[1]);
2603
if (MSC_match(KW_ESCAPE)) {
2604
gpre_nod* expr2 = SQE_value(request, false, NULL, NULL);
2605
node->nod_arg[2] = expr2;
2606
if (expr2->nod_type == nod_value) {
2607
ref* ref_value = (REF) expr2->nod_arg[0];
2608
ref_value->ref_field = MET_make_field("like_escape_character",
2609
dtype_text, 2, false);
2613
node->nod_count = 2;
2615
else if (MSC_match(KW_IS)) {
2616
if (MSC_match(KW_NOT))
2617
negation = !negation;
2618
if (!MSC_match(KW_NULL))
2619
CPR_s_error("NULL");
2620
if (expr1->nod_type == nod_array)
2621
expr1->nod_type = nod_field;
2622
node = MSC_unary(nod_missing, expr1);
2627
for (op = rel_ops; (int) op->rel_kw != (int) KW_none; op++)
2628
if (MSC_match(op->rel_kw))
2630
if ((int) op->rel_kw == (int) KW_none) {
2631
for (const NOD_T* relational_ops = relationals;
2632
*relational_ops != (NOD_T) 0; relational_ops++)
2634
if (expr1->nod_type == *relational_ops)
2637
CPR_s_error("<relational operator>");
2639
if ((int) op->rel_kw == (int) KW_STARTING)
2641
if (MSC_match(KW_ANY)) {
2642
if (!MSC_match(KW_LEFT_PAREN) || !MSC_match(KW_SELECT))
2643
CPR_s_error("<select clause> for ANY");
2644
node = implicit_any(request, expr1, op->rel_op, nod_any);
2647
else if (MSC_match(KW_ALL)) {
2648
if (!MSC_match(KW_LEFT_PAREN) || !MSC_match(KW_SELECT))
2649
CPR_s_error("<select clause> for ALL");
2650
if (op->rel_negation == nod_any
2651
|| op->rel_negation == nod_ansi_any
2652
|| op->rel_negation == nod_ansi_all)
2654
CPR_s_error("<relational operator> for ALL");
2656
node = implicit_any(request, expr1, op->rel_op, nod_ansi_all);
2660
node = MSC_binary(op->rel_op, expr1,
2661
SQE_value(request, false, NULL, NULL));
2662
pair(node->nod_arg[0], node->nod_arg[1]);
2666
return (negation) ? negate(node) : node;
2670
// Out of alphabetical order.
2671
static bool resolve_fields(GPRE_NOD& fields,
2673
gpre_rse* selection)
2675
bool aggregate = false;
2677
gpre_nod** ptr = fields->nod_arg;
2678
int count = fields->nod_count;
2680
for (int i = 0; i < count; i++)
2682
gpre_nod* node = ptr[i];
2684
if (node->nod_type == nod_asterisk) {
2685
const int old_count = count;
2686
fields = explode_asterisk(fields, i, selection);
2687
count = fields->nod_count;
2688
i += count - old_count;
2689
ptr = fields->nod_arg;
2692
aggregate |= SQE_resolve(node, NULL, selection);
2695
switch (node->nod_type)
2700
case nod_agg_average:
2702
if ((node->nod_arg[1]) &&
2703
(request->req_database->dbb_flags & DBB_v3))
2705
selection->rse_reduced =
2706
MSC_unary(nod_sort, node->nod_arg[1]);
2715
//____________________________________________________________
2717
// Parse the SQL equivalent of a record selection expression --
2718
// FROM, WHERE, and ORDER clauses. A field list may or may not
2722
static gpre_rse* par_rse(gpre_req* request,
2726
gpre_lls* stack = NULL;
2728
assert_IS_REQ(request);
2729
assert_IS_NOD(fields);
2731
// Get list and count of relations
2733
if (!MSC_match(KW_FROM))
2734
CPR_s_error("FROM");
2739
if (context = par_joined_relation(request, NULL)) {
2740
MSC_push((GPRE_NOD) context, &stack);
2745
} while (MSC_match(KW_COMMA));
2747
// Now allocate a record select expression
2748
// block for the beast and fill in what we already know.
2750
gpre_rse* select = (gpre_rse*) MSC_alloc(RSE_LEN(count));
2751
select->rse_count = count;
2754
select->rse_context[count] = (gpre_ctx*) MSC_pop(&stack);
2756
// If a field list has been presented, resolve references now
2758
bool aggregate = false;
2761
aggregate = resolve_fields(fields, request, select);
2763
select->rse_fields = fields;
2765
select->rse_reduced = fields;
2767
// Handle a boolean, if present
2769
if (MSC_match(KW_WITH)) {
2770
++request->req_in_where_clause;
2771
select->rse_boolean = SQE_boolean(request, 0);
2772
--request->req_in_where_clause;
2775
if (MSC_match(KW_GROUP)) {
2777
select->rse_group_by =
2778
SQE_list(par_udf_or_field_with_collate, request, false);
2779
gpre_nod** ptr = select->rse_group_by->nod_arg;
2780
for (const gpre_nod* const* const end =
2781
ptr + select->rse_group_by->nod_count; ptr < end; ptr++)
2783
if ((*ptr)->nod_type == nod_array)
2784
PAR_error("Array columns not permitted in GROUP BY clause");
2788
if (select->rse_group_by || aggregate) {
2789
if (validate_references(select->rse_fields, select->rse_group_by))
2791
("simple column reference not allowed in aggregate context");
2792
gpre_rse* sub_rse = select;
2793
map* subselect_map = (map*) MSC_alloc(sizeof(map));
2794
sub_rse->rse_map = subselect_map;
2795
if (select->rse_group_by)
2796
request->req_map = subselect_map;
2797
subselect_map->map_context = MSC_context(request);
2798
select = (gpre_rse*) MSC_alloc(RSE_LEN(0));
2799
select->rse_aggregate = sub_rse;
2802
select->rse_fields = copy_fields(sub_rse->rse_fields, subselect_map);
2804
if (MSC_match(KW_HAVING)) {
2805
++request->req_in_having_clause;
2806
select->rse_boolean = SQE_boolean(request, 0);
2807
--request->req_in_having_clause;
2808
if (validate_references(select->rse_boolean,
2809
sub_rse->rse_group_by))
2811
PAR_error("simple column reference in HAVING must be referenced in GROUP BY");
2816
// parse a user-specified access plan
2818
if (MSC_match(KW_PLAN))
2819
select->rse_plan = par_plan(request);
2825
//____________________________________________________________
2827
// Parse a SELECT (sans keyword) expression (except UNION). This
2828
// is called exclusively by SQE_select, which handles unions. Note:
2829
// if "union_rse" is non-null, we are a subsequent SELECT in a union.
2830
// In this case, check datatypes of the field against the rse field
2834
static gpre_rse* par_select( gpre_req* request, gpre_rse* union_rse)
2836
assert_IS_REQ(request);
2838
// Handle FIRST and SKIP clauses
2839
gpre_nod* rse_first = NULL;
2840
if (MSC_match(KW_FIRST))
2842
rse_first = MSC_node(nod_list, 1);
2843
rse_first->nod_arg[0] = SQE_value(request, false, NULL, NULL);
2846
gpre_nod* rse_skip = NULL;
2847
if (MSC_match(KW_SKIP))
2849
rse_skip = MSC_node(nod_list, 1);
2850
rse_skip->nod_arg[0] = SQE_value(request, false, NULL, NULL);
2853
// Handle the ALL and DISTINCT options
2855
const bool distinct = (!MSC_match(KW_ALL) && MSC_match(KW_DISTINCT));
2857
// Make select list out of select items
2859
++request->req_in_select_list;
2860
gpre_nod* s_list = SQE_list(SQE_value_or_null, request, true);
2861
--request->req_in_select_list;
2863
// If this is not a declare cursor statement and an INTO list is present,
2866
gpre_nod* into_list = NULL;
2867
if (!(request->req_flags & REQ_sql_declare_cursor))
2869
into_list = (MSC_match(KW_INTO)) ? SQE_list(SQE_variable, request,
2873
gpre_rse* select = par_rse(request, s_list, distinct);
2876
resolve_fields(rse_first, request, select);
2877
select->rse_sqlfirst = rse_first;
2880
resolve_fields(rse_skip, request, select);
2881
select->rse_sqlskip = rse_skip;
2883
if (select->rse_into = into_list)
2884
select->rse_flags |= RSE_singleton;
2886
if (union_rse && s_list->nod_count != union_rse->rse_fields->nod_count)
2887
PAR_error("select lists for UNION don't match");
2893
//____________________________________________________________
2895
// Parse a dumb SQL scalar statistical expression. Somebody else
2896
// has already eaten the SELECT on the front.
2899
static GPRE_NOD par_stat( gpre_req* request)
2901
assert_IS_REQ(request);
2903
request->req_in_subselect++;
2904
scope previous_scope;
2905
push_scope(request, &previous_scope);
2907
const bool distinct = (!MSC_match(KW_ALL) && MSC_match(KW_DISTINCT));
2909
request->req_in_select_list++;
2910
gpre_nod* item = par_udf(request);
2912
item = SQE_value(request, false, NULL, NULL);
2913
request->req_in_select_list--;
2915
gpre_nod* field_list = MSC_node(nod_list, 1);
2916
field_list->nod_arg[0] = item;
2917
gpre_rse* select = par_rse(request, field_list, distinct);
2918
select->rse_flags |= RSE_singleton;
2920
item = select->rse_fields->nod_arg[0];
2922
gpre_nod* node = MSC_node(nod_via, 3);
2923
node->nod_count = 0;
2924
node->nod_arg[0] = (GPRE_NOD) select;
2925
node->nod_arg[2] = MSC_node(nod_null, 0);
2926
node->nod_arg[1] = item;
2928
EXP_rse_cleanup(select);
2929
pop_scope(request, &previous_scope);
2930
request->req_in_subselect--;
2936
//____________________________________________________________
2938
// Parse a subscript value.
2941
static GPRE_NOD par_subscript( gpre_req* request)
2943
assert_IS_REQ(request);
2945
ref* reference = (REF) MSC_alloc(REF_LEN);
2946
gpre_nod* node = MSC_unary(nod_value, (GPRE_NOD) reference);
2948
// Special case literals
2950
if (gpreGlob.token_global.tok_type == tok_number) {
2951
node->nod_type = nod_literal;
2952
char* string = (TEXT *) MSC_alloc(gpreGlob.token_global.tok_length + 1);
2953
reference->ref_value = string;
2954
MSC_copy(gpreGlob.token_global.tok_string, gpreGlob.token_global.tok_length, string);
2959
if (!MSC_match(KW_COLON))
2960
CPR_s_error("<colon>");
2962
reference->ref_value = PAR_native_value(false, false);
2965
reference->ref_next = request->req_values;
2966
request->req_values = reference;
2973
//____________________________________________________________
2975
// Match several trailing parentheses.
2978
static void par_terminating_parens(
2979
USHORT * paren_count, USHORT * local_count)
2981
// Suspicious condition.
2982
if (*paren_count && paren_count == local_count)
2985
} while (--(*paren_count));
2989
//____________________________________________________________
2991
// Parse a user defined function. If the current token isn't one,
2992
// return NULL. Otherwise try to parse one. If things go badly,
2993
// complain bitterly.
2996
static GPRE_NOD par_udf( gpre_req* request)
3001
assert_IS_REQ(request);
3003
// Check for user defined functions
3004
// ** resolve only if an identifier *
3005
if ((isQuoted(gpreGlob.token_global.tok_type)) || gpreGlob.token_global.tok_type == tok_ident)
3006
SQL_resolve_identifier("<Udf Name>", NULL, NAME_SIZE);
3012
if (request->req_database)
3013
an_udf = MET_get_udf(request->req_database, gpreGlob.token_global.tok_string);
3015
/* no database was specified, check the metadata for all the databases
3016
for the existence of the udf */
3019
for (DBB db = gpreGlob.isc_databases; db; db = db->dbb_next)
3021
udf* tmp_udf = MET_get_udf(db, gpreGlob.token_global.tok_string);
3024
// udf was found in more than one database
3025
SCHAR s[ERROR_LENGTH];
3026
sprintf(s, "UDF %s is ambiguous", gpreGlob.token_global.tok_string);
3031
request->req_database = db;
3037
if ((SQL_DIALECT_V5 == gpreGlob.sw_sql_dialect) &&
3038
((dtype_sql_date == an_udf->udf_dtype) ||
3039
(dtype_sql_time == an_udf->udf_dtype) ||
3040
(dtype_int64 == an_udf->udf_dtype)))
3042
SQL_dialect1_bad_type(an_udf->udf_dtype);
3045
node = MSC_node(nod_udf, 2);
3046
node->nod_count = 1;
3047
node->nod_arg[1] = (GPRE_NOD) an_udf;
3050
if (!(gpreGlob.token_global.tok_keyword == KW_RIGHT_PAREN)) {
3051
// parse udf parameter references
3052
node->nod_arg[0] = SQE_list(SQE_value, request, false);
3054
if (an_udf->udf_args != node->nod_arg[0]->nod_count)
3055
PAR_error("count of UDF parameters doesn't match definition");
3057
// Match parameter types to the declared parameters
3058
gpre_nod** input = node->nod_arg[0]->nod_arg;
3059
for (gpre_fld* field = an_udf->udf_inputs;
3061
input++, field = field->fld_next)
3063
SQE_post_field(*input, field);
3067
node->nod_arg[0] = (GPRE_NOD) 0;
3068
node->nod_count = 0;
3071
par_terminating_parens(&local_count, &local_count);
3078
// Check for GEN_ID ()
3079
if (MSC_match(KW_GEN_ID)) {
3080
TEXT* gen_name = (TEXT *) MSC_alloc(NAME_SIZE);
3081
node = MSC_node(nod_gen_id, 2);
3082
node->nod_count = 1;
3084
SQL_resolve_identifier("<Generator Name>", gen_name, NAME_SIZE);
3085
node->nod_arg[1] = (GPRE_NOD) gen_name;
3087
if (!MSC_match(KW_COMMA))
3088
CPR_s_error("<comma>");
3089
node->nod_arg[0] = SQE_value(request, false, NULL, NULL);
3091
par_terminating_parens(&local_count, &local_count);
3095
// Check for context variables
3096
// ** Begin date/time/timestamp *
3097
if (MSC_match(KW_CURRENT_DATE))
3098
return MSC_node(nod_current_date, 0);
3099
else if (MSC_match(KW_CURRENT_TIME))
3100
return MSC_node(nod_current_time, 0);
3101
else if (MSC_match(KW_CURRENT_TIMESTAMP))
3102
return MSC_node(nod_current_timestamp, 0);
3103
// End date/time/timestamp *
3104
else if (MSC_match(KW_CURRENT_CONNECTION))
3105
return MSC_node(nod_current_connection, 0);
3106
else if (MSC_match(KW_CURRENT_ROLE))
3107
return MSC_node(nod_current_role, 0);
3108
else if (MSC_match(KW_CURRENT_TRANSACTION))
3109
return MSC_node(nod_current_transaction, 0);
3110
else if (MSC_match(KW_CURRENT_USER))
3111
return MSC_node(nod_user_name, 0);
3113
// End context variables *
3115
// Check for SQL II defined functions
3117
// ** Begin date/time/timestamp *
3118
if (MSC_match(KW_EXTRACT)) {
3119
node = MSC_node(nod_extract, 2);
3121
KWWORDS kw_word = gpreGlob.token_global.tok_keyword;
3122
if (MSC_match(KW_YEAR) || MSC_match(KW_MONTH) || MSC_match(KW_DAY) ||
3123
MSC_match(KW_HOUR) || MSC_match(KW_MINUTE) || MSC_match(KW_SECOND) ||
3124
MSC_match(KW_WEEKDAY) || MSC_match(KW_YEARDAY))
3126
node->nod_arg[0] = (gpre_nod*) kw_word;
3127
if (!MSC_match(KW_FROM))
3128
CPR_s_error("FROM");
3131
CPR_s_error("valid extract part");
3132
node->nod_arg[1] = SQE_value(request, false, NULL, NULL);
3134
par_terminating_parens(&local_count, &local_count);
3138
// End date/time/timestamp *
3140
if (MSC_match(KW_UPPER)) {
3141
node = MSC_node(nod_upcase, 1);
3143
node->nod_arg[0] = SQE_value(request, false, NULL, NULL);
3145
par_terminating_parens(&local_count, &local_count);
3149
if (MSC_match(KW_LOWER)) {
3150
node = MSC_node(nod_lowcase, 1);
3152
node->nod_arg[0] = SQE_value(request, false, NULL, NULL);
3154
par_terminating_parens(&local_count, &local_count);
3158
if (MSC_match(KW_CAST)) {
3159
node = MSC_node(nod_cast, 2);
3160
node->nod_count = 1;
3162
node->nod_arg[0] = SQE_value_or_null(request, false, 0, 0);
3163
if (!MSC_match(KW_AS))
3165
gpre_fld* field = (gpre_fld*) MSC_alloc(FLD_LEN);
3166
node->nod_arg[1] = (GPRE_NOD) field;
3167
SQL_par_field_dtype(request, field, false);
3168
SQL_par_field_collate(request, field);
3169
SQL_adjust_field_dtype(field);
3171
par_terminating_parens(&local_count, &local_count);
3179
//____________________________________________________________
3181
// Parse a user defined function or a field name.
3184
static GPRE_NOD par_udf_or_field(gpre_req* request,
3187
assert_IS_REQ(request);
3189
gpre_nod* node = par_udf(request);
3191
node = SQE_field(request, aster_ok);
3197
//____________________________________________________________
3199
// Parse a user defined function or a field name.
3200
// Allow the collate clause to follow.
3203
static GPRE_NOD par_udf_or_field_with_collate(gpre_req* request,
3205
USHORT * paren_count,
3209
assert_IS_REQ(request);
3211
gpre_nod* node = par_udf_or_field(request, aster_ok);
3212
if (gpreGlob.token_global.tok_keyword == KW_COLLATE)
3213
node = par_collate(request, node);
3219
//____________________________________________________________
3221
// Parse FOR UPDATE WITH LOCK clause
3224
static void par_update(gpre_rse *select, bool have_union, bool view_flag)
3226
// Parse FOR UPDATE if present
3227
if (MSC_match(KW_FOR)) {
3228
if (! MSC_match(KW_UPDATE)) {
3229
CPR_s_error("UPDATE");
3232
if (MSC_match(KW_OF)) {
3235
} while (MSC_match(KW_COMMA));
3237
select->rse_flags |= RSE_for_update;
3240
// Parse WITH LOCK if present
3241
if (MSC_match(KW_WITH)) {
3242
if (! MSC_match(KW_LOCK)) {
3243
CPR_s_error("LOCK");
3247
PAR_error("WITH LOCK in UNION");
3251
PAR_error("WITH LOCK in VIEW");
3254
select->rse_flags |= RSE_with_lock;
3258
//____________________________________________________________
3260
// Post a field or aggregate to a map. This is used to references
3261
// to aggregates and unions. Return a reference to the map (rather
3262
// than the expression itself). Post only the aggregates and fields,
3263
// not the computations around them.
3266
static GPRE_NOD post_fields( GPRE_NOD node, map* to_map)
3268
assert_IS_NOD(node);
3270
switch (node->nod_type) {
3271
/* Removed during fix to BUG_8021 - this would post a literal to
3272
* the map record for each literal used in an expression - which
3273
* would result in unneccesary data movement as the literal is more
3274
* easily experssed in the assignment portion of the mapping select
3277
* 1995-Jul-10 David Schnepper
3282
case nod_agg_average:
3286
return post_map(node, to_map);
3290
node->nod_arg[0] = post_fields(node->nod_arg[0], to_map);
3296
case nod_concatenate:
3304
gpre_nod** ptr = node->nod_arg;
3305
for (const gpre_nod* const* const end = ptr + node->nod_count;
3308
*ptr = post_fields(*ptr, to_map);
3312
// ** Begin date/time/timestamp support *
3314
node->nod_arg[1] = post_fields(node->nod_arg[1], to_map);
3316
// ** End date/time/timestamp support *
3323
//____________________________________________________________
3325
// Post a value expression to a map. This is used to references
3326
// to aggregates and unions. Return a reference to the map (rather
3327
// than the expression itself).
3330
static GPRE_NOD post_map( GPRE_NOD node, map* to_map)
3334
assert_IS_NOD(node);
3336
// Search existing map for equivalent expression. If we find one,
3337
// return a reference to it.
3339
if (node->nod_type == nod_map_ref) {
3340
element = (MEL) node->nod_arg[0];
3341
if (element->mel_context == to_map->map_context)
3345
for (element = to_map->map_elements; element; element = element->mel_next)
3346
if (compare_expr(node, element->mel_expr))
3347
return MSC_unary(nod_map_ref, (GPRE_NOD) element);
3349
// We need to make up a new map reference
3351
element = (MEL) MSC_alloc(sizeof(mel));
3352
element->mel_next = to_map->map_elements;
3353
to_map->map_elements = element;
3354
element->mel_position = to_map->map_count++;
3355
element->mel_expr = node;
3356
element->mel_context = to_map->map_context;
3358
// Make up a reference to the map element
3360
return MSC_unary(nod_map_ref, (GPRE_NOD) element);
3364
//____________________________________________________________
3366
// Copy a selection list to the map generated for a UNION
3367
// construct. Note at this level we want the full expression
3368
// selected posted, not just the portions that come from the
3369
// stream. Thus CAST and other operations will be passed into
3370
// a UNION. See BUG_8021 & BUG_8000 for examples.
3373
static GPRE_NOD post_select_list( GPRE_NOD fields, map* to_map)
3375
assert_IS_NOD(fields);
3377
gpre_nod* list = MSC_node(nod_list, fields->nod_count);
3379
for (USHORT i = 0; i < fields->nod_count; i++)
3380
list->nod_arg[i] = post_map(fields->nod_arg[i], to_map);
3386
//____________________________________________________________
3388
// Restore saved scoping information to the request block
3391
static void pop_scope(gpre_req* request, scope* save_scope)
3393
assert_IS_REQ(request);
3395
request->req_contexts = save_scope->req_contexts;
3396
request->req_scope_level = save_scope->req_scope_level;
3397
request->req_in_aggregate = save_scope->req_in_aggregate;
3398
request->req_in_select_list = save_scope->req_in_select_list;
3399
request->req_in_where_clause = save_scope->req_in_where_clause;
3400
request->req_in_having_clause = save_scope->req_in_having_clause;
3401
request->req_in_order_by_clause = save_scope->req_in_order_by_clause;
3405
//____________________________________________________________
3407
// Save scoping information from the request block
3410
static void push_scope(gpre_req* request, scope* save_scope)
3412
assert_IS_REQ(request);
3414
save_scope->req_contexts = request->req_contexts;
3415
save_scope->req_scope_level = request->req_scope_level;
3416
save_scope->req_in_aggregate = request->req_in_aggregate;
3417
save_scope->req_in_select_list = request->req_in_select_list;
3418
save_scope->req_in_where_clause = request->req_in_where_clause;
3419
save_scope->req_in_having_clause = request->req_in_having_clause;
3420
save_scope->req_in_order_by_clause = request->req_in_order_by_clause;
3421
save_scope->req_in_subselect = request->req_in_subselect;
3422
request->req_scope_level++;
3423
request->req_in_aggregate = 0;
3424
request->req_in_select_list = 0;
3425
request->req_in_where_clause = 0;
3426
request->req_in_having_clause = 0;
3427
request->req_in_order_by_clause = 0;
3428
request->req_in_subselect = 0;
3432
//____________________________________________________________
3434
// Attempt to resolve a field in a context. If successful, return
3435
// the field. Otherwise return NULL. Let somebody else worry about
3439
static gpre_fld* resolve(
3441
gpre_ctx* context, gpre_ctx** found_context, act** slice_action)
3445
assert_IS_NOD(node);
3447
gpre_rse* rs_stream = context->ctx_stream;
3449
for (SSHORT i = 0; i < rs_stream->rse_count; i++)
3451
resolve(node, rs_stream->rse_context[i], found_context,
3460
TOK f_token = (TOK) node->nod_arg[0];
3461
TOK q_token = (TOK) node->nod_arg[1];
3463
if (!(context->ctx_relation || context->ctx_procedure))
3466
// Handle unqualified fields first for simplicity
3469
field = MET_context_field(context, f_token->tok_string);
3471
// Now search alternatives for the qualifier
3473
gpre_sym* symbol = HSH_lookup(q_token->tok_string);
3475
/* This caused gpre to dump core if there are lower case
3476
table aliases in a where clause used with dialect 2 or 3
3478
if ( (symbol == NULL) && (sw_case || gpreGlob.sw_sql_dialect == SQL_DIALECT_V5))
3479
symbol = HSH_lookup2 (q_token->tok_string);
3482
/* So I replaced it with the following, don't know
3483
why we don't do a HSH_lookup2 in any case, but so it may be.
3486
if ((symbol == NULL))
3487
symbol = HSH_lookup2(q_token->tok_string);
3490
for (gpre_sym* temp_symbol = symbol; temp_symbol;
3491
temp_symbol = temp_symbol->sym_homonym)
3493
if (temp_symbol->sym_type == SYM_context) {
3494
symbol = temp_symbol;
3497
else if (temp_symbol->sym_type == SYM_relation) {
3498
symbol = temp_symbol;
3501
else if (temp_symbol->sym_type == SYM_procedure) {
3502
if (symbol->sym_type == SYM_relation)
3505
symbol = temp_symbol;
3511
if (symbol->sym_type == SYM_relation) {
3512
if ((gpre_rel*) symbol->sym_object == context->ctx_relation)
3513
field = MET_field(context->ctx_relation, f_token->tok_string);
3515
else if (symbol->sym_type == SYM_procedure) {
3516
if ((gpre_prc*) symbol->sym_object == context->ctx_procedure)
3517
field = MET_context_field(context, f_token->tok_string);
3519
else if (symbol->sym_type == SYM_context && symbol->sym_object == context)
3520
field = MET_context_field(context, f_token->tok_string);
3524
if (field && found_context)
3525
*found_context = context;
3527
// Check for valid array field
3529
// Set remaining fields for slice
3531
gpre_req* slice_req = (gpre_req*) node->nod_arg[2];
3532
if (slice_req && (slice = slice_req->req_slice) && slice_action)
3534
slice = slice_req->req_slice;
3535
ary* ary_info = field->fld_array_info;
3537
CPR_s_error("<array column>");
3538
if (ary_info->ary_dimension_count != slice->slc_dimensions)
3539
PAR_error("subscript count mismatch");
3540
slice->slc_field = field;
3541
slice->slc_parent_request = context->ctx_request;
3543
/* The action type maybe ACT_get_slice or ACT_put_slice
3544
set as a place holder */
3546
act* action = MSC_action(slice_req, ACT_get_slice);
3547
action->act_object = (REF) slice;
3548
*slice_action = action;
3550
else if ((slice_req = (gpre_req*) node->nod_arg[2]) && slice_action) {
3551
/* The action type maybe ACT_get_slice or ACT_put_slice
3552
set as a place holder */
3554
act* action = MSC_action(slice_req, ACT_get_slice);
3555
*slice_action = action;
3562
//____________________________________________________________
3564
// Attempt to resolve an asterisk in a context.
3565
// If successful, return the context. Otherwise return NULL.
3568
static gpre_ctx* resolve_asterisk( TOK q_token, gpre_rse* selection)
3570
for (int i = 0; i < selection->rse_count; i++) {
3571
gpre_ctx* context = selection->rse_context[i];
3572
gpre_rse* rs_stream = context->ctx_stream;
3574
if (context = resolve_asterisk(q_token, rs_stream))
3578
gpre_sym* symbol = HSH_lookup(q_token->tok_string);
3579
for (; symbol; symbol = symbol->sym_homonym)
3580
if (symbol->sym_type == SYM_relation &&
3581
(gpre_rel*) symbol->sym_object == context->ctx_relation)
3585
else if (symbol->sym_type == SYM_procedure &&
3586
(gpre_prc*) symbol->sym_object == context->ctx_procedure)
3590
else if (symbol->sym_type == SYM_context &&
3591
(gpre_ctx*) symbol->sym_object == context)
3601
//____________________________________________________________
3603
// Set field reference for any host variables in expr to field_ref.
3606
static void set_ref( GPRE_NOD expr, gpre_fld* field_ref)
3608
assert_IS_NOD(expr);
3610
ref* re = (REF) expr->nod_arg[0];
3611
switch (expr->nod_type) {
3613
re->ref_field = field_ref;
3620
case nod_agg_average:
3628
case nod_concatenate:
3631
gpre_nod** ptr = expr->nod_arg;
3632
for (const gpre_nod* const* const end = ptr + expr->nod_count;
3635
set_ref(*ptr, field_ref);
3639
// ** Begin date/time/timestamp support *
3641
set_ref(expr->nod_arg[1], field_ref);
3643
// ** End date/time/timestamp support *
3648
//____________________________________________________________
3650
// Return the uppercase version of
3651
// the input string.
3654
static char* upcase_string(const char* p)
3657
char* const s = (char *) MSC_alloc(strlen(p) + 1);
3661
while ((c = *p++) && (++l <= NAME_SIZE)) {
3670
//____________________________________________________________
3672
// validate that top level field references
3673
// in a select with a group by, real or imagined,
3674
// resolve to grouping fields. Ignore constants
3675
// and aggregates. If there's no group_by list,
3676
// then it's an imaginary group by (a top level
3677
// aggregation, and nothing can be referenced
3681
static bool validate_references(const gpre_nod* fields,
3682
const gpre_nod* group_by)
3684
assert_IS_NOD(fields);
3685
assert_IS_NOD(group_by);
3690
if (fields->nod_type == nod_field) {
3693
const ref* fref = (REF) fields->nod_arg[0];
3695
bool context_match = false;
3696
const gpre_nod* const* ptr = group_by->nod_arg;
3697
for (const gpre_nod* const* const end = ptr + group_by->nod_count;
3700
const ref* gref = (REF) (*ptr)->nod_arg[0];
3701
if (gref->ref_context == fref->ref_context) {
3702
if (gref->ref_field == fref->ref_field)
3704
context_match = true;
3707
return context_match;
3710
if (fields->nod_type == nod_agg_count ||
3711
fields->nod_type == nod_agg_max ||
3712
fields->nod_type == nod_agg_min ||
3713
fields->nod_type == nod_agg_total ||
3714
fields->nod_type == nod_agg_average ||
3715
fields->nod_type == nod_aggregate)
3720
if (fields->nod_type == nod_any || fields->nod_type == nod_ansi_any ||
3721
fields->nod_type == nod_ansi_all)
3723
const gpre_rse* any = (gpre_rse*) fields->nod_arg[0];
3724
return validate_references(any->rse_boolean, group_by);
3727
if ((fields->nod_type == nod_gen_id) || (fields->nod_type == nod_udf))
3728
return validate_references(fields->nod_arg[0], group_by);
3730
bool invalid = false;
3731
const gpre_nod* const* ptr = fields->nod_arg;
3732
for (const gpre_nod* const* const end = ptr + fields->nod_count; ptr < end;
3735
switch ((*ptr)->nod_type) {
3738
const mel* element = (MEL) (*ptr)->nod_arg[0];
3739
const gpre_nod* node = element->mel_expr;
3740
if (node->nod_type != nod_agg_count &&
3741
node->nod_type != nod_agg_max &&
3742
node->nod_type != nod_agg_min &&
3743
node->nod_type != nod_agg_total &&
3744
node->nod_type != nod_agg_average &&
3745
node->nod_type != nod_aggregate)
3747
invalid |= validate_references(node, group_by);
3771
case nod_concatenate:
3773
invalid |= validate_references(*ptr, group_by);