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

« back to all changes in this revision

Viewing changes to src/dsql/gen.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
 *      PROGRAM:        Dynamic SQL runtime support
 
3
 *      MODULE:         gen.cpp
 
4
 *      DESCRIPTION:    Routines to generate BLR.
 
5
 *
 
6
 * The contents of this file are subject to the Interbase Public
 
7
 * License Version 1.0 (the "License"); you may not use this file
 
8
 * except in compliance with the License. You may obtain a copy
 
9
 * of the License at http://www.Inprise.com/IPL.html
 
10
 *
 
11
 * Software distributed under the License is distributed on an
 
12
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
 
13
 * or implied. See the License for the specific language governing
 
14
 * rights and limitations under the License.
 
15
 *
 
16
 * The Original Code was created by Inprise Corporation
 
17
 * and its predecessors. Portions created by Inprise Corporation are
 
18
 * Copyright (C) Inprise Corporation.
 
19
 *
 
20
 * All Rights Reserved.
 
21
 * Contributor(s): ______________________________________
 
22
 * 2001.6.21 Claudio Valderrama: BREAK and SUBSTRING.
 
23
 * 2001.07.28 John Bellardo:  Added code to generate blr_skip.
 
24
 * 2002.07.30 Arno Brinkman:  Added code, procedures to generate COALESCE, CASE
 
25
 * 2002.09.28 Dmitry Yemanov: Reworked internal_info stuff, enhanced
 
26
 *                            exception handling in SPs/triggers,
 
27
 *                            implemented ROWS_AFFECTED system variable
 
28
 * 2002.10.21 Nickolay Samofatov: Added support for explicit pessimistic locks
 
29
 * 2002.10.29 Nickolay Samofatov: Added support for savepoints
 
30
 * 2003.10.05 Dmitry Yemanov: Added support for explicit cursors in PSQL
 
31
 * 2004.01.16 Vlad Horsun: Added support for default parameters and 
 
32
 *   EXECUTE BLOCK statement
 
33
 * Adriano dos Santos Fernandes
 
34
 */
 
35
 
 
36
#include "firebird.h"
 
37
#include <string.h>
 
38
#include <stdio.h>
 
39
#include "../dsql/dsql.h"
 
40
#include "../jrd/ibase.h"
 
41
#include "../jrd/align.h"
 
42
#include "../jrd/constants.h"
 
43
#include "../jrd/intl.h"
 
44
#include "../jrd/val.h"
 
45
#include "../dsql/alld_proto.h"
 
46
#include "../dsql/ddl_proto.h"
 
47
#include "../dsql/errd_proto.h"
 
48
#include "../dsql/gen_proto.h"
 
49
#include "../dsql/make_proto.h"
 
50
#include "../dsql/metd_proto.h"
 
51
#include "../dsql/misc_func.h"
 
52
#include "../dsql/utld_proto.h"
 
53
#include "../jrd/thd.h"
 
54
#include "../jrd/thread_proto.h"
 
55
#include "../jrd/dsc_proto.h"
 
56
#include "../jrd/why_proto.h"
 
57
#include "gen/iberror.h"
 
58
 
 
59
static void gen_aggregate(dsql_req*, const dsql_nod*);
 
60
static void gen_cast(dsql_req*, const dsql_nod*);
 
61
static void gen_coalesce(dsql_req*, const dsql_nod*);
 
62
static void gen_constant(dsql_req*, const dsc*, bool);
 
63
static void gen_constant(dsql_req*, dsql_nod*, bool);
 
64
static void gen_descriptor(dsql_req*, const dsc*, bool);
 
65
static void gen_error_condition(dsql_req*, const dsql_nod*);
 
66
static void gen_field(dsql_req*, const dsql_ctx*, const dsql_fld*, dsql_nod*);
 
67
static void gen_for_select(dsql_req*, const dsql_nod*);
 
68
static void gen_gen_id(dsql_req*, const dsql_nod*);
 
69
static void gen_join_rse(dsql_req*, const dsql_nod*);
 
70
static void gen_map(dsql_req*, dsql_map*);
 
71
static void gen_parameter(dsql_req*, const dsql_par*);
 
72
static void gen_plan(dsql_req*, const dsql_nod*);
 
73
static void gen_relation(dsql_req*, dsql_ctx*);
 
74
static void gen_rse(dsql_req*, const dsql_nod*);
 
75
static void gen_searched_case(dsql_req*, const dsql_nod*);
 
76
static void gen_select(dsql_req*, dsql_nod*);
 
77
static void gen_simple_case(dsql_req*, const dsql_nod*);
 
78
static void gen_sort(dsql_req*, dsql_nod*);
 
79
static void gen_statement(dsql_req*, const dsql_nod*);
 
80
static void gen_sys_function(dsql_req*, const dsql_nod*);
 
81
static void gen_table_lock(dsql_req*, const dsql_nod*, USHORT);
 
82
static void gen_udf(dsql_req*, const dsql_nod*);
 
83
static void gen_union(dsql_req*, const dsql_nod*);
 
84
static void stuff_context(dsql_req*, const dsql_ctx*);
 
85
static void stuff_cstring(dsql_req*, const char*);
 
86
static void stuff_meta_string(dsql_req*, const char*);
 
87
static void stuff_string(dsql_req*, const char*, int);
 
88
static void stuff_word(dsql_req*, USHORT);
 
89
 
 
90
// STUFF is defined in dsql.h for use in common with ddl.c 
 
91
 
 
92
// The following are passed as the third argument to gen_constant 
 
93
const bool NEGATE_VALUE = true;
 
94
const bool USE_VALUE    = false;
 
95
 
 
96
 
 
97
/**
 
98
  
 
99
        GEN_expr
 
100
  
 
101
    @brief      Generate blr for an arbitrary expression.
 
102
 
 
103
 
 
104
    @param request
 
105
    @param node
 
106
 
 
107
 **/
 
108
void GEN_expr( dsql_req* request, dsql_nod* node)
 
109
{
 
110
        UCHAR blr_operator;
 
111
        dsql_nod* ddl_node;
 
112
        dsql_ctx* context;
 
113
        dsql_map* map;
 
114
        dsql_var* variable;
 
115
 
 
116
        switch (node->nod_type) {
 
117
        case nod_alias:
 
118
                GEN_expr(request, node->nod_arg[e_alias_value]);
 
119
                return;
 
120
 
 
121
        case nod_aggregate:
 
122
                gen_aggregate(request, node);
 
123
                return;
 
124
 
 
125
        case nod_constant:
 
126
                gen_constant(request, node, USE_VALUE);
 
127
                return;
 
128
 
 
129
        case nod_derived_field:
 
130
                GEN_expr(request, node->nod_arg[e_derived_field_value]);
 
131
                return;
 
132
 
 
133
        case nod_extract:
 
134
                stuff(request, blr_extract);
 
135
                stuff(request, node->nod_arg[e_extract_part]->getSlong());
 
136
                GEN_expr(request, node->nod_arg[e_extract_value]);
 
137
                return;
 
138
 
 
139
        case nod_strlen:
 
140
                stuff(request, blr_strlen);
 
141
                stuff(request, node->nod_arg[e_strlen_type]->getSlong());
 
142
                GEN_expr(request, node->nod_arg[e_strlen_value]);
 
143
                return;
 
144
 
 
145
        case nod_dbkey:
 
146
                node = node->nod_arg[0];
 
147
                context = (dsql_ctx*) node->nod_arg[e_rel_context];
 
148
                stuff(request, blr_dbkey);
 
149
                stuff_context(request, context);
 
150
                return;
 
151
 
 
152
        case nod_rec_version:
 
153
                node = node->nod_arg[0];
 
154
                context = (dsql_ctx*) node->nod_arg[e_rel_context];
 
155
                stuff(request, blr_record_version);
 
156
                stuff_context(request, context);
 
157
                return;
 
158
 
 
159
        case nod_dom_value:
 
160
                if ((request->req_type != REQ_DDL) ||
 
161
                        !(ddl_node = request->req_ddl_node) ||
 
162
                        !(ddl_node->nod_type == nod_def_domain ||
 
163
                          ddl_node->nod_type == nod_mod_domain))
 
164
                {
 
165
                                ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 901,
 
166
                                                  isc_arg_gds, isc_dsql_domain_err, 0);
 
167
                }
 
168
                stuff(request, blr_fid);
 
169
                stuff(request, 0);                              // Context   
 
170
                stuff_word(request, 0);                 // Field id  
 
171
                return;
 
172
 
 
173
        case nod_field:
 
174
                gen_field(request,
 
175
                                  (dsql_ctx*) node->nod_arg[e_fld_context],
 
176
                                  (dsql_fld*) node->nod_arg[e_fld_field],
 
177
                                  node->nod_arg[e_fld_indices]);
 
178
                return;
 
179
 
 
180
        case nod_user_name:
 
181
                stuff(request, blr_user_name);
 
182
                return;
 
183
 
 
184
        case nod_current_time:
 
185
                if (node->nod_arg[0]) {
 
186
                        const dsql_nod* const_node = node->nod_arg[0];
 
187
                        fb_assert(const_node->nod_type == nod_constant);
 
188
                        const int precision = (int) const_node->getSlong();
 
189
                        stuff(request, blr_current_time2);
 
190
                        stuff(request, precision);
 
191
                }
 
192
                else {
 
193
                        stuff(request, blr_current_time);
 
194
                }
 
195
                return;
 
196
 
 
197
        case nod_current_timestamp:
 
198
                if (node->nod_arg[0]) {
 
199
                        const dsql_nod* const_node = node->nod_arg[0];
 
200
                        fb_assert(const_node->nod_type == nod_constant);
 
201
                        const int precision = (int) const_node->getSlong();
 
202
                        stuff(request, blr_current_timestamp2);
 
203
                        stuff(request, precision);
 
204
                }
 
205
                else {
 
206
                        stuff(request, blr_current_timestamp);
 
207
                }
 
208
                return;
 
209
 
 
210
        case nod_current_date:
 
211
                stuff(request, blr_current_date);
 
212
                return;
 
213
 
 
214
        case nod_current_role:
 
215
                stuff(request, blr_current_role);
 
216
                return;
 
217
 
 
218
        case nod_udf:
 
219
                gen_udf(request, node);
 
220
                return;
 
221
 
 
222
        case nod_sys_function:
 
223
                gen_sys_function(request, node);
 
224
                return;
 
225
 
 
226
        case nod_variable:
 
227
                variable = (dsql_var*) node->nod_arg[e_var_variable];
 
228
                if (variable->var_flags & VAR_input) {
 
229
                        stuff(request, blr_parameter2);
 
230
                        stuff(request, variable->var_msg_number);
 
231
                        stuff_word(request, variable->var_msg_item);
 
232
                        stuff_word(request, variable->var_msg_item + 1);
 
233
                }
 
234
                else {
 
235
                        stuff(request, blr_variable);
 
236
                        stuff_word(request, variable->var_variable_number);
 
237
                }
 
238
                return;
 
239
 
 
240
        case nod_join:
 
241
                gen_join_rse(request, node);
 
242
                return;
 
243
 
 
244
        case nod_map:
 
245
                map = (dsql_map*) node->nod_arg[e_map_map];
 
246
                context = (dsql_ctx*) node->nod_arg[e_map_context];
 
247
                stuff(request, blr_fid);
 
248
                stuff_context(request, context);
 
249
                stuff_word(request, map->map_position);
 
250
                return;
 
251
 
 
252
        case nod_parameter:
 
253
                gen_parameter(request, (dsql_par*) node->nod_arg[e_par_parameter]);
 
254
                return;
 
255
 
 
256
        case nod_relation:
 
257
                gen_relation(request, (dsql_ctx*) node->nod_arg[e_rel_context]);
 
258
                return;
 
259
 
 
260
        case nod_rse:
 
261
                gen_rse(request, node);
 
262
                return;
 
263
 
 
264
        case nod_derived_table:
 
265
                gen_rse(request, node->nod_arg[e_derived_table_rse]);
 
266
                return;
 
267
 
 
268
        case nod_exists:
 
269
                stuff(request, blr_any);
 
270
                gen_rse(request, node->nod_arg[0]);
 
271
                return;
 
272
 
 
273
        case nod_singular:
 
274
                stuff(request, blr_unique);
 
275
                gen_rse(request, node->nod_arg[0]);
 
276
                return;
 
277
 
 
278
        case nod_agg_count:
 
279
                if (node->nod_count)
 
280
                        blr_operator = (node->nod_flags & NOD_AGG_DISTINCT) ?
 
281
                                blr_agg_count_distinct : blr_agg_count2;
 
282
                else
 
283
                        blr_operator = blr_agg_count;
 
284
                break;
 
285
 
 
286
        case nod_agg_min:
 
287
                blr_operator = blr_agg_min;
 
288
                break;
 
289
        case nod_agg_max:
 
290
                blr_operator = blr_agg_max;
 
291
                break;
 
292
 
 
293
        case nod_agg_average:
 
294
                blr_operator = (node->nod_flags & NOD_AGG_DISTINCT) ?
 
295
                        blr_agg_average_distinct : blr_agg_average;
 
296
                break;
 
297
 
 
298
        case nod_agg_total:
 
299
                blr_operator = (node->nod_flags & NOD_AGG_DISTINCT) ?
 
300
                        blr_agg_total_distinct : blr_agg_total;
 
301
                break;
 
302
 
 
303
        case nod_agg_average2:
 
304
                blr_operator = (node->nod_flags & NOD_AGG_DISTINCT) ?
 
305
                        blr_agg_average_distinct : blr_agg_average;
 
306
                break;
 
307
 
 
308
        case nod_agg_total2:
 
309
                blr_operator = (node->nod_flags & NOD_AGG_DISTINCT) ?
 
310
                        blr_agg_total_distinct : blr_agg_total;
 
311
                break;
 
312
 
 
313
        case nod_agg_list:
 
314
                blr_operator = (node->nod_flags & NOD_AGG_DISTINCT) ?
 
315
                        blr_agg_list_distinct : blr_agg_list;
 
316
                break;
 
317
 
 
318
        case nod_and:
 
319
                blr_operator = blr_and;
 
320
                break;
 
321
        case nod_or:
 
322
                blr_operator = blr_or;
 
323
                break;
 
324
        case nod_not:
 
325
                blr_operator = blr_not;
 
326
                break;
 
327
        case nod_eql_all:
 
328
        case nod_eql_any:
 
329
        case nod_eql:
 
330
                blr_operator = blr_eql;
 
331
                break;
 
332
        case nod_equiv:
 
333
                blr_operator = blr_equiv;
 
334
                break;
 
335
        case nod_neq_all:
 
336
        case nod_neq_any:
 
337
        case nod_neq:
 
338
                blr_operator = blr_neq;
 
339
                break;
 
340
        case nod_gtr_all:
 
341
        case nod_gtr_any:
 
342
        case nod_gtr:
 
343
                blr_operator = blr_gtr;
 
344
                break;
 
345
        case nod_leq_all:
 
346
        case nod_leq_any:
 
347
        case nod_leq:
 
348
                blr_operator = blr_leq;
 
349
                break;
 
350
        case nod_geq_all:
 
351
        case nod_geq_any:
 
352
        case nod_geq:
 
353
                blr_operator = blr_geq;
 
354
                break;
 
355
        case nod_lss_all:
 
356
        case nod_lss_any:
 
357
        case nod_lss:
 
358
                blr_operator = blr_lss;
 
359
                break;
 
360
        case nod_between:
 
361
                blr_operator = blr_between;
 
362
                break;
 
363
        case nod_containing:
 
364
                blr_operator = blr_containing;
 
365
                break;
 
366
        case nod_starting:
 
367
                blr_operator = blr_starting;
 
368
                break;
 
369
        case nod_missing:
 
370
                blr_operator = blr_missing;
 
371
                break;
 
372
 
 
373
        case nod_like:
 
374
                blr_operator = (node->nod_count == 2) ? blr_like : blr_ansi_like;
 
375
                break;
 
376
 
 
377
        case nod_add:
 
378
                blr_operator = blr_add;
 
379
                break;
 
380
        case nod_subtract:
 
381
                blr_operator = blr_subtract;
 
382
                break;
 
383
        case nod_multiply:
 
384
                blr_operator = blr_multiply;
 
385
                break;
 
386
 
 
387
        case nod_negate:
 
388
                {
 
389
                        dsql_nod* child = node->nod_arg[0];
 
390
                        if (child->nod_type == nod_constant &&
 
391
                                DTYPE_IS_NUMERIC(child->nod_desc.dsc_dtype))
 
392
                        {
 
393
                                gen_constant(request, child, NEGATE_VALUE);
 
394
                                return;
 
395
                        }
 
396
                }
 
397
                blr_operator = blr_negate;
 
398
                break;
 
399
 
 
400
        case nod_divide:
 
401
                blr_operator = blr_divide;
 
402
                break;
 
403
        case nod_add2:
 
404
                blr_operator = blr_add;
 
405
                break;
 
406
        case nod_subtract2:
 
407
                blr_operator = blr_subtract;
 
408
                break;
 
409
        case nod_multiply2:
 
410
                blr_operator = blr_multiply;
 
411
                break;
 
412
        case nod_divide2:
 
413
                blr_operator = blr_divide;
 
414
                break;
 
415
        case nod_concatenate:
 
416
                blr_operator = blr_concatenate;
 
417
                break;
 
418
        case nod_null:
 
419
                blr_operator = blr_null;
 
420
                break;
 
421
        case nod_any:
 
422
                blr_operator = blr_any;
 
423
                break;
 
424
        case nod_ansi_any:
 
425
                blr_operator = blr_ansi_any;
 
426
                break;
 
427
        case nod_ansi_all:
 
428
                blr_operator = blr_ansi_all;
 
429
                break;
 
430
        case nod_via:
 
431
                blr_operator = blr_via;
 
432
                break;
 
433
 
 
434
        case nod_internal_info:
 
435
                blr_operator = blr_internal_info;
 
436
                break;
 
437
        case nod_upcase:
 
438
                blr_operator = blr_upcase;
 
439
                break;
 
440
        case nod_lowcase:
 
441
                blr_operator = blr_lowcase;
 
442
                break;
 
443
        case nod_substr:        
 
444
        blr_operator = blr_substring;
 
445
        break;
 
446
        case nod_cast:
 
447
                gen_cast(request, node);
 
448
                return;
 
449
        case nod_gen_id:
 
450
        case nod_gen_id2:
 
451
                gen_gen_id(request, node);
 
452
                return;
 
453
    case nod_coalesce: 
 
454
                gen_coalesce(request, node);
 
455
                return;
 
456
    case nod_simple_case: 
 
457
                gen_simple_case(request, node);
 
458
                return;
 
459
    case nod_searched_case: 
 
460
                gen_searched_case(request, node);
 
461
                return;
 
462
        case nod_average:
 
463
        //case nod_count:
 
464
        case nod_from:
 
465
        case nod_max:
 
466
        case nod_min:
 
467
        case nod_total:
 
468
                switch (node->nod_type) {
 
469
                case nod_average:
 
470
                        blr_operator = blr_average;
 
471
                        break;
 
472
                //case nod_count:
 
473
                //      blr_operator = blr_count;
 
474
                // count2
 
475
                //      blr_operator = node->nod_arg[0]->nod_arg[e_rse_items] ? blr_count2 : blr_count;
 
476
 
 
477
                //      break;
 
478
                case nod_from:
 
479
                        blr_operator = blr_from;
 
480
                        break;
 
481
                case nod_max:
 
482
                        blr_operator = blr_maximum;
 
483
                        break;
 
484
                case nod_min:
 
485
                        blr_operator = blr_minimum;
 
486
                        break;
 
487
                case nod_total:
 
488
                        blr_operator = blr_total;
 
489
                        break;
 
490
 
 
491
                default:
 
492
                        break;
 
493
                }
 
494
 
 
495
                stuff(request, blr_operator);
 
496
                gen_rse(request, node->nod_arg[0]);
 
497
                if (blr_operator != blr_count)
 
498
                        GEN_expr(request, node->nod_arg[0]->nod_arg[e_rse_items]);
 
499
                return;
 
500
 
 
501
        case nod_trim:
 
502
                stuff(request, blr_trim);
 
503
                stuff(request, node->nod_arg[e_trim_specification]->getSlong());
 
504
 
 
505
                if (node->nod_arg[e_trim_characters])
 
506
                {
 
507
                        stuff(request, blr_trim_characters);
 
508
                        GEN_expr(request, node->nod_arg[e_trim_characters]);
 
509
                }
 
510
                else
 
511
                        stuff(request, blr_trim_spaces);
 
512
 
 
513
                GEN_expr(request, node->nod_arg[e_trim_value]);
 
514
                return;
 
515
 
 
516
        default:
 
517
                ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 901,
 
518
                                  isc_arg_gds, isc_dsql_internal_err,
 
519
                                  isc_arg_gds, isc_expression_eval_err,
 
520
                                  // expression evaluation not supported 
 
521
                                  0);
 
522
        }
 
523
 
 
524
        stuff(request, blr_operator);
 
525
 
 
526
        dsql_nod* const* ptr = node->nod_arg;
 
527
        for (const dsql_nod* const* const end = ptr + node->nod_count;
 
528
                ptr < end; ptr++)
 
529
        {
 
530
                GEN_expr(request, *ptr);
 
531
        }
 
532
 
 
533
/* Check whether the node we just processed is for a dialect 3
 
534
   operation which gives a different result than the corresponding
 
535
   operation in dialect 1.  If it is, and if the client dialect is 2,
 
536
   issue a warning about the difference. */
 
537
 
 
538
        if (node->nod_type == nod_add2 ||
 
539
                node->nod_type == nod_subtract2 ||
 
540
                node->nod_type == nod_multiply2 ||
 
541
                node->nod_type == nod_divide2 ||
 
542
                node->nod_type == nod_agg_total2 ||
 
543
                node->nod_type == nod_agg_average2) 
 
544
        {
 
545
                dsc desc;
 
546
                const char* s = 0;
 
547
                char message_buf[8];
 
548
 
 
549
                MAKE_desc(request, &desc, node, NULL);
 
550
                if ((node->nod_flags & NOD_COMP_DIALECT) &&
 
551
                        (request->req_client_dialect == SQL_DIALECT_V6_TRANSITION)) 
 
552
                {
 
553
                        switch (node->nod_type) {
 
554
                        case nod_add2:
 
555
                                s = "add";
 
556
                                break;
 
557
                        case nod_subtract2:
 
558
                                s = "subtract";
 
559
                                break;
 
560
                        case nod_multiply2:
 
561
                                s = "multiply";
 
562
                                break;
 
563
                        case nod_divide2:
 
564
                                s = "divide";
 
565
                                break;
 
566
                        case nod_agg_total2:
 
567
                                s = "sum";
 
568
                                break;
 
569
                        case nod_agg_average2:
 
570
                                s = "avg";
 
571
                                break;
 
572
                        default:
 
573
                                sprintf(message_buf, "blr %d", (int) blr_operator);
 
574
                                s = message_buf;
 
575
                        }
 
576
                        ERRD_post_warning(isc_dsql_dialect_warning_expr,
 
577
                                                          isc_arg_string, s, isc_arg_end);
 
578
                }
 
579
        }
 
580
 
 
581
}
 
582
 
 
583
/**
 
584
  
 
585
        GEN_port
 
586
  
 
587
    @brief      Generate a port from a message.  Feel free to rearrange the
 
588
        order of parameters.
 
589
 
 
590
 
 
591
    @param request
 
592
    @param message
 
593
 
 
594
 **/
 
595
void GEN_port( dsql_req* request, dsql_msg* message)
 
596
{
 
597
        tsql* tdsql = DSQL_get_thread_data();
 
598
 
 
599
//      if (request->req_blr_string) {
 
600
                stuff(request, blr_message);
 
601
                stuff(request, message->msg_number);
 
602
                stuff_word(request, message->msg_parameter);
 
603
//      }
 
604
 
 
605
    dsql_par* parameter;
 
606
 
 
607
        ULONG offset = 0;
 
608
        USHORT number = 0;
 
609
        for (parameter = message->msg_parameters; parameter;
 
610
                 parameter = parameter->par_next)
 
611
        {
 
612
                parameter->par_parameter = number++;
 
613
 
 
614
                const USHORT fromCharSet = parameter->par_desc.getCharSet();
 
615
                const USHORT toCharSet = (fromCharSet == CS_NONE || fromCharSet == CS_BINARY) ?
 
616
                        fromCharSet : request->req_dbb->dbb_att_charset;
 
617
 
 
618
                if (parameter->par_desc.dsc_dtype <= dtype_any_text &&
 
619
                        request->req_dbb->dbb_att_charset != CS_NONE &&
 
620
                        request->req_dbb->dbb_att_charset != CS_BINARY)
 
621
                {
 
622
                        USHORT adjust = 0;
 
623
                        if (parameter->par_desc.dsc_dtype == dtype_varying)
 
624
                                adjust = sizeof(USHORT);
 
625
                        else if (parameter->par_desc.dsc_dtype == dtype_cstring)
 
626
                                adjust = 1;
 
627
 
 
628
                        parameter->par_desc.dsc_length -= adjust;
 
629
 
 
630
                        USHORT fromCharSetBPC = METD_get_charset_bpc(request, fromCharSet);
 
631
                        USHORT toCharSetBPC = METD_get_charset_bpc(request, toCharSet);
 
632
 
 
633
                        INTL_ASSIGN_TTYPE(&parameter->par_desc, INTL_CS_COLL_TO_TTYPE(toCharSet,
 
634
                                (fromCharSet == toCharSet ? INTL_GET_COLLATE(&parameter->par_desc) : 0)));
 
635
 
 
636
                        parameter->par_desc.dsc_length =
 
637
                                UTLD_char_length_to_byte_length(parameter->par_desc.dsc_length / fromCharSetBPC, toCharSetBPC);
 
638
 
 
639
                        parameter->par_desc.dsc_length += adjust;
 
640
                }
 
641
                else if (ENCODE_ODS(request->req_dbb->dbb_ods_version,
 
642
                                        request->req_dbb->dbb_minor_version) >= ODS_11_1 &&
 
643
                        parameter->par_desc.dsc_dtype == dtype_blob &&
 
644
                        parameter->par_desc.dsc_sub_type == isc_blob_text &&
 
645
                        request->req_dbb->dbb_att_charset != CS_NONE &&
 
646
                        request->req_dbb->dbb_att_charset != CS_BINARY)
 
647
                {
 
648
                        if (fromCharSet != toCharSet)
 
649
                                parameter->par_desc.setTextType(toCharSet);
 
650
                }
 
651
 
 
652
                /* For older clients - generate an error should they try and
 
653
                   access data types which did not exist in the older dialect */
 
654
                if (request->req_client_dialect <= SQL_DIALECT_V5)
 
655
                        switch (parameter->par_desc.dsc_dtype) {
 
656
 
 
657
                                /* In V6.0 - older clients, which we distinguish by
 
658
                                   their use of SQL DIALECT 0 or 1, are forbidden
 
659
                                   from selecting values of new datatypes */
 
660
                                case dtype_sql_date:
 
661
                                case dtype_sql_time:
 
662
                                case dtype_int64:
 
663
                                        ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 804,
 
664
                                                          isc_arg_gds, isc_dsql_datatype_err,
 
665
                                                          isc_arg_gds, isc_sql_dialect_datatype_unsupport,
 
666
                                                          isc_arg_number, (SLONG) request->req_client_dialect,
 
667
                                                          isc_arg_string,
 
668
                                                          DSC_dtype_tostring(parameter->par_desc.dsc_dtype),
 
669
                                                          0);
 
670
                                        break;
 
671
                                default:
 
672
                                        // No special action for other data types 
 
673
                                        break;
 
674
                        }
 
675
                const USHORT align = type_alignments[parameter->par_desc.dsc_dtype];
 
676
                if (align)
 
677
                        offset = FB_ALIGN(offset, align);
 
678
                parameter->par_desc.dsc_address = (UCHAR*)(IPTR) offset;
 
679
                offset += parameter->par_desc.dsc_length;
 
680
//              if (request->req_blr_string)
 
681
                        gen_descriptor(request, &parameter->par_desc, false);
 
682
        }
 
683
 
 
684
        if (offset > MAX_FORMAT_SIZE) {
 
685
                ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) -204,
 
686
                                  isc_arg_gds, isc_imp_exc,
 
687
                                  isc_arg_gds, isc_blktoobig,
 
688
                                  0);
 
689
        }
 
690
 
 
691
        message->msg_length = (USHORT) offset;
 
692
 
 
693
// Allocate buffer for message 
 
694
        const ULONG new_len = message->msg_length + DOUBLE_ALIGN - 1;
 
695
        dsql_str* buffer = FB_NEW_RPT(*tdsql->getDefaultPool(), new_len) dsql_str;
 
696
        message->msg_buffer =
 
697
                (UCHAR *) FB_ALIGN((U_IPTR) buffer->str_data, DOUBLE_ALIGN);
 
698
 
 
699
// Relocate parameter descriptors to point direction into message buffer 
 
700
 
 
701
        for (parameter = message->msg_parameters; parameter;
 
702
                 parameter = parameter->par_next)
 
703
        {
 
704
                parameter->par_desc.dsc_address = message->msg_buffer + 
 
705
                        (IPTR)parameter->par_desc.dsc_address;
 
706
        }
 
707
}
 
708
 
 
709
 
 
710
/**
 
711
  
 
712
        GEN_request
 
713
  
 
714
    @brief      Generate complete blr for a request.
 
715
                       
 
716
 
 
717
    @param request
 
718
    @param node
 
719
 
 
720
 **/
 
721
void GEN_request( dsql_req* request, dsql_nod* node)
 
722
{
 
723
        if (request->req_type == REQ_DDL) {
 
724
                DDL_generate(request, node);
 
725
                return;
 
726
        }
 
727
 
 
728
        if (request->req_flags & REQ_blr_version4)
 
729
                stuff(request, blr_version4);
 
730
        else
 
731
                stuff(request, blr_version5);
 
732
                
 
733
        if (request->req_type == REQ_SAVEPOINT) 
 
734
        {
 
735
                // Do not generate BEGIN..END block around savepoint statement
 
736
                // to avoid breaking of savepoint logic
 
737
                request->req_send = NULL;
 
738
                request->req_receive = NULL;
 
739
                GEN_statement(request, node);
 
740
        } 
 
741
        else 
 
742
        {       
 
743
                stuff(request, blr_begin);
 
744
 
 
745
                if (request->req_type == REQ_SELECT ||
 
746
                        request->req_type == REQ_SELECT_UPD ||
 
747
                        request->req_type == REQ_EMBED_SELECT)
 
748
                {
 
749
                        gen_select(request, node);
 
750
                }
 
751
                else if (request->req_type == REQ_EXEC_BLOCK ||
 
752
                                 request->req_type == REQ_SELECT_BLOCK )
 
753
                {
 
754
                        GEN_statement(request, node);
 
755
                }
 
756
                else {
 
757
                        dsql_msg* message = request->req_send;
 
758
                        if (!message->msg_parameter)
 
759
                                request->req_send = NULL;
 
760
                        else {
 
761
                                GEN_port(request, message);
 
762
                                stuff(request, blr_receive);
 
763
                                stuff(request, message->msg_number);
 
764
                        }
 
765
                        message = request->req_receive;
 
766
                        if (!message->msg_parameter)
 
767
                                request->req_receive = NULL;
 
768
                        else
 
769
                                GEN_port(request, message);
 
770
                        GEN_statement(request, node);
 
771
                }               
 
772
                stuff(request, blr_end);
 
773
        }
 
774
        
 
775
        stuff(request, blr_eoc);
 
776
}
 
777
 
 
778
 
 
779
/**
 
780
  
 
781
        GEN_start_transaction
 
782
  
 
783
    @brief      Generate tpb for set transaction.  Use blr string of request.
 
784
        If a value is not specified, default is not STUFF'ed, let the
 
785
        engine handle it.
 
786
        Do not allow an option to be specified more than once.
 
787
 
 
788
 
 
789
    @param request
 
790
    @param tran_node
 
791
 
 
792
 **/
 
793
void GEN_start_transaction( dsql_req* request, const dsql_nod* tran_node)
 
794
{
 
795
        SSHORT count = tran_node->nod_count;
 
796
 
 
797
        if (!count)
 
798
                return;
 
799
 
 
800
        const dsql_nod* node = tran_node->nod_arg[0];
 
801
 
 
802
        if (!node)
 
803
                return;
 
804
 
 
805
        // Find out isolation level - if specified. This is required for
 
806
        // specifying the correct lock level in reserving clause.
 
807
 
 
808
        USHORT lock_level = isc_tpb_shared;
 
809
 
 
810
        if (count = node->nod_count) {
 
811
                while (count--) {
 
812
                        const dsql_nod* ptr = node->nod_arg[count];
 
813
 
 
814
                        if ((!ptr) || (ptr->nod_type != nod_isolation))
 
815
                                continue;
 
816
 
 
817
                        lock_level = (ptr->nod_flags & NOD_CONSISTENCY) ?
 
818
                                isc_tpb_protected : isc_tpb_shared;
 
819
                }
 
820
        }
 
821
 
 
822
 
 
823
        bool sw_access = false, sw_wait = false, sw_isolation = false,
 
824
                sw_reserve = false, sw_lock_timeout = false;
 
825
        int misc_flags = 0;
 
826
 
 
827
// Stuff some version info.
 
828
        if (count = node->nod_count)
 
829
                stuff(request, isc_tpb_version1);
 
830
 
 
831
        while (count--)
 
832
        {
 
833
                const dsql_nod* ptr = node->nod_arg[count];
 
834
 
 
835
                if (!ptr)
 
836
                        continue;
 
837
 
 
838
                switch (ptr->nod_type) {
 
839
                case nod_access:
 
840
                        if (sw_access)
 
841
                                ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
 
842
                                                  isc_arg_gds, isc_dsql_dup_option, 0);
 
843
 
 
844
                        sw_access = true;
 
845
                        if (ptr->nod_flags & NOD_READ_ONLY)
 
846
                                stuff(request, isc_tpb_read);
 
847
                        else
 
848
                                stuff(request, isc_tpb_write);
 
849
                        break;
 
850
 
 
851
                case nod_wait:
 
852
                        if (sw_wait)
 
853
                                ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
 
854
                                                  isc_arg_gds, isc_dsql_dup_option, 0);
 
855
 
 
856
                        sw_wait = true;
 
857
                        if (ptr->nod_flags & NOD_NO_WAIT)
 
858
                                stuff(request, isc_tpb_nowait);
 
859
                        else
 
860
                                stuff(request, isc_tpb_wait);
 
861
                        break;
 
862
 
 
863
                case nod_isolation:
 
864
                        if (sw_isolation)
 
865
                                ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
 
866
                                                  isc_arg_gds, isc_dsql_dup_option, 0);
 
867
 
 
868
                        sw_isolation = true;
 
869
 
 
870
                        if (ptr->nod_flags & NOD_CONCURRENCY)
 
871
                                stuff(request, isc_tpb_concurrency);
 
872
                        else if (ptr->nod_flags & NOD_CONSISTENCY)
 
873
                                stuff(request, isc_tpb_consistency);
 
874
                        else {
 
875
                                stuff(request, isc_tpb_read_committed);
 
876
 
 
877
                                if ((ptr->nod_count) && (ptr->nod_arg[0]) &&
 
878
                                        (ptr->nod_arg[0]->nod_type == nod_version))
 
879
                                {
 
880
                                        if (ptr->nod_arg[0]->nod_flags & NOD_VERSION)
 
881
                                                stuff(request, isc_tpb_rec_version);
 
882
                                        else
 
883
                                                stuff(request, isc_tpb_no_rec_version);
 
884
                                }
 
885
                                else
 
886
                                        stuff(request, isc_tpb_no_rec_version);
 
887
                        }
 
888
 
 
889
                        break;
 
890
 
 
891
                case nod_reserve:
 
892
                        {
 
893
                                if (sw_reserve)
 
894
                                        ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
 
895
                                                          isc_arg_gds, isc_dsql_dup_option, 0);
 
896
 
 
897
                                sw_reserve = true;
 
898
                                const dsql_nod* reserve = ptr->nod_arg[0];
 
899
 
 
900
                                if (reserve) {
 
901
                                        const dsql_nod* const* temp = reserve->nod_arg;
 
902
                                        for (const dsql_nod* const* end = temp + reserve->nod_count;
 
903
                                                 temp < end; temp++)
 
904
                                        {
 
905
                                                gen_table_lock(request, *temp, lock_level);
 
906
                                        }
 
907
                                }
 
908
                                break;
 
909
                        }
 
910
                        
 
911
                case nod_tra_misc:
 
912
                        if (misc_flags & ptr->nod_flags)
 
913
                                ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
 
914
                                                  isc_arg_gds, isc_dsql_dup_option, 0);
 
915
                                                  
 
916
                        misc_flags |= ptr->nod_flags;
 
917
                        if (ptr->nod_flags & NOD_NO_AUTO_UNDO)
 
918
                                stuff(request, isc_tpb_no_auto_undo);
 
919
                        else if (ptr->nod_flags & NOD_IGNORE_LIMBO)
 
920
                                stuff(request, isc_tpb_ignore_limbo);
 
921
                        else if (ptr->nod_flags & NOD_RESTART_REQUESTS)
 
922
                                stuff(request, isc_tpb_restart_requests);
 
923
                        break;
 
924
                        
 
925
                case nod_lock_timeout:
 
926
                        if (sw_lock_timeout)
 
927
                                ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
 
928
                                                  isc_arg_gds, isc_dsql_dup_option, 0);
 
929
 
 
930
                        sw_lock_timeout = true;
 
931
                        if (ptr->nod_count == 1 && ptr->nod_arg[0]->nod_type == nod_constant)
 
932
                        {
 
933
                                const int lck_timeout = (int) ptr->nod_arg[0]->getSlong();
 
934
                                stuff(request, isc_tpb_lock_timeout);
 
935
                                stuff(request, 2);
 
936
                                stuff_word(request, lck_timeout);
 
937
                        }
 
938
                        break;
 
939
 
 
940
                default:
 
941
                        ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
 
942
                                          isc_arg_gds, isc_dsql_tran_err, 0);
 
943
                }
 
944
        }
 
945
}
 
946
 
 
947
 
 
948
/**
 
949
  
 
950
        GEN_statement
 
951
  
 
952
    @brief      Generate blr for an arbitrary expression.
 
953
 
 
954
 
 
955
    @param request
 
956
    @param node
 
957
 
 
958
 **/
 
959
void GEN_statement( dsql_req* request, dsql_nod* node)
 
960
{
 
961
        dsql_nod* temp;
 
962
        dsql_nod** ptr;
 
963
        const dsql_nod* const* end;
 
964
        dsql_str* string;
 
965
        ULONG id_length;
 
966
 
 
967
        switch (node->nod_type) {
 
968
        case nod_assign:
 
969
                stuff(request, blr_assignment);
 
970
                GEN_expr(request, node->nod_arg[0]);
 
971
                GEN_expr(request, node->nod_arg[1]);
 
972
                return;
 
973
 
 
974
        case nod_block:
 
975
                stuff(request, blr_block);
 
976
                GEN_statement(request, node->nod_arg[e_blk_action]);
 
977
                if (node->nod_count > 1) {
 
978
                        temp = node->nod_arg[e_blk_errs];
 
979
                        for (ptr = temp->nod_arg, end = ptr + temp->nod_count;
 
980
                                 ptr < end; ptr++)
 
981
                        {
 
982
                                GEN_statement(request, *ptr);
 
983
                        }
 
984
                }
 
985
                stuff(request, blr_end);
 
986
                return;
 
987
 
 
988
        case nod_exec_block:
 
989
                DDL_gen_block(request, node);
 
990
                return;
 
991
 
 
992
        case nod_for_select:
 
993
                gen_for_select(request, node);
 
994
                return;
 
995
 
 
996
        case nod_set_generator:
 
997
        case nod_set_generator2:
 
998
                stuff(request, blr_set_generator);
 
999
                string = (dsql_str*) node->nod_arg[e_gen_id_name];
 
1000
                stuff_cstring(request, string->str_data);
 
1001
                GEN_expr(request, node->nod_arg[e_gen_id_value]);
 
1002
                return;
 
1003
 
 
1004
        case nod_if:
 
1005
                stuff(request, blr_if);
 
1006
                GEN_expr(request, node->nod_arg[e_if_condition]);
 
1007
                GEN_statement(request, node->nod_arg[e_if_true]);
 
1008
                if (node->nod_arg[e_if_false])
 
1009
                        GEN_statement(request, node->nod_arg[e_if_false]);
 
1010
                else
 
1011
                        stuff(request, blr_end);
 
1012
                return;
 
1013
 
 
1014
        case nod_list:
 
1015
                stuff(request, blr_begin);
 
1016
                for (ptr = node->nod_arg, end = ptr + node->nod_count; ptr < end;
 
1017
                         ptr++)
 
1018
                {
 
1019
                        GEN_statement(request, *ptr);
 
1020
                }
 
1021
                stuff(request, blr_end);
 
1022
                return;
 
1023
 
 
1024
        case nod_erase:
 
1025
        case nod_erase_current:
 
1026
        case nod_modify:
 
1027
        case nod_modify_current:
 
1028
        case nod_store:
 
1029
        case nod_exec_procedure:
 
1030
                gen_statement(request, node);
 
1031
                return;
 
1032
 
 
1033
        case nod_on_error:
 
1034
                stuff(request, blr_error_handler);
 
1035
                temp = node->nod_arg[e_err_errs];
 
1036
                stuff_word(request, temp->nod_count);
 
1037
                for (ptr = temp->nod_arg, end = ptr + temp->nod_count; ptr < end;
 
1038
                         ptr++)
 
1039
                {
 
1040
                        gen_error_condition(request, *ptr);
 
1041
                }
 
1042
                GEN_statement(request, node->nod_arg[e_err_action]);
 
1043
                return;
 
1044
 
 
1045
        case nod_post:
 
1046
                if ( (temp = node->nod_arg[e_pst_argument]) ) {
 
1047
                        stuff(request, blr_post_arg);
 
1048
                        GEN_expr(request, node->nod_arg[e_pst_event]);
 
1049
                        GEN_expr(request, temp);
 
1050
                }
 
1051
                else {
 
1052
                        stuff(request, blr_post);
 
1053
                        GEN_expr(request, node->nod_arg[e_pst_event]);
 
1054
                }
 
1055
                return;
 
1056
 
 
1057
        case nod_exec_sql:
 
1058
                stuff(request, blr_exec_sql);
 
1059
                GEN_expr(request, node->nod_arg[e_exec_sql_stmnt]);
 
1060
                return;
 
1061
 
 
1062
        case nod_exec_into:
 
1063
                if (node->nod_arg[e_exec_into_block]) {
 
1064
                        stuff(request, blr_label);
 
1065
                        stuff(request, (int) (IPTR) node->nod_arg[e_exec_into_label]->nod_arg[e_label_number]);
 
1066
                }
 
1067
                stuff(request, blr_exec_into);
 
1068
                temp = node->nod_arg[e_exec_into_list];
 
1069
                stuff_word(request, temp->nod_count);
 
1070
                GEN_expr(request, node->nod_arg[e_exec_into_stmnt]);
 
1071
                if (node->nod_arg[e_exec_into_block]) {
 
1072
                        stuff(request, 0); // Non-singleton
 
1073
                        GEN_statement(request, node->nod_arg[e_exec_into_block]);
 
1074
                }
 
1075
                else
 
1076
                        stuff(request, 1); // Singleton
 
1077
                for (ptr = temp->nod_arg, end = ptr + temp->nod_count; 
 
1078
                                ptr < end; ptr++)
 
1079
                {
 
1080
                        GEN_expr(request, *ptr);
 
1081
                }
 
1082
                return;
 
1083
        
 
1084
        case nod_return:
 
1085
                if ( (temp = node->nod_arg[e_rtn_procedure]) )
 
1086
                {
 
1087
                        if (temp->nod_type == nod_exec_block)
 
1088
                                GEN_return(request, temp->nod_arg[e_exe_blk_outputs], false);
 
1089
                        else 
 
1090
                                GEN_return(request, temp->nod_arg[e_prc_outputs], false);
 
1091
                }
 
1092
                return;
 
1093
 
 
1094
        case nod_exit:
 
1095
                stuff(request, blr_leave);
 
1096
                stuff(request, 0);
 
1097
                return;
 
1098
 
 
1099
        case nod_breakleave:
 
1100
                stuff(request, blr_leave);
 
1101
                stuff(request, (int) (IPTR) node->nod_arg[e_breakleave_label]->nod_arg[e_label_number]);
 
1102
                return;
 
1103
 
 
1104
        case nod_abort:
 
1105
                stuff(request, blr_leave);
 
1106
                stuff(request, (int) (IPTR) node->nod_arg[e_abrt_number]);
 
1107
                return;
 
1108
 
 
1109
        case nod_start_savepoint:
 
1110
                stuff(request, blr_start_savepoint);
 
1111
                return;
 
1112
 
 
1113
        case nod_end_savepoint:
 
1114
                stuff(request, blr_end_savepoint);
 
1115
                return;
 
1116
 
 
1117
        case nod_user_savepoint:
 
1118
                stuff(request, blr_user_savepoint);
 
1119
                stuff(request, blr_savepoint_set);
 
1120
                stuff_cstring(request, ((dsql_str*)node->nod_arg[e_sav_name])->str_data);
 
1121
                return;
 
1122
 
 
1123
        case nod_release_savepoint:
 
1124
                stuff(request, blr_user_savepoint);
 
1125
                if (node->nod_arg[1]) {
 
1126
                        stuff(request, blr_savepoint_release_single);
 
1127
                }
 
1128
                else {
 
1129
                        stuff(request, blr_savepoint_release);
 
1130
                }
 
1131
                stuff_cstring(request, ((dsql_str*)node->nod_arg[e_sav_name])->str_data);
 
1132
                return;
 
1133
 
 
1134
        case nod_undo_savepoint:
 
1135
                stuff(request, blr_user_savepoint);
 
1136
                stuff(request, blr_savepoint_undo);
 
1137
                stuff_cstring(request, ((dsql_str*)node->nod_arg[e_sav_name])->str_data);
 
1138
                return;
 
1139
 
 
1140
        case nod_exception_stmt:
 
1141
                stuff(request, blr_abort);
 
1142
                string = (dsql_str*) node->nod_arg[e_xcps_name];
 
1143
                temp = node->nod_arg[e_xcps_msg];
 
1144
                /* if exception name is undefined,
 
1145
                   it means we have re-initiate semantics here,
 
1146
                   so blr_raise verb should be generated */
 
1147
                if (!string)
 
1148
                {
 
1149
                        stuff(request, blr_raise);
 
1150
                        return;
 
1151
                }
 
1152
                /* if exception value is defined,
 
1153
                   it means we have user-defined exception message here,
 
1154
                   so blr_exception_msg verb should be generated */
 
1155
                if (temp)
 
1156
                {
 
1157
                        stuff(request, blr_exception_msg);
 
1158
                }
 
1159
                /* otherwise go usual way,
 
1160
                   i.e. generate blr_exception */
 
1161
                else
 
1162
                {
 
1163
                        stuff(request, blr_exception);
 
1164
                }
 
1165
                if (!(string->str_flags & STR_delimited_id))
 
1166
                {
 
1167
                        id_length = string->str_length;
 
1168
                        for (TEXT* p = reinterpret_cast<char*>(string->str_data); *p;
 
1169
                                 id_length--)
 
1170
                        {
 
1171
                                *p = UPPER(*p);
 
1172
                                *p++;
 
1173
                        }
 
1174
                }
 
1175
                stuff_cstring(request, string->str_data);
 
1176
                /* if exception value is defined,
 
1177
                   generate appropriate BLR verbs */
 
1178
                if (temp)
 
1179
                {
 
1180
                        GEN_expr(request, temp);
 
1181
                }
 
1182
                return;
 
1183
 
 
1184
        case nod_while:
 
1185
                stuff(request, blr_label);
 
1186
                stuff(request, (int) (IPTR) node->nod_arg[e_while_label]->nod_arg[e_label_number]);
 
1187
                stuff(request, blr_loop);
 
1188
                stuff(request, blr_begin);
 
1189
                stuff(request, blr_if);
 
1190
                GEN_expr(request, node->nod_arg[e_while_cond]);
 
1191
                GEN_statement(request, node->nod_arg[e_while_action]);
 
1192
                stuff(request, blr_leave);
 
1193
                stuff(request, (int) (IPTR) node->nod_arg[e_while_label]->nod_arg[e_label_number]);
 
1194
                stuff(request, blr_end);
 
1195
                return;
 
1196
 
 
1197
        case nod_sqlcode:
 
1198
        case nod_gdscode:
 
1199
                stuff(request, blr_abort);
 
1200
                gen_error_condition(request, node);
 
1201
                return;
 
1202
 
 
1203
        case nod_cursor:
 
1204
                stuff(request, blr_dcl_cursor);
 
1205
                stuff_word(request, (int) (IPTR) node->nod_arg[e_cur_number]);
 
1206
                GEN_expr(request, node->nod_arg[e_cur_rse]);
 
1207
                temp = node->nod_arg[e_cur_rse]->nod_arg[e_rse_items];
 
1208
                stuff_word(request, temp->nod_count);
 
1209
                ptr = temp->nod_arg;
 
1210
                end = ptr + temp->nod_count;
 
1211
                while (ptr < end) {
 
1212
                        GEN_expr(request, *ptr++);
 
1213
                }
 
1214
                return;
 
1215
 
 
1216
        case nod_cursor_open:
 
1217
        case nod_cursor_close:
 
1218
        case nod_cursor_fetch:
 
1219
                {
 
1220
                // op-code
 
1221
                stuff(request, blr_cursor_stmt);
 
1222
                if (node->nod_type == nod_cursor_open)
 
1223
                        stuff(request, blr_cursor_open);
 
1224
                else if (node->nod_type == nod_cursor_close)
 
1225
                        stuff(request, blr_cursor_close);
 
1226
                else
 
1227
                        stuff(request, blr_cursor_fetch);
 
1228
                // cursor reference
 
1229
                dsql_nod* cursor = node->nod_arg[e_cur_stmt_id];
 
1230
                stuff_word(request, (int) (IPTR) cursor->nod_arg[e_cur_number]);
 
1231
                // preliminary navigation
 
1232
                dsql_nod* seek = node->nod_arg[e_cur_stmt_seek];
 
1233
                if (seek) {
 
1234
                        stuff(request, blr_seek);
 
1235
                        GEN_expr(request, seek->nod_arg[0]);
 
1236
                        GEN_expr(request, seek->nod_arg[1]);
 
1237
                }
 
1238
                // assignment
 
1239
                dsql_nod* list_into = node->nod_arg[e_cur_stmt_into];
 
1240
                if (list_into) {
 
1241
                        dsql_nod* list = cursor->nod_arg[e_cur_rse]->nod_arg[e_rse_items];
 
1242
                        if (list->nod_count != list_into->nod_count)
 
1243
                                ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 313,
 
1244
                                                  isc_arg_gds, isc_dsql_count_mismatch, 0);
 
1245
                        stuff(request, blr_begin);
 
1246
                        ptr = list->nod_arg;
 
1247
                        end = ptr + list->nod_count;
 
1248
                        dsql_nod** ptr_to = list_into->nod_arg;
 
1249
                        while (ptr < end) {
 
1250
                                stuff(request, blr_assignment);
 
1251
                                GEN_expr(request, *ptr++);
 
1252
                                GEN_expr(request, *ptr_to++);
 
1253
                        }
 
1254
                        stuff(request, blr_end);
 
1255
                }
 
1256
                }
 
1257
                return;
 
1258
 
 
1259
        case nod_src_info:
 
1260
                request->put_debug_src_info(node->nod_line, node->nod_column);
 
1261
                GEN_statement(request, node->nod_arg[e_src_info_stmt]);
 
1262
                return;
 
1263
 
 
1264
        default:
 
1265
                ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 901,
 
1266
                                  isc_arg_gds, isc_dsql_internal_err,
 
1267
                                  isc_arg_gds, isc_node_err, // gen.c: node not supported
 
1268
                                  0);
 
1269
        }
 
1270
}
 
1271
 
 
1272
 
 
1273
/**
 
1274
  
 
1275
        gen_aggregate
 
1276
  
 
1277
    @brief      Generate blr for a relation reference.
 
1278
 
 
1279
 
 
1280
    @param 
 
1281
    @param 
 
1282
 
 
1283
 **/
 
1284
static void gen_aggregate( dsql_req* request, const dsql_nod* node)
 
1285
{
 
1286
        const dsql_ctx* context = (dsql_ctx*) node->nod_arg[e_agg_context];
 
1287
        stuff(request, blr_aggregate);
 
1288
        stuff_context(request, context);
 
1289
        gen_rse(request, node->nod_arg[e_agg_rse]);
 
1290
 
 
1291
// Handle GROUP BY clause 
 
1292
 
 
1293
        stuff(request, blr_group_by);
 
1294
 
 
1295
        dsql_nod* list = node->nod_arg[e_agg_group];
 
1296
        if (list != NULL) {
 
1297
                stuff(request, list->nod_count);
 
1298
                dsql_nod** ptr = list->nod_arg;
 
1299
                for (const dsql_nod* const* end = ptr + list->nod_count; ptr < end;
 
1300
                         ptr++)
 
1301
                {
 
1302
                        GEN_expr(request, *ptr);
 
1303
                }
 
1304
        }
 
1305
        else
 
1306
                stuff(request, 0);
 
1307
 
 
1308
// Generate value map 
 
1309
 
 
1310
        gen_map(request, context->ctx_map);
 
1311
}
 
1312
 
 
1313
 
 
1314
/**
 
1315
  
 
1316
 gen_cast
 
1317
  
 
1318
    @brief      Generate BLR for a data-type cast operation
 
1319
 
 
1320
 
 
1321
    @param request
 
1322
    @param node
 
1323
 
 
1324
 **/
 
1325
static void gen_cast( dsql_req* request, const dsql_nod* node)
 
1326
{
 
1327
        stuff(request, blr_cast);
 
1328
        const dsql_fld* field = (dsql_fld*) node->nod_arg[e_cast_target];
 
1329
        DDL_put_field_dtype(request, field, true);
 
1330
        GEN_expr(request, node->nod_arg[e_cast_source]);
 
1331
}
 
1332
 
 
1333
 
 
1334
/**
 
1335
  
 
1336
 gen_coalesce
 
1337
  
 
1338
    @brief      Generate BLR for coalesce function
 
1339
 
 
1340
        Generate the blr values, begin with a cast and then :
 
1341
 
 
1342
        blr_value_if
 
1343
        blr_missing
 
1344
        blr for expression 1
 
1345
                blr_value_if
 
1346
                blr_missing
 
1347
                blr for expression n-1
 
1348
                expression n
 
1349
        blr for expression n-1
 
1350
 
 
1351
    @param request
 
1352
    @param node
 
1353
 
 
1354
 **/
 
1355
static void gen_coalesce( dsql_req* request, const dsql_nod* node)
 
1356
{
 
1357
        // blr_value_if is used for building the coalesce function
 
1358
        dsql_nod* list = node->nod_arg[0];
 
1359
        stuff(request, blr_cast);
 
1360
        gen_descriptor(request, &node->nod_desc, true);
 
1361
        dsql_nod* const* ptr = list->nod_arg;
 
1362
        for (const dsql_nod* const* const end = ptr + (list->nod_count - 1);
 
1363
                ptr < end; ptr++)
 
1364
        {
 
1365
                // IF (expression IS NULL) THEN
 
1366
                stuff(request, blr_value_if);
 
1367
                stuff(request, blr_missing);
 
1368
                GEN_expr(request, *ptr);
 
1369
        }
 
1370
        // Return values
 
1371
        list = node->nod_arg[1];
 
1372
        const dsql_nod* const* const begin = list->nod_arg;
 
1373
        ptr = list->nod_arg + list->nod_count;
 
1374
        // if all expressions are NULL return NULL
 
1375
        for (ptr--; ptr >= begin; ptr--)
 
1376
        {
 
1377
                GEN_expr(request, *ptr);
 
1378
        }
 
1379
}
 
1380
 
 
1381
 
 
1382
/**
 
1383
  
 
1384
        gen_constant
 
1385
  
 
1386
    @brief      Generate BLR for a constant.
 
1387
 
 
1388
 
 
1389
    @param request
 
1390
    @param desc
 
1391
    @param negate_value
 
1392
 
 
1393
 **/
 
1394
static void gen_constant( dsql_req* request, const dsc* desc, bool negate_value)
 
1395
{
 
1396
        SLONG value;
 
1397
        SINT64 i64value;
 
1398
 
 
1399
        DSC tmp_desc;
 
1400
 
 
1401
        stuff(request, blr_literal);
 
1402
 
 
1403
        USHORT l = 0; //= desc->dsc_length;
 
1404
        const UCHAR* p = desc->dsc_address;
 
1405
 
 
1406
        switch (desc->dsc_dtype) {
 
1407
        case dtype_short:
 
1408
                gen_descriptor(request, desc, true);
 
1409
                value = *(SSHORT *) p;
 
1410
                if (negate_value)
 
1411
                        value = -value;
 
1412
                stuff_word(request, value);
 
1413
                break;
 
1414
 
 
1415
        case dtype_long:
 
1416
                gen_descriptor(request, desc, true);
 
1417
                value = *(SLONG *) p;
 
1418
                if (negate_value)
 
1419
                        value = -value;
 
1420
                //printf("gen.cpp = %p %d\n", *((void**)p), value);
 
1421
                stuff_word(request, value);
 
1422
                stuff_word(request, value >> 16);
 
1423
                break;
 
1424
 
 
1425
        case dtype_sql_time:
 
1426
        case dtype_sql_date:
 
1427
                gen_descriptor(request, desc, true);
 
1428
                value = *(SLONG *) p;
 
1429
                stuff_word(request, value);
 
1430
                stuff_word(request, value >> 16);
 
1431
                break;
 
1432
 
 
1433
        case dtype_double:
 
1434
                /* this is used for approximate/large numeric literal
 
1435
                   which is transmitted to the engine as a string.
 
1436
                 */
 
1437
                gen_descriptor(request, desc, true);
 
1438
                // Length of string literal, cast because it could be > 127 bytes.
 
1439
                l = (USHORT) (UCHAR) desc->dsc_scale;
 
1440
                if (negate_value) {
 
1441
                        stuff_word(request, l + 1);
 
1442
                        stuff(request, '-');
 
1443
                }
 
1444
                else {
 
1445
                        stuff_word(request, l);
 
1446
                }
 
1447
 
 
1448
                if (l)
 
1449
                        do {
 
1450
                                stuff(request, *p++);
 
1451
                        } while (--l);
 
1452
                break;
 
1453
 
 
1454
        case dtype_int64:
 
1455
                i64value = *(SINT64 *) p;
 
1456
 
 
1457
                if (negate_value)
 
1458
                        i64value = -i64value;
 
1459
                else if (i64value == MIN_SINT64) {
 
1460
                        /* UH OH!
 
1461
                         * yylex correctly recognized the digits as the most-negative
 
1462
                         * possible INT64 value, but unfortunately, there was no
 
1463
                         * preceding '-' (a fact which the lexer could not know).
 
1464
                         * The value is too big for a positive INT64 value, and it
 
1465
                         * didn't contain an exponent so it's not a valid DOUBLE
 
1466
                         * PRECISION literal either, so we have to bounce it.
 
1467
                         */
 
1468
                        ERRD_post(isc_sqlerr,
 
1469
                                          isc_arg_number, (SLONG) - 104,
 
1470
                                          isc_arg_gds, isc_arith_except, 0);
 
1471
                }
 
1472
 
 
1473
                /* We and the lexer both agree that this is an SINT64 constant,
 
1474
                   * and if the value needed to be negated, it already has been.
 
1475
                   * If the value will fit into a 32-bit signed integer, generate
 
1476
                   * it that way, else as an INT64.
 
1477
                 */
 
1478
 
 
1479
                if ((i64value >= (SINT64) MIN_SLONG) &&
 
1480
                        (i64value <= (SINT64) MAX_SLONG))
 
1481
                {
 
1482
                        stuff(request, blr_long);
 
1483
                        stuff(request, desc->dsc_scale);
 
1484
                        stuff_word(request, i64value);
 
1485
                        stuff_word(request, i64value >> 16);
 
1486
                        break;
 
1487
                }
 
1488
                else {
 
1489
                        stuff(request, blr_int64);
 
1490
                        stuff(request, desc->dsc_scale);
 
1491
                        stuff_word(request, i64value);
 
1492
                        stuff_word(request, i64value >> 16);
 
1493
                        stuff_word(request, i64value >> 32);
 
1494
                        stuff_word(request, i64value >> 48);
 
1495
                }
 
1496
                break;
 
1497
 
 
1498
        case dtype_quad:
 
1499
        case dtype_blob:
 
1500
        case dtype_array:
 
1501
        case dtype_timestamp:
 
1502
                gen_descriptor(request, desc, true);
 
1503
                value = *(SLONG *) p;
 
1504
                stuff_word(request, value);
 
1505
                stuff_word(request, value >> 16);
 
1506
                value = *(SLONG *) (p + 4);
 
1507
                stuff_word(request, value);
 
1508
                stuff_word(request, value >> 16);
 
1509
                break;
 
1510
 
 
1511
        case dtype_text:
 
1512
                {
 
1513
                        USHORT length = desc->dsc_length;
 
1514
 
 
1515
                        gen_descriptor(request, desc, true);
 
1516
                        if (length)
 
1517
                                do {
 
1518
                                        stuff(request, *p++);
 
1519
                                } while (--length);
 
1520
                        break;
 
1521
                }
 
1522
 
 
1523
        default:
 
1524
                // gen_constant: datatype not understood 
 
1525
                ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 103,
 
1526
                                  isc_arg_gds, isc_dsql_constant_err, 0);
 
1527
        }
 
1528
}
 
1529
 
 
1530
 
 
1531
/**
 
1532
  
 
1533
        gen_constant
 
1534
  
 
1535
    @brief      Generate BLR for a constant.
 
1536
 
 
1537
 
 
1538
    @param request
 
1539
    @param node
 
1540
    @param negate_value
 
1541
 
 
1542
 **/
 
1543
static void gen_constant( dsql_req* request, dsql_nod* node, bool negate_value)
 
1544
{
 
1545
        if (node->nod_desc.dsc_dtype == dtype_text)
 
1546
                node->nod_desc.dsc_length = ((dsql_str*) node->nod_arg[0])->str_length;
 
1547
 
 
1548
        gen_constant(request, &node->nod_desc, negate_value);
 
1549
}
 
1550
 
 
1551
 
 
1552
/**
 
1553
  
 
1554
        gen_descriptor
 
1555
  
 
1556
    @brief      Generate a blr descriptor from an internal descriptor.
 
1557
 
 
1558
 
 
1559
    @param request
 
1560
    @param desc
 
1561
    @param texttype
 
1562
 
 
1563
 **/
 
1564
static void gen_descriptor( dsql_req* request, const dsc* desc, bool texttype)
 
1565
{
 
1566
        switch (desc->dsc_dtype) {
 
1567
        case dtype_text:
 
1568
                if (texttype || desc->dsc_ttype() == ttype_binary || desc->dsc_ttype() == ttype_none) {
 
1569
                        stuff(request, blr_text2);
 
1570
                        stuff_word(request, desc->dsc_ttype());
 
1571
                }
 
1572
                else {
 
1573
                        stuff(request, blr_text2);      // automatic transliteration 
 
1574
                        stuff_word(request, ttype_dynamic);
 
1575
                }
 
1576
 
 
1577
                stuff_word(request, desc->dsc_length);
 
1578
                break;
 
1579
 
 
1580
        case dtype_varying:
 
1581
                if (texttype || desc->dsc_ttype() == ttype_binary || desc->dsc_ttype() == ttype_none) {
 
1582
                        stuff(request, blr_varying2);
 
1583
                        stuff_word(request, desc->dsc_ttype());
 
1584
                }
 
1585
                else {
 
1586
                        stuff(request, blr_varying2);   // automatic transliteration 
 
1587
                        stuff_word(request, ttype_dynamic);
 
1588
                }
 
1589
                stuff_word(request, desc->dsc_length - sizeof(USHORT));
 
1590
                break;
 
1591
 
 
1592
        case dtype_short:
 
1593
                stuff(request, blr_short);
 
1594
                stuff(request, desc->dsc_scale);
 
1595
                break;
 
1596
 
 
1597
        case dtype_long:
 
1598
                stuff(request, blr_long);
 
1599
                stuff(request, desc->dsc_scale);
 
1600
                break;
 
1601
 
 
1602
        case dtype_quad:
 
1603
                stuff(request, blr_quad);
 
1604
                stuff(request, desc->dsc_scale);
 
1605
                break;
 
1606
 
 
1607
        case dtype_int64:
 
1608
                stuff(request, blr_int64);
 
1609
                stuff(request, desc->dsc_scale);
 
1610
                break;
 
1611
 
 
1612
        case dtype_real:
 
1613
                stuff(request, blr_float);
 
1614
                break;
 
1615
 
 
1616
        case dtype_double:
 
1617
                stuff(request, blr_double);
 
1618
                break;
 
1619
 
 
1620
        case dtype_sql_date:
 
1621
                stuff(request, blr_sql_date);
 
1622
                break;
 
1623
 
 
1624
        case dtype_sql_time:
 
1625
                stuff(request, blr_sql_time);
 
1626
                break;
 
1627
 
 
1628
        case dtype_timestamp:
 
1629
                stuff(request, blr_timestamp);
 
1630
                break;
 
1631
 
 
1632
        case dtype_array:
 
1633
                stuff(request, blr_quad);
 
1634
                stuff(request, 0);
 
1635
                break;
 
1636
 
 
1637
        case dtype_blob:
 
1638
                stuff(request, blr_blob2);
 
1639
                stuff_word(request, desc->dsc_sub_type);
 
1640
                stuff_word(request, desc->getTextType());
 
1641
                break;
 
1642
 
 
1643
        default:
 
1644
                // don't understand dtype 
 
1645
                ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 804,
 
1646
                                  isc_arg_gds, isc_dsql_datatype_err, 0);
 
1647
        }
 
1648
}
 
1649
 
 
1650
 
 
1651
/**
 
1652
  
 
1653
        gen_error_condition
 
1654
  
 
1655
    @brief      Generate blr for an error condtion
 
1656
 
 
1657
 
 
1658
    @param request
 
1659
    @param node
 
1660
 
 
1661
 **/
 
1662
static void gen_error_condition( dsql_req* request, const dsql_nod* node)
 
1663
{
 
1664
        const dsql_str* string;
 
1665
 
 
1666
        switch (node->nod_type) {
 
1667
        case nod_sqlcode:
 
1668
                stuff(request, blr_sql_code);
 
1669
                stuff_word(request, (USHORT)(IPTR) node->nod_arg[0]);
 
1670
                return;
 
1671
 
 
1672
        case nod_gdscode:
 
1673
                stuff(request, blr_gds_code);
 
1674
                string = (dsql_str*) node->nod_arg[0];
 
1675
                stuff_cstring(request, string->str_data);
 
1676
                return;
 
1677
 
 
1678
        case nod_exception:
 
1679
                stuff(request, blr_exception);
 
1680
                string = (dsql_str*) node->nod_arg[0];
 
1681
                stuff_cstring(request, string->str_data);
 
1682
                return;
 
1683
 
 
1684
        case nod_default:
 
1685
                stuff(request, blr_default_code);
 
1686
                return;
 
1687
 
 
1688
        default:
 
1689
                fb_assert(false);
 
1690
                return;
 
1691
        }
 
1692
}
 
1693
 
 
1694
 
 
1695
/**
 
1696
  
 
1697
        gen_field
 
1698
  
 
1699
    @brief      Generate blr for a field - field id's
 
1700
        are preferred but not for trigger or view blr.
 
1701
 
 
1702
 
 
1703
    @param request
 
1704
    @param context
 
1705
    @param field
 
1706
    @param indices
 
1707
 
 
1708
 **/
 
1709
static void gen_field( dsql_req* request, const dsql_ctx* context,
 
1710
        const dsql_fld* field, dsql_nod* indices)
 
1711
{
 
1712
/* For older clients - generate an error should they try and
 
1713
 *    access data types which did not exist in the older dialect */
 
1714
        if (request->req_client_dialect <= SQL_DIALECT_V5) {
 
1715
                switch (field->fld_dtype) {
 
1716
                case dtype_sql_date:
 
1717
                case dtype_sql_time:
 
1718
                case dtype_int64:
 
1719
                        ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 804,
 
1720
                                          isc_arg_gds, isc_dsql_datatype_err,
 
1721
                                          isc_arg_gds, isc_sql_dialect_datatype_unsupport,
 
1722
                                          isc_arg_number, (SLONG) request->req_client_dialect,
 
1723
                                          isc_arg_string,
 
1724
                                          DSC_dtype_tostring(static_cast < UCHAR >
 
1725
                                                                                 (field->fld_dtype)), 0);
 
1726
                        break;
 
1727
                default:
 
1728
                        // No special action for other data types 
 
1729
                        break;
 
1730
                }
 
1731
        }
 
1732
 
 
1733
        if (indices)
 
1734
                stuff(request, blr_index);
 
1735
 
 
1736
        if (DDL_ids(request)) {
 
1737
                stuff(request, blr_fid);
 
1738
                stuff_context(request, context);
 
1739
                stuff_word(request, field->fld_id);
 
1740
        }
 
1741
        else {
 
1742
                stuff(request, blr_field);
 
1743
                stuff_context(request, context);
 
1744
                stuff_cstring(request, field->fld_name);
 
1745
        }
 
1746
 
 
1747
        if (indices) {
 
1748
                stuff(request, indices->nod_count);
 
1749
                dsql_nod** ptr = indices->nod_arg;
 
1750
                for (const dsql_nod* const* end = ptr + indices->nod_count;
 
1751
                         ptr < end; ptr++)
 
1752
                {
 
1753
                        GEN_expr(request, *ptr);
 
1754
                }
 
1755
        }
 
1756
}
 
1757
 
 
1758
 
 
1759
/**
 
1760
  
 
1761
        gen_for_select
 
1762
  
 
1763
    @brief      Generate BLR for a SELECT statement.
 
1764
 
 
1765
 
 
1766
    @param request
 
1767
    @param for_select
 
1768
 
 
1769
 **/
 
1770
static void gen_for_select( dsql_req* request, const dsql_nod* for_select)
 
1771
{
 
1772
        dsql_nod* rse = for_select->nod_arg[e_flp_select];
 
1773
 
 
1774
        // CVC: Only put a label if this is not singular; otherwise,
 
1775
        // what loop is the user trying to abandon?
 
1776
        if (for_select->nod_arg[e_flp_action]) {
 
1777
                stuff(request, blr_label);
 
1778
                stuff(request, (int) (IPTR) for_select->nod_arg[e_flp_label]->nod_arg[e_label_number]);
 
1779
        }
 
1780
 
 
1781
// Generate FOR loop 
 
1782
 
 
1783
        stuff(request, blr_for);
 
1784
 
 
1785
        if (!for_select->nod_arg[e_flp_action])
 
1786
        {
 
1787
                stuff(request, blr_singular);
 
1788
        }
 
1789
        gen_rse(request, rse);
 
1790
        stuff(request, blr_begin);
 
1791
 
 
1792
// Build body of FOR loop 
 
1793
 
 
1794
        // Handle write locks 
 
1795
        dsql_nod* streams = rse->nod_arg[e_rse_streams];
 
1796
        dsql_ctx* context = NULL;
 
1797
 
 
1798
        if (!rse->nod_arg[e_rse_reduced] && streams->nod_count == 1) {
 
1799
                dsql_nod* item = streams->nod_arg[0];
 
1800
                if (item && (item->nod_type == nod_relation))
 
1801
                        context = (dsql_ctx*) item->nod_arg[e_rel_context];
 
1802
        }
 
1803
        
 
1804
        dsql_nod* list = rse->nod_arg[e_rse_items];
 
1805
        dsql_nod* list_to = for_select->nod_arg[e_flp_into];
 
1806
 
 
1807
        if (list_to)
 
1808
        {
 
1809
                if (list->nod_count != list_to->nod_count)
 
1810
                        ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 313,
 
1811
                                        isc_arg_gds, isc_dsql_count_mismatch, 0);
 
1812
                dsql_nod** ptr = list->nod_arg;
 
1813
                dsql_nod** ptr_to = list_to->nod_arg;
 
1814
                for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end;
 
1815
                        ptr++, ptr_to++) 
 
1816
                {
 
1817
                        stuff(request, blr_assignment);
 
1818
                        GEN_expr(request, *ptr);
 
1819
                        GEN_expr(request, *ptr_to);
 
1820
                }
 
1821
        }
 
1822
 
 
1823
        if (for_select->nod_arg[e_flp_action])
 
1824
                GEN_statement(request, for_select->nod_arg[e_flp_action]);
 
1825
        stuff(request, blr_end);
 
1826
}
 
1827
 
 
1828
 
 
1829
/**
 
1830
  
 
1831
 gen_gen_id
 
1832
  
 
1833
    @brief      Generate BLR for gen_id
 
1834
 
 
1835
 
 
1836
    @param request
 
1837
    @param node
 
1838
 
 
1839
 **/
 
1840
static void gen_gen_id( dsql_req* request, const dsql_nod* node)
 
1841
{
 
1842
        stuff(request, blr_gen_id);
 
1843
        const dsql_str* string = (dsql_str*) node->nod_arg[e_gen_id_name];
 
1844
        stuff_cstring(request, string->str_data);
 
1845
        GEN_expr(request, node->nod_arg[e_gen_id_value]);
 
1846
}
 
1847
 
 
1848
 
 
1849
/**
 
1850
  
 
1851
        gen_join_rse
 
1852
  
 
1853
    @brief      Generate a record selection expression
 
1854
        with an explicit join type.
 
1855
 
 
1856
 
 
1857
    @param request
 
1858
    @param rse
 
1859
 
 
1860
 **/
 
1861
static void gen_join_rse( dsql_req* request, const dsql_nod* rse)
 
1862
{
 
1863
        stuff(request, blr_rs_stream);
 
1864
        stuff(request, 2);
 
1865
 
 
1866
        GEN_expr(request, rse->nod_arg[e_join_left_rel]);
 
1867
        GEN_expr(request, rse->nod_arg[e_join_rght_rel]);
 
1868
 
 
1869
        const dsql_nod* node = rse->nod_arg[e_join_type];
 
1870
        if (node->nod_type != nod_join_inner) {
 
1871
                stuff(request, blr_join_type);
 
1872
                if (node->nod_type == nod_join_left)
 
1873
                        stuff(request, blr_left);
 
1874
                else if (node->nod_type == nod_join_right)
 
1875
                        stuff(request, blr_right);
 
1876
                else
 
1877
                        stuff(request, blr_full);
 
1878
        }
 
1879
 
 
1880
        if (rse->nod_arg[e_join_boolean])
 
1881
        {
 
1882
                stuff(request, blr_boolean);
 
1883
                GEN_expr(request, rse->nod_arg[e_join_boolean]);
 
1884
        }
 
1885
 
 
1886
        stuff(request, blr_end);
 
1887
}
 
1888
 
 
1889
 
 
1890
/**
 
1891
  
 
1892
        gen_map
 
1893
  
 
1894
    @brief      Generate a value map for a record selection expression.
 
1895
 
 
1896
 
 
1897
    @param request
 
1898
    @param map
 
1899
 
 
1900
 **/
 
1901
static void gen_map( dsql_req* request, dsql_map* map)
 
1902
{
 
1903
        USHORT count = 0;
 
1904
        dsql_map* temp;
 
1905
        for (temp = map; temp; temp = temp->map_next)
 
1906
                temp->map_position = count++;
 
1907
 
 
1908
        stuff(request, blr_map);
 
1909
        stuff_word(request, count);
 
1910
 
 
1911
        for (temp = map; temp; temp = temp->map_next) {
 
1912
                stuff_word(request, temp->map_position);
 
1913
                GEN_expr(request, temp->map_node);
 
1914
        }
 
1915
}
 
1916
 
 
1917
 
 
1918
/**
 
1919
  
 
1920
        gen_parameter
 
1921
  
 
1922
    @brief      Generate a parameter reference.
 
1923
 
 
1924
 
 
1925
    @param request
 
1926
    @param parameter
 
1927
 
 
1928
 **/
 
1929
static void gen_parameter( dsql_req* request, const dsql_par* parameter)
 
1930
{
 
1931
        const dsql_msg* message = parameter->par_message;
 
1932
 
 
1933
        const dsql_par* null = parameter->par_null;
 
1934
        if (null != NULL) {
 
1935
                stuff(request, blr_parameter2);
 
1936
                stuff(request, message->msg_number);
 
1937
                stuff_word(request, parameter->par_parameter);
 
1938
                stuff_word(request, null->par_parameter);
 
1939
                return;
 
1940
        }
 
1941
 
 
1942
        stuff(request, blr_parameter);
 
1943
        stuff(request, message->msg_number);
 
1944
        stuff_word(request, parameter->par_parameter);
 
1945
}
 
1946
 
 
1947
 
 
1948
 
 
1949
/**
 
1950
  
 
1951
        gen_plan
 
1952
  
 
1953
    @brief      Generate blr for an access plan expression.
 
1954
 
 
1955
 
 
1956
    @param request
 
1957
    @param plan_expression
 
1958
 
 
1959
 **/
 
1960
static void gen_plan( dsql_req* request, const dsql_nod* plan_expression)
 
1961
{
 
1962
// stuff the join type 
 
1963
 
 
1964
        const dsql_nod* list = plan_expression->nod_arg[1];
 
1965
        if (list->nod_count > 1) {
 
1966
                if (plan_expression->nod_arg[0])
 
1967
                        stuff(request, blr_merge);
 
1968
                else
 
1969
                        stuff(request, blr_join);
 
1970
                stuff(request, list->nod_count);
 
1971
        }
 
1972
 
 
1973
// stuff one or more plan items 
 
1974
 
 
1975
        const dsql_nod* const* ptr = list->nod_arg;
 
1976
        for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end; 
 
1977
                ptr++) 
 
1978
        {
 
1979
                const dsql_nod* node = *ptr;
 
1980
                if (node->nod_type == nod_plan_expr) {
 
1981
                        gen_plan(request, node);
 
1982
                        continue;
 
1983
                }
 
1984
 
 
1985
                // if we're here, it must be a nod_plan_item 
 
1986
 
 
1987
                stuff(request, blr_retrieve);
 
1988
 
 
1989
                /* stuff the relation--the relation id itself is redundant except 
 
1990
                   when there is a need to differentiate the base tables of views */
 
1991
 
 
1992
                const dsql_nod* arg = node->nod_arg[0];
 
1993
                gen_relation(request, (dsql_ctx*) arg->nod_arg[e_rel_context]);
 
1994
 
 
1995
                // now stuff the access method for this stream 
 
1996
                const dsql_str* index_string;
 
1997
 
 
1998
                arg = node->nod_arg[1];
 
1999
                switch (arg->nod_type) {
 
2000
                case nod_natural:
 
2001
                        stuff(request, blr_sequential);
 
2002
                        break;
 
2003
 
 
2004
                case nod_index_order:
 
2005
                        stuff(request, blr_navigational);
 
2006
                        index_string = (dsql_str*) arg->nod_arg[0];
 
2007
                        stuff_cstring(request, index_string->str_data);
 
2008
                        if (!arg->nod_arg[1])
 
2009
                                break;
 
2010
                        // dimitr: FALL INTO, if the plan item is ORDER ... INDEX (...)
 
2011
 
 
2012
                case nod_index:
 
2013
                        {
 
2014
                                stuff(request, blr_indices);
 
2015
                                arg = (arg->nod_type == nod_index) ?
 
2016
                                        arg->nod_arg[0] : arg->nod_arg[1];
 
2017
                                stuff(request, arg->nod_count);
 
2018
                                const dsql_nod* const* ptr2 = arg->nod_arg;
 
2019
                                for (const dsql_nod* const* const end2 = ptr2 + arg->nod_count;
 
2020
                                         ptr2 < end2; ptr2++) 
 
2021
                                {
 
2022
                                        index_string = (dsql_str*) * ptr2;
 
2023
                                        stuff_cstring(request, index_string->str_data);
 
2024
                                }
 
2025
                                break;
 
2026
                        }
 
2027
 
 
2028
                default:
 
2029
                        fb_assert(false);
 
2030
                        break;
 
2031
                }
 
2032
 
 
2033
        }
 
2034
}
 
2035
 
 
2036
 
 
2037
 
 
2038
/**
 
2039
  
 
2040
        gen_relation
 
2041
  
 
2042
    @brief      Generate blr for a relation reference.
 
2043
 
 
2044
 
 
2045
    @param request
 
2046
    @param context
 
2047
 
 
2048
 **/
 
2049
static void gen_relation( dsql_req* request, dsql_ctx* context)
 
2050
{
 
2051
        const dsql_rel* relation = context->ctx_relation;
 
2052
        const dsql_prc* procedure = context->ctx_procedure;
 
2053
 
 
2054
        // if this is a trigger or procedure, don't want relation id used 
 
2055
        if (relation) {
 
2056
                if (DDL_ids(request)) {
 
2057
                        if (context->ctx_alias)
 
2058
                                stuff(request, blr_rid2);
 
2059
                        else
 
2060
                                stuff(request, blr_rid);
 
2061
                        stuff_word(request, relation->rel_id);
 
2062
                }
 
2063
                else {
 
2064
                        if (context->ctx_alias)
 
2065
                                stuff(request, blr_relation2);
 
2066
                        else
 
2067
                                stuff(request, blr_relation);
 
2068
                        stuff_meta_string(request, relation->rel_name);
 
2069
                }
 
2070
 
 
2071
                if (context->ctx_alias)
 
2072
                        stuff_meta_string(request, context->ctx_alias);
 
2073
 
 
2074
                stuff_context(request, context);
 
2075
        }
 
2076
        else if (procedure) {
 
2077
                if (DDL_ids(request)) {
 
2078
                        stuff(request, blr_pid);
 
2079
                        stuff_word(request, procedure->prc_id);
 
2080
                }
 
2081
                else {
 
2082
                        stuff(request, blr_procedure);
 
2083
                        stuff_meta_string(request, procedure->prc_name);
 
2084
                }
 
2085
                stuff_context(request, context);
 
2086
 
 
2087
                dsql_nod* inputs = context->ctx_proc_inputs;
 
2088
                if (inputs) {
 
2089
                        stuff_word(request, inputs->nod_count);
 
2090
 
 
2091
                        dsql_nod* const* ptr = inputs->nod_arg;
 
2092
                        for (const dsql_nod* const* const end = ptr + inputs->nod_count;
 
2093
                                 ptr < end; ptr++)
 
2094
                        {
 
2095
                                GEN_expr(request, *ptr);
 
2096
                        }
 
2097
                }
 
2098
                else
 
2099
                        stuff_word(request, 0);
 
2100
        }
 
2101
}
 
2102
 
 
2103
 
 
2104
/**
 
2105
  
 
2106
        gen_return
 
2107
  
 
2108
    @brief      Generate blr for a procedure return.
 
2109
 
 
2110
 
 
2111
    @param request
 
2112
    @param procedure
 
2113
    @param eos_flag
 
2114
 
 
2115
 **/
 
2116
void GEN_return( dsql_req* request, const dsql_nod* parameters, bool eos_flag)
 
2117
{
 
2118
        if (!eos_flag)
 
2119
                stuff(request, blr_begin);
 
2120
        stuff(request, blr_send);
 
2121
        stuff(request, 1);
 
2122
        stuff(request, blr_begin);
 
2123
 
 
2124
        USHORT outputs = 0;
 
2125
        if (parameters) {
 
2126
                const dsql_nod* const* ptr = parameters->nod_arg;
 
2127
                for (const dsql_nod* const* const end = ptr + parameters->nod_count;
 
2128
                         ptr < end; ptr++)
 
2129
                {
 
2130
                        outputs++;
 
2131
                        const dsql_nod* parameter = *ptr;
 
2132
                        const dsql_var* variable = (dsql_var*) parameter->nod_arg[e_var_variable];
 
2133
                        stuff(request, blr_assignment);
 
2134
                        stuff(request, blr_variable);
 
2135
                        stuff_word(request, variable->var_variable_number);
 
2136
                        stuff(request, blr_parameter2);
 
2137
                        stuff(request, variable->var_msg_number);
 
2138
                        stuff_word(request, variable->var_msg_item);
 
2139
                        stuff_word(request, variable->var_msg_item + 1);
 
2140
                }
 
2141
        }
 
2142
        stuff(request, blr_assignment);
 
2143
        stuff(request, blr_literal);
 
2144
        stuff(request, blr_short);
 
2145
        stuff(request, 0);
 
2146
        if (eos_flag)
 
2147
                stuff_word(request, 0);
 
2148
        else
 
2149
                stuff_word(request, 1);
 
2150
        stuff(request, blr_parameter);
 
2151
        stuff(request, 1);
 
2152
        stuff_word(request, 2 * outputs);
 
2153
        stuff(request, blr_end);
 
2154
        if (!eos_flag) {
 
2155
                stuff(request, blr_stall);
 
2156
                stuff(request, blr_end);
 
2157
        }
 
2158
}
 
2159
 
 
2160
 
 
2161
/**
 
2162
  
 
2163
        gen_rse
 
2164
  
 
2165
    @brief      Generate a record selection expression.
 
2166
 
 
2167
 
 
2168
    @param request
 
2169
    @param rse
 
2170
 
 
2171
 **/
 
2172
static void gen_rse( dsql_req* request, const dsql_nod* rse)
 
2173
{
 
2174
        if (rse->nod_flags & NOD_SELECT_EXPR_SINGLETON)
 
2175
        {
 
2176
                stuff(request, blr_singular);
 
2177
        }
 
2178
 
 
2179
        stuff(request, blr_rse);
 
2180
 
 
2181
        dsql_nod* list = rse->nod_arg[e_rse_streams];
 
2182
 
 
2183
// Handle source streams
 
2184
 
 
2185
        if (list->nod_type == nod_union) {
 
2186
                stuff(request, 1);
 
2187
                gen_union(request, rse);
 
2188
        }
 
2189
        else if (list->nod_type == nod_list) {
 
2190
                stuff(request, list->nod_count);
 
2191
                dsql_nod* const* ptr = list->nod_arg;
 
2192
                for (const dsql_nod* const* const end = ptr + list->nod_count;
 
2193
                        ptr < end; ptr++)
 
2194
                {
 
2195
                        dsql_nod* node = *ptr;
 
2196
                        if (node->nod_type == nod_relation ||
 
2197
                                node->nod_type == nod_aggregate ||
 
2198
                                node->nod_type == nod_join)
 
2199
                        {
 
2200
                                GEN_expr(request, node);
 
2201
                        }
 
2202
                        else if (node->nod_type == nod_derived_table) {
 
2203
                                GEN_expr(request, node->nod_arg[e_derived_table_rse]);
 
2204
                        }
 
2205
                }
 
2206
        }
 
2207
        else {
 
2208
                stuff(request, 1);
 
2209
                GEN_expr(request, list);
 
2210
        }
 
2211
 
 
2212
        if (rse->nod_arg[e_rse_lock])
 
2213
                stuff(request, blr_writelock);
 
2214
 
 
2215
        dsql_nod* node;
 
2216
 
 
2217
        if ((node = rse->nod_arg[e_rse_first]) != NULL) {
 
2218
                stuff(request, blr_first);
 
2219
                GEN_expr(request, node);
 
2220
        }
 
2221
 
 
2222
        if ((node = rse->nod_arg[e_rse_skip]) != NULL) {
 
2223
                stuff(request, blr_skip);
 
2224
                GEN_expr (request, node);
 
2225
        }
 
2226
 
 
2227
        if ((node = rse->nod_arg[e_rse_boolean]) != NULL) {
 
2228
                stuff(request, blr_boolean);
 
2229
                GEN_expr(request, node);
 
2230
        }
 
2231
 
 
2232
        if ((list = rse->nod_arg[e_rse_sort]) != NULL)
 
2233
                gen_sort(request, list);
 
2234
 
 
2235
        if ((list = rse->nod_arg[e_rse_reduced]) != NULL) {
 
2236
                stuff(request, blr_project);
 
2237
                stuff(request, list->nod_count);
 
2238
                dsql_nod** ptr = list->nod_arg;
 
2239
                for (const dsql_nod* const* const end = ptr + list->nod_count;
 
2240
                        ptr < end; ptr++)
 
2241
                {
 
2242
                        GEN_expr(request, *ptr);
 
2243
                }
 
2244
        }
 
2245
 
 
2246
// if the user specified an access plan to use, add it here 
 
2247
 
 
2248
        if ((node = rse->nod_arg[e_rse_plan]) != NULL) {
 
2249
                stuff(request, blr_plan);
 
2250
                gen_plan(request, node);
 
2251
        }
 
2252
 
 
2253
#ifdef SCROLLABLE_CURSORS
 
2254
/* generate a statement to be executed if the user scrolls 
 
2255
   in a direction other than forward; a message is sent outside 
 
2256
   the normal send/receive protocol to specify the direction 
 
2257
   and offset to scroll; note that we do this only on a SELECT 
 
2258
   type statement and only when talking to a 4.1 engine or greater */
 
2259
 
 
2260
        if (request->req_type == REQ_SELECT &&
 
2261
                request->req_dbb->dbb_base_level >= 5)
 
2262
        {
 
2263
                stuff(request, blr_receive);
 
2264
                stuff(request, request->req_async->msg_number);
 
2265
                stuff(request, blr_seek);
 
2266
                const dsql_par* parameter = request->req_async->msg_parameters;
 
2267
                gen_parameter(request, parameter->par_next);
 
2268
                gen_parameter(request, parameter);
 
2269
        }
 
2270
#endif
 
2271
 
 
2272
        stuff(request, blr_end);
 
2273
}
 
2274
 
 
2275
 
 
2276
/**
 
2277
  
 
2278
 gen_searched_case
 
2279
  
 
2280
    @brief      Generate BLR for CASE function (searched)
 
2281
 
 
2282
 
 
2283
    @param request
 
2284
    @param node
 
2285
 
 
2286
 **/
 
2287
static void gen_searched_case( dsql_req* request, const dsql_nod* node)
 
2288
{
 
2289
        // blr_value_if is used for building the case expression
 
2290
 
 
2291
        stuff(request, blr_cast);
 
2292
        gen_descriptor(request, &node->nod_desc, true);
 
2293
        const SSHORT count =
 
2294
                node->nod_arg[e_searched_case_search_conditions]->nod_count;
 
2295
        dsql_nod* boolean_list = node->nod_arg[e_searched_case_search_conditions];
 
2296
        dsql_nod* results_list = node->nod_arg[e_searched_case_results];
 
2297
        dsql_nod* const* bptr = boolean_list->nod_arg;
 
2298
        dsql_nod* const* rptr = results_list->nod_arg;
 
2299
        for (const dsql_nod* const* const end = bptr + count; bptr < end;
 
2300
                bptr++, rptr++)
 
2301
        {
 
2302
                stuff(request, blr_value_if);
 
2303
                GEN_expr(request, *bptr);
 
2304
                GEN_expr(request, *rptr);
 
2305
        }
 
2306
        // else_result
 
2307
        GEN_expr(request, node->nod_arg[e_searched_case_results]->nod_arg[count]);
 
2308
}
 
2309
 
 
2310
 
 
2311
/**
 
2312
  
 
2313
        gen_select
 
2314
  
 
2315
    @brief      Generate BLR for a SELECT statement.
 
2316
 
 
2317
 
 
2318
    @param request
 
2319
    @param rse
 
2320
 
 
2321
 **/
 
2322
static void gen_select( dsql_req* request, dsql_nod* rse)
 
2323
{
 
2324
        const dsql_rel* relation;
 
2325
        dsql_ctx* context;
 
2326
 
 
2327
        fb_assert(rse->nod_type == nod_rse);
 
2328
 
 
2329
// Set up parameter for things in the select list 
 
2330
        const dsql_nod* list = rse->nod_arg[e_rse_items];
 
2331
        dsql_nod* const* ptr = list->nod_arg;
 
2332
        for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end;
 
2333
                ptr++) 
 
2334
        {
 
2335
                dsql_par* parameter =
 
2336
                        MAKE_parameter(request->req_receive, true, true, 0, *ptr);
 
2337
                parameter->par_node = *ptr;
 
2338
                MAKE_desc(request, &parameter->par_desc, *ptr, NULL);
 
2339
        }
 
2340
 
 
2341
// Set up parameter to handle EOF 
 
2342
 
 
2343
        dsql_par* parameter_eof =
 
2344
                MAKE_parameter(request->req_receive, false, false, 0, NULL);
 
2345
        request->req_eof = parameter_eof;
 
2346
        parameter_eof->par_desc.dsc_dtype = dtype_short;
 
2347
        parameter_eof->par_desc.dsc_scale = 0;
 
2348
        parameter_eof->par_desc.dsc_length = sizeof(SSHORT);
 
2349
 
 
2350
// Save DBKEYs for possible update later
 
2351
 
 
2352
        list = rse->nod_arg[e_rse_streams];
 
2353
 
 
2354
        if (!rse->nod_arg[e_rse_reduced]) {
 
2355
                dsql_nod* const* ptr2 = list->nod_arg;
 
2356
                for (const dsql_nod* const* const end2 = ptr2 + list->nod_count; 
 
2357
                        ptr2 < end2; ptr2++) 
 
2358
                {
 
2359
                        dsql_nod* item = *ptr2;
 
2360
                        if (item && item->nod_type == nod_relation) {
 
2361
                                context = (dsql_ctx*) item->nod_arg[e_rel_context];
 
2362
                                if (relation = context->ctx_relation) {
 
2363
                                        // Set up dbkey
 
2364
                                        dsql_par* parameter =
 
2365
                                                MAKE_parameter(request->req_receive,
 
2366
                                                                           false, false, 0, NULL);
 
2367
                                        parameter->par_dbkey_ctx = context;
 
2368
                                        parameter->par_desc.dsc_dtype = dtype_text;
 
2369
                                        parameter->par_desc.dsc_ttype() = ttype_binary;
 
2370
                                        parameter->par_desc.dsc_length =
 
2371
                                                relation->rel_dbkey_length;
 
2372
 
 
2373
                                        // Set up record version - for post v33 databases
 
2374
 
 
2375
                                        parameter =
 
2376
                                                MAKE_parameter(request->req_receive, false,
 
2377
                                                                           false, 0, NULL);
 
2378
                                        parameter->par_rec_version_ctx = context;
 
2379
                                        parameter->par_desc.dsc_dtype = dtype_text;
 
2380
                                        parameter->par_desc.dsc_ttype() = ttype_binary;
 
2381
                                        parameter->par_desc.dsc_length =
 
2382
                                                relation->rel_dbkey_length / 2;
 
2383
                                }
 
2384
                        }
 
2385
                }
 
2386
        }
 
2387
 
 
2388
#ifdef SCROLLABLE_CURSORS
 
2389
/* define the parameters for the scrolling message--offset and direction, 
 
2390
   in that order to make it easier to generate the request */
 
2391
 
 
2392
        if (request->req_type == REQ_SELECT &&
 
2393
                request->req_dbb->dbb_base_level >= 5) 
 
2394
        {
 
2395
                dsql_par* parameter =
 
2396
                        MAKE_parameter(request->req_async, false, false, 0, NULL);
 
2397
                parameter->par_desc.dsc_dtype = dtype_short;
 
2398
                parameter->par_desc.dsc_length = sizeof(USHORT);
 
2399
                parameter->par_desc.dsc_scale = 0;
 
2400
                parameter->par_desc.dsc_flags = 0;
 
2401
                parameter->par_desc.dsc_sub_type = 0;
 
2402
 
 
2403
                parameter =
 
2404
                        MAKE_parameter(request->req_async, false, false, 0, NULL);
 
2405
                parameter->par_desc.dsc_dtype = dtype_long;
 
2406
                parameter->par_desc.dsc_length = sizeof(ULONG);
 
2407
                parameter->par_desc.dsc_scale = 0;
 
2408
                parameter->par_desc.dsc_flags = 0;
 
2409
                parameter->par_desc.dsc_sub_type = 0;
 
2410
        }
 
2411
#endif
 
2412
 
 
2413
// Generate definitions for the messages 
 
2414
 
 
2415
        GEN_port(request, request->req_receive);
 
2416
        dsql_msg* message = request->req_send;
 
2417
        if (message->msg_parameter)
 
2418
                GEN_port(request, message);
 
2419
        else
 
2420
                request->req_send = NULL;
 
2421
#ifdef SCROLLABLE_CURSORS
 
2422
        if (request->req_type == REQ_SELECT &&
 
2423
                request->req_dbb->dbb_base_level >= 5)
 
2424
                        GEN_port(request, request->req_async);
 
2425
#endif
 
2426
 
 
2427
// If there is a send message, build a RECEIVE
 
2428
 
 
2429
        if ((message = request->req_send) != NULL) {
 
2430
                stuff(request, blr_receive);
 
2431
                stuff(request, message->msg_number);
 
2432
        }
 
2433
 
 
2434
// Generate FOR loop
 
2435
 
 
2436
        message = request->req_receive;
 
2437
 
 
2438
        stuff(request, blr_for);
 
2439
        stuff(request, blr_stall);
 
2440
        gen_rse(request, rse);  
 
2441
 
 
2442
        stuff(request, blr_send);
 
2443
        stuff(request, message->msg_number);
 
2444
        stuff(request, blr_begin);
 
2445
 
 
2446
// Build body of FOR loop
 
2447
 
 
2448
        SSHORT constant;
 
2449
        dsc constant_desc;
 
2450
        constant_desc.dsc_dtype = dtype_short;
 
2451
        constant_desc.dsc_scale = 0;
 
2452
        constant_desc.dsc_sub_type = 0;
 
2453
        constant_desc.dsc_flags = 0;
 
2454
        constant_desc.dsc_length = sizeof(SSHORT);
 
2455
        constant_desc.dsc_address = (UCHAR*) & constant;
 
2456
 
 
2457
        // Add invalid usage here
 
2458
 
 
2459
        stuff(request, blr_assignment);
 
2460
        constant = 1;
 
2461
        gen_constant(request, &constant_desc, USE_VALUE);
 
2462
        gen_parameter(request, request->req_eof);
 
2463
 
 
2464
        for (dsql_par* parameter = message->msg_parameters; parameter;
 
2465
                 parameter = parameter->par_next)
 
2466
        {
 
2467
                if (parameter->par_node) {
 
2468
                        stuff(request, blr_assignment);
 
2469
                        GEN_expr(request, parameter->par_node);
 
2470
                        gen_parameter(request, parameter);
 
2471
                }
 
2472
                if (context = parameter->par_dbkey_ctx) {
 
2473
                        stuff(request, blr_assignment);
 
2474
                        stuff(request, blr_dbkey);
 
2475
                        stuff_context(request, context);
 
2476
                        gen_parameter(request, parameter);
 
2477
                }
 
2478
                if (context = parameter->par_rec_version_ctx) {
 
2479
                        stuff(request, blr_assignment);
 
2480
                        stuff(request, blr_record_version);
 
2481
                        stuff_context(request, context);
 
2482
                        gen_parameter(request, parameter);
 
2483
                }
 
2484
        }
 
2485
 
 
2486
        stuff(request, blr_end);
 
2487
        stuff(request, blr_send);
 
2488
        stuff(request, message->msg_number);
 
2489
        stuff(request, blr_assignment);
 
2490
        constant = 0;
 
2491
        gen_constant(request, &constant_desc, USE_VALUE);
 
2492
        gen_parameter(request, request->req_eof);
 
2493
}
 
2494
 
 
2495
 
 
2496
/**
 
2497
  
 
2498
 gen_simple_case
 
2499
  
 
2500
    @brief      Generate BLR for CASE function (simple)
 
2501
 
 
2502
 
 
2503
    @param request
 
2504
    @param node
 
2505
 
 
2506
 **/
 
2507
static void gen_simple_case( dsql_req* request, const dsql_nod* node)
 
2508
{
 
2509
        // blr_value_if is used for building the case expression 
 
2510
 
 
2511
        stuff(request, blr_cast);
 
2512
        gen_descriptor(request, &node->nod_desc, true);
 
2513
        SSHORT count = node->nod_arg[e_simple_case_when_operands]->nod_count;
 
2514
        dsql_nod* when_list = node->nod_arg[e_simple_case_when_operands];
 
2515
        dsql_nod* results_list = node->nod_arg[e_simple_case_results];
 
2516
 
 
2517
        dsql_nod* const* wptr = when_list->nod_arg;
 
2518
        dsql_nod* const* rptr = results_list->nod_arg;
 
2519
        for (const dsql_nod* const* const end = wptr + count; wptr < end;
 
2520
                wptr++, rptr++)
 
2521
        {
 
2522
                stuff(request, blr_value_if);
 
2523
                stuff(request, blr_eql);
 
2524
                GEN_expr(request, node->nod_arg[e_simple_case_case_operand]);
 
2525
                GEN_expr(request, *wptr);
 
2526
                GEN_expr(request, *rptr);
 
2527
        }
 
2528
        // else_result 
 
2529
        GEN_expr(request, node->nod_arg[e_simple_case_results]->nod_arg[count]); 
 
2530
}
 
2531
 
 
2532
 
 
2533
/**
 
2534
  
 
2535
        gen_sort
 
2536
  
 
2537
    @brief      Generate a sort clause.
 
2538
 
 
2539
 
 
2540
    @param request
 
2541
    @param list
 
2542
 
 
2543
 **/
 
2544
static void gen_sort( dsql_req* request, dsql_nod* list)
 
2545
{
 
2546
        stuff(request, blr_sort);
 
2547
        stuff(request, list->nod_count);
 
2548
 
 
2549
        dsql_nod* const* ptr = list->nod_arg;
 
2550
        for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end;
 
2551
                ptr++)
 
2552
        {
 
2553
                dsql_nod* nulls_placement = (*ptr)->nod_arg[e_order_nulls];
 
2554
                if (nulls_placement) {
 
2555
                        switch (nulls_placement->getSlong()) {
 
2556
                                case NOD_NULLS_FIRST:
 
2557
                                        stuff(request, blr_nullsfirst);
 
2558
                                        break;
 
2559
                                case NOD_NULLS_LAST:
 
2560
                                        stuff(request, blr_nullslast);
 
2561
                                        break;
 
2562
                        }
 
2563
                }
 
2564
                if ((*ptr)->nod_arg[e_order_flag])
 
2565
                        stuff(request, blr_descending);
 
2566
                else
 
2567
                        stuff(request, blr_ascending);
 
2568
                GEN_expr(request, (*ptr)->nod_arg[e_order_field]);
 
2569
        }
 
2570
}
 
2571
 
 
2572
 
 
2573
/**
 
2574
  
 
2575
        gen_statement
 
2576
  
 
2577
    @brief      Generate BLR for DML statements.
 
2578
 
 
2579
 
 
2580
    @param request
 
2581
    @param node
 
2582
 
 
2583
 **/
 
2584
static void gen_statement(dsql_req* request, const dsql_nod* node)
 
2585
{
 
2586
        dsql_nod* rse = NULL;
 
2587
        const dsql_msg* message = NULL;
 
2588
        bool send_before_for = !(request->req_flags & REQ_dsql_upd_or_ins);
 
2589
 
 
2590
        switch (node->nod_type) {
 
2591
        case nod_store:
 
2592
                rse = node->nod_arg[e_sto_rse];
 
2593
                break;
 
2594
        case nod_modify:
 
2595
                rse = node->nod_arg[e_mod_rse];
 
2596
                break;
 
2597
        case nod_erase:
 
2598
                rse = node->nod_arg[e_era_rse];
 
2599
                break;
 
2600
        default:
 
2601
                send_before_for = false;
 
2602
                break;
 
2603
        }
 
2604
 
 
2605
        if (request->req_type == REQ_EXEC_PROCEDURE && send_before_for)
 
2606
        {
 
2607
                if ((message = request->req_receive))
 
2608
                {
 
2609
                        stuff(request, blr_send);
 
2610
                        stuff(request, message->msg_number);
 
2611
                }
 
2612
        }
 
2613
 
 
2614
        if (rse) {
 
2615
                stuff(request, blr_for);
 
2616
                GEN_expr(request, rse);
 
2617
        }
 
2618
 
 
2619
        if (request->req_type == REQ_EXEC_PROCEDURE)
 
2620
        {
 
2621
                if ((message = request->req_receive))
 
2622
                {
 
2623
                        stuff(request, blr_begin);
 
2624
 
 
2625
                        if (!send_before_for)
 
2626
                        {
 
2627
                                stuff(request, blr_send);
 
2628
                                stuff(request, message->msg_number);
 
2629
                        }
 
2630
                }
 
2631
        }
 
2632
 
 
2633
        dsql_nod* temp;
 
2634
        dsql_ctx* context;
 
2635
        dsql_str* name;
 
2636
 
 
2637
        switch (node->nod_type) {
 
2638
        case nod_store:
 
2639
                stuff(request, node->nod_arg[e_sto_return] ? blr_store2 : blr_store);
 
2640
                GEN_expr(request, node->nod_arg[e_sto_relation]);
 
2641
                GEN_statement(request, node->nod_arg[e_sto_statement]);
 
2642
                if (node->nod_arg[e_sto_return]) {
 
2643
                        GEN_statement(request, node->nod_arg[e_sto_return]);
 
2644
                }
 
2645
                break;
 
2646
 
 
2647
        case nod_modify:
 
2648
                stuff(request, node->nod_arg[e_mod_return] ? blr_modify2 : blr_modify);
 
2649
                temp = node->nod_arg[e_mod_source];
 
2650
                context = (dsql_ctx*) temp->nod_arg[e_rel_context];
 
2651
                stuff_context(request, context);
 
2652
                temp = node->nod_arg[e_mod_update];
 
2653
                context = (dsql_ctx*) temp->nod_arg[e_rel_context];
 
2654
                stuff_context(request, context);
 
2655
                GEN_statement(request, node->nod_arg[e_mod_statement]);
 
2656
                if (node->nod_arg[e_mod_return]) {
 
2657
                        GEN_statement(request, node->nod_arg[e_mod_return]);
 
2658
                }
 
2659
                break;
 
2660
 
 
2661
        case nod_modify_current:
 
2662
                stuff(request, node->nod_arg[e_mdc_return] ? blr_modify2 : blr_modify);
 
2663
                context = (dsql_ctx*) node->nod_arg[e_mdc_context];
 
2664
                stuff_context(request, context);
 
2665
                temp = node->nod_arg[e_mdc_update];
 
2666
                context = (dsql_ctx*) temp->nod_arg[e_rel_context];
 
2667
                stuff_context(request, context);
 
2668
                GEN_statement(request, node->nod_arg[e_mdc_statement]);
 
2669
                if (node->nod_arg[e_mdc_return]) {
 
2670
                        GEN_statement(request, node->nod_arg[e_mdc_return]);
 
2671
                }
 
2672
                break;
 
2673
 
 
2674
        case nod_erase:
 
2675
                temp = node->nod_arg[e_era_relation];
 
2676
                context = (dsql_ctx*) temp->nod_arg[e_rel_context];
 
2677
                if (node->nod_arg[e_era_return]) {
 
2678
                        stuff(request, blr_begin);
 
2679
                        GEN_statement(request, node->nod_arg[e_era_return]);
 
2680
                        stuff(request, blr_erase);
 
2681
                        stuff_context(request, context);
 
2682
                        stuff(request, blr_end);
 
2683
                }
 
2684
                else {
 
2685
                        stuff(request, blr_erase);
 
2686
                        stuff_context(request, context);
 
2687
                }
 
2688
                break;
 
2689
 
 
2690
        case nod_erase_current:
 
2691
                context = (dsql_ctx*) node->nod_arg[e_erc_context];
 
2692
                if (node->nod_arg[e_erc_return]) {
 
2693
                        stuff(request, blr_begin);
 
2694
                        GEN_statement(request, node->nod_arg[e_erc_return]);
 
2695
                        stuff(request, blr_erase);
 
2696
                        stuff_context(request, context);
 
2697
                        stuff(request, blr_end);
 
2698
                }
 
2699
                else {
 
2700
                        stuff(request, blr_erase);
 
2701
                        stuff_context(request, context);
 
2702
                }
 
2703
                break;
 
2704
 
 
2705
        case nod_exec_procedure:
 
2706
                stuff(request, blr_exec_proc);
 
2707
                name = (dsql_str*) node->nod_arg[e_exe_procedure];
 
2708
                stuff_meta_string(request, name->str_data);
 
2709
 
 
2710
                // Input parameters
 
2711
                if ( (temp = node->nod_arg[e_exe_inputs]) ) {
 
2712
                        stuff_word(request, temp->nod_count);
 
2713
                        dsql_nod** ptr = temp->nod_arg;
 
2714
                        const dsql_nod* const* end = ptr + temp->nod_count;
 
2715
                        while (ptr < end)
 
2716
                        {
 
2717
                                GEN_expr(request, *ptr++);
 
2718
                        }
 
2719
                }
 
2720
                else {
 
2721
                        stuff_word(request, 0);
 
2722
                }
 
2723
                // Output parameters
 
2724
                if ( ( temp = node->nod_arg[e_exe_outputs]) ) {
 
2725
                        stuff_word(request, temp->nod_count);
 
2726
                        dsql_nod** ptr = temp->nod_arg;
 
2727
                        const dsql_nod* const* end = ptr + temp->nod_count;
 
2728
                        while (ptr < end)
 
2729
                        {
 
2730
                                GEN_expr(request, *ptr++);
 
2731
                        }
 
2732
                }
 
2733
                else {
 
2734
                        stuff_word(request, 0);
 
2735
                }
 
2736
                break;
 
2737
 
 
2738
        default:
 
2739
                fb_assert(false);
 
2740
        }
 
2741
 
 
2742
        if (message) {
 
2743
                stuff(request, blr_end);
 
2744
        }
 
2745
}
 
2746
 
 
2747
 
 
2748
/**
 
2749
  
 
2750
        gen_sys_function
 
2751
  
 
2752
    @brief      Generate a system defined function.
 
2753
 
 
2754
 
 
2755
    @param request
 
2756
    @param node
 
2757
 
 
2758
 **/
 
2759
static void gen_sys_function(dsql_req* request, const dsql_nod* node)
 
2760
{
 
2761
        stuff(request, blr_sys_function);
 
2762
        stuff_cstring(request, ((dsql_str*) node->nod_arg[e_sysfunc_name])->str_data);
 
2763
 
 
2764
        const dsql_nod* list;
 
2765
        if ((node->nod_count == e_sysfunc_args + 1) && (list = node->nod_arg[e_sysfunc_args]))
 
2766
        {
 
2767
                stuff(request, list->nod_count);
 
2768
                dsql_nod* const* ptr = list->nod_arg;
 
2769
                for (const dsql_nod* const* const end = ptr + list->nod_count;
 
2770
                        ptr < end; ptr++)
 
2771
                {
 
2772
                        GEN_expr(request, *ptr);
 
2773
                }
 
2774
        }
 
2775
        else
 
2776
                stuff(request, 0);
 
2777
}
 
2778
 
 
2779
 
 
2780
/**
 
2781
  
 
2782
        gen_table_lock
 
2783
  
 
2784
    @brief      Generate tpb for table lock.
 
2785
        If lock level is specified, it overrrides the transaction lock level.
 
2786
 
 
2787
 
 
2788
    @param request
 
2789
    @param tbl_lock
 
2790
    @param lock_level
 
2791
 
 
2792
 **/
 
2793
static void gen_table_lock( dsql_req* request, const dsql_nod* tbl_lock,
 
2794
        USHORT lock_level)
 
2795
{
 
2796
        if ((!tbl_lock) || (tbl_lock->nod_type != nod_table_lock))
 
2797
                return;
 
2798
 
 
2799
        const dsql_nod* tbl_names = tbl_lock->nod_arg[e_lock_tables];
 
2800
        SSHORT flags = 0;
 
2801
 
 
2802
        if (tbl_lock->nod_arg[e_lock_mode])
 
2803
                flags = tbl_lock->nod_arg[e_lock_mode]->nod_flags;
 
2804
 
 
2805
        if (flags & NOD_PROTECTED)
 
2806
                lock_level = isc_tpb_protected;
 
2807
        else if (flags & NOD_SHARED)
 
2808
                lock_level = isc_tpb_shared;
 
2809
 
 
2810
        const USHORT lock_mode = (flags & NOD_WRITE) ? 
 
2811
                isc_tpb_lock_write : isc_tpb_lock_read;
 
2812
 
 
2813
        const dsql_nod* const* ptr = tbl_names->nod_arg;
 
2814
        for (const dsql_nod* const* const end = ptr + tbl_names->nod_count;
 
2815
                 ptr < end; ptr++)
 
2816
        {
 
2817
                if ((*ptr)->nod_type != nod_relation_name)
 
2818
                        continue;
 
2819
 
 
2820
                stuff(request, lock_mode);
 
2821
 
 
2822
                // stuff table name 
 
2823
                const dsql_str* temp = (dsql_str*) ((*ptr)->nod_arg[e_rln_name]);
 
2824
                stuff_cstring(request, reinterpret_cast<const char*>(temp->str_data));
 
2825
 
 
2826
                stuff(request, lock_level);
 
2827
        }
 
2828
}
 
2829
 
 
2830
 
 
2831
/**
 
2832
  
 
2833
        gen_udf
 
2834
  
 
2835
    @brief      Generate a user defined function.
 
2836
 
 
2837
 
 
2838
    @param request
 
2839
    @param node
 
2840
 
 
2841
 **/
 
2842
static void gen_udf( dsql_req* request, const dsql_nod* node)
 
2843
{
 
2844
        const dsql_udf* userFunc = (dsql_udf*) node->nod_arg[0];
 
2845
        stuff(request, blr_function);
 
2846
        stuff_cstring(request, userFunc->udf_name);
 
2847
 
 
2848
        const dsql_nod* list;
 
2849
        if ((node->nod_count == 2) && (list = node->nod_arg[1])) {
 
2850
                stuff(request, list->nod_count);
 
2851
                dsql_nod* const* ptr = list->nod_arg;
 
2852
                for (const dsql_nod* const* const end = ptr + list->nod_count;
 
2853
                        ptr < end; ptr++)
 
2854
                {
 
2855
                        GEN_expr(request, *ptr);
 
2856
                }
 
2857
        }
 
2858
        else
 
2859
                stuff(request, 0);
 
2860
}
 
2861
 
 
2862
 
 
2863
/**
 
2864
  
 
2865
        gen_union
 
2866
  
 
2867
    @brief      Generate a union of substreams.
 
2868
 
 
2869
 
 
2870
    @param request
 
2871
    @param union_node
 
2872
 
 
2873
 **/
 
2874
static void gen_union( dsql_req* request, const dsql_nod* union_node)
 
2875
{
 
2876
        if (union_node->nod_arg[0]->nod_flags & NOD_UNION_RECURSIVE) {
 
2877
                stuff(request, blr_recurse);
 
2878
        }
 
2879
        else {
 
2880
                stuff(request, blr_union);
 
2881
        }
 
2882
 
 
2883
// Obtain the context for UNION from the first dsql_map* node
 
2884
        dsql_nod* items = union_node->nod_arg[e_rse_items];
 
2885
        dsql_nod* map_item = items->nod_arg[0];
 
2886
        // AB: First item could be a virtual field generated by derived table.
 
2887
        if (map_item->nod_type == nod_derived_field) {
 
2888
                map_item = map_item->nod_arg[e_alias_value]; 
 
2889
        }
 
2890
        dsql_ctx* union_context = (dsql_ctx*) map_item->nod_arg[e_map_context];
 
2891
        stuff_context(request, union_context);
 
2892
        // secondary context number must be present once in generated blr 
 
2893
        union_context->ctx_flags &= ~CTX_recursive;
 
2894
 
 
2895
        dsql_nod* streams = union_node->nod_arg[e_rse_streams];
 
2896
        stuff(request, streams->nod_count);     // number of substreams 
 
2897
 
 
2898
        dsql_nod** ptr = streams->nod_arg;
 
2899
        for (const dsql_nod* const* const end = ptr + streams->nod_count; ptr < end;
 
2900
                 ptr++)
 
2901
        {
 
2902
                dsql_nod* sub_rse = *ptr;
 
2903
                gen_rse(request, sub_rse);
 
2904
                items = sub_rse->nod_arg[e_rse_items];
 
2905
                stuff(request, blr_map);
 
2906
                stuff_word(request, items->nod_count);
 
2907
                USHORT count = 0;
 
2908
                dsql_nod** iptr = items->nod_arg;
 
2909
                for (const dsql_nod* const* const iend = iptr + items->nod_count;
 
2910
                         iptr < iend; iptr++)
 
2911
                {
 
2912
                        stuff_word(request, count);
 
2913
                        GEN_expr(request, *iptr);
 
2914
                        count++;
 
2915
                }
 
2916
        }
 
2917
}
 
2918
 
 
2919
 
 
2920
/**
 
2921
  
 
2922
        stuff_context
 
2923
  
 
2924
    @brief      Write a context number into the BLR buffer.
 
2925
                        Check for possible overflow.
 
2926
 
 
2927
 
 
2928
    @param request
 
2929
    @param context
 
2930
 
 
2931
 **/
 
2932
static void stuff_context(dsql_req* request, const dsql_ctx* context)
 
2933
{
 
2934
        if (context->ctx_context > MAX_UCHAR) {
 
2935
                ERRD_post(isc_too_many_contexts, 0);
 
2936
        }
 
2937
        stuff(request, context->ctx_context);
 
2938
 
 
2939
        if (context->ctx_flags & CTX_recursive)
 
2940
        {
 
2941
                if (context->ctx_recursive > MAX_UCHAR) {
 
2942
                        ERRD_post(isc_too_many_contexts, 0);
 
2943
                }
 
2944
                stuff(request, context->ctx_recursive);
 
2945
        }
 
2946
}
 
2947
 
 
2948
 
 
2949
/**
 
2950
  
 
2951
        stuff_cstring
 
2952
  
 
2953
    @brief      Write out a string with one byte of length.
 
2954
 
 
2955
 
 
2956
    @param request
 
2957
    @param string
 
2958
 
 
2959
 **/
 
2960
static void stuff_cstring( dsql_req* request, const char* string)
 
2961
{
 
2962
        stuff_string(request, string, strlen(string));
 
2963
}
 
2964
 
 
2965
 
 
2966
/**
 
2967
  
 
2968
        stuff_meta_string
 
2969
  
 
2970
    @brief      Write out a string in metadata charset with one byte of length.
 
2971
 
 
2972
 
 
2973
    @param request
 
2974
    @param string
 
2975
 
 
2976
 **/
 
2977
static void stuff_meta_string(dsql_req* request, const char* string)
 
2978
{
 
2979
        request->append_meta_string(string);
 
2980
}
 
2981
 
 
2982
 
 
2983
/**
 
2984
  
 
2985
        stuff_string
 
2986
  
 
2987
    @brief      Write out a string with one byte of length.
 
2988
 
 
2989
 
 
2990
    @param request
 
2991
    @param string
 
2992
 
 
2993
 **/
 
2994
static void stuff_string(dsql_req* request, const char* string, int len)
 
2995
{
 
2996
        fb_assert(len >= 0 && len <= 255);
 
2997
 
 
2998
        stuff(request, len);
 
2999
 
 
3000
        while (len--)
 
3001
                stuff(request, *string++);
 
3002
}
 
3003
 
 
3004
 
 
3005
/**
 
3006
  
 
3007
        stuff_word
 
3008
  
 
3009
    @brief      Cram a word into the blr buffer.  If the buffer is getting
 
3010
        ready to overflow, expand it.
 
3011
 
 
3012
 
 
3013
    @param request
 
3014
    @param word
 
3015
 
 
3016
 **/
 
3017
static void stuff_word( dsql_req* request, USHORT word)
 
3018
{
 
3019
 
 
3020
        stuff(request, word);
 
3021
        stuff(request, word >> 8);
 
3022
}