示例#1
0
/**
 * Reads a string from wire and put in a DSTR.
 * On error we read the bytes from the wire anyway.
 * \tds
 * \param[out] s output string
 * \param[in] len string length (in characters)
 * \return string or NULL on error
 */
DSTR*
tds_dstr_get(TDSSOCKET * tds, DSTR * s, size_t len)
{
	size_t out_len;

	CHECK_TDS_EXTRA(tds);

	/* assure sufficient space for every conversion */
	if (TDS_UNLIKELY(!tds_dstr_alloc(s, len * 4))) {
		tds_get_n(tds, NULL, len);
		return NULL;
	}

	out_len = tds_get_string(tds, len, tds_dstr_buf(s), len * 4);
	tds_dstr_setlen(s, out_len);
	return s;
}
示例#2
0
文件: native.c 项目: FreeTDS/freetds
/*
 * Function transformation (from ODBC to Sybase)
 * String functions
 * ASCII(string) -> ASCII(string)
 * BIT_LENGTH(string) -> 8*OCTET_LENGTH(string)
 * CHAR_LENGTH(string_exp) -> CHAR_LENGTH(string_exp)
 * CHARACTER_LENGTH(string_exp) -> CHAR_LENGTH(string_exp)
 * CONCAT(string_exp1, string_exp2) -> string_exp1 + string_exp2
 * DIFFERENCE(string_exp1, string_exp2) -> DIFFERENCE(string_exp1, string_exp2)
 * INSERT(string_exp1, start, length, string_exp2) -> STUFF(sameparams)
 * LCASE(string_exp) -> LOWER(string)
 * LEFT(string_exp, count) -> SUBSTRING(string, 1, count)
 * LENGTH(string_exp) -> CHAR_LENGTH(RTRIM(string_exp))
 * LOCATE(string, string [,start]) -> CHARINDEX(string, string)
 * (SQLGetInfo should return third parameter not possible)
 * LTRIM(String) -> LTRIM(String)
 * OCTET_LENGTH(string_exp) -> OCTET_LENGTH(string_exp)
 * POSITION(character_exp IN character_exp) ???
 * REPEAT(string_exp, count) -> REPLICATE(same)
 * REPLACE(string_exp1, string_exp2, string_exp3) -> ??
 * RIGHT(string_exp, count) -> RIGHT(string_exp, count)
 * RTRIM(string_exp) -> RTRIM(string_exp)
 * SOUNDEX(string_exp) -> SOUNDEX(string_exp)
 * SPACE(count) (ODBC 2.0) -> SPACE(count) (ODBC 2.0)
 * SUBSTRING(string_exp, start, length) -> SUBSTRING(string_exp, start, length)
 * UCASE(string_exp) -> UPPER(string)
 *
 * Numeric
 * Nearly all function use same parameters, except:
 * ATAN2 -> ATN2
 * TRUNCATE -> ??
 */
static SQLRETURN
to_native(struct _hdbc *dbc, struct _hstmt *stmt, DSTR *str)
{
	char *d, *s;
	int nest_syntax = 0;
	char *buf = tds_dstr_buf(str);

	/* list of bit, used as stack, is call ? FIXME limites size... */
	unsigned long is_calls = 0;
	int server_scalar;

	assert(dbc);

	server_scalar = TDS_IS_MSSQL(dbc->tds_socket) && dbc->tds_socket->conn->product_version >= TDS_MS_VER(7, 0, 0);

	/*
	 * we can do it because result string will be
	 * not bigger than source string
	 */
	d = s = buf;
	while (*s) {
		if (*s == '-' || *s == '/') {
			size_t len_comment = tds_skip_comment(s) - s;

			memmove(d, s, len_comment);
			s += len_comment;
			d += len_comment;
			continue;
		}

		/* TODO: test syntax like "select 1 as [pi]]p)p{?=call]]]]o], 2" on mssql7+ */
		if (*s == '"' || *s == '\'' || *s == '[') {
			size_t len_quote = tds_skip_quoted(s) - s;

			memmove(d, s, len_quote);
			s += len_quote;
			d += len_quote;
			continue;
		}

		if (*s == '{') {
			char *pcall;

			while (TDS_ISSPACE(*++s))
				continue;
			pcall = s;
			/* FIXME if nest_syntax > 0 problems */
			if (server_scalar && strncasecmp(pcall, "fn ", 3) == 0) {
				*d++ = '{';
				continue;
			}
			if (*pcall == '?') {
				/* skip spaces after ? */
				while (TDS_ISSPACE(*++pcall))
					continue;
				if (*pcall == '=') {
					while (TDS_ISSPACE(*++pcall))
						continue;
				} else {
					/* avoid {?call ... syntax */
					pcall = s;
				}
			}
			if (strncasecmp(pcall, "call ", 5) != 0)
				pcall = NULL;

			if (stmt)
				stmt->prepared_query_is_rpc = 1;
			++nest_syntax;
			is_calls <<= 1;
			if (!pcall) {
				/* assume syntax in the form {type ...} */
				while (TDS_ISALPHA(*s))
					++s;
				while (TDS_ISSPACE(*s))
					++s;
			} else {
				if (*s == '?' && stmt)
					stmt->prepared_query_is_func = 1;
				memcpy(d, "exec ", 5);
				d += 5;
				s = pcall + 5;
				is_calls |= 1;
			}
		} else if (nest_syntax > 0) {
			/* do not copy close syntax */
			if (*s == '}') {
				--nest_syntax;
				is_calls >>= 1;
				++s;
				continue;
				/* convert parenthesis in call to spaces */
			} else if ((is_calls & 1) && (*s == '(' || *s == ')')) {
				*d++ = ' ';
				s++;
			} else {
				*d++ = *s++;
			}
		} else {