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

📄 dbutil.c

📁 在Linux/Unix下面访问WINDOWS SQLSERVER 的ODBC驱动程序
💻 C
字号:
/* FreeTDS - Library of routines accessing Sybase and Microsoft databases * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004  Brian Bruns * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#if HAVE_CONFIG_H#include <config.h>#endif /* HAVE_CONFIG_H */#include <stdarg.h>#include <stdio.h>#include <assert.h>#if HAVE_STDLIB_H#include <stdlib.h>#endif /* HAVE_STDLIB_H */#include "tds.h"#include "sybdb.h"#include "syberror.h"#include "dblib.h"/* #include "fortify.h" */#ifdef DMALLOC#include <dmalloc.h>#endifTDS_RCSID(var, "$Id: dbutil.c,v 1.42 2007/12/07 05:27:55 jklowden Exp $");/* * test include consistency  * I don't think all compiler are able to compile this code... if not comment it */#if ENABLE_EXTRA_CHECKS#if defined(__GNUC__) && __GNUC__ >= 2#define COMPILE_CHECK(name,check) \    extern int name[(check)?1:-1] __attribute__ ((unused))#else#define COMPILE_CHECK(name,check) \    extern int name[(check)?1:-1]#endif/* TODO test SYBxxx consistency */#define TEST_ATTRIBUTE(t,sa,fa,sb,fb) \	COMPILE_CHECK(t,sizeof(((sa*)0)->fa) == sizeof(((sb*)0)->fb) && (int)(&((sa*)0)->fa) == (int)(&((sb*)0)->fb))TEST_ATTRIBUTE(t21,TDS_MONEY4,mny4,DBMONEY4,mny4);TEST_ATTRIBUTE(t22,TDS_OLD_MONEY,mnyhigh,DBMONEY,mnyhigh);TEST_ATTRIBUTE(t23,TDS_OLD_MONEY,mnylow,DBMONEY,mnylow);TEST_ATTRIBUTE(t24,TDS_DATETIME,dtdays,DBDATETIME,dtdays);TEST_ATTRIBUTE(t25,TDS_DATETIME,dttime,DBDATETIME,dttime);TEST_ATTRIBUTE(t26,TDS_DATETIME4,days,DBDATETIME4,days);TEST_ATTRIBUTE(t27,TDS_DATETIME4,minutes,DBDATETIME4,minutes);TEST_ATTRIBUTE(t28,TDS_NUMERIC,precision,DBNUMERIC,precision);TEST_ATTRIBUTE(t29,TDS_NUMERIC,scale,DBNUMERIC,scale);TEST_ATTRIBUTE(t30,TDS_NUMERIC,array,DBNUMERIC,array);#endif/*  * The next 2 functions receive the info and error messages that come from the TDS layer.   * The address of this function is passed to the TDS layer in dbinit().   * It takes a pointer to a DBPROCESS, it's just that the TDS layer didn't  * know what it really was.   */int_dblib_handle_info_message(const TDSCONTEXT * tds_ctx, TDSSOCKET * tds, TDSMESSAGE * msg){	DBPROCESS *dbproc = (tds && tds->parent)? (DBPROCESS *) tds->parent : NULL;	tdsdump_log(TDS_DBG_FUNC, "_dblib_handle_info_message(%p, %p, %p)\n", tds_ctx, tds, msg);	tdsdump_log(TDS_DBG_FUNC, "msgno %d: \"%s\"\n", msg->msgno, msg->message);	/* 	 * Check to see if the user supplied a function, else ignore the message. 	 */	if (_dblib_msg_handler) {		_dblib_msg_handler(dbproc,				   msg->msgno,				   msg->state,				   msg->severity, msg->message, msg->server, msg->proc_name, msg->line_number);	}	if (msg->severity > 10 && _dblib_err_handler) {	/* call the application's error handler, if installed. */		/*		 * Sybase docs say SYBESMSG is generated only in specific		 * cases (severity greater than 16, or deadlock occurred, or		 * a syntax error occurred.)  However, actual observed		 * behavior is that SYBESMSG is always generated for		 * server messages with severity greater than 10.		 */		/* Cannot call dbperror() here because server messsage numbers (and text) are not in its lookup table. */		static char message[] = "General SQL Server error: Check messages from the SQL Server";		(*_dblib_err_handler)(dbproc, msg->severity, msg->msgno, 0, message, NULL);	}	return SUCCEED;}/** \internal *  \dblib_internal *  \brief handle errors generated by libtds *  \param tds_ctx actually a dbproc: contains all information needed by db-lib to manage communications with the server. *  \param tds contains all information needed by libtds to manage communications with the server. *  \param msg the message to send *  \returns  *  \remarks This function is called by libtds via tds_ctx->err_handler.  It exists to convert the db-lib  *	error handler's return code into one that libtds will know  how to handle.   * 	libtds conveniently issues msgno's with the same values and meanings as db-lib and ODBC use.   *	(N.B. ODBC actually uses db-lib msgno numbers for its driver-specific "server errors".     *//*  * Stack: *		libtds *			tds_ctx->err_handler (pointer to _dblib_handle_err_message) *			_dblib_handle_err_message *				dbperror *					client (or default) error handler *					returns db-lib defined return code INT_something. *				returns db-lib return code with Sybase semantics (adjusting client's code if need be) *			returns libtds return code *		decides what to do based on the universal libtds return code, thank you.  */	int_dblib_handle_err_message(const TDSCONTEXT * tds_ctx, TDSSOCKET * tds, TDSMESSAGE * msg){	DBPROCESS *dbproc = (tds && tds->parent)? (DBPROCESS *) tds->parent : NULL;	int rc = INT_CANCEL;	assert(_dblib_err_handler);	assert(msg);	rc = dbperror(dbproc, msg->msgno, msg->oserr);	/*	 * Preprocess the return code to handle INT_TIMEOUT/INT_CONTINUE	 * for non-SYBETIME errors in the strange and different ways as	 * specified by Sybase and Microsoft.	 */	if (msg->msgno != SYBETIME) {		switch (rc) {		case INT_TIMEOUT:			rc = INT_EXIT;			break;		case INT_CONTINUE:			if (!dbproc || !dbproc->msdblib) {				/* Sybase behavior */				assert(0);  /* dbperror() should prevent */				rc = INT_EXIT;			} else {				/* Microsoft behavior */				rc = INT_CANCEL;			}			break;		default:			break;		}	}	/*	 * Convert db-lib return code to libtds return code, and return.	 */	switch (rc) {	case INT_CANCEL:	return TDS_INT_CANCEL;	case INT_TIMEOUT:	return TDS_INT_TIMEOUT;	case INT_CONTINUE:	return TDS_INT_CONTINUE;		case INT_EXIT:		assert(0);  /* dbperror() should prevent */	default:		/* unknown return code from error handler */		exit(EXIT_FAILURE);		break;	}	/* not reached */	assert(0);	return TDS_INT_CANCEL;}/** * \ingroup dblib_internal * \brief check interrupts for libtds. *  * \param vdbproc a DBPROCESS pointer, contains all information needed by db-lib to manage communications with the server. * \sa DBDEAD(), dbsetinterrupt(). */int_dblib_check_and_handle_interrupt(void * vdbproc){	DBPROCESS * dbproc = (DBPROCESS*) vdbproc;	int ret = INT_CONTINUE;		assert( ! (dbproc == NULL && DBDEAD(dbproc)) );  /* a non-process can't be a dead process */		if (dbproc->chkintr == NULL || dbproc->hndlintr == NULL)		return INT_CONTINUE;			tdsdump_log(TDS_DBG_FUNC, "tds_int_handler %p [%p, %p]", dbproc, dbproc->chkintr, dbproc->hndlintr);	if (dbproc->chkintr(dbproc)){		switch (ret = dbproc->hndlintr(dbproc)) {		case INT_EXIT:			tdsdump_log(TDS_DBG_FUNC, "dbproc->hndlintr returned INT_EXIT, goodbye!\n");			exit(1);		case INT_CANCEL:			tdsdump_log(TDS_DBG_FUNC, "dbproc->hndlintr returned INT_CANCEL\n");			break;		case INT_CONTINUE:			tdsdump_log(TDS_DBG_FUNC, "dbproc->hndlintr returned INT_CONTINUE\n");			break;		default:			tdsdump_log(TDS_DBG_FUNC, "dbproc->hndlintr returned an invalid value (%d), returning INT_CONTINUE\n", ret);			ret = INT_CONTINUE;			break;		}	}	return ret;}void_dblib_setTDS_version(TDSLOGIN * tds_login, DBINT version){	switch (version) {	case DBVERSION_42:		tds_set_version(tds_login, 4, 2);		break;	case DBVERSION_46:		tds_set_version(tds_login, 4, 6);		break;	case DBVERSION_100:		tds_set_version(tds_login, 5, 0);		break;	}}

⌨️ 快捷键说明

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