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

📄 dsql.c

📁 firebird源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *	PROGRAM:	Dynamic SQL runtime support *	MODULE:		dsql.c *	DESCRIPTION:	Local processing for External entry points. * * 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.3 Claudio Valderrama: fixed a bad behaved loop in get_plan_info() * and get_rsb_item() that caused a crash when plan info was requested. * 2001.6.9 Claudio Valderrama: Added nod_del_view, nod_current_role and nod_breakleave. * * 2001.07.06 Sean Leyne - Code Cleanup, removed "#ifdef READONLY_DATABASE" *                         conditionals, as the engine now fully supports *                         readonly databases. *//*$Id: dsql.c,v 1.1 2001/10/13 10:21:52 dimitr Exp $*//**************************************************************V4 Multi-threading changes.-- direct calls to gds__ () & isc_ () entrypoints	THREAD_EXIT;	    gds__ () or isc_ () call.	THREAD_ENTER;-- calls through embedded GDML.the following protocol will be used.  Care should be taken ifnested FOR loops are added.    THREAD_EXIT;                // last statment before FOR loop    FOR ...............	THREAD_ENTER;           // First statment in FOR loop	.....some C code....	.....some C code....	THREAD_EXIT;            // last statment in FOR loop    END_FOR;    THREAD_ENTER;               // First statment after FOR loop***************************************************************/#define DSQL_MAIN#include "../jrd/ib_stdio.h"#include <stdlib.h>#include <string.h>#include "../dsql/dsql.h"#include "../dsql/node.h"#include "../dsql/sym.h"#include "../jrd/gds.h"#include "../jrd/thd.h"#include "../jrd/align.h"#include "../jrd/intl.h"#include "../jrd/iberr.h"#include "../dsql/sqlda.h"#include "../dsql/alld_proto.h"#include "../dsql/ddl_proto.h"#include "../dsql/dsql_proto.h"#include "../dsql/errd_proto.h"#include "../dsql/gen_proto.h"#include "../dsql/hsh_proto.h"#include "../dsql/make_proto.h"#include "../dsql/movd_proto.h"#include "../dsql/parse_proto.h"#include "../dsql/pass1_proto.h"#include "../jrd/gds_proto.h"#include "../jrd/sch_proto.h"#include "../jrd/thd_proto.h"#include "../jrd/why_proto.h"ASSERT_FILENAME#ifdef VMS#include <descrip.h>#endif#ifdef NETWARE_386#define PRINTF		ConsolePrintf#endif#ifndef PRINTF#define PRINTF		ib_printf#endif#define ERROR_INIT(env)		{\				tdsql->tsql_status = user_status;\				tdsql->tsql_setjmp = (UCHAR*) env;\				tdsql->tsql_default = NULL;\				if (SETJMP (env))\				    {\				    RESTORE_THREAD_DATA;\				    return tdsql->tsql_status [1];\				    };\				}#define RETURN_SUCCESS		return return_success()#define SET_THREAD_DATA         {\				tdsql = &thd_context;\				THD_put_specific ((THDD) tdsql);\				tdsql->tsql_thd_data.thdd_type = THDD_TYPE_TSQL;\				}#define RESTORE_THREAD_DATA     THD_restore_specific()#ifdef STACK_REDUCTION#define FREE_MEM_RETURN		{\				if (buffer)\				    {\				    gds__free ((SLONG *)buffer);\				    buffer = (TEXT*) NULL;\				    }\				return;\				}#else#define FREE_MEM_RETURN		return#endifSTATUS DLL_EXPORT callback_execute_immediate (STATUS *, int *, int *, UCHAR *, int);static void	cleanup (void *);static void	cleanup_database (SLONG **, SLONG);static void	cleanup_transaction (SLONG *, SLONG);static void	close_cursor (REQ);static USHORT	convert (SLONG, SCHAR *);static STATUS	error (void);static void	execute_blob (REQ, int **, USHORT, UCHAR *, USHORT, UCHAR *, USHORT, UCHAR *, USHORT, UCHAR *);static STATUS	execute_request (REQ, int **, USHORT, UCHAR *, USHORT, UCHAR *, USHORT, UCHAR *, USHORT, UCHAR *, USHORT);static SSHORT	filter_sub_type (REQ, NOD);static BOOLEAN	get_indices (SSHORT *, SCHAR **, SSHORT *, SCHAR **);static USHORT	get_plan_info (REQ, SSHORT, SCHAR **);static USHORT	get_request_info (REQ, SSHORT, SCHAR *);static BOOLEAN	get_rsb_item (SSHORT *, SCHAR **, SSHORT *, SCHAR **, USHORT *, USHORT *);static DBB	init (SLONG **);static void	map_in_out (REQ, MSG, USHORT, UCHAR *, USHORT, UCHAR *);static USHORT	name_length (TEXT *);static USHORT	parse_blr (USHORT, UCHAR *, USHORT, PAR);static REQ	prepare (REQ, USHORT, TEXT *, USHORT, USHORT);static void	punt (void);static SCHAR	*put_item (SCHAR, USHORT, SCHAR *, SCHAR *, SCHAR *);static void	release_request (REQ, USHORT);static STATUS	return_success (void);static SCHAR	*var_info (MSG, SCHAR *, SCHAR *, SCHAR *, SCHAR *, USHORT);extern NOD      DSQL_parse;static USHORT   init_flag;static DBB      databases;static OPN	open_cursors;static CONST SCHAR	db_hdr_info_items [] = {	                    isc_info_db_sql_dialect,			    gds__info_ods_version,			    gds__info_base_level,			    isc_info_db_read_only,			    frb_info_att_charset,			    gds__info_end			};static CONST SCHAR 	explain_info [] = {	gds__info_access_path };static CONST SCHAR 	record_info [] = {	gds__info_req_update_count, gds__info_req_delete_count,	gds__info_req_select_count, gds__info_req_insert_count };static CONST SCHAR	sql_records_info [] = {	gds__info_sql_records };#ifdef	ANY_THREADINGstatic	MUTX_T	databases_mutex;static	MUTX_T	cursors_mutex;static	USHORT	mutex_inited = 0;#endif/* STUFF_INFO used in place of STUFF to avoid confusion with BLR STUFF   macro defined in dsql.h */#define STUFF_INFO_WORD(p,value)	{*p++ = value; *p++ = value >> 8;}#define STUFF_INFO(p,value)		*p++ = value;#define GDS_DSQL_ALLOCATE	dsql8_allocate_statement#define GDS_DSQL_EXECUTE	dsql8_execute#define GDS_DSQL_EXECUTE_IMMED	dsql8_execute_immediate#define GDS_DSQL_FETCH		dsql8_fetch#define GDS_DSQL_FREE		dsql8_free_statement#define GDS_DSQL_INSERT		dsql8_insert#define GDS_DSQL_PREPARE	dsql8_prepare#define GDS_DSQL_SET_CURSOR	dsql8_set_cursor#define GDS_DSQL_SQL_INFO	dsql8_sql_infoSTATUS DLL_EXPORT callback_execute_immediate (    STATUS	*status,    int 	*jrd_attachment_handle,    int 	*jrd_transaction_handle,    UCHAR	*sql_operator,    int 	len){/************************************** * * Functional description *	Execute sql_operator in context of jrd_transaction_handle * **************************************/STATUS s;typedef struct hndl {    UCHAR	type;    UCHAR	flags;    USHORT	implementation;    int		*handle;    struct hndl	*parent;    struct hndl	*next;    struct hndl	*requests;    struct hndl	*statements;    struct hndl *blobs;    struct hndl	**user_handle;    struct clean *cleanup;    TEXT	*db_path;} *WHY;  /* exact copy of `struct hndl' from why.c */WHY	why_db_handle = NULL;WHY	why_trans_handle = NULL;DBB	database;/* 1. Locate why_db_handle, corresponding to jrd_database_handle */THD_MUTEX_LOCK (&databases_mutex);for (database = databases; database; database = database->dbb_next)    if (((WHY)(database->dbb_database_handle))->handle == jrd_attachment_handle)	break;if (! database)    {    status[0] = gds_arg_gds;    status[1] = gds__bad_db_handle;    status[2] = gds_arg_end;    THD_MUTEX_UNLOCK (&databases_mutex);    return status[1];    }why_db_handle = (WHY)(database->dbb_database_handle);/* 2. Create why_trans_handle - it's new, but points to the same jrd      transaction as original before callback. */why_trans_handle = (WHY) gds__alloc ((SLONG) sizeof (struct hndl));if (! why_trans_handle)    {    status[0] = gds_arg_gds;    status[1] = gds__virmemexh;    status[2] = gds_arg_end;    THD_MUTEX_UNLOCK (&databases_mutex);    return status[1];    }memset (why_trans_handle, 0, sizeof (struct hndl));why_trans_handle->implementation = why_db_handle->implementation;why_trans_handle->handle = jrd_transaction_handle;#define HANDLE_transaction 2   /* exact copy of `HANDLE_transaction' from why.c */why_trans_handle->type = HANDLE_transaction;#undef HANDLE_transactionwhy_trans_handle->parent = why_db_handle;THD_MUTEX_UNLOCK (&databases_mutex);/* 3. Call isc... function */THREAD_EXIT;s = isc_dsql_execute_immediate (	status,	&why_db_handle,	&why_trans_handle,	len, sql_operator, database->dbb_db_SQL_dialect, NULL);THREAD_ENTER;gds__free(why_trans_handle);return s;}STATUS DLL_EXPORT GDS_DSQL_ALLOCATE (    STATUS	*user_status,    int		**db_handle,    REQ		*req_handle){/************************************** * *	d s q l _ a l l o c a t e _ s t a t e m e n t * ************************************** * * Functional description *	Allocate a statement handle. * **************************************/DBB		database;REQ		request;struct tsql	thd_context, *tdsql;JMP_BUF		env;SET_THREAD_DATA;ERROR_INIT (env);init (NULL_PTR);/* If we haven't been initialized yet, do it now */database = init ((SLONG **) db_handle);tdsql->tsql_default = ALLD_pool();/* allocate the request block */request = (REQ) ALLOCD (type_req);request->req_dbb = database;request->req_pool = tdsql->tsql_default;*req_handle = request;RETURN_SUCCESS;}STATUS DLL_EXPORT GDS_DSQL_EXECUTE (    STATUS	*user_status,    isc_tr_handle	*trans_handle,    REQ		*req_handle,    USHORT	in_blr_length,    UCHAR	*in_blr,    USHORT	in_msg_type,    USHORT	in_msg_length,    UCHAR	*in_msg,    USHORT	out_blr_length,    UCHAR	*out_blr,    USHORT	out_msg_type,    USHORT	out_msg_length,    UCHAR	*out_msg){/************************************** * *	d s q l _ e x e c u t e * ************************************** * * Functional description *	Execute a non-SELECT dynamic SQL statement. * **************************************/REQ		request;OPN		open_cursor;STATUS		local_status [ISC_STATUS_LENGTH];struct tsql	thd_context, *tdsql;JMP_BUF		env;USHORT		singleton;STATUS		sing_status;SET_THREAD_DATA;ERROR_INIT (env);init (NULL_PTR);sing_status = 0;request = *req_handle;tdsql->tsql_default = request->req_pool;if ((SSHORT) in_msg_type == -1)    request->req_type = REQ_EMBED_SELECT;/* Only allow NULL trans_handle if we're starting a transaction */if (*trans_handle == NULL && request->req_type != REQ_START_TRANS)    ERRD_post (gds__sqlerr, gds_arg_number, (SLONG) -901,	    gds_arg_gds, gds__bad_trans_handle,	    0);/* If the request is a SELECT or blob statement then this is an open./* If the request is a SELECT or blob statement then this is an open.   Make sure the cursor is not already open. */if (request->req_type == REQ_SELECT ||    request->req_type == REQ_SELECT_UPD ||    request->req_type == REQ_EMBED_SELECT ||    request->req_type == REQ_GET_SEGMENT ||    request->req_type == REQ_PUT_SEGMENT)    if (request->req_flags & REQ_cursor_open)	{	ERRD_post (gds__sqlerr, gds_arg_number, (SLONG) -502,            gds_arg_gds, gds__dsql_cursor_open_err,	    0);	}/* A select with a non zero output length is a singleton select */if (request->req_type == REQ_SELECT && out_msg_length != 0)    singleton = TRUE;else    singleton = FALSE;if (request->req_type != REQ_EMBED_SELECT)    sing_status = execute_request (request, trans_handle,	in_blr_length, in_blr, in_msg_length, in_msg,	out_blr_length, out_blr, out_msg_length, out_msg, singleton);/* If the output message length is zero on a REQ_SELECT then we must * be doing an OPEN cursor operation. * If we do have an output message length, then we're doing * a singleton SELECT.  In that event, we don't add the cursor * to the list of open cursors (it's not really open). */if ((request->req_type == REQ_SELECT && out_msg_length == 0) ||    request->req_type == REQ_SELECT_UPD ||    request->req_type == REQ_EMBED_SELECT ||    request->req_type == REQ_GET_SEGMENT ||    request->req_type == REQ_PUT_SEGMENT)    {    request->req_flags |= REQ_cursor_open |	((request->req_type == REQ_EMBED_SELECT) ? REQ_embedded_sql_cursor : 0);    request->req_open_cursor = open_cursor = (OPN) ALLOCP (type_opn);    open_cursor->opn_request = request;    open_cursor->opn_transaction = (SLONG*) *trans_handle;    THD_MUTEX_LOCK (&cursors_mutex);    open_cursor->opn_next = open_cursors;    open_cursors = open_cursor;    THD_MUTEX_UNLOCK (&cursors_mutex);    THREAD_EXIT;    gds__transaction_cleanup (local_status, trans_handle, (isc_callback) cleanup_transaction, 0);    THREAD_ENTER;    }if (!sing_status)    RETURN_SUCCESS;else    {    RESTORE_THREAD_DATA;    return sing_status;    }}STATUS DLL_EXPORT GDS_DSQL_EXECUTE_IMMED (    STATUS	*user_status,    int		**db_handle,    int		**trans_handle,    USHORT	length,    TEXT	*string,    USHORT	dialect,    USHORT	in_blr_length,    UCHAR	*in_blr,    USHORT	in_msg_type,    USHORT	in_msg_length,    UCHAR	*in_msg,    USHORT	out_blr_length,    UCHAR	*out_blr,    USHORT	out_msg_type,    USHORT	out_msg_length,    UCHAR	*out_msg){/************************************** * *	d s q l _ e x e c u t e _ i m m e d i a t e * ************************************** * * Functional description *	Prepare and execute a statement. * **************************************/REQ		request;DBB		database;USHORT		parser_version;STATUS		status;struct tsql	thd_context, *tdsql;JMP_BUF		env;SET_THREAD_DATA;ERROR_INIT (env);database = init (db_handle);tdsql->tsql_default = ALLD_pool();/* allocate the request block, then prepare the request */request = (REQ) ALLOCD (type_req);request->req_dbb = database;request->req_pool = tdsql->tsql_default;request->req_trans = (int *) *trans_handle;if (SETJMP (tdsql->tsql_setjmp))    {    status = error();    release_request (request, TRUE);    RESTORE_THREAD_DATA;    return status;    }if (!length)    length = strlen (string);/* Figure out which parser version to use *//* Since the API to GDS_DSQL_EXECUTE_IMMED is public and can not be changed, there needs to * be a way to send the parser version to DSQL so that the parser can compare the keyword * version to the parser version.  To accomplish this, the parser version is combined with * the client dialect and sent across that way.  In dsql8_execute_immediate, the parser version * and client dialect are separated and passed on to their final desintations.  The information * is combined as follows:

⌨️ 快捷键说明

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