2
* PROGRAM: JRD Access Method
4
* DESCRIPTION: BLR Parser
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
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.
16
* The Original Code was created by Inprise Corporation
17
* and its predecessors. Portions created by Inprise Corporation are
18
* Copyright (C) Inprise Corporation.
20
* All Rights Reserved.
21
* Contributor(s): ______________________________________.
23
* 27-May-2001 Claudio Valderrama: par_plan() no longer uppercases
24
* an index's name before doing a lookup of such index.
25
* 2001.07.28: Added parse code for blr_skip to support LIMIT.
26
* 2002.09.28 Dmitry Yemanov: Reworked internal_info stuff, enhanced
27
* exception handling in SPs/triggers,
28
* implemented ROWS_AFFECTED system variable
29
* 2002.10.21 Nickolay Samofatov: Added support for explicit pessimistic locks
30
* 2002.10.28 Sean Leyne - Code cleanup, removed obsolete "MPEXL" port
31
* 2002.10.29 Mike Nordell - Fixed breakage.
32
* 2002.10.29 Nickolay Samofatov: Added support for savepoints
33
* 2002.10.29 Sean Leyne - Removed obsolete "Netware" port
34
* 2003.10.05 Dmitry Yemanov: Added support for explicit cursors in PSQL
35
* 2004.01.16 Vlad Horsun: Added support for default parameters
36
* Adriano dos Santos Fernandes
42
#include "../jrd/common.h"
44
#include "../jrd/jrd.h"
45
#include "../jrd/ibase.h"
46
#include "../jrd/ini.h"
47
#include "../jrd/val.h"
48
#include "../jrd/align.h"
49
#include "../jrd/exe.h"
50
#include "../jrd/lls.h"
51
#include "../jrd/rse.h" // for MAX_STREAMS
53
#include "../jrd/scl.h"
54
#include "../jrd/all.h"
55
#include "../jrd/req.h"
56
#include "../jrd/blb.h"
57
#include "../jrd/intl.h"
58
#include "../jrd/met.h"
59
#include "../jrd/cmp_proto.h"
60
#include "../jrd/cvt_proto.h"
61
#include "../jrd/err_proto.h"
62
#include "../jrd/fun_proto.h"
63
#include "../jrd/gds_proto.h"
64
#include "../jrd/met_proto.h"
65
#include "../jrd/par_proto.h"
66
#include "../jrd/thd.h"
67
#include "../common/utils_proto.h"
68
#include "../jrd/SysFunction.h"
71
/* blr type classes */
74
const int STATEMENT = 1;
75
const int TYPE_BOOL = 2;
77
const int TYPE_RSE = 4;
78
const int RELATION = 5;
79
const int ACCESS_TYPE = 6;
83
#include "gen/blrtable.h"
87
static const TEXT elements[][14] =
88
{ "", "statement", "boolean", "value", "RecordSelExpr", "TABLE" };
90
#include "gen/codetext.h"
93
static void error(CompilerScratch*, ...);
94
static SSHORT find_proc_field(const jrd_prc*, const Firebird::MetaName&);
95
static jrd_nod* par_args(thread_db*, CompilerScratch*, USHORT);
96
static jrd_nod* par_cast(thread_db*, CompilerScratch*);
97
static PsqlException* par_condition(thread_db*, CompilerScratch*);
98
static PsqlException* par_conditions(thread_db*, CompilerScratch*);
99
static SSHORT par_context(CompilerScratch*, SSHORT *);
100
static void par_dependency(thread_db*, CompilerScratch*, SSHORT, SSHORT, const Firebird::MetaName&);
101
static jrd_nod* par_exec_proc(thread_db*, CompilerScratch*, SSHORT);
102
static jrd_nod* par_fetch(thread_db*, CompilerScratch*, jrd_nod*);
103
static jrd_nod* par_field(thread_db*, CompilerScratch*, SSHORT);
104
static jrd_nod* par_function(thread_db*, CompilerScratch*);
105
static jrd_nod* par_literal(thread_db*, CompilerScratch*);
106
static jrd_nod* par_map(thread_db*, CompilerScratch*, USHORT);
107
static jrd_nod* par_message(thread_db*, CompilerScratch*);
108
static jrd_nod* par_modify(thread_db*, CompilerScratch*, SSHORT);
109
static USHORT par_name(CompilerScratch*, Firebird::MetaName&);
110
static size_t par_name(CompilerScratch* csb, Firebird::string& name);
111
static jrd_nod* par_plan(thread_db*, CompilerScratch*);
112
static jrd_nod* par_procedure(thread_db*, CompilerScratch*, SSHORT);
113
static void par_procedure_parms(thread_db*, CompilerScratch*, jrd_prc*, jrd_nod**,
115
static jrd_nod* par_relation(thread_db*, CompilerScratch*, SSHORT, bool);
116
static jrd_nod* par_rse(thread_db*, CompilerScratch*, SSHORT);
117
static jrd_nod* par_sort(thread_db*, CompilerScratch*, bool);
118
#ifdef NOT_USED_OR_REPLACED
119
static jrd_nod* par_stream(thread_db*, CompilerScratch*);
121
static jrd_nod* par_sys_function(thread_db*, CompilerScratch*);
122
static jrd_nod* par_union(thread_db*, CompilerScratch*, bool);
123
static USHORT par_word(CompilerScratch*);
124
static jrd_nod* parse(thread_db*, CompilerScratch*, USHORT, USHORT expected_optional = 0);
125
static void syntax_error(CompilerScratch*, const TEXT*);
126
static void warning(CompilerScratch*, ...);
128
#define BLR_PEEK *(csb->csb_running)
129
#define BLR_BYTE *(csb->csb_running)++
130
#define BLR_PUSH (csb->csb_running)--
131
#define BLR_WORD par_word (csb)
134
jrd_nod* PAR_blr(thread_db* tdbb,
137
CompilerScratch* view_csb,
138
CompilerScratch** csb_ptr,
139
jrd_req** request_ptr,
143
/**************************************
147
**************************************
149
* Functional description
150
* Parse blr, returning a compiler scratch block with the results.
151
* Caller must do pool handling.
153
**************************************/
157
cmp_trace("BLR code given for JRD parsing:");
158
// CVC: Couldn't find isc_trace_printer, so changed it to gds__trace_printer.
159
gds__print_blr(blr, gds__trace_printer, 0, 0);
162
CompilerScratch* csb;
163
if (!(csb_ptr && (csb = *csb_ptr))) {
166
count += view_csb->csb_rpt.getCapacity();
167
csb = CompilerScratch::newCsb(*tdbb->getDefaultPool(), count);
168
csb->csb_g_flags |= flags;
171
/* If there is a request ptr, this is a trigger. Set up contexts 0 and 1 for
172
the target relation */
175
SSHORT stream = csb->nextStream();
176
CompilerScratch::csb_repeat* t1 = CMP_csb_element(csb, 0);
177
t1->csb_flags |= csb_used | csb_active | csb_trigger;
178
t1->csb_relation = relation;
179
t1->csb_stream = (UCHAR) stream;
181
stream = csb->nextStream();
182
t1 = CMP_csb_element(csb, 1);
183
t1->csb_flags |= csb_used | csb_active | csb_trigger;
184
t1->csb_relation = relation;
185
t1->csb_stream = (UCHAR) stream;
188
CompilerScratch::csb_repeat* t1 = CMP_csb_element(csb, 0);
189
t1->csb_stream = csb->nextStream();
190
t1->csb_relation = relation;
191
t1->csb_flags = csb_used | csb_active;
194
csb->csb_running = csb->csb_blr = blr;
197
CompilerScratch::rpt_itr ptr = view_csb->csb_rpt.begin();
198
// AB: csb_n_stream replaced by view_csb->csb_rpt.getCount(), because there could
199
// be more then just csb_n_stream-numbers that hold data.
200
// Certainly csb_stream (see par_context where the context is retrieved)
201
const CompilerScratch::rpt_const_itr end = view_csb->csb_rpt.end();
202
for (SSHORT stream = 0; ptr != end; ++ptr, ++stream) {
203
CompilerScratch::csb_repeat* t2 = CMP_csb_element(csb, stream);
204
t2->csb_relation = ptr->csb_relation;
205
t2->csb_stream = ptr->csb_stream;
206
t2->csb_flags = ptr->csb_flags & csb_used;
208
csb->csb_n_stream = view_csb->csb_n_stream;
211
const SSHORT version = *csb->csb_running++;
213
if (version != blr_version4 && version != blr_version5) {
214
error(csb, isc_metadata_corrupt,
215
isc_arg_gds, isc_wroblrver,
216
isc_arg_number, (SLONG) blr_version4,
217
isc_arg_number, (SLONG) version, 0);
220
if (version == blr_version4)
221
csb->csb_g_flags |= csb_blr_version4;
223
jrd_nod* node = parse(tdbb, csb, OTHER);
224
csb->csb_node = node;
226
if (*csb->csb_running++ != (UCHAR) blr_eoc)
227
syntax_error(csb, "end_of_command");
230
*request_ptr = CMP_make_request(tdbb, csb);
241
USHORT PAR_desc(thread_db* tdbb, CompilerScratch* csb, DSC* desc, ItemInfo* itemInfo)
243
/**************************************
247
**************************************
249
* Functional description
250
* Parse a BLR descriptor. Return the alignment requirements
253
**************************************/
256
itemInfo->nullable = true;
257
itemInfo->explicitCollation = false;
258
itemInfo->fullDomain = false;
262
desc->dsc_sub_type = 0;
263
desc->dsc_address = NULL;
266
const USHORT dtype = BLR_BYTE;
270
case blr_not_nullable:
271
PAR_desc(tdbb, csb, desc, itemInfo);
273
itemInfo->nullable = false;
277
desc->dsc_dtype = dtype_text;
278
desc->dsc_flags |= DSC_no_subtype;
279
desc->dsc_length = BLR_WORD;
280
INTL_ASSIGN_TTYPE(desc, ttype_dynamic);
284
desc->dsc_dtype = dtype_cstring;
285
desc->dsc_flags |= DSC_no_subtype;
286
desc->dsc_length = BLR_WORD;
287
INTL_ASSIGN_TTYPE(desc, ttype_dynamic);
291
desc->dsc_dtype = dtype_varying;
292
desc->dsc_flags |= DSC_no_subtype;
293
desc->dsc_length = BLR_WORD + sizeof(USHORT);
294
INTL_ASSIGN_TTYPE(desc, ttype_dynamic);
298
desc->dsc_dtype = dtype_text;
299
INTL_ASSIGN_TTYPE(desc, BLR_WORD);
300
desc->dsc_length = BLR_WORD;
304
desc->dsc_dtype = dtype_cstring;
305
INTL_ASSIGN_TTYPE(desc, BLR_WORD);
306
desc->dsc_length = BLR_WORD;
310
desc->dsc_dtype = dtype_varying;
311
INTL_ASSIGN_TTYPE(desc, BLR_WORD);
312
desc->dsc_length = BLR_WORD + sizeof(USHORT);
316
desc->dsc_dtype = dtype_short;
317
desc->dsc_length = sizeof(SSHORT);
318
desc->dsc_scale = (int) BLR_BYTE;
322
desc->dsc_dtype = dtype_long;
323
desc->dsc_length = sizeof(SLONG);
324
desc->dsc_scale = (int) BLR_BYTE;
328
desc->dsc_dtype = dtype_int64;
329
desc->dsc_length = sizeof(SINT64);
330
desc->dsc_scale = (int) BLR_BYTE;
334
desc->dsc_dtype = dtype_quad;
335
desc->dsc_length = sizeof(ISC_QUAD);
336
desc->dsc_scale = (int) BLR_BYTE;
340
desc->dsc_dtype = dtype_real;
341
desc->dsc_length = sizeof(float);
345
desc->dsc_dtype = dtype_timestamp;
346
desc->dsc_length = sizeof(ISC_QUAD);
350
desc->dsc_dtype = dtype_sql_date;
351
desc->dsc_length = type_lengths[dtype_sql_date];
355
desc->dsc_dtype = dtype_sql_time;
356
desc->dsc_length = type_lengths[dtype_sql_time];
363
desc->dsc_dtype = dtype_double;
364
desc->dsc_length = sizeof(double);
369
desc->dsc_dtype = dtype_d_float;
370
desc->dsc_length = sizeof(double);
376
desc->dsc_dtype = dtype_blob;
377
desc->dsc_length = sizeof(ISC_QUAD);
378
desc->dsc_sub_type = BLR_WORD;
380
USHORT ttype = BLR_WORD;
381
desc->dsc_scale = ttype & 0xFF; // BLOB character set
382
desc->dsc_flags = ttype & 0xFF00; // BLOB collation
386
case blr_domain_name:
387
case blr_domain_name2:
389
bool fullDomain = (BLR_BYTE == blr_domain_full);
390
Firebird::MetaName* name = FB_NEW(csb->csb_pool) Firebird::MetaName(csb->csb_pool);
391
par_name(csb, *name);
394
bool exist = csb->csb_map_field_info.get(*name, fieldInfo);
395
MET_get_domain(tdbb, *name, desc, (exist ? NULL : &fieldInfo));
398
csb->csb_map_field_info.put(*name, fieldInfo);
402
itemInfo->field = *name;
406
itemInfo->nullable = fieldInfo.nullable;
407
itemInfo->fullDomain = true;
410
itemInfo->nullable = true;
413
if (dtype == blr_domain_name2)
415
USHORT ttype = BLR_WORD;
417
switch (desc->dsc_dtype)
422
INTL_ASSIGN_TTYPE(desc, ttype);
426
desc->dsc_scale = ttype & 0xFF; // BLOB character set
427
desc->dsc_flags = ttype & 0xFF00; // BLOB collation
431
error(csb, isc_collation_requires_text, 0);
436
jrd_nod* dep_node = PAR_make_node(tdbb, e_dep_length);
437
dep_node->nod_type = nod_dependency;
438
dep_node->nod_arg[e_dep_object] = (jrd_nod*) name;
439
dep_node->nod_arg[e_dep_object_type] = (jrd_nod*)(IPTR) obj_field;
440
csb->csb_dependencies.push(dep_node);
446
error(csb, isc_datnotsup, 0);
451
if (dtype == blr_cstring2 || dtype == blr_text2 || dtype == blr_varying2 ||
452
dtype == blr_blob2 || dtype == blr_domain_name2)
454
itemInfo->explicitCollation = true;
458
return type_alignments[desc->dsc_dtype];
462
jrd_nod* PAR_gen_field(thread_db* tdbb, USHORT stream, USHORT id)
464
/**************************************
466
* P A R _ g e n _ f i e l d
468
**************************************
470
* Functional description
471
* Generate a field block.
473
**************************************/
476
jrd_nod* node = FB_NEW_RPT(*tdbb->getDefaultPool(), e_fld_length) jrd_nod();
477
node->nod_type = nod_field;
478
node->nod_arg[e_fld_id] = (jrd_nod*) (IPTR) id;
479
node->nod_arg[e_fld_stream] = (jrd_nod*) (IPTR) stream;
485
jrd_nod* PAR_make_field(thread_db* tdbb, CompilerScratch* csb,
487
const Firebird::MetaName& base_field)
489
/**************************************
491
* P A R _ m a k e _ f i e l d
493
**************************************
495
* Functional description
496
* Make up a field node in the permanent pool. This is used
497
* by MET_scan_relation to handle view fields.
499
**************************************/
502
const USHORT stream = csb->csb_rpt[context].csb_stream;
504
/* CVC: This is just another case of a custom function that isn't prepared
505
for quoted identifiers and that causes views with fields names like "z x"
506
to fail miserably. Since this function was truncating field names like "z x",
507
MET_lookup_field() call below failed and hence the function returned NULL
508
so only caller MET_scan_relation() did field->fld_source = 0;
509
This means a field without entry in rdb$fields. This is the origin of the
510
mysterious message "cannot access column z x in view VF" when selecting from
511
such view that has field "z x". This closes Firebird Bug #227758. */
512
// solved by using MetaName& as parameter - AP
513
jrd_rel* relation = csb->csb_rpt[stream].csb_relation;
514
jrd_prc* procedure = csb->csb_rpt[stream].csb_procedure;
516
const SSHORT id = procedure ? find_proc_field(procedure, base_field) :
517
MET_lookup_field (tdbb, csb->csb_rpt[stream].csb_relation, base_field, 0);
522
/* If rel_fields is NULL this means that the relation is
523
* in a temporary state (partially loaded). In this case
524
* there is nothing we can do but post an error and exit.
525
* Note: This will most likely happen if we have a large list
526
* of deferred work which can not complete because of some
527
* error, and while we are trying to commit, we find
528
* that we have a dependency on something later in the list.
529
* IF there were no error, then the dependency woyld have
530
* been resolved, because we would have fully loaded the
531
* relation, but if it can not be loaded, then we have this
532
* problem. The only thing that can be done to remedy this
533
* problem is to rollback. This will clear the DeferredWork list and
534
* allow the user to remedy the original error. Note: it would
535
* be incorrect for us (the server) to perform the rollback
536
* implicitly, because this is a task for the user to do, and
537
* should never be decided by the server. This fixes bug 10052 */
539
// CVC: The code for procedures now compiles correctly, but Vlad has
540
// pointed out that we don't have default for output fields, therefore
541
// the code is commented till better times.
542
jrd_fld* field = NULL;
544
Parameter* param = NULL;
548
param = (*procedure->prc_output_fields)[id];
554
if (!relation->rel_fields) {
555
ERR_post(isc_depend_on_uncommitted_rel, 0);
557
field = (*relation->rel_fields)[id];
560
if (csb->csb_g_flags & csb_get_dependencies) {
561
par_dependency(tdbb, csb, stream, id, base_field);
564
jrd_nod* temp_node = PAR_gen_field(tdbb, stream, id);
568
if (param->prm_default_value) //&& param->prm_not_null)
569
temp_node->nod_arg[e_fld_default_value] =
570
param->prm_default_value;
576
if (field->fld_default_value && field->fld_not_null)
577
temp_node->nod_arg[e_fld_default_value] = field->fld_default_value;
584
jrd_nod* PAR_make_list(thread_db* tdbb, NodeStack& stack)
586
/**************************************
588
* P A R _ m a k e _ l i s t
590
**************************************
592
* Functional description
593
* Make a list node out of a stack.
595
**************************************/
598
/* Count the number of nodes */
599
USHORT count = stack.getCount();
601
jrd_nod* node = PAR_make_node(tdbb, count);
602
node->nod_type = nod_list;
603
jrd_nod** ptr = node->nod_arg + count;
605
while (stack.hasData())
607
*--ptr = stack.pop();
614
jrd_nod* PAR_make_node(thread_db* tdbb, int size)
616
/**************************************
618
* P A R _ m a k e _ n o d e
620
**************************************
622
* Functional description
623
* Make a node element and pass it back.
625
**************************************/
628
jrd_nod* node = FB_NEW_RPT(*tdbb->getDefaultPool(), size) jrd_nod();
629
node->nod_count = size;
635
CompilerScratch* PAR_parse(thread_db* tdbb, const UCHAR* blr, USHORT internal_flag,
636
USHORT dbginfo_length, const UCHAR* dbginfo)
638
/**************************************
642
**************************************
644
* Functional description
645
* Parse blr, returning a compiler scratch block with the results.
647
**************************************/
650
CompilerScratch* csb = CompilerScratch::newCsb(*tdbb->getDefaultPool(), 5);
651
csb->csb_running = csb->csb_blr = blr;
652
const SSHORT version = *csb->csb_running++;
654
csb->csb_g_flags |= csb_internal;
656
if (version != blr_version4 && version != blr_version5)
658
error(csb, isc_wroblrver,
659
isc_arg_number, (SLONG) blr_version4,
660
isc_arg_number, (SLONG) version, 0);
663
if (version == blr_version4)
665
csb->csb_g_flags |= csb_blr_version4;
668
if (dbginfo_length > 0)
669
DBG_parse_debug_info(dbginfo_length, dbginfo, csb->csb_dbg_info);
671
jrd_nod* node = parse(tdbb, csb, OTHER);
672
csb->csb_node = node;
674
if (*csb->csb_running++ != (UCHAR) blr_eoc)
676
syntax_error(csb, "end_of_command");
683
SLONG PAR_symbol_to_gdscode(const Firebird::MetaName& name)
685
/**************************************
687
* P A R _ s y m b o l _ t o _ g d s c o d e
689
**************************************
691
* Functional description
692
* Symbolic ASCII names are used in blr for posting and handling
693
* exceptions. They are also used to identify error codes
694
* within system triggers in a database.
696
* Returns the gds error status code for the given symbolic
697
* name, or 0 if not found.
699
* Symbolic names may be null or space terminated.
701
**************************************/
703
for (int i = 0; codes[i].code_number; ++i) {
704
if (name == codes[i].code_string) {
705
return codes[i].code_number;
713
static void error(CompilerScratch* csb, ...)
715
/**************************************
719
**************************************
721
* Functional description
722
* We've got a blr error other than a syntax error. Handle it.
724
**************************************/
730
/* Don't bother to pass tdbb for error handling */
731
thread_db* tdbb = JRD_get_thread_data();
736
offset = csb->csb_running - csb->csb_blr;
737
p = tdbb->tdbb_status_vector;
739
*p++ = isc_invalid_blr;
740
*p++ = isc_arg_number;
744
*p++ = va_arg(args, ISC_STATUS);
746
/* Pick up remaining args */
748
while ( (*p++ = type = va_arg(args, int)) )
752
*p++ = (ISC_STATUS) va_arg(args, ISC_STATUS);
756
case isc_arg_interpreted:
757
*p++ = (ISC_STATUS) va_arg(args, TEXT *);
760
case isc_arg_cstring:
761
*p++ = (ISC_STATUS) va_arg(args, int);
762
*p++ = (ISC_STATUS) va_arg(args, TEXT *);
766
*p++ = (ISC_STATUS) va_arg(args, SLONG);
774
*p++ = va_arg(args, int);
780
/* Give up whatever we were doing and return to the user. */
786
static SSHORT find_proc_field(const jrd_prc* procedure, const Firebird::MetaName& name)
788
/**************************************
790
* f i n d _ p r o c _ f i e l d
792
**************************************
794
* Functional description
795
* Look for named field in procedure output fields.
797
**************************************/
798
vec<Parameter*>* list = procedure->prc_output_fields;
799
vec<Parameter*>::const_iterator ptr = list->begin();
800
for (const vec<Parameter*>::const_iterator end = list->end(); ptr < end; ++ptr)
802
const Parameter* param = *ptr;
803
if (name == param->prm_name)
804
return param->prm_number;
811
static jrd_nod* par_args(thread_db* tdbb, CompilerScratch* csb, USHORT expected)
813
/**************************************
817
**************************************
819
* Functional description
820
* Parse a counted argument list.
822
**************************************/
825
USHORT count = BLR_BYTE;
826
jrd_nod* node = PAR_make_node(tdbb, count);
827
node->nod_type = nod_list;
828
jrd_nod** ptr = node->nod_arg;
832
*ptr++ = parse(tdbb, csb, expected);
840
static jrd_nod* par_cast(thread_db* tdbb, CompilerScratch* csb)
842
/**************************************
846
**************************************
848
* Functional description
849
* Parse a datatype cast
851
**************************************/
854
jrd_nod* node = PAR_make_node(tdbb, e_cast_length);
855
node->nod_count = count_table[blr_cast];
857
Format* format = Format::newFormat(*tdbb->getDefaultPool(), 1);
858
node->nod_arg[e_cast_fmt] = (jrd_nod*) format;
860
dsc* desc = &format->fmt_desc[0];
862
PAR_desc(tdbb, csb, desc, &itemInfo);
863
format->fmt_length = desc->dsc_length;
865
node->nod_arg[e_cast_source] = parse(tdbb, csb, VALUE);
867
if (itemInfo.isSpecial())
869
ItemInfo* p = FB_NEW(*tdbb->getDefaultPool()) ItemInfo(*tdbb->getDefaultPool(), itemInfo);
870
node->nod_arg[e_cast_iteminfo] = (jrd_nod*) p;
873
if (itemInfo.explicitCollation)
875
jrd_nod* dep_node = PAR_make_node (tdbb, e_dep_length);
876
dep_node->nod_type = nod_dependency;
877
dep_node->nod_arg [e_dep_object] = (jrd_nod*)(IPTR) INTL_TEXT_TYPE(*desc);
878
dep_node->nod_arg [e_dep_object_type] = (jrd_nod*)(IPTR) obj_collation;
879
csb->csb_dependencies.push(dep_node);
886
static PsqlException* par_condition(thread_db* tdbb, CompilerScratch* csb)
888
/**************************************
890
* p a r _ c o n d i t i o n
892
**************************************
894
* Functional description
895
* Parse an error conditions list.
897
**************************************/
900
Firebird::MetaName name;
904
/* allocate a node to represent the conditions list */
906
const USHORT code_type = BLR_BYTE;
908
/* don't create PsqlException if blr_raise is used,
910
if (code_type == blr_raise)
915
PsqlException* exception_list = FB_NEW_RPT(*tdbb->getDefaultPool(), 1) PsqlException();
916
exception_list->xcp_count = 1;
917
xcp_repeat& item = exception_list->xcp_rpt[0];
921
item.xcp_type = xcp_sql_code;
922
item.xcp_code = (SSHORT) BLR_WORD;
926
item.xcp_type = xcp_gds_code;
929
code_number = PAR_symbol_to_gdscode(name);
931
item.xcp_code = code_number;
933
error(csb, isc_codnotdef, isc_arg_string, ERR_cstring(name), 0);
937
case blr_exception_msg:
938
item.xcp_type = xcp_xcp_code;
940
if (!(item.xcp_code = MET_lookup_exception_number(tdbb, name)))
941
error(csb, isc_xcpnotdef, isc_arg_string, ERR_cstring(name), 0);
942
dep_node = PAR_make_node(tdbb, e_dep_length);
943
dep_node->nod_type = nod_dependency;
944
dep_node->nod_arg[e_dep_object] = (jrd_nod*)(IPTR) item.xcp_code;
945
dep_node->nod_arg[e_dep_object_type] = (jrd_nod*)(IPTR) obj_exception;
946
csb->csb_dependencies.push(dep_node);
954
return exception_list;
958
static PsqlException* par_conditions(thread_db* tdbb, CompilerScratch* csb)
960
/**************************************
962
* p a r _ c o n d i t i o n s
964
**************************************
966
* Functional description
967
* Parse an error conditions list.
969
**************************************/
972
Firebird::MetaName name;
976
/* allocate a node to represent the conditions list */
978
const USHORT n = BLR_WORD;
979
PsqlException* exception_list = FB_NEW_RPT(*tdbb->getDefaultPool(), n) PsqlException();
980
exception_list->xcp_count = n;
981
for (int i = 0; i < n; i++) {
982
const USHORT code_type = BLR_BYTE;
983
xcp_repeat& item = exception_list->xcp_rpt[i];
987
item.xcp_type = xcp_sql_code;
988
item.xcp_code = (SSHORT) BLR_WORD;
992
item.xcp_type = xcp_gds_code;
995
code_number = PAR_symbol_to_gdscode(name);
997
item.xcp_code = code_number;
999
error(csb, isc_codnotdef, isc_arg_string, ERR_cstring(name), 0);
1003
item.xcp_type = xcp_xcp_code;
1004
par_name(csb, name);
1005
if (!(item.xcp_code = MET_lookup_exception_number(tdbb, name)))
1006
error(csb, isc_xcpnotdef, isc_arg_string, ERR_cstring(name), 0);
1007
dep_node = PAR_make_node(tdbb, e_dep_length);
1008
dep_node->nod_type = nod_dependency;
1009
dep_node->nod_arg[e_dep_object] = (jrd_nod*)(IPTR) item.xcp_code;
1010
dep_node->nod_arg[e_dep_object_type] = (jrd_nod*)(IPTR) obj_exception;
1011
csb->csb_dependencies.push(dep_node);
1014
case blr_default_code:
1015
item.xcp_type = xcp_default;
1025
return exception_list;
1029
static SSHORT par_context(CompilerScratch* csb, SSHORT* context_ptr)
1031
/**************************************
1033
* p a r _ c o n t e x t
1035
**************************************
1037
* Functional description
1038
* Introduce a new context into the system. This involves
1039
* assigning a stream and possibly extending the compile
1042
**************************************/
1044
const SSHORT context = (unsigned int) BLR_BYTE;
1047
*context_ptr = context;
1049
CompilerScratch::csb_repeat* tail = CMP_csb_element(csb, context);
1051
if (tail->csb_flags & csb_used) {
1052
if (csb->csb_g_flags & csb_reuse_context) {
1053
return tail->csb_stream;
1056
error(csb, isc_ctxinuse, 0);
1060
const SSHORT stream = csb->nextStream(false);
1061
if (stream >= MAX_STREAMS)
1063
error(csb, isc_too_many_contexts, 0);
1066
tail->csb_flags |= csb_used;
1067
tail->csb_stream = (UCHAR) stream;
1069
CMP_csb_element(csb, stream);
1075
static void par_dependency(thread_db* tdbb,
1076
CompilerScratch* csb,
1079
const Firebird::MetaName& field_name)
1081
/**************************************
1083
* p a r _ d e p e n d e n c y
1085
**************************************
1087
* Functional description
1088
* Register a field, relation, procedure or exception reference
1091
**************************************/
1094
jrd_nod* node = PAR_make_node(tdbb, e_dep_length);
1095
node->nod_type = nod_dependency;
1096
if (csb->csb_rpt[stream].csb_relation) {
1097
node->nod_arg[e_dep_object] =
1098
(jrd_nod*) csb->csb_rpt[stream].csb_relation;
1099
// How do I determine reliably this is a view?
1100
// At this time, rel_view_rse is still null.
1102
// node->nod_arg[e_dep_object_type] = (jrd_nod*)(IPTR) obj_view;
1104
node->nod_arg[e_dep_object_type] = (jrd_nod*)(IPTR) obj_relation;
1106
else if (csb->csb_rpt[stream].csb_procedure) {
1107
node->nod_arg[e_dep_object] =
1108
(jrd_nod*) csb->csb_rpt[stream].csb_procedure;
1109
node->nod_arg[e_dep_object_type] = (jrd_nod*)(IPTR) obj_procedure;
1112
if (field_name.length() > 0) {
1113
jrd_nod* field_node = PAR_make_node(tdbb, 1);
1114
node->nod_arg[e_dep_field] = field_node;
1115
field_node->nod_type = nod_literal;
1116
field_node->nod_arg[0] = (jrd_nod*)
1117
stringDup(*tdbb->getDefaultPool(), field_name.c_str());
1120
jrd_nod* field_node = PAR_make_node(tdbb, 1);
1121
node->nod_arg[e_dep_field] = field_node;
1122
field_node->nod_type = nod_field;
1123
field_node->nod_arg[0] = (jrd_nod*) (IPTR) id;
1126
csb->csb_dependencies.push(node);
1130
static jrd_nod* par_exec_proc(thread_db* tdbb, CompilerScratch* csb, SSHORT blr_operator)
1132
/**************************************
1134
* p a r _ e x e c _ p r o c
1136
**************************************
1138
* Functional description
1139
* Parse an execute procedure reference.
1141
**************************************/
1144
jrd_prc* procedure = NULL;
1146
Firebird::MetaName name;
1148
if (blr_operator == blr_exec_pid) {
1149
const USHORT pid = BLR_WORD;
1150
if (!(procedure = MET_lookup_procedure_id(tdbb, pid, false, false, 0)))
1151
name.printf("id %d", pid);
1154
par_name(csb, name);
1155
procedure = MET_lookup_procedure(tdbb, name, false);
1158
error(csb, isc_prcnotdef, isc_arg_string, ERR_cstring(name), 0);
1161
jrd_nod* node = PAR_make_node(tdbb, e_esp_length);
1162
node->nod_type = nod_exec_proc;
1163
node->nod_count = count_table[blr_exec_proc];
1164
node->nod_arg[e_esp_procedure] = (jrd_nod*) procedure;
1166
par_procedure_parms(tdbb, csb, procedure, &node->nod_arg[e_esp_in_msg],
1167
&node->nod_arg[e_esp_inputs], true);
1168
par_procedure_parms(tdbb, csb, procedure, &node->nod_arg[e_esp_out_msg],
1169
&node->nod_arg[e_esp_outputs], false);
1171
jrd_nod* dep_node = PAR_make_node(tdbb, e_dep_length);
1172
dep_node->nod_type = nod_dependency;
1173
dep_node->nod_arg[e_dep_object] = (jrd_nod*) procedure;
1174
dep_node->nod_arg[e_dep_object_type] = (jrd_nod*)(IPTR) obj_procedure;
1176
csb->csb_dependencies.push(dep_node);
1182
static jrd_nod* par_fetch(thread_db* tdbb, CompilerScratch* csb, jrd_nod* for_node)
1184
/**************************************
1188
**************************************
1190
* Functional description
1191
* Parse a FETCH statement, and map it into
1193
* FOR x IN relation WITH x.DBKEY EQ value ...
1195
**************************************/
1198
/* Fake RecordSelExpr */
1200
for_node->nod_arg[e_for_re] = PAR_make_node(tdbb, 1 + rse_delta + 2);
1201
RecordSelExpr* rse = (RecordSelExpr*) for_node->nod_arg[e_for_re];
1202
rse->nod_type = nod_rse;
1205
jrd_nod* relation = parse(tdbb, csb, RELATION);
1206
rse->rse_relation[0] = relation;
1210
jrd_nod* node = rse->rse_boolean = PAR_make_node(tdbb, 2);
1211
node->nod_type = nod_eql;
1212
node->nod_flags = nod_comparison;
1213
node->nod_arg[1] = parse(tdbb, csb, VALUE);
1214
node->nod_arg[0] = PAR_make_node(tdbb, 1);
1215
node = node->nod_arg[0];
1216
node->nod_type = nod_dbkey;
1217
node->nod_count = 0;
1218
node->nod_arg[0] = relation->nod_arg[e_rel_stream];
1220
/* Pick up statement */
1222
for_node->nod_arg[e_for_statement] = parse(tdbb, csb, STATEMENT);
1228
static jrd_nod* par_field(thread_db* tdbb, CompilerScratch* csb, SSHORT blr_operator)
1230
/**************************************
1234
**************************************
1236
* Functional description
1239
**************************************/
1242
const USHORT context = (unsigned int) BLR_BYTE;
1244
// check if this is a VALUE of domain's check constraint
1245
if (!csb->csb_domain_validation.isEmpty() &&
1246
(blr_operator == blr_fid || blr_operator == blr_field) &&
1249
if (blr_operator == blr_fid) {
1250
SSHORT id = BLR_WORD;
1254
Firebird::MetaName name;
1255
par_name(csb, name);
1258
jrd_nod* node = PAR_make_node(tdbb, e_domval_length);
1259
node->nod_type = nod_domain_validation;
1260
node->nod_count = 0;
1262
dsc* desc = (dsc*) (node->nod_arg + e_domval_desc);
1263
MET_get_domain(tdbb, csb->csb_domain_validation, desc, NULL);
1268
if (context >= csb->csb_rpt.getCount())/* ||
1269
!(csb->csb_rpt[context].csb_flags & csb_used) )
1271
dimitr: commented out to support system triggers implementing
1272
WITH CHECK OPTION. They reference the relation stream (#2)
1273
directly, without a DSQL context. It breaks the layering,
1274
but we must support legacy BLR.
1277
error(csb, isc_ctxnotdef, 0);
1280
Firebird::MetaName name;
1282
const SSHORT stream = csb->csb_rpt[context].csb_stream;
1284
bool is_column = false;
1286
if (blr_operator == blr_fid)
1292
else if (blr_operator == blr_field)
1294
CompilerScratch::csb_repeat* tail = &csb->csb_rpt[stream];
1295
const jrd_prc* procedure = tail->csb_procedure;
1297
/* make sure procedure has been scanned before using it */
1299
if (procedure && (!(procedure->prc_flags & PRC_scanned)
1300
|| (procedure->prc_flags & PRC_being_scanned)
1301
|| (procedure->prc_flags & PRC_being_altered)))
1303
const jrd_prc* scan_proc = MET_procedure(tdbb, procedure->prc_id, false, 0);
1304
if (scan_proc != procedure)
1309
par_name(csb, name);
1310
if ((id = find_proc_field(procedure, name)) == -1)
1313
isc_arg_string, ERR_cstring(name),
1314
isc_arg_string, procedure->prc_name.c_str(), 0);
1317
jrd_rel* relation = tail->csb_relation;
1319
error(csb, isc_ctxnotdef, 0);
1321
/* make sure relation has been scanned before using it */
1323
if (!(relation->rel_flags & REL_scanned) ||
1324
(relation->rel_flags & REL_being_scanned))
1326
MET_scan_relation(tdbb, relation);
1329
par_name(csb, name);
1330
if ((id = MET_lookup_field(tdbb, relation, name.c_str(), 0)) < 0) {
1331
if (csb->csb_g_flags & csb_validation) {
1337
if (tdbb->getAttachment()->att_flags & ATT_gbak_attachment)
1339
warning(csb, isc_fldnotdef, isc_arg_string,
1340
ERR_cstring(name), isc_arg_string,
1341
relation->rel_name.c_str(), 0);
1343
else if (relation->rel_name.length() > 0)
1345
error(csb, isc_fldnotdef, isc_arg_string,
1346
ERR_cstring(name), isc_arg_string,
1347
relation->rel_name.c_str(), 0);
1350
error(csb, isc_ctxnotdef, 0);
1356
/* check for dependencies -- if a field name was given,
1357
use it because when restoring the database the field
1358
id's may not be valid yet */
1360
if (csb->csb_g_flags & csb_get_dependencies) {
1361
if (blr_operator == blr_fid)
1362
par_dependency(tdbb, csb, stream, id, "");
1364
par_dependency(tdbb, csb, stream, id, name);
1367
jrd_nod* node = PAR_gen_field(tdbb, stream, id);
1368
node->nod_flags |= flags;
1372
jrd_rel* temp_rel = csb->csb_rpt[stream].csb_relation;
1378
if (id < (int) temp_rel->rel_fields->count() && (field = (*temp_rel->rel_fields)[id]))
1380
if (field->fld_default_value && field->fld_not_null)
1381
node->nod_arg[e_fld_default_value] = field->fld_default_value;
1385
if (temp_rel->rel_flags & REL_system)
1387
node = PAR_make_node(tdbb, 0);
1388
node->nod_type = nod_null;
1398
static jrd_nod* par_function(thread_db* tdbb, CompilerScratch* csb)
1400
/**************************************
1402
* p a r _ f u n c t i o n
1404
**************************************
1406
* Functional description
1407
* Parse a function reference.
1409
**************************************/
1412
Firebird::MetaName name;
1413
const USHORT count = par_name(csb, name);
1415
UserFunction* function = FUN_lookup_function(name,
1416
!(tdbb->getAttachment()->att_flags & ATT_gbak_attachment));
1418
if (tdbb->tdbb_flags & TDBB_prc_being_dropped) {
1419
jrd_nod* anode = PAR_make_node(tdbb, e_fun_length);
1420
anode->nod_count = 1;
1421
anode->nod_arg[e_fun_function] = NULL;
1422
anode->nod_arg[e_fun_args] = par_args(tdbb, csb, VALUE);
1426
csb->csb_running -= count;
1427
error(csb, isc_funnotdef, isc_arg_string, ERR_cstring(name), 0);
1431
UserFunction* homonyms;
1432
for (homonyms = function; homonyms; homonyms = homonyms->fun_homonym) {
1433
if (homonyms->fun_entrypoint)
1438
if (tdbb->getAttachment()->att_flags & ATT_gbak_attachment)
1440
warning(csb, isc_funnotdef,
1441
isc_arg_string, ERR_cstring(name),
1442
isc_arg_interpreted,
1443
"module name or entrypoint could not be found", 0);
1446
csb->csb_running -= count;
1447
error(csb, isc_funnotdef,
1448
isc_arg_string, ERR_cstring(name),
1449
isc_arg_interpreted,
1450
"module name or entrypoint could not be found", 0);
1453
jrd_nod* node = PAR_make_node(tdbb, e_fun_length);
1454
node->nod_count = 1;
1455
node->nod_arg[e_fun_function] = (jrd_nod*) function;
1456
node->nod_arg[e_fun_args] = par_args(tdbb, csb, VALUE);
1458
/* CVC: I will track ufds only if a proc is not being dropped. */
1459
if (csb->csb_g_flags & csb_get_dependencies) {
1460
jrd_nod* dep_node = PAR_make_node (tdbb, e_dep_length);
1461
dep_node->nod_type = nod_dependency;
1462
dep_node->nod_arg [e_dep_object] = (jrd_nod*) function;
1463
dep_node->nod_arg [e_dep_object_type] = (jrd_nod*)(IPTR) obj_udf;
1464
csb->csb_dependencies.push(dep_node);
1471
static jrd_nod* par_literal(thread_db* tdbb, CompilerScratch* csb)
1473
/**************************************
1475
* p a r _ l i t e r a l
1477
**************************************
1479
* Functional description
1480
* Parse a literal value.
1482
**************************************/
1489
PAR_desc(tdbb, csb, &desc);
1490
const int count = lit_delta +
1491
(desc.dsc_length + sizeof(jrd_nod*) - 1) / sizeof(jrd_nod*);
1492
jrd_nod* node = PAR_make_node(tdbb, count);
1493
Literal* literal = (Literal*) node;
1494
node->nod_count = 0;
1495
literal->lit_desc = desc;
1496
UCHAR* p = reinterpret_cast<UCHAR*>(literal->lit_data);
1497
literal->lit_desc.dsc_address = p;
1498
literal->lit_desc.dsc_flags = 0;
1499
const UCHAR* q = csb->csb_running;
1500
USHORT l = desc.dsc_length;
1502
switch (desc.dsc_dtype) {
1505
*(SSHORT *) p = (SSHORT) gds__vax_integer(q, l);
1509
case dtype_sql_date:
1510
case dtype_sql_time:
1512
*(SLONG *) p = gds__vax_integer(q, l);
1515
case dtype_timestamp:
1517
*(SLONG *) p = gds__vax_integer(q, 4);
1520
*(SLONG *) p = gds__vax_integer(q, 4);
1525
*(SINT64 *) p = isc_portable_integer(q, l);
1529
/* the double literal could potentially be used for any
1530
numeric literal - the value is passed as if it were a
1531
text string. Convert the numeric string to its binary
1532
value (int64, long or double as appropriate). */
1534
q = csb->csb_running;
1536
CVT_get_numeric(q, l, &scale, (double *) p, ERR_post);
1537
literal->lit_desc.dsc_dtype = dtype;
1538
if (dtype == dtype_double)
1539
literal->lit_desc.dsc_length = sizeof(double);
1540
else if (dtype == dtype_long) {
1541
literal->lit_desc.dsc_length = sizeof(SLONG);
1542
literal->lit_desc.dsc_scale = (SCHAR) scale;
1545
literal->lit_desc.dsc_length = sizeof(SINT64);
1546
literal->lit_desc.dsc_scale = (SCHAR) scale;
1558
csb->csb_running += l;
1564
static jrd_nod* par_map(thread_db* tdbb, CompilerScratch* csb, USHORT stream)
1566
/**************************************
1570
**************************************
1572
* Functional description
1573
* Parse a MAP clause for a union or global aggregate expression.
1575
**************************************/
1578
if (BLR_BYTE != blr_map)
1579
syntax_error(csb, "blr_map");
1581
SSHORT count = BLR_WORD;
1584
while (--count >= 0) {
1585
jrd_nod* assignment = PAR_make_node(tdbb, e_asgn_length);
1586
assignment->nod_type = nod_assignment;
1587
assignment->nod_count = e_asgn_length;
1588
assignment->nod_arg[e_asgn_to] =
1589
PAR_gen_field(tdbb, stream, BLR_WORD);
1590
assignment->nod_arg[e_asgn_from] = parse(tdbb, csb, VALUE);
1591
map.push(assignment);
1594
jrd_nod* node = PAR_make_list(tdbb, map);
1595
node->nod_type = nod_map;
1601
static jrd_nod* par_message(thread_db* tdbb, CompilerScratch* csb)
1603
/**************************************
1605
* p a r _ m e s s a g e
1607
**************************************
1609
* Functional description
1610
* Parse a message declaration, including operator byte.
1612
**************************************/
1615
/* Get message number, register it in the compiler scratch block, and
1616
allocate a node to represent the message */
1618
USHORT n = (unsigned int) BLR_BYTE;
1619
CompilerScratch::csb_repeat* tail = CMP_csb_element(csb, n);
1620
jrd_nod* node = PAR_make_node(tdbb, e_msg_length);
1621
tail->csb_message = node;
1622
node->nod_count = 0;
1623
node->nod_arg[e_msg_number] = (jrd_nod*) (IPTR) n;
1624
if (n > csb->csb_msg_number)
1625
csb->csb_msg_number = n;
1627
/* Get the number of parameters in the message and prepare to fill
1628
out the format block */
1631
Format* format = Format::newFormat(*tdbb->getDefaultPool(), n);
1632
node->nod_arg[e_msg_format] = (jrd_nod*) format;
1635
Format::fmt_desc_iterator desc, end;
1638
for (desc = format->fmt_desc.begin(), end = desc + n; desc < end; ++desc, ++index)
1641
const USHORT alignment = PAR_desc(tdbb, csb, &*desc, &itemInfo);
1643
offset = FB_ALIGN(offset, alignment);
1644
desc->dsc_address = (UCHAR *) (IPTR) offset;
1645
offset += desc->dsc_length;
1647
// ASF: Odd indexes are the nullable flag.
1648
// So we only check even indexes, which is the actual parameter.
1649
if (itemInfo.isSpecial() && index % 2 == 0)
1651
csb->csb_dbg_info.argInfoToName.get(
1652
Firebird::ArgumentInfo(csb->csb_msg_number, index / 2), itemInfo.name);
1654
csb->csb_map_item_info.put(
1655
Item(nod_argument, csb->csb_msg_number, index), itemInfo);
1659
if (offset > MAX_FORMAT_SIZE)
1660
error(csb, isc_imp_exc, isc_arg_gds, isc_blktoobig, 0);
1662
format->fmt_length = (USHORT) offset;
1668
static jrd_nod* par_modify(thread_db* tdbb, CompilerScratch* csb, SSHORT blr_operator)
1670
/**************************************
1672
* p a r _ m o d i f y
1674
**************************************
1676
* Functional description
1677
* Parse a modify statement.
1679
**************************************/
1682
/* Parse the original and new contexts */
1684
USHORT context = (unsigned int) BLR_BYTE;
1685
if (context >= csb->csb_rpt.getCount() ||
1686
!(csb->csb_rpt[context].csb_flags & csb_used))
1688
error(csb, isc_ctxnotdef, 0);
1690
const SSHORT org_stream = csb->csb_rpt[context].csb_stream;
1691
const SSHORT new_stream = csb->nextStream(false);
1692
if (new_stream >= MAX_STREAMS)
1694
error(csb, isc_too_many_contexts, 0);
1696
context = (unsigned int) BLR_BYTE;
1698
/* Make sure the compiler scratch block is big enough to hold
1701
CompilerScratch::csb_repeat* tail = CMP_csb_element(csb, context);
1702
tail->csb_stream = (UCHAR) new_stream;
1703
tail->csb_flags |= csb_used;
1705
tail = CMP_csb_element(csb, new_stream);
1706
tail->csb_relation = csb->csb_rpt[org_stream].csb_relation;
1708
/* Make the node and parse the sub-expression */
1710
jrd_nod* node = PAR_make_node(tdbb, e_mod_length);
1711
node->nod_count = 1;
1712
node->nod_arg[e_mod_org_stream] = (jrd_nod*) (IPTR) org_stream;
1713
node->nod_arg[e_mod_new_stream] = (jrd_nod*) (IPTR) new_stream;
1714
node->nod_arg[e_mod_statement] = parse(tdbb, csb, STATEMENT);
1716
if (blr_operator == blr_modify2)
1718
node->nod_count = 2;
1719
node->nod_arg[e_mod_statement2] = parse(tdbb, csb, STATEMENT);
1726
static USHORT par_name(CompilerScratch* csb, Firebird::MetaName& name)
1728
/**************************************
1732
**************************************
1734
* Functional description
1735
* Parse a counted string, returning count.
1737
**************************************/
1738
size_t l = BLR_BYTE;
1740
// Check for overly long identifiers at BLR parse stage to prevent unwanted
1741
// surprises in deeper layers of the engine.
1742
if (l > MAX_SQL_IDENTIFIER_LEN) {
1745
l = MAX_SQL_IDENTIFIER_LEN;
1750
ERR_post(isc_identifier_too_long, isc_arg_string, ERR_cstring(st), 0);
1753
char* s = name.getBuffer(l);
1760
return name.length();
1764
static size_t par_name(CompilerScratch* csb, Firebird::string& name)
1766
/**************************************
1770
**************************************
1772
* Functional description
1773
* Parse a counted string of virtually unlimited size
1774
* (up to 64K, actually <= 255), returning count.
1776
**************************************/
1777
size_t l = BLR_BYTE;
1778
char* s = name.getBuffer(l);
1785
return name.length();
1789
static jrd_nod* par_plan(thread_db* tdbb, CompilerScratch* csb)
1791
/**************************************
1795
**************************************
1797
* Functional description
1798
* Parse an access plan expression.
1799
* At this stage we are just generating the
1800
* parse tree and checking contexts
1803
**************************************/
1806
USHORT node_type = (USHORT) BLR_BYTE;
1808
/* a join type indicates a cross of two or more streams */
1810
if (node_type == blr_join || node_type == blr_merge) {
1811
USHORT count = (USHORT) BLR_BYTE;
1812
jrd_nod* plan = PAR_make_node(tdbb, count);
1813
plan->nod_type = (NOD_T) (USHORT) blr_table[node_type];
1815
for (jrd_nod** arg = plan->nod_arg; count--;)
1816
*arg++ = par_plan(tdbb, csb);
1820
/* we have hit a stream; parse the context number and access type */
1822
if (node_type == blr_retrieve) {
1823
jrd_nod* plan = PAR_make_node(tdbb, e_retrieve_length);
1824
plan->nod_type = (NOD_T) (USHORT) blr_table[node_type];
1826
/* parse the relation name and context--the relation
1827
itself is redundant except in the case of a view,
1828
in which case the base relation (and alias) must be specified */
1830
USHORT n = (unsigned int) BLR_BYTE;
1831
if (n != blr_relation && n != blr_relation2 &&
1832
n != blr_rid && n != blr_rid2)
1834
syntax_error(csb, elements[RELATION]);
1837
/* don't have par_relation() parse the context, because
1838
this would add a new context; while this is a reference to
1839
an existing context */
1841
jrd_nod* relation_node = par_relation(tdbb, csb, n, false);
1842
plan->nod_arg[e_retrieve_relation] = relation_node;
1843
jrd_rel* relation = (jrd_rel*) relation_node->nod_arg[e_rel_relation];
1846
if (n >= csb->csb_rpt.getCount() || !(csb->csb_rpt[n].csb_flags & csb_used))
1847
error(csb, isc_ctxnotdef, 0);
1848
const SSHORT stream = csb->csb_rpt[n].csb_stream;
1850
relation_node->nod_arg[e_rel_stream] = (jrd_nod*) (IPTR) stream;
1851
relation_node->nod_arg[e_rel_context] = (jrd_nod*) (IPTR) n;
1853
/* Access plan types (sequential is default) */
1855
node_type = (USHORT) BLR_BYTE;
1856
USHORT extra_count = 0;
1857
jrd_nod* access_type = 0;
1858
Firebird::MetaName name;
1861
switch (node_type) {
1862
case blr_navigational:
1864
access_type = plan->nod_arg[e_retrieve_access_type] =
1865
PAR_make_node(tdbb, e_access_type_length);
1866
access_type->nod_type = nod_navigational;
1868
/* pick up the index name and look up the appropriate ids */
1870
par_name(csb, name);
1871
/* CVC: We can't do this. Index names are identifiers.
1872
for (p = name; *p; *p++)
1877
const SLONG index_id =
1878
MET_lookup_index_name(tdbb, name, &relation_id, &idx_status);
1880
if (idx_status == MET_object_unknown ||
1881
idx_status == MET_object_inactive)
1883
if (tdbb->getAttachment()->att_flags & ATT_gbak_attachment)
1885
warning(csb, isc_indexname, isc_arg_string,
1886
ERR_cstring(name), isc_arg_string,
1887
relation->rel_name.c_str(), 0);
1891
error(csb, isc_indexname, isc_arg_string,
1892
ERR_cstring(name), isc_arg_string,
1893
relation->rel_name.c_str(), 0);
1897
/* save both the relation id and the index id, since
1898
the relation could be a base relation of a view;
1899
save the index name also, for convenience */
1901
access_type->nod_arg[e_access_type_relation] = (jrd_nod*) (IPTR) relation_id;
1902
access_type->nod_arg[e_access_type_index] = (jrd_nod*) (IPTR) index_id;
1903
idx_name = stringDup(*tdbb->getDefaultPool(), name.c_str());
1904
access_type->nod_arg[e_access_type_index_name] = (jrd_nod*) idx_name;
1906
if (csb->csb_g_flags & csb_get_dependencies)
1908
jrd_nod* dep_node = PAR_make_node (tdbb, e_dep_length);
1909
dep_node->nod_type = nod_dependency;
1910
dep_node->nod_arg[e_dep_object] = (jrd_nod*) idx_name;
1911
dep_node->nod_arg[e_dep_object_type] = (jrd_nod*)(IPTR) obj_index;
1912
csb->csb_dependencies.push(dep_node);
1915
if (BLR_PEEK == blr_indices)
1916
// dimitr: FALL INTO, if the plan item is ORDER ... INDEX (...)
1924
BLR_BYTE; // skip blr_indices
1925
USHORT count = (USHORT) BLR_BYTE;
1926
jrd_nod* temp = plan->nod_arg[e_retrieve_access_type] =
1927
PAR_make_node(tdbb, count * e_access_type_length + extra_count);
1928
for (USHORT i = 0; i < extra_count; i++) {
1929
temp->nod_arg[i] = access_type->nod_arg[i];
1931
temp->nod_type = (extra_count) ? nod_navigational : nod_indices;
1936
/* pick up the index names and look up the appropriate ids */
1938
for (jrd_nod** arg = access_type->nod_arg + extra_count; count--;) {
1939
par_name(csb, name);
1940
/* Nickolay Samofatov: We can't do this. Index names are identifiers.
1941
for (p = name; *p; *p++)
1946
const SLONG index_id =
1947
MET_lookup_index_name(tdbb, name, &relation_id, &idx_status);
1949
if (idx_status == MET_object_unknown ||
1950
idx_status == MET_object_inactive)
1952
if (tdbb->getAttachment()->att_flags & ATT_gbak_attachment)
1954
warning(csb, isc_indexname, isc_arg_string,
1955
ERR_cstring(name), isc_arg_string,
1956
relation->rel_name.c_str(), 0);
1960
error(csb, isc_indexname, isc_arg_string,
1961
ERR_cstring(name), isc_arg_string,
1962
relation->rel_name.c_str(), 0);
1966
/* save both the relation id and the index id, since
1967
the relation could be a base relation of a view;
1968
save the index name also, for convenience */
1970
*arg++ = (jrd_nod*) (IPTR) relation_id;
1971
*arg++ = (jrd_nod*) (IPTR) index_id;
1972
idx_name = stringDup(*tdbb->getDefaultPool(), name.c_str());
1973
*arg++ = (jrd_nod*) idx_name;
1975
if (csb->csb_g_flags & csb_get_dependencies)
1977
jrd_nod* dep_node = PAR_make_node (tdbb, e_dep_length);
1978
dep_node->nod_type = nod_dependency;
1979
dep_node->nod_arg[e_dep_object] = (jrd_nod*) idx_name;
1980
dep_node->nod_arg[e_dep_object_type] = (jrd_nod*)(IPTR) obj_index;
1981
csb->csb_dependencies.push(dep_node);
1986
case blr_sequential:
1989
syntax_error(csb, "access type");
1995
syntax_error(csb, "plan item");
1996
return NULL; /* Added to remove compiler warning */
2000
static jrd_nod* par_procedure(thread_db* tdbb, CompilerScratch* csb, SSHORT blr_operator)
2002
/**************************************
2004
* p a r _ p r o c e d u r e
2006
**************************************
2008
* Functional description
2009
* Parse an procedural view reference.
2011
**************************************/
2017
Firebird::MetaName name;
2019
if (blr_operator == blr_procedure) {
2020
par_name(csb, name);
2021
procedure = MET_lookup_procedure(tdbb, name, false);
2024
const SSHORT pid = BLR_WORD;
2025
if (!(procedure = MET_lookup_procedure_id(tdbb, pid, false, false, 0)))
2026
name.printf("id %d", pid);
2029
error(csb, isc_prcnotdef, isc_arg_string, ERR_cstring(name), 0);
2032
if (procedure->prc_type == prc_executable)
2034
error(csb, isc_illegal_prc_type,
2035
isc_arg_string, ERR_string(procedure->prc_name), 0);
2038
jrd_nod* node = PAR_make_node(tdbb, e_prc_length);
2039
node->nod_type = nod_procedure;
2040
node->nod_count = count_table[blr_procedure];
2041
node->nod_arg[e_prc_procedure] = (jrd_nod*) (IPTR) procedure->prc_id;
2043
const USHORT stream = par_context(csb, 0);
2044
node->nod_arg[e_prc_stream] = (jrd_nod*) (IPTR) stream;
2045
csb->csb_rpt[stream].csb_procedure = procedure;
2047
par_procedure_parms(tdbb, csb, procedure, &node->nod_arg[e_prc_in_msg],
2048
&node->nod_arg[e_prc_inputs], true);
2050
if (csb->csb_g_flags & csb_get_dependencies)
2051
par_dependency(tdbb, csb, stream, (SSHORT) - 1, "");
2057
static void par_procedure_parms(
2059
CompilerScratch* csb,
2061
jrd_nod** message_ptr,
2062
jrd_nod** parameter_ptr, bool input_flag)
2064
/**************************************
2066
* p a r _ p r o c e d u r e _ p a r m s
2068
**************************************
2070
* Functional description
2071
* Parse some procedure parameters.
2073
**************************************/
2075
bool mismatch = false;
2076
SLONG count = BLR_WORD;
2078
/** Check to see if the parameter count matches **/
2080
(count < (procedure->prc_inputs - procedure->prc_defaults) ||
2081
(count > procedure->prc_inputs) ) :
2082
(count != procedure->prc_outputs))
2084
/** They don't match...Hmmm...Its OK if we were dropping the procedure **/
2085
if (!(tdbb->tdbb_flags & TDBB_prc_being_dropped)) {
2087
input_flag ? isc_prcmismat : isc_prc_out_param_mismatch,
2089
ERR_cstring(procedure->prc_name.c_str()),
2096
if (count || input_flag && procedure->prc_defaults) {
2097
/** We have a few parameters. Get on with creating the message block **/
2098
USHORT n = ++csb->csb_msg_number;
2100
csb->csb_msg_number = n = 2;
2101
CompilerScratch::csb_repeat* tail = CMP_csb_element(csb, n);
2102
jrd_nod* message = PAR_make_node(tdbb, e_msg_length);
2103
tail->csb_message = message;
2104
message->nod_type = nod_message;
2105
message->nod_count = count_table[blr_message];
2106
*message_ptr = message;
2107
message->nod_count = 0;
2108
message->nod_arg[e_msg_number] = (jrd_nod*)(IPTR) n;
2109
const Format* format =
2110
input_flag ? procedure->prc_input_fmt : procedure->prc_output_fmt;
2111
/* dimitr: procedure (with its parameter formats) is allocated out of
2112
its own pool (prc_request->req_pool) and can be freed during
2113
the cache cleanup (MET_clear_cache). Since the current
2114
tdbb default pool is different from the procedure's one,
2115
it's dangerous to copy a pointer from one request to another.
2116
As an experiment, I've decided to copy format by value
2117
instead of copying the reference. Since Format structure
2118
doesn't contain any pointers, it should be safe to use a
2119
default assignment operator which does a simple byte copy.
2120
This change fixes one serious bug in the current codebase.
2121
I think that this situation can (and probably should) be
2122
handled by the metadata cache (via incrementing prc_use_count)
2123
to avoid unexpected cache cleanups, but that area is out of my
2124
knowledge. So this fix should be considered a temporary solution.
2126
message->nod_arg[e_msg_format] = (jrd_nod*) format;
2128
Format* fmt_copy = Format::newFormat(*tdbb->getDefaultPool(), format->fmt_count);
2129
*fmt_copy = *format;
2130
message->nod_arg[e_msg_format] = (jrd_nod*) fmt_copy;
2131
/* --- end of fix --- */
2133
n = format->fmt_count / 2;
2135
/* There was a parameter mismatch hence can't depend upon the format's
2136
fmt_count. Use count instead.
2140
jrd_nod* list = *parameter_ptr = PAR_make_node(tdbb, n);
2141
list->nod_type = nod_list;
2142
list->nod_count = n;
2143
jrd_nod** ptr = list->nod_arg;
2144
USHORT asgn_arg1, asgn_arg2;
2146
asgn_arg1 = e_asgn_from;
2147
asgn_arg2 = e_asgn_to;
2150
asgn_arg1 = e_asgn_to;
2151
asgn_arg2 = e_asgn_from;
2153
for (USHORT i = 0; n; count--, n--) {
2154
jrd_nod* asgn = PAR_make_node(tdbb, e_asgn_length);
2156
asgn->nod_type = nod_assignment;
2157
asgn->nod_count = count_table[blr_assignment];
2159
// default value for parameter
2160
if ((count <= 0) && input_flag) {
2161
Parameter* parameter =
2162
(*procedure->prc_input_fields)[procedure->prc_inputs - n];
2163
asgn->nod_arg[asgn_arg1] = parameter->prm_default_value;
2166
asgn->nod_arg[asgn_arg1] = parse(tdbb, csb, VALUE);
2168
jrd_nod* prm = asgn->nod_arg[asgn_arg2] =
2169
PAR_make_node(tdbb, e_arg_length);
2170
prm->nod_type = nod_argument;
2172
prm->nod_arg[e_arg_message] = message;
2173
prm->nod_arg[e_arg_number] = (jrd_nod*)(IPTR) i++;
2174
jrd_nod* prm_f = prm->nod_arg[e_arg_flag] =
2175
PAR_make_node(tdbb, e_arg_length);
2176
prm_f->nod_type = nod_argument;
2177
prm_f->nod_count = 0;
2178
prm_f->nod_arg[e_arg_message] = message;
2179
prm_f->nod_arg[e_arg_number] = (jrd_nod*)(IPTR) i++;
2182
else if ((input_flag ? procedure->prc_inputs : procedure->prc_outputs) &&
2186
input_flag ? isc_prcmismat : isc_prc_out_param_mismatch,
2188
ERR_cstring(procedure->prc_name.c_str()),
2194
static jrd_nod* par_relation(
2196
CompilerScratch* csb, SSHORT blr_operator, bool parse_context)
2198
/**************************************
2200
* p a r _ r e l a t i o n
2202
**************************************
2204
* Functional description
2205
* Parse a relation reference.
2207
**************************************/
2208
Firebird::MetaName name;
2212
/* Make a relation reference node */
2214
jrd_nod* node = PAR_make_node(tdbb, e_rel_length);
2215
node->nod_count = 0;
2217
/* Find relation either by id or by name */
2218
jrd_rel* relation = 0;
2219
Firebird::string* alias_string = 0;
2220
if (blr_operator == blr_rid || blr_operator == blr_rid2) {
2221
const SSHORT id = BLR_WORD;
2222
if (blr_operator == blr_rid2) {
2223
alias_string = FB_NEW(csb->csb_pool) Firebird::string(csb->csb_pool);
2224
par_name(csb, *alias_string);
2226
if (!(relation = MET_lookup_relation_id(tdbb, id, false))) {
2227
name.printf("id %d", id);
2228
error(csb, isc_relnotdef, isc_arg_string, ERR_cstring(name), 0);
2231
else if (blr_operator == blr_relation || blr_operator == blr_relation2) {
2232
par_name(csb, name);
2233
if (blr_operator == blr_relation2) {
2234
alias_string = FB_NEW(csb->csb_pool) Firebird::string(csb->csb_pool);
2235
par_name(csb, *alias_string);
2237
if (!(relation = MET_lookup_relation(tdbb, name)))
2238
error(csb, isc_relnotdef, isc_arg_string, ERR_cstring(name), 0);
2241
/* if an alias was passed, store with the relation */
2245
node->nod_arg[e_rel_alias] =
2246
(jrd_nod*) stringDup(*tdbb->getDefaultPool(), alias_string->c_str());
2249
/* Scan the relation if it hasn't already been scanned for meta data */
2251
if ((!(relation->rel_flags & REL_scanned)
2252
|| (relation->rel_flags & REL_being_scanned))
2253
&& ((relation->rel_flags & REL_force_scan)
2254
|| !(csb->csb_g_flags & csb_internal)))
2256
relation->rel_flags &= ~REL_force_scan;
2257
MET_scan_relation(tdbb, relation);
2259
else if (relation->rel_flags & REL_sys_triggers)
2261
MET_parse_sys_trigger(tdbb, relation);
2264
/* generate a stream for the relation reference,
2265
assuming it is a real reference */
2267
if (parse_context) {
2269
const SSHORT stream = par_context(csb, &context);
2270
fb_assert(stream <= MAX_STREAMS);
2271
node->nod_arg[e_rel_stream] = (jrd_nod*) (IPTR) stream;
2272
node->nod_arg[e_rel_context] = (jrd_nod*) (IPTR) context;
2274
csb->csb_rpt[stream].csb_relation = relation;
2275
csb->csb_rpt[stream].csb_alias = alias_string;
2277
if (csb->csb_g_flags & csb_get_dependencies)
2278
par_dependency(tdbb, csb, stream, (SSHORT) -1, "");
2282
delete alias_string;
2285
node->nod_arg[e_rel_relation] = (jrd_nod*) relation;
2291
static jrd_nod* par_rse(thread_db* tdbb, CompilerScratch* csb, SSHORT rse_op)
2293
/**************************************
2297
**************************************
2299
* Functional description
2300
* Parse a record selection expression.
2302
**************************************/
2305
SSHORT count = (unsigned int) BLR_BYTE;
2306
RecordSelExpr* rse = (RecordSelExpr*) PAR_make_node(tdbb, count + rse_delta + 2);
2308
rse->rse_count = count;
2309
jrd_nod** ptr = rse->rse_relation;
2311
while (--count >= 0) {
2312
// AB: Added TYPE_RSE for derived table support
2313
*ptr++ = parse(tdbb, csb, RELATION, TYPE_RSE);
2314
//*ptr++ = parse(tdbb, csb, RELATION);
2318
const UCHAR op = BLR_BYTE;
2321
rse->rse_boolean = parse(tdbb, csb, TYPE_BOOL);
2325
if (rse_op == blr_rs_stream)
2326
syntax_error(csb, "RecordSelExpr stream clause");
2327
rse->rse_first = parse(tdbb, csb, VALUE);
2331
if (rse_op == blr_rs_stream)
2332
syntax_error (csb, "RecordSelExpr stream clause");
2333
rse->rse_skip = parse (tdbb, csb, VALUE);
2337
if (rse_op == blr_rs_stream)
2338
syntax_error(csb, "RecordSelExpr stream clause");
2339
rse->rse_sorted = par_sort(tdbb, csb, true);
2343
if (rse_op == blr_rs_stream)
2344
syntax_error(csb, "RecordSelExpr stream clause");
2345
rse->rse_projection = par_sort(tdbb, csb, false);
2350
const USHORT jointype = (USHORT) BLR_BYTE;
2351
rse->rse_jointype = jointype;
2352
if (jointype != blr_inner
2353
&& jointype != blr_left && jointype != blr_right
2354
&& jointype != blr_full)
2356
syntax_error(csb, "join type clause");
2362
rse->rse_plan = par_plan(tdbb, csb);
2366
rse->rse_writelock = true;
2369
#ifdef SCROLLABLE_CURSORS
2370
/* if a receive is seen here, then it is intended to be an asynchronous
2371
receive which can happen at any time during the scope of the RecordSelExpr--
2372
this is intended to be a more efficient mechanism for scrolling through
2373
a record stream, to prevent having to send a message to the engine
2378
rse->rse_async_message = parse(tdbb, csb, STATEMENT);
2383
if (op == (UCHAR) blr_end) {
2384
/* An outer join is only allowed when the stream count is 2
2385
and a boolean expression has been supplied */
2387
if (!rse->rse_jointype ||
2388
(rse->rse_count == 2 && rse->rse_boolean))
2390
// Convert right outer joins to left joins to avoid
2391
// RIGHT JOIN handling at lower engine levels
2392
if (rse->rse_jointype == blr_right) {
2394
jrd_nod* temp = rse->rse_relation[0];
2395
rse->rse_relation[0] = rse->rse_relation[1];
2396
rse->rse_relation[1] = temp;
2398
rse->rse_jointype = blr_left;
2400
return (jrd_nod*) rse;
2403
syntax_error(csb, (TEXT*)((rse_op == blr_rs_stream) ?
2404
"RecordSelExpr stream clause" :
2405
"record selection expression clause"));
2411
static jrd_nod* par_sort(thread_db* tdbb, CompilerScratch* csb, bool flag)
2413
/**************************************
2417
**************************************
2419
* Functional description
2420
* Parse a sort clause (sans header byte). This is used for
2421
* BLR_SORT, BLR_PROJECT, and BLR_GROUP.
2423
**************************************/
2426
SSHORT count = (unsigned int) BLR_BYTE;
2427
jrd_nod* clause = PAR_make_node(tdbb, count * 3);
2428
clause->nod_type = nod_sort;
2429
clause->nod_count = count;
2430
jrd_nod** ptr = clause->nod_arg;
2431
jrd_nod** ptr2 = ptr + count;
2432
jrd_nod** ptr3 = ptr2 + count;
2434
while (--count >= 0) {
2436
UCHAR code = BLR_BYTE;
2438
case blr_nullsfirst:
2439
*ptr3++ = (jrd_nod*) (IPTR) rse_nulls_first;
2443
*ptr3++ = (jrd_nod*) (IPTR) rse_nulls_last;
2447
*ptr3++ = (jrd_nod*) (IPTR) rse_nulls_default;
2451
(jrd_nod*) (IPTR) ((code == blr_descending) ? TRUE : FALSE);
2453
*ptr++ = parse(tdbb, csb, VALUE);
2460
#ifdef NOT_USED_OR_REPLACED
2461
static jrd_nod* par_stream(thread_db* tdbb, CompilerScratch* csb)
2463
/**************************************
2465
* p a r _ s t r e a m
2467
**************************************
2469
* Functional description
2470
* Parse a stream expression.
2472
**************************************/
2475
RecordSelExpr* rse = (RecordSelExpr*) PAR_make_node(tdbb, 1 + rse_delta + 2);
2478
rse->rse_relation[0] = parse(tdbb, csb, RELATION);
2481
const UCHAR op = BLR_BYTE;
2484
rse->rse_boolean = parse(tdbb, csb, TYPE_BOOL);
2488
if (op == (UCHAR) blr_end)
2489
return (jrd_nod*) rse;
2490
syntax_error(csb, "stream_clause");
2497
static jrd_nod* par_sys_function(thread_db* tdbb, CompilerScratch* csb)
2499
/**************************************
2501
* p a r _ s y s _ f u n c t i o n
2503
**************************************
2505
* Functional description
2506
* Parse a system function reference.
2508
**************************************/
2511
Firebird::MetaName name;
2512
const USHORT count = par_name(csb, name);
2514
const SysFunction* function = SysFunction::lookup(name);
2518
csb->csb_running -= count;
2519
error(csb, isc_funnotdef, isc_arg_string, ERR_cstring(name), 0);
2522
jrd_nod* node = PAR_make_node(tdbb, e_sysfun_length);
2523
node->nod_count = count_table[blr_sys_function];
2524
node->nod_arg[e_sysfun_args] = par_args(tdbb, csb, VALUE);
2525
node->nod_arg[e_sysfun_function] = (jrd_nod*) function;
2531
static jrd_nod* par_union(thread_db* tdbb, CompilerScratch* csb, bool recursive)
2533
/**************************************
2537
**************************************
2539
* Functional description
2540
* Parse a union reference.
2542
**************************************/
2545
/* Make the node, parse the context number, get a stream assigned,
2546
and get the number of sub-RecordSelExpr's. */
2548
jrd_nod* node = PAR_make_node(tdbb, e_uni_length);
2549
node->nod_count = 3;
2550
const USHORT stream = par_context(csb, 0);
2551
node->nod_arg[e_uni_stream] = (jrd_nod*) (IPTR) stream;
2553
// assign separate context for mapped record if union is recursive
2554
USHORT map_stream = stream;
2557
node->nod_flags |= nod_recurse;
2558
map_stream = par_context(csb, 0);
2559
node->nod_arg[e_uni_map_stream] = (jrd_nod*) (IPTR) map_stream;
2562
SSHORT count = (unsigned int) BLR_BYTE;
2564
/* Pick up the sub-RecordSelExpr's and maps */
2568
while (--count >= 0) {
2569
clauses.push(parse(tdbb, csb, TYPE_RSE));
2570
clauses.push(par_map(tdbb, csb, map_stream));
2573
node->nod_arg[e_uni_clauses] = PAR_make_list(tdbb, clauses);
2579
static USHORT par_word(CompilerScratch* csb)
2581
/**************************************
2585
**************************************
2587
* Functional description
2588
* Pick up a BLR word.
2590
**************************************/
2591
const UCHAR low = BLR_BYTE;
2592
const UCHAR high = BLR_BYTE;
2594
return high * 256 + low;
2598
static jrd_nod* parse(thread_db* tdbb, CompilerScratch* csb, USHORT expected,
2599
USHORT expected_optional)
2601
/**************************************
2605
**************************************
2607
* Functional description
2608
* Parse a BLR expression.
2610
**************************************/
2613
const USHORT blr_offset = csb->csb_running - csb->csb_blr;
2614
const SSHORT blr_operator = BLR_BYTE;
2616
if (blr_operator < 0 || blr_operator >= FB_NELEM(type_table)) {
2617
// NS: This error string is correct, please do not mangle it again and again.
2618
// The whole error message is "BLR syntax error: expected %s at offset %d, encountered %d"
2619
syntax_error(csb, "valid BLR code");
2622
const SSHORT sub_type = sub_type_table[blr_operator];
2624
if (expected && (expected != type_table[blr_operator])) {
2625
if (expected_optional) {
2626
if (expected_optional != type_table[blr_operator]) {
2627
syntax_error(csb, elements[expected]);
2631
syntax_error(csb, elements[expected]);
2635
/* If there is a length given in the length table, pre-allocate
2636
the node and set its count. This saves an enormous amount of
2641
USHORT n = length_table[blr_operator];
2643
node = PAR_make_node(tdbb, n);
2644
node->nod_count = count_table[blr_operator];
2645
arg = node->nod_arg;
2652
bool set_type = true;
2654
/* Dispatch on operator type. */
2656
switch (blr_operator) {
2662
node->nod_arg[e_any_rse] = parse(tdbb, csb, sub_type);
2665
/* Boring operators -- no special handling req'd */
2671
*arg++ = parse(tdbb, csb, sub_type);
2672
*arg++ = parse(tdbb, csb, sub_type);
2673
*arg++ = parse(tdbb, csb, sub_type);
2678
node->nod_count = e_trim_count;
2679
node->nod_arg[e_trim_specification] = (jrd_nod*)(U_IPTR) BLR_BYTE;
2681
BYTE trimWhat = BLR_BYTE;
2683
if (trimWhat == blr_trim_characters)
2684
node->nod_arg[e_trim_characters] = parse(tdbb, csb, sub_type);
2687
node->nod_arg[e_trim_characters] = NULL;
2691
node->nod_arg[e_trim_value] = parse(tdbb, csb, sub_type);
2699
case blr_containing:
2707
case blr_concatenate:
2709
case blr_assignment:
2710
*arg++ = parse(tdbb, csb, sub_type);
2716
case blr_lock_state:
2722
case blr_agg_count2:
2726
case blr_agg_average:
2727
case blr_agg_count_distinct:
2728
case blr_agg_total_distinct:
2729
case blr_agg_average_distinct:
2731
case blr_internal_info:
2732
*arg++ = parse(tdbb, csb, sub_type);
2736
case blr_agg_list_distinct:
2737
*arg++ = parse(tdbb, csb, sub_type);
2738
*arg++ = parse(tdbb, csb, VALUE);
2742
*arg++ = parse(tdbb, csb, sub_type);
2746
n = BLR_WORD + 2; // e_exec_into_count - 1
2747
node = PAR_make_node(tdbb, n);
2748
arg = node->nod_arg;
2749
*arg++ = parse(tdbb, csb, VALUE);
2750
if (BLR_BYTE) // singleton
2753
*arg++ = parse(tdbb, csb, STATEMENT);
2754
for (n = 2/*e_exec_into_list*/; n < node->nod_count; n++)
2755
*arg++ = parse(tdbb, csb, VALUE);
2759
*arg++ = parse(tdbb, csb, sub_type);
2760
*arg++ = parse(tdbb, csb, sub_type);
2766
case blr_current_role:
2767
case blr_current_date:
2768
case blr_start_savepoint:
2769
case blr_end_savepoint:
2772
case blr_current_time:
2773
node->nod_arg[0] = (jrd_nod*) (IPTR) DEFAULT_TIME_PRECISION;
2776
case blr_current_timestamp:
2777
node->nod_arg[0] = (jrd_nod*) (IPTR) DEFAULT_TIMESTAMP_PRECISION;
2780
case blr_current_time2:
2781
case blr_current_timestamp2:
2783
if (n > MAX_TIME_PRECISION) {
2784
ERR_post(isc_invalid_time_precision,
2785
isc_arg_number, MAX_TIME_PRECISION, 0);
2787
node->nod_arg[0] = (jrd_nod*) (IPTR) n;
2790
case blr_user_savepoint:
2792
*arg++ = (jrd_nod*) (IPTR) BLR_BYTE;
2793
Firebird::MetaName name;
2794
par_name(csb, name);
2795
*arg++ = (jrd_nod*) stringDup(*tdbb->getDefaultPool(), name.c_str());
2801
node->nod_arg[e_sto_relation] = parse(tdbb, csb, RELATION);
2802
node->nod_arg[e_sto_statement] = parse(tdbb, csb, sub_type);
2803
if (blr_operator == blr_store2)
2804
node->nod_arg[e_sto_statement2] = parse(tdbb, csb, sub_type);
2807
/* Comparison operators */
2810
*arg++ = parse(tdbb, csb, sub_type);
2819
*arg++ = parse(tdbb, csb, sub_type);
2820
*arg++ = parse(tdbb, csb, sub_type);
2821
node->nod_flags = nod_comparison;
2826
if (n >= csb->csb_rpt.getCount() || !(csb->csb_rpt[n].csb_flags & csb_used))
2827
error(csb, isc_ctxnotdef, 0);
2828
node->nod_arg[e_erase_stream] =
2829
(jrd_nod*) (IPTR) csb->csb_rpt[n].csb_stream;
2834
node = par_modify(tdbb, csb, blr_operator);
2839
node = par_exec_proc(tdbb, csb, blr_operator);
2844
node = par_procedure(tdbb, csb, blr_operator);
2848
node = par_function(tdbb, csb);
2852
node->nod_arg[0] = parse(tdbb, csb, sub_type);
2853
node->nod_arg[1] = par_args(tdbb, csb, sub_type);
2857
if (BLR_PEEK == (UCHAR) blr_stall)
2858
node->nod_arg[e_for_stall] = parse(tdbb, csb, STATEMENT);
2860
if (BLR_PEEK == (UCHAR) blr_rse ||
2861
BLR_PEEK == (UCHAR) blr_singular)
2862
node->nod_arg[e_for_re] = parse(tdbb, csb, TYPE_RSE);
2864
node->nod_arg[e_for_re] = par_rse(tdbb, csb, blr_operator);
2865
node->nod_arg[e_for_statement] = parse(tdbb, csb, sub_type);
2868
case blr_dcl_cursor:
2870
node->nod_arg[e_dcl_cursor_number] = (jrd_nod*) (IPTR) BLR_WORD;
2871
node->nod_arg[e_dcl_cursor_rse] = parse(tdbb, csb, TYPE_RSE);
2873
jrd_nod* temp = PAR_make_node(tdbb, n);
2874
temp->nod_type = nod_list;
2875
for (jrd_nod** ptr = temp->nod_arg; n; n--) {
2876
*ptr++ = parse(tdbb, csb, VALUE);
2878
node->nod_arg[e_dcl_cursor_refs] = temp;
2882
case blr_cursor_stmt:
2884
node->nod_arg[e_cursor_stmt_op] = (jrd_nod*) (IPTR) n;
2885
node->nod_arg[e_cursor_stmt_number] = (jrd_nod*) (IPTR) BLR_WORD;
2887
case blr_cursor_open:
2888
case blr_cursor_close:
2890
case blr_cursor_fetch:
2891
#ifdef SCROLLABLE_CURSORS
2892
if (BLR_PEEK == blr_seek)
2893
node->nod_arg[e_cursor_stmt_seek] = parse(tdbb, csb, STATEMENT);
2895
csb->csb_g_flags |= csb_reuse_context;
2896
node->nod_arg[e_cursor_stmt_into] = parse(tdbb, csb, STATEMENT);
2897
csb->csb_g_flags &= ~csb_reuse_context;
2900
syntax_error(csb, "cursor operation clause");
2906
node = par_rse(tdbb, csb, blr_operator);
2910
node = parse(tdbb, csb, TYPE_RSE);
2911
((RecordSelExpr*) node)->nod_flags |= rse_singular;
2918
node = par_relation(tdbb, csb, blr_operator, true);
2922
node = par_union(tdbb, csb, false);
2926
node = par_union(tdbb, csb, true);
2930
node->nod_arg[e_agg_stream] = (jrd_nod*) (IPTR) par_context(csb, 0);
2931
fb_assert((int) (IPTR)node->nod_arg[e_agg_stream] <= MAX_STREAMS);
2932
node->nod_arg[e_agg_rse] = parse(tdbb, csb, TYPE_RSE);
2933
node->nod_arg[e_agg_group] = parse(tdbb, csb, OTHER);
2934
node->nod_arg[e_agg_map] =
2935
par_map(tdbb, csb, (USHORT)(IPTR) node->nod_arg[e_agg_stream]);
2939
node = par_sort(tdbb, csb, false);
2940
return (node->nod_count) ? node : NULL;
2944
node = par_field(tdbb, csb, blr_operator);
2945
if (node->nod_type == nod_domain_validation || node->nod_type == nod_null)
2946
set_type = false; // to not change nod->nod_type to nod_field
2950
case blr_set_generator:
2952
Firebird::MetaName name;
2954
par_name(csb, name);
2955
const SLONG tmp = MET_lookup_generator(tdbb, name.c_str());
2957
error(csb, isc_gennotdef,
2958
isc_arg_string, ERR_cstring(name), 0);
2960
node->nod_arg[e_gen_relation] = (jrd_nod*) (IPTR) tmp;
2961
node->nod_arg[e_gen_value] = parse(tdbb, csb, VALUE);
2963
/* CVC: There're thousand ways to go wrong, but I don't see any value
2964
in posting dependencies with set generator since it's DDL, so I will
2965
track only gen_id() in both dialects. */
2966
if ((blr_operator == blr_gen_id)
2967
&& (csb->csb_g_flags & csb_get_dependencies))
2969
jrd_nod* dep_node = PAR_make_node (tdbb, e_dep_length);
2970
dep_node->nod_type = nod_dependency;
2971
dep_node->nod_arg [e_dep_object] = (jrd_nod*) (IPTR) tmp;
2972
dep_node->nod_arg [e_dep_object_type] = (jrd_nod*)(IPTR) obj_generator;
2973
csb->csb_dependencies.push(dep_node);
2979
case blr_record_version:
2982
if (n >= csb->csb_rpt.getCount() || !(csb->csb_rpt[n].csb_flags & csb_used))
2983
error(csb, isc_ctxnotdef, 0);
2984
node->nod_arg[0] = (jrd_nod*) (IPTR) csb->csb_rpt[n].csb_stream;
2988
par_fetch(tdbb, csb, node);
2994
node->nod_arg[e_send_message] = csb->csb_rpt[n].csb_message;
2995
node->nod_arg[e_send_statement] = parse(tdbb, csb, sub_type);
2999
node = par_message(tdbb, csb);
3003
node = par_literal(tdbb, csb);
3007
node = par_cast(tdbb, csb);
3011
// This forced conversion looks strange, but extract_part fits in a byte
3012
node->nod_arg[e_extract_part] = (jrd_nod*)(U_IPTR) BLR_BYTE;
3013
node->nod_arg[e_extract_value] = parse(tdbb, csb, sub_type);
3014
node->nod_count = e_extract_count;
3018
// This forced conversion looks strange, but length_type fits in a byte
3019
node->nod_arg[e_strlen_type] = (jrd_nod*)(U_IPTR) BLR_BYTE;
3020
node->nod_arg[e_strlen_value] = parse(tdbb, csb, sub_type);
3021
node->nod_count = e_strlen_count;
3024
case blr_dcl_variable:
3026
dsc* desc = (dsc*) (node->nod_arg + e_dcl_desc);
3031
node->nod_arg[e_dcl_id] = (jrd_nod*) (IPTR) n;
3032
PAR_desc(tdbb, csb, desc, &itemInfo);
3033
vec<jrd_nod*>* vector = csb->csb_variables =
3034
vec<jrd_nod*>::newVector(*tdbb->getDefaultPool(), csb->csb_variables, n + 1);
3035
(*vector)[n] = node;
3037
if (itemInfo.isSpecial())
3039
csb->csb_dbg_info.varIndexToName.get(n, itemInfo.name);
3040
csb->csb_map_item_info.put(Item(nod_variable, n), itemInfo);
3043
if (itemInfo.explicitCollation)
3045
jrd_nod* dep_node = PAR_make_node (tdbb, e_dep_length);
3046
dep_node->nod_type = nod_dependency;
3047
dep_node->nod_arg [e_dep_object] = (jrd_nod*)(IPTR) INTL_TEXT_TYPE(*desc);
3048
dep_node->nod_arg [e_dep_object_type] = (jrd_nod*)(IPTR) obj_collation;
3049
csb->csb_dependencies.push(dep_node);
3057
node->nod_arg[e_var_id] = (jrd_nod*) (IPTR) n;
3058
vec<jrd_nod*>* vector = csb->csb_variables;
3059
if (!vector || n >= vector->count() ||
3060
!(node->nod_arg[e_var_variable] = (*vector)[n]))
3062
syntax_error(csb, "variable identifier");
3068
case blr_parameter2:
3069
case blr_parameter3:
3072
n = (USHORT) BLR_BYTE;
3073
if (n >= csb->csb_rpt.getCount() ||
3074
!(message = csb->csb_rpt[n].csb_message))
3076
error(csb, isc_badmsgnum, 0);
3078
node->nod_arg[e_arg_message] = message;
3080
node->nod_arg[e_arg_number] = (jrd_nod*) (IPTR) n;
3081
const Format* format = (Format*) message->nod_arg[e_msg_format];
3082
if (n >= format->fmt_count)
3083
error(csb, isc_badparnum, 0);
3084
if (blr_operator != blr_parameter) {
3085
jrd_nod* temp = PAR_make_node(tdbb, e_arg_length);
3086
node->nod_arg[e_arg_flag] = temp;
3087
node->nod_count = 1;
3088
temp->nod_count = 0;
3089
temp->nod_type = nod_argument;
3090
temp->nod_arg[e_arg_message] = message;
3092
temp->nod_arg[e_arg_number] = (jrd_nod*) (IPTR) n;
3093
if (n >= format->fmt_count)
3094
error(csb, isc_badparnum, 0);
3096
if (blr_operator == blr_parameter3) {
3097
jrd_nod* temp = PAR_make_node(tdbb, e_arg_length);
3098
node->nod_arg[e_arg_indicator] = temp;
3099
node->nod_count = 2;
3100
temp->nod_count = 0;
3101
temp->nod_type = nod_argument;
3102
temp->nod_arg[e_arg_message] = message;
3104
temp->nod_arg[e_arg_number] = (jrd_nod*) (IPTR) n;
3105
if (n >= format->fmt_count)
3106
error(csb, isc_badparnum, 0);
3119
while (BLR_PEEK != (UCHAR) blr_end) {
3120
if (blr_operator == blr_select && BLR_PEEK != blr_receive)
3121
syntax_error(csb, "blr_receive");
3122
stack.push(parse(tdbb, csb, sub_type));
3124
BLR_BYTE; // skip blr_end
3125
node = PAR_make_list(tdbb, stack);
3133
node->nod_arg[e_blk_action] = parse(tdbb, csb, sub_type);
3134
while (BLR_PEEK != (UCHAR) blr_end)
3136
stack.push(parse(tdbb, csb, sub_type));
3138
BLR_BYTE; // skip blr_end
3139
node->nod_arg[e_blk_handlers] = PAR_make_list(tdbb, stack);
3143
case blr_error_handler:
3144
node->nod_arg[e_err_conditions] = (jrd_nod*) par_conditions(tdbb, csb);
3145
node->nod_arg[e_err_action] = parse(tdbb, csb, sub_type);
3150
const bool flag = (BLR_PEEK == blr_exception_msg);
3151
node->nod_arg[e_xcp_desc] = (jrd_nod*) par_condition(tdbb, csb);
3154
node->nod_arg[e_xcp_msg] = parse(tdbb, csb, sub_type);
3160
node->nod_arg[e_if_boolean] = parse(tdbb, csb, TYPE_BOOL);
3161
node->nod_arg[e_if_true] = parse(tdbb, csb, sub_type);
3162
if (BLR_PEEK == (UCHAR) blr_end) {
3163
node->nod_count = 2;
3164
BLR_BYTE; // skip blr_end
3167
node->nod_arg[e_if_false] = parse(tdbb, csb, sub_type);
3171
node->nod_arg[e_lbl_label] = (jrd_nod*) (IPTR) BLR_BYTE;
3172
node->nod_arg[e_lbl_statement] = parse(tdbb, csb, sub_type);
3176
node->nod_arg[0] = (jrd_nod*) (IPTR) BLR_BYTE;
3190
node->nod_arg[e_stat_rse] = parse(tdbb, csb, TYPE_RSE);
3191
if (blr_operator != blr_count)
3192
node->nod_arg[e_stat_value] = parse(tdbb, csb, VALUE);
3193
if (blr_operator == blr_via)
3194
node->nod_arg[e_stat_default] = parse(tdbb, csb, VALUE);
3197
#ifdef SCROLLABLE_CURSORS
3199
node->nod_arg[e_seek_direction] = parse(tdbb, csb, VALUE);
3200
node->nod_arg[e_seek_offset] = parse(tdbb, csb, VALUE);
3204
case blr_init_variable:
3207
node->nod_arg[e_init_var_id] = (jrd_nod*)(U_IPTR) n;
3208
vec<jrd_nod*>* vector = csb->csb_variables;
3209
if (!vector || n >= vector->count() ||
3210
!(node->nod_arg[e_init_var_variable] = (*vector)[n]))
3212
syntax_error(csb, "variable identifier");
3217
case blr_sys_function:
3218
node = par_sys_function(tdbb, csb);
3222
syntax_error(csb, elements[expected]);
3227
if (csb->csb_g_flags & csb_blr_version4)
3228
node->nod_type = (NOD_T) (USHORT) blr_table4[(int) blr_operator];
3230
node->nod_type = (NOD_T) (USHORT) blr_table[(int) blr_operator];
3234
if (csb->csb_dbg_info.blrToSrc.find(blr_offset, pos))
3236
Firebird::MapBlrToSrcItem& i = csb->csb_dbg_info.blrToSrc[pos];
3237
jrd_nod* node_src = PAR_make_node(tdbb, e_src_info_length);
3239
node_src->nod_type = nod_src_info;
3240
node_src->nod_arg[e_src_info_line] = (jrd_nod*) (IPTR) i.mbs_src_line;
3241
node_src->nod_arg[e_src_info_col] = (jrd_nod*) (IPTR) i.mbs_src_col;
3242
node_src->nod_arg[e_src_info_node] = node;
3251
static void syntax_error(CompilerScratch* csb, const TEXT* string)
3253
/**************************************
3255
* s y n t a x _ e r r o r
3257
**************************************
3259
* Functional description
3260
* Post a syntax error message.
3262
**************************************/
3264
error(csb, isc_syntaxerr,
3265
isc_arg_string, string,
3266
isc_arg_number, (SLONG) (csb->csb_running - csb->csb_blr - 1),
3267
isc_arg_number, (SLONG) csb->csb_running[-1], 0);
3271
static void warning(CompilerScratch* csb, ...)
3273
/**************************************
3277
**************************************
3279
* Functional description
3280
* This is for GBAK so that we can pass warning messages
3281
* back to the client. DO NOT USE this function until we
3282
* fully implement warning at the engine level.
3284
* We will use the status vector like a warning vector. What
3285
* we are going to do is leave the [1] position of the vector
3286
* as 0 so that this will not be treated as an error, and we
3287
* will place our warning message in the consecutive positions.
3288
* It will be up to the caller to check these positions for
3291
**************************************/
3296
thread_db* tdbb = JRD_get_thread_data();
3298
va_start(args, csb);
3300
p = tdbb->tdbb_status_vector;
3302
/* Make sure that the [1] position is 0
3303
indicating that no error has occured */
3308
/* Now place your warning messages starting
3309
with position [2] */
3312
*p++ = va_arg(args, ISC_STATUS);
3314
/* Pick up remaining args */
3316
while ( (*p++ = type = va_arg(args, int)) )
3320
*p++ = (ISC_STATUS) va_arg(args, ISC_STATUS);
3323
case isc_arg_string:
3324
case isc_arg_interpreted:
3325
*p++ = (ISC_STATUS) va_arg(args, TEXT *);
3328
case isc_arg_cstring:
3329
*p++ = (ISC_STATUS) va_arg(args, int);
3330
*p++ = (ISC_STATUS) va_arg(args, TEXT *);
3333
case isc_arg_number:
3334
*p++ = (ISC_STATUS) va_arg(args, SLONG);
3342
*p++ = va_arg(args, int);