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

📄 token.c

📁 在Linux/Unix下面访问WINDOWS SQLSERVER 的ODBC驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
		/* Adjust column size according to client's encoding */		curcol->on_server.column_size = curcol->column_size;		adjust_character_column_size(tds, curcol);		/* discard Locale */		tds_get_n(tds, NULL, tds_get_byte(tds));		/* 		 *  Dump all information on this column		 */		tdsdump_log(TDS_DBG_INFO1, "col %d:\n", col);		tdsdump_log(TDS_DBG_INFO1, "\tcolumn_name=[%s]\n", curcol->column_name);/*		tdsdump_log(TDS_DBG_INFO1, "\tcolumn_name=[%s]\n", curcol->column_colname);		tdsdump_log(TDS_DBG_INFO1, "\tcatalog=[%s] schema=[%s] table=[%s]\n",			    curcol->catalog_name, curcol->schema_name, curcol->table_name, curcol->column_colname);*/		tdsdump_log(TDS_DBG_INFO1, "\tflags=%x utype=%d type=%d varint=%d\n",			    curcol->column_flags, curcol->column_usertype, curcol->column_type, curcol->column_varint_size);		tdsdump_log(TDS_DBG_INFO1, "\tcolsize=%d prec=%d scale=%d\n",			    curcol->column_size, curcol->column_prec, curcol->column_scale);	}	return tds_alloc_row(info);}/** * tds_process_compute() processes compute rows and places them in the row * buffer.   */static inttds_process_compute(TDSSOCKET * tds, TDS_INT * pcomputeid){	int i;	TDSCOLUMN *curcol;	TDSCOMPUTEINFO *info;	TDS_INT id;	CHECK_TDS_EXTRA(tds);	id = tds_get_smallint(tds);		tdsdump_log(TDS_DBG_INFO1, "tds_process_compute() found compute id %d\n", id);	for (i = 0;; ++i) {		if (i >= tds->num_comp_info) {			tdsdump_log(TDS_DBG_INFO1, "tds_process_compute() FAIL: id exceeds bound (%d)\n", tds->num_comp_info);			return TDS_FAIL;		}		info = tds->comp_info[i];		if (info->computeid == id)			break;	}	tds->current_results = info;	for (i = 0; i < info->num_cols; i++) {		curcol = info->columns[i];		if (tds_get_data(tds, curcol) != TDS_SUCCEED) {			tdsdump_log(TDS_DBG_INFO1, "tds_process_compute() FAIL: tds_get_data() failed\n");			return TDS_FAIL;		}	}	if (pcomputeid)		*pcomputeid = id;	return TDS_SUCCEED;}/** * Read a data from wire * \param tds state information for the socket and the TDS protocol * \param curcol column where store column information * \return TDS_FAIL on error or TDS_SUCCEED */static inttds_get_data(TDSSOCKET * tds, TDSCOLUMN * curcol){	unsigned char *dest;	int len, colsize;	int fillchar;	TDSBLOB *blob = NULL;	CHECK_TDS_EXTRA(tds);	CHECK_COLUMN_EXTRA(curcol);	tdsdump_log(TDS_DBG_INFO1, "tds_get_data: type %d, varint size %d\n", curcol->column_type, curcol->column_varint_size);	switch (curcol->column_varint_size) {	case 4:		/*		 * TODO finish 		 * This strange type has following structure 		 * 0 len (int32) -- NULL 		 * len (int32), type (int8), data -- ints, date, etc		 * len (int32), type (int8), 7 (int8), collation, column size (int16) -- [n]char, [n]varchar, binary, varbinary 		 * BLOBS (text/image) not supported		 */		if (curcol->column_type == SYBVARIANT) {			colsize = tds_get_int(tds);			tds_get_n(tds, NULL, colsize);			curcol->column_cur_size = -1;			return TDS_SUCCEED;		}				/*		 * LONGBINARY		 * This type just stores a 4-byte length		 */		if (curcol->column_type == SYBLONGBINARY) {			colsize = tds_get_int(tds);			break;		}				/* It's a BLOB... */		len = tds_get_byte(tds);		blob = (TDSBLOB *) curcol->column_data;		if (len == 16) {	/*  Jeff's hack */			tds_get_n(tds, blob->textptr, 16);			tds_get_n(tds, blob->timestamp, 8);			colsize = tds_get_int(tds);		} else {			colsize = -1;		}		break;	case 5:		colsize = tds_get_int(tds);		break;	case 2:		colsize = tds_get_smallint(tds);		break;	case 1:		colsize = tds_get_byte(tds);		if (colsize == 0)			colsize = -1;		break;	case 0:		/* TODO this should be column_size */		colsize = tds_get_size_by_type(curcol->column_type);		break;	default:		colsize = -1;		break;	}	if (IS_TDSDEAD(tds))		return TDS_FAIL;	tdsdump_log(TDS_DBG_INFO1, "tds_get_data(): wire column size is %d \n", colsize);	/* set NULL flag in the row buffer */	if (colsize < 0) {		curcol->column_cur_size = -1;		return TDS_SUCCEED;	}	/* 	 * We're now set to read the data from the wire.  For varying types (e.g. char/varchar)	 * make sure that curcol->column_cur_size reflects the size of the read data, 	 * after any charset conversion.  tds_get_char_data() does that for you, 	 * but of course tds_get_n() doesn't.  	 *	 * colsize == wire_size, bytes to read	 * curcol->column_cur_size == sizeof destination buffer, room to write	 */	dest = curcol->column_data;	if (is_numeric_type(curcol->column_type)) {		/* 		 * Handling NUMERIC datatypes: 		 * Since these can be passed around independent		 * of the original column they came from, we embed the TDS_NUMERIC datatype in the row buffer		 * instead of using the wire representation, even though it uses a few more bytes.  		 */		TDS_NUMERIC *num = (TDS_NUMERIC *) dest;		memset(num, '\0', sizeof(TDS_NUMERIC));		/* TODO perhaps it would be fine to change format ?? */		num->precision = curcol->column_prec;		num->scale = curcol->column_scale;		/* server is going to crash freetds ?? */		/* TODO close connection it server try to do so ?? */		if (colsize > sizeof(num->array))			return TDS_FAIL;		tds_get_n(tds, num->array, colsize);		/* corrected colsize for column_cur_size */		colsize = sizeof(TDS_NUMERIC);		if (IS_TDS7_PLUS(tds)) {			tdsdump_log(TDS_DBG_INFO1, "swapping numeric data...\n");			tds_swap_numeric(num);		}		curcol->column_cur_size = colsize;	} else if (is_blob_type(curcol->column_type)) {		TDS_CHAR *p;		int new_blob_size;		assert(blob == (TDSBLOB *) dest); 	/* cf. column_varint_size case 4, above */				/* 		 * Blobs don't use a column's fixed buffer because the official maximum size is 2 GB.		 * Instead, they're reallocated as necessary, based on the data's size.  		 * Here we allocate memory, if need be.  		 */		/* TODO this can lead to a big waste of memory */		new_blob_size = determine_adjusted_size(curcol->char_conv, colsize);		if (new_blob_size == 0) {			curcol->column_cur_size = 0;			if (blob->textvalue)				TDS_ZERO_FREE(blob->textvalue);			return TDS_SUCCEED;		}		p = blob->textvalue; /* save pointer in case realloc fails */		if (!p) {			p = (TDS_CHAR *) malloc(new_blob_size);		} else {			/* TODO perhaps we should store allocated bytes too ? */			if (new_blob_size > curcol->column_cur_size ||  (curcol->column_cur_size - new_blob_size) > 10240) {				p = (TDS_CHAR *) realloc(p, new_blob_size);			}		}				if (!p)			return TDS_FAIL;		blob->textvalue = p;		curcol->column_cur_size = new_blob_size;				/* read the data */		if (is_char_type(curcol->column_type)) {			if (tds_get_char_data(tds, (char *) blob, colsize, curcol) == TDS_FAIL)				return TDS_FAIL;		} else {			assert(colsize == new_blob_size);			tds_get_n(tds, blob->textvalue, colsize);		}	} else {		/* non-numeric and non-blob */		curcol->column_cur_size = colsize;		if (curcol->char_conv) {			if (tds_get_char_data(tds, (char *) dest, colsize, curcol) == TDS_FAIL)				return TDS_FAIL;		} else {				/*			 * special case, some servers seem to return more data in some conditions 			 * (ASA 7 returning 4 byte nullable integer)			 */			int discard_len = 0;			if (colsize > curcol->column_size) {				discard_len = colsize - curcol->column_size;				colsize = curcol->column_size;			}			if (tds_get_n(tds, dest, colsize) == NULL)				return TDS_FAIL;			if (discard_len > 0)				tds_get_n(tds, NULL, discard_len);			curcol->column_cur_size = colsize;		}		/* pad (UNI)CHAR and BINARY types */		fillchar = 0;		switch (curcol->column_type) {		/* extra handling for SYBLONGBINARY */		case SYBLONGBINARY:			if (curcol->column_usertype != USER_UNICHAR_TYPE)				break;		case SYBCHAR:		case XSYBCHAR:			if (curcol->column_size != curcol->on_server.column_size)				break;			/* FIXME use client charset */			fillchar = ' ';		case SYBBINARY:		case XSYBBINARY:			if (colsize < curcol->column_size)				memset(dest + colsize, fillchar, curcol->column_size - colsize);			colsize = curcol->column_size;			break;		}		if (curcol->column_type == SYBDATETIME4) {			tdsdump_log(TDS_DBG_INFO1, "datetime4 %d %d %d %d\n", dest[0], dest[1], dest[2], dest[3]);		}	}#ifdef WORDS_BIGENDIAN	/*	 * MS SQL Server 7.0 has broken date types from big endian	 * machines, this swaps the low and high halves of the	 * affected datatypes	 *	 * Thought - this might be because we don't have the	 * right flags set on login.  -mjs	 *	 * Nope its an actual MS SQL bug -bsb	 */	/* TODO test on login, remove configuration -- freddy77 */	if (tds->broken_dates &&	    (curcol->column_type == SYBDATETIME ||	     curcol->column_type == SYBDATETIME4 ||	     curcol->column_type == SYBDATETIMN ||	     curcol->column_type == SYBMONEY ||	     curcol->column_type == SYBMONEY4 || (curcol->column_type == SYBMONEYN && curcol->column_size > 4)))		/*		 * above line changed -- don't want this for 4 byte SYBMONEYN		 * values (mlilback, 11/7/01)		 */	{		unsigned char temp_buf[8];		memcpy(temp_buf, dest, colsize / 2);		memcpy(dest, &dest[colsize / 2], colsize / 2);		memcpy(&dest[colsize / 2], temp_buf, colsize / 2);	}	if (tds->emul_little_endian) {		tdsdump_log(TDS_DBG_INFO1, "swapping coltype %d\n", tds_get_conversion_type(curcol->column_type, colsize));		tds_swap_datatype(tds_get_conversion_type(curcol->column_type, colsize), dest);	}#endif	return TDS_SUCCEED;}/** * tds_process_row() processes rows and places them in the row buffer. */static inttds_process_row(TDSSOCKET * tds){	int i;	TDSCOLUMN *curcol;	TDSRESULTINFO *info;	CHECK_TDS_EXTRA(tds);	info = tds->current_results;	if (!info)		return TDS_FAIL;	assert(info->num_cols > 0);		info->row_count++;	for (i = 0; i < info->num_cols; i++) {		tdsdump_log(TDS_DBG_INFO1, "tds_process_row(): reading column %d \n", i);		curcol = info->columns[i];		if (tds_get_data(tds, curcol) != TDS_SUCCEED)			return TDS_FAIL;	}	return TDS_SUCCEED;}/** * tds_process_end() processes any of the DONE, DONEPROC, or DONEINPROC * tokens. * \param tds        state information for the socket and the TDS protocol * \param marker     TDS token number * \param flags_parm filled with bit flags (see TDS_DONE_ constants).  *        Is NULL nothing is returned */static inttds_process_end(TDSSOCKET * tds, int marker, int *flags_parm){	int more_results, was_cancelled, error, done_count_valid;	int tmp, state;	TDS_INT8 rows_affected;	CHECK_TDS_EXTRA(tds);	tmp = tds_get_smallint(tds);	state = tds_get_smallint(tds);	more_results = (tmp & TDS_DONE_MORE_RESULTS) != 0;	was_cancelled = (tmp & TDS_DONE_CANCELLED) != 0;	error = (tmp & TDS_DONE_ERROR) != 0;	done_count_valid = (tmp & TDS_DONE_COUNT) != 0;	tdsdump_log(TDS_DBG_FUNC, "tds_process_end: more_results = %d\n"		    "\t\twas_cancelled = %d\n"		    "\t\terror = %d\n"		    "\t\tdone_count_valid = %d\n", more_results, was_cancelled, error, done_count_valid);	if (tds->res_info) {		tds->res_info->more_results = more_results;		if (tds->current_results == NULL)			tds->current_results = tds->res_info;	}	if (flags_parm)		*flags_parm = tmp;	if (was_cancelled || (!more_results && !tds->in_cancel)) {		tdsdump_log(TDS_DBG_FUNC, "tds_process_end() state set to TDS_IDLE\n");		/* reset of in_cancel should must done before setting IDLE */		tds->in_cancel = 0;		tds_set_state(tds, TDS_IDLE);	}	if (IS_TDSDEAD(tds))		return TDS_FAIL;	/*	 * rows affected is in the tds struct because a query may affect rows but	 * have no result set.	 */	rows_affected = IS_TDS90(tds) ? tds_get_int8(tds) : tds_get_int(tds);	tdsdump_log(TDS_DBG_FUNC, "                rows_affected = %" TDS_I64_FORMAT "\n", rows_affected);	if (done_count_valid)		tds->rows_affected = rows_affected;	else		tds->rows_affected = TDS_NO_COUNT;	if (IS_TDSDEAD(tds))		return TDS_FAIL;	return was_cancelled ? TDS_CANCELLED : TDS_SUCCEED;}/** * tds_process_env_chg()  * when ever certain things change on the server, such as database, character * set, language, or block size.  A environment change message is generated * There is no action taken currently, but certain functions at the CLI level * that return the name of the current database will need to use this. */static inttds_process_env_chg(TDSSOCKET * tds){	int size, type;	char *oldval = NULL;	char *newval = NULL;	char **dest;	int new_block_size;	int lcid;	int memrc = 0;	CHECK_TDS_EXTRA(tds);	size = tds_get_smallint(tds);	/*	 * this came in a patch, apparently someone saw an env message	 * that was different from what we are handling? -- brian	 * changed back because it won't handle multibyte chars -- 7.0	 */	/* tds_get_n(tds,NULL,size); */	type = tds_get_byte(tds);	/*	 * handle collate default change (if you change db or during login)	 * this environment is not a string so need different handles	 */	if (type == TDS_ENV_SQLCOLLATION) {		/* save new collation */		size = tds_get_byte(tds);		tdsdump_log(TDS_DBG_ERROR, "tds_process_env_chg(): %d bytes of collation data received\n", size);		tdsdump_dump_buf(TDS_DBG_NETWORK, "tds->collation was", tds->collation, 5);		memset(tds->collation, 0, 5);		if (size < 5) {			tds_get_n(tds, tds->collation, size);

⌨️ 快捷键说明

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