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

📄 pass1.c

📁 firebird源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *	PROGRAM:	Dynamic SQL runtime support *	MODULE:		pass1.c *	DESCRIPTION:	First-pass compiler for request trees. * * 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.5.26: Claudio Valderrama: COMPUTED fields will be skipped if a dummy *       "insert into tbl values(...)" sentence is issued. * 2001.5.26: Claudio Valderrama: field names should be skimmed from trailing *		blanks to allow reliable comparisons in pass1_field. Same for table and *		and index names in plans. * 2001.5.29: Claudio Valderrama: handle DROP VIEW case in pass1_statement(). * 2001.6.12: Claudio Valderrama: add basic BREAK capability to procedures. * 2001.6.27: Claudio Valderrama: pass1_variable() now gives the name of the * variable it can't find in the error message. * 2001.6.30: Claudio Valderrama: Enhanced again to provide (line, col), see node.h. * 2001.7.28: John Bellardo: added code to handle nod_limit and associated fields. * 2001.08.14 Claudio Valderrama: fixed crash with trigger and CURRENT OF <cursor> syntax. * 2001.09.10 John Bellardo: fixed gen_rse to attribute skip/first nodes to the parent_rse *   if present instead of the child rse.  BUG #451798 * 2001.09.26 Claudio Valderrama: ambiguous field names are rejected from now. * 2001.10.01 Claudio Valderrama: check constraints are allowed to have ambiguous field *   names because they use OLD and NEW as aliases of the same table. However, if the *   check constraint has an embedded ambiguous SELECT statement, it won't be detected. *   The code should be revisited if check constraints' before delete triggers are used *   for whatever reason. Currently they are never generated. The code can be improved *   to not report errors for fields between NEW and OLD contexts but complain otherwise. * 2001.10.05 Neil McCalden: validate udf and parameters when comparing select list and *   group by list, to detect invalid SQL statements when grouping by UDFs. */#include "../jrd/ib_stdio.h"#include <string.h>#include "../dsql/dsql.h"#include "../dsql/node.h"#include "../dsql/sym.h"#include "../jrd/codes.h"#include "../jrd/thd.h"#include "../jrd/intl.h"#include "../jrd/blr.h"#include "../jrd/gds.h"#include "../dsql/alld_proto.h"#include "../dsql/ddl_proto.h"#include "../dsql/errd_proto.h"#include "../dsql/hsh_proto.h"#include "../dsql/make_proto.h"#include "../dsql/metd_proto.h"#include "../dsql/pass1_proto.h"#include "../jrd/dsc_proto.h"#include "../jrd/thd_proto.h"ASSERT_FILENAME				/* Define things assert() needs */static BOOLEAN	aggregate_found (REQ, NOD, NOD *);static BOOLEAN	aggregate_found2 (REQ, NOD, NOD *, BOOLEAN *);static void	assign_fld_dtype_from_dsc (FLD, DSC *);static NOD	compose (NOD, NOD, NOD_TYPE);static NOD	copy_field (NOD, CTX);static NOD	copy_fields (NOD, CTX);static void	explode_asterisk (NOD, NOD, LLS *);static NOD	explode_outputs (REQ, PRC);static void	field_error (TEXT *, TEXT *, NOD);static PAR	find_dbkey (REQ, NOD);static PAR	find_record_version (REQ, NOD);static BOOLEAN	invalid_reference (NOD, NOD);static void 	mark_ctx_outer_join (NOD);static BOOLEAN	node_match (NOD, NOD);static NOD	pass1_alias_list (REQ, NOD);static CTX	pass1_alias (REQ, STR);static NOD	pass1_any (REQ, NOD, NOD_TYPE);static DSQL_REL	pass1_base_table (REQ, DSQL_REL, STR);static void	pass1_blob (REQ, NOD);static NOD	pass1_collate (REQ, NOD, STR);static NOD	pass1_constant (REQ, NOD);static NOD	pass1_cursor (REQ, NOD, NOD);static CTX	pass1_cursor_context (REQ, NOD, NOD);static NOD	pass1_dbkey (REQ, NOD);static NOD	pass1_delete (REQ, NOD);static NOD	pass1_field (REQ, NOD, USHORT, USHORT *);static NOD	pass1_insert (REQ, NOD);static NOD	pass1_node (REQ, NOD, USHORT, USHORT *);static NOD	pass1_relation (REQ, NOD);static NOD	pass1_rse (REQ, NOD, NOD);static NOD	pass1_sel_list ( REQ, NOD);static NOD	pass1_sort (REQ, NOD, NOD);static NOD	pass1_udf (REQ, NOD, USHORT);static void	pass1_udf_args (REQ, NOD, LLS *, USHORT);static NOD	pass1_union (REQ, NOD, NOD);static NOD	pass1_update (REQ, NOD);static NOD	pass1_variable (REQ, NOD);static NOD	post_map (NOD, CTX);static void 	remap_streams_to_parent_context (NOD, CTX);static FLD	resolve_context (REQ, STR, STR, CTX, DSQL_REL*, PRC*);static BOOLEAN	set_parameter_type (NOD, NOD, BOOLEAN);static void	set_parameters_name (NOD, NOD);static void	set_parameter_name (NOD, NOD, DSQL_REL);static TEXT *pass_exact_name (TEXT *);STR	temp_collation_name = NULL;#define DB_KEY_STRING	"DB_KEY"		/* NTX: pseudo field name */#define MAX_MEMBER_LIST	1500		/* Maximum members in "IN" list.					 * For eg. SELECT * FROM T WHERE					 *         F IN (1, 2, 3, ...)					 *					 * Bug 10061, bsriram - 19-Apr-1999					 */#define FIREBIRD_REJECT_AMBIGUITYCTX PASS1_make_context (    REQ		request,    NOD		relation_node){/************************************** * *	P A S S 1 _ m a k e _ c o n t e x t * ************************************** * * Functional description *	Generate a context for a request. * **************************************/CTX		context, conflict;STR		relation_name, string;DSQL_REL	relation;PRC		procedure;FLD		field;NOD		*input;LLS		stack;TEXT		*conflict_name;STATUS		error_code;struct nod	desc_node;TSQL		tdsql;USHORT		count;DEV_BLKCHK (request, type_req);DEV_BLKCHK (relation_node, type_nod);tdsql = GET_THREAD_DATA;relation = NULL;procedure = NULL;/* figure out whether this is a relation or a procedure   and give an error if it is neither */if (relation_node->nod_type == nod_rel_proc_name)    relation_name = (STR) relation_node->nod_arg [e_rpn_name];else    relation_name = (STR) relation_node->nod_arg [e_rln_name];/* CVC: Let's skim the context, too. */if (relation_name && relation_name -> str_data)	pass_exact_name (relation_name -> str_data);DEV_BLKCHK (relation_name, type_str);if ((relation_node->nod_type == nod_rel_proc_name) &&	relation_node->nod_arg [e_rpn_inputs]){    if (!(procedure = METD_get_procedure (request, relation_name)))	{		TEXT linecol [64];		sprintf (linecol, "At line %d, column %d.",			(int) relation_node->nod_line, (int) relation_node->nod_column);        ERRD_post (gds__sqlerr, gds_arg_number, (SLONG) -204,			gds_arg_gds, gds__dsql_procedure_err,			gds_arg_gds, gds__random,			gds_arg_string, relation_name->str_data,			gds_arg_gds, gds__random,			gds_arg_string, linecol,			0);	}}else{    if (!(relation = METD_get_relation (request, relation_name)) &&        (relation_node->nod_type == nod_rel_proc_name))        procedure = METD_get_procedure (request, relation_name);    if (!relation && !procedure) 	{		TEXT linecol [64];		sprintf (linecol, "At line %d, column %d.",			(int) relation_node->nod_line, (int) relation_node->nod_column);		ERRD_post (gds__sqlerr, gds_arg_number, (SLONG) -204, 			gds_arg_gds, gds__dsql_relation_err, 			gds_arg_gds, gds__random, 			gds_arg_string, relation_name->str_data,			gds_arg_gds, gds__random,			gds_arg_string, linecol,			0);	}}if (procedure && !procedure->prc_out_count){	TEXT linecol [64];	sprintf (linecol, "At line %d, column %d.",		(int) relation_node->nod_line, (int) relation_node->nod_column);    ERRD_post (gds__sqlerr, gds_arg_number, (SLONG) -84,		gds_arg_gds, gds__dsql_procedure_use_err,		gds_arg_string, relation_name->str_data,		gds_arg_gds, gds__random,		gds_arg_string, linecol,		0);}/* Set up context block */context = (CTX) ALLOCD (type_ctx);context->ctx_relation = relation;context->ctx_procedure = procedure;context->ctx_request = request;context->ctx_context = request->req_context_number++;context->ctx_scope_level = request->req_scope_level;/* find the context alias name, if it exists */if (relation_node->nod_type == nod_rel_proc_name)    string = (STR) relation_node->nod_arg [e_rpn_alias];else    string = (STR) relation_node->nod_arg [e_rln_alias];DEV_BLKCHK (string, type_str);if (string)    {    context->ctx_alias = (TEXT*) string->str_data;    /* check to make sure the context is not already used at this same         query level (if there are no subqueries, this checks that the       alias is not used twice in the request) */    for (stack = request->req_context; stack; stack = stack->lls_next)	{	conflict = (CTX) stack->lls_object;	if (conflict->ctx_scope_level != context->ctx_scope_level)	    continue;	if (conflict->ctx_alias)	    {	    conflict_name = conflict->ctx_alias;	    error_code = gds__alias_conflict_err;	    /* alias %s conflicts with an alias in the same statement */	    }	else if (conflict->ctx_procedure)	    {	    conflict_name = conflict->ctx_procedure->prc_name;	    error_code = gds__procedure_conflict_error;	    /* alias %s conflicts with a procedure in the same statement */	    }	else if (conflict->ctx_relation)	    {	    conflict_name = conflict->ctx_relation->rel_name;	    error_code = gds__relation_conflict_err;	    /* alias %s conflicts with a relation in the same statement */	    }	else	    continue;    	if (!strcmp (conflict_name, context->ctx_alias))	    ERRD_post (gds__sqlerr, gds_arg_number, (SLONG) -204, 		gds_arg_gds, error_code, 		gds_arg_string, conflict_name,		0);	}    }    if (procedure)    {    if (request->req_scope_level == 1)	request->req_flags |= REQ_no_batch;	    if (relation_node->nod_arg [e_rpn_inputs])	{    	context->ctx_proc_inputs = PASS1_node (request, 				relation_node->nod_arg [e_rpn_inputs], 0);    	count = context->ctx_proc_inputs->nod_count;	}    else	count = 0;    if (!(request->req_type & REQ_procedure))	{	    	if (count != procedure->prc_in_count)	    ERRD_post (gds__prcmismat, gds_arg_string, relation_name->str_data, 0);    	if (count)	    {	    /* Initialize this stack variable, and make it look like a node */	    memset ((SCHAR *) &desc_node, 0, sizeof (desc_node));	    desc_node.nod_header.blk_type = type_nod;            for (input = context->ctx_proc_inputs->nod_arg,	 		field = procedure->prc_inputs;	 		field;	 		input++, field = field->fld_next)	    	{		DEV_BLKCHK (field, type_fld);		DEV_BLKCHK (*input, type_nod);            	MAKE_desc_from_field (&desc_node.nod_desc, field);	    	set_parameter_type (*input, &desc_node, FALSE);	    	}	    }	}    }/* push the context onto the request context stack    for matching fields against */LLS_PUSH (context, &request->req_context);return context;}NOD PASS1_node (    REQ		request,    NOD		input,    USHORT	proc_flag){/************************************** * *	P A S S 1 _ n o d e * ************************************** * * Functional description *	Compile a parsed request into something more interesting. *  CVC: This function now is a wrapper around pass1_node(). * **************************************/	USHORT	fcount;	return pass1_node (request, input, proc_flag, &fcount);}NOD PASS1_rse (    REQ		request,    NOD		input,    NOD		order){/************************************** * *	P A S S 1 _ r s e * ************************************** * * Functional description *	Compile a record selection expression,  *	bumping up the request scope level  *	everytime an rse is seen.  The scope *	level controls parsing of aliases. * **************************************/NOD	node;int foo;DEV_BLKCHK (request, type_req);DEV_BLKCHK (input, type_nod);DEV_BLKCHK (order, type_nod);request->req_scope_level++;foo = request->req_scope_level;node = pass1_rse (request, input, order);request->req_scope_level--;return node;}NOD PASS1_statement (    REQ		request,    NOD		input,    USHORT	proc_flag){/************************************** * *	P A S S 1 _ s t a t e m e n t * ************************************** * * Functional description *	Compile a parsed request into something more interesting. * **************************************/NOD		node, *ptr, *end, *ptr2, *end2, into_in, into_out, procedure,		cursor, temp, parameters, variables;LLS		base;FLD		field, field2;STR		name;struct nod	desc_node;USHORT		count;/*CTX		context;*/DEV_BLKCHK (request, type_req);DEV_BLKCHK (input, type_nod);#ifdef DEV_BUILDif (DSQL_debug > 2)    DSQL_pretty (input, 0);#endifbase = request->req_context;/* Dispatch on node type.  Fall thru on easy ones */switch (input->nod_type)    {          case nod_def_relation:    case nod_redef_relation:    case nod_def_index:    case nod_def_view:    case nod_def_constraint:    case nod_def_exception:    case nod_mod_relation:    case nod_mod_exception:    case nod_del_relation:    /* CVC: Deleting view is a new case. */    case nod_del_view:    case nod_del_index:    case nod_del_exception:    case nod_grant:    case nod_revoke:    case nod_def_database:    case nod_mod_database:    case nod_def_generator:    case nod_def_role:    case nod_del_role:    case nod_del_generator:    case nod_def_filter:    case nod_del_filter:    case nod_def_domain:    case nod_del_domain:    case nod_mod_domain:    case nod_def_udf:    case nod_del_udf:    case nod_def_shadow:    case nod_del_shadow:    case nod_mod_index:    case nod_set_statistics:	request->req_type = REQ_DDL;	return input;    case nod_def_trigger:    case nod_mod_trigger:    case nod_del_trigger:	request->req_type = REQ_DDL;	request->req_flags |= REQ_procedure;	request->req_flags |= REQ_trigger;	return input;    case nod_del_procedure:	request->req_type = REQ_DDL;	request->req_flags |= REQ_procedure;	return input;    case nod_def_procedure:	case nod_redef_procedure:    case nod_mod_procedure:	request->req_type = REQ_DDL;	request->req_flags |= REQ_procedure;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -