⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gen.c

📁 firebird源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *	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    FALSEUCHAR 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, &parameter->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 + -