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

📄 dblib.c

📁 在Linux/Unix下面访问WINDOWS SQLSERVER 的ODBC驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/* FreeTDS - Library of routines accessing Sybase and Microsoft databases * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005  Brian Bruns * Copyright (C) 2006, 2007  Frediano Ziglio * * 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>#if TIME_WITH_SYS_TIME# include <sys/time.h># include <time.h>#else# if HAVE_SYS_TIME_H#  include <sys/time.h># else#  include <time.h># endif#endif#include <assert.h>#include <stdio.h>#if HAVE_STDLIB_H#include <stdlib.h>#endif /* HAVE_STDLIB_H */#if HAVE_STRING_H#include <string.h>#endif /* HAVE_STRING_H */#if HAVE_UNISTD_H#include <unistd.h>#endif /* HAVE_UNISTD_H */#if HAVE_ERRNO_H# include <errno.h>#else  static int errno=0;#endif /* HAVE_ERRNO_H *//**  * \ingroup dblib_core * \remarks Either SYBDBLIB or MSDBLIB (not both) must be defined.  * 	This affects how certain application-addressable  * 	strucures are defined.   */#define SYBDBLIB 1#include "tds.h"#include "tdsthread.h"#include "sybfront.h"#include "sybdb.h"#include "syberror.h"#include "dblib.h"#include "tdsconvert.h"#include "replacements.h"#ifdef DMALLOC#include <dmalloc.h>#endifTDS_RCSID(var, "$Id: dblib.c,v 1.320 2008/01/01 23:09:46 freddy77 Exp $");static RETCODE _dbresults(DBPROCESS * dbproc);static int _db_get_server_type(int bindtype);static int _get_printable_size(TDSCOLUMN * colinfo);static char *_dbprdate(char *timestr);static int _dbnullable(DBPROCESS * dbproc, int column);static char *tds_prdatatype(TDS_SERVER_TYPE datatype_token);static void copy_data_to_host_var(DBPROCESS *, int, const BYTE *, DBINT, int, BYTE *, DBINT, int, DBSMALLINT *);static int default_err_handler(DBPROCESS * dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr);static RETCODE dbgetnull(DBPROCESS *dbproc, int bindtype, int varlen, BYTE* varaddr);/** * \file dblib.c * Main implementation file for \c db-lib. *//** * \file bcp.c * Implementation of \c db-lib bulk copy functions. *//** * \defgroup dblib_api The db-lib API * Functions callable by \c db-lib client programs * * The \c db_lib interface is implemented by both Sybase and Microsoft.  FreeTDS seeks to implement  * first the intersection of the functions defined by the vendors.   */ /** * \ingroup dblib_api * \defgroup dblib_core Primary functions * Core functions needed by most db-lib programs.  *//** * \ingroup dblib_api * \defgroup dblib_rpc Remote Procedure functions * Functions used with stored procedures.   * Especially useful for OUTPUT parameters, because modern Microsoft servers do not  * return output parameter data to the client unless the procedure was invoked * with dbrpcsend().   *//** * \ingroup dblib_api * \defgroup dblib_bcp Bulk copy functions * Functions to bulk-copy (a/k/a \em bcp) data to/from the database.   *//** * \ingroup dblib_bcp * \defgroup dblib_bcp_internal Internal bcp functions * Static functions internal to the bcp library.   *//** * \ingroup dblib_api * \defgroup dblib_money Money functions  * Functions to manipulate the MONEY datatype.   *//** * \ingroup dblib_api * \defgroup dblib_datetime Datetime functions  * Functions to manipulate DBDATETIME structures.  Defined by Sybase only.   * These are not implemented: *	- dbdate4cmp() *	- dbdate4zero() *	- dbdatechar() *	- dbdatename() *	- dbdateorder() *	- dbdatepart() *	- dbdatezero() *	- dbdayname() *//** * \ingroup dblib_api * \defgroup dblib_internal Internals * Functions called within \c db-lib for self-help.   * These functions are of interest only to people hacking on the FreeTDS db-lib implementation.   *//** * \ingroup dblib_api * \defgroup dblib_unimplemented Unimplemented * Functions thus far not implemented in the FreeTDS db-lib implementation.   * While some of these are simply awaiting someone with time and skill (and inclination) * it might be noted here that the old browse functions (e.g. dbcolbrowse())  * are on the never-to-do list.   * They were defined by Sybase and were superseded long ago, although they're still * present in Microsoft's implementation.   * They were never popular and today better alternatives are available.   * For completeness, they are: * 	- dbcolbrowse() * 	- dbcolsource() * 	- dbfreequal() * 	- dbqual() * 	- dbtabbrowse() * 	- dbtabcount() * 	- dbtabname() * 	- dbtabsource() * 	- dbtsnewlen() * 	- dbtsnewval() * 	- dbtsput() *//* info/err message handler functions (or rather pointers to them) */MHANDLEFUNC _dblib_msg_handler = NULL;EHANDLEFUNC _dblib_err_handler = default_err_handler;/** \internal * \dblib_internal * \remarks A db-lib connection has an implicit TDS context.  */typedef struct dblib_context{	/** reference count, time dbinit called */	int ref_count;	/** libTDS context */	TDSCONTEXT *tds_ctx;	/** libTDS context reference counter */	int tds_ctx_ref_count;	/* save all connection in a list */	TDSSOCKET **connection_list;	int connection_list_size;	int connection_list_size_represented;	char *recftos_filename;	int recftos_filenum;	int login_timeout;	/**< not used unless positive */	int query_timeout;	/**< not used unless positive */}DBLIBCONTEXT;static DBLIBCONTEXT g_dblib_ctx;static TDS_MUTEX_DECLARE(dblib_mutex);static int g_dblib_version =#ifdef TDS42	DBVERSION_42;#endif#ifdef TDS50DBVERSION_100;#endif#ifdef TDS46DBVERSION_46;#endif#ifdef TDS70DBVERSION_70;#endif#ifdef TDS80DBVERSION_80;#endifstatic intdblib_add_connection(DBLIBCONTEXT * ctx, TDSSOCKET * tds){	int i = 0;	const int list_size = ctx->connection_list_size_represented;	tdsdump_log(TDS_DBG_FUNC, "dblib_add_connection(%p, %p)\n", ctx, tds);	while (i < list_size && ctx->connection_list[i])		i++;	if (i == list_size) {		fprintf(stderr, "Max connections reached, increase value of TDS_MAX_CONN\n");		return 1;	} else {		ctx->connection_list[i] = tds;		return 0;	}}static voiddblib_del_connection(DBLIBCONTEXT * ctx, TDSSOCKET * tds){	int i = 0;	const int list_size = ctx->connection_list_size;	tdsdump_log(TDS_DBG_FUNC, "dblib_del_connection(%p, %p)\n", ctx, tds);	while (i < list_size && ctx->connection_list[i] != tds)		i++;	if (i == list_size) {		/* connection wasn't on the free list...now what */	} else {		/* remove it */		ctx->connection_list[i] = NULL;	}}static TDSCONTEXT*dblib_get_tds_ctx(void){	tdsdump_log(TDS_DBG_FUNC, "dblib_get_tds_ctx(void)\n");	TDS_MUTEX_LOCK(&dblib_mutex);	++g_dblib_ctx.tds_ctx_ref_count;	if (g_dblib_ctx.tds_ctx == NULL) {		g_dblib_ctx.tds_ctx = tds_alloc_context(&g_dblib_ctx);		/*		 * Set the functions in the TDS layer to point to the correct handler functions		 */		g_dblib_ctx.tds_ctx->msg_handler = _dblib_handle_info_message;		g_dblib_ctx.tds_ctx->err_handler = _dblib_handle_err_message;		g_dblib_ctx.tds_ctx->int_handler = _dblib_check_and_handle_interrupt;		if (g_dblib_ctx.tds_ctx->locale && !g_dblib_ctx.tds_ctx->locale->date_fmt) {			/* set default in case there's no locale file */			const static char date_format[] = #ifndef WIN32							   "%b %e %Y %I:%M:%S:%z%p";#else							   "%b %d %Y %I:%M:%S:%z%p";#endif			g_dblib_ctx.tds_ctx->locale->date_fmt = strdup(date_format);		}	}	TDS_MUTEX_UNLOCK(&dblib_mutex);	return g_dblib_ctx.tds_ctx;}static voiddblib_release_tds_ctx(int count){	tdsdump_log(TDS_DBG_FUNC, "dblib_release_tds_ctx(%d)\n", count);	TDS_MUTEX_LOCK(&dblib_mutex);	g_dblib_ctx.tds_ctx_ref_count -= count;	if (g_dblib_ctx.tds_ctx_ref_count <= 0) {		tds_free_context(g_dblib_ctx.tds_ctx);		g_dblib_ctx.tds_ctx = NULL;	}	TDS_MUTEX_UNLOCK(&dblib_mutex);}#include "buffering.h"static voiddb_env_chg(TDSSOCKET * tds, int type, char *oldval, char *newval){	DBPROCESS *dbproc;	assert(oldval != NULL && newval != NULL);	if (strlen(oldval) == 1 && *oldval == 1)		oldval = "(0x1)";			tdsdump_log(TDS_DBG_FUNC, "db_env_chg(%p, %d, %s, %s)\n", tds, type, oldval, newval);	if (tds == NULL || tds->parent == NULL ) {		return;	}	dbproc = (DBPROCESS *) tds->parent;	dbproc->envchange_rcv |= (1 << (type - 1));	switch (type) {	case TDS_ENV_DATABASE:		tds_strlcpy(dbproc->dbcurdb, newval, sizeof(dbproc->dbcurdb));		break;	case TDS_ENV_CHARSET:		tds_strlcpy(dbproc->servcharset, newval, sizeof(dbproc->servcharset));		break;	default:		break;	}	return;}/** \internal * \ingroup dblib_internal * \brief Sanity checks for column-oriented functions.   *  * \param dbproc contains all information needed by db-lib to manage communications with the server. * \param pcolinfo address of pointer to a TDSCOLUMN structure. * \remarks Makes sure dbproc and the requested column are valid.   *	Calls dbperror() if not.   * \returns appropriate error or SUCCEED */static TDSCOLUMN*dbcolptr(DBPROCESS* dbproc, int column){	if (!dbproc) {		dbperror(dbproc, SYBENULL, 0);		return NULL;	}	if (IS_TDSDEAD(dbproc->tds_socket)) {		dbperror(dbproc, SYBEDDNE, 0);		return NULL;	}	if (!dbproc->tds_socket->res_info)		return NULL;	if (column < 1 || column > dbproc->tds_socket->res_info->num_cols) {		dbperror(dbproc, SYBECNOR, 0);		return NULL;	} 		return dbproc->tds_socket->res_info->columns[column - 1];}static TDSCOLUMN*dbacolptr(DBPROCESS* dbproc, int computeid, int column, int is_bind){	int i;	TDSSOCKET *tds;	TDSCOMPUTEINFO *info;	if (!dbproc) {		dbperror(dbproc, SYBENULL, 0);		return NULL;	}	tds = dbproc->tds_socket;	if (IS_TDSDEAD(tds)) {		dbperror(dbproc, SYBEDDNE, 0);		return NULL;	}	for (i = 0;; ++i) {		if (i >= tds->num_comp_info) {			/* Attempt to bind user variable to a non-existent compute row */			if (is_bind)				dbperror(dbproc, SYBEBNCR, 0);			return NULL;		}		info = tds->comp_info[i];		info = dbproc->tds_socket->comp_info[i];		if (info->computeid == computeid)			break;	}	/* Fail if either the compute id or the column number is invalid. */	if (column < 1 || column > info->num_cols) {		dbperror(dbproc, is_bind ? SYBEABNC : SYBECNOR, 0);		return NULL;	}	return info->columns[column - 1];}/* * Default null substitution values * Binding Type		Null Substitution Value * TINYBIND		0 * SMALLBIND		0 * INTBIND		0 * CHARBIND		Empty string (padded with blanks) * STRINGBIND		Empty string (padded with blanks, null-terminated) * NTBSTRINGBIND	Empty string (null-terminated) * VARYCHARBIND		Empty string * BINARYBIND		Empty array (padded with zeros) * VARYBINBIND		Empty array * DATETIMEBIND		8 bytes of zeros * SMALLDATETIMEBIND	8 bytes of zeros * MONEYBIND		$0.00 * SMALLMONEYBIND	$0.00 * FLT8BIND		0.0 * REALBIND		0.0 * DECIMALBIND		0.0 (with default scale and precision) * NUMERICBIND		0.0 (with default scale and precision) * BOUNDARYBIND		Empty string (null-terminated) * SENSITIVITYBIND	Empty string (null-terminated) */static const DBBIT		null_BIT = 0;static const DBTINYINT		null_TINYINT = 0;static const DBSMALLINT		null_SMALLINT = 0;static const DBINT		null_INT = 0;static const DBFLT8		null_FLT8 = 0;static const DBREAL		null_REAL = 0;static const DBCHAR		null_CHAR = '\0';static const DBVARYCHAR		null_VARYCHAR = { 0, {0} };static const DBBINARY		null_BINARY = 0;static const DBDATETIME		null_DATETIME = { 0, 0 };static const DBDATETIME4	null_SMALLDATETIME = { 0, 0 };static const DBMONEY		null_MONEY = { 0, 0 };static const DBMONEY4		null_SMALLMONEY = {0};static const DBNUMERIC		null_NUMERIC = { 0, 0, {0} };static NULLREP default_null_representations[MAXBINDTYPES] = {	/* CHARBIND	     0  */	  {         NULL, 0 }	/* STRINGBIND	     1  */	, {         NULL, 0 }	/* NTBSTRINGBIND     2  */	, { (BYTE*) &null_CHAR, sizeof(null_CHAR) }	/* VARYCHARBIND      3  */	, { (BYTE*) &null_VARYCHAR, sizeof(null_VARYCHAR) }	/* VARYBINBIND       4  */	, {         &null_BINARY, sizeof(null_BINARY) }	/* no such bind      5  */	, {         NULL, 0 }				/* TINYBIND	     6  */	, {         &null_TINYINT, sizeof(null_TINYINT) }	/* SMALLBIND	     7  */	, { (BYTE*) &null_SMALLINT, sizeof(null_SMALLINT) }	/* INTBIND	     8  */	, { (BYTE*) &null_INT, sizeof(null_INT) }	/* FLT8BIND	     9  */	, { (BYTE*) &null_FLT8, sizeof(null_FLT8) }	/* REALBIND	     10 */	, { (BYTE*) &null_REAL, sizeof(null_REAL) }	/* DATETIMEBIND      11 */	, { (BYTE*) &null_DATETIME, sizeof(null_DATETIME) }	/* SMALLDATETIMEBIND 12 */	, { (BYTE*) &null_SMALLDATETIME, sizeof(null_SMALLDATETIME) }	/* MONEYBIND	     13 */	, { (BYTE*) &null_MONEY, sizeof(null_MONEY) }	/* SMALLMONEYBIND    14 */	, { (BYTE*) &null_SMALLMONEY, sizeof(null_SMALLMONEY) }	/* BINARYBIND	     15 */	, {         NULL, 0 }		    	/* BITBIND	     16 */	, {         &null_BIT, sizeof(null_BIT) }	/* NUMERICBIND       17 */	, { (BYTE*) &null_NUMERIC, sizeof(null_NUMERIC) }	/* DECIMALBIND       18 */	, { (BYTE*) &null_NUMERIC, sizeof(null_NUMERIC) }	/* MAXBINDTYPES      19 */};static intdbbindtype(int datatype){	switch (datatype) {	case SYBIMAGE:	case SYBVARBINARY:	case SYBBINARY:		return BINARYBIND;		case SYBBIT:		return BITBIND;	case SYBTEXT:	case SYBVARCHAR:	case SYBCHAR:		return NTBSTRINGBIND;

⌨️ 快捷键说明

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