~ubuntu-branches/ubuntu/karmic/firebird2.1/karmic

« back to all changes in this revision

Viewing changes to src/gpre/sqe.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Damyan Ivanov
  • Date: 2008-05-26 23:59:25 UTC
  • Revision ID: james.westby@ubuntu.com-20080526235925-2pnqj6nxpppoeaer
Tags: upstream-2.1.0.17798-0.ds2
ImportĀ upstreamĀ versionĀ 2.1.0.17798-0.ds2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//____________________________________________________________
 
2
//  
 
3
//              PROGRAM:        C Preprocessor
 
4
//              MODULE:         sqe.cpp
 
5
//              DESCRIPTION:    SQL expression parser
 
6
//  
 
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
 
11
//  
 
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.
 
16
//  
 
17
//  The Original Code was created by Inprise Corporation
 
18
//  and its predecessors. Portions created by Inprise Corporation are
 
19
//  Copyright (C) Inprise Corporation.
 
20
//  
 
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
 
26
//  
 
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)
 
30
//  
 
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)
 
34
//  
 
35
//  TMN (Mike Nordell) 11.APR.2001 - Reduce compiler warnings
 
36
//  
 
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.
 
41
//
 
42
//____________________________________________________________
 
43
//
 
44
//
 
45
 
 
46
#include "firebird.h"
 
47
#include <stdio.h>
 
48
#include <string.h>
 
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"
 
62
 
 
63
 
 
64
struct scope {
 
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 
 
73
};
 
74
 
 
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*);
 
121
 
 
122
 
 
123
 
 
124
 
 
125
struct ops {
 
126
        enum nod_t rel_op;
 
127
        enum kwwords rel_kw;
 
128
        enum nod_t rel_negation;
 
129
};
 
130
 
 
131
static const ops rel_ops[] =
 
132
{
 
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 }
 
146
};
 
147
 
 
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}
 
157
};
 
158
#endif
 
159
 
 
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 }
 
170
};
 
171
 
 
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
 
176
};
 
177
 
 
178
 
 
179
//____________________________________________________________
 
180
//  
 
181
//              Parse an OR boolean expression.
 
182
//  
 
183
 
 
184
GPRE_NOD SQE_boolean( gpre_req* request, USHORT * paren_count)
 
185
{
 
186
        USHORT local_count;
 
187
 
 
188
        assert_IS_REQ(request);
 
189
 
 
190
        if (!paren_count) {
 
191
                local_count = 0;
 
192
                paren_count = &local_count;
 
193
        }
 
194
 
 
195
        gpre_nod* expr1 = par_and(request, paren_count);
 
196
 
 
197
        if (!MSC_match(KW_OR) && !MSC_match(KW_OR1)) {
 
198
                par_terminating_parens(paren_count, &local_count);
 
199
                return expr1;
 
200
        }
 
201
 
 
202
        expr1 = MSC_binary(nod_or, expr1, SQE_boolean(request, paren_count));
 
203
        par_terminating_parens(paren_count, &local_count);
 
204
 
 
205
        return expr1;
 
206
}
 
207
 
 
208
 
 
209
//____________________________________________________________
 
210
//  
 
211
//              Parse a reference to a relation name
 
212
//              and generate a context for it.
 
213
//  
 
214
 
 
215
gpre_ctx* SQE_context(gpre_req* request)
 
216
{
 
217
        SCHAR r_name[NAME_SIZE], db_name[NAME_SIZE], owner_name[NAME_SIZE];
 
218
        SCHAR s[ERROR_LENGTH];
 
219
 
 
220
        assert_IS_REQ(request);
 
221
 
 
222
        gpre_ctx* context = MSC_context(request);
 
223
        SQL_relation_name(r_name, db_name, owner_name);
 
224
 
 
225
        if (!(context->ctx_relation =
 
226
                  SQL_relation(request, r_name, db_name, owner_name, false)))
 
227
        {
 
228
                // check for a procedure 
 
229
                gpre_prc* procedure = context->ctx_procedure =
 
230
                        SQL_procedure(request, r_name, db_name, owner_name, false);
 
231
                if (procedure)
 
232
                {
 
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)
 
242
                                {
 
243
                                        PAR_error("count of input values doesn't match count of parameters");
 
244
                                }
 
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)
 
248
                                {
 
249
                                        SQE_post_field(*input, field);
 
250
                                }
 
251
                        }
 
252
                }
 
253
                else {
 
254
                        if (owner_name[0])
 
255
                                sprintf(s, "table %s.%s not defined", owner_name, r_name);
 
256
                        else
 
257
                                sprintf(s, "table %s not defined", r_name);
 
258
                        PAR_error(s);
 
259
                }
 
260
 
 
261
        }
 
262
 
 
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. 
 
266
 
 
267
        gpre_sym* symbol = gpreGlob.token_global.tok_symbol;
 
268
        if (symbol && symbol->sym_type == SYM_keyword) {
 
269
                if (!gpreGlob.token_global.tok_length)
 
270
                        CPR_token();
 
271
                return context;
 
272
        }
 
273
 
 
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 
 
277
 
 
278
        gpre_ctx* conflict;
 
279
        for (conflict = request->req_contexts; conflict;
 
280
                 conflict = conflict->ctx_next)
 
281
        {
 
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))
 
288
                {
 
289
                        break;
 
290
                }
 
291
        }
 
292
 
 
293
        if (conflict) {
 
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";
 
299
                else
 
300
                        error_type = "context";
 
301
 
 
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);
 
305
                PAR_error(s);
 
306
        }
 
307
 
 
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;
 
312
        HSH_insert(symbol);
 
313
 
 
314
        PAR_get_token();
 
315
 
 
316
        return context;
 
317
}
 
318
 
 
319
 
 
320
//____________________________________________________________
 
321
//  
 
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.
 
328
//  
 
329
 
 
330
GPRE_NOD SQE_field(gpre_req* request,
 
331
                                   bool aster_ok)
 
332
{
 
333
        GPRE_NOD node;
 
334
        gpre_req* slice_req;
 
335
 
 
336
        assert_IS_REQ(request);
 
337
 
 
338
        gpre_lls* upper_dim = NULL;
 
339
        gpre_lls* lower_dim = NULL;
 
340
        tok hold_token;
 
341
        hold_token.tok_type = tok_t(0);
 
342
 
 
343
        if (aster_ok && MSC_match(KW_ASTERISK)) {
 
344
                node = MSC_node(nod_asterisk, 1);
 
345
                return node;
 
346
        }
 
347
 
 
348
//  if the token isn't an identifier, complain 
 
349
 
 
350
        SQL_resolve_identifier("<column name>", NULL, NAME_SIZE);
 
351
 
 
352
//  For domains we can't be resolving tokens to field names
 
353
//  in the CHECK constraint. 
 
354
 
 
355
        TEXT s[ERROR_LENGTH];
 
356
                
 
357
        act* action;
 
358
        if (request &&
 
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))
 
363
        {
 
364
                fb_utils::snprintf(s, sizeof(s),
 
365
                                "Illegal use of identifier: %s in domain constraint",
 
366
                                gpreGlob.token_global.tok_string);
 
367
                PAR_error(s);
 
368
        }
 
369
 
 
370
 
 
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
 
376
//  precisely match.
 
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 
 
381
//  
 
382
 
 
383
//  if the request is null, make a deferred name block
 
384
 
 
385
        if (!request || !request->req_contexts || request->req_in_select_list) {
 
386
                node = MSC_node(nod_deferred, 3);
 
387
                node->nod_count = 0;
 
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);
 
392
                CPR_token();
 
393
 
 
394
                if (MSC_match(KW_DOT)) {
 
395
                        if ((int) gpreGlob.token_global.tok_keyword == (int) KW_ASTERISK) {
 
396
                                if (aster_ok)
 
397
                                        node->nod_type = nod_asterisk;
 
398
                                else
 
399
                                        PAR_error("* not allowed");
 
400
                        }
 
401
                        else {
 
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);
 
407
                        }
 
408
                        CPR_token();
 
409
                }
 
410
                if (MSC_match(KW_L_BRCKET)) {
 
411
                        // We have a complete array or an array slice here 
 
412
 
 
413
                        if (!MSC_match(KW_R_BRCKET)) {
 
414
                                slice_req = MSC_request(REQ_slice);
 
415
                                int count = 0;
 
416
                                do {
 
417
                                        count++;
 
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);
 
425
                                        }
 
426
                                        else
 
427
                                                MSC_push(tail, &upper_dim);
 
428
                                } while (MSC_match(KW_COMMA));
 
429
 
 
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;
 
437
                                while (lower_dim) {
 
438
                                        --tail_ptr;
 
439
                                        tail_ptr->slc_lower = MSC_pop(&lower_dim);
 
440
                                        tail_ptr->slc_upper = MSC_pop(&upper_dim);
 
441
                                }
 
442
                                node->nod_arg[2] = (GPRE_NOD) slice_req;
 
443
 
 
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
 
448
                                 */
 
449
                                node->nod_count = 3;
 
450
                        }
 
451
                        else {
 
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;
 
455
                        }
 
456
                }
 
457
 
 
458
                return node;
 
459
        }
 
460
 
 
461
        gpre_ctx* context;
 
462
        ref* reference = (REF) MSC_alloc(REF_LEN);
 
463
        node = MSC_unary(nod_field, (GPRE_NOD) reference);
 
464
 
 
465
        gpre_sym* symbol = gpreGlob.token_global.tok_symbol;
 
466
        if (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 */
 
470
 
 
471
                if (symbol->sym_type != SYM_field) {
 
472
                        for (gpre_sym* temp_symbol = symbol; temp_symbol;
 
473
                                 temp_symbol = temp_symbol->sym_homonym)
 
474
                        {
 
475
                                if (temp_symbol->sym_type == SYM_context) {
 
476
                                        symbol = temp_symbol;
 
477
                                        break;
 
478
                                }
 
479
                                else if (temp_symbol->sym_type == SYM_relation) {
 
480
                                        symbol = temp_symbol;
 
481
                                        continue;
 
482
                                }
 
483
                                else if (temp_symbol->sym_type == SYM_procedure) {
 
484
                                        if (symbol->sym_type == SYM_relation)
 
485
                                                continue;
 
486
                                        else {
 
487
                                                symbol = temp_symbol;
 
488
                                                continue;
 
489
                                        }
 
490
                                }
 
491
                        }
 
492
 
 
493
                        if (symbol->sym_type == SYM_context) {
 
494
                                context = symbol->sym_object;
 
495
                                CPR_token();
 
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);
 
501
                                if (!
 
502
                                        (reference->ref_field =
 
503
                                         MET_context_field(context, gpreGlob.token_global.tok_string)))
 
504
                                {
 
505
                                        sprintf(s, "column \"%s\" not in context",
 
506
                                                        gpreGlob.token_global.tok_string);
 
507
                                        PAR_error(s);
 
508
                                }
 
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))
 
514
                                        {
 
515
                                                SQL_dialect1_bad_type(field_dtype);
 
516
                                        }
 
517
                                }
 
518
                                reference->ref_context = context;
 
519
                                CPR_token();
 
520
                                return node;
 
521
                        }
 
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");
 
526
 
 
527
                                CPR_token();
 
528
 
 
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.
 
535
                                 */
 
536
 
 
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;
 
541
                                }
 
542
                                else {
 
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)
 
547
                                        {
 
548
                                                if (context->ctx_relation == relation &&
 
549
                                                                (reference->ref_field =
 
550
                                                                 MET_field(context->ctx_relation,
 
551
                                                                                   gpreGlob.token_global.tok_string)))
 
552
                                                {
 
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))
 
558
                                                                {
 
559
                                                                        SQL_dialect1_bad_type(field_dtype);
 
560
                                                                }
 
561
                                                        }
 
562
                                                        reference->ref_context = context;
 
563
                                                        CPR_token();
 
564
                                                        if (reference->ref_field->fld_array_info) {
 
565
                                                                node =
 
566
                                                                        EXP_array(request, reference->ref_field,
 
567
                                                                                true, true);
 
568
                                                                node->nod_arg[0] = (GPRE_NOD) reference;
 
569
                                                        }
 
570
                                                        return node;
 
571
                                                }
 
572
                                        }
 
573
 
 
574
                                        fb_utils::snprintf(s, sizeof(s),
 
575
                                                        "column \"%s\" not in context",
 
576
                                                        gpreGlob.token_global.tok_string);
 
577
                                        PAR_error(s);
 
578
                                }
 
579
                        }
 
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");
 
584
                                CPR_token();
 
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)
 
590
                                {
 
591
                                        if (context->ctx_procedure == procedure &&
 
592
                                                        (reference->ref_field =
 
593
                                                         MET_context_field(context, gpreGlob.token_global.tok_string)))
 
594
                                        {
 
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))
 
600
                                                        {
 
601
                                                                SQL_dialect1_bad_type(field_dtype);
 
602
                                                        }
 
603
                                                }
 
604
                                                reference->ref_context = context;
 
605
                                                if (reference->ref_field->fld_array_info) {
 
606
                                                        node =
 
607
                                                                EXP_array(request, reference->ref_field, true,
 
608
                                                                                  true);
 
609
                                                        node->nod_arg[0] = (GPRE_NOD) reference;
 
610
                                                }
 
611
                                                CPR_token();
 
612
                                                return node;
 
613
                                        }
 
614
                                }
 
615
 
 
616
                                fb_utils::snprintf(s, sizeof(s),
 
617
                                        "column \"%s\" not in context", gpreGlob.token_global.tok_string);
 
618
                                PAR_error(s);
 
619
                        }
 
620
                }
 
621
        }
 
622
 
 
623
//  Hmmm.  So it wasn't a qualified field.  Try any field. 
 
624
 
 
625
        SQL_resolve_identifier("<Column Name>", NULL, NAME_SIZE);
 
626
        for (context = request->req_contexts; context;
 
627
                 context = context->ctx_next)
 
628
        {
 
629
                if (reference->ref_field = MET_context_field(context,
 
630
                                                                                                         gpreGlob.token_global.tok_string))
 
631
                {
 
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))
 
637
                                {
 
638
                                        SQL_dialect1_bad_type(field_dtype);
 
639
                                }
 
640
                        }
 
641
                        reference->ref_context = context;
 
642
 
 
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
 
645
                           ** continue.
 
646
                         */
 
647
                        if (hold_token.tok_type != 0) {
 
648
                                gpreGlob.prior_token = gpreGlob.token_global;
 
649
                                gpreGlob.token_global = hold_token;
 
650
                        }
 
651
                        else
 
652
                                CPR_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;
 
656
                        }
 
657
                        if (request->req_map)
 
658
                                return post_map(node, request->req_map);
 
659
                        return node;
 
660
                }
 
661
        }
 
662
 
 
663
        CPR_s_error("<column name>");
 
664
        return NULL;                            // silence compiler 
 
665
}
 
666
 
 
667
 
 
668
//____________________________________________________________
 
669
//  
 
670
//              Parse a list of "things", separated by commas.  Return the
 
671
//              whole mess in a list node.
 
672
//  
 
673
 
 
674
GPRE_NOD SQE_list(pfn_SQE_list_cb routine,
 
675
                                  gpre_req* request,
 
676
                                  bool aster_ok)
 
677
{
 
678
        assert_IS_REQ(request);
 
679
 
 
680
        gpre_lls* stack = NULL;
 
681
        int count = 0;
 
682
 
 
683
        do {
 
684
                count++;
 
685
                MSC_push((*routine) (request, aster_ok, NULL, NULL), &stack);
 
686
        } while (MSC_match(KW_COMMA));
 
687
 
 
688
        gpre_nod* list = MSC_node(nod_list, (SSHORT) count);
 
689
        gpre_nod** ptr = &list->nod_arg[count];
 
690
 
 
691
        while (stack)
 
692
                *--ptr = (GPRE_NOD) MSC_pop(&stack);
 
693
 
 
694
        return list;
 
695
}
 
696
 
 
697
 
 
698
//____________________________________________________________
 
699
//  
 
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,
 
703
//       "INDICATOR".
 
704
//  
 
705
 
 
706
REF SQE_parameter(gpre_req* request,
 
707
                                  bool aster_ok)
 
708
{
 
709
        REF reference;
 
710
        SCHAR* string;
 
711
 
 
712
        assert_IS_REQ(request);
 
713
 
 
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;
 
720
                CPR_token();
 
721
                return reference;
 
722
        }
 
723
 
 
724
        if ((isQuoted(gpreGlob.token_global.tok_type) && gpreGlob.sw_sql_dialect == 1) ||
 
725
                gpreGlob.token_global.tok_type == tok_sglquoted)
 
726
        {
 
727
        /** 
 
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 
 
730
    literal.
 
731
    ***/
 
732
                reference = (REF) MSC_alloc(REF_LEN);
 
733
                string = (TEXT *) MSC_alloc(gpreGlob.token_global.tok_length + 3);
 
734
                string[0] = '\"';
 
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;
 
740
                CPR_token();
 
741
                return reference;
 
742
        }
 
743
 
 
744
        if (gpreGlob.token_global.tok_keyword == KW_PLUS || gpreGlob.token_global.tok_keyword == KW_MINUS)
 
745
        {
 
746
                int sign;
 
747
                if (gpreGlob.token_global.tok_keyword == KW_MINUS)
 
748
                        sign = 1;
 
749
                else
 
750
                        sign = 0;
 
751
                CPR_token();
 
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);
 
756
                if (sign)
 
757
                        *s++ = '-';
 
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;
 
761
                CPR_token();
 
762
                return reference;
 
763
        }
 
764
 
 
765
        if (!MSC_match(KW_COLON))
 
766
                CPR_s_error("<host variable> or <constant>");
 
767
 
 
768
        if (gpreGlob.token_global.tok_type != tok_ident)
 
769
                CPR_s_error("<host variable> or <constant>");
 
770
 
 
771
        reference = (REF) MSC_alloc(REF_LEN);
 
772
 
 
773
        for (gpre_sym* symbol = gpreGlob.token_global.tok_symbol; symbol;
 
774
                symbol = symbol->sym_homonym)
 
775
        {
 
776
                if (symbol->sym_type == SYM_variable) {
 
777
                        reference->ref_field = (gpre_fld*) symbol->sym_object;
 
778
                        break;
 
779
                }
 
780
        }
 
781
 
 
782
        reference->ref_value = PAR_native_value(false, false);
 
783
 
 
784
        MSC_match(KW_INDICATOR);
 
785
 
 
786
        if (MSC_match(KW_COLON))
 
787
                reference->ref_null_value = PAR_native_value(false, false);
 
788
 
 
789
        return reference;
 
790
}
 
791
 
 
792
 
 
793
//____________________________________________________________
 
794
//  
 
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".
 
798
//  
 
799
 
 
800
void SQE_post_field( GPRE_NOD input, gpre_fld* field)
 
801
{
 
802
        if (!input || !field)
 
803
                return;
 
804
 
 
805
        assert_IS_NOD(input);
 
806
 
 
807
        switch (input->nod_type)
 
808
        {
 
809
        case nod_value:
 
810
                {
 
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
 
815
                                 */
 
816
                                reference->ref_field = field;
 
817
                        }
 
818
                        return;
 
819
                }
 
820
 
 
821
        case nod_field:
 
822
        case nod_literal:
 
823
        case nod_deferred:
 
824
        case nod_array:
 
825
                return;
 
826
 
 
827
        case nod_map_ref:
 
828
                {
 
829
                        mel* element = (MEL) input->nod_arg[0];
 
830
                        gpre_nod* node = element->mel_expr;
 
831
                        SQE_post_field(node, field);
 
832
                        return;
 
833
                }
 
834
 
 
835
        default:
 
836
                {
 
837
                        gpre_nod** ptr = input->nod_arg;
 
838
                        for (const gpre_nod* const* const end = ptr + input->nod_count;
 
839
                                ptr < end; ptr++)
 
840
                        {
 
841
                                SQE_post_field(*ptr, field);
 
842
                        }
 
843
                        return;
 
844
                }
 
845
        }
 
846
}
 
847
 
 
848
 
 
849
//____________________________________________________________
 
850
//  
 
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.
 
855
//  
 
856
 
 
857
REF SQE_post_reference(gpre_req* request, gpre_fld* field, gpre_ctx* context,
 
858
        GPRE_NOD node)
 
859
{
 
860
        REF reference;
 
861
 
 
862
        assert_IS_REQ(request);
 
863
        assert_IS_NOD(node);
 
864
 
 
865
//  If the beast is already a field reference, get component parts 
 
866
 
 
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;
 
871
        }
 
872
 
 
873
//  See if there is already a reference to this guy.  If so, return it. 
 
874
 
 
875
        for (reference = request->req_references; reference;
 
876
                 reference = reference->ref_next)
 
877
        {
 
878
                        if ((reference->ref_expr && compare_expr(node, reference->ref_expr))
 
879
                                || (!reference->ref_expr && field == reference->ref_field
 
880
                                        && context == reference->ref_context))
 
881
                {
 
882
                        return reference;
 
883
                }
 
884
        }
 
885
 
 
886
//  If there isn't a field given, make one up 
 
887
 
 
888
        if (!field) {
 
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;
 
893
        }
 
894
 
 
895
//  No reference -- make one 
 
896
 
 
897
        reference = (REF) MSC_alloc(REF_LEN);
 
898
        reference->ref_context = context;
 
899
        reference->ref_field = field;
 
900
        reference->ref_expr = node;
 
901
 
 
902
        reference->ref_next = request->req_references;
 
903
        request->req_references = reference;
 
904
 
 
905
        return reference;
 
906
}
 
907
 
 
908
 
 
909
//____________________________________________________________
 
910
//  
 
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.
 
916
//  
 
917
//              If the expression contains a global aggregate, return true,
 
918
//              otherwise false.
 
919
//  
 
920
 
 
921
bool SQE_resolve(GPRE_NOD node,
 
922
                                 gpre_req* request,
 
923
                                 gpre_rse* selection)
 
924
{
 
925
        bool result = false;
 
926
        act* slice_action = 0;
 
927
 
 
928
        assert_IS_REQ(request);
 
929
        assert_IS_NOD(node);
 
930
 
 
931
        switch (node->nod_type) {
 
932
        case nod_plus:
 
933
        case nod_minus:
 
934
        case nod_times:
 
935
        case nod_divide:
 
936
        case nod_negate:
 
937
        case nod_upcase:
 
938
        case nod_lowcase:
 
939
        case nod_concatenate:
 
940
        case nod_cast:
 
941
                {
 
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);
 
946
                        return result;
 
947
                }
 
948
 
 
949
        case nod_agg_max:
 
950
        case nod_agg_min:
 
951
        case nod_agg_total:
 
952
        case nod_agg_average:
 
953
        case nod_agg_count:
 
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)
 
960
                        {
 
961
                                PAR_error
 
962
                                        ("Array columns not permitted in aggregate functions");
 
963
                        }
 
964
                }
 
965
                return true;
 
966
 
 
967
        case nod_udf:
 
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);
 
973
                }
 
974
                return result;
 
975
 
 
976
        case nod_gen_id:
 
977
                return SQE_resolve(node->nod_arg[0], request, selection);
 
978
 
 
979
// ** Begin date/time/timestamp support *
 
980
        case nod_extract:
 
981
                result |= SQE_resolve(node->nod_arg[1], request, selection);
 
982
                return result;
 
983
// ** End date/time/timestamp support *
 
984
 
 
985
        case nod_deferred:
 
986
                break;
 
987
 
 
988
        default:
 
989
                return false;
 
990
        }
 
991
 
 
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];
 
995
        if (q_token)
 
996
                q_token->tok_symbol = HSH_lookup(q_token->tok_string);
 
997
 
 
998
        gpre_fld* field = NULL;
 
999
 
 
1000
        gpre_ctx* context;
 
1001
        if (request)
 
1002
                for (context = request->req_contexts; context;
 
1003
                         context = context->ctx_next)
 
1004
                {
 
1005
                        if (!context->ctx_stream
 
1006
                                && (field = resolve(node, context, 0, &slice_action))) break;
 
1007
                }
 
1008
        else
 
1009
                for (SSHORT i = 0; i < selection->rse_count; i++) {
 
1010
                        if (field = resolve(node, selection->rse_context[i], &context, &slice_action))
 
1011
                                break;
 
1012
                }
 
1013
 
 
1014
        if (!field) {
 
1015
                SCHAR s[ERROR_LENGTH];
 
1016
                if (q_token)
 
1017
                        fb_utils::snprintf(s, sizeof(s),
 
1018
                                        "column \"%s.%s\" cannot be resolved",
 
1019
                                        q_token->tok_string, f_token->tok_string);
 
1020
                else
 
1021
                        fb_utils::snprintf(s, sizeof(s),
 
1022
                                        "column \"%s\" cannot be resolved",
 
1023
                                        f_token->tok_string);
 
1024
                PAR_error(s);
 
1025
        }
 
1026
 
 
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)))
 
1033
        {
 
1034
                SQL_dialect1_bad_type(field->fld_dtype);
 
1035
        }
 
1036
 
 
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;
 
1041
 
 
1042
//  donot reinit if this is a nod_deffered type 
 
1043
        if (node->nod_type != nod_deferred)
 
1044
                node->nod_count = 0;
 
1045
 
 
1046
 
 
1047
        node->nod_type = nod_field;
 
1048
        node->nod_arg[0] = (GPRE_NOD) reference;
 
1049
 
 
1050
        return false;
 
1051
}
 
1052
 
 
1053
 
 
1054
//____________________________________________________________
 
1055
//  
 
1056
//              Parse a SELECT (sans keyword) expression.
 
1057
//  
 
1058
 
 
1059
gpre_rse* SQE_select(gpre_req* request,
 
1060
                           bool view_flag)
 
1061
{
 
1062
        gpre_lls* context_stack = NULL;
 
1063
        gpre_ctx* context = 0;
 
1064
        bool have_union = false;
 
1065
 
 
1066
        assert_IS_REQ(request);
 
1067
 
 
1068
        map* const old_map = request->req_map;
 
1069
 
 
1070
//  Get components of union.  Most likely there isn't one, so this is
 
1071
//  probably wasted work.  
 
1072
 
 
1073
        gpre_rse* select = NULL;
 
1074
        gpre_rse* rse1 = NULL;
 
1075
        select = rse1 = par_select(request, NULL);
 
1076
 
 
1077
//  "Look for ... the UNION label ... " 
 
1078
        while (MSC_match(KW_UNION)) {
 
1079
 
 
1080
                have_union = true;
 
1081
                const bool union_all = MSC_match(KW_ALL);
 
1082
                if (!MSC_match(KW_SELECT))
 
1083
                        CPR_s_error("SELECT");
 
1084
 
 
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);
 
1089
 
 
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. */
 
1092
 
 
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;
 
1099
 
 
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);
 
1104
 
 
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);
 
1108
 
 
1109
                select->rse_into = rse1->rse_into;
 
1110
                if (!union_all)
 
1111
                        select->rse_reduced = select->rse_fields;
 
1112
 
 
1113
                // Result of this UNION might be the left side of the NEXT UNION 
 
1114
                rse1 = select;
 
1115
        }
 
1116
 
 
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 
 
1120
 
 
1121
        while (context_stack) {
 
1122
                while (context->ctx_next)
 
1123
                        context = context->ctx_next;
 
1124
                context->ctx_next = (gpre_ctx*) MSC_pop(&context_stack);
 
1125
        }
 
1126
 
 
1127
//  Pick up any dangling ORDER clause 
 
1128
 
 
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;
 
1134
 
 
1135
        return select;
 
1136
}
 
1137
 
 
1138
 
 
1139
//____________________________________________________________
 
1140
//  
 
1141
//              Parse either of the low precedence operators + and -.
 
1142
//  
 
1143
 
 
1144
GPRE_NOD SQE_value(gpre_req* request,
 
1145
                                   bool aster_ok,
 
1146
                                   USHORT * paren_count,
 
1147
                                   bool * bool_flag)
 
1148
{
 
1149
        USHORT local_count;
 
1150
        bool local_flag;
 
1151
 
 
1152
        assert_IS_REQ(request);
 
1153
 
 
1154
        if (!paren_count) {
 
1155
                local_count = 0;
 
1156
                paren_count = &local_count;
 
1157
        }
 
1158
        if (!bool_flag) {
 
1159
                local_flag = false;
 
1160
                bool_flag = &local_flag;
 
1161
        }
 
1162
 
 
1163
        MSC_match(KW_PLUS);
 
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);
 
1168
                return node;
 
1169
        }
 
1170
 
 
1171
        nod_t nod_type;
 
1172
        while (true) {
 
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;
 
1179
                else {
 
1180
                        par_terminating_parens(paren_count, &local_count);
 
1181
                        return node;
 
1182
                }
 
1183
                gpre_nod* arg = node;
 
1184
                node = MSC_binary(nod_type, arg,
 
1185
                                                  par_multiply(request, false, paren_count, bool_flag));
 
1186
        }
 
1187
}
 
1188
 
 
1189
 
 
1190
//____________________________________________________________
 
1191
//  
 
1192
//              Parse either a literal NULL expression or a value
 
1193
//              expression.
 
1194
//  
 
1195
 
 
1196
GPRE_NOD SQE_value_or_null(gpre_req* request,
 
1197
                                                   bool aster_ok,
 
1198
                                                   USHORT * paren_count,
 
1199
                                                   bool * bool_flag)
 
1200
{
 
1201
        if (MSC_match(KW_NULL)) {
 
1202
                return MSC_node(nod_null, 0);
 
1203
        }
 
1204
        else
 
1205
                return SQE_value(request, aster_ok, paren_count, bool_flag);
 
1206
}
 
1207
 
 
1208
 
 
1209
//____________________________________________________________
 
1210
//  
 
1211
//              Parse host variable reference and, perhaps, a missing
 
1212
//              flag reference, which may be prefaced by the noiseword,
 
1213
//       "INDICATOR".
 
1214
//  
 
1215
 
 
1216
GPRE_NOD SQE_variable(gpre_req* request,
 
1217
                                          bool aster_ok,
 
1218
                                          USHORT * paren_count,
 
1219
                                          bool * bool_flag)
 
1220
{
 
1221
        assert_IS_REQ(request);
 
1222
 
 
1223
        if (!MSC_match(KW_COLON))
 
1224
                CPR_s_error("<colon>");
 
1225
 
 
1226
        if (isQuoted(gpreGlob.token_global.tok_type))
 
1227
                CPR_s_error("<host variable>");
 
1228
 
 
1229
        ref* reference = (REF) MSC_alloc(REF_LEN);
 
1230
 
 
1231
        for (gpre_sym* symbol = gpreGlob.token_global.tok_symbol; symbol;
 
1232
                symbol = symbol->sym_homonym)
 
1233
        {
 
1234
                if (symbol->sym_type == SYM_variable) {
 
1235
                        reference->ref_field = (gpre_fld*) symbol->sym_object;
 
1236
                        break;
 
1237
                }
 
1238
        }
 
1239
 
 
1240
        reference->ref_value = PAR_native_value(false, false);
 
1241
 
 
1242
        MSC_match(KW_INDICATOR);
 
1243
 
 
1244
        if (MSC_match(KW_COLON))
 
1245
                reference->ref_null_value = PAR_native_value(false, false);
 
1246
 
 
1247
        return (GPRE_NOD) reference;
 
1248
}
 
1249
 
 
1250
 
 
1251
//____________________________________________________________
 
1252
//  
 
1253
//              Compare two expressions symbollically.  If they're the same,
 
1254
//              return TRUE, otherwise FALSE.
 
1255
//  
 
1256
 
 
1257
static bool compare_expr(GPRE_NOD node1,
 
1258
                                                 GPRE_NOD node2)
 
1259
{
 
1260
        REF ref1, ref2;
 
1261
 
 
1262
        assert_IS_NOD(node1);
 
1263
        assert_IS_NOD(node2);
 
1264
 
 
1265
        if (node1->nod_type != node2->nod_type)
 
1266
                return false;
 
1267
 
 
1268
        switch (node1->nod_type) {
 
1269
        case nod_field:
 
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) 
 
1275
                {
 
1276
                        return false;
 
1277
                }
 
1278
                return true;
 
1279
 
 
1280
        case nod_map_ref:
 
1281
                if (node1->nod_arg[0] != node2->nod_arg[0])
 
1282
                        return false;
 
1283
                return true;
 
1284
 
 
1285
        case nod_udf:
 
1286
        case nod_gen_id:
 
1287
                if (node1->nod_arg[0] != node2->nod_arg[0] ||
 
1288
                        node1->nod_arg[1] != node2->nod_arg[1])
 
1289
                {
 
1290
                        return false;
 
1291
                }
 
1292
                return true;
 
1293
 
 
1294
        default:
 
1295
                return false;
 
1296
        }
 
1297
}
 
1298
 
 
1299
 
 
1300
//____________________________________________________________
 
1301
//  
 
1302
//              Copy a field list for a SELECT against an artificial context.
 
1303
//  
 
1304
 
 
1305
static GPRE_NOD copy_fields( GPRE_NOD fields, map* fields_map)
 
1306
{
 
1307
        assert_IS_NOD(fields);
 
1308
 
 
1309
        gpre_nod* list = MSC_node(nod_list, fields->nod_count);
 
1310
 
 
1311
        for (USHORT i = 0; i < fields->nod_count; i++)
 
1312
                list->nod_arg[i] = post_fields(fields->nod_arg[i], fields_map);
 
1313
 
 
1314
        return list;
 
1315
}
 
1316
 
 
1317
 
 
1318
//____________________________________________________________
 
1319
//  
 
1320
//              Expand an '*' in a field list to the corresponding fields.
 
1321
//  
 
1322
 
 
1323
static GPRE_NOD explode_asterisk( GPRE_NOD fields, int n, gpre_rse* selection)
 
1324
{
 
1325
        TEXT s[ERROR_LENGTH];
 
1326
 
 
1327
        assert_IS_NOD(fields);
 
1328
 
 
1329
        gpre_nod* node = fields->nod_arg[n];
 
1330
        TOK q_token = (TOK) node->nod_arg[0];
 
1331
        if (q_token) {
 
1332
                // expand for single relation 
 
1333
                gpre_ctx* context = resolve_asterisk(q_token, selection);
 
1334
                if (context)
 
1335
                        fields = merge_fields(fields, MET_fields(context), n, true);
 
1336
                else {
 
1337
                        sprintf(s, "columns \"%s.*\" cannot be resolved",
 
1338
                                        q_token->tok_string);
 
1339
                        PAR_error(s);
 
1340
                }
 
1341
        }
 
1342
        else {
 
1343
                // expand for all relations in context list 
 
1344
 
 
1345
                fields = explode_asterisk_all(fields, n, selection, true);
 
1346
        }
 
1347
 
 
1348
        return fields;
 
1349
}
 
1350
 
 
1351
 
 
1352
//____________________________________________________________
 
1353
//  
 
1354
//              Expand an '*' for all relations
 
1355
//              in the context list.
 
1356
//  
 
1357
 
 
1358
static GPRE_NOD explode_asterisk_all(GPRE_NOD fields,
 
1359
                                                                         int n,
 
1360
                                                                         gpre_rse* selection,
 
1361
                                                                         bool replace)
 
1362
{
 
1363
        assert_IS_NOD(fields);
 
1364
 
 
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,
 
1370
                                                                                  replace);
 
1371
                else
 
1372
                        fields = merge_fields(fields, MET_fields(context), n, replace);
 
1373
                n += fields->nod_count - old_count;
 
1374
                replace = false;
 
1375
        }
 
1376
 
 
1377
        return fields;
 
1378
}
 
1379
 
 
1380
 
 
1381
//____________________________________________________________
 
1382
//  
 
1383
//              Get an element of an expression to act as a reference
 
1384
//              field for determining the data type of a host variable.
 
1385
//  
 
1386
 
 
1387
static gpre_fld* get_ref( GPRE_NOD expr)
 
1388
{
 
1389
        gpre_fld* field;
 
1390
 
 
1391
        assert_IS_NOD(expr);
 
1392
 
 
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;
 
1398
                return field;
 
1399
        }
 
1400
 
 
1401
        ref* reference;
 
1402
        
 
1403
        switch (expr->nod_type) {
 
1404
        case nod_field:
 
1405
                reference = (ref*) expr->nod_arg[0];
 
1406
                return reference->ref_field;
 
1407
 
 
1408
 
 
1409
        case nod_array:
 
1410
                reference = (ref*) expr->nod_arg[0];
 
1411
                return reference->ref_field->fld_array;
 
1412
 
 
1413
        case nod_agg_count:
 
1414
        case nod_agg_max:
 
1415
        case nod_agg_min:
 
1416
        case nod_agg_total:
 
1417
        case nod_agg_average:
 
1418
        case nod_plus:
 
1419
        case nod_minus:
 
1420
        case nod_times:
 
1421
        case nod_divide:
 
1422
        case nod_negate:
 
1423
        case nod_upcase:
 
1424
        case nod_lowcase:
 
1425
        case nod_concatenate:
 
1426
                {
 
1427
                        gpre_nod** ptr = expr->nod_arg;
 
1428
                        for (const gpre_nod* const* const end = ptr + expr->nod_count;
 
1429
                                ptr < end; ptr++)
 
1430
                        {
 
1431
                                if (field = get_ref(*ptr))
 
1432
                                        return field;
 
1433
                        }
 
1434
                        break;
 
1435
                }
 
1436
 
 
1437
// ** Begin date/time/timestamp support *
 
1438
        case nod_extract:
 
1439
                if (field = get_ref(expr->nod_arg[1]))
 
1440
                        return field;
 
1441
                break;
 
1442
// ** End date/time/timestamp support *
 
1443
        case nod_map_ref:
 
1444
                {
 
1445
                        mel* element = (MEL) expr->nod_arg[0];
 
1446
                        gpre_nod* node = element->mel_expr;
 
1447
                        return get_ref(node);
 
1448
                }
 
1449
        }
 
1450
 
 
1451
        return 0;
 
1452
}
 
1453
 
 
1454
 
 
1455
//____________________________________________________________
 
1456
//  
 
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
 
1460
//              map.
 
1461
//  
 
1462
 
 
1463
static GPRE_NOD implicit_any(gpre_req* request,
 
1464
                                                         GPRE_NOD value,
 
1465
                                                         enum nod_t comparison,
 
1466
                                                         enum nod_t any_all)
 
1467
{
 
1468
        GPRE_NOD node;
 
1469
        scope previous_scope;
 
1470
 
 
1471
        assert_IS_REQ(request);
 
1472
        assert_IS_NOD(value);
 
1473
 
 
1474
        gpre_ctx* original = request->req_contexts;
 
1475
 
 
1476
        request->req_in_subselect++;
 
1477
        push_scope(request, &previous_scope);
 
1478
 
 
1479
        if (!(original->ctx_relation || original->ctx_procedure) &&     request->req_map)
 
1480
                value = post_fields(value, request->req_map);
 
1481
 
 
1482
//  Handle the ALL and DISTINCT options 
 
1483
        const bool distinct = (!MSC_match(KW_ALL) && MSC_match(KW_DISTINCT));
 
1484
 
 
1485
        request->req_in_select_list++;
 
1486
        gpre_nod* value2 = SQE_value(request, false, NULL, NULL);
 
1487
        request->req_in_select_list--;
 
1488
 
 
1489
        gpre_nod* field_list = MSC_node(nod_list, 1);
 
1490
        field_list->nod_arg[0] = value2;
 
1491
 
 
1492
        gpre_rse* selection = par_rse(request, field_list, distinct);
 
1493
        value2 = selection->rse_fields->nod_arg[0];
 
1494
 
 
1495
        gpre_rse* sub = selection->rse_aggregate;
 
1496
        if (sub) {
 
1497
                if (validate_references(value2, sub->rse_group_by))
 
1498
                        PAR_error
 
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);
 
1508
                        else
 
1509
                                node = MSC_node(nod_any, 1);
 
1510
                        node->nod_count = 0;
 
1511
                        node->nod_arg[0] = (GPRE_NOD) selection;
 
1512
                }
 
1513
                else {
 
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]);
 
1521
                }
 
1522
        }
 
1523
        else {
 
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);
 
1531
                else
 
1532
                        node = MSC_node(nod_any, 1);
 
1533
                node->nod_count = 0;
 
1534
                node->nod_arg[0] = (GPRE_NOD) selection;
 
1535
        }
 
1536
 
 
1537
        EXP_rse_cleanup(selection);
 
1538
 
 
1539
        pop_scope(request, &previous_scope);
 
1540
        request->req_in_subselect--;
 
1541
 
 
1542
        return node;
 
1543
}
 
1544
 
 
1545
 
 
1546
//____________________________________________________________
 
1547
//  
 
1548
//              Merge two (possibly null) booleans into a single conjunct.
 
1549
//  
 
1550
 
 
1551
static GPRE_NOD merge( GPRE_NOD expr1, GPRE_NOD expr2)
 
1552
{
 
1553
 
 
1554
        if (!expr1)
 
1555
                return expr2;
 
1556
 
 
1557
        if (!expr2)
 
1558
                return expr1;
 
1559
 
 
1560
        assert_IS_NOD(expr1);
 
1561
        assert_IS_NOD(expr1);
 
1562
 
 
1563
        return MSC_binary(nod_and, expr1, expr2);
 
1564
}
 
1565
 
 
1566
 
 
1567
//____________________________________________________________
 
1568
//  
 
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.
 
1573
//  
 
1574
 
 
1575
static GPRE_NOD merge_fields(GPRE_NOD fields_1,
 
1576
                                                         GPRE_NOD fields_2,
 
1577
                                                         int n,
 
1578
                                                         bool replace)
 
1579
{
 
1580
        int i;
 
1581
 
 
1582
        assert_IS_NOD(fields_1);
 
1583
        assert_IS_NOD(fields_2);
 
1584
 
 
1585
        int count = fields_1->nod_count + fields_2->nod_count;
 
1586
        if (replace)
 
1587
                count--;
 
1588
        gpre_nod* fields = MSC_node(nod_list, (SSHORT) count);
 
1589
 
 
1590
        count = n;
 
1591
        if (!replace)
 
1592
                count++;
 
1593
        for (i = 0; i < count; i++)
 
1594
                fields->nod_arg[i] = fields_1->nod_arg[i];
 
1595
 
 
1596
        for (i = 0; i < fields_2->nod_count; i++)
 
1597
                fields->nod_arg[i + count] = fields_2->nod_arg[i];
 
1598
 
 
1599
        int offset = 0;
 
1600
        if (replace) {
 
1601
                count++;
 
1602
                offset = 1;
 
1603
        }
 
1604
 
 
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];
 
1608
 
 
1609
        return fields;
 
1610
}
 
1611
 
 
1612
 
 
1613
//____________________________________________________________
 
1614
//  
 
1615
//              Construct negation of expression.
 
1616
//  
 
1617
 
 
1618
static GPRE_NOD negate( GPRE_NOD expr)
 
1619
{
 
1620
 
 
1621
        assert_IS_NOD(expr);
 
1622
 
 
1623
        return MSC_unary(nod_not, expr);
 
1624
}
 
1625
 
 
1626
 
 
1627
//____________________________________________________________
 
1628
//  
 
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.
 
1633
//  
 
1634
 
 
1635
static void pair( GPRE_NOD expr1, GPRE_NOD expr2)
 
1636
{
 
1637
        assert_IS_NOD(expr1);
 
1638
        assert_IS_NOD(expr2);
 
1639
 
 
1640
//  Verify that an array field without subscripts is not
 
1641
//  being used inappropriately 
 
1642
 
 
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");
 
1648
        }
 
1649
 
 
1650
        gpre_fld* field = 0;
 
1651
        if (expr2)
 
1652
                field = get_ref(expr2);
 
1653
        if (!field)
 
1654
                field = get_ref(expr1);
 
1655
 
 
1656
        if (!field)
 
1657
                return;
 
1658
 
 
1659
        set_ref(expr1, field);
 
1660
 
 
1661
        if (!expr2)
 
1662
                return;
 
1663
 
 
1664
        gpre_fld* temp = get_ref(expr1);
 
1665
        if (temp)
 
1666
                field = temp;
 
1667
 
 
1668
        set_ref(expr2, field);
 
1669
}
 
1670
 
 
1671
 
 
1672
//____________________________________________________________
 
1673
//  
 
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.
 
1681
//  
 
1682
 
 
1683
static gpre_ctx* par_alias_list( gpre_req* request, GPRE_NOD alias_list)
 
1684
{
 
1685
        assert_IS_REQ(request);
 
1686
        assert_IS_NOD(alias_list);
 
1687
 
 
1688
        gpre_nod** arg = alias_list->nod_arg;
 
1689
        const gpre_nod* const* const end = alias_list->nod_arg + alias_list->nod_count;
 
1690
 
 
1691
//  check the first alias in the list with the relations
 
1692
//  in the current context for a match 
 
1693
 
 
1694
        gpre_rel* relation = 0; // unreliable test many lines below without initializing.
 
1695
        gpre_ctx* context = par_alias(request, (const TEXT*) * arg);
 
1696
        if (context) {
 
1697
                if (alias_list->nod_count == 1)
 
1698
                        return context;
 
1699
                relation = context->ctx_relation;
 
1700
        }
 
1701
 
 
1702
        SCHAR error_string[ERROR_LENGTH];
 
1703
                
 
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 
 
1707
 
 
1708
        if (!context)
 
1709
                for (context = request->req_contexts; context;
 
1710
                         context = context->ctx_next)
 
1711
                {
 
1712
                        if (context->ctx_scope_level != request->req_scope_level)
 
1713
                                continue;
 
1714
                        if (!context->ctx_relation)
 
1715
                                continue;
 
1716
                        if (relation =
 
1717
                                par_base_table(request, context->ctx_relation,
 
1718
                                                           (const TEXT*) * arg))
 
1719
                        {
 
1720
                                break;
 
1721
                        }
 
1722
                }
 
1723
 
 
1724
                if (!context) {
 
1725
                        fb_utils::snprintf(error_string, sizeof(error_string),
 
1726
                                "there is no alias or table named %s at this scope level",
 
1727
                                (TEXT *) * arg);
 
1728
                PAR_error(error_string);
 
1729
        }
 
1730
 
 
1731
//  find the base table using the specified alias list, skipping the first one
 
1732
//  since we already matched it to the context 
 
1733
 
 
1734
        for (arg++; arg < end; arg++)
 
1735
                if (!(relation = par_base_table(request, relation, (const TEXT*) * arg)))
 
1736
                        break;
 
1737
 
 
1738
        if (!relation) {
 
1739
                fb_utils::snprintf(error_string, sizeof(error_string),
 
1740
                                "there is no alias or table named %s at this scope level",
 
1741
                                (TEXT *) * arg);
 
1742
                PAR_error(error_string);
 
1743
        }
 
1744
 
 
1745
//  make up a dummy context to hold the resultant relation 
 
1746
 
 
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;
 
1751
 
 
1752
//  concatenate all the contexts to form the alias name;
 
1753
//  calculate the length leaving room for spaces and a null 
 
1754
 
 
1755
        USHORT alias_length = alias_list->nod_count;
 
1756
        for (arg = alias_list->nod_arg; arg < end; arg++)
 
1757
                alias_length += strlen((TEXT *) * arg);
 
1758
 
 
1759
        TEXT* alias = (TEXT *) MSC_alloc(alias_length);
 
1760
 
 
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;)
 
1766
                        *p++ = *q++;
 
1767
                *p++ = ' ';
 
1768
        }
 
1769
 
 
1770
        p[-1] = 0;
 
1771
 
 
1772
        return new_context;
 
1773
}
 
1774
 
 
1775
 
 
1776
//____________________________________________________________
 
1777
//  
 
1778
//              The passed relation or alias represents 
 
1779
//              a context which was previously specified
 
1780
//              in the from list.  Find and return the 
 
1781
//              proper context.
 
1782
//  
 
1783
 
 
1784
static gpre_ctx* par_alias( gpre_req* request, const TEXT* alias)
 
1785
{
 
1786
        SCHAR error_string[ERROR_LENGTH];
 
1787
 
 
1788
        assert_IS_REQ(request);
 
1789
 
 
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 
 
1793
 
 
1794
        gpre_ctx* relation_context = NULL;
 
1795
        for (gpre_ctx* context = request->req_contexts; context;
 
1796
                 context = context->ctx_next)
 
1797
        {
 
1798
                if (context->ctx_scope_level != request->req_scope_level)
 
1799
                        continue;
 
1800
 
 
1801
                // check for matching alias 
 
1802
 
 
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))
 
1808
                                        break;
 
1809
                        if (!*p && !*q)
 
1810
                                return context;
 
1811
                }
 
1812
 
 
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 */
 
1816
 
 
1817
                if (context->ctx_relation &&
 
1818
                        !strcmp(context->ctx_relation->rel_symbol->sym_string, alias))
 
1819
                {
 
1820
                        if (relation_context) {
 
1821
                                fb_utils::snprintf(error_string, sizeof(error_string),
 
1822
                                                "the table %s is referenced twice; use aliases to differentiate",
 
1823
                                                alias);
 
1824
                                PAR_error(error_string);
 
1825
                        }
 
1826
                        relation_context = context;
 
1827
                }
 
1828
        }
 
1829
 
 
1830
        return relation_context;
 
1831
}
 
1832
 
 
1833
 
 
1834
//____________________________________________________________
 
1835
//  
 
1836
//              Check if the relation in the passed context
 
1837
//              has a base table which matches the passed alias.
 
1838
//  
 
1839
 
 
1840
static gpre_rel* par_base_table( gpre_req* request, const gpre_rel* relation,
 
1841
        const TEXT* alias)
 
1842
{
 
1843
 
 
1844
        assert_IS_REQ(request);
 
1845
 
 
1846
        return MET_get_view_relation(request, relation->rel_symbol->sym_string,
 
1847
                                                                 alias, 0);
 
1848
}
 
1849
 
 
1850
 
 
1851
//____________________________________________________________
 
1852
//  
 
1853
//              Parse an AND boolean expression.
 
1854
//  
 
1855
 
 
1856
static GPRE_NOD par_and( gpre_req* request, USHORT * paren_count)
 
1857
{
 
1858
        assert_IS_REQ(request);
 
1859
 
 
1860
        gpre_nod* expr1 = par_not(request, paren_count);
 
1861
 
 
1862
        if (!MSC_match(KW_AND))
 
1863
                return expr1;
 
1864
 
 
1865
        return merge(expr1, par_and(request, paren_count));
 
1866
}
 
1867
 
 
1868
 
 
1869
//____________________________________________________________
 
1870
//  
 
1871
//  
 
1872
 
 
1873
static GPRE_NOD par_collate( gpre_req* request, GPRE_NOD arg)
 
1874
{
 
1875
        assert_IS_REQ(request);
 
1876
        assert_IS_NOD(arg);
 
1877
 
 
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 
 
1886
                // maximum length 
 
1887
 
 
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;
 
1893
        }
 
1894
        else if (field->fld_sub_type) {
 
1895
                field->fld_character_set = MET_get_text_subtype(field->fld_sub_type);
 
1896
        }
 
1897
        SQL_par_field_collate(request, field);
 
1898
        SQL_adjust_field_dtype(field);
 
1899
 
 
1900
        return node;
 
1901
}
 
1902
 
 
1903
 
 
1904
//____________________________________________________________
 
1905
//  
 
1906
//              Parse a SQL "IN" expression.  This comes in two flavors:
 
1907
//  
 
1908
//                      <value> IN (<value_comma_list>)
 
1909
//                      <value> IN (SELECT <column> <from_nonsense>)
 
1910
//  
 
1911
 
 
1912
static GPRE_NOD par_in( gpre_req* request, GPRE_NOD value)
 
1913
{
 
1914
        GPRE_NOD node;
 
1915
        SCHAR s[ERROR_LENGTH];
 
1916
 
 
1917
        assert_IS_REQ(request);
 
1918
        assert_IS_NOD(value);
 
1919
 
 
1920
        EXP_left_paren(0);
 
1921
 
 
1922
//  If the next token isn't SELECT, we must have the comma list flavor. 
 
1923
 
 
1924
        if (MSC_match(KW_SELECT))
 
1925
                node = implicit_any(request, value, nod_eq, nod_ansi_any);
 
1926
        else {
 
1927
                node = NULL;
 
1928
                while (true) {
 
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;
 
1935
                                }
 
1936
                                else {
 
1937
                                        fb_utils::snprintf(s, sizeof(s),
 
1938
                                                        "datatype of %s can not be determined",
 
1939
                                                        gpreGlob.token_global.tok_string);
 
1940
                                        PAR_error(s);
 
1941
                                }
 
1942
                        }
 
1943
                        if (!node)
 
1944
                                node = MSC_binary(nod_eq, value, value2);
 
1945
                        else
 
1946
                                node =
 
1947
                                        MSC_binary(nod_or, node,
 
1948
                                                           MSC_binary(nod_eq, value, value2));
 
1949
 
 
1950
                        if (!(MSC_match(KW_COMMA)))
 
1951
                                break;
 
1952
                }
 
1953
        }
 
1954
 
 
1955
        if (!EXP_match_paren())
 
1956
                return NULL;
 
1957
 
 
1958
        return node;
 
1959
}
 
1960
 
 
1961
 
 
1962
//____________________________________________________________
 
1963
//  
 
1964
//              Parse a join relation clause.
 
1965
//  
 
1966
 
 
1967
static gpre_ctx* par_joined_relation( gpre_req* request, gpre_ctx* prior_context)
 
1968
{
 
1969
        gpre_ctx* context1;
 
1970
 
 
1971
        assert_IS_REQ(request);
 
1972
 
 
1973
        if (MSC_match(KW_LEFT_PAREN)) {
 
1974
                context1 = par_joined_relation(request, NULL);
 
1975
                EXP_match_paren();
 
1976
        }
 
1977
        else if (!(context1 = SQE_context(request)))
 
1978
                return NULL;
 
1979
 
 
1980
        return par_join_clause(request, context1);
 
1981
}
 
1982
 
 
1983
 
 
1984
//____________________________________________________________
 
1985
//  
 
1986
//              Parse a join relation clause.
 
1987
//  
 
1988
 
 
1989
static gpre_ctx* par_join_clause( gpre_req* request, gpre_ctx* context1)
 
1990
{
 
1991
        assert_IS_REQ(request);
 
1992
 
 
1993
        const NOD_T join_type = par_join_type();
 
1994
        if (join_type == (NOD_T) 0)
 
1995
                return context1;
 
1996
 
 
1997
        gpre_ctx* context2 = par_joined_relation(request, context1);
 
1998
        if (!context2)
 
1999
                CPR_s_error("<joined table clause>");
 
2000
 
 
2001
        if (!MSC_match(KW_ON))
 
2002
                CPR_s_error("ON");
 
2003
 
 
2004
        gpre_nod* node = SQE_boolean(request, NULL);
 
2005
 
 
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;
 
2012
 
 
2013
        context1 = MSC_context(request);
 
2014
        context1->ctx_stream = selection;
 
2015
 
 
2016
        return par_join_clause(request, context1);
 
2017
}
 
2018
 
 
2019
 
 
2020
//____________________________________________________________
 
2021
//  
 
2022
//              Parse a join type.
 
2023
//  
 
2024
 
 
2025
static NOD_T par_join_type(void)
 
2026
{
 
2027
        NOD_T nod_type;
 
2028
 
 
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;
 
2039
        else
 
2040
                return (NOD_T) 0;
 
2041
 
 
2042
        if (nod_type != nod_join_inner)
 
2043
                MSC_match(KW_OUTER);
 
2044
 
 
2045
        if (!MSC_match(KW_JOIN))
 
2046
                CPR_s_error("JOIN");
 
2047
 
 
2048
        return nod_type;
 
2049
}
 
2050
 
 
2051
 
 
2052
//____________________________________________________________
 
2053
//  
 
2054
//              Parse either of the high precedence operators * and /.
 
2055
//  
 
2056
 
 
2057
static GPRE_NOD par_multiply(gpre_req* request,
 
2058
                                                         bool aster_ok,
 
2059
                                                         USHORT * paren_count,
 
2060
                                                         bool * bool_flag)
 
2061
{
 
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)
 
2065
                return node;
 
2066
 
 
2067
        if (gpreGlob.token_global.tok_keyword == KW_COLLATE)
 
2068
                return par_collate(request, node);
 
2069
 
 
2070
        GPRE_NOD arg;
 
2071
        enum nod_t nod_type;
 
2072
        while (true) {
 
2073
                if (MSC_match(KW_ASTERISK))
 
2074
                        nod_type = nod_times;
 
2075
                else if (MSC_match(KW_SLASH))
 
2076
                        nod_type = nod_divide;
 
2077
                else
 
2078
                        return node;
 
2079
                arg = node;
 
2080
                node =
 
2081
                        MSC_binary(nod_type, arg,
 
2082
                                           par_primitive_value(request, false, paren_count,
 
2083
                                                                                   bool_flag));
 
2084
        }
 
2085
}
 
2086
 
 
2087
 
 
2088
//____________________________________________________________
 
2089
//  
 
2090
//              Parse an NOT boolean expression.
 
2091
//  
 
2092
 
 
2093
static GPRE_NOD par_not( gpre_req* request, USHORT * paren_count)
 
2094
{
 
2095
        assert_IS_REQ(request);
 
2096
 
 
2097
        if (MSC_match(KW_NOT))
 
2098
                return negate(par_not(request, paren_count));
 
2099
 
 
2100
        enum nod_t type = (enum nod_t) 0;
 
2101
 
 
2102
        if (MSC_match(KW_EXISTS))
 
2103
                type = nod_any;
 
2104
        else if (MSC_match(KW_SINGULAR))
 
2105
                type = nod_unique;
 
2106
        if (type == nod_any || type == nod_unique) {
 
2107
                scope saved_scope;
 
2108
                push_scope(request, &saved_scope);
 
2109
 
 
2110
                EXP_left_paren(0);
 
2111
                if (!MSC_match(KW_SELECT))
 
2112
                        CPR_s_error("SELECT");
 
2113
 
 
2114
                request->req_in_select_list++;
 
2115
                gpre_nod* field;
 
2116
                if (MSC_match(KW_ASTERISK))
 
2117
                        field = NULL;
 
2118
                else if (!(field = par_udf(request)))
 
2119
                        field = SQE_field(request, false);
 
2120
                request->req_in_select_list--;
 
2121
 
 
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;
 
2126
                if (field) {
 
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);
 
2130
                }
 
2131
                EXP_rse_cleanup((gpre_rse*) node->nod_arg[0]);
 
2132
                pop_scope(request, &saved_scope);
 
2133
                EXP_match_paren();
 
2134
                return node;
 
2135
        }
 
2136
 
 
2137
        return par_relational(request, paren_count);
 
2138
}
 
2139
 
 
2140
 
 
2141
//____________________________________________________________
 
2142
//  
 
2143
//              Parse ORDER clause of SELECT expression.  This is 
 
2144
//              particularly difficult since the ORDER clause can
 
2145
//              refer to fields by position.
 
2146
//  
 
2147
 
 
2148
static void par_order(gpre_req* request,
 
2149
                                          gpre_rse* select,
 
2150
                                          bool union_f,
 
2151
                                          bool view_flag)
 
2152
{
 
2153
        GPRE_NOD sort;
 
2154
        map* request_map;
 
2155
        USHORT i;
 
2156
 
 
2157
        assert_IS_REQ(request);
 
2158
 
 
2159
        if (!MSC_match(KW_ORDER))
 
2160
                return;
 
2161
        if (view_flag)
 
2162
                PAR_error("sort clause not allowed in a view definition");
 
2163
 
 
2164
        MSC_match(KW_BY);
 
2165
        gpre_lls* items = NULL;
 
2166
        gpre_lls* directions = NULL;
 
2167
        int count = 0, direction = 0;
 
2168
        gpre_nod* values = select->rse_fields;
 
2169
 
 
2170
        while (true) {
 
2171
                direction = FALSE;
 
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];
 
2177
                        PAR_get_token();
 
2178
                        if (gpreGlob.token_global.tok_keyword == KW_COLLATE)
 
2179
                                sort = par_collate(request, sort);
 
2180
                }
 
2181
                else {
 
2182
                        if (union_f)
 
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);
 
2187
                }
 
2188
                if (MSC_match(KW_ASCENDING))
 
2189
                        direction = FALSE;
 
2190
                else if (MSC_match(KW_DESCENDING))
 
2191
                        direction = TRUE;
 
2192
                count++;
 
2193
                MSC_push((GPRE_NOD)(IPTR)direction, &directions);
 
2194
                MSC_push(sort, &items);
 
2195
                if (!MSC_match(KW_COMMA))
 
2196
                        break;
 
2197
        }
 
2198
 
 
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;
 
2202
 
 
2203
        while (items) {
 
2204
                *--ptr = (GPRE_NOD) MSC_pop(&items);
 
2205
                *--ptr = (GPRE_NOD) MSC_pop(&directions);
 
2206
        }
 
2207
}
 
2208
 
 
2209
 
 
2210
//____________________________________________________________
 
2211
//  
 
2212
//              Allow the user to specify the access plan
 
2213
//              for a query as part of a select expression.
 
2214
//  
 
2215
 
 
2216
static GPRE_NOD par_plan( gpre_req* request)
 
2217
{
 
2218
        assert_IS_REQ(request);
 
2219
 
 
2220
//  parse the join type 
 
2221
 
 
2222
        NOD_T nod_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;
 
2229
        else
 
2230
                nod_type = nod_join;
 
2231
 
 
2232
//  make up the plan expression node 
 
2233
 
 
2234
        gpre_nod* plan_expression = MSC_node(nod_plan_expr, 2);
 
2235
 
 
2236
        if (nod_type != nod_join)
 
2237
                plan_expression->nod_arg[0] = MSC_node(nod_type, 0);
 
2238
 
 
2239
//  parse the plan items at this level 
 
2240
 
 
2241
        EXP_left_paren(0);
 
2242
 
 
2243
        plan_expression->nod_arg[1] = SQE_list(par_plan_item, request, false);
 
2244
 
 
2245
        if (!EXP_match_paren())
 
2246
                return NULL;
 
2247
        return plan_expression;
 
2248
}
 
2249
 
 
2250
 
 
2251
//____________________________________________________________
 
2252
//  
 
2253
//              Parse an individual plan item for an 
 
2254
//              access plan.
 
2255
//  
 
2256
 
 
2257
static GPRE_NOD par_plan_item(gpre_req* request,
 
2258
                                                          bool aster_ok,
 
2259
                                                          USHORT * paren_count,
 
2260
                                                          bool * bool_flag)
 
2261
{
 
2262
        assert_IS_REQ(request);
 
2263
 
 
2264
//  check for a plan expression 
 
2265
 
 
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)
 
2268
        {
 
2269
                return par_plan(request);
 
2270
        }
 
2271
 
 
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) 
 
2275
 
 
2276
        int count;
 
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)
 
2282
                {
 
2283
                        break;
 
2284
                }
 
2285
 
 
2286
                MSC_push((GPRE_NOD) upcase_string(gpreGlob.token_global.tok_string), &stack);
 
2287
                PAR_get_token();
 
2288
        }
 
2289
 
 
2290
        if (!count)
 
2291
                CPR_s_error("<table name> or <alias>");
 
2292
 
 
2293
        gpre_nod** ptr;
 
2294
 
 
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);
 
2298
 
 
2299
//  lookup the contexts for the aliases 
 
2300
 
 
2301
        gpre_ctx* context = par_alias_list(request, alias_list);
 
2302
 
 
2303
//  parse the access type 
 
2304
 
 
2305
        gpre_nod* access_type;
 
2306
        if (gpreGlob.token_global.tok_keyword == KW_NATURAL) {
 
2307
                access_type = MSC_node(nod_natural, 0);
 
2308
                PAR_get_token();
 
2309
        }
 
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;
 
2313
                PAR_get_token();
 
2314
 
 
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);
 
2318
                PAR_get_token();
 
2319
        }
 
2320
        else if (gpreGlob.token_global.tok_keyword == KW_INDEX) {
 
2321
                access_type = MSC_node(nod_index, 1);
 
2322
                access_type->nod_count = 0;
 
2323
                PAR_get_token();
 
2324
 
 
2325
                EXP_left_paren(0);
 
2326
 
 
2327
                stack = NULL;
 
2328
                for (count = 0; gpreGlob.token_global.tok_type == tok_ident;) {
 
2329
                        MSC_push((GPRE_NOD) upcase_string(gpreGlob.token_global.tok_string), &stack);
 
2330
                        PAR_get_token();
 
2331
 
 
2332
                        count++;
 
2333
 
 
2334
                        if (!MSC_match(KW_COMMA))
 
2335
                                break;
 
2336
                }
 
2337
                if (!count)
 
2338
                        CPR_s_error("<table name> or <alias>");
 
2339
 
 
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);
 
2344
 
 
2345
                if (!EXP_match_paren())
 
2346
                        return NULL;
 
2347
        }
 
2348
        else {
 
2349
                CPR_s_error("NATURAL, ORDER, or INDEX");
 
2350
        }
 
2351
 
 
2352
 
 
2353
//  generate the plan item node 
 
2354
 
 
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;
 
2360
 
 
2361
        return plan_item;
 
2362
}
 
2363
 
 
2364
 
 
2365
//____________________________________________________________
 
2366
//  
 
2367
//              Parse a value expression.  The value could be any of the
 
2368
//              following:
 
2369
//  
 
2370
//                      "quoted string"
 
2371
//                      _CHARSET"quoted string"
 
2372
//                      123
 
2373
//                      +1.234E-3
 
2374
//                      field
 
2375
//                      relation.field
 
2376
//                      context.field
 
2377
//                      user defined function
 
2378
//  
 
2379
 
 
2380
static GPRE_NOD par_primitive_value(gpre_req* request,
 
2381
                                                                        bool aster_ok,
 
2382
                                                                        USHORT * paren_count,
 
2383
                                                                        bool * bool_flag)
 
2384
{
 
2385
        USHORT local_count;
 
2386
 
 
2387
        assert_IS_REQ(request);
 
2388
 
 
2389
        gpre_nod* node = 0;
 
2390
 
 
2391
        if (!paren_count) {
 
2392
                local_count = 0;
 
2393
                paren_count = &local_count;
 
2394
        }
 
2395
 
 
2396
        if (MSC_match(KW_SELECT))
 
2397
                return par_stat(request);
 
2398
 
 
2399
        if (MSC_match(KW_MINUS))
 
2400
                return MSC_unary(nod_negate,
 
2401
                                                 par_primitive_value(request, false, paren_count, false));
 
2402
 
 
2403
        MSC_match(KW_PLUS);
 
2404
 
 
2405
        if (MSC_match(KW_USER)) {
 
2406
                return MSC_node(nod_user_name, 0);
 
2407
        }
 
2408
 
 
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
 
2412
                 */
 
2413
                if (!request)
 
2414
                        PAR_error("VALUE cannot be used in this context");
 
2415
                const act* action = request->req_actions;
 
2416
                if (request->req_type != REQ_ddl ||
 
2417
                        !action ||
 
2418
                        !(action->act_type == ACT_create_domain ||
 
2419
                          action->act_type == ACT_alter_domain))
 
2420
                {
 
2421
                        PAR_error("VALUE cannot be used in this context");
 
2422
                }
 
2423
 
 
2424
                return MSC_node(nod_dom_value, 0);
 
2425
        }
 
2426
 
 
2427
        if (MSC_match(KW_LEFT_PAREN)) {
 
2428
                (*paren_count)++;
 
2429
                if (bool_flag && *bool_flag)
 
2430
                        node = SQE_boolean(request, paren_count);
 
2431
                else
 
2432
                        node = SQE_value(request, false, paren_count, bool_flag);
 
2433
                EXP_match_paren();
 
2434
                (*paren_count)--;
 
2435
                return node;
 
2436
        }
 
2437
 
 
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. 
 
2442
 
 
2443
        map* tmp_map = 0;
 
2444
        for (const ops *op = stat_ops; (int) op->rel_kw != (int) KW_none; op++) {
 
2445
                MSC_match(KW_ALL);
 
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)))
 
2451
                        {
 
2452
                                /* either nested aggregate, or not part of a select
 
2453
                                   list, having clause, or order by clause (in any subquery)
 
2454
                                 */
 
2455
                                PAR_error("Invalid aggregate reference");
 
2456
                        }
 
2457
 
 
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);
 
2462
                        if (request) {
 
2463
                                tmp_map = request->req_map;
 
2464
                                request->req_map = NULL;
 
2465
                                ++request->req_in_aggregate;
 
2466
                        }
 
2467
                        if (node->nod_type == nod_agg_count && MSC_match(KW_ASTERISK))
 
2468
                                node->nod_count = 0;
 
2469
                        else {
 
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)
 
2474
                                        PAR_error
 
2475
                                                ("Array columns not permitted in aggregate functions");
 
2476
                        }
 
2477
 
 
2478
                        if (distinct)
 
2479
                                node->nod_arg[1] = node->nod_arg[0];
 
2480
                        EXP_match_paren();
 
2481
                        if (request) {
 
2482
                                if (tmp_map)
 
2483
                                        node = post_map(node, tmp_map);
 
2484
                                request->req_map = tmp_map;
 
2485
                                --request->req_in_aggregate;
 
2486
                        }
 
2487
                        return node;
 
2488
                }
 
2489
        }
 
2490
 
 
2491
//  If it's a number or a quoted string, it's a literal 
 
2492
 
 
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)
 
2496
        {
 
2497
                node = EXP_literal();
 
2498
                return node;
 
2499
        }
 
2500
 
 
2501
//  moved this timestamp support down some lines, because it caused
 
2502
//  gpre to segfault when it was done here.
 
2503
//  FSG 15.Nov.2000
 
2504
//  
 
2505
 
 
2506
 
 
2507
//  If the next token is a colon, it is a variable reference 
 
2508
 
 
2509
        if ((int) gpreGlob.token_global.tok_keyword == (int) KW_COLON) {
 
2510
                if (!request) {
 
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)
 
2514
                         */
 
2515
                        PAR_error(":hostvar reference not supported in this context");
 
2516
                        return NULL;
 
2517
                }
 
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;
 
2522
                return node;
 
2523
        }
 
2524
 
 
2525
 
 
2526
 
 
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);
 
2529
 
 
2530
//  
 
2531
//if (request && (map = request->req_map))
 
2532
//   return post_map (node, map);
 
2533
//  
 
2534
 
 
2535
        if (!node)
 
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 
 
2538
        {
 
2539
// ** Begin date/time/timestamp support *
 
2540
                const KWWORDS kw_word = gpreGlob.token_global.tok_keyword;
 
2541
 
 
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();
 
2545
                        return node;
 
2546
                }
 
2547
 
 
2548
// ** End date/time/timestamp support *
 
2549
 
 
2550
        }
 
2551
 
 
2552
        return node;
 
2553
}
 
2554
 
 
2555
 
 
2556
//____________________________________________________________
 
2557
//  
 
2558
//              Parse relational expression.
 
2559
//  
 
2560
 
 
2561
static GPRE_NOD par_relational(gpre_req* request,
 
2562
                                                           USHORT * paren_count)
 
2563
{
 
2564
        assert_IS_REQ(request);
 
2565
 
 
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)
 
2569
                return expr1;
 
2570
        if (gpreGlob.token_global.tok_keyword == KW_SEMI_COLON)
 
2571
        {
 
2572
                for (const NOD_T* relational_ops = relationals; *relational_ops != (NOD_T) 0;
 
2573
                         relational_ops++)
 
2574
                {
 
2575
                        if (expr1->nod_type == *relational_ops)
 
2576
                                return expr1;
 
2577
                }
 
2578
        }
 
2579
 
 
2580
        bool negation = false;
 
2581
        if (MSC_match(KW_NOT))
 
2582
                negation = true;
 
2583
 
 
2584
//  Check for one of the binary operators 
 
2585
 
 
2586
        GPRE_NOD node;
 
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);
 
2593
                MSC_match(KW_AND);
 
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]);
 
2597
        }
 
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);
 
2610
                        }
 
2611
                }
 
2612
                else
 
2613
                        node->nod_count = 2;
 
2614
        }
 
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);
 
2623
        }
 
2624
        else {
 
2625
                node = NULL;
 
2626
                const ops* op;
 
2627
                for (op = rel_ops; (int) op->rel_kw != (int) KW_none; op++)
 
2628
                        if (MSC_match(op->rel_kw))
 
2629
                                break;
 
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++)
 
2633
                        {
 
2634
                                if (expr1->nod_type == *relational_ops)
 
2635
                                        return expr1;
 
2636
                        }
 
2637
                        CPR_s_error("<relational operator>");
 
2638
                }
 
2639
                if ((int) op->rel_kw == (int) KW_STARTING)
 
2640
                        MSC_match(KW_WITH);
 
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);
 
2645
                        EXP_match_paren();
 
2646
                }
 
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)
 
2653
                        {
 
2654
                                CPR_s_error("<relational operator> for ALL");
 
2655
                        }
 
2656
                        node = implicit_any(request, expr1, op->rel_op, nod_ansi_all);
 
2657
                        EXP_match_paren();
 
2658
                }
 
2659
                else {
 
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]);
 
2663
                }
 
2664
        }
 
2665
 
 
2666
        return (negation) ? negate(node) : node;
 
2667
}
 
2668
 
 
2669
 
 
2670
// Out of alphabetical order.
 
2671
static bool resolve_fields(GPRE_NOD& fields,
 
2672
                                        gpre_req* request,
 
2673
                                        gpre_rse* selection)
 
2674
{
 
2675
        bool aggregate = false;
 
2676
 
 
2677
        gpre_nod** ptr = fields->nod_arg;
 
2678
        int count = fields->nod_count;
 
2679
 
 
2680
        for (int i = 0; i < count; i++)
 
2681
        {
 
2682
                gpre_nod* node = ptr[i];
 
2683
 
 
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;
 
2690
                }
 
2691
                else {
 
2692
                        aggregate |= SQE_resolve(node, NULL, selection);
 
2693
                        pair(node, 0);
 
2694
 
 
2695
                        switch (node->nod_type)
 
2696
                        {
 
2697
                                case nod_agg_count:
 
2698
                                case nod_agg_max:
 
2699
                                case nod_agg_min:
 
2700
                                case nod_agg_average:
 
2701
                                case nod_agg_total:
 
2702
                                        if ((node->nod_arg[1]) &&
 
2703
                                                (request->req_database->dbb_flags & DBB_v3))
 
2704
                                        {
 
2705
                                                selection->rse_reduced =
 
2706
                                                        MSC_unary(nod_sort, node->nod_arg[1]);
 
2707
                                        }
 
2708
                                        break;
 
2709
                        }
 
2710
                }
 
2711
        }
 
2712
 
 
2713
        return aggregate;
 
2714
}
 
2715
//____________________________________________________________
 
2716
//  
 
2717
//              Parse the SQL equivalent of a record selection expression --
 
2718
//              FROM, WHERE, and ORDER clauses.  A field list may or may not
 
2719
//              be present.
 
2720
//  
 
2721
 
 
2722
static gpre_rse* par_rse(gpre_req* request,
 
2723
                                   GPRE_NOD fields,
 
2724
                                   bool distinct)
 
2725
{
 
2726
        gpre_lls* stack = NULL;
 
2727
 
 
2728
        assert_IS_REQ(request);
 
2729
        assert_IS_NOD(fields);
 
2730
 
 
2731
//  Get list and count of relations 
 
2732
 
 
2733
        if (!MSC_match(KW_FROM))
 
2734
                CPR_s_error("FROM");
 
2735
 
 
2736
        int count = 0;
 
2737
        gpre_ctx* context;
 
2738
        do {
 
2739
                if (context = par_joined_relation(request, NULL)) {
 
2740
                        MSC_push((GPRE_NOD) context, &stack);
 
2741
                        count++;
 
2742
                }
 
2743
                else
 
2744
                        return NULL;
 
2745
        } while (MSC_match(KW_COMMA));
 
2746
 
 
2747
//  Now allocate a record select expression
 
2748
//  block for the beast and fill in what we already know.  
 
2749
 
 
2750
        gpre_rse* select = (gpre_rse*) MSC_alloc(RSE_LEN(count));
 
2751
        select->rse_count = count;
 
2752
 
 
2753
        while (count--)
 
2754
                select->rse_context[count] = (gpre_ctx*) MSC_pop(&stack);
 
2755
 
 
2756
//  If a field list has been presented, resolve references now 
 
2757
 
 
2758
        bool aggregate = false;
 
2759
 
 
2760
        if (fields)
 
2761
                aggregate = resolve_fields(fields, request, select);
 
2762
 
 
2763
        select->rse_fields = fields;
 
2764
        if (distinct)
 
2765
                select->rse_reduced = fields;
 
2766
 
 
2767
//  Handle a boolean, if present 
 
2768
 
 
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;
 
2773
        }
 
2774
 
 
2775
        if (MSC_match(KW_GROUP)) {
 
2776
                MSC_match(KW_BY);
 
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++)
 
2782
                {
 
2783
                        if ((*ptr)->nod_type == nod_array)
 
2784
                                PAR_error("Array columns not permitted in GROUP BY clause");
 
2785
                }
 
2786
        }
 
2787
 
 
2788
        if (select->rse_group_by || aggregate) {
 
2789
                if (validate_references(select->rse_fields, select->rse_group_by))
 
2790
                        PAR_error
 
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;
 
2800
 
 
2801
                if (fields)
 
2802
                        select->rse_fields = copy_fields(sub_rse->rse_fields, subselect_map);
 
2803
 
 
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))
 
2810
                        {
 
2811
                                PAR_error("simple column reference in HAVING must be referenced in GROUP BY");
 
2812
                        }
 
2813
                }
 
2814
        }
 
2815
 
 
2816
//  parse a user-specified access plan 
 
2817
 
 
2818
        if (MSC_match(KW_PLAN))
 
2819
                select->rse_plan = par_plan(request);
 
2820
 
 
2821
        return select;
 
2822
}
 
2823
 
 
2824
 
 
2825
//____________________________________________________________
 
2826
//  
 
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
 
2831
//              list.
 
2832
//  
 
2833
 
 
2834
static gpre_rse* par_select( gpre_req* request, gpre_rse* union_rse)
 
2835
{
 
2836
        assert_IS_REQ(request);
 
2837
 
 
2838
        // Handle FIRST and SKIP clauses
 
2839
        gpre_nod* rse_first = NULL;
 
2840
        if (MSC_match(KW_FIRST))
 
2841
        {
 
2842
                rse_first = MSC_node(nod_list, 1);
 
2843
                rse_first->nod_arg[0] = SQE_value(request, false, NULL, NULL);
 
2844
        }
 
2845
 
 
2846
        gpre_nod* rse_skip = NULL;
 
2847
        if (MSC_match(KW_SKIP))
 
2848
        {
 
2849
                rse_skip = MSC_node(nod_list, 1);
 
2850
                rse_skip->nod_arg[0] = SQE_value(request, false, NULL, NULL);
 
2851
        }
 
2852
 
 
2853
//  Handle the ALL and DISTINCT options 
 
2854
 
 
2855
        const bool distinct = (!MSC_match(KW_ALL) && MSC_match(KW_DISTINCT));
 
2856
 
 
2857
//  Make select list out of select items 
 
2858
 
 
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;
 
2862
 
 
2863
//  If this is not a declare cursor statement and an INTO list is present,
 
2864
//  parse it. 
 
2865
 
 
2866
        gpre_nod* into_list = NULL;
 
2867
        if (!(request->req_flags & REQ_sql_declare_cursor))
 
2868
        {
 
2869
                into_list = (MSC_match(KW_INTO)) ? SQE_list(SQE_variable, request,
 
2870
                                                                                false) : NULL;
 
2871
        }
 
2872
 
 
2873
        gpre_rse* select = par_rse(request, s_list, distinct);
 
2874
 
 
2875
        if (rse_first)
 
2876
                resolve_fields(rse_first, request, select);
 
2877
        select->rse_sqlfirst = rse_first;
 
2878
 
 
2879
        if (rse_skip)
 
2880
                resolve_fields(rse_skip, request, select);
 
2881
        select->rse_sqlskip = rse_skip;
 
2882
 
 
2883
        if (select->rse_into = into_list)
 
2884
                select->rse_flags |= RSE_singleton;
 
2885
 
 
2886
        if (union_rse && s_list->nod_count != union_rse->rse_fields->nod_count)
 
2887
                PAR_error("select lists for UNION don't match");
 
2888
 
 
2889
        return select;
 
2890
}
 
2891
 
 
2892
 
 
2893
//____________________________________________________________
 
2894
//  
 
2895
//              Parse a dumb SQL scalar statistical expression.  Somebody else
 
2896
//              has already eaten the SELECT on the front.
 
2897
//  
 
2898
 
 
2899
static GPRE_NOD par_stat( gpre_req* request)
 
2900
{
 
2901
        assert_IS_REQ(request);
 
2902
 
 
2903
        request->req_in_subselect++;
 
2904
        scope previous_scope;
 
2905
        push_scope(request, &previous_scope);
 
2906
 
 
2907
        const bool distinct = (!MSC_match(KW_ALL) && MSC_match(KW_DISTINCT));
 
2908
 
 
2909
        request->req_in_select_list++;
 
2910
        gpre_nod* item = par_udf(request);
 
2911
        if (!item)
 
2912
                item = SQE_value(request, false, NULL, NULL);
 
2913
        request->req_in_select_list--;
 
2914
 
 
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;
 
2919
 
 
2920
        item = select->rse_fields->nod_arg[0];
 
2921
 
 
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;
 
2927
 
 
2928
        EXP_rse_cleanup(select);
 
2929
        pop_scope(request, &previous_scope);
 
2930
        request->req_in_subselect--;
 
2931
 
 
2932
        return node;
 
2933
}
 
2934
 
 
2935
 
 
2936
//____________________________________________________________
 
2937
//  
 
2938
//       Parse a subscript value.  
 
2939
//  
 
2940
 
 
2941
static GPRE_NOD par_subscript( gpre_req* request)
 
2942
{
 
2943
        assert_IS_REQ(request);
 
2944
 
 
2945
        ref* reference = (REF) MSC_alloc(REF_LEN);
 
2946
        gpre_nod* node = MSC_unary(nod_value, (GPRE_NOD) reference);
 
2947
 
 
2948
//  Special case literals 
 
2949
 
 
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);
 
2955
                PAR_get_token();
 
2956
                return node;
 
2957
        }
 
2958
 
 
2959
        if (!MSC_match(KW_COLON))
 
2960
                CPR_s_error("<colon>");
 
2961
 
 
2962
        reference->ref_value = PAR_native_value(false, false);
 
2963
 
 
2964
        if (request) {
 
2965
                reference->ref_next = request->req_values;
 
2966
                request->req_values = reference;
 
2967
        }
 
2968
 
 
2969
        return node;
 
2970
}
 
2971
 
 
2972
 
 
2973
//____________________________________________________________
 
2974
//  
 
2975
//              Match several trailing parentheses.
 
2976
//  
 
2977
 
 
2978
static void par_terminating_parens(
 
2979
                                                                   USHORT * paren_count, USHORT * local_count)
 
2980
{
 
2981
        // Suspicious condition.
 
2982
        if (*paren_count && paren_count == local_count)
 
2983
                do {
 
2984
                        EXP_match_paren();
 
2985
                } while (--(*paren_count));
 
2986
}
 
2987
 
 
2988
 
 
2989
//____________________________________________________________
 
2990
//  
 
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.
 
2994
//  
 
2995
 
 
2996
static GPRE_NOD par_udf( gpre_req* request)
 
2997
{
 
2998
        if (!request)
 
2999
                return NULL;
 
3000
 
 
3001
        assert_IS_REQ(request);
 
3002
 
 
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);
 
3007
 
 
3008
        GPRE_NOD node;
 
3009
        USHORT local_count;
 
3010
        
 
3011
        udf* an_udf;
 
3012
        if (request->req_database)
 
3013
                an_udf = MET_get_udf(request->req_database, gpreGlob.token_global.tok_string);
 
3014
        else {
 
3015
                /* no database was specified, check the metadata for all the databases
 
3016
                   for the existence of the udf */
 
3017
 
 
3018
                an_udf = NULL;
 
3019
                for (DBB db = gpreGlob.isc_databases; db; db = db->dbb_next)
 
3020
                {
 
3021
                        udf* tmp_udf = MET_get_udf(db, gpreGlob.token_global.tok_string);
 
3022
                        if (tmp_udf)
 
3023
                                if (an_udf) {
 
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);
 
3027
                                        PAR_error(s);
 
3028
                                }
 
3029
                                else {
 
3030
                                        an_udf = tmp_udf;
 
3031
                                        request->req_database = db;
 
3032
                                }
 
3033
                }
 
3034
        }
 
3035
 
 
3036
        if (an_udf) {
 
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)))
 
3041
                {
 
3042
                        SQL_dialect1_bad_type(an_udf->udf_dtype);
 
3043
                }
 
3044
 
 
3045
                node = MSC_node(nod_udf, 2);
 
3046
                node->nod_count = 1;
 
3047
                node->nod_arg[1] = (GPRE_NOD) an_udf;
 
3048
                PAR_get_token();
 
3049
                EXP_left_paren(0);
 
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);
 
3053
 
 
3054
                        if (an_udf->udf_args != node->nod_arg[0]->nod_count)
 
3055
                                PAR_error("count of UDF parameters doesn't match definition");
 
3056
 
 
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;
 
3060
                                 field;
 
3061
                                 input++, field = field->fld_next)
 
3062
                        {
 
3063
                                SQE_post_field(*input, field);
 
3064
                        }
 
3065
                }
 
3066
                else {
 
3067
                        node->nod_arg[0] = (GPRE_NOD) 0;
 
3068
                        node->nod_count = 0;
 
3069
                }
 
3070
                local_count = 1;
 
3071
                par_terminating_parens(&local_count, &local_count);
 
3072
                return node;
 
3073
        }
 
3074
 
 
3075
        if (!request)
 
3076
                return NULL;
 
3077
 
 
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;
 
3083
                EXP_left_paren(0);
 
3084
                SQL_resolve_identifier("<Generator Name>", gen_name, NAME_SIZE);
 
3085
                node->nod_arg[1] = (GPRE_NOD) gen_name;
 
3086
                PAR_get_token();
 
3087
                if (!MSC_match(KW_COMMA))
 
3088
                        CPR_s_error("<comma>");
 
3089
                node->nod_arg[0] = SQE_value(request, false, NULL, NULL);
 
3090
                local_count = 1;
 
3091
                par_terminating_parens(&local_count, &local_count);
 
3092
                return node;
 
3093
        }
 
3094
 
 
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);
 
3112
 
 
3113
//  End context variables *
 
3114
 
 
3115
//  Check for SQL II defined functions 
 
3116
 
 
3117
// ** Begin date/time/timestamp *
 
3118
        if (MSC_match(KW_EXTRACT)) {
 
3119
                node = MSC_node(nod_extract, 2);
 
3120
                EXP_left_paren(0);
 
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))
 
3125
                {
 
3126
                        node->nod_arg[0] = (gpre_nod*) kw_word;
 
3127
                        if (!MSC_match(KW_FROM))
 
3128
                                CPR_s_error("FROM");
 
3129
                }
 
3130
                else
 
3131
                        CPR_s_error("valid extract part");
 
3132
                node->nod_arg[1] = SQE_value(request, false, NULL, NULL);
 
3133
                local_count = 1;
 
3134
                par_terminating_parens(&local_count, &local_count);
 
3135
                return node;
 
3136
        }
 
3137
 
 
3138
//  End date/time/timestamp *
 
3139
 
 
3140
        if (MSC_match(KW_UPPER)) {
 
3141
                node = MSC_node(nod_upcase, 1);
 
3142
                EXP_left_paren(0);
 
3143
                node->nod_arg[0] = SQE_value(request, false, NULL, NULL);
 
3144
                local_count = 1;
 
3145
                par_terminating_parens(&local_count, &local_count);
 
3146
                return node;
 
3147
        }
 
3148
 
 
3149
        if (MSC_match(KW_LOWER)) {
 
3150
                node = MSC_node(nod_lowcase, 1);
 
3151
                EXP_left_paren(0);
 
3152
                node->nod_arg[0] = SQE_value(request, false, NULL, NULL);
 
3153
                local_count = 1;
 
3154
                par_terminating_parens(&local_count, &local_count);
 
3155
                return node;
 
3156
        }
 
3157
 
 
3158
        if (MSC_match(KW_CAST)) {
 
3159
                node = MSC_node(nod_cast, 2);
 
3160
                node->nod_count = 1;
 
3161
                EXP_left_paren(0);
 
3162
                node->nod_arg[0] = SQE_value_or_null(request, false, 0, 0);
 
3163
                if (!MSC_match(KW_AS))
 
3164
                        CPR_s_error("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);
 
3170
                local_count = 1;
 
3171
                par_terminating_parens(&local_count, &local_count);
 
3172
                return node;
 
3173
        }
 
3174
 
 
3175
        return NULL;
 
3176
}
 
3177
 
 
3178
 
 
3179
//____________________________________________________________
 
3180
//  
 
3181
//              Parse a user defined function or a field name.
 
3182
//  
 
3183
 
 
3184
static GPRE_NOD par_udf_or_field(gpre_req* request,
 
3185
                                                                 bool aster_ok)
 
3186
{
 
3187
        assert_IS_REQ(request);
 
3188
 
 
3189
        gpre_nod* node = par_udf(request);
 
3190
        if (!node)
 
3191
                node = SQE_field(request, aster_ok);
 
3192
 
 
3193
        return node;
 
3194
}
 
3195
 
 
3196
 
 
3197
//____________________________________________________________
 
3198
//  
 
3199
//              Parse a user defined function or a field name.
 
3200
//              Allow the collate clause to follow.
 
3201
//  
 
3202
 
 
3203
static GPRE_NOD par_udf_or_field_with_collate(gpre_req* request,
 
3204
                                                                                          bool aster_ok,
 
3205
                                                                                          USHORT * paren_count,
 
3206
                                                                                          bool * bool_flag)
 
3207
 
 
3208
{
 
3209
        assert_IS_REQ(request);
 
3210
 
 
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);
 
3214
 
 
3215
        return node;
 
3216
}
 
3217
 
 
3218
 
 
3219
//____________________________________________________________
 
3220
//
 
3221
//              Parse FOR UPDATE WITH LOCK clause
 
3222
//
 
3223
 
 
3224
static void par_update(gpre_rse *select, bool have_union, bool view_flag)
 
3225
{
 
3226
        // Parse FOR UPDATE if present
 
3227
        if (MSC_match(KW_FOR)) {
 
3228
                if (! MSC_match(KW_UPDATE)) {
 
3229
                        CPR_s_error("UPDATE");
 
3230
                        return;
 
3231
                }
 
3232
                if (MSC_match(KW_OF)) {
 
3233
                        do {
 
3234
                                CPR_token();
 
3235
                        } while (MSC_match(KW_COMMA));
 
3236
                }
 
3237
                select->rse_flags |= RSE_for_update;
 
3238
        }
 
3239
 
 
3240
        // Parse WITH LOCK if present
 
3241
        if (MSC_match(KW_WITH)) {
 
3242
                if (! MSC_match(KW_LOCK)) {
 
3243
                        CPR_s_error("LOCK");
 
3244
                        return;
 
3245
                }
 
3246
                if (have_union) {
 
3247
                        PAR_error("WITH LOCK in UNION");
 
3248
                        return;
 
3249
                }
 
3250
                if (view_flag) {
 
3251
                        PAR_error("WITH LOCK in VIEW");
 
3252
                        return;
 
3253
                }
 
3254
                select->rse_flags |= RSE_with_lock;
 
3255
        }
 
3256
}
 
3257
 
 
3258
//____________________________________________________________
 
3259
//  
 
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.
 
3264
//  
 
3265
 
 
3266
static GPRE_NOD post_fields( GPRE_NOD node, map* to_map)
 
3267
{
 
3268
        assert_IS_NOD(node);
 
3269
 
 
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
 
3275
                 * operation.
 
3276
                 case nod_literal:
 
3277
                 * 1995-Jul-10 David Schnepper 
 
3278
                 */
 
3279
        case nod_field:
 
3280
        case nod_agg_max:
 
3281
        case nod_agg_min:
 
3282
        case nod_agg_average:
 
3283
        case nod_agg_total:
 
3284
        case nod_agg_count:
 
3285
        case nod_map_ref:
 
3286
                return post_map(node, to_map);
 
3287
 
 
3288
        case nod_udf:
 
3289
        case nod_gen_id:
 
3290
                node->nod_arg[0] = post_fields(node->nod_arg[0], to_map);
 
3291
                break;
 
3292
 
 
3293
        case nod_list:
 
3294
        case nod_upcase:
 
3295
        case nod_lowcase:
 
3296
        case nod_concatenate:
 
3297
        case nod_cast:
 
3298
        case nod_plus:
 
3299
        case nod_minus:
 
3300
        case nod_times:
 
3301
        case nod_divide:
 
3302
        case nod_negate:
 
3303
                {
 
3304
                        gpre_nod** ptr = node->nod_arg;
 
3305
                        for (const gpre_nod* const* const end = ptr + node->nod_count;
 
3306
                                ptr < end; ptr++)
 
3307
                        {
 
3308
                                *ptr = post_fields(*ptr, to_map);
 
3309
                        }
 
3310
                        break;
 
3311
                }
 
3312
// ** Begin date/time/timestamp support *
 
3313
        case nod_extract:
 
3314
                node->nod_arg[1] = post_fields(node->nod_arg[1], to_map);
 
3315
                break;
 
3316
// ** End date/time/timestamp support *
 
3317
        }
 
3318
 
 
3319
        return node;
 
3320
}
 
3321
 
 
3322
 
 
3323
//____________________________________________________________
 
3324
//  
 
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).
 
3328
//  
 
3329
 
 
3330
static GPRE_NOD post_map( GPRE_NOD node, map* to_map)
 
3331
{
 
3332
        MEL element;
 
3333
 
 
3334
        assert_IS_NOD(node);
 
3335
 
 
3336
//  Search existing map for equivalent expression.  If we find one,
 
3337
//  return a reference to it. 
 
3338
 
 
3339
        if (node->nod_type == nod_map_ref) {
 
3340
                element = (MEL) node->nod_arg[0];
 
3341
                if (element->mel_context == to_map->map_context)
 
3342
                        return node;
 
3343
        }
 
3344
 
 
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);
 
3348
 
 
3349
//  We need to make up a new map reference 
 
3350
 
 
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;
 
3357
 
 
3358
//  Make up a reference to the map element 
 
3359
 
 
3360
        return MSC_unary(nod_map_ref, (GPRE_NOD) element);
 
3361
}
 
3362
 
 
3363
 
 
3364
//____________________________________________________________
 
3365
//  
 
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.
 
3371
//  
 
3372
 
 
3373
static GPRE_NOD post_select_list( GPRE_NOD fields, map* to_map)
 
3374
{
 
3375
        assert_IS_NOD(fields);
 
3376
 
 
3377
        gpre_nod* list = MSC_node(nod_list, fields->nod_count);
 
3378
 
 
3379
        for (USHORT i = 0; i < fields->nod_count; i++)
 
3380
                list->nod_arg[i] = post_map(fields->nod_arg[i], to_map);
 
3381
 
 
3382
        return list;
 
3383
}
 
3384
 
 
3385
 
 
3386
//____________________________________________________________
 
3387
//  
 
3388
//              Restore saved scoping information to the request block
 
3389
//  
 
3390
 
 
3391
static void pop_scope(gpre_req* request, scope* save_scope)
 
3392
{
 
3393
        assert_IS_REQ(request);
 
3394
 
 
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;
 
3402
}
 
3403
 
 
3404
 
 
3405
//____________________________________________________________
 
3406
//  
 
3407
//              Save scoping information from the request block
 
3408
//  
 
3409
 
 
3410
static void push_scope(gpre_req* request, scope* save_scope)
 
3411
{
 
3412
        assert_IS_REQ(request);
 
3413
 
 
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;
 
3429
}
 
3430
 
 
3431
 
 
3432
//____________________________________________________________
 
3433
//  
 
3434
//              Attempt to resolve a field in a context.  If successful, return
 
3435
//              the field.  Otherwise return NULL.  Let somebody else worry about
 
3436
//              errors.
 
3437
//  
 
3438
 
 
3439
static gpre_fld* resolve(
 
3440
                                   GPRE_NOD node,
 
3441
                                   gpre_ctx* context, gpre_ctx** found_context, act** slice_action)
 
3442
{
 
3443
        gpre_fld* field;
 
3444
 
 
3445
        assert_IS_NOD(node);
 
3446
 
 
3447
        gpre_rse* rs_stream = context->ctx_stream;
 
3448
        if (rs_stream) {
 
3449
                for (SSHORT i = 0; i < rs_stream->rse_count; i++)
 
3450
                        if (field =
 
3451
                                resolve(node, rs_stream->rse_context[i], found_context,
 
3452
                                                slice_action))
 
3453
                        {
 
3454
                                return field;
 
3455
                        }
 
3456
 
 
3457
                return NULL;
 
3458
        }
 
3459
 
 
3460
        TOK f_token = (TOK) node->nod_arg[0];
 
3461
        TOK q_token = (TOK) node->nod_arg[1];
 
3462
 
 
3463
        if (!(context->ctx_relation || context->ctx_procedure))
 
3464
                return NULL;
 
3465
 
 
3466
//  Handle unqualified fields first for simplicity 
 
3467
 
 
3468
        if (!q_token)
 
3469
                field = MET_context_field(context, f_token->tok_string);
 
3470
        else {
 
3471
                // Now search alternatives for the qualifier 
 
3472
 
 
3473
                gpre_sym* symbol = HSH_lookup(q_token->tok_string);
 
3474
 
 
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 
 
3477
 
 
3478
                   if ( (symbol == NULL) && (sw_case || gpreGlob.sw_sql_dialect == SQL_DIALECT_V5))
 
3479
                   symbol = HSH_lookup2 (q_token->tok_string);
 
3480
                 */
 
3481
 
 
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.
 
3484
                   FSG 16.Nov.2000
 
3485
                 */
 
3486
                if ((symbol == NULL))
 
3487
                        symbol = HSH_lookup2(q_token->tok_string);
 
3488
 
 
3489
 
 
3490
                for (gpre_sym* temp_symbol = symbol; temp_symbol;
 
3491
                         temp_symbol = temp_symbol->sym_homonym)
 
3492
                {
 
3493
                        if (temp_symbol->sym_type == SYM_context) {
 
3494
                                symbol = temp_symbol;
 
3495
                                break;
 
3496
                        }
 
3497
                        else if (temp_symbol->sym_type == SYM_relation) {
 
3498
                                symbol = temp_symbol;
 
3499
                                continue;
 
3500
                        }
 
3501
                        else if (temp_symbol->sym_type == SYM_procedure) {
 
3502
                                if (symbol->sym_type == SYM_relation)
 
3503
                                        continue;
 
3504
                                else
 
3505
                                        symbol = temp_symbol;
 
3506
                        }
 
3507
                }
 
3508
 
 
3509
 
 
3510
                field = NULL;
 
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);
 
3514
                }
 
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);
 
3518
                }
 
3519
                else if (symbol->sym_type == SYM_context && symbol->sym_object == context)
 
3520
                        field = MET_context_field(context, f_token->tok_string);
 
3521
        }
 
3522
 
 
3523
 
 
3524
        if (field && found_context)
 
3525
                *found_context = context;
 
3526
 
 
3527
//  Check for valid array field  
 
3528
//  Check dimensions 
 
3529
//  Set remaining fields for slice 
 
3530
        slc* slice;
 
3531
        gpre_req* slice_req = (gpre_req*) node->nod_arg[2];
 
3532
        if (slice_req && (slice = slice_req->req_slice) && slice_action)
 
3533
        {
 
3534
                slice = slice_req->req_slice;
 
3535
                ary* ary_info = field->fld_array_info;
 
3536
                if (!ary_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;
 
3542
 
 
3543
                /* The action type maybe ACT_get_slice or ACT_put_slice 
 
3544
                   set as a place holder */
 
3545
 
 
3546
                act* action = MSC_action(slice_req, ACT_get_slice);
 
3547
                action->act_object = (REF) slice;
 
3548
                *slice_action = action;
 
3549
        }
 
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 */
 
3553
 
 
3554
                act* action = MSC_action(slice_req, ACT_get_slice);
 
3555
                *slice_action = action;
 
3556
        }
 
3557
 
 
3558
        return field;
 
3559
}
 
3560
 
 
3561
 
 
3562
//____________________________________________________________
 
3563
//  
 
3564
//              Attempt to resolve an asterisk in a context.
 
3565
//              If successful, return the context.  Otherwise return NULL.
 
3566
//  
 
3567
 
 
3568
static gpre_ctx* resolve_asterisk( TOK q_token, gpre_rse* selection)
 
3569
{
 
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;
 
3573
                if (rs_stream) {
 
3574
                        if (context = resolve_asterisk(q_token, rs_stream))
 
3575
                                return context;
 
3576
                        continue;
 
3577
                }
 
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)
 
3582
                        {
 
3583
                                return context;
 
3584
                        }
 
3585
                        else if (symbol->sym_type == SYM_procedure &&
 
3586
                                         (gpre_prc*) symbol->sym_object == context->ctx_procedure)
 
3587
                        {
 
3588
                                return context;
 
3589
                        }
 
3590
                        else if (symbol->sym_type == SYM_context &&
 
3591
                                         (gpre_ctx*) symbol->sym_object == context)
 
3592
                        {
 
3593
                                return context;
 
3594
                        }
 
3595
        }
 
3596
 
 
3597
        return NULL;
 
3598
}
 
3599
 
 
3600
 
 
3601
//____________________________________________________________
 
3602
//  
 
3603
//              Set field reference for any host variables in expr to field_ref.
 
3604
//  
 
3605
 
 
3606
static void set_ref( GPRE_NOD expr, gpre_fld* field_ref)
 
3607
{
 
3608
        assert_IS_NOD(expr);
 
3609
 
 
3610
        ref* re = (REF) expr->nod_arg[0];
 
3611
        switch (expr->nod_type) {
 
3612
        case nod_value:
 
3613
                re->ref_field = field_ref;
 
3614
                break;
 
3615
 
 
3616
        case nod_agg_count:
 
3617
        case nod_agg_max:
 
3618
        case nod_agg_min:
 
3619
        case nod_agg_total:
 
3620
        case nod_agg_average:
 
3621
        case nod_plus:
 
3622
        case nod_minus:
 
3623
        case nod_times:
 
3624
        case nod_divide:
 
3625
        case nod_negate:
 
3626
        case nod_upcase:
 
3627
        case nod_lowcase:
 
3628
        case nod_concatenate:
 
3629
        case nod_cast:
 
3630
                {
 
3631
            gpre_nod** ptr = expr->nod_arg;
 
3632
                        for (const gpre_nod* const* const end = ptr + expr->nod_count;
 
3633
                                ptr < end; ptr++)
 
3634
                        {
 
3635
                                set_ref(*ptr, field_ref);
 
3636
                        }
 
3637
                        break;
 
3638
                }
 
3639
// ** Begin date/time/timestamp support *
 
3640
        case nod_extract:
 
3641
                set_ref(expr->nod_arg[1], field_ref);
 
3642
                break;
 
3643
// ** End date/time/timestamp support *
 
3644
        }
 
3645
}
 
3646
 
 
3647
 
 
3648
//____________________________________________________________
 
3649
//  
 
3650
//              Return the uppercase version of
 
3651
//              the input string.
 
3652
//  
 
3653
 
 
3654
static char* upcase_string(const char* p)
 
3655
{
 
3656
        USHORT l = 0;
 
3657
        char* const s = (char *) MSC_alloc(strlen(p) + 1);
 
3658
        char* q = s;
 
3659
 
 
3660
        char c;
 
3661
        while ((c = *p++) && (++l <= NAME_SIZE)) {
 
3662
                *q++ = UPPER7(c);
 
3663
        }
 
3664
        *q = 0;
 
3665
 
 
3666
        return s;
 
3667
}
 
3668
 
 
3669
 
 
3670
//____________________________________________________________
 
3671
//  
 
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
 
3678
//              directly.       
 
3679
//  
 
3680
 
 
3681
static bool validate_references(const gpre_nod* fields,
 
3682
                                                                const gpre_nod* group_by)
 
3683
{
 
3684
        assert_IS_NOD(fields);
 
3685
        assert_IS_NOD(group_by);
 
3686
 
 
3687
        if (!fields)
 
3688
                return false;
 
3689
 
 
3690
        if (fields->nod_type == nod_field) {
 
3691
                if (!group_by)
 
3692
                        return true;
 
3693
                const ref* fref = (REF) fields->nod_arg[0];
 
3694
 
 
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;
 
3698
                         ptr < end; ptr++)
 
3699
                {
 
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)
 
3703
                                        return false;
 
3704
                                context_match = true;
 
3705
                        }
 
3706
                }
 
3707
                return context_match;
 
3708
        }
 
3709
 
 
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)
 
3716
        {
 
3717
                return false;
 
3718
        }
 
3719
 
 
3720
        if (fields->nod_type == nod_any || fields->nod_type == nod_ansi_any ||
 
3721
                fields->nod_type == nod_ansi_all) 
 
3722
        {
 
3723
                const gpre_rse* any = (gpre_rse*) fields->nod_arg[0];
 
3724
                return validate_references(any->rse_boolean, group_by);
 
3725
        }
 
3726
 
 
3727
        if ((fields->nod_type == nod_gen_id) || (fields->nod_type == nod_udf))
 
3728
                return validate_references(fields->nod_arg[0], group_by);
 
3729
 
 
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;
 
3733
                 ptr++)
 
3734
        {
 
3735
                switch ((*ptr)->nod_type) {
 
3736
                case nod_map_ref:
 
3737
                        {
 
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)
 
3746
                                {
 
3747
                                        invalid |= validate_references(node, group_by);
 
3748
                                }
 
3749
                                break;
 
3750
                        }
 
3751
 
 
3752
                case nod_field:
 
3753
                case nod_plus:
 
3754
                case nod_minus:
 
3755
                case nod_times:
 
3756
                case nod_negate:
 
3757
                case nod_divide:
 
3758
                case nod_and:
 
3759
                case nod_like:
 
3760
                case nod_missing:
 
3761
                case nod_not:
 
3762
                case nod_or:
 
3763
                case nod_eq:
 
3764
                case nod_ne:
 
3765
                case nod_gt:
 
3766
                case nod_ge:
 
3767
                case nod_le:
 
3768
                case nod_lt:
 
3769
                case nod_upcase:
 
3770
                case nod_lowcase:
 
3771
                case nod_concatenate:
 
3772
                case nod_cast:
 
3773
                        invalid |= validate_references(*ptr, group_by);
 
3774
                        break;
 
3775
                }
 
3776
        }
 
3777
 
 
3778
        return invalid;
 
3779
}
 
3780