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

📄 convert.c

📁 在Linux/Unix下面访问WINDOWS SQLSERVER 的ODBC驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
		break;	case SYBINT2:		dollars = mny.mny4 / 10000;		if (!IS_SMALLINT(dollars))			return TDS_CONVERT_OVERFLOW;		cr->si = (TDS_SMALLINT) dollars;		return sizeof(TDS_SMALLINT);		break;	case SYBINT4:		cr->i = mny.mny4 / 10000;		return sizeof(TDS_INT);		break;	case SYBINT8:		cr->bi = mny.mny4 / 10000;		return sizeof(TDS_INT8);		break;	case SYBBIT:	case SYBBITN:		cr->ti = mny.mny4 ? 1 : 0;		return sizeof(TDS_TINYINT);		break;	case SYBFLT8:		cr->f = ((TDS_FLOAT) mny.mny4) / 10000.0;		return sizeof(TDS_FLOAT);		break;	case SYBREAL:		cr->r = (TDS_REAL) (mny.mny4 / 10000.0);		return sizeof(TDS_REAL);		break;	case SYBMONEY:		cr->m.mny = (TDS_INT8) mny.mny4;		return sizeof(TDS_MONEY);		break;	case SYBMONEY4:		cr->m4 = mny;		return sizeof(TDS_MONEY4);		break;		/* conversions not allowed */	case SYBUNIQUE:	case SYBDATETIME4:	case SYBDATETIME:	case SYBDATETIMN:		break;	case SYBDECIMAL:	case SYBNUMERIC:		dollars = mny.mny4 / 10000;		fraction = mny.mny4 % 10000;		if (fraction < 0) {			fraction = -fraction;		}		sprintf(tmp_str, "%ld.%04lu", dollars, fraction);		return stringz_to_numeric(tmp_str, cr);	default:		return TDS_CONVERT_NOAVAIL;		break;	}	return TDS_CONVERT_FAIL;}static TDS_INTtds_convert_money(int srctype, const TDS_CHAR * src, int desttype, CONV_RESULT * cr){	char *s;	TDS_INT8 mymoney, dollars;	char tmpstr[64];	tdsdump_log(TDS_DBG_FUNC, "tds_convert_money()\n");#if defined(WORDS_BIGENDIAN) || !defined(HAVE_INT64)	memcpy(&mymoney, src, sizeof(TDS_INT8));#else	memcpy(((char *) &mymoney) + 4, src, 4);	memcpy(&mymoney, src + 4, 4);#endif	switch (desttype) {	case TDS_CONVERT_CHAR:	case CASE_ALL_CHAR:		s = tds_money_to_string((const TDS_MONEY *) src, tmpstr);		return string_to_result(s, cr);		break;	case CASE_ALL_BINARY:		return binary_to_result(src, sizeof(TDS_MONEY), cr);		break;	case SYBINT1:		if (mymoney <= -10000 || mymoney >= 256 * 10000)			return TDS_CONVERT_OVERFLOW;		/* TODO: round ?? */		cr->ti = (TDS_TINYINT) (((TDS_INT) mymoney) / 10000);		return sizeof(TDS_TINYINT);		break;	case SYBINT2:		if (mymoney <= -32769 * 10000 || mymoney >= 32768 * 10000)			return TDS_CONVERT_OVERFLOW;		cr->si = (TDS_SMALLINT) (((TDS_INT) mymoney) / 10000);		return sizeof(TDS_SMALLINT);		break;	case SYBINT4:		dollars = mymoney / 10000;		if (!IS_INT(dollars))			return TDS_CONVERT_OVERFLOW;		cr->i = (TDS_INT) dollars;		return sizeof(TDS_INT);		break;	case SYBINT8:		cr->bi = mymoney / 10000;		return sizeof(TDS_INT8);		break;	case SYBBIT:	case SYBBITN:		cr->ti = mymoney ? 1 : 0;		return sizeof(TDS_TINYINT);		break;	case SYBFLT8:		cr->f = ((TDS_FLOAT) mymoney) / 10000.0;		return sizeof(TDS_FLOAT);		break;	case SYBREAL:		cr->r = (TDS_REAL) (mymoney / 10000.0);		return sizeof(TDS_REAL);		break;	case SYBMONEY4:		if (!IS_INT(mymoney))			return TDS_CONVERT_OVERFLOW;		cr->m4.mny4 = (TDS_INT) mymoney;		return sizeof(TDS_MONEY4);		break;	case SYBMONEY:		cr->m.mny = mymoney;		return sizeof(TDS_MONEY);		break;	case SYBDECIMAL:	case SYBNUMERIC:		s = tds_money_to_string((const TDS_MONEY *) src, tmpstr);		return stringz_to_numeric(tmpstr, cr);		break;		/* conversions not allowed */	case SYBUNIQUE:	case SYBDATETIME4:	case SYBDATETIME:	case SYBDATETIMN:	default:		break;	}	return TDS_CONVERT_NOAVAIL;}static TDS_INTtds_convert_datetime(const TDSCONTEXT * tds_ctx, int srctype, const TDS_CHAR * src, int desttype, CONV_RESULT * cr){	TDS_INT dt_days, dt_time;	char whole_date_string[30];	TDSDATEREC when;	switch (desttype) {	case TDS_CONVERT_CHAR:	case CASE_ALL_CHAR:		memset(&when, 0, sizeof(when));		tds_datecrack(SYBDATETIME, src, &when);		tds_strftime(whole_date_string, sizeof(whole_date_string), tds_ctx->locale->date_fmt, &when);		return string_to_result(whole_date_string, cr);		break;	case CASE_ALL_BINARY:		return binary_to_result(src, sizeof(TDS_DATETIME), cr);		break;	case SYBDATETIME:		memcpy(&cr->dt, src, sizeof(TDS_DATETIME));		return sizeof(TDS_DATETIME);		break;	case SYBDATETIME4:		memcpy(&dt_days, src, 4);		memcpy(&dt_time, src + 4, 4);		cr->dt4.days = dt_days;		cr->dt4.minutes = (dt_time / 300) / 60;		return sizeof(TDS_DATETIME4);		break;		/* conversions not allowed */	case SYBUNIQUE:	case SYBBIT:	case SYBBITN:	case SYBINT1:	case SYBINT2:	case SYBINT4:	case SYBINT8:	case SYBMONEY4:	case SYBMONEY:	case SYBNUMERIC:	case SYBDECIMAL:	default:		break;	}	return TDS_CONVERT_NOAVAIL;}/*static int days_this_year (int years){int year;   year = 1900 + years;   if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)      return 366;   else      return 365;}*/static TDS_INTtds_convert_datetime4(const TDSCONTEXT * tds_ctx, int srctype, const TDS_CHAR * src, int desttype, CONV_RESULT * cr){	TDS_USMALLINT dt_days, dt_mins;	char whole_date_string[30];	TDSDATEREC when;	switch (desttype) {	case TDS_CONVERT_CHAR:	case CASE_ALL_CHAR:		memset(&when, 0, sizeof(when));		tds_datecrack(SYBDATETIME4, src, &when);		tds_strftime(whole_date_string, sizeof(whole_date_string), tds_ctx->locale->date_fmt, &when);		return string_to_result(whole_date_string, cr);		break;	case CASE_ALL_BINARY:		return binary_to_result(src, sizeof(TDS_DATETIME4), cr);		break;	case SYBDATETIME:		memcpy(&dt_days, src, 2);		memcpy(&dt_mins, src + 2, 2);		cr->dt.dtdays = dt_days;		cr->dt.dttime = (dt_mins * 60) * 300;		return sizeof(TDS_DATETIME);		break;	case SYBDATETIME4:		memcpy(&cr->dt4, src, sizeof(TDS_DATETIME4));		return sizeof(TDS_DATETIME4);		break;		/* conversions not allowed */	case SYBUNIQUE:	case SYBBIT:	case SYBBITN:	case SYBINT1:	case SYBINT2:	case SYBINT4:	case SYBINT8:	case SYBMONEY4:	case SYBMONEY:	case SYBNUMERIC:	case SYBDECIMAL:	default:		break;	}	return TDS_CONVERT_NOAVAIL;}static TDS_INTtds_convert_real(int srctype, const TDS_CHAR * src, int desttype, CONV_RESULT * cr){	TDS_REAL the_value;/* FIXME how many big should be this buffer ?? */	char tmp_str[128];	TDS_INT mymoney4;	TDS_INT8 mymoney;	memcpy(&the_value, src, 4);	switch (desttype) {	case TDS_CONVERT_CHAR:	case CASE_ALL_CHAR:		sprintf(tmp_str, "%.7g", the_value);		return string_to_result(tmp_str, cr);		break;	case CASE_ALL_BINARY:		return binary_to_result(src, sizeof(TDS_REAL), cr);		break;	case SYBINT1:		if (!IS_TINYINT(the_value))			return TDS_CONVERT_OVERFLOW;		cr->ti = (TDS_TINYINT) the_value;		return sizeof(TDS_TINYINT);		break;	case SYBINT2:		if (!IS_SMALLINT(the_value))			return TDS_CONVERT_OVERFLOW;		cr->si = (TDS_SMALLINT) the_value;		return sizeof(TDS_SMALLINT);		break;	case SYBINT4:		if (!IS_INT(the_value))			return TDS_CONVERT_OVERFLOW;		cr->i = (TDS_INT) the_value;		return sizeof(TDS_INT);		break;	case SYBINT8:		if (the_value > (TDS_REAL) TDS_INT8_MAX || the_value < (TDS_REAL) TDS_INT8_MIN)			return TDS_CONVERT_OVERFLOW;		cr->bi = (TDS_INT8) the_value;		return sizeof(TDS_INT8);		break;	case SYBBIT:	case SYBBITN:		cr->ti = the_value ? 1 : 0;		return sizeof(TDS_TINYINT);		break;	case SYBFLT8:		cr->f = the_value;		return sizeof(TDS_FLOAT);		break;	case SYBREAL:		cr->r = the_value;		return sizeof(TDS_REAL);		break;	case SYBMONEY:		if (the_value > (TDS_REAL) (TDS_INT8_MAX / 10000) || the_value < (TDS_REAL) (TDS_INT8_MIN / 10000))			return TDS_CONVERT_OVERFLOW;		mymoney = ((TDS_INT8) the_value) * 10000;		cr->m.mny = mymoney;		return sizeof(TDS_MONEY);		break;	case SYBMONEY4:		if (the_value > (TDS_REAL) (TDS_INT_MAX / 10000) || the_value < (TDS_REAL) (TDS_INT_MIN / 10000))			return TDS_CONVERT_OVERFLOW;		mymoney4 = ((TDS_INT) the_value) * 10000;		cr->m4.mny4 = mymoney4;		return sizeof(TDS_MONEY4);		break;	case SYBNUMERIC:	case SYBDECIMAL:		sprintf(tmp_str, "%.*f", cr->n.scale, the_value);		return stringz_to_numeric(tmp_str, cr);		break;		/* not allowed */	case SYBUNIQUE:	case SYBDATETIME4:	case SYBDATETIME:	case SYBDATETIMN:	default:		break;	}	return TDS_CONVERT_NOAVAIL;}/* * TODO: emit SYBECLPR errors: "Data conversion resulted in loss of precision".   * There are many places where this would be correct to do, but the test is tedious  * (convert e.g. 1.5 -> SYBINT and test if output == input) and we don't have a good,  * API-independent alternative to tds_client_msg().  Postponed until then.   */static TDS_INTtds_convert_flt8(int srctype, const TDS_CHAR * src, int desttype, CONV_RESULT * cr){	TDS_FLOAT the_value;	char tmp_str[25];	memcpy(&the_value, src, 8);	switch (desttype) {	case TDS_CONVERT_CHAR:	case CASE_ALL_CHAR:		sprintf(tmp_str, "%.16g", the_value);		return string_to_result(tmp_str, cr);		break;	case CASE_ALL_BINARY:		return binary_to_result(src, sizeof(TDS_FLOAT), cr);		break;	case SYBINT1:		if (!IS_TINYINT(the_value))			return TDS_CONVERT_OVERFLOW;		cr->ti = (TDS_TINYINT) the_value;		return sizeof(TDS_TINYINT);		break;	case SYBINT2:		if (!IS_SMALLINT(the_value))			return TDS_CONVERT_OVERFLOW;		cr->si = (TDS_SMALLINT) the_value;		return sizeof(TDS_SMALLINT);		break;	case SYBINT4:		if (!IS_INT(the_value))			return TDS_CONVERT_OVERFLOW;		cr->i = (TDS_INT) the_value;		return sizeof(TDS_INT);		break;	case SYBINT8:		if (the_value > (TDS_FLOAT) TDS_INT8_MAX || the_value < (TDS_FLOAT) TDS_INT8_MIN)			return TDS_CONVERT_OVERFLOW;		cr->bi = (TDS_INT8) the_value;		return sizeof(TDS_INT8);		break;	case SYBBIT:	case SYBBITN:		cr->ti = the_value ? 1 : 0;		return sizeof(TDS_TINYINT);		break;	case SYBMONEY:		if (the_value > (TDS_FLOAT) (TDS_INT8_MAX / 10000) || the_value < (TDS_FLOAT) (TDS_INT8_MIN / 10000))			return TDS_CONVERT_OVERFLOW;		cr->m.mny = ((TDS_INT8) the_value) * 10000;		return sizeof(TDS_MONEY);		break;	case SYBMONEY4:		if (the_value > (TDS_FLOAT) (TDS_INT_MAX / 10000) || the_value < (TDS_FLOAT) (TDS_INT_MIN / 10000))			return TDS_CONVERT_OVERFLOW;		cr->m4.mny4 = ((TDS_INT) the_value) * 10000;		return sizeof(TDS_MONEY4);		break;	case SYBREAL:		/* TODO check overflow */		cr->r = the_value;		return sizeof(TDS_REAL);		break;	case SYBFLT8:		cr->f = the_value;		return sizeof(TDS_FLOAT);		break;	case SYBNUMERIC:	case SYBDECIMAL:		sprintf(tmp_str, "%.16g", the_value);		return stringz_to_numeric(tmp_str, cr);		break;		/* not allowed */	case SYBUNIQUE:	case SYBDATETIME4:	case SYBDATETIME:	case SYBDATETIMN:	default:		break;	}	return TDS_CONVERT_NOAVAIL;}static TDS_INTtds_convert_unique(int srctype, const TDS_CHAR * src, TDS_INT srclen, int desttype, CONV_RESULT * cr){	/*	 * raw data is equivalent to structure and always aligned, 	 * so this cast is portable	 */	const TDS_UNIQUE *u = (const TDS_UNIQUE *) src;	char buf[37];	switch (desttype) {	case TDS_CONVERT_CHAR:	case CASE_ALL_CHAR:		sprintf(buf, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",			(int) u->Data1, (int) u->Data2, (int) u->Data3,			u->Data4[0], u->Data4[1], u->Data4[2], u->Data4[3], u->Data4[4], u->Data4[5], u->Data4[6], u->Data4[7]);		return string_to_result(buf, cr);		break;	case CASE_ALL_BINARY:		return binary_to_result(src, sizeof(TDS_UNIQUE), cr);		break;	case SYBUNIQUE:		/*		 * Here we can copy raw to structure because we adjust		 * byte order in tds_swap_datatype		 */		memcpy(&(cr->u), src, sizeof(TDS_UNIQUE));		return sizeof(TDS_UNIQUE);		break;		/* no not warning for not convertible types */	case SYBBIT:	case SYBBITN:	case SYBINT1:	case SYBINT2:	case SYBINT4:	case SYBINT8:	case SYBMONEY4:	case SYBMONEY:	case SYBDATETIME4:	case SYBDATETIME:	case SYBDATETIMN:	case SYBREAL:	case SYBFLT8:	default:		break;	}	return TDS_CONVERT_NOAVAIL;}/** * tds_convert * convert a type to another. * If you convert to SYBDECIMAL/SYBNUMERIC you MUST initialize precision  * and scale of cr. * Do not expect strings to be zero terminated. Databases support zero inside * string. Using strlen may result on data loss or even a segmentation fault. * Instead, use memcpy to copy destination using length returned. * This function does not handle NULL, srclen should be >0.  Client libraries handle NULLs each in their own way.  * @param tds_ctx  context (used in conversion to data and to return messages) * @param srctype  type of source * @param src      pointer to source data to convert * @param srclen   length in bytes of source (not counting terminator or strings) * @param desttype type of destination * @param cr       structure to hold result * @return length of result or TDS_CONVERT_* failure code on failure. All TDS_CONVERT_* constants are <0. */TDS_INTtds_convert(const TDSCONTEXT * tds_ctx, int srctype, const TDS_CHAR * src, TDS_UINT srclen, int desttype, CONV_RESULT * cr){	TDS_INT length = 0;	assert(srclen >= 0 && srclen <= 2147483647u);	switch (srctype) {	case CASE_ALL_CHAR:		length = tds_convert_char(srctype, src, srclen, desttype, cr);		break;	case SYBMONEY4:		length = tds_convert_money4(srctype, src, srclen, desttype, cr);		break;	case SYBMONEY:		length = tds_convert_money(srctype, src, desttype, cr);		break;	case SYBNUMERIC:	case SYBDECIMAL:		length = tds_convert_numeric(srctype, (const TDS_NUMERIC *) src, srclen, desttype, cr);		break;	case SYBBIT:	case SYBBITN:		length = tds_convert_bit(srctype, src, desttype, cr);		break;	case SYBINT1:		length = tds_convert_int1(srctype, src, desttype, cr);		break;	case SYBINT2:		length = tds_convert_int2(srctype, src, desttype, cr);		break;	case SYBINT4:		length = tds_convert_int4(srctype, src, desttype, cr);		break;	case SYBINT8:		length = tds_convert_int8(srctype, src, desttype, cr);		break;	case SYBREAL:		length = tds_convert_real(srctype, src, desttype, cr);		break;	case SYBFLT8:		length = tds_convert_flt8(srctype, src, desttype, cr);		break;	case SYBDATETIME:		length = tds_convert_datetime(tds_ctx, srctype, src, desttype, cr);		break;	case SYBDATETIME4:		length = tds_convert_datetime4(tds_ctx, srctype, src, desttype, cr);		break;	case SYBLONGBINARY:	case CASE_ALL_BINARY:		length = tds_convert_binary(srctype, (const TDS_UCHAR *) src, srclen, desttype, cr);		break;	case SYBUNIQUE:		length = tds_convert_unique(srctype, src, srclen, desttype, cr);		break;	case SYBNVARCHAR:	case SYBNTEXT:	default:		return TDS_CONVERT_NOAVAIL;		break;	}

⌨️ 快捷键说明

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