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

📄 token.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) 2005, 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 */#if HAVE_STRING_H#include <string.h>#endif /* HAVE_STRING_H */#if HAVE_STDLIB_H#include <stdlib.h>#endif /* HAVE_STDLIB_H */#include <assert.h>#include "tds.h"#include "tdsstring.h"#include "tdsconvert.h"#include "tdsiconv.h"#include "tds_checks.h"#include "replacements.h"#ifdef DMALLOC#include <dmalloc.h>#endifTDS_RCSID(var, "$Id: token.c,v 1.343.2.1 2008/01/27 10:41:23 freddy77 Exp $");static int tds_process_msg(TDSSOCKET * tds, int marker);static int tds_process_compute_result(TDSSOCKET * tds);static int tds_process_compute_names(TDSSOCKET * tds);static int tds7_process_compute_result(TDSSOCKET * tds);static int tds_process_result(TDSSOCKET * tds);static int tds_process_col_name(TDSSOCKET * tds);static int tds_process_col_fmt(TDSSOCKET * tds);static int tds_process_tabname(TDSSOCKET *tds);static int tds_process_colinfo(TDSSOCKET * tds, char **names, int num_names);static int tds_process_compute(TDSSOCKET * tds, TDS_INT * computeid);static int tds_process_cursor_tokens(TDSSOCKET * tds);static int tds_process_row(TDSSOCKET * tds);static int tds_process_param_result(TDSSOCKET * tds, TDSPARAMINFO ** info);static int tds7_process_result(TDSSOCKET * tds);static TDSDYNAMIC *tds_process_dynamic(TDSSOCKET * tds);static int tds_process_auth(TDSSOCKET * tds);static int tds_process_env_chg(TDSSOCKET * tds);static int tds_process_param_result_tokens(TDSSOCKET * tds);static int tds_process_params_result_token(TDSSOCKET * tds);static int tds_process_dyn_result(TDSSOCKET * tds);static int tds5_process_result(TDSSOCKET * tds);static int tds5_process_dyn_result2(TDSSOCKET * tds);static int tds_process_default_tokens(TDSSOCKET * tds, int marker);static int tds5_process_optioncmd(TDSSOCKET * tds);static int tds_process_end(TDSSOCKET * tds, int marker, /*@out@*/ int *flags_parm);static int tds_get_data(TDSSOCKET * tds, TDSCOLUMN * curcol);static int tds_get_data_info(TDSSOCKET * tds, TDSCOLUMN * curcol, int is_param);static /*@observer@*/ const char *_tds_token_name(unsigned char marker);static void adjust_character_column_size(const TDSSOCKET * tds, TDSCOLUMN * curcol);static int determine_adjusted_size(const TDSICONV * char_conv, int size);static /*@observer@*/ const char *tds_pr_op(int op);static int tds_alloc_get_string(TDSSOCKET * tds, /*@special@*/ char **string, int len) /*allocates *string*/;/** * \ingroup libtds * \defgroup token Results processing * Handle tokens in packets. Many PDU (packets data unit) contain tokens. * (like result description, rows, data, errors and many other). *//** * \addtogroup token * @{  *//** * tds_process_default_tokens() is a catch all function that is called to * process tokens not known to other tds_process_* routines */static inttds_process_default_tokens(TDSSOCKET * tds, int marker){	int tok_size;	int done_flags;	TDS_INT ret_status;	CHECK_TDS_EXTRA(tds);	tdsdump_log(TDS_DBG_FUNC, "tds_process_default_tokens() marker is %x(%s)\n", marker, _tds_token_name(marker));	if (IS_TDSDEAD(tds)) {		tdsdump_log(TDS_DBG_FUNC, "leaving tds_process_default_tokens() connection dead\n");		tds_close_socket(tds);		return TDS_FAIL;	}	switch (marker) {	case TDS_AUTH_TOKEN:		return tds_process_auth(tds);		break;	case TDS_ENVCHANGE_TOKEN:		return tds_process_env_chg(tds);		break;	case TDS_DONE_TOKEN:	case TDS_DONEPROC_TOKEN:	case TDS_DONEINPROC_TOKEN:		return tds_process_end(tds, marker, &done_flags);		break;	case TDS_PROCID_TOKEN:		tds_get_n(tds, NULL, 8);		break;	case TDS_RETURNSTATUS_TOKEN:		ret_status = tds_get_int(tds);		marker = tds_peek(tds);		if (marker != TDS_PARAM_TOKEN && marker != TDS_DONEPROC_TOKEN && marker != TDS_DONE_TOKEN)			break;		tds->has_status = 1;		tds->ret_status = ret_status;		tdsdump_log(TDS_DBG_FUNC, "tds_process_default_tokens: return status is %d\n", tds->ret_status);		break;	case TDS_ERROR_TOKEN:	case TDS_INFO_TOKEN:	case TDS_EED_TOKEN:		return tds_process_msg(tds, marker);		break;	case TDS_CAPABILITY_TOKEN:		/* TODO split two part of capability and use it */		tok_size = tds_get_smallint(tds);		/* vicm */		/*		 * Sybase 11.0 servers return the wrong length in the capability packet, causing use to read		 * past the done packet.		 */		if (!TDS_IS_MSSQL(tds) && tds->product_version < TDS_SYB_VER(12, 0, 0)) {			unsigned char type, size, *p, *pend;			p = tds->capabilities;			pend = tds->capabilities + TDS_MAX_CAPABILITY;			do {				type = tds_get_byte(tds);				size = tds_get_byte(tds);				if ((p + 2) > pend)					break;				*p++ = type;				*p++ = size;				if ((p + size) > pend)					break;				if (tds_get_n(tds, p, size) == NULL)					return TDS_FAIL;			} while (type != 2);		} else {			const int len = tok_size < TDS_MAX_CAPABILITY? tok_size : TDS_MAX_CAPABILITY;			if (tds_get_n(tds, tds->capabilities, len) == NULL)				return TDS_FAIL;		}		break;		/* PARAM_TOKEN can be returned inserting text in db, to return new timestamp */	case TDS_PARAM_TOKEN:		tds_unget_byte(tds);		return tds_process_param_result_tokens(tds);		break;	case TDS7_RESULT_TOKEN:		return tds7_process_result(tds);		break;	case TDS_OPTIONCMD_TOKEN:		return tds5_process_optioncmd(tds);		break;	case TDS_RESULT_TOKEN:		return tds_process_result(tds);		break;	case TDS_ROWFMT2_TOKEN:		return tds5_process_result(tds);		break;	case TDS_COLNAME_TOKEN:		return tds_process_col_name(tds);		break;	case TDS_COLFMT_TOKEN:		return tds_process_col_fmt(tds);		break;	case TDS_ROW_TOKEN:		return tds_process_row(tds);		break;	case TDS5_PARAMFMT_TOKEN:		/* store discarded parameters in param_info, not in old dynamic */		tds->cur_dyn = NULL;		return tds_process_dyn_result(tds);		break;	case TDS5_PARAMFMT2_TOKEN:		tds->cur_dyn = NULL;		return tds5_process_dyn_result2(tds);		break;	case TDS5_PARAMS_TOKEN:		/* save params */		return tds_process_params_result_token(tds);		break;	case TDS_CURINFO_TOKEN:		return tds_process_cursor_tokens(tds);		break;	case TDS5_DYNAMIC_TOKEN:	case TDS_LOGINACK_TOKEN:	case TDS_ORDERBY_TOKEN:	case TDS_CONTROL_TOKEN:		tdsdump_log(TDS_DBG_WARN, "Eating %s token\n", _tds_token_name(marker));		tds_get_n(tds, NULL, tds_get_smallint(tds));		break;	case TDS_TABNAME_TOKEN:	/* used for FOR BROWSE query */		return tds_process_tabname(tds);		break;	case TDS_COLINFO_TOKEN:		return tds_process_colinfo(tds, NULL, 0);		break;	case TDS_ORDERBY2_TOKEN:		tdsdump_log(TDS_DBG_WARN, "Eating %s token\n", _tds_token_name(marker));		tds_get_n(tds, NULL, tds_get_int(tds));		break;	default: /* SYBEBTOK */		tds_close_socket(tds);		tdserror(tds->tds_ctx, tds, TDSEBTOK, 0);		tdsdump_log(TDS_DBG_ERROR, "Unknown marker: %d(%x)!!\n", marker, (unsigned char) marker);		return TDS_FAIL;	}	return TDS_SUCCEED;}static inttds_set_spid(TDSSOCKET * tds){	TDS_INT result_type;	TDS_INT done_flags;	TDS_INT rc;	TDSCOLUMN *curcol;	CHECK_TDS_EXTRA(tds);	if (tds_submit_query(tds, "select @@spid") != TDS_SUCCEED) {		return TDS_FAIL;	}	while ((rc = tds_process_tokens(tds, &result_type, &done_flags, TDS_RETURN_ROWFMT|TDS_RETURN_ROW|TDS_RETURN_DONE)) == TDS_SUCCEED) {		switch (result_type) {			case TDS_ROWFMT_RESULT:				if (tds->res_info->num_cols != 1) 					return TDS_FAIL;				break;			case TDS_ROW_RESULT:				curcol = tds->res_info->columns[0];				if (curcol->column_type == SYBINT2 || (curcol->column_type == SYBINTN && curcol->column_size == 2)) {					tds->spid = *((TDS_USMALLINT *) curcol->column_data);				} else if (curcol->column_type == SYBINT4 || (curcol->column_type == SYBINTN && curcol->column_size == 4)) {					tds->spid = *((TDS_UINT *) curcol->column_data);				} else					return TDS_FAIL;				break;			case TDS_DONE_RESULT:				if ((done_flags & TDS_DONE_ERROR) != 0)					return TDS_FAIL;				break;			default:				break;		}	}	if (rc != TDS_NO_MORE_RESULTS) 		return TDS_FAIL;	return TDS_SUCCEED;}/** * tds_process_login_tokens() is called after sending the login packet  * to the server.  It returns the success or failure of the login  * dependent on the protocol version. 4.2 sends an ACK token only when * successful, TDS 5.0 sends it always with a success byte within */inttds_process_login_tokens(TDSSOCKET * tds){	int succeed = TDS_FAIL;	int marker;	int len;	int memrc = 0;	unsigned char major_ver, minor_ver;	unsigned char ack;	TDS_UINT product_version;	CHECK_TDS_EXTRA(tds);	tdsdump_log(TDS_DBG_FUNC, "tds_process_login_tokens()\n");	/* get_incoming(tds->s); */	do {		marker = tds_get_byte(tds);		tdsdump_log(TDS_DBG_FUNC, "looking for login token, got  %x(%s)\n", marker, _tds_token_name(marker));		switch (marker) {		case TDS_AUTH_TOKEN:			tds_process_auth(tds);			break;		case TDS_LOGINACK_TOKEN:			/* TODO function */			len = tds_get_smallint(tds);			ack = tds_get_byte(tds);			major_ver = tds_get_byte(tds);			minor_ver = tds_get_byte(tds);			tds_get_n(tds, NULL, 2);			/* ignore product name length, see below */			tds_get_byte(tds);			product_version = 0;			/* get server product name */			/* compute length from packet, some version seem to fill this information wrongly */			len -= 10;			free(tds->product_name);			if (major_ver >= 7u) {				product_version = 0x80000000u;				memrc += tds_alloc_get_string(tds, &tds->product_name, len / 2);			} else if (major_ver >= 5) {				memrc += tds_alloc_get_string(tds, &tds->product_name, len);			} else {				memrc += tds_alloc_get_string(tds, &tds->product_name, len);				if (tds->product_name != NULL && strstr(tds->product_name, "Microsoft") != NULL)					product_version = 0x80000000u;			}			product_version |= ((TDS_UINT) tds_get_byte(tds)) << 24;			product_version |= ((TDS_UINT) tds_get_byte(tds)) << 16;			product_version |= ((TDS_UINT) tds_get_byte(tds)) << 8;			product_version |= tds_get_byte(tds);			/*			 * MSSQL 6.5 and 7.0 seem to return strange values for this			 * using TDS 4.2, something like 5F 06 32 FF for 6.50			 */			if (major_ver == 4 && minor_ver == 2 && (product_version & 0xff0000ffu) == 0x5f0000ffu)				product_version = ((product_version & 0xffff00u) | 0x800000u) << 8;			tds->product_version = product_version;#ifdef WORDS_BIGENDIAN			/* TODO do a best check *//*								if (major_ver==7) {					tds->broken_dates=1;				}*/#endif			/*			 * TDS 5.0 reports 5 on success 6 on failure			 * TDS 4.2 reports 1 on success and is not			 * present on failure			 */			if (ack == 5 || ack == 1)				succeed = TDS_SUCCEED;			/* authentication is now useless */			if (tds->authentication) {				tds->authentication->free(tds, tds->authentication);				tds->authentication = NULL;			}			break;		default:			if (tds_process_default_tokens(tds, marker) == TDS_FAIL)				return TDS_FAIL;			break;		}	} while (marker != TDS_DONE_TOKEN);	/* TODO why ?? */	tds->spid = tds->rows_affected;	if (tds->spid == 0) {		if (tds_set_spid(tds) != TDS_SUCCEED) {			tdsdump_log(TDS_DBG_ERROR, "tds_set_spid() failed\n");			succeed = TDS_FAIL;		}	}	tdsdump_log(TDS_DBG_FUNC, "leaving tds_process_login_tokens() returning %d\n", succeed);	if (memrc != 0)		succeed = TDS_FAIL;	return succeed;}static inttds_process_auth(TDSSOCKET * tds){	int pdu_size;	CHECK_TDS_EXTRA(tds);#if ENABLE_EXTRA_CHECKS	if (!IS_TDS7_PLUS(tds))		tdsdump_log(TDS_DBG_ERROR, "Called auth on TDS version < 7\n");#endif	pdu_size = tds_get_smallint(tds);	tdsdump_log(TDS_DBG_INFO1, "TDS_AUTH_TOKEN PDU size %d\n", pdu_size);	if (!tds->authentication)		return TDS_FAIL;	return tds->authentication->handle_next(tds, tds->authentication, pdu_size);}/** * process all streams. * tds_process_tokens() is called after submitting a query with * tds_submit_query() and is responsible for calling the routines to * populate tds->res_info if appropriate (some query have no result sets) * @param tds A pointer to the TDSSOCKET structure managing a client/server operation. * @param result_type A pointer to an integer variable which  *        tds_process_tokens sets to indicate the current type of result. *  @par *  <b>Values that indicate command status</b> *  <table> *   <tr><td>TDS_DONE_RESULT</td><td>The results of a command have been completely processed.  * 					This command returned no rows.</td></tr> *   <tr><td>TDS_DONEPROC_RESULT</td><td>The results of a  command have been completely processed.   * 					This command returned rows.</td></tr> *   <tr><td>TDS_DONEINPROC_RESULT</td><td>The results of a  command have been completely processed.   * 					This command returned rows.</td></tr> *  </table> *  <b>Values that indicate results information is available</b> *  <table><tr> *    <td>TDS_ROWFMT_RESULT</td><td>Regular Data format information</td> *    <td>tds->res_info now contains the result details ; tds->current_results now points to that data</td> *   </tr><tr> *    <td>TDS_COMPUTEFMT_ RESULT</td><td>Compute data format information</td> *    <td>tds->comp_info now contains the result data; tds->current_results now points to that data</td> *   </tr><tr> *    <td>TDS_DESCRIBE_RESULT</td><td></td> *    <td></td> *  </tr></table> *  <b>Values that indicate data is available</b> *  <table><tr> *   <td><b>Value</b></td><td><b>Meaning</b></td><td><b>Information returned</b></td> *   </tr><tr> *    <td>TDS_ROW_RESULT</td><td>Regular row results</td> *    <td>1 or more rows of regular data can now be retrieved</td> *   </tr><tr> *    <td>TDS_COMPUTE_RESULT</td><td>Compute row results</td> *    <td>A single row of compute data can now be retrieved</td>

⌨️ 快捷键说明

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