📄 odbc_util.c
字号:
case SQL_VARBINARY: case SQL_LONGVARBINARY: size = col->column_size * 2; break; case SQL_BIGINT: size = 20; break; case SQL_INTEGER: size = 11; /* -1000000000 */ break; case SQL_SMALLINT: size = 6; /* -10000 */ break; case SQL_BIT: size = 1; break; case SQL_TINYINT: size = 3; /* 255 */ break; case SQL_DECIMAL: case SQL_NUMERIC: size = col->column_prec + 2; break; case SQL_DATE: /* FIXME check always yyyy-mm-dd ?? */ size = 19; break; case SQL_TIME: /* FIXME check always hh:mm:ss[.fff] */ size = 19; break; case SQL_TYPE_TIMESTAMP: case SQL_TIMESTAMP: /* TODO dependent on precision (decimal second digits) */ /* we always format using yyyy-mm-dd hh:mm:ss[.fff], see convert_tds2sql.c */ size = 19; if (col->column_type == SYBDATETIME || (col->column_type == SYBDATETIMN && col->column_size == 8)) size = 23; break; case SQL_FLOAT: case SQL_REAL: case SQL_DOUBLE: /* TODO check REAL/FLOAT format */ if (col->column_type == SYBREAL || (col->column_type == SYBFLTN && col->column_size == 4)) size = 14; /* TODO check money format returned by propretary ODBC, scale == 4 but we use 2 digits */ else if (col->column_type == SYBMONEY || (col->column_type == SYBMONEYN && col->column_size == 8)) size = 21; else if (col->column_type == SYBMONEY4 || (col->column_type == SYBMONEYN && col->column_size == 4)) size = 12; else size = 24; /* FIXME -- what should the correct size be? */ break;#ifdef SQL_GUID case SQL_GUID: size = 36; break;#endif default: /* FIXME TODO finish, should support ALL types (interval, binary) */ size = 40; tdsdump_log(TDS_DBG_INFO1, "odbc_sql_to_displaysize: unknown sql type %d\n", (int) sqltype); break; } return size;}intodbc_sql_to_c_type_default(int sql_type){ switch (sql_type) { case SQL_CHAR: case SQL_VARCHAR: case SQL_LONGVARCHAR: return SQL_C_CHAR; /* for compatibility numeric are converted to CHAR, not to structure */ case SQL_DECIMAL: case SQL_NUMERIC: return SQL_C_CHAR;#ifdef SQL_GUID case SQL_GUID: /* TODO return SQL_C_CHAR for Sybase ?? */ return SQL_C_GUID;#endif case SQL_BIT: return SQL_C_BIT; case SQL_TINYINT: return SQL_C_UTINYINT; case SQL_SMALLINT: return SQL_C_SSHORT; case SQL_INTEGER: return SQL_C_SLONG; case SQL_BIGINT: return SQL_C_SBIGINT; case SQL_REAL: return SQL_C_FLOAT; case SQL_FLOAT: case SQL_DOUBLE: return SQL_C_DOUBLE; case SQL_DATE: case SQL_TYPE_DATE: return SQL_C_TYPE_DATE; case SQL_TIME: case SQL_TYPE_TIME: return SQL_C_TYPE_TIME; case SQL_TIMESTAMP: case SQL_TYPE_TIMESTAMP: return SQL_C_TYPE_TIMESTAMP; case SQL_BINARY: case SQL_VARBINARY: case SQL_LONGVARBINARY: return SQL_C_BINARY; /* TODO interval types */ default: return 0; }}intodbc_sql_to_server_type(TDSSOCKET * tds, int sql_type){ switch (sql_type) { case SQL_CHAR: return SYBCHAR; case SQL_VARCHAR: return SYBVARCHAR; case SQL_LONGVARCHAR: return SYBTEXT; case SQL_DECIMAL: return SYBDECIMAL; case SQL_NUMERIC: return SYBNUMERIC;#ifdef SQL_GUID case SQL_GUID: if (IS_TDS7_PLUS(tds)) return SYBUNIQUE; return 0;#endif case SQL_BIT: if (IS_TDS7_PLUS(tds)) return SYBBITN; return SYBBIT; case SQL_TINYINT: return SYBINT1; case SQL_SMALLINT: return SYBINT2; case SQL_INTEGER: return SYBINT4; case SQL_BIGINT: return SYBINT8; case SQL_REAL: return SYBREAL; case SQL_FLOAT: case SQL_DOUBLE: return SYBFLT8; /* ODBC version 2 */ case SQL_DATE: case SQL_TIME: case SQL_TIMESTAMP: /* ODBC version 3 */ case SQL_TYPE_DATE: case SQL_TYPE_TIME: case SQL_TYPE_TIMESTAMP: return SYBDATETIME; case SQL_BINARY: return SYBBINARY; case SQL_VARBINARY: return SYBVARBINARY; case SQL_LONGVARBINARY: return SYBIMAGE; /* TODO interval types */ default: return 0; }}/** * Copy a string to client setting size according to ODBC convenction * @param buffer client buffer * @param cbBuffer client buffer size (in bytes) * @param pcbBuffer pointer to SQLSMALLINT to hold string size * @param s string to copy * @param len len of string to copy. <0 null terminated */SQLRETURNodbc_set_string(SQLPOINTER buffer, SQLSMALLINT cbBuffer, SQLSMALLINT FAR * pcbBuffer, const char *s, int len){ SQLRETURN result = SQL_SUCCESS; if (len < 0) len = strlen(s); if (pcbBuffer) *pcbBuffer = len; if (len >= cbBuffer) { len = cbBuffer - 1; result = SQL_SUCCESS_WITH_INFO; } if (buffer && len >= 0) { /* buffer can overlap, use memmove, thanks to Valgrind */ memmove((char *) buffer, s, len); ((char *) buffer)[len] = 0; } return result;}SQLRETURNodbc_set_string_i(SQLPOINTER buffer, SQLINTEGER cbBuffer, SQLINTEGER FAR * pcbBuffer, const char *s, int len){ SQLRETURN result = SQL_SUCCESS; if (len < 0) len = strlen(s); if (pcbBuffer) *pcbBuffer = len; if (len >= cbBuffer) { len = cbBuffer - 1; result = SQL_SUCCESS_WITH_INFO; } if (buffer && len >= 0) { /* buffer can overlap, use memmove, thanks to Valgrind */ memmove((char *) buffer, s, len); ((char *) buffer)[len] = 0; } return result;}/** Returns the version of the RDBMS in the ODBC format */voidodbc_rdbms_version(TDSSOCKET * tds, char *pversion_string){ sprintf(pversion_string, "%.02d.%.02d.%.04d", (int) ((tds->product_version & 0x7F000000) >> 24), (int) ((tds->product_version & 0x00FF0000) >> 16), (int) (tds->product_version & 0x0000FFFF));}/** Return length of parameter from parameter information */SQLINTEGERodbc_get_param_len(const struct _drecord *drec_axd, const struct _drecord *drec_ixd, const TDS_DESC* axd, unsigned int n_row){ SQLINTEGER len; int size; TDS_INTPTR len_offset; if (axd->header.sql_desc_bind_type != SQL_BIND_BY_COLUMN) { len_offset = axd->header.sql_desc_bind_type * n_row; if (axd->header.sql_desc_bind_offset_ptr) len_offset += *axd->header.sql_desc_bind_offset_ptr; } else { len_offset = sizeof(SQLLEN) * n_row; }#define LEN(ptr) *((SQLLEN*)(((char*)(ptr)) + len_offset)) if (drec_axd->sql_desc_indicator_ptr && LEN(drec_axd->sql_desc_indicator_ptr) == SQL_NULL_DATA) len = SQL_NULL_DATA; else if (drec_axd->sql_desc_octet_length_ptr) len = LEN(drec_axd->sql_desc_octet_length_ptr); else { len = 0; /* TODO add XML if defined */ /* FIXME, other types available */ if (drec_axd->sql_desc_concise_type == SQL_C_CHAR || drec_axd->sql_desc_concise_type == SQL_C_BINARY) { len = SQL_NTS; } else { int type = drec_axd->sql_desc_concise_type; if (type == SQL_C_DEFAULT) type = odbc_sql_to_c_type_default(drec_ixd->sql_desc_concise_type); type = odbc_c_to_server_type(type); /* FIXME check what happen to DATE/TIME types */ size = tds_get_size_by_type(type); if (size > 0) len = size; } } return len;#undef LEN}#ifdef SQL_GUID# define TYPE_NORMAL_SQL_GUID TYPE_NORMAL(SQL_GUID)#else# define TYPE_NORMAL_SQL_GUID#endif#define SQL_TYPES \ TYPE_NORMAL(SQL_BIT) \ TYPE_NORMAL(SQL_SMALLINT) \ TYPE_NORMAL(SQL_TINYINT) \ TYPE_NORMAL(SQL_INTEGER) \ TYPE_NORMAL(SQL_BIGINT) \\ TYPE_NORMAL_SQL_GUID \\ TYPE_NORMAL(SQL_BINARY) \ TYPE_NORMAL(SQL_VARBINARY) \ TYPE_NORMAL(SQL_LONGVARBINARY) \\ TYPE_NORMAL(SQL_CHAR) \ TYPE_NORMAL(SQL_VARCHAR) \ TYPE_NORMAL(SQL_LONGVARCHAR) \\ TYPE_NORMAL(SQL_DECIMAL) \ TYPE_NORMAL(SQL_NUMERIC) \\ TYPE_NORMAL(SQL_FLOAT) \ TYPE_NORMAL(SQL_REAL) \ TYPE_NORMAL(SQL_DOUBLE)\\ TYPE_VERBOSE_START(SQL_DATETIME) \ TYPE_VERBOSE_DATE(SQL_DATETIME, SQL_CODE_TIMESTAMP, SQL_TYPE_TIMESTAMP, SQL_TIMESTAMP) \ TYPE_VERBOSE_END(SQL_DATETIME)SQLSMALLINTodbc_get_concise_sql_type(SQLSMALLINT type, SQLSMALLINT interval){#define TYPE_NORMAL(t) case t: return type;#define TYPE_VERBOSE_START(t) \ case t: switch (interval) {#define TYPE_VERBOSE_DATE(t, interval, concise, old) \ case interval: return concise;#define TYPE_VERBOSE_END(t) \ } switch (type) { SQL_TYPES; } return 0;#undef TYPE_NORMAL#undef TYPE_VERBOSE_START#undef TYPE_VERBOSE_DATE#undef TYPE_VERBOSE_END}/** * Set concise type and all cascading field. * @param concise_type concise type to set * @param drec record to set. NULL to test error without setting * @param check_only it <>0 (true) check only, do not set type */SQLRETURNodbc_set_concise_sql_type(SQLSMALLINT concise_type, struct _drecord * drec, int check_only){ SQLSMALLINT type = concise_type, interval_code = 0;#define TYPE_NORMAL(t) case t: break;#define TYPE_VERBOSE_START(t)#define TYPE_VERBOSE_DATE(t, interval, concise, old) \ case old: concise_type = concise; \ case concise: type = t; interval_code = interval; break;#define TYPE_VERBOSE_END(t) switch (type) { SQL_TYPES; default: return SQL_ERROR; } if (!check_only) { drec->sql_desc_concise_type = concise_type; drec->sql_desc_type = type; drec->sql_desc_datetime_interval_code = interval_code; switch (drec->sql_desc_type) { case SQL_NUMERIC: case SQL_DECIMAL: drec->sql_desc_precision = 38; drec->sql_desc_scale = 0; break; /* TODO finish */ } } return SQL_SUCCESS;#undef TYPE_NORMAL#undef TYPE_VERBOSE_START#undef TYPE_VERBOSE_DATE#undef TYPE_VERBOSE_END}#ifdef SQL_C_GUID# define TYPE_NORMAL_SQL_C_GUID TYPE_NORMAL(SQL_C_GUID)#else# define TYPE_NORMAL_SQL_C_GUID#endif#define C_TYPES \ TYPE_NORMAL(SQL_C_BIT) \ TYPE_NORMAL(SQL_C_SHORT) \ TYPE_NORMAL(SQL_C_TINYINT) \ TYPE_NORMAL(SQL_C_UTINYINT) \ TYPE_NORMAL(SQL_C_STINYINT) \ TYPE_NORMAL(SQL_C_LONG) \ TYPE_NORMAL(SQL_C_SBIGINT) \ TYPE_NORMAL(SQL_C_UBIGINT) \ TYPE_NORMAL(SQL_C_SSHORT) \ TYPE_NORMAL(SQL_C_SLONG) \ TYPE_NORMAL(SQL_C_USHORT) \ TYPE_NORMAL(SQL_C_ULONG) \\ TYPE_NORMAL_SQL_C_GUID \ TYPE_NORMAL(SQL_C_DEFAULT) \\ TYPE_NORMAL(SQL_C_BINARY) \\ TYPE_NORMAL(SQL_C_CHAR) \\ TYPE_NORMAL(SQL_C_NUMERIC) \\ TYPE_NORMAL(SQL_C_FLOAT) \ TYPE_NORMAL(SQL_C_DOUBLE)\\ TYPE_VERBOSE_START(SQL_DATETIME) \ TYPE_VERBOSE_DATE(SQL_DATETIME, SQL_CODE_DATE, SQL_C_TYPE_DATE, SQL_C_DATE) \ TYPE_VERBOSE_DATE(SQL_DATETIME, SQL_CODE_TIME, SQL_C_TYPE_TIME, SQL_C_TIME) \ TYPE_VERBOSE_DATE(SQL_DATETIME, SQL_CODE_TIMESTAMP, SQL_C_TYPE_TIMESTAMP, SQL_C_TIMESTAMP) \ TYPE_VERBOSE_END(SQL_DATETIME) \\ TYPE_VERBOSE_START(SQL_INTERVAL) \ TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_DAY, SQL_C_INTERVAL_DAY) \ TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_DAY_TO_HOUR, SQL_C_INTERVAL_DAY_TO_HOUR) \ TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_DAY_TO_MINUTE, SQL_C_INTERVAL_DAY_TO_MINUTE) \ TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_DAY_TO_SECOND, SQL_C_INTERVAL_DAY_TO_SECOND) \ TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_HOUR, SQL_C_INTERVAL_HOUR) \ TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_HOUR_TO_MINUTE, SQL_C_INTERVAL_HOUR_TO_MINUTE) \ TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_HOUR_TO_SECOND, SQL_C_INTERVAL_HOUR_TO_SECOND) \ TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_MINUTE, SQL_C_INTERVAL_MINUTE) \ TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_MINUTE_TO_SECOND, SQL_C_INTERVAL_MINUTE_TO_SECOND) \ TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_MONTH, SQL_C_INTERVAL_MONTH) \ TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_SECOND, SQL_C_INTERVAL_SECOND) \ TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_YEAR, SQL_C_INTERVAL_YEAR) \ TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_YEAR_TO_MONTH, SQL_C_INTERVAL_YEAR_TO_MONTH) \ TYPE_VERBOSE_END(SQL_INTERVAL)SQLSMALLINTodbc_get_concise_c_type(SQLSMALLINT type, SQLSMALLINT interval){#define TYPE_NORMAL(t) case t: return type;#define TYPE_VERBOSE_START(t) \ case t: switch (interval) {#define TYPE_VERBOSE(t, interval, concise) \ case interval: return concise;#define TYPE_VERBOSE_DATE(t, interval, concise, old) \ case interval: return concise;#define TYPE_VERBOSE_END(t) \ } switch (type) { C_TYPES; } return 0;#undef TYPE_NORMAL#undef TYPE_VERBOSE_START#undef TYPE_VERBOSE#undef TYPE_VERBOSE_DATE#undef TYPE_VERBOSE_END}/** * Set concise type and all cascading field. * @param concise_type concise type to set * @param drec record to set. NULL to test error without setting * @param check_only it <>0 (true) check only, do not set type */SQLRETURNodbc_set_concise_c_type(SQLSMALLINT concise_type, struct _drecord * drec, int check_only){ SQLSMALLINT type = concise_type, interval_code = 0;#define TYPE_NORMAL(t) case t: break;#define TYPE_VERBOSE_START(t)#define TYPE_VERBOSE(t, interval, concise) \ case concise: type = t; interval_code = interval; break;#define TYPE_VERBOSE_DATE(t, interval, concise, old) \ case concise: type = t; interval_code = interval; break; \ case old: concise_type = concise; type = t; interval_code = interval; break;#define TYPE_VERBOSE_END(t) switch (type) { C_TYPES; default: return SQL_ERROR; } if (!check_only) { drec->sql_desc_concise_type = concise_type; drec->sql_desc_type = type; drec->sql_desc_datetime_interval_code = interval_code; switch (drec->sql_desc_type) { case SQL_C_NUMERIC: drec->sql_desc_precision = 38; drec->sql_desc_scale = 0; break; /* TODO finish */ } } return SQL_SUCCESS;#undef TYPE_NORMAL#undef TYPE_VERBOSE_START#undef TYPE_VERBOSE#undef TYPE_VERBOSE_DATE#undef TYPE_VERBOSE_END}SQLLENodbc_get_octet_len(int c_type, const struct _drecord *drec){ SQLLEN len; /* this shit is mine -- freddy77 */ switch (c_type) { case SQL_C_CHAR: case SQL_C_BINARY: len = drec->sql_desc_octet_length; break; case SQL_C_DATE: case SQL_C_TYPE_DATE: len = sizeof(DATE_STRUCT); break; case SQL_C_TIME: case SQL_C_TYPE_TIME: len = sizeof(TIME_STRUCT); break; case SQL_C_TIMESTAMP: case SQL_C_TYPE_TIMESTAMP: len = sizeof(TIMESTAMP_STRUCT); break; case SQL_C_NUMERIC: len = sizeof(SQL_NUMERIC_STRUCT); break; default: len = tds_get_size_by_type(odbc_c_to_server_type(c_type)); break; } return len;}/** @} */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -