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

📄 query.c

📁 在Linux/Unix下面访问WINDOWS SQLSERVER 的ODBC驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
tds_skip_comment_ucs2le(const char *s, const char *end){	const char *p = s;	if (p+4 <= end && memcmp(p, "-\0-", 4) == 0) {		for (;(p+=2) < end;)			if (p[0] == '\n' && p[1] == 0)				return p + 2;	} else if (p+4 <= end && memcmp(p, "/\0*", 4) == 0) {		p += 2;		end -= 2;		for(;(p+=2) < end;)			if (memcmp(p, "*\0/", 4) == 0)				return p + 4;	} else		p += 2;	return p;}static const char *tds_skip_quoted_ucs2le(const char *s, const char *end){	const char *p = s;	char quote = (*s == '[') ? ']' : *s;	assert(s[1] == 0 && s < end && (end - s) % 2 == 0);	for (; (p += 2) != end;) {		if (p[0] == quote && !p[1]) {			p += 2;			if (p == end || p[0] != quote || p[1])				return p;		}	}	return p;}static const char *tds_next_placeholder_ucs2le(const char *start, const char *end, int named){	const char *p = start;	char prev = ' ', c;	assert(p && start <= end && (end - start) % 2 == 0);	for (; p != end;) {		if (p[1]) {			prev = ' ';			p += 2;			continue;		}		c = p[0];		switch (c) {		case '\'':		case '\"':		case '[':			p = tds_skip_quoted_ucs2le(p, end);			break;		case '-':		case '/':			p = tds_skip_comment_ucs2le(p, end);			c = ' ';			break;		case '?':			return p;		case '@':			if (named && !isalnum((unsigned char) prev))				return p;		default:			p += 2;			break;		}		prev = c;	}	return end;}static inttds_count_placeholders_ucs2le(const char *query, const char *query_end){	const char *p = query - 2;	int count = 0;	for (;; ++count) {		if ((p = tds_next_placeholder_ucs2le(p + 2, query_end, 0)) == query_end)			return count;	}}/** * Return declaration for column (like "varchar(20)") * \param tds    state information for the socket and the TDS protocol * \param curcol column * \param out    buffer to hold declaration * \return TDS_FAIL or TDS_SUCCEED */static inttds_get_column_declaration(TDSSOCKET * tds, TDSCOLUMN * curcol, char *out){	const char *fmt = NULL;	int max_len = IS_TDS7_PLUS(tds) ? 8000 : 255;	CHECK_TDS_EXTRA(tds);	CHECK_COLUMN_EXTRA(curcol);	switch (tds_get_conversion_type(curcol->on_server.column_type, curcol->on_server.column_size)) {	case XSYBCHAR:	case SYBCHAR:		fmt = "CHAR(%d)";		break;	case SYBVARCHAR:	case XSYBVARCHAR:		fmt = "VARCHAR(%d)";		break;	case SYBINT1:		fmt = "TINYINT";		break;	case SYBINT2:		fmt = "SMALLINT";		break;	case SYBINT4:		fmt = "INT";		break;	case SYBINT8:		/* TODO even for Sybase ?? */		fmt = "BIGINT";		break;	case SYBFLT8:		fmt = "FLOAT";		break;	case SYBDATETIME:		fmt = "DATETIME";		break;	case SYBBIT:		fmt = "BIT";		break;	case SYBTEXT:		fmt = "TEXT";		break;	case SYBLONGBINARY:	/* TODO correct ?? */	case SYBIMAGE:		fmt = "IMAGE";		break;	case SYBMONEY4:		fmt = "SMALLMONEY";		break;	case SYBMONEY:		fmt = "MONEY";		break;	case SYBDATETIME4:		fmt = "SMALLDATETIME";		break;	case SYBREAL:		fmt = "REAL";		break;	case SYBBINARY:	case XSYBBINARY:		fmt = "BINARY(%d)";		break;	case SYBVARBINARY:	case XSYBVARBINARY:		fmt = "VARBINARY(%d)";		break;	case SYBNUMERIC:		fmt = "NUMERIC(%d,%d)";		goto numeric_decimal;	case SYBDECIMAL:		fmt = "DECIMAL(%d,%d)";	      numeric_decimal:		sprintf(out, fmt, curcol->column_prec, curcol->column_scale);		return TDS_SUCCEED;		break;	case SYBUNIQUE:		if (IS_TDS7_PLUS(tds))			fmt = "UNIQUEIDENTIFIER";		break;	case SYBNTEXT:		if (IS_TDS7_PLUS(tds))			fmt = "NTEXT";		break;	case SYBNVARCHAR:	case XSYBNVARCHAR:		if (IS_TDS7_PLUS(tds)) {			fmt = "NVARCHAR(%d)";			max_len = 4000;		}		break;	case XSYBNCHAR:		if (IS_TDS7_PLUS(tds)) {			fmt = "NCHAR(%d)";			max_len = 4000;		}		break;		/* nullable types should not occur here... */	case SYBFLTN:	case SYBMONEYN:	case SYBDATETIMN:	case SYBBITN:	case SYBINTN:		assert(0);		/* TODO... */	case SYBVOID:	case SYBSINT1:	case SYBUINT2:	case SYBUINT4:	case SYBUINT8:	case SYBVARIANT:		break;	}	if (fmt) {		TDS_INT size = curcol->on_server.column_size;		if (!size)			size = curcol->column_size;		/* fill out */		sprintf(out, fmt, size > 0 ? (size > max_len ? max_len : size) : 1);		return TDS_SUCCEED;	}	out[0] = 0;	return TDS_FAIL;}/** * Return string with parameters definition, useful for TDS7+ * \param tds     state information for the socket and the TDS protocol * \param params  parameters to build declaration * \param out_len length output buffer in bytes * \return allocated and filled string or NULL on failure (coded in ucs2le charset ) *//* TODO find a better name for this function */static char *tds7_build_param_def_from_query(TDSSOCKET * tds, const char* converted_query, int converted_query_len, TDSPARAMINFO * params, size_t *out_len){	size_t size = 512;	char *param_str;	char *p;	char declaration[40];	size_t l = 0;	int i, count;	assert(IS_TDS7_PLUS(tds));	assert(out_len);	CHECK_TDS_EXTRA(tds);	if (params)		CHECK_PARAMINFO_EXTRA(params);	count = tds_count_placeholders_ucs2le(converted_query, converted_query + converted_query_len);		param_str = (char *) malloc(512);	if (!param_str)		return NULL;	for (i = 0; i < count; ++i) {		if (l > 0u) {			param_str[l++] = ',';			param_str[l++] = 0;		}		/* realloc on insufficient space */		while ((l + (2u * 40u)) > size) {			p = (char *) realloc(param_str, size += 512u);			if (!p)				goto Cleanup;			param_str = p;		}		/* get this parameter declaration */		sprintf(declaration, "@P%d ", i+1);		if (params && i < params->num_cols) {			if (tds_get_column_declaration(tds, params->columns[i], declaration + strlen(declaration)) == TDS_FAIL)				goto Cleanup;		} else {			strcat(declaration, "varchar(80)");		}		/* convert it to ucs2 and append */		l += tds_ascii_to_ucs2(param_str + l, declaration);	}	*out_len = l;	return param_str;      Cleanup:	free(param_str);	return NULL;}/** * Return string with parameters definition, useful for TDS7+ * \param tds     state information for the socket and the TDS protocol * \param params  parameters to build declaration * \param out_len length output buffer in bytes * \return allocated and filled string or NULL on failure (coded in ucs2le charset ) *//* TODO find a better name for this function */static char *tds7_build_param_def_from_params(TDSSOCKET * tds, const char* query, size_t query_len,  TDSPARAMINFO * params, size_t *out_len){	size_t size = 512;	char *param_str;	char *p;	char declaration[40];	size_t l = 0;	int i;	struct tds_ids {		const char *p;		size_t len;	} *ids = NULL; 	assert(IS_TDS7_PLUS(tds));	assert(out_len); 	CHECK_TDS_EXTRA(tds);	if (params)		CHECK_PARAMINFO_EXTRA(params); 	param_str = (char *) malloc(512);	if (!param_str)		return NULL;	/* try to detect missing names */	if (params->num_cols) {		ids = (struct tds_ids *) calloc(params->num_cols, sizeof(struct tds_ids));		if (!ids)			goto Cleanup;		if (!params->columns[0]->column_name[0]) {			const char *s = query, *e, *id_end;			const char *query_end = query + query_len;			for (i = 0;  i < params->num_cols; s = e + 2) {				e = tds_next_placeholder_ucs2le(s, query_end, 1);				if (e == query_end)					break;				if (e[0] != '@')					continue;				/* find end of param name */				for (id_end = e + 2; id_end != query_end; id_end += 2)					if (!id_end[1] && (id_end[0] != '_' && id_end[1] != '#' && !isalnum((unsigned char) id_end[0])))						break;				ids[i].p = e;				ids[i].len = id_end - e;				++i;			}		}	} 	for (i = 0; i < params->num_cols; ++i) {		const char *ib;		char *ob;		size_t il, ol; 		if (l > 0u) {			param_str[l++] = ',';			param_str[l++] = 0;		} 		/* realloc on insufficient space */		il = ids[i].p ? ids[i].len : 2 * params->columns[i]->column_namelen;		while ((l + (2u * 26u) + il) > size) {			p = (char *) realloc(param_str, size += 512);			if (!p)				goto Cleanup;			param_str = p;		} 		/* this part of buffer can be not-ascii compatible, use all ucs2... */		if (ids[i].len) {			memcpy(param_str + l, ids[i].p, ids[i].len);			l += ids[i].len;		} else {			ib = params->columns[i]->column_name;			il = params->columns[i]->column_namelen;			ob = param_str + l;			ol = size - l;			memset(&tds->char_convs[iso2server_metadata]->suppress, 0, sizeof(tds->char_convs[iso2server_metadata]->suppress));			if (tds_iconv(tds, tds->char_convs[iso2server_metadata], to_server, &ib, &il, &ob, &ol) == (size_t) - 1)				goto Cleanup;			l = size - ol;		}		param_str[l++] = ' ';		param_str[l++] = 0; 		/* get this parameter declaration */		tds_get_column_declaration(tds, params->columns[i], declaration);		if (!declaration[0])			goto Cleanup; 		/* convert it to ucs2 and append */		l += tds_ascii_to_ucs2(param_str + l, declaration); 	}	free(ids);	*out_len = l;	return param_str;       Cleanup:	free(ids);	free(param_str);	return NULL;}/** * Output params types and query (required by sp_prepare/sp_executesql/sp_prepexec) * \param tds       state information for the socket and the TDS protocol * \param query     query (in ucs2le codings) * \param query_len query length in bytes */static voidtds7_put_query_params(TDSSOCKET * tds, const char *query, int query_len){	int len, i, num_placeholders;	const char *s, *e;	char buf[24];	const char *const query_end = query + query_len;	CHECK_TDS_EXTRA(tds);	assert(IS_TDS7_PLUS(tds));	/* we use all "@PX" for parameters */	num_placeholders = tds_count_placeholders_ucs2le(query, query_end);	len = num_placeholders * 2;	/* adjust for the length of X */	for (i = 10; i <= num_placeholders; i *= 10) {		len += num_placeholders - i + 1;	}	/* string with sql statement */	/* replace placeholders with dummy parametes */	tds_put_byte(tds, 0);	tds_put_byte(tds, 0);	tds_put_byte(tds, SYBNTEXT);	/* must be Ntype */	len = 2 * len + query_len;	tds_put_int(tds, len);	if (IS_TDS8_PLUS(tds))		tds_put_n(tds, tds->collation, 5);	tds_put_int(tds, len);	s = query;	/* TODO do a test with "...?" and "...?)" */	for (i = 1;; ++i) {		e = tds_next_placeholder_ucs2le(s, query_end, 0);		assert(e && query <= e && e <= query_end);		tds_put_n(tds, s, e - s);		if (e == query_end)			break;		sprintf(buf, "@P%d", i);		tds_put_string(tds, buf, -1);		s = e + 2;	}}static voidtds7_put_params_definition(TDSSOCKET * tds, const char *param_definition, size_t param_length){	CHECK_TDS_EXTRA(tds);	/* string with parameters types */	tds_put_byte(tds, 0);	tds_put_byte(tds, 0);	tds_put_byte(tds, SYBNTEXT);	/* must be Ntype */	/* put parameters definitions */	tds_put_int(tds, param_length);	if (IS_TDS8_PLUS(tds))		tds_put_n(tds, tds->collation, 5);	tds_put_int(tds, param_length ? param_length : -1);	tds_put_n(tds, param_definition, param_length);}/** * tds_submit_prepare() creates a temporary stored procedure in the server. * Under TDS 4.2 dynamic statements are emulated building sql command * \param tds     state information for the socket and the TDS protocol * \param query   language query with given placeholders (?) * \param id      string to identify the dynamic query. Pass NULL for automatic generation. * \param dyn_out will receive allocated TDSDYNAMIC*. Any older allocated dynamic won't be freed, Can be NULL. * \param params  parameters to use. It can be NULL even if parameters are present. Used only for TDS7+ * \return TDS_FAIL or TDS_SUCCEED *//* TODO parse all results ?? */inttds_submit_prepare(TDSSOCKET * tds, const char *query, const char *id, TDSDYNAMIC ** dyn_out, TDSPARAMINFO * params){	int id_len, query_len;	int rc;	TDSDYNAMIC *dyn;	CHECK_TDS_EXTRA(tds);	if (params)		CHECK_PARAMINFO_EXTRA(params);	if (!query)		return TDS_FAIL;	/* allocate a structure for this thing */	if (!id) {		char *tmp_id = NULL;		if (tds_get_dynid(tds, &tmp_id) == TDS_FAIL)			return TDS_FAIL;		dyn = tds_alloc_dynamic(tds, tmp_id);		free(tmp_id);	} else {

⌨️ 快捷键说明

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