📄 gen.c
字号:
/* * PROGRAM: Dynamic SQL runtime support * MODULE: gen.c * 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. * Contributor(s): ______________________________________. * 2001.6.21 Claudio Valderrama: BREAK and SUBSTRING. * 2001.07.28: John Bellardo: Added code to generate blr_skip. *//*$Id: gen.c,v 1.1 2001/10/13 10:21:52 dimitr Exp $*/#include <string.h>#include "../dsql/dsql.h"#include "../jrd/gds.h"#include "../jrd/align.h"#include "../dsql/node.h" #include "../jrd/intl.h"#include "../dsql/sym.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"#include "../jrd/thd_proto.h"#include "../jrd/dsc_proto.h"#include "../jrd/iberror.h"ASSERT_FILENAMEstatic void gen_aggregate (REQ, NOD);static void gen_cast (REQ, NOD);static void gen_constant (REQ, DSC *, USHORT);static void gen_descriptor (REQ, DSC *, USHORT);static void gen_error_condition (REQ, NOD);static void gen_field (REQ, CTX, FLD, NOD);static void gen_for_select (REQ, NOD);static void gen_gen_id (REQ, NOD);static void gen_join_rse (REQ, NOD);static void gen_map (REQ, MAP);static void gen_parameter (REQ, PAR);static void gen_plan (REQ, NOD);static void gen_relation (REQ, CTX);static void gen_rse (REQ, NOD);static void gen_select (REQ, NOD);static void gen_sort (REQ, NOD);static void gen_table_lock (REQ, NOD, USHORT);static void gen_udf (REQ, NOD);static void gen_union (REQ, NOD);static void stuff_cstring (REQ, UCHAR *);static void stuff_word (REQ, USHORT);static CONST SCHAR db_key_name [] = "DB_KEY";/* STUFF is defined in dsql.h for use in common with ddl.c */#define STUFF_WORD(word) stuff_word (request, (USHORT)(word))#define STUFF_CSTRING(cstring) stuff_cstring (request, (UCHAR *) (cstring))/* The following are passed as the third argument to gen_constant */#define NEGATE_VALUE TRUE#define USE_VALUE FALSEUCHAR GEN_expand_buffer ( REQ request, UCHAR byte){/************************************** * * G E N _ e x p a n d _ b u f f e r * ************************************** * * Functional description * The blr buffer needs to be expanded. * **************************************/ULONG length;ULONG copy_length;PLB pool;STR new_buffer;BLOB_PTR *p; /* one huge pointer per line for LIBS */BLOB_PTR *q; /* one huge pointer per line for LIBS */BLOB_PTR *end; /* one huge pointer per line for LIBS */TSQL tdsql;tdsql = GET_THREAD_DATA;length = request->req_blr_string->str_length + 2048L;pool = (request->req_blr_string->str_header.blk_pool_id == DSQL_permanent_pool->plb_pool_id) ? DSQL_permanent_pool : tdsql->tsql_default;new_buffer = (STR) ALLOCV (type_str, pool, length);new_buffer->str_length = length;p = new_buffer->str_data;q = request->req_blr_string->str_data;end = request->req_blr;copy_length = (ULONG)( end - q);memcpy( p, q, copy_length);ALLD_release (request->req_blr_string);request->req_blr_string = new_buffer;request->req_blr = p + copy_length;request->req_blr_yellow = new_buffer->str_data + length;return (*request->req_blr++ = byte);}void GEN_expr ( REQ request, NOD node){/************************************** * * G E N _ e x p r * ************************************** * * Functional description * Generate blr for an arbitrary expression. * **************************************/UCHAR operator;NOD *ptr, *end, ddl_node;CTX context;MAP map;VAR variable;DSC desc;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; case nod_extract: STUFF (blr_extract); STUFF (*(SLONG *)node->nod_arg[e_extract_part]->nod_desc.dsc_address); GEN_expr (request, node->nod_arg [e_extract_value]); return; case nod_dbkey: node = node->nod_arg [0]; context = (CTX) node->nod_arg [e_rel_context]; STUFF (blr_dbkey); STUFF (context->ctx_context); return; case nod_rec_version: node = node->nod_arg [0]; context = (CTX) node->nod_arg [e_rel_context]; STUFF (blr_record_version); STUFF (context->ctx_context); 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)) ERRD_post (gds__sqlerr, gds_arg_number, (SLONG) -901, gds_arg_gds, gds__dsql_domain_err, 0); STUFF (blr_fid); STUFF (0); /* Context */ STUFF_WORD (0); /* Field id */ return; case nod_field: gen_field (request, (CTX) node->nod_arg [e_fld_context], (FLD) node->nod_arg [e_fld_field], node->nod_arg [e_fld_indices]); return; case nod_user_name: STUFF (blr_user_name); return; case nod_current_time: STUFF (blr_current_time); return; case nod_current_timestamp: STUFF (blr_current_timestamp); return; case nod_current_date: STUFF (blr_current_date); return; case nod_current_role: STUFF (blr_current_role); return; case nod_breakleave: STUFF (blr_leave); STUFF (0); return; case nod_udf: gen_udf (request, node); return; case nod_variable: variable = (VAR) node->nod_arg[e_var_variable]; if (variable->var_flags & VAR_input) { STUFF (blr_parameter2); STUFF (variable->var_msg_number); STUFF_WORD (variable->var_msg_item); STUFF_WORD (variable->var_msg_item + 1); } else { STUFF (blr_variable); STUFF_WORD (variable->var_variable_number); } return; case nod_join: gen_join_rse (request, node); return; case nod_map: map = (MAP) node->nod_arg [e_map_map]; context = (CTX) node->nod_arg [e_map_context]; STUFF (blr_fid); STUFF (context->ctx_context); STUFF_WORD (map->map_position); return; case nod_parameter: gen_parameter (request, (PAR) node->nod_arg [e_par_parameter]); return; case nod_relation: gen_relation (request, (CTX) node->nod_arg [e_rel_context]); return; case nod_rse: gen_rse (request, node); return; case nod_exists: STUFF (blr_any); gen_rse (request, node->nod_arg[0]); return; case nod_singular: STUFF (blr_unique); gen_rse (request, node->nod_arg[0]); return; case nod_agg_count: if (!(request->req_dbb->dbb_flags & DBB_v3)) { if (node->nod_count) operator = (node->nod_flags & NOD_AGG_DISTINCT) ? blr_agg_count_distinct : blr_agg_count2; else operator = blr_agg_count; } else operator = blr_agg_count; break; case nod_agg_min: operator = blr_agg_min; break; case nod_agg_max: operator = blr_agg_max; break; case nod_agg_average: if (!(request->req_dbb->dbb_flags & DBB_v3)) operator = (node->nod_flags & NOD_AGG_DISTINCT) ? blr_agg_average_distinct : blr_agg_average; else operator = blr_agg_average; break; case nod_agg_total: if (!(request->req_dbb->dbb_flags & DBB_v3)) operator = (node->nod_flags & NOD_AGG_DISTINCT) ? blr_agg_total_distinct : blr_agg_total; else operator = blr_agg_total; break; case nod_agg_average2: operator = (node->nod_flags & NOD_AGG_DISTINCT) ? blr_agg_average_distinct : blr_agg_average; break; case nod_agg_total2: operator = (node->nod_flags & NOD_AGG_DISTINCT) ? blr_agg_total_distinct : blr_agg_total; break; case nod_and: operator = blr_and; break; case nod_or: operator = blr_or; break; case nod_not: operator = blr_not; break; case nod_eql_all: case nod_eql_any: case nod_eql: operator = blr_eql; break; case nod_neq_all: case nod_neq_any: case nod_neq: operator = blr_neq; break; case nod_gtr_all: case nod_gtr_any: case nod_gtr: operator = blr_gtr; break; case nod_leq_all: case nod_leq_any: case nod_leq: operator = blr_leq; break; case nod_geq_all: case nod_geq_any: case nod_geq: operator = blr_geq; break; case nod_lss_all: case nod_lss_any: case nod_lss: operator = blr_lss; break; case nod_between: operator = blr_between; break; case nod_containing: operator = blr_containing; break; case nod_starting: operator = blr_starting; break; case nod_missing: operator = blr_missing; break; case nod_like: operator = (node->nod_count == 2) ? blr_like : blr_ansi_like; break; case nod_add: operator = blr_add; break; case nod_subtract: operator = blr_subtract; break; case nod_multiply: operator = blr_multiply; break; case nod_negate: { NOD child = node->nod_arg[0]; if ( child->nod_type == nod_constant && DTYPE_IS_NUMERIC(child->nod_desc.dsc_dtype) ) { gen_constant (request, &child->nod_desc, NEGATE_VALUE); return; } } operator = blr_negate; break; case nod_divide: operator = blr_divide; break; case nod_add2: operator = blr_add; break; case nod_subtract2: operator = blr_subtract; break; case nod_multiply2: operator = blr_multiply; break; case nod_divide2: operator = blr_divide; break; case nod_concatenate: operator = blr_concatenate; break; case nod_null: operator = blr_null; break; case nod_any: operator = blr_any; break; case nod_ansi_any: if (!(request->req_dbb->dbb_flags & DBB_v3)) operator = blr_ansi_any; else operator = blr_any; break; case nod_ansi_all: operator = blr_ansi_all; break; case nod_via: operator = blr_via; break; case nod_upcase: operator = blr_upcase; break; case nod_substr: operator = blr_substring; break; case nod_cast: gen_cast (request, node); return; case nod_gen_id: case nod_gen_id2: gen_gen_id (request, node); return; 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: operator = blr_average; break; case nod_count: operator = blr_count;/* count2 operator = node->nod_arg [0]->nod_arg [e_rse_items] ? blr_count2 : blr_count;*/ break; case nod_from: operator = blr_from; break; case nod_max: operator = blr_maximum; break; case nod_min: operator = blr_minimum; break; case nod_total: operator = blr_total; break; default: break; } STUFF (operator); gen_rse (request, node->nod_arg[0]); if (operator != blr_count) 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); }STUFF (operator);for (ptr = node->nod_arg, end = ptr + node->nod_count; ptr < end; ptr++) GEN_expr (request, *ptr);/* 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 || node->nod_type == nod_agg_average2 ) { DSC desc; char *s; char message_buf[8]; MAKE_desc(&desc, node); if( (node->nod_flags & NOD_COMP_DIALECT) && (request->req_client_dialect == SQL_DIALECT_V6_TRANSITION) ) { 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: sprintf(message_buf, "blr %d", operator); s = message_buf; } ERRD_post_warning(isc_dsql_dialect_warning_expr, gds_arg_string, s, gds_arg_end); } }}void GEN_port ( REQ request, MSG message){/************************************** * * G E N _ p o r t * ************************************** * * Functional description * Generate a port from a message. Feel free to rearrange the * order of parameters. * **************************************/STR buffer;PAR parameter;USHORT number, align;TSQL tdsql;tdsql = GET_THREAD_DATA;if (request->req_blr_string) { STUFF (blr_message); STUFF (message->msg_number); STUFF_WORD (message->msg_parameter); }for (parameter = message->msg_parameters, number = 0; parameter; parameter = parameter->par_next) { 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) {#ifdef SQL_DIALECT_1_NEW_DATATYPES_CONVERT_TO_TEXT /* An early design of how to handle access of new datatype fields by older clients determined that conversion of the new types to TEXT was the proper way. A later design meeting decided that SQL Dialect 1 should forbid all access to the newer datatypes. Should this decision be revisited during v6.0 BETA, this is the code that converts select & insert references to the new datatypes to TEXT. 1999-Mar-17 David Schnepper */ case dtype_sql_date: parameter->par_desc.dsc_dtype = dtype_text; parameter->par_desc.dsc_scale = 0; parameter->par_desc.dsc_ttype = ttype_ascii; parameter->par_desc.dsc_length = DSC_convert_to_text_length (dtype_sql_date); break; case dtype_sql_time: parameter->par_desc.dsc_dtype = dtype_text; parameter->par_desc.dsc_scale = 0; parameter->par_desc.dsc_ttype = ttype_ascii; parameter->par_desc.dsc_length = DSC_convert_to_text_length (dtype_sql_time); break; case dtype_int64: if (parameter->par_desc.dsc_scale < 0) length = 1; /* For decimal point */ else length = parameter->par_desc.dsc_scale; length += DSC_convert_to_text_length (dtype_int64) - 1; parameter->par_desc.dsc_dtype = dtype_text; parameter->par_desc.dsc_scale = 0; parameter->par_desc.dsc_ttype = ttype_ascii; parameter->par_desc.dsc_length = length; break;#else /* 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 */ 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;#endif /* SQL_DIALECT_1_NEW_DATATYPES_CONVERT_TO_TEXT */ default: /* No special action for other data types */ break; }; align = type_alignments [parameter->par_desc.dsc_dtype]; if (align) message->msg_length = FB_ALIGN(message->msg_length, align); parameter->par_desc.dsc_address = (UCHAR*) (SLONG) message->msg_length; message->msg_length += parameter->par_desc.dsc_length; if (request->req_blr_string) gen_descriptor (request, ¶meter->par_desc, FALSE); }/* Allocate buffer for message */buffer = (STR) ALLOCDV (type_str, message->msg_length + DOUBLE_ALIGN - 1);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) parameter->par_desc.dsc_address = message->msg_buffer + (SLONG) parameter->par_desc.dsc_address;}void GEN_request ( REQ request, NOD node){/************************************** * * G E N _ r e q u e s t * ************************************** * * Functional description * Generate complete blr for a request. * **************************************/MSG message;if (request->req_type == REQ_DDL) { DDL_generate (request, node); return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -