2
* PROGRAM: Dynamic SQL runtime support
4
* DESCRIPTION: Routines to generate BLR.
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): ______________________________________
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
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"
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);
90
// STUFF is defined in dsql.h for use in common with ddl.c
92
// The following are passed as the third argument to gen_constant
93
const bool NEGATE_VALUE = true;
94
const bool USE_VALUE = false;
101
@brief Generate blr for an arbitrary expression.
108
void GEN_expr( dsql_req* request, dsql_nod* node)
116
switch (node->nod_type) {
118
GEN_expr(request, node->nod_arg[e_alias_value]);
122
gen_aggregate(request, node);
126
gen_constant(request, node, USE_VALUE);
129
case nod_derived_field:
130
GEN_expr(request, node->nod_arg[e_derived_field_value]);
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]);
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]);
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);
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);
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))
165
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 901,
166
isc_arg_gds, isc_dsql_domain_err, 0);
168
stuff(request, blr_fid);
169
stuff(request, 0); // Context
170
stuff_word(request, 0); // Field id
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]);
181
stuff(request, blr_user_name);
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);
193
stuff(request, blr_current_time);
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);
206
stuff(request, blr_current_timestamp);
210
case nod_current_date:
211
stuff(request, blr_current_date);
214
case nod_current_role:
215
stuff(request, blr_current_role);
219
gen_udf(request, node);
222
case nod_sys_function:
223
gen_sys_function(request, node);
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);
235
stuff(request, blr_variable);
236
stuff_word(request, variable->var_variable_number);
241
gen_join_rse(request, node);
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);
253
gen_parameter(request, (dsql_par*) node->nod_arg[e_par_parameter]);
257
gen_relation(request, (dsql_ctx*) node->nod_arg[e_rel_context]);
261
gen_rse(request, node);
264
case nod_derived_table:
265
gen_rse(request, node->nod_arg[e_derived_table_rse]);
269
stuff(request, blr_any);
270
gen_rse(request, node->nod_arg[0]);
274
stuff(request, blr_unique);
275
gen_rse(request, node->nod_arg[0]);
280
blr_operator = (node->nod_flags & NOD_AGG_DISTINCT) ?
281
blr_agg_count_distinct : blr_agg_count2;
283
blr_operator = blr_agg_count;
287
blr_operator = blr_agg_min;
290
blr_operator = blr_agg_max;
293
case nod_agg_average:
294
blr_operator = (node->nod_flags & NOD_AGG_DISTINCT) ?
295
blr_agg_average_distinct : blr_agg_average;
299
blr_operator = (node->nod_flags & NOD_AGG_DISTINCT) ?
300
blr_agg_total_distinct : blr_agg_total;
303
case nod_agg_average2:
304
blr_operator = (node->nod_flags & NOD_AGG_DISTINCT) ?
305
blr_agg_average_distinct : blr_agg_average;
309
blr_operator = (node->nod_flags & NOD_AGG_DISTINCT) ?
310
blr_agg_total_distinct : blr_agg_total;
314
blr_operator = (node->nod_flags & NOD_AGG_DISTINCT) ?
315
blr_agg_list_distinct : blr_agg_list;
319
blr_operator = blr_and;
322
blr_operator = blr_or;
325
blr_operator = blr_not;
330
blr_operator = blr_eql;
333
blr_operator = blr_equiv;
338
blr_operator = blr_neq;
343
blr_operator = blr_gtr;
348
blr_operator = blr_leq;
353
blr_operator = blr_geq;
358
blr_operator = blr_lss;
361
blr_operator = blr_between;
364
blr_operator = blr_containing;
367
blr_operator = blr_starting;
370
blr_operator = blr_missing;
374
blr_operator = (node->nod_count == 2) ? blr_like : blr_ansi_like;
378
blr_operator = blr_add;
381
blr_operator = blr_subtract;
384
blr_operator = blr_multiply;
389
dsql_nod* child = node->nod_arg[0];
390
if (child->nod_type == nod_constant &&
391
DTYPE_IS_NUMERIC(child->nod_desc.dsc_dtype))
393
gen_constant(request, child, NEGATE_VALUE);
397
blr_operator = blr_negate;
401
blr_operator = blr_divide;
404
blr_operator = blr_add;
407
blr_operator = blr_subtract;
410
blr_operator = blr_multiply;
413
blr_operator = blr_divide;
415
case nod_concatenate:
416
blr_operator = blr_concatenate;
419
blr_operator = blr_null;
422
blr_operator = blr_any;
425
blr_operator = blr_ansi_any;
428
blr_operator = blr_ansi_all;
431
blr_operator = blr_via;
434
case nod_internal_info:
435
blr_operator = blr_internal_info;
438
blr_operator = blr_upcase;
441
blr_operator = blr_lowcase;
444
blr_operator = blr_substring;
447
gen_cast(request, node);
451
gen_gen_id(request, node);
454
gen_coalesce(request, node);
456
case nod_simple_case:
457
gen_simple_case(request, node);
459
case nod_searched_case:
460
gen_searched_case(request, node);
468
switch (node->nod_type) {
470
blr_operator = blr_average;
473
// blr_operator = blr_count;
475
// blr_operator = node->nod_arg[0]->nod_arg[e_rse_items] ? blr_count2 : blr_count;
479
blr_operator = blr_from;
482
blr_operator = blr_maximum;
485
blr_operator = blr_minimum;
488
blr_operator = blr_total;
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]);
502
stuff(request, blr_trim);
503
stuff(request, node->nod_arg[e_trim_specification]->getSlong());
505
if (node->nod_arg[e_trim_characters])
507
stuff(request, blr_trim_characters);
508
GEN_expr(request, node->nod_arg[e_trim_characters]);
511
stuff(request, blr_trim_spaces);
513
GEN_expr(request, node->nod_arg[e_trim_value]);
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
524
stuff(request, blr_operator);
526
dsql_nod* const* ptr = node->nod_arg;
527
for (const dsql_nod* const* const end = ptr + node->nod_count;
530
GEN_expr(request, *ptr);
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. */
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)
549
MAKE_desc(request, &desc, node, NULL);
550
if ((node->nod_flags & NOD_COMP_DIALECT) &&
551
(request->req_client_dialect == SQL_DIALECT_V6_TRANSITION))
553
switch (node->nod_type) {
569
case nod_agg_average2:
573
sprintf(message_buf, "blr %d", (int) blr_operator);
576
ERRD_post_warning(isc_dsql_dialect_warning_expr,
577
isc_arg_string, s, isc_arg_end);
587
@brief Generate a port from a message. Feel free to rearrange the
595
void GEN_port( dsql_req* request, dsql_msg* message)
597
tsql* tdsql = DSQL_get_thread_data();
599
// if (request->req_blr_string) {
600
stuff(request, blr_message);
601
stuff(request, message->msg_number);
602
stuff_word(request, message->msg_parameter);
609
for (parameter = message->msg_parameters; parameter;
610
parameter = parameter->par_next)
612
parameter->par_parameter = number++;
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;
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)
623
if (parameter->par_desc.dsc_dtype == dtype_varying)
624
adjust = sizeof(USHORT);
625
else if (parameter->par_desc.dsc_dtype == dtype_cstring)
628
parameter->par_desc.dsc_length -= adjust;
630
USHORT fromCharSetBPC = METD_get_charset_bpc(request, fromCharSet);
631
USHORT toCharSetBPC = METD_get_charset_bpc(request, toCharSet);
633
INTL_ASSIGN_TTYPE(¶meter->par_desc, INTL_CS_COLL_TO_TTYPE(toCharSet,
634
(fromCharSet == toCharSet ? INTL_GET_COLLATE(¶meter->par_desc) : 0)));
636
parameter->par_desc.dsc_length =
637
UTLD_char_length_to_byte_length(parameter->par_desc.dsc_length / fromCharSetBPC, toCharSetBPC);
639
parameter->par_desc.dsc_length += adjust;
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)
648
if (fromCharSet != toCharSet)
649
parameter->par_desc.setTextType(toCharSet);
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) {
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 */
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,
668
DSC_dtype_tostring(parameter->par_desc.dsc_dtype),
672
// No special action for other data types
675
const USHORT align = type_alignments[parameter->par_desc.dsc_dtype];
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, ¶meter->par_desc, false);
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,
691
message->msg_length = (USHORT) offset;
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);
699
// Relocate parameter descriptors to point direction into message buffer
701
for (parameter = message->msg_parameters; parameter;
702
parameter = parameter->par_next)
704
parameter->par_desc.dsc_address = message->msg_buffer +
705
(IPTR)parameter->par_desc.dsc_address;
714
@brief Generate complete blr for a request.
721
void GEN_request( dsql_req* request, dsql_nod* node)
723
if (request->req_type == REQ_DDL) {
724
DDL_generate(request, node);
728
if (request->req_flags & REQ_blr_version4)
729
stuff(request, blr_version4);
731
stuff(request, blr_version5);
733
if (request->req_type == REQ_SAVEPOINT)
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);
743
stuff(request, blr_begin);
745
if (request->req_type == REQ_SELECT ||
746
request->req_type == REQ_SELECT_UPD ||
747
request->req_type == REQ_EMBED_SELECT)
749
gen_select(request, node);
751
else if (request->req_type == REQ_EXEC_BLOCK ||
752
request->req_type == REQ_SELECT_BLOCK )
754
GEN_statement(request, node);
757
dsql_msg* message = request->req_send;
758
if (!message->msg_parameter)
759
request->req_send = NULL;
761
GEN_port(request, message);
762
stuff(request, blr_receive);
763
stuff(request, message->msg_number);
765
message = request->req_receive;
766
if (!message->msg_parameter)
767
request->req_receive = NULL;
769
GEN_port(request, message);
770
GEN_statement(request, node);
772
stuff(request, blr_end);
775
stuff(request, blr_eoc);
781
GEN_start_transaction
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
786
Do not allow an option to be specified more than once.
793
void GEN_start_transaction( dsql_req* request, const dsql_nod* tran_node)
795
SSHORT count = tran_node->nod_count;
800
const dsql_nod* node = tran_node->nod_arg[0];
805
// Find out isolation level - if specified. This is required for
806
// specifying the correct lock level in reserving clause.
808
USHORT lock_level = isc_tpb_shared;
810
if (count = node->nod_count) {
812
const dsql_nod* ptr = node->nod_arg[count];
814
if ((!ptr) || (ptr->nod_type != nod_isolation))
817
lock_level = (ptr->nod_flags & NOD_CONSISTENCY) ?
818
isc_tpb_protected : isc_tpb_shared;
823
bool sw_access = false, sw_wait = false, sw_isolation = false,
824
sw_reserve = false, sw_lock_timeout = false;
827
// Stuff some version info.
828
if (count = node->nod_count)
829
stuff(request, isc_tpb_version1);
833
const dsql_nod* ptr = node->nod_arg[count];
838
switch (ptr->nod_type) {
841
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
842
isc_arg_gds, isc_dsql_dup_option, 0);
845
if (ptr->nod_flags & NOD_READ_ONLY)
846
stuff(request, isc_tpb_read);
848
stuff(request, isc_tpb_write);
853
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
854
isc_arg_gds, isc_dsql_dup_option, 0);
857
if (ptr->nod_flags & NOD_NO_WAIT)
858
stuff(request, isc_tpb_nowait);
860
stuff(request, isc_tpb_wait);
865
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
866
isc_arg_gds, isc_dsql_dup_option, 0);
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);
875
stuff(request, isc_tpb_read_committed);
877
if ((ptr->nod_count) && (ptr->nod_arg[0]) &&
878
(ptr->nod_arg[0]->nod_type == nod_version))
880
if (ptr->nod_arg[0]->nod_flags & NOD_VERSION)
881
stuff(request, isc_tpb_rec_version);
883
stuff(request, isc_tpb_no_rec_version);
886
stuff(request, isc_tpb_no_rec_version);
894
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
895
isc_arg_gds, isc_dsql_dup_option, 0);
898
const dsql_nod* reserve = ptr->nod_arg[0];
901
const dsql_nod* const* temp = reserve->nod_arg;
902
for (const dsql_nod* const* end = temp + reserve->nod_count;
905
gen_table_lock(request, *temp, lock_level);
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);
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);
925
case nod_lock_timeout:
927
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
928
isc_arg_gds, isc_dsql_dup_option, 0);
930
sw_lock_timeout = true;
931
if (ptr->nod_count == 1 && ptr->nod_arg[0]->nod_type == nod_constant)
933
const int lck_timeout = (int) ptr->nod_arg[0]->getSlong();
934
stuff(request, isc_tpb_lock_timeout);
936
stuff_word(request, lck_timeout);
941
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 104,
942
isc_arg_gds, isc_dsql_tran_err, 0);
952
@brief Generate blr for an arbitrary expression.
959
void GEN_statement( dsql_req* request, dsql_nod* node)
963
const dsql_nod* const* end;
967
switch (node->nod_type) {
969
stuff(request, blr_assignment);
970
GEN_expr(request, node->nod_arg[0]);
971
GEN_expr(request, node->nod_arg[1]);
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;
982
GEN_statement(request, *ptr);
985
stuff(request, blr_end);
989
DDL_gen_block(request, node);
993
gen_for_select(request, node);
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]);
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]);
1011
stuff(request, blr_end);
1015
stuff(request, blr_begin);
1016
for (ptr = node->nod_arg, end = ptr + node->nod_count; ptr < end;
1019
GEN_statement(request, *ptr);
1021
stuff(request, blr_end);
1025
case nod_erase_current:
1027
case nod_modify_current:
1029
case nod_exec_procedure:
1030
gen_statement(request, node);
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;
1040
gen_error_condition(request, *ptr);
1042
GEN_statement(request, node->nod_arg[e_err_action]);
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);
1052
stuff(request, blr_post);
1053
GEN_expr(request, node->nod_arg[e_pst_event]);
1058
stuff(request, blr_exec_sql);
1059
GEN_expr(request, node->nod_arg[e_exec_sql_stmnt]);
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]);
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]);
1076
stuff(request, 1); // Singleton
1077
for (ptr = temp->nod_arg, end = ptr + temp->nod_count;
1080
GEN_expr(request, *ptr);
1085
if ( (temp = node->nod_arg[e_rtn_procedure]) )
1087
if (temp->nod_type == nod_exec_block)
1088
GEN_return(request, temp->nod_arg[e_exe_blk_outputs], false);
1090
GEN_return(request, temp->nod_arg[e_prc_outputs], false);
1095
stuff(request, blr_leave);
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]);
1105
stuff(request, blr_leave);
1106
stuff(request, (int) (IPTR) node->nod_arg[e_abrt_number]);
1109
case nod_start_savepoint:
1110
stuff(request, blr_start_savepoint);
1113
case nod_end_savepoint:
1114
stuff(request, blr_end_savepoint);
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);
1123
case nod_release_savepoint:
1124
stuff(request, blr_user_savepoint);
1125
if (node->nod_arg[1]) {
1126
stuff(request, blr_savepoint_release_single);
1129
stuff(request, blr_savepoint_release);
1131
stuff_cstring(request, ((dsql_str*)node->nod_arg[e_sav_name])->str_data);
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);
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 */
1149
stuff(request, blr_raise);
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 */
1157
stuff(request, blr_exception_msg);
1159
/* otherwise go usual way,
1160
i.e. generate blr_exception */
1163
stuff(request, blr_exception);
1165
if (!(string->str_flags & STR_delimited_id))
1167
id_length = string->str_length;
1168
for (TEXT* p = reinterpret_cast<char*>(string->str_data); *p;
1175
stuff_cstring(request, string->str_data);
1176
/* if exception value is defined,
1177
generate appropriate BLR verbs */
1180
GEN_expr(request, temp);
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);
1199
stuff(request, blr_abort);
1200
gen_error_condition(request, node);
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;
1212
GEN_expr(request, *ptr++);
1216
case nod_cursor_open:
1217
case nod_cursor_close:
1218
case nod_cursor_fetch:
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);
1227
stuff(request, blr_cursor_fetch);
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];
1234
stuff(request, blr_seek);
1235
GEN_expr(request, seek->nod_arg[0]);
1236
GEN_expr(request, seek->nod_arg[1]);
1239
dsql_nod* list_into = node->nod_arg[e_cur_stmt_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;
1250
stuff(request, blr_assignment);
1251
GEN_expr(request, *ptr++);
1252
GEN_expr(request, *ptr_to++);
1254
stuff(request, blr_end);
1260
request->put_debug_src_info(node->nod_line, node->nod_column);
1261
GEN_statement(request, node->nod_arg[e_src_info_stmt]);
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
1277
@brief Generate blr for a relation reference.
1284
static void gen_aggregate( dsql_req* request, const dsql_nod* node)
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]);
1291
// Handle GROUP BY clause
1293
stuff(request, blr_group_by);
1295
dsql_nod* list = node->nod_arg[e_agg_group];
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;
1302
GEN_expr(request, *ptr);
1308
// Generate value map
1310
gen_map(request, context->ctx_map);
1318
@brief Generate BLR for a data-type cast operation
1325
static void gen_cast( dsql_req* request, const dsql_nod* node)
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]);
1338
@brief Generate BLR for coalesce function
1340
Generate the blr values, begin with a cast and then :
1344
blr for expression 1
1347
blr for expression n-1
1349
blr for expression n-1
1355
static void gen_coalesce( dsql_req* request, const dsql_nod* node)
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);
1365
// IF (expression IS NULL) THEN
1366
stuff(request, blr_value_if);
1367
stuff(request, blr_missing);
1368
GEN_expr(request, *ptr);
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--)
1377
GEN_expr(request, *ptr);
1386
@brief Generate BLR for a constant.
1394
static void gen_constant( dsql_req* request, const dsc* desc, bool negate_value)
1401
stuff(request, blr_literal);
1403
USHORT l = 0; //= desc->dsc_length;
1404
const UCHAR* p = desc->dsc_address;
1406
switch (desc->dsc_dtype) {
1408
gen_descriptor(request, desc, true);
1409
value = *(SSHORT *) p;
1412
stuff_word(request, value);
1416
gen_descriptor(request, desc, true);
1417
value = *(SLONG *) p;
1420
//printf("gen.cpp = %p %d\n", *((void**)p), value);
1421
stuff_word(request, value);
1422
stuff_word(request, value >> 16);
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);
1434
/* this is used for approximate/large numeric literal
1435
which is transmitted to the engine as a string.
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;
1441
stuff_word(request, l + 1);
1442
stuff(request, '-');
1445
stuff_word(request, l);
1450
stuff(request, *p++);
1455
i64value = *(SINT64 *) p;
1458
i64value = -i64value;
1459
else if (i64value == MIN_SINT64) {
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.
1468
ERRD_post(isc_sqlerr,
1469
isc_arg_number, (SLONG) - 104,
1470
isc_arg_gds, isc_arith_except, 0);
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.
1479
if ((i64value >= (SINT64) MIN_SLONG) &&
1480
(i64value <= (SINT64) MAX_SLONG))
1482
stuff(request, blr_long);
1483
stuff(request, desc->dsc_scale);
1484
stuff_word(request, i64value);
1485
stuff_word(request, i64value >> 16);
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);
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);
1513
USHORT length = desc->dsc_length;
1515
gen_descriptor(request, desc, true);
1518
stuff(request, *p++);
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);
1535
@brief Generate BLR for a constant.
1543
static void gen_constant( dsql_req* request, dsql_nod* node, bool negate_value)
1545
if (node->nod_desc.dsc_dtype == dtype_text)
1546
node->nod_desc.dsc_length = ((dsql_str*) node->nod_arg[0])->str_length;
1548
gen_constant(request, &node->nod_desc, negate_value);
1556
@brief Generate a blr descriptor from an internal descriptor.
1564
static void gen_descriptor( dsql_req* request, const dsc* desc, bool texttype)
1566
switch (desc->dsc_dtype) {
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());
1573
stuff(request, blr_text2); // automatic transliteration
1574
stuff_word(request, ttype_dynamic);
1577
stuff_word(request, desc->dsc_length);
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());
1586
stuff(request, blr_varying2); // automatic transliteration
1587
stuff_word(request, ttype_dynamic);
1589
stuff_word(request, desc->dsc_length - sizeof(USHORT));
1593
stuff(request, blr_short);
1594
stuff(request, desc->dsc_scale);
1598
stuff(request, blr_long);
1599
stuff(request, desc->dsc_scale);
1603
stuff(request, blr_quad);
1604
stuff(request, desc->dsc_scale);
1608
stuff(request, blr_int64);
1609
stuff(request, desc->dsc_scale);
1613
stuff(request, blr_float);
1617
stuff(request, blr_double);
1620
case dtype_sql_date:
1621
stuff(request, blr_sql_date);
1624
case dtype_sql_time:
1625
stuff(request, blr_sql_time);
1628
case dtype_timestamp:
1629
stuff(request, blr_timestamp);
1633
stuff(request, blr_quad);
1638
stuff(request, blr_blob2);
1639
stuff_word(request, desc->dsc_sub_type);
1640
stuff_word(request, desc->getTextType());
1644
// don't understand dtype
1645
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) - 804,
1646
isc_arg_gds, isc_dsql_datatype_err, 0);
1655
@brief Generate blr for an error condtion
1662
static void gen_error_condition( dsql_req* request, const dsql_nod* node)
1664
const dsql_str* string;
1666
switch (node->nod_type) {
1668
stuff(request, blr_sql_code);
1669
stuff_word(request, (USHORT)(IPTR) node->nod_arg[0]);
1673
stuff(request, blr_gds_code);
1674
string = (dsql_str*) node->nod_arg[0];
1675
stuff_cstring(request, string->str_data);
1679
stuff(request, blr_exception);
1680
string = (dsql_str*) node->nod_arg[0];
1681
stuff_cstring(request, string->str_data);
1685
stuff(request, blr_default_code);
1699
@brief Generate blr for a field - field id's
1700
are preferred but not for trigger or view blr.
1709
static void gen_field( dsql_req* request, const dsql_ctx* context,
1710
const dsql_fld* field, dsql_nod* indices)
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:
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,
1724
DSC_dtype_tostring(static_cast < UCHAR >
1725
(field->fld_dtype)), 0);
1728
// No special action for other data types
1734
stuff(request, blr_index);
1736
if (DDL_ids(request)) {
1737
stuff(request, blr_fid);
1738
stuff_context(request, context);
1739
stuff_word(request, field->fld_id);
1742
stuff(request, blr_field);
1743
stuff_context(request, context);
1744
stuff_cstring(request, field->fld_name);
1748
stuff(request, indices->nod_count);
1749
dsql_nod** ptr = indices->nod_arg;
1750
for (const dsql_nod* const* end = ptr + indices->nod_count;
1753
GEN_expr(request, *ptr);
1763
@brief Generate BLR for a SELECT statement.
1770
static void gen_for_select( dsql_req* request, const dsql_nod* for_select)
1772
dsql_nod* rse = for_select->nod_arg[e_flp_select];
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]);
1781
// Generate FOR loop
1783
stuff(request, blr_for);
1785
if (!for_select->nod_arg[e_flp_action])
1787
stuff(request, blr_singular);
1789
gen_rse(request, rse);
1790
stuff(request, blr_begin);
1792
// Build body of FOR loop
1794
// Handle write locks
1795
dsql_nod* streams = rse->nod_arg[e_rse_streams];
1796
dsql_ctx* context = NULL;
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];
1804
dsql_nod* list = rse->nod_arg[e_rse_items];
1805
dsql_nod* list_to = for_select->nod_arg[e_flp_into];
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;
1817
stuff(request, blr_assignment);
1818
GEN_expr(request, *ptr);
1819
GEN_expr(request, *ptr_to);
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);
1833
@brief Generate BLR for gen_id
1840
static void gen_gen_id( dsql_req* request, const dsql_nod* node)
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]);
1853
@brief Generate a record selection expression
1854
with an explicit join type.
1861
static void gen_join_rse( dsql_req* request, const dsql_nod* rse)
1863
stuff(request, blr_rs_stream);
1866
GEN_expr(request, rse->nod_arg[e_join_left_rel]);
1867
GEN_expr(request, rse->nod_arg[e_join_rght_rel]);
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);
1877
stuff(request, blr_full);
1880
if (rse->nod_arg[e_join_boolean])
1882
stuff(request, blr_boolean);
1883
GEN_expr(request, rse->nod_arg[e_join_boolean]);
1886
stuff(request, blr_end);
1894
@brief Generate a value map for a record selection expression.
1901
static void gen_map( dsql_req* request, dsql_map* map)
1905
for (temp = map; temp; temp = temp->map_next)
1906
temp->map_position = count++;
1908
stuff(request, blr_map);
1909
stuff_word(request, count);
1911
for (temp = map; temp; temp = temp->map_next) {
1912
stuff_word(request, temp->map_position);
1913
GEN_expr(request, temp->map_node);
1922
@brief Generate a parameter reference.
1929
static void gen_parameter( dsql_req* request, const dsql_par* parameter)
1931
const dsql_msg* message = parameter->par_message;
1933
const dsql_par* null = parameter->par_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);
1942
stuff(request, blr_parameter);
1943
stuff(request, message->msg_number);
1944
stuff_word(request, parameter->par_parameter);
1953
@brief Generate blr for an access plan expression.
1957
@param plan_expression
1960
static void gen_plan( dsql_req* request, const dsql_nod* plan_expression)
1962
// stuff the join type
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);
1969
stuff(request, blr_join);
1970
stuff(request, list->nod_count);
1973
// stuff one or more plan items
1975
const dsql_nod* const* ptr = list->nod_arg;
1976
for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end;
1979
const dsql_nod* node = *ptr;
1980
if (node->nod_type == nod_plan_expr) {
1981
gen_plan(request, node);
1985
// if we're here, it must be a nod_plan_item
1987
stuff(request, blr_retrieve);
1989
/* stuff the relation--the relation id itself is redundant except
1990
when there is a need to differentiate the base tables of views */
1992
const dsql_nod* arg = node->nod_arg[0];
1993
gen_relation(request, (dsql_ctx*) arg->nod_arg[e_rel_context]);
1995
// now stuff the access method for this stream
1996
const dsql_str* index_string;
1998
arg = node->nod_arg[1];
1999
switch (arg->nod_type) {
2001
stuff(request, blr_sequential);
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])
2010
// dimitr: FALL INTO, if the plan item is ORDER ... INDEX (...)
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++)
2022
index_string = (dsql_str*) * ptr2;
2023
stuff_cstring(request, index_string->str_data);
2042
@brief Generate blr for a relation reference.
2049
static void gen_relation( dsql_req* request, dsql_ctx* context)
2051
const dsql_rel* relation = context->ctx_relation;
2052
const dsql_prc* procedure = context->ctx_procedure;
2054
// if this is a trigger or procedure, don't want relation id used
2056
if (DDL_ids(request)) {
2057
if (context->ctx_alias)
2058
stuff(request, blr_rid2);
2060
stuff(request, blr_rid);
2061
stuff_word(request, relation->rel_id);
2064
if (context->ctx_alias)
2065
stuff(request, blr_relation2);
2067
stuff(request, blr_relation);
2068
stuff_meta_string(request, relation->rel_name);
2071
if (context->ctx_alias)
2072
stuff_meta_string(request, context->ctx_alias);
2074
stuff_context(request, context);
2076
else if (procedure) {
2077
if (DDL_ids(request)) {
2078
stuff(request, blr_pid);
2079
stuff_word(request, procedure->prc_id);
2082
stuff(request, blr_procedure);
2083
stuff_meta_string(request, procedure->prc_name);
2085
stuff_context(request, context);
2087
dsql_nod* inputs = context->ctx_proc_inputs;
2089
stuff_word(request, inputs->nod_count);
2091
dsql_nod* const* ptr = inputs->nod_arg;
2092
for (const dsql_nod* const* const end = ptr + inputs->nod_count;
2095
GEN_expr(request, *ptr);
2099
stuff_word(request, 0);
2108
@brief Generate blr for a procedure return.
2116
void GEN_return( dsql_req* request, const dsql_nod* parameters, bool eos_flag)
2119
stuff(request, blr_begin);
2120
stuff(request, blr_send);
2122
stuff(request, blr_begin);
2126
const dsql_nod* const* ptr = parameters->nod_arg;
2127
for (const dsql_nod* const* const end = ptr + parameters->nod_count;
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);
2142
stuff(request, blr_assignment);
2143
stuff(request, blr_literal);
2144
stuff(request, blr_short);
2147
stuff_word(request, 0);
2149
stuff_word(request, 1);
2150
stuff(request, blr_parameter);
2152
stuff_word(request, 2 * outputs);
2153
stuff(request, blr_end);
2155
stuff(request, blr_stall);
2156
stuff(request, blr_end);
2165
@brief Generate a record selection expression.
2172
static void gen_rse( dsql_req* request, const dsql_nod* rse)
2174
if (rse->nod_flags & NOD_SELECT_EXPR_SINGLETON)
2176
stuff(request, blr_singular);
2179
stuff(request, blr_rse);
2181
dsql_nod* list = rse->nod_arg[e_rse_streams];
2183
// Handle source streams
2185
if (list->nod_type == nod_union) {
2187
gen_union(request, rse);
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;
2195
dsql_nod* node = *ptr;
2196
if (node->nod_type == nod_relation ||
2197
node->nod_type == nod_aggregate ||
2198
node->nod_type == nod_join)
2200
GEN_expr(request, node);
2202
else if (node->nod_type == nod_derived_table) {
2203
GEN_expr(request, node->nod_arg[e_derived_table_rse]);
2209
GEN_expr(request, list);
2212
if (rse->nod_arg[e_rse_lock])
2213
stuff(request, blr_writelock);
2217
if ((node = rse->nod_arg[e_rse_first]) != NULL) {
2218
stuff(request, blr_first);
2219
GEN_expr(request, node);
2222
if ((node = rse->nod_arg[e_rse_skip]) != NULL) {
2223
stuff(request, blr_skip);
2224
GEN_expr (request, node);
2227
if ((node = rse->nod_arg[e_rse_boolean]) != NULL) {
2228
stuff(request, blr_boolean);
2229
GEN_expr(request, node);
2232
if ((list = rse->nod_arg[e_rse_sort]) != NULL)
2233
gen_sort(request, list);
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;
2242
GEN_expr(request, *ptr);
2246
// if the user specified an access plan to use, add it here
2248
if ((node = rse->nod_arg[e_rse_plan]) != NULL) {
2249
stuff(request, blr_plan);
2250
gen_plan(request, node);
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 */
2260
if (request->req_type == REQ_SELECT &&
2261
request->req_dbb->dbb_base_level >= 5)
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);
2272
stuff(request, blr_end);
2280
@brief Generate BLR for CASE function (searched)
2287
static void gen_searched_case( dsql_req* request, const dsql_nod* node)
2289
// blr_value_if is used for building the case expression
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;
2302
stuff(request, blr_value_if);
2303
GEN_expr(request, *bptr);
2304
GEN_expr(request, *rptr);
2307
GEN_expr(request, node->nod_arg[e_searched_case_results]->nod_arg[count]);
2315
@brief Generate BLR for a SELECT statement.
2322
static void gen_select( dsql_req* request, dsql_nod* rse)
2324
const dsql_rel* relation;
2327
fb_assert(rse->nod_type == nod_rse);
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;
2335
dsql_par* parameter =
2336
MAKE_parameter(request->req_receive, true, true, 0, *ptr);
2337
parameter->par_node = *ptr;
2338
MAKE_desc(request, ¶meter->par_desc, *ptr, NULL);
2341
// Set up parameter to handle EOF
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);
2350
// Save DBKEYs for possible update later
2352
list = rse->nod_arg[e_rse_streams];
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++)
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) {
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;
2373
// Set up record version - for post v33 databases
2376
MAKE_parameter(request->req_receive, false,
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;
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 */
2392
if (request->req_type == REQ_SELECT &&
2393
request->req_dbb->dbb_base_level >= 5)
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;
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;
2413
// Generate definitions for the messages
2415
GEN_port(request, request->req_receive);
2416
dsql_msg* message = request->req_send;
2417
if (message->msg_parameter)
2418
GEN_port(request, message);
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);
2427
// If there is a send message, build a RECEIVE
2429
if ((message = request->req_send) != NULL) {
2430
stuff(request, blr_receive);
2431
stuff(request, message->msg_number);
2434
// Generate FOR loop
2436
message = request->req_receive;
2438
stuff(request, blr_for);
2439
stuff(request, blr_stall);
2440
gen_rse(request, rse);
2442
stuff(request, blr_send);
2443
stuff(request, message->msg_number);
2444
stuff(request, blr_begin);
2446
// Build body of FOR loop
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;
2457
// Add invalid usage here
2459
stuff(request, blr_assignment);
2461
gen_constant(request, &constant_desc, USE_VALUE);
2462
gen_parameter(request, request->req_eof);
2464
for (dsql_par* parameter = message->msg_parameters; parameter;
2465
parameter = parameter->par_next)
2467
if (parameter->par_node) {
2468
stuff(request, blr_assignment);
2469
GEN_expr(request, parameter->par_node);
2470
gen_parameter(request, parameter);
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);
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);
2486
stuff(request, blr_end);
2487
stuff(request, blr_send);
2488
stuff(request, message->msg_number);
2489
stuff(request, blr_assignment);
2491
gen_constant(request, &constant_desc, USE_VALUE);
2492
gen_parameter(request, request->req_eof);
2500
@brief Generate BLR for CASE function (simple)
2507
static void gen_simple_case( dsql_req* request, const dsql_nod* node)
2509
// blr_value_if is used for building the case expression
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];
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;
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);
2529
GEN_expr(request, node->nod_arg[e_simple_case_results]->nod_arg[count]);
2537
@brief Generate a sort clause.
2544
static void gen_sort( dsql_req* request, dsql_nod* list)
2546
stuff(request, blr_sort);
2547
stuff(request, list->nod_count);
2549
dsql_nod* const* ptr = list->nod_arg;
2550
for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end;
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);
2559
case NOD_NULLS_LAST:
2560
stuff(request, blr_nullslast);
2564
if ((*ptr)->nod_arg[e_order_flag])
2565
stuff(request, blr_descending);
2567
stuff(request, blr_ascending);
2568
GEN_expr(request, (*ptr)->nod_arg[e_order_field]);
2577
@brief Generate BLR for DML statements.
2584
static void gen_statement(dsql_req* request, const dsql_nod* node)
2586
dsql_nod* rse = NULL;
2587
const dsql_msg* message = NULL;
2588
bool send_before_for = !(request->req_flags & REQ_dsql_upd_or_ins);
2590
switch (node->nod_type) {
2592
rse = node->nod_arg[e_sto_rse];
2595
rse = node->nod_arg[e_mod_rse];
2598
rse = node->nod_arg[e_era_rse];
2601
send_before_for = false;
2605
if (request->req_type == REQ_EXEC_PROCEDURE && send_before_for)
2607
if ((message = request->req_receive))
2609
stuff(request, blr_send);
2610
stuff(request, message->msg_number);
2615
stuff(request, blr_for);
2616
GEN_expr(request, rse);
2619
if (request->req_type == REQ_EXEC_PROCEDURE)
2621
if ((message = request->req_receive))
2623
stuff(request, blr_begin);
2625
if (!send_before_for)
2627
stuff(request, blr_send);
2628
stuff(request, message->msg_number);
2637
switch (node->nod_type) {
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]);
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]);
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]);
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);
2685
stuff(request, blr_erase);
2686
stuff_context(request, context);
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);
2700
stuff(request, blr_erase);
2701
stuff_context(request, context);
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);
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;
2717
GEN_expr(request, *ptr++);
2721
stuff_word(request, 0);
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;
2730
GEN_expr(request, *ptr++);
2734
stuff_word(request, 0);
2743
stuff(request, blr_end);
2752
@brief Generate a system defined function.
2759
static void gen_sys_function(dsql_req* request, const dsql_nod* node)
2761
stuff(request, blr_sys_function);
2762
stuff_cstring(request, ((dsql_str*) node->nod_arg[e_sysfunc_name])->str_data);
2764
const dsql_nod* list;
2765
if ((node->nod_count == e_sysfunc_args + 1) && (list = node->nod_arg[e_sysfunc_args]))
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;
2772
GEN_expr(request, *ptr);
2784
@brief Generate tpb for table lock.
2785
If lock level is specified, it overrrides the transaction lock level.
2793
static void gen_table_lock( dsql_req* request, const dsql_nod* tbl_lock,
2796
if ((!tbl_lock) || (tbl_lock->nod_type != nod_table_lock))
2799
const dsql_nod* tbl_names = tbl_lock->nod_arg[e_lock_tables];
2802
if (tbl_lock->nod_arg[e_lock_mode])
2803
flags = tbl_lock->nod_arg[e_lock_mode]->nod_flags;
2805
if (flags & NOD_PROTECTED)
2806
lock_level = isc_tpb_protected;
2807
else if (flags & NOD_SHARED)
2808
lock_level = isc_tpb_shared;
2810
const USHORT lock_mode = (flags & NOD_WRITE) ?
2811
isc_tpb_lock_write : isc_tpb_lock_read;
2813
const dsql_nod* const* ptr = tbl_names->nod_arg;
2814
for (const dsql_nod* const* const end = ptr + tbl_names->nod_count;
2817
if ((*ptr)->nod_type != nod_relation_name)
2820
stuff(request, lock_mode);
2823
const dsql_str* temp = (dsql_str*) ((*ptr)->nod_arg[e_rln_name]);
2824
stuff_cstring(request, reinterpret_cast<const char*>(temp->str_data));
2826
stuff(request, lock_level);
2835
@brief Generate a user defined function.
2842
static void gen_udf( dsql_req* request, const dsql_nod* node)
2844
const dsql_udf* userFunc = (dsql_udf*) node->nod_arg[0];
2845
stuff(request, blr_function);
2846
stuff_cstring(request, userFunc->udf_name);
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;
2855
GEN_expr(request, *ptr);
2867
@brief Generate a union of substreams.
2874
static void gen_union( dsql_req* request, const dsql_nod* union_node)
2876
if (union_node->nod_arg[0]->nod_flags & NOD_UNION_RECURSIVE) {
2877
stuff(request, blr_recurse);
2880
stuff(request, blr_union);
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];
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;
2895
dsql_nod* streams = union_node->nod_arg[e_rse_streams];
2896
stuff(request, streams->nod_count); // number of substreams
2898
dsql_nod** ptr = streams->nod_arg;
2899
for (const dsql_nod* const* const end = ptr + streams->nod_count; ptr < end;
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);
2908
dsql_nod** iptr = items->nod_arg;
2909
for (const dsql_nod* const* const iend = iptr + items->nod_count;
2910
iptr < iend; iptr++)
2912
stuff_word(request, count);
2913
GEN_expr(request, *iptr);
2924
@brief Write a context number into the BLR buffer.
2925
Check for possible overflow.
2932
static void stuff_context(dsql_req* request, const dsql_ctx* context)
2934
if (context->ctx_context > MAX_UCHAR) {
2935
ERRD_post(isc_too_many_contexts, 0);
2937
stuff(request, context->ctx_context);
2939
if (context->ctx_flags & CTX_recursive)
2941
if (context->ctx_recursive > MAX_UCHAR) {
2942
ERRD_post(isc_too_many_contexts, 0);
2944
stuff(request, context->ctx_recursive);
2953
@brief Write out a string with one byte of length.
2960
static void stuff_cstring( dsql_req* request, const char* string)
2962
stuff_string(request, string, strlen(string));
2970
@brief Write out a string in metadata charset with one byte of length.
2977
static void stuff_meta_string(dsql_req* request, const char* string)
2979
request->append_meta_string(string);
2987
@brief Write out a string with one byte of length.
2994
static void stuff_string(dsql_req* request, const char* string, int len)
2996
fb_assert(len >= 0 && len <= 255);
2998
stuff(request, len);
3001
stuff(request, *string++);
3009
@brief Cram a word into the blr buffer. If the buffer is getting
3010
ready to overflow, expand it.
3017
static void stuff_word( dsql_req* request, USHORT word)
3020
stuff(request, word);
3021
stuff(request, word >> 8);