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

📄 dblib.c

📁 在Linux/Unix下面访问WINDOWS SQLSERVER 的ODBC驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	tdsdump_log(TDS_DBG_FUNC, "dbnextrow() dbresults_state = %d (%s)\n", 					dbproc->dbresults_state, prdbresults_state(dbproc->dbresults_state));	if (!resinfo || dbproc->dbresults_state != _DB_RES_RESULTSET_ROWS) {		/* no result set or result set empty (no rows) */		tdsdump_log(TDS_DBG_FUNC, "leaving dbnextrow() returning %d (NO_MORE_ROWS)\n", NO_MORE_ROWS);		return dbproc->row_type = NO_MORE_ROWS;	}	/*	 * Try to get the dbproc->row_buf.current item from the buffered rows, if any.  	 * Else read from the stream, unless the buffer is exhausted.  	 * If no rows are read, DBROWTYPE() will report NO_MORE_ROWS. 	 */	dbproc->row_type = NO_MORE_ROWS; 	computeid = REG_ROW;	if (-1 != (idx = buffer_current_index(dbproc))) {					/*		 * Cool, the item we want is already there		 */		result = dbproc->row_type = REG_ROW;		res_type = TDS_ROW_RESULT;			} else if (buffer_is_full(&dbproc->row_buf)) {				result = BUF_FULL;		res_type = TDS_ROWFMT_RESULT;	} else {		const int mask = TDS_STOPAT_ROWFMT|TDS_RETURN_DONE|TDS_RETURN_ROW|TDS_RETURN_COMPUTE;		buffer_save_row(dbproc);		/* Get the row from the TDS stream.  */		switch (tds_process_tokens(tds, &res_type, NULL, mask)) {		case TDS_SUCCEED:			if (res_type == TDS_ROW_RESULT || res_type == TDS_COMPUTE_RESULT) {				if (res_type == TDS_COMPUTE_RESULT)					computeid = tds->current_results->computeid;				/* Add the row to the row buffer, whose capacity is always at least 1 */				resinfo = tds->current_results;				idx = buffer_add_row(dbproc, resinfo);				assert(idx != -1);				result = dbproc->row_type = (res_type == TDS_ROW_RESULT)? REG_ROW : computeid;#if 0 /* TODO */				tds_process_tokens(tds, &res_type, NULL, TDS_TOKEN_TRAILING);#endif				break;			}		case TDS_NO_MORE_RESULTS:			dbproc->dbresults_state = _DB_RES_NEXT_RESULT;			result = NO_MORE_ROWS;			break;		default:			tdsdump_log(TDS_DBG_FUNC, "unexpected: leaving dbnextrow() returning FAIL\n");			return FAIL;			break;		}	}	if (res_type == TDS_ROW_RESULT || res_type == TDS_COMPUTE_RESULT) {		/*		 * Transfer the data from the row buffer to the bound variables.  		 */		buffer_transfer_bound_data(&dbproc->row_buf, res_type, computeid, dbproc, idx);	}		if (res_type == TDS_COMPUTE_RESULT) {		tdsdump_log(TDS_DBG_FUNC, "leaving dbnextrow() returning compute_id %d\n", result);	} else {		tdsdump_log(TDS_DBG_FUNC, "leaving dbnextrow() returning %s\n", prdbretcode(result));	}	return result;} /* dbnextrow()  */static int_db_get_server_type(int bindtype){	switch (bindtype) {	case CHARBIND:	case STRINGBIND:	case NTBSTRINGBIND:		return SYBCHAR;		break;	case FLT8BIND:		return SYBFLT8;		break;	case REALBIND:		return SYBREAL;		break;	case INTBIND:		return SYBINT4;		break;	case SMALLBIND:		return SYBINT2;		break;	case TINYBIND:		return SYBINT1;		break;	case DATETIMEBIND:		return SYBDATETIME;		break;	case SMALLDATETIMEBIND:		return SYBDATETIME4;		break;	case MONEYBIND:		return SYBMONEY;		break;	case SMALLMONEYBIND:		return SYBMONEY4;		break;	case BINARYBIND:		return SYBBINARY;		break;	case VARYCHARBIND:		return SYBVARCHAR;		break;	case BITBIND:		return SYBBIT;		break;	case NUMERICBIND:		return SYBNUMERIC;		break;	case DECIMALBIND:		return SYBDECIMAL;		break;	default:		return -1;		break;	}}/** * \ingroup dblib_core * \brief Convert one datatype to another. * * \param dbproc contains all information needed by db-lib to manage communications with the server. * \param srctype datatype of the data to convert.  * \param src buffer to convert * \param srclen length of \a src * \param desttype target datatype * \param dest output buffer * \param destlen size of \a dest * \returns	On success, the count of output bytes in \a dest, else -1. On failure, it will call any user-supplied error handler.  * \remarks 	 Causes of failure:  * 		- No such conversion unavailable.  * 		- Character data output was truncated, or numerical data overflowed or lost precision.  * 		- In converting character data to one of the numeric types, the string could not be interpreted as a number.   *		 * Conversion functions are handled in the TDS layer. *  * The main reason for this is that \c ct-lib and \c ODBC (and presumably \c DBI) need * to be able to do conversions between datatypes. This is possible because * the format of complex data (dates, money, numeric, decimal) is defined by * its representation on the wire; thus what we call \c DBMONEY is exactly its * format on the wire. CLIs that need a different representation (ODBC?)  * need to convert from this format anyway, so the code would already be in * place. *  * Each datatype is also defined by its Server-type so all CLIs should be  * able to map native types to server types as well. * * tds_convert() copies from src to dest and returns the output data length, * period.  All padding and termination is the responsibility of the API library * and is done post-conversion.  The peculiar rule in dbconvert() is that * a \a destlen of -1 and a \a desttype of \c SYBCHAR means the output buffer * should be null-terminated. *   * \sa dbaltbind(), dbaltbind_ps(), dbbind(), dbbind_ps(), dbconvert_ps(), dberrhandle(), dbsetnull(), dbsetversion(), dbwillconvert(). * \todo What happens if client does not reset values?  * \todo Microsoft and Sybase define this function differently.   */DBINTdbconvert(DBPROCESS * dbproc, int srctype, const BYTE * src, DBINT srclen, int desttype, BYTE * dest, DBINT destlen){	CONV_RESULT dres;	DBINT ret;	int i;	int len;	DBNUMERIC *num;	tdsdump_log(TDS_DBG_FUNC, "dbconvert(%p, %s, %p, %d, %s, %p, %d)\n", 			dbproc, tds_prdatatype(srctype), src, srclen, tds_prdatatype(desttype), dest, destlen);	/* dbproc and src can be NULLs */	CHECK_PARAMETER(dest, SYBEACNV, -1);		if (0 == destlen) 		return 0; 	if (src == NULL || srclen == 0) {		int bind = dbbindtype(desttype);		int size = tds_get_size_by_type(desttype);				if (SYBCHAR == desttype) {			if (destlen > 0) {				size = destlen;				bind = CHARBIND;			} else { 				size = 1;				bind = NTBSTRINGBIND;			}		}		dbgetnull(dbproc, bind, size, dest);		return size;	}	/* srclen of -1 means the source data is definitely NULL terminated */	if (srclen == -1)		srclen = strlen((const char *) src);	/* oft times we are asked to convert a data type to itself */	if (srctype == desttype) {		ret = -2;  /* to make sure we always set it */		tdsdump_log(TDS_DBG_INFO1, "dbconvert() srctype == desttype\n");		switch (desttype) {		case SYBBINARY:		case SYBVARBINARY:		case SYBIMAGE:			if (srclen > destlen && destlen >= 0) {				dbperror(dbproc, SYBECOFL, 0);				ret = -1;			} else {				memcpy(dest, src, srclen);				if (srclen < destlen)					memset(dest + srclen, 0, destlen - srclen);				ret = srclen;			}			break;		case SYBCHAR:		case SYBVARCHAR:		case SYBTEXT:			/* srclen of -1 means the source data is definitely NULL terminated */			if (srclen == -1)				srclen = strlen((const char *) src);			switch (destlen) {			case  0:	/* nothing to copy */				ret = 0;				break;			case -1:	/* rtrim and null terminate */				while (srclen && src[srclen - 1] == ' ') {					--srclen;				}				/* fall thru */			case -2:	/* just null terminate */				memcpy(dest, src, srclen);				dest[srclen] = '\0';				ret = srclen;				break;			default:				assert(destlen > 0);				if (destlen < 0 || srclen > destlen) {					dbperror(dbproc, SYBECOFL, 0);					ret = -1;				} else {					memcpy(dest, src, srclen);					for (i = srclen; i < destlen; i++)						dest[i] = ' ';					ret = srclen;				}				break;			}			break;		case SYBINT1:		case SYBINT2:		case SYBINT4:		case SYBINT8:		case SYBFLT8:		case SYBREAL:		case SYBBIT:		case SYBBITN:		case SYBMONEY:		case SYBMONEY4:		case SYBDATETIME:		case SYBDATETIME4:		case SYBUNIQUE:			ret = tds_get_size_by_type(desttype);			memcpy(dest, src, ret);			break;		case SYBNUMERIC:		case SYBDECIMAL:			memcpy(dest, src, sizeof(DBNUMERIC));			ret = sizeof(DBNUMERIC);			break;		default:			ret = -1;			break;		}		assert(ret > -2);		return ret;	}	/* end srctype == desttype */	assert(srctype != desttype);	/*	 * Character types need no conversion.  Just move the data.	 */	if (is_similar_type(srctype, desttype)) {		if (src && dest && srclen > 0 && destlen >= srclen) {			memcpy(dest, src, srclen);			return srclen;		}	}	/* FIXME what happen if client do not reset values ??? */	/* FIXME act differently for ms and sybase */	if (is_numeric_type(desttype)) {		num = (DBNUMERIC *) dest;		if (num->precision == 0)			dres.n.precision = 18;		else			dres.n.precision = num->precision;		if (num->scale == 0)			dres.n.scale = 0;		else			dres.n.scale = num->scale;	}	tdsdump_log(TDS_DBG_INFO1, "dbconvert() calling tds_convert\n");	len = tds_convert(g_dblib_ctx.tds_ctx, srctype, (const TDS_CHAR *) src, srclen, desttype, &dres);	tdsdump_log(TDS_DBG_INFO1, "dbconvert() called tds_convert returned %d\n", len);	switch (len) {	case TDS_CONVERT_NOAVAIL:		dbperror(dbproc, SYBERDCN, 0);		return -1;		break;	case TDS_CONVERT_SYNTAX:		dbperror(dbproc, SYBECSYN, 0);		return -1;		break;	case TDS_CONVERT_NOMEM:		dbperror(dbproc, SYBEMEM, ENOMEM);		return -1;		break;	case TDS_CONVERT_OVERFLOW:		dbperror(dbproc, SYBECOFL, 0);		return -1;		break;	case TDS_CONVERT_FAIL:		dbperror(dbproc, SYBECINTERNAL, 0);		return -1;		break;	default:		if (len < 0) { /* logic error: should be captured above */			dbperror(dbproc, SYBECINTERNAL, 0);			return -1;		}		break;	}	switch (desttype) {	case SYBBINARY:	case SYBVARBINARY:	case SYBIMAGE:		if (len > destlen && destlen >= 0) {			dbperror(dbproc, SYBECOFL, 0);			ret = -1;		} else {			memcpy(dest, dres.ib, len);			free(dres.ib);			if (len < destlen)				memset(dest + len, 0, destlen - len);			ret = len;		}		break;	case SYBINT1:		memcpy(dest, &(dres.ti), 1);		ret = 1;		break;	case SYBINT2:		memcpy(dest, &(dres.si), 2);		ret = 2;		break;	case SYBINT4:		memcpy(dest, &(dres.i), 4);		ret = 4;		break;	case SYBINT8:		memcpy(dest, &(dres.bi), 8);		ret = 8;		break;	case SYBFLT8:		memcpy(dest, &(dres.f), 8);		ret = 8;		break;	case SYBREAL:		memcpy(dest, &(dres.r), 4);		ret = 4;		break;	case SYBBIT:	case SYBBITN:		memcpy(dest, &(dres.ti), 1);		ret = 1;		break;	case SYBMONEY:		memcpy(dest, &(dres.m), sizeof(TDS_MONEY));		ret = sizeof(TDS_MONEY);		break;	case SYBMONEY4:		memcpy(dest, &(dres.m4), sizeof(TDS_MONEY4));		ret = sizeof(TDS_MONEY4);		break;	case SYBDATETIME:		memcpy(dest, &(dres.dt), sizeof(TDS_DATETIME));		ret = sizeof(TDS_DATETIME);		break;	case SYBDATETIME4:		memcpy(dest, &(dres.dt4), sizeof(TDS_DATETIME4));		ret = sizeof(TDS_DATETIME4);		break;	case SYBNUMERIC:	case SYBDECIMAL:		memcpy(dest, &(dres.n), sizeof(TDS_NUMERIC));		ret = sizeof(TDS_NUMERIC);		break;	case SYBUNIQUE:		memcpy(dest, &(dres.u), sizeof(TDS_UNIQUE));		ret = sizeof(TDS_UNIQUE);		break;	case SYBCHAR:	case SYBVARCHAR:	case SYBTEXT:		tdsdump_log(TDS_DBG_INFO1, "dbconvert() outputting %d bytes character data destlen = %d \n", len, destlen);		if (destlen < -2)			destlen = 0;	/* failure condition */		switch (destlen) {		case 0:			ret = FAIL;			break;		case -1:	/* rtrim and null terminate */			for (i = len - 1; i >= 0 && dres.c[i] == ' '; --i) {				len = i;			}			memcpy(dest, dres.c, len);			dest[len] = '\0';			ret = len;			break;		case -2:	/* just null terminate */			memcpy(dest, dres.c, len);			dest[len] = 0;			ret = len;			break;		default:			assert(destlen > 0);			if (destlen < 0 || len > destlen) {				dbperror(dbproc, SYBECOFL, 0);				ret = -1;				tdsdump_log(TDS_DBG_INFO1, "%d bytes type %d -> %d, destlen %d < %d required\n",					    srclen, srctype, desttype, destlen, len);				break;			}			/* else pad with blanks */			memcpy(dest, dres.c, len);			for (i = len; i < destlen; i++)				dest[i] = ' ';			ret = len;			break;		}		free(dres.c);		break;	default:		tdsdump_log(TDS_DBG_INFO1, "error: dbconvert(): unrecognized desttype %d \n", desttype);		ret = -1;		break;	}	return (ret);}/** * \ingroup dblib_core * \brief cf. dbconvert(), above *  * \em Sybase: Convert numeric types. * \param dbproc contains all information needed by db-lib to manage com

⌨️ 快捷键说明

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