📄 convert.c
字号:
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 + -