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

📄 token.c

📁 在Linux/Unix下面访问WINDOWS SQLSERVER 的ODBC驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
 *   </tr><tr> *    <td>TDS_PARAM_RESULT</td><td>Return parameter results</td> *    <td>param_info or cur_dyn->params contain returned parameters</td> *   </tr><tr> *    <td>TDS_STATUS_RESULT</td><td>Stored procedure status results</td> *    <td>tds->ret_status contain the returned code</td> *  </tr></table> * @param flag Flags to select token type to stop/return * @todo Complete TDS_DESCRIBE_RESULT description * @retval TDS_SUCCEED if a result set is available for processing. * @retval TDS_FAIL on error. * @retval TDS_NO_MORE_RESULTS if all results have been completely processed. * @retval anything returned by one of the many functions it calls.  :-( */inttds_process_tokens(TDSSOCKET *tds, TDS_INT *result_type, int *done_flags, unsigned flag){	int marker;	TDSPARAMINFO *pinfo = NULL;	TDSCOLUMN   *curcol;	int rc;	TDS_INT8 saved_rows_affected = tds->rows_affected;	TDS_INT ret_status;	int cancel_seen = 0;	unsigned return_flag = 0;#define SET_RETURN(ret, f) \	*result_type = ret; \	return_flag = TDS_RETURN_##f | TDS_STOPAT_##f; \	if (flag & TDS_STOPAT_##f) {\		tds_unget_byte(tds); \		tdsdump_log(TDS_DBG_FUNC, "tds_process_tokens::SET_RETURN stopping on current token\n"); \		break; \	}	CHECK_TDS_EXTRA(tds);	tdsdump_log(TDS_DBG_FUNC, "tds_process_tokens(%p, %p, %p, 0x%x)\n", tds, result_type, done_flags, flag);		if (tds->state == TDS_IDLE) {		tdsdump_log(TDS_DBG_FUNC, "tds_process_tokens() state is COMPLETED\n");		*result_type = TDS_DONE_RESULT;		return TDS_NO_MORE_RESULTS;	}	if (tds_set_state(tds, TDS_READING) != TDS_READING)		return TDS_FAIL;	rc = TDS_SUCCEED;	for (;;) {		marker = tds_get_byte(tds);		tdsdump_log(TDS_DBG_INFO1, "processing result tokens.  marker is  %x(%s)\n", marker, _tds_token_name(marker));		switch (marker) {		case TDS7_RESULT_TOKEN:			/*			 * If we're processing the results of a cursor fetch			 * from sql server we don't want to pass back the			 * TDS_ROWFMT_RESULT to the calling API			 */			if (tds->internal_sp_called == TDS_SP_CURSORFETCH) {				rc = tds7_process_result(tds);				marker = tds_get_byte(tds);				if (marker != TDS_TABNAME_TOKEN)					tds_unget_byte(tds);				else					rc = tds_process_tabname(tds);			} else {				SET_RETURN(TDS_ROWFMT_RESULT, ROWFMT);				rc = tds7_process_result(tds);				/* handle browse information (if presents) */				marker = tds_get_byte(tds);				if (marker != TDS_TABNAME_TOKEN) {					tds_unget_byte(tds);					rc = TDS_SUCCEED;					break;				}				rc = tds_process_tabname(tds);			}			break;		case TDS_RESULT_TOKEN:			SET_RETURN(TDS_ROWFMT_RESULT, ROWFMT);			rc = tds_process_result(tds);			break;		case TDS_ROWFMT2_TOKEN:			SET_RETURN(TDS_ROWFMT_RESULT, ROWFMT);			rc = tds5_process_result(tds);			break;		case TDS_COLNAME_TOKEN:			rc = tds_process_col_name(tds);			break;		case TDS_COLFMT_TOKEN:			SET_RETURN(TDS_ROWFMT_RESULT, ROWFMT);			rc = tds_process_col_fmt(tds);			/* handle browse information (if present) */			marker = tds_get_byte(tds);			if (marker != TDS_TABNAME_TOKEN) {				tds_unget_byte(tds);				break;			}			rc = tds_process_tabname(tds);			break;		case TDS_PARAM_TOKEN:			tds_unget_byte(tds);			if (tds->internal_sp_called) {				tdsdump_log(TDS_DBG_FUNC, "processing parameters for sp %d\n", tds->internal_sp_called);				while ((marker = tds_get_byte(tds)) == TDS_PARAM_TOKEN) {					tdsdump_log(TDS_DBG_INFO1, "calling tds_process_param_result\n");					tds_process_param_result(tds, &pinfo);				}				tds_unget_byte(tds);				tdsdump_log(TDS_DBG_FUNC, "%d hidden return parameters\n", pinfo ? pinfo->num_cols : -1);				if (pinfo && pinfo->num_cols > 0) {					curcol = pinfo->columns[0];					if (tds->internal_sp_called == TDS_SP_CURSOROPEN && tds->cur_cursor) {						TDSCURSOR  *cursor = tds->cur_cursor; 						cursor->cursor_id = *(TDS_INT *) curcol->column_data;						tdsdump_log(TDS_DBG_FUNC, "stored internal cursor id %d\n", cursor->cursor_id);						cursor->srv_status &= ~(TDS_CUR_ISTAT_CLOSED|TDS_CUR_ISTAT_OPEN|TDS_CUR_ISTAT_DEALLOC);						cursor->srv_status |= cursor->cursor_id ? TDS_CUR_ISTAT_OPEN : TDS_CUR_ISTAT_CLOSED|TDS_CUR_ISTAT_DEALLOC;					}					if (tds->internal_sp_called == TDS_SP_PREPARE 					    && tds->cur_dyn && tds->cur_dyn->num_id == 0 && curcol->column_cur_size > 0) {						tds->cur_dyn->num_id = *(TDS_INT *) curcol->column_data;					}				}				tds_free_param_results(pinfo);			} else {				SET_RETURN(TDS_PARAM_RESULT, PROC);				rc = tds_process_param_result_tokens(tds);			}			break;		case TDS_COMPUTE_NAMES_TOKEN:			rc = tds_process_compute_names(tds);			break;		case TDS_COMPUTE_RESULT_TOKEN:			SET_RETURN(TDS_COMPUTEFMT_RESULT, COMPUTEFMT);			rc = tds_process_compute_result(tds);			break;		case TDS7_COMPUTE_RESULT_TOKEN:			SET_RETURN(TDS_COMPUTEFMT_RESULT, COMPUTEFMT);			rc = tds7_process_compute_result(tds);			break;		case TDS_ROW_TOKEN:			/* overstepped the mark... */			if (tds->cur_cursor) {				TDSCURSOR  *cursor = tds->cur_cursor; 				tds->current_results = cursor->res_info;				tdsdump_log(TDS_DBG_INFO1, "tds_process_tokens(). set current_results to cursor->res_info\n");			} else {				/* assure that we point to row, not to compute */				if (tds->res_info)					tds->current_results = tds->res_info;			}			/* I don't know when this it's false but it happened, also server can send garbage... */			if (tds->current_results)				tds->current_results->rows_exist = 1;			SET_RETURN(TDS_ROW_RESULT, ROW);			rc = tds_process_row(tds);			break;		case TDS_CMP_ROW_TOKEN:			/* I don't know when this it's false but it happened, also server can send garbage... */			if (tds->res_info)				tds->res_info->rows_exist = 1;			SET_RETURN(TDS_COMPUTE_RESULT, COMPUTE);			rc = tds_process_compute(tds, NULL);			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 && marker != TDS5_PARAMFMT_TOKEN && marker != TDS5_PARAMFMT2_TOKEN)				break;			if (tds->internal_sp_called) {				/* TODO perhaps we should use ret_status ?? */			} else {				/* TODO optimize */				flag &= ~TDS_STOPAT_PROC;				SET_RETURN(TDS_STATUS_RESULT, PROC);				tds->has_status = 1;				tds->ret_status = ret_status;				tdsdump_log(TDS_DBG_FUNC, "tds_process_tokens: return status is %d\n", tds->ret_status);				rc = TDS_SUCCEED;			}			break;		case TDS5_DYNAMIC_TOKEN:			/* process acknowledge dynamic */			tds->cur_dyn = tds_process_dynamic(tds);			/* special case, prepared statement cannot be prepared */			if (!tds->cur_dyn || tds->cur_dyn->emulated)				break;			marker = tds_get_byte(tds);			if (marker != TDS_EED_TOKEN) {				tds_unget_byte(tds);				break;			}			tds_process_msg(tds, marker);			if (!tds->cur_dyn || !tds->cur_dyn->emulated)				break;			marker = tds_get_byte(tds);			if (marker != TDS_DONE_TOKEN) {				tds_unget_byte(tds);				break;			}			rc = tds_process_end(tds, marker, done_flags);			if (done_flags)				*done_flags &= ~TDS_DONE_ERROR;			/* FIXME warning to macro expansion */			SET_RETURN(TDS_DONE_RESULT, DONE);			break;		case TDS5_PARAMFMT_TOKEN:			SET_RETURN(TDS_DESCRIBE_RESULT, PARAMFMT);			rc = tds_process_dyn_result(tds);			break;		case TDS5_PARAMFMT2_TOKEN:			SET_RETURN(TDS_DESCRIBE_RESULT, PARAMFMT);			rc = tds5_process_dyn_result2(tds);			break;		case TDS5_PARAMS_TOKEN:			SET_RETURN(TDS_PARAM_RESULT, PROC);			rc = tds_process_params_result_token(tds);			break;		case TDS_CURINFO_TOKEN:			rc = tds_process_cursor_tokens(tds);			break;		case TDS_DONE_TOKEN:			SET_RETURN(TDS_DONE_RESULT, DONE);			rc = tds_process_end(tds, marker, done_flags);			break;		case TDS_DONEPROC_TOKEN:			SET_RETURN(TDS_DONEPROC_RESULT, DONE);			rc = tds_process_end(tds, marker, done_flags);			switch (tds->internal_sp_called) {			case 0: 			case TDS_SP_PREPARE: 			case TDS_SP_EXECUTE: 			case TDS_SP_UNPREPARE: 			case TDS_SP_EXECUTESQL:				break;			case TDS_SP_CURSOROPEN: 				*result_type       = TDS_DONE_RESULT;				tds->rows_affected = saved_rows_affected;				break;			case TDS_SP_CURSORCLOSE:				tdsdump_log(TDS_DBG_FUNC, "TDS_SP_CURSORCLOSE\n");				if (tds->cur_cursor) { 					TDSCURSOR  *cursor = tds->cur_cursor; 					cursor->srv_status &= ~TDS_CUR_ISTAT_OPEN;					cursor->srv_status |= TDS_CUR_ISTAT_CLOSED|TDS_CUR_ISTAT_DECLARED;					if (cursor->status.dealloc == TDS_CURSOR_STATE_SENT) {						tds_cursor_deallocated(tds, cursor);					}				}				*result_type = TDS_NO_MORE_RESULTS;				rc = TDS_NO_MORE_RESULTS;				break;			default:				*result_type = TDS_NO_MORE_RESULTS;				rc = TDS_NO_MORE_RESULTS;				break;			}			break;		case TDS_DONEINPROC_TOKEN:			switch(tds->internal_sp_called) {			case TDS_SP_CURSOROPEN:			case TDS_SP_CURSORFETCH:			case TDS_SP_PREPARE:			case TDS_SP_CURSORCLOSE:				rc = tds_process_end(tds, marker, done_flags);				if (tds->rows_affected != TDS_NO_COUNT) {					saved_rows_affected = tds->rows_affected;				}				break;			default:				SET_RETURN(TDS_DONEINPROC_RESULT, DONE);				rc = tds_process_end(tds, marker, done_flags);				break;			}			break;		case TDS_ERROR_TOKEN:		case TDS_INFO_TOKEN:		case TDS_EED_TOKEN:			SET_RETURN(TDS_MSG_RESULT, MSG);			rc = tds_process_default_tokens(tds, marker);			break;		default:			SET_RETURN(TDS_OTHERS_RESULT, OTHERS);			rc = tds_process_default_tokens(tds, marker);			break;		}		if (rc == TDS_FAIL) {			tds_set_state(tds, TDS_PENDING);			return rc;		}		cancel_seen |= tds->in_cancel;		if (cancel_seen) {			/* during cancel handle all tokens */			flag = TDS_HANDLE_ALL;		}		if ((return_flag & flag) != 0) {			tds_set_state(tds, TDS_PENDING);			return rc;		}		if (tds->state == TDS_IDLE)			return cancel_seen ? TDS_CANCELLED : TDS_NO_MORE_RESULTS;		if (tds->state == TDS_DEAD) {			/* TODO free all results ?? */			return TDS_FAIL;		}	}}/** * Process results for simple query as "SET TEXTSIZE" or "USE dbname" * If the statement returns results, beware they are discarded. * * This function was written to avoid direct calls to tds_process_default_tokens * (which caused problems such as ignoring query errors). * Results are read until idle state or severe failure (do not stop for  * statement failure). * @return see tds_process_tokens for results (TDS_NO_MORE_RESULTS is never returned) */inttds_process_simple_query(TDSSOCKET * tds){	TDS_INT res_type;	TDS_INT done_flags;	int     rc;	int     ret = TDS_SUCCEED;	CHECK_TDS_EXTRA(tds);	while ((rc = tds_process_tokens(tds, &res_type, &done_flags, TDS_RETURN_DONE)) == TDS_SUCCEED) {		switch (res_type) {			case TDS_DONE_RESULT:			case TDS_DONEPROC_RESULT:			case TDS_DONEINPROC_RESULT:				if ((done_flags & TDS_DONE_ERROR) != 0) 					ret = TDS_FAIL;				break;			default:				break;		}	}	if (rc != TDS_NO_MORE_RESULTS) {		ret = TDS_FAIL;	}	return ret;}struct namelist{	char *name;	struct namelist *next;};static voidtds_free_namelist(struct namelist *head){	struct namelist *cur = head, *prev;	while (cur != NULL) {		prev = cur;		cur = cur->next;		free(prev->name);		free(prev);	}}static inttds_read_namelist(TDSSOCKET * tds, int remainder, struct namelist **p_head, int large){	struct namelist *head = NULL, *cur = NULL, *prev;	int num_names = 0;	/*	 * this is a little messy...TDS 5.0 gives the number of columns	 * upfront, while in TDS 4.2, you're expected to figure it out	 * by the size of the message. So, I use a link list to get the	 * colum names and then allocate the result structure, copy	 * and delete the linked list	 */	while (remainder > 0) {		int namelen;		prev = cur;		if (!(cur = (struct namelist *) malloc(sizeof(struct namelist)))) {			tds_free_namelist(head);			return -1;		}		cur->next = NULL;		if (prev)			prev->next = cur;		else			head = cur;		if (large) {			namelen = tds_get_smallint(tds);			remainder -= 2;		} else {			namelen = tds_get_byte(tds);			--remainder;		}		if (tds_alloc_get_string(tds, &cur->name, namelen) < 0) {			tds_free_namelist(head);			return -1;		}		remainder -= namelen;		num_names++;	}	*p_head = head;	return num_names;}/** * tds_process_col_name() is one half of the result set under TDS 4.2 * it contains all the column names, a TDS_COLFMT_TOKEN should  * immediately follow this token with the datatype/size information * This is a 4.2 only function */static inttds_process_col_name(TDSSOCKET * tds){	int hdrsize;	int col, num_names = 0;	struct namelist *head = NULL, *cur = NULL, *prev;	TDSCOLUMN *curcol;	TDSRESULTINFO *info;	CHECK_TDS_EXTRA(tds);	hdrsize = tds_get_smallint(tds);	if ((num_names = tds_read_namelist(tds, hdrsize, &head, 0)) < 0)		return TDS_FAIL;	/* free results/computes/params etc... */

⌨️ 快捷键说明

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