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

📄 query.c

📁 在Linux/Unix下面访问WINDOWS SQLSERVER 的ODBC驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
			tds_convert_string_free((char*)src, s);	} else {		/* TODO ICONV handle charset conversions for data */		/* put size of data */		switch (curcol->column_varint_size) {		case 4:	/* It's a BLOB... */			blob = (TDSBLOB *) curcol->column_data;			tds_put_byte(tds, 16);			tds_put_n(tds, blob->textptr, 16);			tds_put_n(tds, blob->timestamp, 8);			colsize = MIN(colsize, 0x7fffffff);			tds_put_int(tds, colsize);			break;		case 2:			colsize = MIN(colsize, 8000);			tds_put_smallint(tds, colsize);			break;		case 1:			if (is_numeric_type(curcol->column_type))				colsize = tds_numeric_bytes_per_prec[((TDS_NUMERIC *) src)->precision];			colsize = MIN(colsize, 255);			tds_put_byte(tds, colsize);			break;		case 0:			/* TODO should be column_size */			colsize = tds_get_size_by_type(curcol->column_type);			break;		}		/* put real data */		if (is_numeric_type(curcol->column_type)) {			num = (TDS_NUMERIC *) src;			tds_put_n(tds, num->array, colsize);		} else if (is_blob_type(curcol->column_type)) {			blob = (TDSBLOB *) src;			/* FIXME ICONV handle conversion when needed */			tds_put_n(tds, blob->textvalue, colsize);		} else {#ifdef WORDS_BIGENDIAN			unsigned char buf[64];			if (tds->emul_little_endian && colsize < 64) {				tdsdump_log(TDS_DBG_INFO1, "swapping coltype %d\n",					    tds_get_conversion_type(curcol->column_type, colsize));				memcpy(buf, src, colsize);				tds_swap_datatype(tds_get_conversion_type(curcol->column_type, colsize), buf);				src = buf;			}#endif			tds_put_n(tds, src, colsize);		}	}	return TDS_SUCCEED;}static voidtds7_send_execute(TDSSOCKET * tds, TDSDYNAMIC * dyn){	TDSCOLUMN *param;	TDSPARAMINFO *info;	int i;	/* procedure name */	tds_put_smallint(tds, 10);	/* NOTE do not call this procedure using integer name (TDS_SP_EXECUTE) on mssql2k, it doesn't work! */	TDS_PUT_N_AS_UCS2(tds, "sp_execute");	tds_put_smallint(tds, 0);	/* flags */	/* id of prepared statement */	tds_put_byte(tds, 0);	tds_put_byte(tds, 0);	tds_put_byte(tds, SYBINTN);	tds_put_byte(tds, 4);	tds_put_byte(tds, 4);	tds_put_int(tds, dyn->num_id);	info = dyn->params;	if (info)		for (i = 0; i < info->num_cols; i++) {			param = info->columns[i];			/* TODO check error */			tds_put_data_info(tds, param, 0);			tds_put_data(tds, param);		}	tds->internal_sp_called = TDS_SP_EXECUTE;}/** * tds_submit_execute() sends a previously prepared dynamic statement to the  * server. * \param tds state information for the socket and the TDS protocol * \param dyn dynamic proc to execute. Must build from same tds. */inttds_submit_execute(TDSSOCKET * tds, TDSDYNAMIC * dyn){	int id_len;	CHECK_TDS_EXTRA(tds);	/* TODO this dynamic should be in tds */	CHECK_DYNAMIC_EXTRA(dyn);	tdsdump_log(TDS_DBG_FUNC, "tds_submit_execute()\n");	if (tds_set_state(tds, TDS_QUERYING) != TDS_QUERYING)		return TDS_FAIL;	tds->cur_dyn = dyn;	if (IS_TDS7_PLUS(tds)) {		/* check proper id */		if (dyn->num_id == 0) {			tds_set_state(tds, TDS_IDLE);			return TDS_FAIL;		}		/* RPC on sp_execute */		tds->out_flag = TDS_RPC;		START_QUERY;		tds7_send_execute(tds, dyn);		return tds_query_flush_packet(tds);	}	if (dyn->emulated) {		if (tds_send_emulated_execute(tds, dyn->query, dyn->params) != TDS_SUCCEED)			return TDS_FAIL;		return tds_query_flush_packet(tds);	}	/* query has been prepared successfully, discard original query */	if (dyn->query)		TDS_ZERO_FREE(dyn->query);	tds->out_flag = TDS_NORMAL;	/* dynamic id */	id_len = strlen(dyn->id);	tds_put_byte(tds, TDS5_DYNAMIC_TOKEN);	tds_put_smallint(tds, id_len + 5);	tds_put_byte(tds, 0x02);	tds_put_byte(tds, dyn->params ? 0x01 : 0);	tds_put_byte(tds, id_len);	tds_put_n(tds, dyn->id, id_len);	tds_put_smallint(tds, 0);	if (dyn->params)		tds_put_params(tds, dyn->params, 0);	/* send it */	return tds_query_flush_packet(tds);}static voidtds_put_params(TDSSOCKET * tds, TDSPARAMINFO * info, int flags){	int i, len;	CHECK_TDS_EXTRA(tds);	CHECK_PARAMINFO_EXTRA(info);	/* column descriptions */	tds_put_byte(tds, TDS5_PARAMFMT_TOKEN);	/* size */	len = 2;	for (i = 0; i < info->num_cols; i++)		len += tds_put_data_info_length(tds, info->columns[i], flags);	tds_put_smallint(tds, len);	/* number of parameters */	tds_put_smallint(tds, info->num_cols);	/* column detail for each parameter */	for (i = 0; i < info->num_cols; i++) {		/* FIXME add error handling */		tds_put_data_info(tds, info->columns[i], flags);	}	/* row data */	tds_put_byte(tds, TDS5_PARAMS_TOKEN);	for (i = 0; i < info->num_cols; i++) {		tds_put_data(tds, info->columns[i]);	}}static volatile int inc_num = 1;/** * Get an id for dynamic query based on TDS information * \param tds state information for the socket and the TDS protocol * \return TDS_FAIL or TDS_SUCCEED */inttds_get_dynid(TDSSOCKET * tds, char **id){	unsigned long n;	int i;	char *p;	char c;	CHECK_TDS_EXTRA(tds);	inc_num = (inc_num + 1) & 0xffff;	/* some version of Sybase require length <= 10, so we code id */	n = (unsigned long) tds;	if (!(p = (char *) malloc(16)))		return TDS_FAIL;	*id = p;	*p++ = (char) ('a' + (n % 26u));	n /= 26u;	for (i = 0; i < 9; ++i) {		c = (char) ('0' + (n % 36u));		*p++ = (c < ('0' + 10)) ? c : c + ('a' - '0' - 10);		/* printf("%d -> %d(%c)\n",n%36u,p[-1],p[-1]); */		n /= 36u;		if (i == 4)			n += 3u * inc_num;	}	*p++ = 0;	return TDS_SUCCEED;}/** * Send a unprepare request for a prepared query * \param tds state information for the socket and the TDS protocol * \param dyn dynamic query * \result TDS_SUCCEED or TDS_FAIL */inttds_submit_unprepare(TDSSOCKET * tds, TDSDYNAMIC * dyn){	int id_len;	CHECK_TDS_EXTRA(tds);	/* TODO test dyn in tds */	CHECK_DYNAMIC_EXTRA(dyn);	if (!dyn)		return TDS_FAIL;	tdsdump_log(TDS_DBG_FUNC, "tds_submit_unprepare() %s\n", dyn->id);	if (tds_set_state(tds, TDS_QUERYING) != TDS_QUERYING)		return TDS_FAIL;	tds->cur_dyn = dyn;	if (IS_TDS7_PLUS(tds)) {		/* RPC on sp_execute */		tds->out_flag = TDS_RPC;		START_QUERY;		/* procedure name */		if (IS_TDS8_PLUS(tds)) {			/* save some byte for mssql2k */			tds_put_smallint(tds, -1);			tds_put_smallint(tds, TDS_SP_UNPREPARE);		} else {			tds_put_smallint(tds, 12);			TDS_PUT_N_AS_UCS2(tds, "sp_unprepare");		}		tds_put_smallint(tds, 0);	/* flags */		/* id of prepared statement */		tds_put_byte(tds, 0);		tds_put_byte(tds, 0);		tds_put_byte(tds, SYBINTN);		tds_put_byte(tds, 4);		tds_put_byte(tds, 4);		tds_put_int(tds, dyn->num_id);		tds->internal_sp_called = TDS_SP_UNPREPARE;		return tds_query_flush_packet(tds);	}	if (dyn->emulated) {		tds->out_flag = TDS_QUERY;		START_QUERY;		/* just a dummy select to return some data */		tds_put_string(tds, "select 1 where 0=1", -1);		return tds_query_flush_packet(tds);	}	tds->out_flag = TDS_NORMAL;	/* dynamic id */	id_len = strlen(dyn->id);	tds_put_byte(tds, TDS5_DYNAMIC_TOKEN);	tds_put_smallint(tds, id_len + 5);	tds_put_byte(tds, 0x04);	tds_put_byte(tds, 0x00);	tds_put_byte(tds, id_len);	tds_put_n(tds, dyn->id, id_len);	tds_put_smallint(tds, 0);	/* send it */	return tds_query_flush_packet(tds);}/** * tds_submit_rpc() call a RPC from server. Output parameters will be stored in tds->param_info * \param tds      state information for the socket and the TDS protocol * \param rpc_name name of RPC * \param params   parameters informations. NULL for no parameters */inttds_submit_rpc(TDSSOCKET * tds, const char *rpc_name, TDSPARAMINFO * params){	TDSCOLUMN *param;	int rpc_name_len, i;	int num_params = params ? params->num_cols : 0;	CHECK_TDS_EXTRA(tds);	if (params)		CHECK_PARAMINFO_EXTRA(params);	assert(tds);	assert(rpc_name);	if (tds_set_state(tds, TDS_QUERYING) != TDS_QUERYING)		return TDS_FAIL;	/* distinguish from dynamic query  */	tds->cur_dyn = NULL;	rpc_name_len = strlen(rpc_name);	if (IS_TDS7_PLUS(tds)) {		const char *converted_name;		int converted_name_len;		tds->out_flag = TDS_RPC;		/* procedure name */		converted_name = tds_convert_string(tds, tds->char_convs[client2ucs2], rpc_name, rpc_name_len, &converted_name_len);		if (!converted_name) {			tds_set_state(tds, TDS_IDLE);			return TDS_FAIL;		}		START_QUERY;		tds_put_smallint(tds, converted_name_len / 2);		tds_put_n(tds, converted_name, converted_name_len);		tds_convert_string_free(rpc_name, converted_name);		/*		 * TODO support flags		 * bit 0 (1 as flag) in TDS7/TDS5 is "recompile"		 * bit 1 (2 as flag) in TDS7+ is "no metadata" bit 		 * (I don't know meaning of "no metadata")		 */		tds_put_smallint(tds, 0);		for (i = 0; i < num_params; i++) {			param = params->columns[i];			/* TODO check error */			tds_put_data_info(tds, param, TDS_PUT_DATA_USE_NAME);			tds_put_data(tds, param);		}		return tds_query_flush_packet(tds);	}	if (IS_TDS50(tds)) {		tds->out_flag = TDS_NORMAL;		/* DBRPC */		tds_put_byte(tds, TDS_DBRPC_TOKEN);		/* TODO ICONV convert rpc name */		tds_put_smallint(tds, rpc_name_len + 3);		tds_put_byte(tds, rpc_name_len);		tds_put_n(tds, rpc_name, rpc_name_len);		/* TODO flags */		tds_put_smallint(tds, num_params ? 2 : 0);		if (num_params)			tds_put_params(tds, params, TDS_PUT_DATA_USE_NAME);		/* send it */		return tds_query_flush_packet(tds);	}	/* TODO emulate it for TDS4.x, send RPC for mssql */	/* TODO continue, support for TDS4?? */	tds_set_state(tds, TDS_IDLE);	return TDS_FAIL;}/** * tds_send_cancel() sends an empty packet (8 byte header only) * tds_process_cancel should be called directly after this. * \param tds state information for the socket and the TDS protocol * \remarks *	tcp will either deliver the packet or time out.  *	(TIME_WAIT determines how long it waits between retries.)   *	 *	On sending the cancel, we may get EAGAIN.  We then select(2) until we know *	either 1) it succeeded or 2) it didn't.  On failure, close the socket, *	tell the app, and fail the function.   *	 *	On success, we read(2) and wait for a reply with select(2).  If we get *	one, great.  If the client's timeout expires, we tell him, but all we can *	do is wait some more or give up and close the connection.  If he tells us *	to cancel again, we wait some more.   */inttds_send_cancel(TDSSOCKET * tds){	CHECK_TDS_EXTRA(tds); 	tdsdump_log(TDS_DBG_FUNC, "tds_send_cancel: %sin_cancel and %sidle\n", 				(tds->in_cancel? "":"not "), (tds->state == TDS_IDLE? "":"not "));		/* one cancel is sufficient */	if (tds->in_cancel || tds->state == TDS_IDLE)		return TDS_SUCCEED;	tds->out_flag = TDS_CANCEL;	tds->in_cancel = 1; 	tdsdump_log(TDS_DBG_FUNC, "tds_send_cancel: sending cancel packet\n");	return tds_flush_packet(tds);}static inttds_quote(TDSSOCKET * tds, char *buffer, char quoting, const char *id, int len){	int i;	const char *src, *pend;	char *dst;	CHECK_TDS_EXTRA(tds);	pend = id + len;	/* quote */	src = id;	if (!buffer) {		i = 2 + len;		for (; src != pend; ++src)			if (*src == quoting)				++i;		return i;	}	dst = buffer;	*dst++ = (quoting == ']') ? '[' : quoting;	for (; src != pend; ++src) {		if (*src == quoting)			*dst++ = quoting;		*dst++ = *src;	}	*dst++ = quoting;	*dst = 0;	return dst - buffer;}/** * Quote an id * \param tds    state information for the socket and the TDS protocol * \param buffer buffer to store quoted id. If NULL do not write anything  *        (useful to compute quote length) * \param id     id to quote * \param idlen  id length * \result written chars (not including needed terminator) */inttds_quote_id(TDSSOCKET * tds, char *buffer, const char *id, int idlen){	int i;	CHECK_TDS_EXTRA(tds);	if (idlen < 0)		idlen = strlen(id);	/* need quote ?? */	for (i = 0; i < idlen; ++i) {		char c = id[i];		if (c >= 'a' && c <= 'z')			continue;		if (c >= 'A' && c <= 'Z')			continue;		if (i > 0 && c >= '0' && c <= '9')			continue;		if (c == '_')			continue;		return tds_quote(tds, buffer, TDS_IS_MSSQL(tds) ? ']' : '\"', id, idlen);	}	if (buffer) {		memcpy(buffer, id, idlen);		buffer[idlen] = '\0';	}	return idlen;}/** * Quote a string * \param tds    state information for the socket and the TDS protocol * \param buffer buffer to store quoted id. If NULL do not write anything  *        (useful to compute quote length) * \param str    string to quote (not necessary null-terminated) * \param len    length of string (-1 for null terminated) * \result written chars (not including needed terminator) */inttds_quote_string(TDSSOCKET * tds, char *buffer, const char *str, int len){	return tds_quote(tds, buffer, '\'', str, len < 0 ? strlen(str) : len);}static inline void

⌨️ 快捷键说明

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