2001-05-23 15:26:42 +02:00
|
|
|
/*
|
|
|
|
* PROGRAM: Dynamic SQL runtime support
|
2003-10-05 08:27:16 +02:00
|
|
|
* MODULE: gen.cpp
|
2001-05-23 15:26:42 +02:00
|
|
|
* DESCRIPTION: Routines to generate BLR.
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Interbase Public
|
|
|
|
* License Version 1.0 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy
|
|
|
|
* of the License at http://www.Inprise.com/IPL.html
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an
|
|
|
|
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
|
|
|
* or implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
|
|
|
*
|
|
|
|
* The Original Code was created by Inprise Corporation
|
|
|
|
* and its predecessors. Portions created by Inprise Corporation are
|
|
|
|
* Copyright (C) Inprise Corporation.
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
2002-06-29 08:56:51 +02:00
|
|
|
* Contributor(s): ______________________________________
|
|
|
|
* 2001.6.21 Claudio Valderrama: BREAK and SUBSTRING.
|
2002-09-28 16:04:35 +02:00
|
|
|
* 2001.07.28 John Bellardo: Added code to generate blr_skip.
|
|
|
|
* 2002.07.30 Arno Brinkman: Added code, procedures to generate COALESCE, CASE
|
|
|
|
* 2002.09.28 Dmitry Yemanov: Reworked internal_info stuff, enhanced
|
|
|
|
* exception handling in SPs/triggers,
|
|
|
|
* implemented ROWS_AFFECTED system variable
|
2002-10-29 21:20:44 +01:00
|
|
|
* 2002.10.21 Nickolay Samofatov: Added support for explicit pessimistic locks
|
|
|
|
* 2002.10.29 Nickolay Samofatov: Added support for savepoints
|
2003-11-02 13:28:30 +01:00
|
|
|
* 2003.10.05 Dmitry Yemanov: Added support for explicit cursors in PSQL
|
2001-05-23 15:26:42 +02:00
|
|
|
*/
|
|
|
|
|
2001-07-30 01:43:24 +02:00
|
|
|
#include "firebird.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "../dsql/dsql.h"
|
2001-07-30 01:43:24 +02:00
|
|
|
#include "../jrd/gds.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/align.h"
|
|
|
|
#include "../jrd/intl.h"
|
|
|
|
#include "../dsql/alld_proto.h"
|
|
|
|
#include "../dsql/ddl_proto.h"
|
|
|
|
#include "../dsql/errd_proto.h"
|
|
|
|
#include "../dsql/gen_proto.h"
|
|
|
|
#include "../dsql/make_proto.h"
|
|
|
|
#include "../dsql/metd_proto.h"
|
2002-09-28 16:04:35 +02:00
|
|
|
#include "../dsql/misc_func.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/thd_proto.h"
|
|
|
|
#include "../jrd/dsc_proto.h"
|
2001-07-30 01:43:24 +02:00
|
|
|
#include "gen/iberror.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_aggregate(dsql_req*, const dsql_nod*);
|
|
|
|
static void gen_cast(dsql_req*, const dsql_nod*);
|
|
|
|
static void gen_coalesce(dsql_req*, const dsql_nod*);
|
|
|
|
static void gen_constant(dsql_req*, dsc*, bool);
|
|
|
|
static void gen_descriptor(dsql_req*, const dsc*, bool);
|
|
|
|
static void gen_error_condition(dsql_req*, const dsql_nod*);
|
|
|
|
static void gen_field(dsql_req*, const dsql_ctx*, const dsql_fld*, dsql_nod*);
|
|
|
|
static void gen_for_select(dsql_req*, dsql_nod*);
|
|
|
|
static void gen_gen_id(dsql_req*, const dsql_nod*);
|
|
|
|
static void gen_join_rse(dsql_req*, const dsql_nod*);
|
|
|
|
static void gen_map(dsql_req*, dsql_map*);
|
|
|
|
static void gen_parameter(dsql_req*, const par*);
|
|
|
|
static void gen_plan(dsql_req*, const dsql_nod*);
|
|
|
|
static void gen_relation(dsql_req*, dsql_ctx*);
|
|
|
|
static void gen_rse(dsql_req*, const dsql_nod*);
|
|
|
|
static void gen_searched_case(dsql_req*, const dsql_nod*);
|
|
|
|
static void gen_select(dsql_req*, dsql_nod*);
|
|
|
|
static void gen_simple_case(dsql_req*, const dsql_nod*);
|
|
|
|
static void gen_sort(dsql_req*, dsql_nod*);
|
|
|
|
static void gen_table_lock(dsql_req*, const dsql_nod*, USHORT);
|
|
|
|
static void gen_udf(dsql_req*, const dsql_nod*);
|
|
|
|
static void gen_union(dsql_req*, const dsql_nod*);
|
|
|
|
static void stuff_cstring(dsql_req*, const char*);
|
|
|
|
static void stuff_word(dsql_req*, USHORT);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-02-13 10:33:26 +01:00
|
|
|
static const SCHAR db_key_name[] = "DB_KEY";
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* STUFF is defined in dsql.h for use in common with ddl.c */
|
|
|
|
|
|
|
|
/* The following are passed as the third argument to gen_constant */
|
2003-09-28 02:36:28 +02:00
|
|
|
const bool NEGATE_VALUE = true;
|
|
|
|
const bool USE_VALUE = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-02-12 20:28:13 +01:00
|
|
|
|
2003-02-21 01:27:16 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
GEN_expand_buffer
|
|
|
|
|
|
|
|
@brief The blr buffer needs to be expanded.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param byte
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
UCHAR GEN_expand_buffer( dsql_req* request, UCHAR byte)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2001-12-24 03:51:06 +01:00
|
|
|
TSQL tdsql = GET_THREAD_DATA;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-02-12 20:28:13 +01:00
|
|
|
const ULONG length = request->req_blr_string->str_length + 2048;
|
2003-02-27 00:41:00 +01:00
|
|
|
// AB: We must define a maximum length and post an error when exceeded else
|
|
|
|
// the server can crash with a huge SQL command.
|
|
|
|
|
2003-02-12 20:28:13 +01:00
|
|
|
const bool bIsPermanentPool = MemoryPool::blk_pool(request->req_blr_string) == DSQL_permanent_pool;
|
|
|
|
DsqlMemoryPool* pool = bIsPermanentPool ? DSQL_permanent_pool : tdsql->tsql_default;
|
2003-11-01 11:26:43 +01:00
|
|
|
str* new_buffer = FB_NEW_RPT(*pool, length) str;
|
2001-05-23 15:26:42 +02:00
|
|
|
new_buffer->str_length = length;
|
|
|
|
|
2003-02-12 20:28:13 +01:00
|
|
|
// one huge pointer per line for LIBS
|
|
|
|
// TMN: What does that mean???
|
2003-02-27 00:41:00 +01:00
|
|
|
|
2003-02-12 20:28:13 +01:00
|
|
|
char* p = new_buffer->str_data;
|
|
|
|
const char* q = request->req_blr_string->str_data;
|
|
|
|
BLOB_PTR* end = request->req_blr;
|
|
|
|
const size_t copy_length = (reinterpret_cast<char*>(end) - q);
|
2001-05-23 15:26:42 +02:00
|
|
|
memcpy(p, q, copy_length);
|
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
delete request->req_blr_string;
|
2001-05-23 15:26:42 +02:00
|
|
|
request->req_blr_string = new_buffer;
|
2003-02-12 20:28:13 +01:00
|
|
|
request->req_blr = reinterpret_cast<BLOB_PTR*>(p + copy_length);
|
|
|
|
request->req_blr_yellow = reinterpret_cast<BLOB_PTR*>(new_buffer->str_data + length);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
return (*request->req_blr++ = byte);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
GEN_expr
|
|
|
|
|
|
|
|
@brief Generate blr for an arbitrary expression.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param node
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
void GEN_expr( dsql_req* request, dsql_nod* node)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
UCHAR blr_operator;
|
|
|
|
dsql_nod* ddl_node;
|
|
|
|
dsql_ctx* context;
|
|
|
|
dsql_map* map;
|
|
|
|
var* variable;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
switch (node->nod_type) {
|
|
|
|
case nod_alias:
|
|
|
|
GEN_expr(request, node->nod_arg[e_alias_value]);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_aggregate:
|
|
|
|
gen_aggregate(request, node);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_constant:
|
|
|
|
gen_constant(request, &node->nod_desc, USE_VALUE);
|
|
|
|
return;
|
|
|
|
|
2003-09-04 17:02:22 +02:00
|
|
|
case nod_derived_field:
|
|
|
|
GEN_expr(request, node->nod_arg[e_derived_field_value]);
|
|
|
|
return;
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
case nod_extract:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_extract);
|
|
|
|
stuff(request, *(SLONG *) node->nod_arg[e_extract_part]->nod_desc.dsc_address);
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, node->nod_arg[e_extract_value]);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_dbkey:
|
|
|
|
node = node->nod_arg[0];
|
2003-11-01 11:26:43 +01:00
|
|
|
context = (dsql_ctx*) node->nod_arg[e_rel_context];
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_dbkey);
|
|
|
|
stuff(request, context->ctx_context);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_rec_version:
|
|
|
|
node = node->nod_arg[0];
|
2003-11-01 11:26:43 +01:00
|
|
|
context = (dsql_ctx*) node->nod_arg[e_rel_context];
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_record_version);
|
|
|
|
stuff(request, context->ctx_context);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_dom_value:
|
|
|
|
if ((request->req_type != REQ_DDL) ||
|
|
|
|
!(ddl_node = request->req_ddl_node) ||
|
|
|
|
!(ddl_node->nod_type == nod_def_domain ||
|
|
|
|
ddl_node->nod_type == nod_mod_domain))
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 901,
|
|
|
|
gds_arg_gds, gds_dsql_domain_err, 0);
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_fid);
|
|
|
|
stuff(request, 0); /* Context */
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, 0); /* Field id */
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_field:
|
|
|
|
gen_field(request,
|
2003-11-01 11:26:43 +01:00
|
|
|
(dsql_ctx*) node->nod_arg[e_fld_context],
|
|
|
|
(dsql_fld*) node->nod_arg[e_fld_field],
|
2001-05-23 15:26:42 +02:00
|
|
|
node->nod_arg[e_fld_indices]);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_user_name:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_user_name);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_current_time:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_current_time);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_current_timestamp:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_current_timestamp);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_current_date:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_current_date);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
2002-06-29 08:56:51 +02:00
|
|
|
case nod_current_role:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_current_role);
|
2002-06-29 08:56:51 +02:00
|
|
|
return;
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
case nod_udf:
|
|
|
|
gen_udf(request, node);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_variable:
|
2003-11-01 11:26:43 +01:00
|
|
|
variable = (var*) node->nod_arg[e_var_variable];
|
2001-05-23 15:26:42 +02:00
|
|
|
if (variable->var_flags & VAR_input) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_parameter2);
|
|
|
|
stuff(request, variable->var_msg_number);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, variable->var_msg_item);
|
|
|
|
stuff_word(request, variable->var_msg_item + 1);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_variable);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, variable->var_variable_number);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_join:
|
|
|
|
gen_join_rse(request, node);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_map:
|
2003-11-01 11:26:43 +01:00
|
|
|
map = (dsql_map*) node->nod_arg[e_map_map];
|
|
|
|
context = (dsql_ctx*) node->nod_arg[e_map_context];
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_fid);
|
|
|
|
stuff(request, context->ctx_context);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, map->map_position);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_parameter:
|
2003-11-01 11:26:43 +01:00
|
|
|
gen_parameter(request, (par*) node->nod_arg[e_par_parameter]);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_relation:
|
2003-11-01 11:26:43 +01:00
|
|
|
gen_relation(request, (dsql_ctx*) node->nod_arg[e_rel_context]);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_rse:
|
|
|
|
gen_rse(request, node);
|
|
|
|
return;
|
|
|
|
|
2003-08-15 01:34:37 +02:00
|
|
|
case nod_derived_table:
|
|
|
|
gen_rse(request, node->nod_arg[e_derived_table_rse]);
|
|
|
|
return;
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
case nod_exists:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_any);
|
2001-05-23 15:26:42 +02:00
|
|
|
gen_rse(request, node->nod_arg[0]);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_singular:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_unique);
|
2001-05-23 15:26:42 +02:00
|
|
|
gen_rse(request, node->nod_arg[0]);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_agg_count:
|
|
|
|
if (!(request->req_dbb->dbb_flags & DBB_v3)) {
|
|
|
|
if (node->nod_count)
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = (node->nod_flags & NOD_AGG_DISTINCT) ?
|
2001-05-23 15:26:42 +02:00
|
|
|
blr_agg_count_distinct : blr_agg_count2;
|
|
|
|
else
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_agg_count;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_agg_count;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_agg_min:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_agg_min;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_agg_max:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_agg_max;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_agg_average:
|
|
|
|
if (!(request->req_dbb->dbb_flags & DBB_v3))
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = (node->nod_flags & NOD_AGG_DISTINCT) ?
|
2001-05-23 15:26:42 +02:00
|
|
|
blr_agg_average_distinct : blr_agg_average;
|
|
|
|
else
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_agg_average;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_agg_total:
|
|
|
|
if (!(request->req_dbb->dbb_flags & DBB_v3))
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = (node->nod_flags & NOD_AGG_DISTINCT) ?
|
2001-05-23 15:26:42 +02:00
|
|
|
blr_agg_total_distinct : blr_agg_total;
|
|
|
|
else
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_agg_total;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_agg_average2:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = (node->nod_flags & NOD_AGG_DISTINCT) ?
|
2001-05-23 15:26:42 +02:00
|
|
|
blr_agg_average_distinct : blr_agg_average;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_agg_total2:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = (node->nod_flags & NOD_AGG_DISTINCT) ?
|
2001-05-23 15:26:42 +02:00
|
|
|
blr_agg_total_distinct : blr_agg_total;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_and:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_and;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_or:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_or;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_not:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_not;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_eql_all:
|
|
|
|
case nod_eql_any:
|
|
|
|
case nod_eql:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_eql;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_neq_all:
|
|
|
|
case nod_neq_any:
|
|
|
|
case nod_neq:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_neq;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_gtr_all:
|
|
|
|
case nod_gtr_any:
|
|
|
|
case nod_gtr:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_gtr;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_leq_all:
|
|
|
|
case nod_leq_any:
|
|
|
|
case nod_leq:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_leq;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_geq_all:
|
|
|
|
case nod_geq_any:
|
|
|
|
case nod_geq:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_geq;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_lss_all:
|
|
|
|
case nod_lss_any:
|
|
|
|
case nod_lss:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_lss;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_between:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_between;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_containing:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_containing;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_starting:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_starting;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_missing:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_missing;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_like:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = (node->nod_count == 2) ? blr_like : blr_ansi_like;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_add:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_add;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_subtract:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_subtract;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_multiply:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_multiply;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_negate:
|
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* child = node->nod_arg[0];
|
2001-05-23 15:26:42 +02:00
|
|
|
if (child->nod_type == nod_constant &&
|
|
|
|
DTYPE_IS_NUMERIC(child->nod_desc.dsc_dtype)) {
|
|
|
|
gen_constant(request, &child->nod_desc, NEGATE_VALUE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_negate;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_divide:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_divide;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_add2:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_add;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_subtract2:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_subtract;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_multiply2:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_multiply;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_divide2:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_divide;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_concatenate:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_concatenate;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_null:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_null;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_any:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_any;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_ansi_any:
|
|
|
|
if (!(request->req_dbb->dbb_flags & DBB_v3))
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_ansi_any;
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_any;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_ansi_all:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_ansi_all;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_via:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_via;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2002-06-14 14:07:20 +02:00
|
|
|
case nod_internal_info:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_internal_info;
|
2002-06-14 14:07:20 +02:00
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
case nod_upcase:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_upcase;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
2002-06-29 08:56:51 +02:00
|
|
|
case nod_substr:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_substring;
|
2002-06-29 08:56:51 +02:00
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
case nod_cast:
|
|
|
|
gen_cast(request, node);
|
|
|
|
return;
|
|
|
|
case nod_gen_id:
|
|
|
|
case nod_gen_id2:
|
|
|
|
gen_gen_id(request, node);
|
|
|
|
return;
|
2002-08-03 17:27:20 +02:00
|
|
|
case nod_coalesce:
|
|
|
|
gen_coalesce(request, node);
|
|
|
|
return;
|
|
|
|
case nod_simple_case:
|
|
|
|
gen_simple_case(request, node);
|
|
|
|
return;
|
|
|
|
case nod_searched_case:
|
|
|
|
gen_searched_case(request, node);
|
|
|
|
return;
|
2001-05-23 15:26:42 +02:00
|
|
|
case nod_average:
|
|
|
|
case nod_count:
|
|
|
|
case nod_from:
|
|
|
|
case nod_max:
|
|
|
|
case nod_min:
|
|
|
|
case nod_total:
|
|
|
|
switch (node->nod_type) {
|
|
|
|
case nod_average:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_average;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_count:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_count;
|
2001-05-23 15:26:42 +02:00
|
|
|
/* count2
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = node->nod_arg [0]->nod_arg [e_rse_items] ? blr_count2 : blr_count;
|
2001-05-23 15:26:42 +02:00
|
|
|
*/
|
|
|
|
break;
|
|
|
|
case nod_from:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_from;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_max:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_maximum;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_min:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_minimum;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
case nod_total:
|
2003-11-01 11:26:43 +01:00
|
|
|
blr_operator = blr_total;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
stuff(request, blr_operator);
|
2001-05-23 15:26:42 +02:00
|
|
|
gen_rse(request, node->nod_arg[0]);
|
2003-11-01 11:26:43 +01:00
|
|
|
if (blr_operator != blr_count)
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, node->nod_arg[0]->nod_arg[e_rse_items]);
|
|
|
|
return;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 901,
|
|
|
|
gds_arg_gds, gds_dsql_internal_err,
|
|
|
|
gds_arg_gds, gds_expression_eval_err,
|
|
|
|
/* expression evaluation not supported */
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
stuff(request, blr_operator);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* const* ptr = node->nod_arg;
|
|
|
|
for (const dsql_nod* const* const end = ptr + node->nod_count;
|
|
|
|
ptr < end; ptr++)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, *ptr);
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* Check whether the node we just processed is for a dialect 3
|
|
|
|
operation which gives a different result than the corresponding
|
|
|
|
operation in dialect 1. If it is, and if the client dialect is 2,
|
|
|
|
issue a warning about the difference. */
|
|
|
|
|
|
|
|
if (node->nod_type == nod_add2 ||
|
|
|
|
node->nod_type == nod_subtract2 ||
|
|
|
|
node->nod_type == nod_multiply2 ||
|
|
|
|
node->nod_type == nod_divide2 ||
|
|
|
|
node->nod_type == nod_agg_total2 ||
|
2003-11-01 11:26:43 +01:00
|
|
|
node->nod_type == nod_agg_average2)
|
|
|
|
{
|
|
|
|
dsc desc;
|
|
|
|
const char* s = 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
char message_buf[8];
|
|
|
|
|
|
|
|
MAKE_desc(&desc, node);
|
|
|
|
if ((node->nod_flags & NOD_COMP_DIALECT) &&
|
2003-11-01 11:26:43 +01:00
|
|
|
(request->req_client_dialect == SQL_DIALECT_V6_TRANSITION))
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
switch (node->nod_type) {
|
|
|
|
case nod_add2:
|
|
|
|
s = "add";
|
|
|
|
break;
|
|
|
|
case nod_subtract2:
|
|
|
|
s = "subtract";
|
|
|
|
break;
|
|
|
|
case nod_multiply2:
|
|
|
|
s = "multiply";
|
|
|
|
break;
|
|
|
|
case nod_divide2:
|
|
|
|
s = "divide";
|
|
|
|
break;
|
|
|
|
case nod_agg_total2:
|
|
|
|
s = "sum";
|
|
|
|
break;
|
|
|
|
case nod_agg_average2:
|
|
|
|
s = "avg";
|
|
|
|
break;
|
|
|
|
default:
|
2003-11-01 11:26:43 +01:00
|
|
|
sprintf(message_buf, "blr %d", (int) blr_operator);
|
2001-05-23 15:26:42 +02:00
|
|
|
s = message_buf;
|
|
|
|
}
|
|
|
|
ERRD_post_warning(isc_dsql_dialect_warning_expr,
|
|
|
|
gds_arg_string, s, gds_arg_end);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
GEN_port
|
|
|
|
|
|
|
|
@brief Generate a port from a message. Feel free to rearrange the
|
|
|
|
order of parameters.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param message
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
void GEN_port( dsql_req* request, dsql_msg* message)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
TSQL tdsql = GET_THREAD_DATA;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (request->req_blr_string) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_message);
|
|
|
|
stuff(request, message->msg_number);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, message->msg_parameter);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
par* parameter;
|
|
|
|
|
|
|
|
USHORT number = 0;
|
|
|
|
for (parameter = message->msg_parameters; parameter;
|
|
|
|
parameter = parameter->par_next)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
parameter->par_parameter = number++;
|
|
|
|
|
|
|
|
/* For older clients - generate an error should they try and
|
|
|
|
access data types which did not exist in the older dialect */
|
|
|
|
if (request->req_client_dialect <= SQL_DIALECT_V5)
|
|
|
|
switch (parameter->par_desc.dsc_dtype) {
|
|
|
|
|
|
|
|
/* In V6.0 - older clients, which we distinguish by
|
|
|
|
their use of SQL DIALECT 0 or 1, are forbidden
|
|
|
|
from selecting values of new datatypes */
|
2003-02-10 20:57:57 +01:00
|
|
|
case dtype_sql_date:
|
|
|
|
case dtype_sql_time:
|
|
|
|
case dtype_int64:
|
|
|
|
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 804,
|
|
|
|
gds_arg_gds, gds_dsql_datatype_err,
|
|
|
|
gds_arg_gds, isc_sql_dialect_datatype_unsupport,
|
|
|
|
gds_arg_number, request->req_client_dialect,
|
|
|
|
gds_arg_string,
|
|
|
|
DSC_dtype_tostring(parameter->par_desc.dsc_dtype),
|
|
|
|
0);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* No special action for other data types */
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
};
|
2003-11-01 11:26:43 +01:00
|
|
|
const USHORT align = type_alignments[parameter->par_desc.dsc_dtype];
|
2001-05-23 15:26:42 +02:00
|
|
|
if (align)
|
|
|
|
message->msg_length = FB_ALIGN(message->msg_length, align);
|
|
|
|
parameter->par_desc.dsc_address =
|
|
|
|
(UCHAR *) (SLONG) message->msg_length;
|
2003-11-01 11:26:43 +01:00
|
|
|
// CVC: No check for overflow here? Should be < 64K
|
2001-05-23 15:26:42 +02:00
|
|
|
message->msg_length += parameter->par_desc.dsc_length;
|
|
|
|
if (request->req_blr_string)
|
2003-09-04 01:52:47 +02:00
|
|
|
gen_descriptor(request, ¶meter->par_desc, false);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Allocate buffer for message */
|
2003-11-01 11:26:43 +01:00
|
|
|
// CVC: again, final possibility of having overflow! Should be < 64K
|
|
|
|
const USHORT new_len = message->msg_length + DOUBLE_ALIGN - 1;
|
|
|
|
str* buffer = FB_NEW_RPT(*tdsql->tsql_default, new_len) str;
|
2001-05-23 15:26:42 +02:00
|
|
|
message->msg_buffer =
|
|
|
|
(UCHAR *) FB_ALIGN((U_IPTR) buffer->str_data, DOUBLE_ALIGN);
|
|
|
|
|
|
|
|
/* Relocate parameter descriptors to point direction into message buffer */
|
|
|
|
|
|
|
|
for (parameter = message->msg_parameters; parameter;
|
|
|
|
parameter = parameter->par_next)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
parameter->par_desc.dsc_address =
|
|
|
|
message->msg_buffer + (SLONG) parameter->par_desc.dsc_address;
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
GEN_request
|
|
|
|
|
|
|
|
@brief Generate complete blr for a request.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param node
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
void GEN_request( dsql_req* request, dsql_nod* node)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
if (request->req_type == REQ_DDL) {
|
|
|
|
DDL_generate(request, node);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (request->req_flags & REQ_blr_version4)
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_version4);
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_version5);
|
2002-10-29 21:20:44 +01:00
|
|
|
|
|
|
|
if (request->req_type == REQ_SAVEPOINT)
|
|
|
|
{
|
|
|
|
// Do not generate BEGIN..END block around savepoint statement
|
|
|
|
// to avoid breaking of savepoint logic
|
|
|
|
request->req_send = NULL;
|
|
|
|
request->req_receive = NULL;
|
|
|
|
GEN_statement(request, node);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_begin);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-10-29 21:20:44 +01:00
|
|
|
if (request->req_type == REQ_SELECT ||
|
|
|
|
request->req_type == REQ_SELECT_UPD ||
|
|
|
|
request->req_type == REQ_EMBED_SELECT) {
|
|
|
|
gen_select(request, node);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
else {
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_msg* message = request->req_send;
|
2002-10-29 21:20:44 +01:00
|
|
|
if (!message->msg_parameter)
|
|
|
|
request->req_send = NULL;
|
|
|
|
else {
|
|
|
|
GEN_port(request, message);
|
|
|
|
if (request->req_type != REQ_EXEC_PROCEDURE) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_receive);
|
|
|
|
stuff(request, message->msg_number);
|
2002-10-29 21:20:44 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2002-10-29 21:20:44 +01:00
|
|
|
message = request->req_receive;
|
|
|
|
if (!message->msg_parameter)
|
|
|
|
request->req_receive = NULL;
|
|
|
|
else
|
|
|
|
GEN_port(request, message);
|
|
|
|
GEN_statement(request, node);
|
|
|
|
}
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2002-10-29 21:20:44 +01:00
|
|
|
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_eoc);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
GEN_start_transaction
|
|
|
|
|
|
|
|
@brief Generate tpb for set transaction. Use blr string of request.
|
|
|
|
If a value is not specified, default is not STUFF'ed, let the
|
|
|
|
engine handle it.
|
|
|
|
Do not allow an option to be specified more than once.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param tran_node
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
void GEN_start_transaction( dsql_req* request, const dsql_nod* tran_node)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
SSHORT count = tran_node->nod_count;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (!count)
|
|
|
|
return;
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* node = tran_node->nod_arg[0];
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (!node)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* find out isolation level - if specified. This is required for
|
|
|
|
* specifying the correct lock level in reserving clause. */
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
USHORT lock_level = gds_tpb_shared;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (count = node->nod_count) {
|
|
|
|
while (count--) {
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* ptr = node->nod_arg[count];
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if ((!ptr) || (ptr->nod_type != nod_isolation))
|
|
|
|
continue;
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
lock_level = (ptr->nod_flags & NOD_CONSISTENCY) ?
|
|
|
|
gds_tpb_protected : gds_tpb_shared;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
bool sw_access = false, sw_wait = false, sw_isolation = false,
|
|
|
|
sw_reserve = false;
|
|
|
|
|
|
|
|
// Stuff some version info.
|
2001-05-23 15:26:42 +02:00
|
|
|
if (count = node->nod_count)
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, gds_tpb_version1);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
while (count--) {
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* ptr = node->nod_arg[count];
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (!ptr)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
switch (ptr->nod_type) {
|
|
|
|
case nod_access:
|
|
|
|
if (sw_access)
|
|
|
|
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 104,
|
|
|
|
gds_arg_gds, gds_dsql_dup_option, 0);
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
sw_access = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
if (ptr->nod_flags & NOD_READ_ONLY)
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, gds_tpb_read);
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, gds_tpb_write);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_wait:
|
|
|
|
if (sw_wait)
|
|
|
|
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 104,
|
|
|
|
gds_arg_gds, gds_dsql_dup_option, 0);
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
sw_wait = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
if (ptr->nod_flags & NOD_NO_WAIT)
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, gds_tpb_nowait);
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, gds_tpb_wait);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_isolation:
|
|
|
|
if (sw_isolation)
|
|
|
|
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 104,
|
|
|
|
gds_arg_gds, gds_dsql_dup_option, 0);
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
sw_isolation = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (ptr->nod_flags & NOD_CONCURRENCY)
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, gds_tpb_concurrency);
|
2001-05-23 15:26:42 +02:00
|
|
|
else if (ptr->nod_flags & NOD_CONSISTENCY)
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, gds_tpb_consistency);
|
2001-05-23 15:26:42 +02:00
|
|
|
else {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, gds_tpb_read_committed);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if ((ptr->nod_count) && (ptr->nod_arg[0]) &&
|
|
|
|
(ptr->nod_arg[0]->nod_type == nod_version)) {
|
|
|
|
if (ptr->nod_arg[0]->nod_flags & NOD_VERSION)
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, gds_tpb_rec_version);
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, gds_tpb_no_rec_version);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, gds_tpb_no_rec_version);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_reserve:
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
|
|
|
if (sw_reserve)
|
|
|
|
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 104,
|
|
|
|
gds_arg_gds, gds_dsql_dup_option, 0);
|
|
|
|
|
|
|
|
sw_reserve = true;
|
|
|
|
const dsql_nod* reserve = ptr->nod_arg[0];
|
|
|
|
|
|
|
|
if (reserve) {
|
|
|
|
const dsql_nod* const* temp = reserve->nod_arg;
|
|
|
|
for (const dsql_nod* const* end = temp + reserve->nod_count;
|
|
|
|
temp < end; temp++)
|
|
|
|
{
|
|
|
|
gen_table_lock(request, *temp, lock_level);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
default:
|
|
|
|
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 104,
|
|
|
|
gds_arg_gds, gds_dsql_tran_err, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
GEN_statement
|
|
|
|
|
|
|
|
@brief Generate blr for an arbitrary expression.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param node
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
void GEN_statement( dsql_req* request, dsql_nod* node)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* temp;
|
|
|
|
dsql_nod** ptr;
|
|
|
|
const dsql_nod* const* end;
|
|
|
|
dsql_ctx* context;
|
|
|
|
dsql_msg* message;
|
|
|
|
str* name;
|
|
|
|
str* string;
|
2001-05-23 15:26:42 +02:00
|
|
|
ULONG id_length;
|
|
|
|
|
|
|
|
switch (node->nod_type) {
|
|
|
|
case nod_assign:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_assignment);
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, node->nod_arg[0]);
|
|
|
|
GEN_expr(request, node->nod_arg[1]);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_block:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_block);
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_statement(request, node->nod_arg[e_blk_action]);
|
|
|
|
if (node->nod_count > 1) {
|
|
|
|
temp = node->nod_arg[e_blk_errs];
|
|
|
|
for (ptr = temp->nod_arg, end = ptr + temp->nod_count;
|
|
|
|
ptr < end; ptr++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_statement(request, *ptr);
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_erase:
|
|
|
|
if ((temp = node->nod_arg[e_era_rse]) != NULL) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_for);
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, temp);
|
|
|
|
}
|
|
|
|
temp = node->nod_arg[e_era_relation];
|
2003-11-01 11:26:43 +01:00
|
|
|
context = (dsql_ctx*) temp->nod_arg[e_rel_context];
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_erase);
|
|
|
|
stuff(request, context->ctx_context);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_erase_current:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_erase);
|
2003-11-01 11:26:43 +01:00
|
|
|
context = (dsql_ctx*) node->nod_arg[e_erc_context];
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, context->ctx_context);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_exec_procedure:
|
|
|
|
if (request->req_type == REQ_EXEC_PROCEDURE) {
|
|
|
|
if (message = request->req_receive) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_begin);
|
|
|
|
stuff(request, blr_send);
|
|
|
|
stuff(request, message->msg_number);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
message = NULL;
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_exec_proc);
|
2003-11-01 11:26:43 +01:00
|
|
|
name = (str*) node->nod_arg[e_exe_procedure];
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_cstring(request, name->str_data);
|
2001-05-23 15:26:42 +02:00
|
|
|
if (temp = node->nod_arg[e_exe_inputs]) {
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, temp->nod_count);
|
2001-05-23 15:26:42 +02:00
|
|
|
for (ptr = temp->nod_arg, end = ptr + temp->nod_count;
|
|
|
|
ptr < end; ptr++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, *ptr);
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
if (temp = node->nod_arg[e_exe_outputs]) {
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, temp->nod_count);
|
2001-05-23 15:26:42 +02:00
|
|
|
for (ptr = temp->nod_arg, end = ptr + temp->nod_count;
|
|
|
|
ptr < end; ptr++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, *ptr);
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
if (message)
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_for_select:
|
|
|
|
gen_for_select(request, node);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_set_generator:
|
|
|
|
case nod_set_generator2:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_set_generator);
|
2003-11-01 11:26:43 +01:00
|
|
|
string = (str*) node->nod_arg[e_gen_id_name];
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_cstring(request, string->str_data);
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, node->nod_arg[e_gen_id_value]);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_if:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_if);
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, node->nod_arg[e_if_condition]);
|
|
|
|
GEN_statement(request, node->nod_arg[e_if_true]);
|
|
|
|
if (node->nod_arg[e_if_false])
|
|
|
|
GEN_statement(request, node->nod_arg[e_if_false]);
|
|
|
|
else
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_list:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_begin);
|
2001-05-23 15:26:42 +02:00
|
|
|
for (ptr = node->nod_arg, end = ptr + node->nod_count; ptr < end;
|
|
|
|
ptr++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_statement(request, *ptr);
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_modify:
|
|
|
|
if ((temp = node->nod_arg[e_mod_rse]) != NULL) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_for);
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, temp);
|
|
|
|
}
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_modify);
|
2001-05-23 15:26:42 +02:00
|
|
|
temp = node->nod_arg[e_mod_source];
|
2003-11-01 11:26:43 +01:00
|
|
|
context = (dsql_ctx*) temp->nod_arg[e_rel_context];
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, context->ctx_context);
|
2001-05-23 15:26:42 +02:00
|
|
|
temp = node->nod_arg[e_mod_update];
|
2003-11-01 11:26:43 +01:00
|
|
|
context = (dsql_ctx*) temp->nod_arg[e_rel_context];
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, context->ctx_context);
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_statement(request, node->nod_arg[e_mod_statement]);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_modify_current:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_modify);
|
2003-11-01 11:26:43 +01:00
|
|
|
context = (dsql_ctx*) node->nod_arg[e_mdc_context];
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, context->ctx_context);
|
2001-05-23 15:26:42 +02:00
|
|
|
temp = node->nod_arg[e_mdc_update];
|
2003-11-01 11:26:43 +01:00
|
|
|
context = (dsql_ctx*) temp->nod_arg[e_rel_context];
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, context->ctx_context);
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_statement(request, node->nod_arg[e_mdc_statement]);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_on_error:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_error_handler);
|
2001-05-23 15:26:42 +02:00
|
|
|
temp = node->nod_arg[e_err_errs];
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, temp->nod_count);
|
2001-05-23 15:26:42 +02:00
|
|
|
for (ptr = temp->nod_arg, end = ptr + temp->nod_count; ptr < end;
|
|
|
|
ptr++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
gen_error_condition(request, *ptr);
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_statement(request, node->nod_arg[e_err_action]);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_post:
|
2003-01-15 13:00:33 +01:00
|
|
|
if ( (temp = node->nod_arg[e_pst_argument]) ) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_post_arg);
|
2003-01-15 13:00:33 +01:00
|
|
|
GEN_expr(request, node->nod_arg[e_pst_event]);
|
|
|
|
GEN_expr(request, temp);
|
|
|
|
}
|
|
|
|
else {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_post);
|
2003-01-15 13:00:33 +01:00
|
|
|
GEN_expr(request, node->nod_arg[e_pst_event]);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
2002-04-04 15:53:20 +02:00
|
|
|
case nod_exec_sql:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_exec_sql);
|
2003-03-01 20:19:23 +01:00
|
|
|
GEN_expr(request, node->nod_arg[e_exec_sql_stmnt]);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_exec_into:
|
2003-08-26 09:13:33 +02:00
|
|
|
if (node->nod_arg[e_exec_into_block]) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_label);
|
|
|
|
stuff(request, (int) (IPTR) node->nod_arg[e_exec_into_label]->nod_arg[e_label_number]);
|
2003-08-26 09:13:33 +02:00
|
|
|
}
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_exec_into);
|
2003-03-01 20:19:23 +01:00
|
|
|
temp = node->nod_arg[e_exec_into_list];
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, temp->nod_count);
|
2003-03-01 20:19:23 +01:00
|
|
|
GEN_expr(request, node->nod_arg[e_exec_into_stmnt]);
|
|
|
|
if (node->nod_arg[e_exec_into_block]) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, 0); // Non-singleton
|
2003-03-01 20:19:23 +01:00
|
|
|
GEN_statement(request, node->nod_arg[e_exec_into_block]);
|
|
|
|
}
|
|
|
|
else
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, 1); // Singleton
|
2003-03-01 20:19:23 +01:00
|
|
|
for (ptr = temp->nod_arg, end = ptr + temp->nod_count;
|
|
|
|
ptr < end; ptr++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2003-03-01 20:19:23 +01:00
|
|
|
GEN_expr(request, *ptr);
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2002-04-04 15:53:20 +02:00
|
|
|
return;
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
case nod_return:
|
2003-09-04 01:52:47 +02:00
|
|
|
GEN_return(request, node->nod_arg[e_rtn_procedure], false);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_exit:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_leave);
|
|
|
|
stuff(request, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
2002-06-29 08:56:51 +02:00
|
|
|
case nod_breakleave:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_leave);
|
|
|
|
stuff(request, (int) (IPTR) node->nod_arg[e_breakleave_label]->nod_arg[e_label_number]);
|
2002-06-29 08:56:51 +02:00
|
|
|
return;
|
2002-12-18 16:01:50 +01:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
case nod_store:
|
|
|
|
if ((temp = node->nod_arg[e_sto_rse]) != NULL) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_for);
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, temp);
|
|
|
|
}
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_store);
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, node->nod_arg[e_sto_relation]);
|
|
|
|
GEN_statement(request, node->nod_arg[e_sto_statement]);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_abort:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_leave);
|
|
|
|
stuff(request, (int) (IPTR) node->nod_arg[e_abrt_number]);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_start_savepoint:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_start_savepoint);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_end_savepoint:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_end_savepoint);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
2003-06-10 15:40:19 +02:00
|
|
|
|
2002-10-29 21:20:44 +01:00
|
|
|
case nod_user_savepoint:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_user_savepoint);
|
|
|
|
stuff(request, blr_savepoint_set);
|
2003-11-01 11:26:43 +01:00
|
|
|
stuff_cstring(request, ((str*)node->nod_arg[e_sav_name])->str_data);
|
2002-10-29 21:20:44 +01:00
|
|
|
return;
|
2003-06-10 15:40:19 +02:00
|
|
|
|
|
|
|
case nod_release_savepoint:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_user_savepoint);
|
2003-06-26 12:44:16 +02:00
|
|
|
if (node->nod_arg[1]) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_savepoint_release_single);
|
2003-06-26 12:44:16 +02:00
|
|
|
}
|
|
|
|
else {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_savepoint_release);
|
2003-06-26 12:44:16 +02:00
|
|
|
}
|
2003-11-01 11:26:43 +01:00
|
|
|
stuff_cstring(request, ((str*)node->nod_arg[e_sav_name])->str_data);
|
2003-06-10 15:40:19 +02:00
|
|
|
return;
|
|
|
|
|
2002-10-29 21:20:44 +01:00
|
|
|
case nod_undo_savepoint:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_user_savepoint);
|
|
|
|
stuff(request, blr_savepoint_undo);
|
2003-11-01 11:26:43 +01:00
|
|
|
stuff_cstring(request, ((str*)node->nod_arg[e_sav_name])->str_data);
|
2002-10-29 21:20:44 +01:00
|
|
|
return;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
case nod_exception_stmt:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_abort);
|
2003-11-01 11:26:43 +01:00
|
|
|
string = (str*) node->nod_arg[e_xcps_name];
|
2003-10-01 20:11:23 +02:00
|
|
|
temp = node->nod_arg[e_xcps_msg];
|
2002-09-28 16:04:35 +02:00
|
|
|
/* if exception name is undefined,
|
|
|
|
it means we have re-initiate semantics here,
|
|
|
|
so blr_raise verb should be generated */
|
|
|
|
if (!string)
|
|
|
|
{
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_raise);
|
2002-09-28 16:04:35 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* if exception value is defined,
|
|
|
|
it means we have user-defined exception message here,
|
|
|
|
so blr_exception_msg verb should be generated */
|
|
|
|
if (temp)
|
|
|
|
{
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_exception_msg);
|
2002-09-28 16:04:35 +02:00
|
|
|
}
|
|
|
|
/* otherwise go usual way,
|
|
|
|
i.e. generate blr_exception */
|
|
|
|
else
|
|
|
|
{
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_exception);
|
2002-09-28 16:04:35 +02:00
|
|
|
}
|
|
|
|
if (!(string->str_flags & STR_delimited_id))
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
id_length = string->str_length;
|
2003-11-01 11:26:43 +01:00
|
|
|
for (TEXT* p = reinterpret_cast<char*>(string->str_data); *p;
|
2002-09-28 16:04:35 +02:00
|
|
|
id_length--)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
*p = UPPER(*p);
|
|
|
|
*p++;
|
|
|
|
}
|
|
|
|
}
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_cstring(request, string->str_data);
|
2002-09-28 16:04:35 +02:00
|
|
|
/* if exception value is defined,
|
|
|
|
generate appropriate BLR verbs */
|
|
|
|
if (temp)
|
|
|
|
{
|
|
|
|
GEN_expr(request, temp);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_while:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_label);
|
|
|
|
stuff(request, (int) (IPTR) node->nod_arg[e_while_label]->nod_arg[e_label_number]);
|
|
|
|
stuff(request, blr_loop);
|
|
|
|
stuff(request, blr_begin);
|
|
|
|
stuff(request, blr_if);
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, node->nod_arg[e_while_cond]);
|
|
|
|
GEN_statement(request, node->nod_arg[e_while_action]);
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_leave);
|
|
|
|
stuff(request, (int) (IPTR) node->nod_arg[e_while_label]->nod_arg[e_label_number]);
|
|
|
|
stuff(request, blr_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_sqlcode:
|
|
|
|
case nod_gdscode:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_abort);
|
2001-05-23 15:26:42 +02:00
|
|
|
gen_error_condition(request, node);
|
|
|
|
return;
|
|
|
|
|
2003-11-02 13:28:30 +01:00
|
|
|
case nod_cursor:
|
|
|
|
stuff(request, blr_dcl_cursor);
|
|
|
|
stuff_word(request, (int) (IPTR) node->nod_arg[e_cur_number]);
|
|
|
|
GEN_expr(request, node->nod_arg[e_cur_rse]);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_cursor_open:
|
|
|
|
case nod_cursor_close:
|
|
|
|
case nod_cursor_fetch:
|
|
|
|
{
|
|
|
|
// op-code
|
|
|
|
stuff(request, blr_cursor_stmt);
|
|
|
|
if (node->nod_type == nod_cursor_open)
|
|
|
|
stuff(request, blr_cursor_open);
|
|
|
|
else if (node->nod_type == nod_cursor_close)
|
|
|
|
stuff(request, blr_cursor_close);
|
|
|
|
else
|
|
|
|
stuff(request, blr_cursor_fetch);
|
|
|
|
// cursor reference
|
|
|
|
dsql_nod* cursor = node->nod_arg[e_cur_stmt_id];
|
|
|
|
stuff_word(request, (int) (IPTR) cursor->nod_arg[e_cur_number]);
|
|
|
|
// preliminary navigation
|
|
|
|
dsql_nod* seek = node->nod_arg[e_cur_stmt_seek];
|
|
|
|
if (seek) {
|
|
|
|
stuff(request, blr_seek);
|
|
|
|
GEN_expr(request, seek->nod_arg[0]);
|
|
|
|
GEN_expr(request, seek->nod_arg[1]);
|
|
|
|
}
|
|
|
|
// assignment
|
|
|
|
dsql_nod* list_into = node->nod_arg[e_cur_stmt_into];
|
|
|
|
if (list_into) {
|
|
|
|
dsql_nod* list = cursor->nod_arg[e_cur_rse]->nod_arg[e_rse_items];
|
|
|
|
if (list->nod_count != list_into->nod_count)
|
|
|
|
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 313,
|
|
|
|
gds_arg_gds, gds_dsql_count_mismatch, 0);
|
|
|
|
stuff(request, blr_begin);
|
|
|
|
ptr = list->nod_arg;
|
|
|
|
end = ptr + list->nod_count;
|
|
|
|
dsql_nod** ptr_to = list_into->nod_arg;
|
|
|
|
while (ptr < end) {
|
|
|
|
stuff(request, blr_assignment);
|
|
|
|
GEN_expr(request, *ptr++);
|
|
|
|
GEN_expr(request, *ptr_to++);
|
|
|
|
}
|
|
|
|
stuff(request, blr_end);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
default:
|
|
|
|
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 901,
|
2003-11-01 11:26:43 +01:00
|
|
|
gds_arg_gds, gds_dsql_internal_err,
|
|
|
|
gds_arg_gds, gds_node_err, // gen.c: node not supported
|
2001-05-23 15:26:42 +02:00
|
|
|
0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_aggregate
|
|
|
|
|
|
|
|
@brief Generate blr for a relation reference.
|
|
|
|
|
|
|
|
|
|
|
|
@param
|
|
|
|
@param
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_aggregate( dsql_req* request, const dsql_nod* node)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_ctx* context = (dsql_ctx*) node->nod_arg[e_agg_context];
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_aggregate);
|
|
|
|
stuff(request, context->ctx_context);
|
2001-05-23 15:26:42 +02:00
|
|
|
gen_rse(request, node->nod_arg[e_agg_rse]);
|
|
|
|
|
|
|
|
/* Handle GROUP BY clause */
|
|
|
|
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_group_by);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* list = node->nod_arg[e_agg_group];
|
|
|
|
if (list != NULL) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, list->nod_count);
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod** ptr = list->nod_arg;
|
|
|
|
for (const dsql_nod* const* end = ptr + list->nod_count; ptr < end;
|
2001-05-23 15:26:42 +02:00
|
|
|
ptr++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, *ptr);
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* Generate value map */
|
|
|
|
|
|
|
|
gen_map(request, context->ctx_map);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_cast
|
|
|
|
|
|
|
|
@brief Generate BLR for a data-type cast operation
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param node
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_cast( dsql_req* request, const dsql_nod* node)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_cast);
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_fld* field = (dsql_fld*) node->nod_arg[e_cast_target];
|
2003-09-04 01:52:47 +02:00
|
|
|
DDL_put_field_dtype(request, field, true);
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, node->nod_arg[e_cast_source]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_coalesce
|
|
|
|
|
|
|
|
@brief Generate BLR for coalesce function
|
2003-03-31 21:11:55 +02:00
|
|
|
|
|
|
|
Generate the blr values, begin with a cast and then :
|
|
|
|
|
|
|
|
blr_value_if
|
|
|
|
blr_missing
|
|
|
|
blr for expression 1
|
|
|
|
blr_value_if
|
|
|
|
blr_missing
|
|
|
|
blr for expression n
|
|
|
|
blr_null
|
|
|
|
blr for expression n-1
|
2003-02-15 04:01:51 +01:00
|
|
|
|
|
|
|
@param request
|
|
|
|
@param node
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_coalesce( dsql_req* request, const dsql_nod* node)
|
2002-08-03 17:27:20 +02:00
|
|
|
{
|
2003-03-31 21:11:55 +02:00
|
|
|
// blr_value_if is used for building the coalesce function
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* list = node->nod_arg[0];
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_cast);
|
2003-09-04 01:52:47 +02:00
|
|
|
gen_descriptor(request, &node->nod_desc, true);
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* const* ptr = list->nod_arg;
|
|
|
|
for (const dsql_nod* const* const end = ptr + list->nod_count;
|
|
|
|
ptr < end; ptr++)
|
2002-08-03 17:27:20 +02:00
|
|
|
{
|
2003-03-31 21:11:55 +02:00
|
|
|
// IF (expression IS NULL) THEN
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_value_if);
|
|
|
|
stuff(request, blr_missing);
|
2002-08-03 17:27:20 +02:00
|
|
|
GEN_expr(request, *ptr);
|
|
|
|
}
|
2003-03-31 21:11:55 +02:00
|
|
|
// Return values
|
|
|
|
list = node->nod_arg[1];
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* const* const begin = list->nod_arg;
|
|
|
|
ptr = list->nod_arg + list->nod_count;
|
2003-03-31 21:11:55 +02:00
|
|
|
// if all expressions are NULL return NULL
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_null);
|
2003-11-01 11:26:43 +01:00
|
|
|
for (ptr--; ptr >= begin; ptr--)
|
2002-08-03 17:27:20 +02:00
|
|
|
{
|
|
|
|
GEN_expr(request, *ptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_constant
|
|
|
|
|
|
|
|
@brief Generate BLR for a constant.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param desc
|
|
|
|
@param negate_value
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_constant( dsql_req* request, dsc* desc, bool negate_value)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
SLONG value;
|
|
|
|
SINT64 i64value;
|
|
|
|
|
|
|
|
DSC tmp_desc;
|
|
|
|
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_literal);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if ((desc->dsc_dtype == dtype_double)
|
|
|
|
&& (request->req_dbb->dbb_flags & DBB_v3))
|
|
|
|
/* v3 doesn't understand blr_double literal, generate blr_text instead */
|
|
|
|
{
|
|
|
|
tmp_desc = *desc;
|
|
|
|
tmp_desc.dsc_dtype = dtype_text;
|
|
|
|
tmp_desc.dsc_length = desc->dsc_scale; /* length of string literal */
|
|
|
|
tmp_desc.dsc_scale = 0;
|
|
|
|
desc = &tmp_desc;
|
|
|
|
}
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
USHORT l = desc->dsc_length;
|
|
|
|
const UCHAR* p = desc->dsc_address;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
switch (desc->dsc_dtype) {
|
|
|
|
case dtype_short:
|
2003-09-04 01:52:47 +02:00
|
|
|
gen_descriptor(request, desc, true);
|
2001-05-23 15:26:42 +02:00
|
|
|
value = *(SSHORT *) p;
|
|
|
|
if (negate_value)
|
|
|
|
value = -value;
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, value);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_long:
|
2003-09-04 01:52:47 +02:00
|
|
|
gen_descriptor(request, desc, true);
|
2001-05-23 15:26:42 +02:00
|
|
|
value = *(SLONG *) p;
|
|
|
|
if (negate_value)
|
|
|
|
value = -value;
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, value);
|
|
|
|
stuff_word(request, value >> 16);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_sql_time:
|
|
|
|
case dtype_sql_date:
|
2003-09-04 01:52:47 +02:00
|
|
|
gen_descriptor(request, desc, true);
|
2001-05-23 15:26:42 +02:00
|
|
|
value = *(SLONG *) p;
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, value);
|
|
|
|
stuff_word(request, value >> 16);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_double:
|
|
|
|
/* this is used for approximate/large numeric literal
|
|
|
|
which is transmitted to the engine as a string.
|
|
|
|
*/
|
2003-09-04 01:52:47 +02:00
|
|
|
gen_descriptor(request, desc, true);
|
2001-05-23 15:26:42 +02:00
|
|
|
l = (USHORT) desc->dsc_scale; /* length of string literal */
|
|
|
|
if (negate_value) {
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, l + 1);
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, '-');
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else {
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, l);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (l)
|
2003-11-01 11:26:43 +01:00
|
|
|
do {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, *p++);
|
2003-11-01 11:26:43 +01:00
|
|
|
} while (--l);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_int64:
|
|
|
|
i64value = *(SINT64 *) p;
|
|
|
|
|
|
|
|
if (negate_value)
|
|
|
|
i64value = -i64value;
|
|
|
|
else if (i64value == MIN_SINT64) {
|
|
|
|
/* UH OH!
|
|
|
|
* yylex correctly recognized the digits as the most-negative
|
|
|
|
* possible INT64 value, but unfortunately, there was no
|
|
|
|
* preceding '-' (a fact which the lexer could not know).
|
|
|
|
* The value is too big for a positive INT64 value, and it
|
|
|
|
* didn't contain an exponent so it's not a valid DOUBLE
|
|
|
|
* PRECISION literal either, so we have to bounce it.
|
|
|
|
*/
|
|
|
|
ERRD_post(isc_sqlerr,
|
|
|
|
gds_arg_number, (SLONG) - 104,
|
|
|
|
gds_arg_gds, isc_arith_except, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We and the lexer both agree that this is an SINT64 constant,
|
|
|
|
* and if the value needed to be negated, it already has been.
|
|
|
|
* If the value will fit into a 32-bit signed integer, generate
|
|
|
|
* it that way, else as an INT64.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if ((i64value >= (SINT64) MIN_SLONG) &&
|
2003-11-01 11:26:43 +01:00
|
|
|
(i64value <= (SINT64) MAX_SLONG))
|
|
|
|
{
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_long);
|
|
|
|
stuff(request, desc->dsc_scale);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, i64value);
|
|
|
|
stuff_word(request, i64value >> 16);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_int64);
|
|
|
|
stuff(request, desc->dsc_scale);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, i64value);
|
|
|
|
stuff_word(request, i64value >> 16);
|
|
|
|
stuff_word(request, i64value >> 32);
|
|
|
|
stuff_word(request, i64value >> 48);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_quad:
|
|
|
|
case dtype_blob:
|
|
|
|
case dtype_array:
|
|
|
|
case dtype_timestamp:
|
2003-09-04 01:52:47 +02:00
|
|
|
gen_descriptor(request, desc, true);
|
2001-05-23 15:26:42 +02:00
|
|
|
value = *(SLONG *) p;
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, value);
|
|
|
|
stuff_word(request, value >> 16);
|
2001-05-23 15:26:42 +02:00
|
|
|
value = *(SLONG *) (p + 4);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, value);
|
|
|
|
stuff_word(request, value >> 16);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_text:
|
2003-09-04 01:52:47 +02:00
|
|
|
gen_descriptor(request, desc, true);
|
2001-05-23 15:26:42 +02:00
|
|
|
if (l)
|
2003-11-01 11:26:43 +01:00
|
|
|
do {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, *p++);
|
2003-11-01 11:26:43 +01:00
|
|
|
} while (--l);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* gen_constant: datatype not understood */
|
|
|
|
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 103,
|
|
|
|
gds_arg_gds, gds_dsql_constant_err, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_descriptor
|
|
|
|
|
|
|
|
@brief Generate a blr descriptor from an internal descriptor.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param desc
|
|
|
|
@param texttype
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_descriptor( dsql_req* request, const dsc* desc, bool texttype)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
switch (desc->dsc_dtype) {
|
|
|
|
case dtype_text:
|
|
|
|
if (request->req_dbb->dbb_flags & DBB_v3)
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_text);
|
2001-05-23 15:26:42 +02:00
|
|
|
else if (texttype || desc->dsc_ttype == ttype_binary) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_text2);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, desc->dsc_ttype);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_text2); /* automatic transliteration */
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, ttype_dynamic);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, desc->dsc_length);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_varying:
|
|
|
|
if (request->req_dbb->dbb_flags & DBB_v3)
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_varying);
|
2001-05-23 15:26:42 +02:00
|
|
|
else if (texttype || desc->dsc_ttype == ttype_binary) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_varying2);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, desc->dsc_ttype);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_varying2); /* automatic transliteration */
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, ttype_dynamic);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, desc->dsc_length - sizeof(USHORT));
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_short:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_short);
|
|
|
|
stuff(request, desc->dsc_scale);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_long:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_long);
|
|
|
|
stuff(request, desc->dsc_scale);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_quad:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_quad);
|
|
|
|
stuff(request, desc->dsc_scale);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_int64:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_int64);
|
|
|
|
stuff(request, desc->dsc_scale);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_real:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_float);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_double:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_double);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_sql_date:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_sql_date);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_sql_time:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_sql_time);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_timestamp:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_timestamp);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_blob:
|
|
|
|
case dtype_array:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_quad);
|
|
|
|
stuff(request, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* don't understand dtype */
|
|
|
|
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 804,
|
|
|
|
gds_arg_gds, gds_dsql_datatype_err, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_error_condition
|
|
|
|
|
|
|
|
@brief Generate blr for an error condtion
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param node
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_error_condition( dsql_req* request, const dsql_nod* node)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
const str* string;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
switch (node->nod_type) {
|
|
|
|
case nod_sqlcode:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_sql_code);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, (USHORT)(ULONG) node->nod_arg[0]);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_gdscode:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_gds_code);
|
2003-11-01 11:26:43 +01:00
|
|
|
string = (str*) node->nod_arg[0];
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_cstring(request, string->str_data);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_exception:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_exception);
|
2003-11-01 11:26:43 +01:00
|
|
|
string = (str*) node->nod_arg[0];
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_cstring(request, string->str_data);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_default:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_default_code);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
default:
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(false);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_field
|
|
|
|
|
|
|
|
@brief Generate blr for a field - field id's
|
|
|
|
are preferred but not for trigger or view blr.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param context
|
|
|
|
@param field
|
|
|
|
@param indices
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_field( dsql_req* request, const dsql_ctx* context,
|
|
|
|
const dsql_fld* field, dsql_nod* indices)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/* For older clients - generate an error should they try and
|
|
|
|
* access data types which did not exist in the older dialect */
|
|
|
|
if (request->req_client_dialect <= SQL_DIALECT_V5) {
|
|
|
|
switch (field->fld_dtype) {
|
|
|
|
case dtype_sql_date:
|
|
|
|
case dtype_sql_time:
|
|
|
|
case dtype_int64:
|
|
|
|
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 804,
|
|
|
|
gds_arg_gds, gds_dsql_datatype_err,
|
|
|
|
gds_arg_gds, isc_sql_dialect_datatype_unsupport,
|
|
|
|
gds_arg_number, request->req_client_dialect,
|
|
|
|
gds_arg_string,
|
|
|
|
DSC_dtype_tostring(static_cast < UCHAR >
|
|
|
|
(field->fld_dtype)), 0);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* No special action for other data types */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (indices)
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_index);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (DDL_ids(request)) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_fid);
|
|
|
|
stuff(request, context->ctx_context);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, field->fld_id);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_field);
|
|
|
|
stuff(request, context->ctx_context);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_cstring(request, field->fld_name);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (indices) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, indices->nod_count);
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod** ptr = indices->nod_arg;
|
|
|
|
for (const dsql_nod* const* end = ptr + indices->nod_count;
|
2001-05-23 15:26:42 +02:00
|
|
|
ptr < end; ptr++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, *ptr);
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_for_select
|
|
|
|
|
|
|
|
@brief Generate BLR for a SELECT statement.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param for_select
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_for_select( dsql_req* request, dsql_nod* for_select)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* rse = for_select->nod_arg[e_flp_select];
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-06-29 08:56:51 +02:00
|
|
|
/* CVC: Only put a label if this is not singular; otherwise,
|
|
|
|
what loop is the user trying to abandon? */
|
2003-09-28 13:12:03 +02:00
|
|
|
if (for_select->nod_arg[e_flp_action]) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_label);
|
|
|
|
stuff(request, (int) (IPTR) for_select->nod_arg[e_flp_label]->nod_arg[e_label_number]);
|
2002-06-29 08:56:51 +02:00
|
|
|
}
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
/* Generate FOR loop */
|
|
|
|
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_for);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (!for_select->nod_arg[e_flp_action] &&
|
2003-10-01 20:11:23 +02:00
|
|
|
!(request->req_dbb->dbb_flags & DBB_v3))
|
|
|
|
{
|
|
|
|
stuff(request, blr_singular);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
gen_rse(request, rse);
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_begin);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* Build body of FOR loop */
|
|
|
|
|
2002-10-29 21:20:44 +01:00
|
|
|
/* Handle write locks */
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* streams = rse->nod_arg[e_rse_streams];
|
|
|
|
dsql_ctx* context = NULL;
|
2002-10-29 21:20:44 +01:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
if (!rse->nod_arg[e_rse_reduced] && streams->nod_count == 1) {
|
|
|
|
dsql_nod* item = streams->nod_arg[0];
|
2002-10-29 21:20:44 +01:00
|
|
|
if (item && (item->nod_type == nod_relation))
|
2003-11-01 11:26:43 +01:00
|
|
|
context = (dsql_ctx*) item->nod_arg[e_rel_context];
|
2002-10-29 21:20:44 +01:00
|
|
|
}
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* list = rse->nod_arg[e_rse_items];
|
|
|
|
dsql_nod* list_to = for_select->nod_arg[e_flp_into];
|
2001-05-23 15:26:42 +02:00
|
|
|
if (list->nod_count != list_to->nod_count)
|
|
|
|
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 313,
|
|
|
|
gds_arg_gds, gds_dsql_count_mismatch, 0);
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod** ptr = list->nod_arg;
|
|
|
|
dsql_nod** ptr_to = list_to->nod_arg;
|
|
|
|
for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end;
|
|
|
|
ptr++, ptr_to++)
|
|
|
|
{
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_assignment);
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, *ptr);
|
|
|
|
GEN_expr(request, *ptr_to);
|
|
|
|
}
|
|
|
|
if (for_select->nod_arg[e_flp_action])
|
|
|
|
GEN_statement(request, for_select->nod_arg[e_flp_action]);
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_gen_id
|
|
|
|
|
|
|
|
@brief Generate BLR for gen_id
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param node
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_gen_id( dsql_req* request, const dsql_nod* node)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_gen_id);
|
2003-11-01 11:26:43 +01:00
|
|
|
const str* string = (str*) node->nod_arg[e_gen_id_name];
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_cstring(request, string->str_data);
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, node->nod_arg[e_gen_id_value]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_join_rse
|
|
|
|
|
|
|
|
@brief Generate a record selection expression
|
|
|
|
with an explicit join type.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param rse
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_join_rse( dsql_req* request, const dsql_nod* rse)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_rs_stream);
|
|
|
|
stuff(request, 2);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
GEN_expr(request, rse->nod_arg[e_join_left_rel]);
|
|
|
|
GEN_expr(request, rse->nod_arg[e_join_rght_rel]);
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* node = rse->nod_arg[e_join_type];
|
2001-05-23 15:26:42 +02:00
|
|
|
if (node->nod_type != nod_join_inner) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_join_type);
|
2001-05-23 15:26:42 +02:00
|
|
|
if (node->nod_type == nod_join_left)
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_left);
|
2001-05-23 15:26:42 +02:00
|
|
|
else if (node->nod_type == nod_join_right)
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_right);
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_full);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_boolean);
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, rse->nod_arg[e_join_boolean]);
|
|
|
|
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_map
|
|
|
|
|
|
|
|
@brief Generate a value map for a record selection expression.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param map
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_map( dsql_req* request, dsql_map* map)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
USHORT count = 0;
|
|
|
|
dsql_map* temp;
|
2001-05-23 15:26:42 +02:00
|
|
|
for (temp = map; temp; temp = temp->map_next)
|
|
|
|
temp->map_position = count++;
|
|
|
|
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_map);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, count);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
for (temp = map; temp; temp = temp->map_next) {
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, temp->map_position);
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, temp->map_node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_parameter
|
|
|
|
|
|
|
|
@brief Generate a parameter reference.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param parameter
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_parameter( dsql_req* request, const par* parameter)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_msg* message = parameter->par_message;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
const par* null = parameter->par_null;
|
|
|
|
if (null != NULL) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_parameter2);
|
|
|
|
stuff(request, message->msg_number);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, parameter->par_parameter);
|
|
|
|
stuff_word(request, null->par_parameter);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_parameter);
|
|
|
|
stuff(request, message->msg_number);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, parameter->par_parameter);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_plan
|
|
|
|
|
|
|
|
@brief Generate blr for an access plan expression.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param plan_expression
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_plan( dsql_req* request, const dsql_nod* plan_expression)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/* stuff the join type */
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* list = plan_expression->nod_arg[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
if (list->nod_count > 1) {
|
2003-11-01 11:26:43 +01:00
|
|
|
if (plan_expression->nod_arg[0])
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_merge);
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_join);
|
|
|
|
stuff(request, list->nod_count);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* stuff one or more plan items */
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* const* ptr = list->nod_arg;
|
|
|
|
for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end;
|
|
|
|
ptr++)
|
|
|
|
{
|
|
|
|
const dsql_nod* node = *ptr;
|
2001-05-23 15:26:42 +02:00
|
|
|
if (node->nod_type == nod_plan_expr) {
|
|
|
|
gen_plan(request, node);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if we're here, it must be a nod_plan_item */
|
|
|
|
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_retrieve);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* stuff the relation--the relation id itself is redundant except
|
|
|
|
when there is a need to differentiate the base tables of views */
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* arg = node->nod_arg[0];
|
|
|
|
gen_relation(request, (dsql_ctx*) arg->nod_arg[e_rel_context]);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* now stuff the access method for this stream */
|
2003-11-01 11:26:43 +01:00
|
|
|
const str* index_string;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
arg = node->nod_arg[1];
|
|
|
|
switch (arg->nod_type) {
|
|
|
|
case nod_natural:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_sequential);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_index_order:
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_navigational);
|
2003-11-01 11:26:43 +01:00
|
|
|
index_string = (str*) arg->nod_arg[0];
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_cstring(request, index_string->str_data);
|
2003-09-14 17:37:05 +02:00
|
|
|
if (!arg->nod_arg[1])
|
|
|
|
break;
|
|
|
|
// dimitr: FALL INTO, if the plan item is ORDER ... INDEX (...)
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
case nod_index:
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
|
|
|
stuff(request, blr_indices);
|
|
|
|
arg = (arg->nod_type == nod_index) ?
|
|
|
|
arg->nod_arg[0] : arg->nod_arg[1];
|
|
|
|
stuff(request, arg->nod_count);
|
|
|
|
const dsql_nod* const* ptr2 = arg->nod_arg;
|
|
|
|
for (const dsql_nod* const* const end2 = ptr2 + arg->nod_count;
|
|
|
|
ptr2 < end2; ptr2++)
|
|
|
|
{
|
|
|
|
index_string = (str*) * ptr2;
|
|
|
|
stuff_cstring(request, index_string->str_data);
|
|
|
|
}
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(false);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_relation
|
|
|
|
|
|
|
|
@brief Generate blr for a relation reference.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param context
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_relation( dsql_req* request, dsql_ctx* context)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_rel* relation = context->ctx_relation;
|
|
|
|
const dsql_prc* procedure = context->ctx_procedure;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* if this is a trigger or procedure , don't want relation id used */
|
|
|
|
if (relation) {
|
|
|
|
if (DDL_ids(request)) {
|
|
|
|
if (context->ctx_alias)
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_rid2);
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_rid);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, relation->rel_id);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (context->ctx_alias)
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_relation2);
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_relation);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_cstring(request, relation->rel_name);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (context->ctx_alias)
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_cstring(request, context->ctx_alias);
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, context->ctx_context);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2003-08-20 01:34:23 +02:00
|
|
|
else if (procedure) {
|
2001-05-23 15:26:42 +02:00
|
|
|
if (DDL_ids(request)) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_pid);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, procedure->prc_id);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_procedure);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_cstring(request, procedure->prc_name);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, context->ctx_context);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, procedure->prc_in_count);
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* inputs = context->ctx_proc_inputs;
|
|
|
|
if (inputs) {
|
|
|
|
dsql_nod* const* ptr = inputs->nod_arg;
|
|
|
|
for (const dsql_nod* const* const end = ptr + inputs->nod_count;
|
2001-05-23 15:26:42 +02:00
|
|
|
ptr < end; ptr++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, *ptr);
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_return
|
|
|
|
|
|
|
|
@brief Generate blr for a procedure return.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param procedure
|
|
|
|
@param eos_flag
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
void GEN_return( dsql_req* request, const dsql_nod* procedure, bool eos_flag)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
if (!procedure)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!eos_flag)
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_begin);
|
|
|
|
stuff(request, blr_send);
|
|
|
|
stuff(request, 1);
|
|
|
|
stuff(request, blr_begin);
|
2003-08-13 13:09:57 +02:00
|
|
|
|
|
|
|
USHORT outputs = 0;
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* parameters = procedure->nod_arg[e_prc_outputs];
|
2003-08-13 13:09:57 +02:00
|
|
|
if (parameters) {
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* const* ptr = parameters->nod_arg;
|
|
|
|
for (const dsql_nod* const* const end = ptr + parameters->nod_count;
|
|
|
|
ptr < end; ptr++)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
outputs++;
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* parameter = *ptr;
|
|
|
|
const var* variable = (var*) parameter->nod_arg[e_var_variable];
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_assignment);
|
|
|
|
stuff(request, blr_variable);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, variable->var_variable_number);
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_parameter2);
|
|
|
|
stuff(request, variable->var_msg_number);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, variable->var_msg_item);
|
|
|
|
stuff_word(request, variable->var_msg_item + 1);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_assignment);
|
|
|
|
stuff(request, blr_literal);
|
|
|
|
stuff(request, blr_short);
|
|
|
|
stuff(request, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
if (eos_flag)
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, 1);
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_parameter);
|
|
|
|
stuff(request, 1);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, 2 * outputs);
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!eos_flag) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_stall);
|
|
|
|
stuff(request, blr_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_rse
|
|
|
|
|
|
|
|
@brief Generate a record selection expression.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param rse
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_rse( dsql_req* request, const dsql_nod* rse)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
if (rse->nod_arg[e_rse_singleton]
|
2003-10-05 08:27:16 +02:00
|
|
|
&& !(request->req_dbb->dbb_flags & DBB_v3))
|
|
|
|
{
|
|
|
|
stuff(request, blr_singular);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_rse);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* list = rse->nod_arg[e_rse_streams];
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-08-13 13:09:57 +02:00
|
|
|
// Handle source streams
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (list->nod_type == nod_union) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, 1);
|
2001-05-23 15:26:42 +02:00
|
|
|
gen_union(request, rse);
|
|
|
|
}
|
|
|
|
else if (list->nod_type == nod_list) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, list->nod_count);
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* const* ptr = list->nod_arg;
|
|
|
|
for (const dsql_nod* const* const end = ptr + list->nod_count;
|
|
|
|
ptr < end; ptr++)
|
|
|
|
{
|
|
|
|
dsql_nod* node = *ptr;
|
2001-05-23 15:26:42 +02:00
|
|
|
if (node->nod_type == nod_relation ||
|
2003-11-01 11:26:43 +01:00
|
|
|
node->nod_type == nod_aggregate || node->nod_type == nod_join)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, node);
|
2003-08-15 01:34:37 +02:00
|
|
|
}
|
|
|
|
else if (node->nod_type == nod_derived_table) {
|
|
|
|
GEN_expr(request, node->nod_arg[e_derived_table_rse]);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, 1);
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, list);
|
|
|
|
}
|
|
|
|
|
2002-11-18 21:27:24 +01:00
|
|
|
if (rse->nod_arg[e_rse_lock])
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_writelock);
|
2003-08-13 13:09:57 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* node;
|
2003-08-13 13:09:57 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
if ((node = rse->nod_arg[e_rse_first]) != NULL) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_first);
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, node);
|
|
|
|
}
|
|
|
|
|
2002-06-29 08:56:51 +02:00
|
|
|
if ((node = rse->nod_arg [e_rse_skip]) != NULL) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_skip);
|
2002-06-29 08:56:51 +02:00
|
|
|
GEN_expr (request, node);
|
|
|
|
}
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
if ((node = rse->nod_arg[e_rse_boolean]) != NULL) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_boolean);
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, node);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((list = rse->nod_arg[e_rse_sort]) != NULL)
|
|
|
|
gen_sort(request, list);
|
|
|
|
|
|
|
|
if ((list = rse->nod_arg[e_rse_reduced]) != NULL) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_project);
|
|
|
|
stuff(request, list->nod_count);
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod** ptr = list->nod_arg;
|
|
|
|
for (const dsql_nod* const* const end = ptr + list->nod_count;
|
|
|
|
ptr < end; ptr++)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, *ptr);
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* if the user specified an access plan to use, add it here */
|
|
|
|
|
|
|
|
if ((node = rse->nod_arg[e_rse_plan]) != NULL) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_plan);
|
2001-05-23 15:26:42 +02:00
|
|
|
gen_plan(request, node);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef SCROLLABLE_CURSORS
|
|
|
|
/* generate a statement to be executed if the user scrolls
|
|
|
|
in a direction other than forward; a message is sent outside
|
|
|
|
the normal send/receive protocol to specify the direction
|
|
|
|
and offset to scroll; note that we do this only on a SELECT
|
|
|
|
type statement and only when talking to a 4.1 engine or greater */
|
|
|
|
|
|
|
|
if (request->req_type == REQ_SELECT &&
|
2003-11-01 11:26:43 +01:00
|
|
|
request->req_dbb->dbb_base_level >= 5)
|
|
|
|
{
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_receive);
|
|
|
|
stuff(request, request->req_async->msg_number);
|
|
|
|
stuff(request, blr_seek);
|
2003-11-01 11:26:43 +01:00
|
|
|
const par* parameter = request->req_async->msg_parameters;
|
2001-05-23 15:26:42 +02:00
|
|
|
gen_parameter(request, parameter->par_next);
|
|
|
|
gen_parameter(request, parameter);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_searched_case
|
|
|
|
|
|
|
|
@brief Generate BLR for CASE function (searched)
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param node
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_searched_case( dsql_req* request, const dsql_nod* node)
|
2002-08-03 17:27:20 +02:00
|
|
|
{
|
2003-08-13 13:09:57 +02:00
|
|
|
// blr_value_if is used for building the case expression
|
2002-08-03 17:27:20 +02:00
|
|
|
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_cast);
|
2003-09-04 01:52:47 +02:00
|
|
|
gen_descriptor(request, &node->nod_desc, true);
|
2003-11-01 11:26:43 +01:00
|
|
|
const SSHORT count =
|
|
|
|
node->nod_arg[e_searched_case_search_conditions]->nod_count;
|
|
|
|
dsql_nod* boolean_list = node->nod_arg[e_searched_case_search_conditions];
|
|
|
|
dsql_nod* results_list = node->nod_arg[e_searched_case_results];
|
|
|
|
dsql_nod* const* bptr = boolean_list->nod_arg;
|
|
|
|
dsql_nod* const* rptr = results_list->nod_arg;
|
|
|
|
for (const dsql_nod* const* const end = bptr + count; bptr < end;
|
|
|
|
bptr++, rptr++)
|
2002-08-03 17:27:20 +02:00
|
|
|
{
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_value_if);
|
2002-08-03 17:27:20 +02:00
|
|
|
GEN_expr(request, *bptr);
|
|
|
|
GEN_expr(request, *rptr);
|
|
|
|
}
|
2003-08-13 13:09:57 +02:00
|
|
|
// else_result
|
2002-08-03 17:27:20 +02:00
|
|
|
GEN_expr(request, node->nod_arg[e_searched_case_results]->nod_arg[count]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_select
|
|
|
|
|
|
|
|
@brief Generate BLR for a SELECT statement.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param rse
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_select( dsql_req* request, dsql_nod* rse)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_fld* field;
|
|
|
|
const dsql_rel* relation;
|
|
|
|
dsql_ctx* context;
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
SSHORT constant;
|
2003-11-01 11:26:43 +01:00
|
|
|
dsc constant_desc;
|
2001-05-23 15:26:42 +02:00
|
|
|
constant_desc.dsc_dtype = dtype_short;
|
|
|
|
constant_desc.dsc_scale = 0;
|
|
|
|
constant_desc.dsc_sub_type = 0;
|
|
|
|
constant_desc.dsc_flags = 0;
|
|
|
|
constant_desc.dsc_length = sizeof(SSHORT);
|
|
|
|
constant_desc.dsc_address = (UCHAR *) & constant;
|
|
|
|
|
|
|
|
/* Set up parameter for things in the select list */
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* list = rse->nod_arg[e_rse_items];
|
|
|
|
dsql_nod* const* ptr = list->nod_arg;
|
|
|
|
for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end;
|
|
|
|
ptr++)
|
|
|
|
{
|
|
|
|
dsql_nod* item = *ptr;
|
|
|
|
par* parameter = MAKE_parameter(request->req_receive, true, true, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
parameter->par_node = item;
|
|
|
|
MAKE_desc(¶meter->par_desc, item);
|
2003-11-01 11:26:43 +01:00
|
|
|
const char* name_alias = NULL;
|
2003-08-13 13:09:57 +02:00
|
|
|
|
|
|
|
switch(item->nod_type) {
|
|
|
|
case nod_field: {
|
2003-11-01 11:26:43 +01:00
|
|
|
field = (dsql_fld*) item->nod_arg[e_fld_field];
|
2003-08-13 13:09:57 +02:00
|
|
|
name_alias = field->fld_name;
|
2003-11-01 11:26:43 +01:00
|
|
|
context = (dsql_ctx*) item->nod_arg[e_fld_context];
|
2001-05-23 15:26:42 +02:00
|
|
|
if (context->ctx_relation) {
|
|
|
|
parameter->par_rel_name = context->ctx_relation->rel_name;
|
|
|
|
parameter->par_owner_name = context->ctx_relation->rel_owner;
|
|
|
|
}
|
|
|
|
else if (context->ctx_procedure) {
|
|
|
|
parameter->par_rel_name = context->ctx_procedure->prc_name;
|
|
|
|
parameter->par_owner_name = context->ctx_procedure->prc_owner;
|
|
|
|
}
|
2003-08-13 13:09:57 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case nod_dbkey: {
|
2003-11-01 11:26:43 +01:00
|
|
|
parameter->par_name = parameter->par_alias = db_key_name;
|
|
|
|
context = (dsql_ctx*) item->nod_arg[0]->nod_arg[0];
|
2001-05-23 15:26:42 +02:00
|
|
|
parameter->par_rel_name = context->ctx_relation->rel_name;
|
|
|
|
parameter->par_owner_name = context->ctx_relation->rel_owner;
|
2003-08-13 13:09:57 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case nod_alias: {
|
2003-11-01 11:26:43 +01:00
|
|
|
const str* string = (str*) item->nod_arg[e_alias_alias];
|
|
|
|
parameter->par_alias = reinterpret_cast<const TEXT*>(string->str_data);
|
|
|
|
dsql_nod* alias = item->nod_arg[e_alias_value];
|
2001-05-23 15:26:42 +02:00
|
|
|
if (alias->nod_type == nod_field) {
|
2003-11-01 11:26:43 +01:00
|
|
|
field = (dsql_fld*) alias->nod_arg[e_fld_field];
|
2001-05-23 15:26:42 +02:00
|
|
|
parameter->par_name = field->fld_name;
|
2003-11-01 11:26:43 +01:00
|
|
|
context = (dsql_ctx*) alias->nod_arg[e_fld_context];
|
2001-05-23 15:26:42 +02:00
|
|
|
if (context->ctx_relation) {
|
|
|
|
parameter->par_rel_name = context->ctx_relation->rel_name;
|
|
|
|
parameter->par_owner_name =
|
|
|
|
context->ctx_relation->rel_owner;
|
|
|
|
}
|
|
|
|
else if (context->ctx_procedure) {
|
|
|
|
parameter->par_rel_name =
|
|
|
|
context->ctx_procedure->prc_name;
|
|
|
|
parameter->par_owner_name =
|
|
|
|
context->ctx_procedure->prc_owner;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (alias->nod_type == nod_dbkey) {
|
2003-08-13 13:09:57 +02:00
|
|
|
parameter->par_name = const_cast<char*>(db_key_name);
|
2003-11-01 11:26:43 +01:00
|
|
|
context = (dsql_ctx*) alias->nod_arg[0]->nod_arg[0];
|
2001-05-23 15:26:42 +02:00
|
|
|
parameter->par_rel_name = context->ctx_relation->rel_name;
|
|
|
|
parameter->par_owner_name = context->ctx_relation->rel_owner;
|
|
|
|
}
|
2003-08-13 13:09:57 +02:00
|
|
|
break;
|
|
|
|
}
|
2003-09-04 17:02:22 +02:00
|
|
|
case nod_derived_field: {
|
2003-11-01 11:26:43 +01:00
|
|
|
const str* string = (str*) item->nod_arg[e_derived_field_name];
|
|
|
|
parameter->par_alias = reinterpret_cast<const TEXT*>(string->str_data);
|
|
|
|
dsql_nod* alias = item->nod_arg[e_derived_field_value];
|
2003-09-04 17:02:22 +02:00
|
|
|
if (alias->nod_type == nod_field) {
|
2003-11-01 11:26:43 +01:00
|
|
|
field = (dsql_fld*) alias->nod_arg[e_fld_field];
|
2003-09-04 17:02:22 +02:00
|
|
|
parameter->par_name = field->fld_name;
|
2003-11-01 11:26:43 +01:00
|
|
|
context = (dsql_ctx*) alias->nod_arg[e_fld_context];
|
2003-09-04 17:02:22 +02:00
|
|
|
if (context->ctx_relation) {
|
|
|
|
parameter->par_rel_name = context->ctx_relation->rel_name;
|
|
|
|
parameter->par_owner_name =
|
|
|
|
context->ctx_relation->rel_owner;
|
|
|
|
}
|
|
|
|
else if (context->ctx_procedure) {
|
|
|
|
parameter->par_rel_name =
|
|
|
|
context->ctx_procedure->prc_name;
|
|
|
|
parameter->par_owner_name =
|
|
|
|
context->ctx_procedure->prc_owner;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (alias->nod_type == nod_dbkey) {
|
|
|
|
parameter->par_name = const_cast<char*>(db_key_name);
|
2003-11-01 11:26:43 +01:00
|
|
|
context = (dsql_ctx*) alias->nod_arg[0]->nod_arg[0];
|
2003-09-04 17:02:22 +02:00
|
|
|
parameter->par_rel_name = context->ctx_relation->rel_name;
|
|
|
|
parameter->par_owner_name = context->ctx_relation->rel_owner;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2003-08-13 13:09:57 +02:00
|
|
|
case nod_map: {
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_map* map = (dsql_map*) item->nod_arg[e_map_map];
|
|
|
|
const dsql_nod* map_node = map->map_node;
|
2001-05-23 15:26:42 +02:00
|
|
|
while (map_node->nod_type == nod_map) {
|
2003-08-13 13:09:57 +02:00
|
|
|
// skip all the nod_map nodes
|
2003-11-01 11:26:43 +01:00
|
|
|
map = (dsql_map*) map_node->nod_arg[e_map_map];
|
2001-05-23 15:26:42 +02:00
|
|
|
map_node = map->map_node;
|
|
|
|
}
|
2003-08-13 13:09:57 +02:00
|
|
|
switch(map_node->nod_type) {
|
|
|
|
case nod_field: {
|
2003-11-01 11:26:43 +01:00
|
|
|
field = (dsql_fld*) map_node->nod_arg[e_fld_field];
|
2003-08-13 13:09:57 +02:00
|
|
|
name_alias = field->fld_name;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case nod_alias: {
|
2003-11-01 11:26:43 +01:00
|
|
|
const str* string = (str*) map_node->nod_arg[e_alias_alias];
|
|
|
|
parameter->par_alias = reinterpret_cast<const TEXT*>(string->str_data);
|
|
|
|
dsql_nod* alias = map_node->nod_arg[e_alias_value];
|
2001-05-23 15:26:42 +02:00
|
|
|
if (alias->nod_type == nod_field) {
|
2003-11-01 11:26:43 +01:00
|
|
|
field = (dsql_fld*) alias->nod_arg[e_fld_field];
|
2001-05-23 15:26:42 +02:00
|
|
|
parameter->par_name = field->fld_name;
|
|
|
|
}
|
2003-08-13 13:09:57 +02:00
|
|
|
break;
|
|
|
|
}
|
2003-09-04 17:02:22 +02:00
|
|
|
case nod_derived_field: {
|
2003-11-01 11:26:43 +01:00
|
|
|
const str* string = (str*) map_node->nod_arg[e_derived_field_name];
|
|
|
|
parameter->par_alias = reinterpret_cast<const TEXT*>(string->str_data);
|
|
|
|
dsql_nod* alias = map_node->nod_arg[e_derived_field_value];
|
2003-09-04 17:02:22 +02:00
|
|
|
if (alias->nod_type == nod_field) {
|
2003-11-01 11:26:43 +01:00
|
|
|
field = (dsql_fld*) alias->nod_arg[e_fld_field];
|
2003-09-04 17:02:22 +02:00
|
|
|
parameter->par_name = field->fld_name;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2003-08-13 13:09:57 +02:00
|
|
|
case nod_agg_count:
|
|
|
|
name_alias = "COUNT";
|
|
|
|
break;
|
|
|
|
case nod_agg_total:
|
|
|
|
name_alias = "SUM";
|
|
|
|
break;
|
|
|
|
case nod_agg_average:
|
|
|
|
name_alias = "AVG";
|
|
|
|
break;
|
|
|
|
case nod_agg_total2:
|
|
|
|
name_alias = "SUM";
|
|
|
|
break;
|
|
|
|
case nod_agg_average2:
|
|
|
|
name_alias = "AVG";
|
|
|
|
break;
|
|
|
|
case nod_agg_min:
|
|
|
|
name_alias = "MIN";
|
|
|
|
break;
|
|
|
|
case nod_agg_max:
|
|
|
|
name_alias = "MAX";
|
|
|
|
break;
|
|
|
|
} // switch(map_node->nod_type)
|
|
|
|
break;
|
2003-11-01 11:26:43 +01:00
|
|
|
} // case nod_map
|
|
|
|
case nod_udf:
|
|
|
|
{
|
|
|
|
udf* userFunc = (UDF) item->nod_arg[0];
|
|
|
|
name_alias = userFunc->udf_name;
|
2003-08-13 13:09:57 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case nod_gen_id:
|
|
|
|
name_alias = "GEN_ID";
|
|
|
|
break;
|
|
|
|
case nod_gen_id2:
|
|
|
|
name_alias = "GEN_ID";
|
|
|
|
break;
|
|
|
|
case nod_user_name:
|
|
|
|
name_alias = "USER";
|
|
|
|
break;
|
|
|
|
case nod_current_role:
|
|
|
|
name_alias = "ROLE";
|
|
|
|
break;
|
2003-11-01 11:26:43 +01:00
|
|
|
case nod_internal_info:
|
|
|
|
{
|
2002-09-28 16:04:35 +02:00
|
|
|
internal_info_id id =
|
|
|
|
*reinterpret_cast<internal_info_id*>(item->nod_arg[0]->nod_desc.dsc_address);
|
2003-08-13 13:09:57 +02:00
|
|
|
name_alias = InternalInfo::getAlias(id);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case nod_concatenate:
|
|
|
|
name_alias = "CONCATENATION";
|
|
|
|
break;
|
2003-11-02 13:28:30 +01:00
|
|
|
case nod_substr:
|
2003-08-13 13:09:57 +02:00
|
|
|
name_alias = "SUBSTRING";
|
|
|
|
break;
|
|
|
|
case nod_cast:
|
|
|
|
name_alias = "CAST";
|
|
|
|
break;
|
|
|
|
case nod_upcase:
|
|
|
|
name_alias = "UPPER";
|
|
|
|
break;
|
|
|
|
case nod_current_date:
|
|
|
|
name_alias = "CURRENT_DATE";
|
|
|
|
break;
|
|
|
|
case nod_current_time:
|
|
|
|
name_alias = "CURRENT_TIME";
|
|
|
|
break;
|
|
|
|
case nod_current_timestamp:
|
|
|
|
name_alias = "CURRENT_TIMESTAMP";
|
|
|
|
break;
|
|
|
|
case nod_extract:
|
|
|
|
name_alias = "EXTRACT";
|
|
|
|
break;
|
|
|
|
case nod_searched_case:
|
|
|
|
case nod_simple_case:
|
|
|
|
name_alias = "CASE";
|
|
|
|
break;
|
|
|
|
case nod_coalesce:
|
|
|
|
name_alias = "COALESCE";
|
|
|
|
break;
|
|
|
|
} // end switch(item->nod_type)
|
|
|
|
if (name_alias)
|
|
|
|
parameter->par_name = parameter->par_alias = name_alias;
|
|
|
|
} // for (ptr = list->nod_arg
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-08-13 13:09:57 +02:00
|
|
|
// Set up parameter to handle EOF
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-08-13 13:09:57 +02:00
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
par* parameter_eof = MAKE_parameter(request->req_receive, false, false, 0);
|
2003-08-13 13:09:57 +02:00
|
|
|
request->req_eof = parameter_eof;
|
|
|
|
parameter_eof->par_desc.dsc_dtype = dtype_short;
|
|
|
|
parameter_eof->par_desc.dsc_scale = 0;
|
|
|
|
parameter_eof->par_desc.dsc_length = sizeof(SSHORT);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Save DBKEYs for possible update later
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
list = rse->nod_arg[e_rse_streams];
|
|
|
|
|
|
|
|
if (!rse->nod_arg[e_rse_reduced]) {
|
2003-11-01 11:26:43 +01:00
|
|
|
ptr = list->nod_arg;
|
|
|
|
for (const dsql_nod* const* const end2 = ptr + list->nod_count;
|
|
|
|
ptr < end2; ptr++)
|
|
|
|
{
|
|
|
|
dsql_nod* item = *ptr;
|
2003-08-13 13:09:57 +02:00
|
|
|
if (item && item->nod_type == nod_relation) {
|
2003-11-01 11:26:43 +01:00
|
|
|
context = (dsql_ctx*) item->nod_arg[e_rel_context];
|
2001-05-23 15:26:42 +02:00
|
|
|
if (relation = context->ctx_relation) {
|
2003-08-13 13:09:57 +02:00
|
|
|
// Set up dbkey
|
2003-11-01 11:26:43 +01:00
|
|
|
par* parameter =
|
2003-09-04 01:52:47 +02:00
|
|
|
MAKE_parameter(request->req_receive, false, false, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
parameter->par_dbkey_ctx = context;
|
|
|
|
parameter->par_desc.dsc_dtype = dtype_text;
|
|
|
|
parameter->par_desc.dsc_ttype = ttype_binary;
|
|
|
|
parameter->par_desc.dsc_length =
|
|
|
|
relation->rel_dbkey_length;
|
|
|
|
|
2003-08-13 13:09:57 +02:00
|
|
|
// Set up record version - for post v33 databases
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (!(request->req_dbb->dbb_flags & DBB_v3)) {
|
|
|
|
parameter =
|
2003-09-04 01:52:47 +02:00
|
|
|
MAKE_parameter(request->req_receive, false,
|
|
|
|
false, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
parameter->par_rec_version_ctx = context;
|
|
|
|
parameter->par_desc.dsc_dtype = dtype_text;
|
|
|
|
parameter->par_desc.dsc_ttype = ttype_binary;
|
|
|
|
parameter->par_desc.dsc_length =
|
|
|
|
relation->rel_dbkey_length / 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-08-13 13:09:57 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef SCROLLABLE_CURSORS
|
|
|
|
/* define the parameters for the scrolling message--offset and direction,
|
|
|
|
in that order to make it easier to generate the request */
|
|
|
|
|
|
|
|
if (request->req_type == REQ_SELECT &&
|
2003-11-01 11:26:43 +01:00
|
|
|
request->req_dbb->dbb_base_level >= 5)
|
|
|
|
{
|
|
|
|
par* parameter = MAKE_parameter(request->req_async, false, false, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
parameter->par_desc.dsc_dtype = dtype_short;
|
|
|
|
parameter->par_desc.dsc_length = sizeof(USHORT);
|
|
|
|
parameter->par_desc.dsc_scale = 0;
|
|
|
|
parameter->par_desc.dsc_flags = 0;
|
|
|
|
parameter->par_desc.dsc_sub_type = 0;
|
|
|
|
|
2003-09-04 01:52:47 +02:00
|
|
|
parameter = MAKE_parameter(request->req_async, false, false, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
parameter->par_desc.dsc_dtype = dtype_long;
|
|
|
|
parameter->par_desc.dsc_length = sizeof(ULONG);
|
|
|
|
parameter->par_desc.dsc_scale = 0;
|
|
|
|
parameter->par_desc.dsc_flags = 0;
|
|
|
|
parameter->par_desc.dsc_sub_type = 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2003-08-13 13:09:57 +02:00
|
|
|
// Generate definitions for the messages
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
GEN_port(request, request->req_receive);
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_msg* message = request->req_send;
|
2001-05-23 15:26:42 +02:00
|
|
|
if (message->msg_parameter)
|
|
|
|
GEN_port(request, message);
|
|
|
|
else
|
|
|
|
request->req_send = NULL;
|
|
|
|
#ifdef SCROLLABLE_CURSORS
|
|
|
|
if (request->req_type == REQ_SELECT &&
|
|
|
|
request->req_dbb->dbb_base_level >= 5)
|
|
|
|
GEN_port(request, request->req_async);
|
|
|
|
#endif
|
|
|
|
|
2003-08-13 13:09:57 +02:00
|
|
|
// If there is a send message, build a RECEIVE
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if ((message = request->req_send) != NULL) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_receive);
|
|
|
|
stuff(request, message->msg_number);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2003-08-13 13:09:57 +02:00
|
|
|
// Generate FOR loop
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
message = request->req_receive;
|
|
|
|
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_for);
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!(request->req_dbb->dbb_flags & DBB_v3))
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_stall);
|
2002-11-18 21:27:24 +01:00
|
|
|
gen_rse(request, rse);
|
2003-11-02 13:28:30 +01:00
|
|
|
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_send);
|
|
|
|
stuff(request, message->msg_number);
|
|
|
|
stuff(request, blr_begin);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-08-13 13:09:57 +02:00
|
|
|
// Build body of FOR loop
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-08-13 13:09:57 +02:00
|
|
|
// Add invalid usage here
|
2002-10-29 21:20:44 +01:00
|
|
|
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_assignment);
|
2001-05-23 15:26:42 +02:00
|
|
|
constant = 1;
|
|
|
|
gen_constant(request, &constant_desc, USE_VALUE);
|
|
|
|
gen_parameter(request, request->req_eof);
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
for (par* parameter = message->msg_parameters; parameter;
|
2001-05-23 15:26:42 +02:00
|
|
|
parameter = parameter->par_next) {
|
|
|
|
if (parameter->par_node) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_assignment);
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, parameter->par_node);
|
|
|
|
gen_parameter(request, parameter);
|
|
|
|
}
|
|
|
|
if (context = parameter->par_dbkey_ctx) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_assignment);
|
|
|
|
stuff(request, blr_dbkey);
|
|
|
|
stuff(request, context->ctx_context);
|
2001-05-23 15:26:42 +02:00
|
|
|
gen_parameter(request, parameter);
|
|
|
|
}
|
|
|
|
if (context = parameter->par_rec_version_ctx) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_assignment);
|
|
|
|
stuff(request, blr_record_version);
|
|
|
|
stuff(request, context->ctx_context);
|
2001-05-23 15:26:42 +02:00
|
|
|
gen_parameter(request, parameter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_end);
|
|
|
|
stuff(request, blr_send);
|
|
|
|
stuff(request, message->msg_number);
|
|
|
|
stuff(request, blr_assignment);
|
2001-05-23 15:26:42 +02:00
|
|
|
constant = 0;
|
|
|
|
gen_constant(request, &constant_desc, USE_VALUE);
|
|
|
|
gen_parameter(request, request->req_eof);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_simple_case
|
|
|
|
|
|
|
|
@brief Generate BLR for CASE function (simple)
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param node
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_simple_case( dsql_req* request, const dsql_nod* node)
|
2002-08-03 17:27:20 +02:00
|
|
|
{
|
|
|
|
/* blr_value_if is used for building the case expression */
|
|
|
|
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_cast);
|
2003-09-04 01:52:47 +02:00
|
|
|
gen_descriptor(request, &node->nod_desc, true);
|
2002-08-03 17:27:20 +02:00
|
|
|
SSHORT count = node->nod_arg[e_simple_case_when_operands]->nod_count;
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* when_list = node->nod_arg[e_simple_case_when_operands];
|
|
|
|
dsql_nod* results_list = node->nod_arg[e_simple_case_results];
|
2003-08-13 13:09:57 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* const* wptr = when_list->nod_arg;
|
|
|
|
dsql_nod* const* rptr = results_list->nod_arg;
|
|
|
|
for (const dsql_nod* const* const end = wptr + count; wptr < end;
|
|
|
|
wptr++, rptr++)
|
2002-08-03 17:27:20 +02:00
|
|
|
{
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_value_if);
|
|
|
|
stuff(request, blr_eql);
|
2002-08-03 17:27:20 +02:00
|
|
|
GEN_expr(request, node->nod_arg[e_simple_case_case_operand]);
|
|
|
|
GEN_expr(request, *wptr);
|
|
|
|
GEN_expr(request, *rptr);
|
|
|
|
}
|
|
|
|
/* else_result */
|
|
|
|
GEN_expr(request, node->nod_arg[e_simple_case_results]->nod_arg[count]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_sort
|
|
|
|
|
|
|
|
@brief Generate a sort clause.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param list
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_sort( dsql_req* request, dsql_nod* list)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_sort);
|
|
|
|
stuff(request, list->nod_count);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* const* ptr = list->nod_arg;
|
|
|
|
for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end;
|
|
|
|
ptr++)
|
|
|
|
{
|
2002-09-10 20:28:23 +02:00
|
|
|
if ((*ptr)->nod_arg[e_order_nulls])
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_nullsfirst);
|
2002-09-10 20:28:23 +02:00
|
|
|
if ((*ptr)->nod_arg[e_order_flag])
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_descending);
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_ascending);
|
2002-09-10 20:28:23 +02:00
|
|
|
GEN_expr(request, (*ptr)->nod_arg[e_order_field]);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_table_lock
|
|
|
|
|
|
|
|
@brief Generate tpb for table lock.
|
|
|
|
If lock level is specified, it overrrides the transaction lock level.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param tbl_lock
|
|
|
|
@param lock_level
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_table_lock( dsql_req* request, const dsql_nod* tbl_lock,
|
|
|
|
USHORT lock_level)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
if ((!tbl_lock) || (tbl_lock->nod_type != nod_table_lock))
|
|
|
|
return;
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* tbl_names = tbl_lock->nod_arg[e_lock_tables];
|
2003-08-13 13:09:57 +02:00
|
|
|
SSHORT flags = 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (tbl_lock->nod_arg[e_lock_mode])
|
|
|
|
flags = tbl_lock->nod_arg[e_lock_mode]->nod_flags;
|
|
|
|
|
|
|
|
if (flags & NOD_PROTECTED)
|
|
|
|
lock_level = gds_tpb_protected;
|
|
|
|
else if (flags & NOD_SHARED)
|
|
|
|
lock_level = gds_tpb_shared;
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
const USHORT lock_mode = (flags & NOD_WRITE) ?
|
|
|
|
gds_tpb_lock_write : gds_tpb_lock_read;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* const* ptr = tbl_names->nod_arg;
|
|
|
|
for (const dsql_nod* const* const end = ptr + tbl_names->nod_count;
|
|
|
|
ptr < end; ptr++)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
if ((*ptr)->nod_type != nod_relation_name)
|
|
|
|
continue;
|
|
|
|
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, lock_mode);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* stuff table name */
|
2003-11-01 11:26:43 +01:00
|
|
|
const str* temp = (str*) ((*ptr)->nod_arg[e_rln_name]);
|
|
|
|
stuff_cstring(request, reinterpret_cast<const char*>(temp->str_data));
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, lock_level);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_udf
|
|
|
|
|
|
|
|
@brief Generate a user defined function.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param node
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_udf( dsql_req* request, const dsql_nod* node)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
const udf* userFunc = (UDF) node->nod_arg[0];
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_function);
|
2003-11-01 11:26:43 +01:00
|
|
|
stuff_cstring(request, userFunc->udf_name);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* list;
|
2001-05-23 15:26:42 +02:00
|
|
|
if ((node->nod_count == 2) && (list = node->nod_arg[1])) {
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, list->nod_count);
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* const* ptr = list->nod_arg;
|
|
|
|
for (const dsql_nod* const* const end = ptr + list->nod_count;
|
|
|
|
ptr < end; ptr++)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, *ptr);
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
gen_union
|
|
|
|
|
|
|
|
@brief Generate a union of substreams.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param union_node
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void gen_union( dsql_req* request, const dsql_nod* union_node)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_union);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-08-26 09:13:33 +02:00
|
|
|
// Obtain the context for UNION from the first DSQL_MAP node
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* items = union_node->nod_arg[e_rse_items];
|
|
|
|
dsql_nod* map_item = items->nod_arg[0];
|
2003-09-04 17:02:22 +02:00
|
|
|
// AB: First item could be a virtual field generated by derived table.
|
|
|
|
if (map_item->nod_type == nod_derived_field) {
|
2003-08-15 01:34:37 +02:00
|
|
|
map_item = map_item->nod_arg[e_alias_value];
|
|
|
|
}
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_ctx* union_context = (dsql_ctx*) map_item->nod_arg[e_map_context];
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, union_context->ctx_context);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* streams = union_node->nod_arg[e_rse_streams];
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, streams->nod_count); /* number of substreams */
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod** ptr = streams->nod_arg;
|
|
|
|
for (const dsql_nod* const* const end = ptr + streams->nod_count; ptr < end;
|
|
|
|
ptr++)
|
|
|
|
{
|
|
|
|
dsql_nod* sub_rse = *ptr;
|
2001-05-23 15:26:42 +02:00
|
|
|
gen_rse(request, sub_rse);
|
|
|
|
items = sub_rse->nod_arg[e_rse_items];
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, blr_map);
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, items->nod_count);
|
2003-08-13 13:09:57 +02:00
|
|
|
USHORT count = 0;
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod** iptr = items->nod_arg;
|
|
|
|
for (const dsql_nod* const* const iend = iptr + items->nod_count;
|
|
|
|
iptr < iend; iptr++)
|
|
|
|
{
|
2003-09-28 02:36:28 +02:00
|
|
|
stuff_word(request, count);
|
2001-05-23 15:26:42 +02:00
|
|
|
GEN_expr(request, *iptr);
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
stuff_cstring
|
|
|
|
|
|
|
|
@brief Write out a string with one byte of length.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param string
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void stuff_cstring( dsql_req* request, const char* string)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
UCHAR c;
|
|
|
|
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, strlen(string));
|
2001-05-23 15:26:42 +02:00
|
|
|
while ((c = *string++))
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, c);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
stuff_word
|
|
|
|
|
|
|
|
@brief Cram a word into the blr buffer. If the buffer is getting
|
|
|
|
ready to overflow, expand it.
|
|
|
|
|
|
|
|
|
|
|
|
@param request
|
|
|
|
@param word
|
|
|
|
|
|
|
|
**/
|
2003-11-01 11:26:43 +01:00
|
|
|
static void stuff_word( dsql_req* request, USHORT word)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
|
2003-10-01 20:11:23 +02:00
|
|
|
stuff(request, word);
|
|
|
|
stuff(request, word >> 8);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2003-11-01 11:26:43 +01:00
|
|
|
|