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

📄 dblib.c

📁 在Linux/Unix下面访问WINDOWS SQLSERVER 的ODBC驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	TDS_MUTEX_UNLOCK(&dblib_mutex);	dblib_release_tds_ctx(count);}static const char *prdbresults_state(int retcode){	static char unknown[12]="oops: ";	switch(retcode) {	case _DB_RES_INIT:		return "_DB_RES_INIT";	case _DB_RES_RESULTSET_EMPTY:	return "_DB_RES_RESULTSET_EMPTY";	case _DB_RES_RESULTSET_ROWS:	return "_DB_RES_RESULTSET_ROWS";	case _DB_RES_NEXT_RESULT:	return "_DB_RES_NEXT_RESULT";	case _DB_RES_NO_MORE_RESULTS:	return "_DB_RES_NO_MORE_RESULTS";	case _DB_RES_SUCCEED:		return "_DB_RES_SUCCEED";	default:		sprintf(unknown + 6, "%u ??", retcode);	}	return unknown;}static const char *prdbretcode(int retcode){	static char unknown[12]="oops: ";	switch(retcode) {	case REG_ROW:		return "REG_ROW/MORE_ROWS";	case NO_MORE_ROWS:	return "NO_MORE_ROWS";	case BUF_FULL:		return "BUF_FULL";	case NO_MORE_RESULTS:	return "NO_MORE_RESULTS";	case SUCCEED:		return "SUCCEED";	case FAIL:		return "FAIL";	default:		sprintf(unknown + 6, "%u ??", retcode);	}	return unknown;}static const char *prretcode(int retcode){	static char unknown[12]="oops";	switch(retcode) {	case TDS_SUCCEED:		return "TDS_SUCCEED";	case TDS_FAIL:			return "TDS_FAIL";	case TDS_NO_MORE_RESULTS:	return "TDS_NO_MORE_RESULTS";	case TDS_CANCELLED:		return "TDS_CANCELLED";	default:		sprintf(unknown, "%u ??", retcode);	}	return unknown;}static const char *prresult_type(int result_type){	static char unknown[12]="oops";	switch(result_type) {	case TDS_ROW_RESULT:		return "TDS_ROW_RESULT";	case TDS_PARAM_RESULT:		return "TDS_PARAM_RESULT";	case TDS_STATUS_RESULT:		return "TDS_STATUS_RESULT";	case TDS_MSG_RESULT:		return "TDS_MSG_RESULT";	case TDS_COMPUTE_RESULT:	return "TDS_COMPUTE_RESULT";	case TDS_CMD_DONE:		return "TDS_CMD_DONE";	case TDS_CMD_SUCCEED:		return "TDS_CMD_SUCCEED";	case TDS_CMD_FAIL:		return "TDS_CMD_FAIL";	case TDS_ROWFMT_RESULT:		return "TDS_ROWFMT_RESULT";	case TDS_COMPUTEFMT_RESULT:	return "TDS_COMPUTEFMT_RESULT";	case TDS_DESCRIBE_RESULT:	return "TDS_DESCRIBE_RESULT";	case TDS_DONE_RESULT:		return "TDS_DONE_RESULT";	case TDS_DONEPROC_RESULT:	return "TDS_DONEPROC_RESULT";	case TDS_DONEINPROC_RESULT:	return "TDS_DONEINPROC_RESULT";	case TDS_OTHERS_RESULT:		return "TDS_OTHERS_RESULT";	default:		sprintf(unknown, "%u ??", result_type);	}	return unknown;}/** * \ingroup dblib_core * \brief Set up query results.   * * \param dbproc contains all information needed by db-lib to manage communications with the server. * \retval SUCCEED Some results are available. * \retval FAIL query was not processed successfully by the server * \retval NO_MORE_RESULTS query produced no results.  * * \remarks Call dbresults() after calling dbsqlexec() or dbsqlok(), or dbrpcsend() returns SUCCEED.  Unless *	one of them fails, dbresults will return either SUCCEED or NO_MORE_RESULTS.   * *	The meaning of \em results is very specific and not very intuitive.  Results are created by either *	- a SELECT statement * 	- a stored procedure * * 	When dbresults returns SUCCEED, therefore, it indicates the server processed the query successfully and  * 	that one or more of these is present: *	- metadata -- dbnumcols() returns 1 or more *	- data -- dbnextrow() returns SUCCEED *	- return status -- dbhasretstat() returns TRUE *	- output parameters -- dbnumrets() returns 1 or more * *	If none of the above are present, dbresults() returns NO_MORE_RESULTS.   * 	 * 	SUCCEED does not imply that DBROWS() will return TRUE or even that dbnumcols() will return nonzero.   *	A general algorithm for reading results will call dbresults() until it return NO_MORE_RESULTS (or FAIL).   * 	An application should check for all the above kinds of results within the dbresults() loop.   *  * \sa dbsqlexec(), dbsqlok(), dbrpcsend(), dbcancel(), DBROWS(), dbnextrow(), dbnumcols(), dbhasretstat(), dbretstatus(), dbnumrets() */RETCODEdbresults(DBPROCESS * dbproc){	RETCODE erc = _dbresults(dbproc);	tdsdump_log(TDS_DBG_FUNC, "dbresults returning %d (%s)\n", erc, prdbretcode(erc));	return erc;}static RETCODE_dbresults(DBPROCESS * dbproc){	RETCODE retcode = FAIL;	TDSSOCKET *tds;	int result_type;	int done_flags;	tdsdump_log(TDS_DBG_FUNC, "dbresults(%p)\n", dbproc);	CHECK_DBPROC();	DBPERROR_RETURN(IS_TDSDEAD(dbproc->tds_socket), SYBEDDNE);	tds = dbproc->tds_socket;	if (IS_TDSDEAD(tds))		return FAIL;	tdsdump_log(TDS_DBG_FUNC, "dbresults: dbresults_state is %d (%s)\n", 					dbproc->dbresults_state, prdbresults_state(dbproc->dbresults_state));	switch ( dbproc->dbresults_state ) {	case _DB_RES_SUCCEED:		dbproc->dbresults_state = _DB_RES_NEXT_RESULT;		return SUCCEED;		break;	case _DB_RES_RESULTSET_ROWS:		dbperror(dbproc, SYBERPND, 0); /* dbresults called while rows outstanding.... */		return FAIL;		break;	case _DB_RES_NO_MORE_RESULTS:		return NO_MORE_RESULTS;		break;	default:		break;	}	for (;;) {		retcode = tds_process_tokens(tds, &result_type, &done_flags, TDS_TOKEN_RESULTS);		tdsdump_log(TDS_DBG_FUNC, "dbresults() tds_process_tokens returned %d (%s),\n\t\t\tresult_type %s\n", 						retcode, prretcode(retcode), prresult_type(result_type));		switch (retcode) {		case TDS_SUCCEED:			switch (result_type) {				case TDS_ROWFMT_RESULT:				buffer_free(&dbproc->row_buf);				buffer_alloc(dbproc);				dbproc->dbresults_state = _DB_RES_RESULTSET_EMPTY;				break;				case TDS_COMPUTEFMT_RESULT:				break;				case TDS_ROW_RESULT:			case TDS_COMPUTE_RESULT:					dbproc->dbresults_state = _DB_RES_RESULTSET_ROWS;				return SUCCEED;				break;				case TDS_DONE_RESULT:			case TDS_DONEPROC_RESULT:				tdsdump_log(TDS_DBG_FUNC, "dbresults(): dbresults_state is %d (%s)\n", 						dbproc->dbresults_state, prdbresults_state(dbproc->dbresults_state));				/* A done token signifies the end of a logical command.				 * There are three possibilities:				 * 1. Simple command with no result set, i.e. update, delete, insert				 * 2. Command with result set but no rows				 * 3. Command with result set and rows				 */				switch (dbproc->dbresults_state) {				case _DB_RES_INIT:				case _DB_RES_NEXT_RESULT:					dbproc->dbresults_state = _DB_RES_NEXT_RESULT;					if (done_flags & TDS_DONE_ERROR)						return FAIL;					break;				case _DB_RES_RESULTSET_EMPTY:				case _DB_RES_RESULTSET_ROWS:					dbproc->dbresults_state = _DB_RES_NEXT_RESULT;					return SUCCEED;					break;				default:					assert(0);					break;				}							case TDS_DONEINPROC_RESULT:				/* 				 * Return SUCCEED on a command within a stored procedure				 * only if the command returned a result set. 				 */				switch (dbproc->dbresults_state) {				case _DB_RES_INIT:  				case _DB_RES_NEXT_RESULT: 					dbproc->dbresults_state = _DB_RES_NEXT_RESULT;					break;				case _DB_RES_RESULTSET_EMPTY :				case _DB_RES_RESULTSET_ROWS : 					dbproc->dbresults_state = _DB_RES_NEXT_RESULT;					return SUCCEED;					break;				}				break;			case TDS_STATUS_RESULT:			case TDS_MSG_RESULT:			case TDS_DESCRIBE_RESULT:			case TDS_PARAM_RESULT:			default:				break;			}			break;		case TDS_NO_MORE_RESULTS:			dbproc->dbresults_state = _DB_RES_NO_MORE_RESULTS;			return NO_MORE_RESULTS;			break;		case TDS_CANCELLED:		case TDS_FAIL:			dbproc->dbresults_state = _DB_RES_INIT;			return FAIL;			break;					default:			tdsdump_log(TDS_DBG_FUNC, "dbresults() does not recognize return code from process_result_tokens\n");			assert(0);			return FAIL;			break;		}	}}/** * \ingroup dblib_core * \brief Return number of regular columns in a result set.   *  * \param dbproc contains all information needed by db-lib to manage communications with the server. * \sa dbcollen(), dbcolname(), dbnumalts(). */intdbnumcols(DBPROCESS * dbproc){	tdsdump_log(TDS_DBG_FUNC, "dbnumcols(%p)\n", dbproc);	CHECK_PARAMETER(dbproc, SYBENULL, 0);	if (dbproc && dbproc->tds_socket && dbproc->tds_socket->res_info)		return dbproc->tds_socket->res_info->num_cols;	return 0;}/** * \ingroup dblib_core * \brief Return name of a regular result column. *  * \param dbproc contains all information needed by db-lib to manage communications with the server. * \param column Nth in the result set, starting with 1.   * \return pointer to ASCII null-terminated string, the name of the column.  * \retval NULL \a column is not in range. * \sa dbcollen(), dbcoltype(), dbdata(), dbdatlen(), dbnumcols(). * \bug Relies on ASCII column names, post iconv conversion.   *      Will not work as described for UTF-8 or UCS-2 clients.   *      But maybe it shouldn't.   */char *dbcolname(DBPROCESS * dbproc, int column){	TDSCOLUMN *colinfo;		tdsdump_log(TDS_DBG_FUNC, "dbcolname(%p, %d)\n", dbproc, column);	colinfo = dbcolptr(dbproc, column);	if (!colinfo)		return NULL;			assert(colinfo->column_name[colinfo->column_namelen] == 0);	return colinfo->column_name;}/** * \ingroup dblib_core * \brief Read a row from the row buffer. *  * When row buffering is enabled (DBBUFFER option is on), the client can use dbgetrow() to re-read a row previously fetched  * with dbnextrow().  The effect is to move the row pointer -- analogous to fseek() -- back to \a row.   * Calls to dbnextrow() read from \a row + 1 until the buffer is exhausted, at which point it resumes * its normal behavior, except that as each row is fetched from the server, it is added to the row * buffer (in addition to being returned to the client).  When the buffer is filled, dbnextrow()  returns  * \c FAIL until the buffer is at least partially emptied with dbclrbuf(). * \param dbproc contains all information needed by db-lib to manage communications with the server. * \param row Nth row to read, starting with 1. * \retval REG_ROW returned row is a regular row. * \returns computeid when returned row is a compute row. * \retval NO_MORE_ROWS no such row in the row buffer.  Current row is unchanged. * \retval FAIL unsuccessful; row buffer may be full.   * \sa dbaltbind(), dbbind(), dbclrbuf(), DBCURROW(), DBFIRSTROW(), DBLASTROW(), dbnextrow(), dbsetrow(). */RETCODEdbgetrow(DBPROCESS * dbproc, DBINT row){	RETCODE result = FAIL;	const int idx = buffer_row2idx(&dbproc->row_buf, row);	tdsdump_log(TDS_DBG_FUNC, "dbgetrow(%p, %d)\n", dbproc, row);	CHECK_DBPROC();	DBPERROR_RETURN(IS_TDSDEAD(dbproc->tds_socket), SYBEDDNE);	if (-1 == idx)		return NO_MORE_ROWS;	dbproc->row_buf.current = idx;	buffer_transfer_bound_data(&dbproc->row_buf, TDS_ROW_RESULT, 0, dbproc, idx);	result = REG_ROW;	return result;}/** * \ingroup dblib_core * \brief Define substitution values to be used when binding null values. *  * \param dbproc contains all information needed by db-lib to manage communications with the server. * \param bindtype	type of binding to which the substitute value will apply.  * \param bindlen 	size of the substitute value you are supplying, in bytes.  * 			Ignored except for CHARBIND and BINARYBIND.  * \param bindval 	pointer to a buffer containing the substitute value. * \retval SUCCEED query was processed without errors. * \retval FAIL query was not processed * \sa dbaltbind(), dbbind(), dbconvert(), dbnullbind(). */RETCODEdbsetnull(DBPROCESS * dbproc, int bindtype, int bindlen, BYTE *bindval){	BYTE *pval;		tdsdump_log(TDS_DBG_FUNC, "dbsetnull(%p, %d, %d, %p)\n", dbproc, bindtype, bindlen, bindval);		CHECK_DBPROC();	DBPERROR_RETURN(IS_TDSDEAD(dbproc->tds_socket), SYBEDDNE);	CHECK_PARAMETER(bindval, SYBENBVP, FAIL);		switch (bindtype) {	case DATETIMEBIND:	case DECIMALBIND:	case FLT8BIND:	case INTBIND:	case MONEYBIND:	case NUMERICBIND:	case REALBIND:	case SMALLBIND:	case SMALLDATETIMEBIND:	case SMALLMONEYBIND:	case TINYBIND:		bindlen = default_null_representations[bindtype].len;		break;	case CHARBIND:	case BINARYBIND:		CHECK_PARAMETER(bindlen >= 0, SYBEBBL, FAIL);		break;			case NTBSTRINGBIND:	bindlen = strlen((char *) bindval);		break;	case STRINGBIND:	bindlen = strlen((char *) bindval);		break;	case VARYBINBIND:	bindlen = ((TDS_VARBINARY*) bindval)->len;		break;	case VARYCHARBIND:	bindlen = ((TDS_VARCHAR*) bindval)->len;		break;#if 0	case SENSITIVITYBIND:	case BOUNDARYBIND:#endif	default:		dbperror(dbproc, SYBEBTYP, 0);		return FAIL;	}	if ((pval = malloc(bindlen)) == NULL) {		dbperror(dbproc, SYBEMEM, errno);		return FAIL;	}		/* free any prior allocation */	if (dbproc->nullreps[bindtype].bindval != default_null_representations[bindtype].bindval)		free((BYTE*)dbproc->nullreps[bindtype].bindval);	memcpy(pval, bindval, bindlen);		dbproc->nullreps[bindtype].bindval = pval;	dbproc->nullreps[bindtype].len = bindlen;	tdsdump_dump_buf(TDS_DBG_NETWORK, "null representation set ", pval,  bindlen);	return SUCCEED;}/** * \ingroup dblib_core * \brief Make a buffered row "current" without fetching it into bound variables.   *  * \param dbproc contains all information needed by db-lib to manage communications with the server. * \retval MORE_ROWS row found * \retval NO_MORE_ROWS row not found * \retval FAIL \a dbproc is dead or not enabled * \sa dbaltbind(), dbbind(), dbcanquery(), dbclrbuf(), dbgetrow(), dbnextrow(), dbprrow(). */RETCODEdbsetrow(DBPROCESS * dbproc, DBINT row){	const int idx = buffer_row2idx(&dbproc->row_buf, row);	tdsdump_log(TDS_DBG_FUNC, "dbsetrow(%p, %d)\n", dbproc, row);	CHECK_DBPROC();	DBPERROR_RETURN(IS_TDSDEAD(dbproc->tds_socket), SYBEDDNE);	if (-1 == idx)		return NO_MORE_ROWS;			dbproc->row_buf.current = idx;			/* FIXME: should determine REG_ROW or compute_id; */	return REG_ROW;	}/** * \ingroup dblib_core * \brief Read result row into the row buffer and into any bound host variables. *  * \param dbproc contains all information needed by db-lib to manage communications with the server. * \retval REG_ROW regular row has been read. * \returns computeid when a compute row is read.  * \retval BUF_FULL reading next row would cause the buffer to be exceeded (and buffering is turned on). * No row was read from the server * \sa dbaltbind(), dbbind(), dbcanquery(), dbclrbuf(), dbgetrow(), dbprrow(), dbsetrow(). */RETCODEdbnextrow(DBPROCESS * dbproc){	TDSRESULTINFO *resinfo;	TDSSOCKET *tds;	RETCODE result = FAIL;	TDS_INT res_type;	TDS_INT computeid;	int idx; /* row buffer index.  Unless DBUFFER is on, idx will always be 0. */	tdsdump_log(TDS_DBG_FUNC, "dbnextrow(%p)\n", dbproc);	CHECK_DBPROC();	DBPERROR_RETURN(IS_TDSDEAD(dbproc->tds_socket), SYBEDDNE);	tds = dbproc->tds_socket;	if (IS_TDSDEAD(tds)) {		dbperror(dbproc, SYBEDDNE, 0);		return FAIL;	}	resinfo = tds->res_info;

⌨️ 快捷键说明

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