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

📄 exe.c

📁 firebird源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *	PROGRAM:	JRD Access Method *	MODULE:		exe.c *	DESCRIPTION:	Statement execution * * 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: Allow inserting strings into blob fields. * 2001.6.28 Claudio Valderrama: Move code to cleanup_rpb() as directed * by Ann Harrison and cleanup of new record in store() routine. * 2001.10.11 Claudio Valderrama: Fix SF Bug #436462: From now, we only * count real store, modify and delete operations either in an external * file or in a table. Counting on a view caused up to three operations * being reported instead of one. *//*$Id: exe.c,v 1.1 2001/10/13 10:22:56 dimitr Exp $*/#include "../jrd/common.h"#include "../jrd/ibsetjmp.h"#include <string.h>#include "../jrd/jrd.h"#include "../jrd/req.h"#include "../jrd/val.h"#include "../jrd/exe.h"#include "../jrd/tra.h"#include "../jrd/codes.h"#include "../jrd/ods.h"#include "../jrd/btr.h"#include "../jrd/rse.h"#include "../jrd/lck.h"#include "../jrd/intl.h"#include "../jrd/rng.h"#include "../jrd/sbm.h"#include "../jrd/blb.h"#include "../jrd/blr.h"#include "../jrd/all_proto.h"#include "../jrd/bkm_proto.h"#include "../jrd/blb_proto.h"#include "../jrd/btr_proto.h"#include "../jrd/cmp_proto.h"#include "../jrd/dfw_proto.h"#include "../jrd/dpm_proto.h"#include "../jrd/err_proto.h"#include "../jrd/evl_proto.h"#include "../jrd/exe_proto.h"#include "../jrd/ext_proto.h"#include "../jrd/gds_proto.h"#include "../jrd/idx_proto.h"#include "../jrd/jrd_proto.h"#include "../jrd/lck_proto.h"#include "../jrd/met_proto.h"#include "../jrd/mov_proto.h"#include "../jrd/opt_proto.h"#include "../jrd/par_proto.h"#include "../jrd/rlck_proto.h"#include "../jrd/rse_proto.h"#include "../jrd/rng_proto.h"#include "../jrd/thd_proto.h"#include "../jrd/tra_proto.h"#include "../jrd/vio_proto.h"#ifdef HSDEBUGSTACK#include "TestStck.h"#endif#ifdef SHLIB_DEFS#undef send#endifextern STATUS DLL_EXPORT callback_execute_immediate (STATUS *, int *, int *, UCHAR *, int);static void cleanup_rpb (TDBB, RPB *);static NOD	erase			(TDBB, NOD, SSHORT);static void	exec_sql		(REQ, TDBB, DSC *);static void 	execute_looper		(TDBB, REQ, TRA,						ENUM req_s);static void	execute_procedure	(TDBB, NOD);static REQ	execute_triggers	(TDBB, VEC *, REC, REC);static NOD	looper			(TDBB, REQ, NOD);static NOD	modify			(TDBB, register NOD, SSHORT);static NOD	receive_msg		(TDBB, register NOD);static void	release_blobs		(TDBB, REQ);static void 	release_proc_save_points (REQ);static void	release_triggers 	(TDBB, VEC);#ifdef SCROLLABLE_CURSORSstatic NOD 	seek_rse		(TDBB, REQ, NOD);static void 	seek_rsb		(TDBB, REQ, RSB, USHORT, SLONG);#endifstatic NOD	selct			(TDBB, register NOD);static NOD	send_msg		(TDBB, register NOD);static void	set_error		(TDBB, XCP);static NOD	stall			(TDBB, register NOD);static NOD	store			(TDBB, register NOD,						SSHORT);static BOOLEAN	test_error		(TDBB, XCP);static void	trigger_failure		(TDBB, REQ);static void	validate		(TDBB, NOD);#ifdef PC_ENGINEstatic BOOLEAN	check_crack (RSB, USHORT);static NOD	find			(TDBB, register NOD);static NOD	find_dbkey		(TDBB, register NOD);static LCK	implicit_record_lock (TRA, RPB *);static NOD	release_bookmark	(TDBB, NOD);static NOD	set_bookmark		(TDBB, NOD);static NOD	set_index		(TDBB, register NOD);static NOD	stream			(TDBB, register NOD);#endif#ifdef DEBUG_GDS_ALLOCstatic SLONG	memory_debug = 1;static SLONG	memory_count = 0;#endif DEBUG_GDS_ALLOC/* macro definitions */#define NULL_STRING	"*** null ***"#ifdef PC_PLATFORM/* The PC cannot support that many recursions */#define	MAX_CLONES	75#endif#if (defined SUPERSERVER) && (defined WIN_NT || defined SOLARIS_MT)#define MAX_CLONES	750#endif#if defined (HP10) && defined (SUPERSERVER)#define MAX_CLONES	110#endif#ifdef DECOSF#define MAX_CLONES	200#endif#ifndef MAX_CLONES#define MAX_CLONES	1000#endif#define MAX_CALLBACKS   50#define ALL_TRIGS	0#define PRE_TRIG	1#define POST_TRIG	2/* this constant defines how many records are locked   before we check whether record locking has been   turned off for a given relation; if we set the    constant to a low number, we will do too much    locking in the case where record locking is always   turned on; too high and we will do too much record   locking in the case where someone is only occasionally   locking a record */#define RECORD_LOCK_CHECK_INTERVAL	10void EXE_assignment (    TDBB		tdbb,    register NOD	node){/************************************** * *	E X E _ a s s i g n m e n t * ************************************** * * Functional description *	Perform an assignment * **************************************/register REQ	request;DSC		*to_desc, *from_desc, *missing, *indicator, temp;register NOD	to;REC		record;SSHORT		null, id, len;DEV_BLKCHK (node, type_nod);SET_TDBB (tdbb);request = tdbb->tdbb_request;BLKCHK (node, type_nod);/* Get descriptors of receiving and sending fields/parmaters, variables, etc. */missing = NULL;if (node->nod_arg [e_asgn_missing])    missing = EVL_expr (tdbb, node->nod_arg [e_asgn_missing]);to = node->nod_arg [e_asgn_to];to_desc = EVL_assign_to (tdbb, to);request->req_flags &= ~req_null;from_desc = EVL_expr (tdbb, node->nod_arg [e_asgn_from]);null = (request->req_flags & req_null) ? -1 : 0;if (!null && missing && MOV_compare (missing, from_desc) == 0)    null = -1;/* If the value is non-missing, move/convert it.  Otherwise fill the   field with appropriate nulls. */if (!null)    {    /* if necessary and appropriate, use the indicator variable */    if (to->nod_type == nod_argument && to->nod_arg [e_arg_indicator])	{	indicator = EVL_assign_to (tdbb, to->nod_arg[e_arg_indicator]); 	temp.dsc_dtype = dtype_short;	temp.dsc_length = sizeof (SSHORT);	temp.dsc_scale = 0;	temp.dsc_sub_type = 0;	if ((from_desc->dsc_dtype <= dtype_varying) &&	    (to_desc->dsc_dtype <= dtype_varying) &&	    (TEXT_LEN (from_desc) > TEXT_LEN (to_desc))) 	    len = TEXT_LEN (from_desc); 	else	    len = 0;	temp.dsc_address = (UCHAR*) &len; 	MOV_move (&temp, indicator);	if (len)	    {	    temp = *from_desc;	    temp.dsc_length = TEXT_LEN (to_desc); 	    if (temp.dsc_dtype == dtype_cstring)		temp.dsc_length += 1;	    else if (temp.dsc_dtype == dtype_varying)		temp.dsc_length += 2;	    from_desc = &temp;	    }	} #ifndef VMS    if (DTYPE_IS_BLOB (to_desc->dsc_dtype))#else    if (DTYPE_IS_BLOB (to_desc->dsc_dtype) && to_desc->dsc_dtype != dtype_d_float)#endif	{		/* CVC: This is a case that has hurt me for years and I'm going to solve it.		It should be possible to copy a string to a blob, even if the charset is		lost as a result of this experimental implementation. */		if (from_desc->dsc_dtype <= dtype_varying)			BLB_move_from_string (tdbb, from_desc, to_desc, to);		else 			BLB_move (tdbb, from_desc, to_desc, to);	}    else if (!DSC_EQUIV (from_desc, to_desc))	MOV_move (from_desc, to_desc);    else if (from_desc->dsc_dtype == dtype_short)	*((SSHORT*) to_desc->dsc_address) = *((SSHORT*) from_desc->dsc_address);    else if (from_desc->dsc_dtype == dtype_long)	*((SLONG*) to_desc->dsc_address) = *((SLONG*) from_desc->dsc_address);    else if (from_desc->dsc_dtype == dtype_int64)	*((SINT64*) to_desc->dsc_address) = *((SINT64*) from_desc->dsc_address);    else if (((U_IPTR) from_desc->dsc_address & (ALIGNMENT - 1)) ||	((U_IPTR) to_desc->dsc_address & (ALIGNMENT - 1)))	MOVE_FAST (from_desc->dsc_address, to_desc->dsc_address,		  from_desc->dsc_length);    else	MOVE_FASTER (from_desc->dsc_address, to_desc->dsc_address,		  from_desc->dsc_length);    to_desc->dsc_flags &= ~DSC_null;    }else if (node->nod_arg [e_asgn_missing2] &&    (missing = EVL_expr (tdbb, node->nod_arg [e_asgn_missing2])))    {    MOV_move (missing, to_desc);    to_desc->dsc_flags |= DSC_null;    }else    {    UCHAR	*p;    USHORT	l;    l = to_desc->dsc_length;    p = to_desc->dsc_address;    switch (to_desc->dsc_dtype)	{	case dtype_text:		/* YYY - not necessarily the right thing to do */		/* for text formats that don't have trailing spaces */	    if (l) do *p++ = ' '; while (--l);	    break;	case dtype_cstring:	    *p = 0;	    break;	case dtype_varying:	    *(SSHORT *) p = 0;	    break;	default:	    do *p++ = 0; while (--l);	    break;	}    to_desc->dsc_flags |= DSC_null;    }/* Handle the null flag as appropriate for fields and message arguments. */if (to->nod_type == nod_field)    {    id = (USHORT) to->nod_arg [e_fld_id];    record = request->req_rpb [(int) to->nod_arg [e_fld_stream]].rpb_record;    if (null)	SET_NULL (record, id);    else	CLEAR_NULL (record, id);    }else if (to->nod_type == nod_argument && to->nod_arg [e_arg_flag])    {    to_desc = EVL_assign_to (tdbb, to->nod_arg [e_arg_flag]);    /* If the null flag is a string with an effective length of one,       then -1 will not fit.  Therefore, store 1 instead. */    if (null &&	to_desc->dsc_dtype <= dtype_varying &&	to_desc->dsc_length <=	    ((to_desc->dsc_dtype == dtype_text) ? 1 : ((to_desc->dsc_dtype == dtype_cstring) ? 2 : 3)))	null = 1;    temp.dsc_dtype = dtype_short;    temp.dsc_length = sizeof (SSHORT);    temp.dsc_scale = 0;    temp.dsc_sub_type = 0;    temp.dsc_address = (UCHAR*) &null;    MOV_move (&temp, to_desc);    if (null && to->nod_arg[e_arg_indicator])	{	to_desc = EVL_assign_to (tdbb, to->nod_arg [e_arg_indicator]);	MOV_move (&temp, to_desc); 	}    }request->req_operation = req_return;}#ifdef PC_ENGINEBOOLEAN EXE_crack (    TDBB	tdbb,    RSB		rsb,    USHORT	flags){/************************************** * *	E X E _ c r a c k * ************************************** * * Functional description *	Check whether stream is on a crack, BOF *	or EOF, according to the flags passed. * **************************************/REQ	request;RPB	*rpb;IRSB    impure;DEV_BLKCHK (rsb, type_rsb);SET_TDBB (tdbb);request = tdbb->tdbb_request;/* correct boolean rsbs to point to the "real" rsb */if (rsb->rsb_type == rsb_boolean)    rsb = rsb->rsb_next;impure = (IRSB) ((UCHAR*) request + rsb->rsb_impure);/* if any of the passed flags are set, return TRUE */if (impure->irsb_flags & flags)    return TRUE;else    return FALSE;}#endifREQ EXE_find_request (    TDBB	tdbb,    REQ 	request,    BOOLEAN	validate){/************************************** * *	E X E _ f i n d _ r e q u e s t * ************************************** * * Functional description *	Find an inactive incarnation of a trigger request.  If necessary, *	clone it. * **************************************/#ifdef ANY_THREADINGDBB	dbb;#endifREQ	clone, next;USHORT	n, clones, count;VEC	vector;DEV_BLKCHK (request, type_req);SET_TDBB (tdbb);#ifdef ANY_THREADINGdbb = tdbb->tdbb_database;#endif/* I found a core file from my test runs that came from a NULL request - * but have no idea what test was running.  Let's bugcheck so we can * figure it out */if (!request)    BUGCHECK /* REQUEST */ (167); /* msg 167 invalid SEND request */THD_MUTEX_LOCK (dbb->dbb_mutexes + DBB_MUTX_clone);clone = NULL;count = 0;if (!(request->req_flags & req_in_use))    clone = request;else     {    if (request->req_attachment == tdbb->tdbb_attachment)	count++;    /* Request exists and is in use.  Search clones for one in use by    this attachment. If not found, return first inactive request. */    clones = (vector = request->req_sub_requests) ? (vector->vec_count - 1) : 0;    for (n = 1; n <= clones; n++)	{	next = CMP_clone_request (tdbb, request, n, validate);	if (next->req_attachment == tdbb->tdbb_attachment)	    {	    if (!(next->req_flags & req_in_use))		{		clone = next;		break;		}	    else		count++;	    }	else 	    if (!(next->req_flags & req_in_use) && !clone)		clone = next;	}    if (count > MAX_CLONES)	{	THD_MUTEX_UNLOCK (dbb->dbb_mutexes + DBB_MUTX_clone);	ERR_post (gds__req_max_clones_exceeded, 0);	}    if (!clone)	clone = CMP_clone_request (tdbb, request, n, validate);    }clone->req_attachment = tdbb->tdbb_attachment;clone->req_flags |= req_in_use;THD_MUTEX_UNLOCK (dbb->dbb_mutexes + DBB_MUTX_clone);return clone;}#ifdef PC_ENGINEvoid EXE_mark_crack (    TDBB	tdbb,    RSB		rsb,    USHORT	flag){/************************************** * *	E X E _ m a r k _ c r a c k * ************************************** * * Functional description *	Mark a stream as being at a crack, *	plus report the fact in the status *	vector. * **************************************/SET_TDBB (tdbb);DEV_BLKCHK (rsb, type_rsb);

⌨️ 快捷键说明

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