📄 exe.c
字号:
/* * 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 10void 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;}#endifREQ 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 + -