diff --git a/driver/connect.c b/driver/connect.c index 524be7c8..9cf8a411 100644 --- a/driver/connect.c +++ b/driver/connect.c @@ -2290,12 +2290,11 @@ static void set_display_size(esodbc_estype_st *es_type) { switch (es_type->data_type) { case SQL_CHAR: - case SQL_VARCHAR: /* KEYWORD, TEXT */ + case SQL_VARCHAR: case SQL_LONGVARCHAR: case SQL_WCHAR: case SQL_WVARCHAR: case SQL_WLONGVARCHAR: - // TODO: 45 if IP? es_type->display_size = es_type->column_size; break; @@ -2465,7 +2464,7 @@ static void *copy_types_rows(esodbc_dbc_st *dbc, estype_row_st *type_row, SQLWCHAR *pos; int c; SQLULEN i; - SQLSMALLINT sql_type, sec_prec; + SQLSMALLINT sec_prec; /* pointer to start position where the strings will be copied in */ pos = (SQLWCHAR *)&types[rows_fetched]; @@ -2548,35 +2547,16 @@ static void *copy_types_rows(esodbc_dbc_st *dbc, estype_row_st *type_row, /* resolve ES type to SQL and SQL C type */ if (! elastic_name2types(&types[i].type_name, &types[i].c_concise_type, - &sql_type)) { + &types[i].data_type)) { /* ES version newer than driver's? */ ERRH(dbc, "failed to convert type name `" LWPDL "` to SQL C type.", LWSTR(&types[i].type_name)); return NULL; } - DBGH(dbc, "ES type `" LWPDL "` resolved to C concise: %hd, SQL: %hd.", - LWSTR(&types[i].type_name), types[i].c_concise_type, sql_type); - - /* BOOLEAN is used in catalog calls (like SYS TYPES / SQLGetTypeInfo), - * and the data type is piped through to the app (just like with any - * other statement), which causes issues, since it's not a standard - * type => change it to SQL_BIT */ - if (types[i].data_type == ESODBC_SQL_BOOLEAN) { - types[i].data_type = ES_BOOLEAN_TO_SQL; - } - /* GEO (SHAPE, POINT), SHAPE types are WKT encodings */ - if (types[i].data_type == ESODBC_SQL_GEO) { - types[i].data_type = ES_GEO_TO_SQL; - } + DBGH(dbc, "ES type `" LWPDL "` resolved to concise: C=%hd, SQL=%hd.", + LWSTR(&types[i].type_name), types[i].c_concise_type, + types[i].data_type); - /* .data_type is used in data conversions -> make sure the SQL type - * derived from type's name is the same with type reported value */ - if (sql_type != types[i].data_type) { - ERRH(dbc, "type `" LWPDL "` derived (%d) and reported (%d) SQL " - "type identifiers differ.", LWSTR(&types[i].type_name), - sql_type, types[i].data_type); - return NULL; - } /* set meta type */ types[i].meta_type = concise_to_meta(types[i].c_concise_type, /*C type -> AxD*/DESC_TYPE_ARD); @@ -2585,8 +2565,9 @@ static void *copy_types_rows(esodbc_dbc_st *dbc, estype_row_st *type_row, concise_to_type_code(types[i].data_type, &types[i].sql_data_type, &types[i].sql_datetime_sub); - /* if there's a varchar limit, apply it to string types */ - if (types[i].sql_data_type == ESODBC_SQL_STRING) { + /* if there's a set varchar limit, apply it to the string types */ + if (types[i].data_type == ES_WVARCHAR_SQL || + types[i].data_type == ES_VARCHAR_SQL) { assert(0 <= types[i].column_size); if (dbc->varchar_limit && dbc->varchar_limit < (SQLUINTEGER)types[i].column_size) { @@ -2632,18 +2613,21 @@ static void set_es_types(esodbc_dbc_st *dbc, SQLULEN rows_fetched, assert(dbc->max_varchar_type == NULL); for (i = 0; i < rows_fetched; i ++) { - if (types[i].data_type == SQL_FLOAT) { - max_float_size = dbc->max_float_type ? - dbc->max_float_type->column_size : 0; - if (max_float_size < types[i].column_size) { - dbc->max_float_type = &types[i]; - } - } else if (types[i].data_type == SQL_VARCHAR) { - max_varchar_size = dbc->max_varchar_type ? - dbc->max_varchar_type->column_size : 0; - if (max_varchar_size < types[i].column_size) { - dbc->max_varchar_type = &types[i]; - } + switch (types[i].data_type) { + case SQL_DOUBLE: + max_float_size = dbc->max_float_type ? + dbc->max_float_type->column_size : 0; + if (max_float_size < types[i].column_size) { + dbc->max_float_type = &types[i]; + } + break; + case ES_VARCHAR_SQL: + case ES_WVARCHAR_SQL: + max_varchar_size = dbc->max_varchar_type ? + dbc->max_varchar_type->column_size : 0; + if (max_varchar_size < types[i].column_size) { + dbc->max_varchar_type = &types[i]; + } } } @@ -2651,7 +2635,7 @@ static void set_es_types(esodbc_dbc_st *dbc, SQLULEN rows_fetched, assert(dbc->max_varchar_type); DBGH(dbc, "%lu ES/SQL types available, maximum sizes supported for: " - "SQL_FLOAT: %ld, SQL_VARCHAR: %ld.", (unsigned long)rows_fetched, + "floats: %ld, varchar: %ld.", (unsigned long)rows_fetched, dbc->max_float_type->column_size, dbc->max_varchar_type->column_size); } diff --git a/driver/connect.h b/driver/connect.h index 15957631..860ae37f 100644 --- a/driver/connect.h +++ b/driver/connect.h @@ -12,82 +12,6 @@ #include "dsn.h" -/* - * ES-to-C-SQL mappings. - * DATA_TYPE(SYS TYPES) : SQL_ -> SQL_C_ - * Intervals not covered, since C==SQL, with no ES customization. - */ -/* -6: SQL_TINYINT -> SQL_C_TINYINT */ -#define ES_BYTE_TO_CSQL SQL_C_TINYINT -#define ES_BYTE_TO_SQL SQL_TINYINT -/* 5: SQL_SMALLINT -> SQL_C_SHORT */ -#define ES_SHORT_TO_CSQL SQL_C_SSHORT -#define ES_SHORT_TO_SQL SQL_SMALLINT -/* 4: SQL_INTEGER -> SQL_C_LONG */ -#define ES_INTEGER_TO_CSQL SQL_C_SLONG -#define ES_INTEGER_TO_SQL SQL_INTEGER -/* -5: SQL_BIGINT -> SQL_C_SBIGINT */ -#define ES_LONG_TO_CSQL SQL_C_SBIGINT -#define ES_LONG_TO_SQL SQL_BIGINT -/* 6: SQL_FLOAT -> SQL_C_DOUBLE */ -#define ES_HALF_TO_CSQL_FLOAT SQL_C_DOUBLE -#define ES_HALF_TO_SQL_FLOAT SQL_FLOAT -/* 6: SQL_FLOAT -> SQL_C_DOUBLE */ -#define ES_SCALED_TO_CSQL_FLOAT SQL_C_DOUBLE -#define ES_SCALED_TO_SQL_FLOAT SQL_DOUBLE -/* 7: SQL_REAL -> SQL_C_DOUBLE */ -#define ES_FLOAT_TO_CSQL SQL_C_FLOAT -#define ES_FLOAT_TO_SQL SQL_REAL -/* 8: SQL_DOUBLE -> SQL_C_FLOAT */ -#define ES_DOUBLE_TO_CSQL SQL_C_DOUBLE -#define ES_DOUBLE_TO_SQL SQL_DOUBLE -/* 16: ??? -> SQL_C_TINYINT */ -#define ES_BOOLEAN_TO_CSQL SQL_C_BIT -#define ES_BOOLEAN_TO_SQL SQL_BIT -/* 12: SQL_VARCHAR -> SQL_C_WCHAR */ -#define ES_KEYWORD_TO_CSQL SQL_C_WCHAR -#define ES_KEYWORD_TO_SQL SQL_VARCHAR -/* 12: SQL_VARCHAR -> SQL_C_WCHAR */ -#define ES_CKEYWORD_TO_CSQL SQL_C_WCHAR -#define ES_CKEYWORD_TO_SQL SQL_VARCHAR -/* 12: SQL_VARCHAR -> SQL_C_WCHAR */ -#define ES_TEXT_TO_CSQL SQL_C_WCHAR -#define ES_TEXT_TO_SQL SQL_VARCHAR -/* 12: SQL_VARCHAR -> SQL_C_WCHAR */ -#define ES_IP_TO_CSQL SQL_C_WCHAR -#define ES_IP_TO_SQL SQL_VARCHAR -/* 92: SQL_TYPE_TIME -> SQL_C_TYPE_TIME */ -#define ES_TIME_TO_CSQL SQL_C_TYPE_TIME -#define ES_TIME_TO_SQL SQL_TYPE_TIME -/* 91: SQL_TYPE_DATE -> SQL_C_TYPE_DATE */ -#define ES_DATE_TO_CSQL SQL_C_TYPE_DATE -#define ES_DATE_TO_SQL SQL_TYPE_DATE -/* 93: SQL_TYPE_TIMESTAMP -> SQL_C_TYPE_TIMESTAMP */ -#define ES_DATETIME_TO_CSQL SQL_C_TYPE_TIMESTAMP -#define ES_DATETIME_TO_SQL SQL_TYPE_TIMESTAMP -/* -3: SQL_VARBINARY -> SQL_C_BINARY */ -#define ES_BINARY_TO_CSQL SQL_C_BINARY -#define ES_BINARY_TO_SQL SQL_BINARY -/* 0: SQL_TYPE_NULL -> SQL_C_TINYINT */ -#define ES_NULL_TO_CSQL SQL_C_STINYINT // ??? -#define ES_NULL_TO_SQL SQL_TYPE_NULL -/* - * ES-non mappable - */ -/* 114: ??? -> SQL_C_WCHAR */ -#define ES_GEO_TO_CSQL SQL_C_WCHAR /* XXX: CBOR needs _CHAR */ -#define ES_GEO_TO_SQL SQL_VARCHAR - -/* 1111: ??? -> SQL_C_BINARY */ -#define ES_UNSUPPORTED_TO_CSQL SQL_C_BINARY -#define ES_UNSUPPORTED_TO_SQL ESODBC_SQL_UNSUPPORTED -/* 2002: ??? -> SQL_C_BINARY */ -#define ES_OBJECT_TO_CSQL SQL_C_BINARY -#define ES_OBJECT_TO_SQL ESODBC_SQL_OBJECT -/* 2002: ??? -> SQL_C_BINARY */ -#define ES_NESTED_TO_CSQL SQL_C_BINARY -#define ES_NESTED_TO_SQL ESODBC_SQL_NESTED - BOOL connect_init(); void connect_cleanup(); diff --git a/driver/convert.c b/driver/convert.c index 4b497cea..a8836103 100644 --- a/driver/convert.c +++ b/driver/convert.c @@ -1859,7 +1859,8 @@ static SQLRETURN wstr_to_timestamp_struct(esodbc_rec_st *arec, } break; case SQL_TYPE_TIME: - case SQL_VARCHAR: + case ES_VARCHAR_SQL: + case ES_WVARCHAR_SQL: ret = parse_date_time_ts(stmt, &xstr, /*sql2c*/TRUE, tss, format); if (! SQL_SUCCEEDED(ret)) { @@ -2783,7 +2784,7 @@ static SQLRETURN sql2c_interval(esodbc_rec_st *arec, } /* split processing by the source type */ - if (sqltype == SQL_VARCHAR) { + if (sqltype == ES_WVARCHAR_SQL || sqltype == ES_VARCHAR_SQL) { ret = parse_interval_literal(arec, wstr, &ivl); assert(0 <= ivl.interval_type && ivl.interval_type <= sizeof(ivl_type2c_type)/sizeof(ivl_type2c_type[0])); diff --git a/driver/defs.h b/driver/defs.h index 509a50df..cbdedd69 100644 --- a/driver/defs.h +++ b/driver/defs.h @@ -404,9 +404,6 @@ #define ODBC_SQL92_VALUE_EXPRESSIONS (0LU | \ SQL_SVE_CASE | SQL_SVE_CAST | SQL_SVE_COALESCE | SQL_SVE_NULLIF) -/* the type ES/SQL uses for string types (KEYWORD, TEXT, CONSTANT_KEYWORD), - * plus IP and GEO */ -#define ESODBC_SQL_STRING SQL_VARCHAR /* * ES specific data types */ @@ -417,6 +414,99 @@ #define ESODBC_SQL_OBJECT 2002 #define ESODBC_SQL_NESTED 2002 +/* the SQL type ES/SQL uses for string types (KEYWORD, TEXT, CONSTANT_KEYWORD), + * plus IP and GEO */ +#define ESODBC_SQL_VARCHAR SQL_VARCHAR + +/* C SQL and SQL types for ES types that + * - contain UTF8 chars */ +#define ES_WVARCHAR_CSQL SQL_C_WCHAR +#define ES_WVARCHAR_SQL SQL_WVARCHAR +/* - contain ANSI chars */ +#define ES_VARCHAR_CSQL SQL_C_CHAR +#define ES_VARCHAR_SQL SQL_VARCHAR +/* + * ES-to-C-SQL mappings. + * DATA_TYPE(SYS TYPES) : SQL_ -> SQL_C_ + * Intervals not covered, since C==SQL, with no ES customization. + */ +/* -6: BYTE */ +#define ES_BYTE_TO_CSQL SQL_C_TINYINT +#define ES_BYTE_TO_SQL SQL_TINYINT +/* 5: SHORT */ +#define ES_SHORT_TO_CSQL SQL_C_SSHORT +#define ES_SHORT_TO_SQL SQL_SMALLINT +/* 4: INTEGER */ +#define ES_INTEGER_TO_CSQL SQL_C_SLONG +#define ES_INTEGER_TO_SQL SQL_INTEGER +/* -5: LONG */ +#define ES_LONG_TO_CSQL SQL_C_SBIGINT +#define ES_LONG_TO_SQL SQL_BIGINT +/* 6: HALF_FLOAT */ +#define ES_HALF_TO_CSQL_FLOAT SQL_C_DOUBLE +#define ES_HALF_TO_SQL_FLOAT SQL_FLOAT +/* 7: FLOAT */ +#define ES_FLOAT_TO_CSQL SQL_C_FLOAT +#define ES_FLOAT_TO_SQL SQL_REAL +/* 8: DOUBLE */ +#define ES_DOUBLE_TO_CSQL SQL_C_DOUBLE +#define ES_DOUBLE_TO_SQL SQL_DOUBLE +/* 8: SCALED_FLOAT */ +#define ES_SCALED_TO_CSQL_FLOAT SQL_C_DOUBLE +#define ES_SCALED_TO_SQL_FLOAT SQL_DOUBLE +/* 16: BOOLEAN */ +#define ES_BOOLEAN_TO_CSQL SQL_C_BIT +/* BOOLEAN is used in catalog calls (like SYS TYPES / SQLGetTypeInfo), and the + * data type is piped through to the app (just like with any other statement), + * which causes issues, since it's not a standard type => use ODBC's SQL_BIT */ +#define ES_BOOLEAN_TO_SQL SQL_BIT +/* 12: KEYWORD */ +#define ES_KEYWORD_TO_CSQL ES_WVARCHAR_CSQL +#define ES_KEYWORD_TO_SQL ES_WVARCHAR_SQL +/* 12: CONSTANT_KEYWORD */ +#define ES_CKEYWORD_TO_CSQL ES_WVARCHAR_CSQL +#define ES_CKEYWORD_TO_SQL ES_WVARCHAR_SQL +/* 12: TEXT */ +#define ES_TEXT_TO_CSQL ES_WVARCHAR_CSQL +#define ES_TEXT_TO_SQL ES_WVARCHAR_SQL +/* 12: IP */ +#define ES_IP_TO_CSQL ES_VARCHAR_CSQL +#define ES_IP_TO_SQL ES_VARCHAR_SQL +/* 92: TIME */ +#define ES_TIME_TO_CSQL SQL_C_TYPE_TIME +#define ES_TIME_TO_SQL SQL_TYPE_TIME +/* 91: DATE */ +#define ES_DATE_TO_CSQL SQL_C_TYPE_DATE +#define ES_DATE_TO_SQL SQL_TYPE_DATE +/* 93: DATETIME (TIMESTAMP) */ +#define ES_DATETIME_TO_CSQL SQL_C_TYPE_TIMESTAMP +#define ES_DATETIME_TO_SQL SQL_TYPE_TIMESTAMP +/* -3: BINARY */ +#define ES_BINARY_TO_CSQL SQL_C_BINARY +#define ES_BINARY_TO_SQL SQL_BINARY +/* 0: NULL */ +/* there's no standard C SQL ID for a NULL type (but there's a SQL one); so + * map it to a valid C SQL ID (though it should actually be used). */ +#define ES_NULL_TO_CSQL SQL_C_STINYINT +#define ES_NULL_TO_SQL SQL_TYPE_NULL +/* + * ES-non mappable + */ +/* 114: GEO_POINT/_SHAPE, SHAPE */ +#define ES_GEO_TO_CSQL ES_VARCHAR_CSQL +/* WKT encodings */ +#define ES_GEO_TO_SQL ES_VARCHAR_SQL + +/* 1111: UNSUPPORTED */ +#define ES_UNSUPPORTED_TO_CSQL SQL_C_BINARY +#define ES_UNSUPPORTED_TO_SQL ESODBC_SQL_UNSUPPORTED +/* 2002: OBJECT */ +#define ES_OBJECT_TO_CSQL SQL_C_BINARY +#define ES_OBJECT_TO_SQL ESODBC_SQL_OBJECT +/* 2002: NESTED */ +#define ES_NESTED_TO_CSQL SQL_C_BINARY +#define ES_NESTED_TO_SQL ESODBC_SQL_NESTED + #endif /* __DEFS_H__ */ diff --git a/driver/queries.c b/driver/queries.c index c8ef195c..9593bdf6 100644 --- a/driver/queries.c +++ b/driver/queries.c @@ -2456,9 +2456,9 @@ SQLRETURN EsSQLPrepareW /* Find the ES/SQL type given in es_type; for ID matching multiple types - * (scaled/half_float), but not keyword/text, use the best matching col_size, - * which is the smallest, that's still matching (<=) the given one. This - * assumes the types are ordered by it (as per the spec). */ + * (scaled_float/double), but not keyword/text, use the best matching + * col_size, which is the smallest, that's still matching (<=) the given one. + * This assumes the types are ordered by it (as per the spec). */ esodbc_estype_st *lookup_es_type(esodbc_dbc_st *dbc, SQLSMALLINT es_type, SQLULEN col_size) { @@ -2467,7 +2467,7 @@ esodbc_estype_st *lookup_es_type(esodbc_dbc_st *dbc, /* for strings, choose text straight away: some type (IP, GEO) must coform * to a format and no content inspection is done in the driver */ - if (es_type == SQL_VARCHAR) { + if (es_type == ES_VARCHAR_SQL || es_type == ES_WVARCHAR_SQL) { return dbc->max_varchar_type; } for (i = 0; i < dbc->no_types; i ++) { @@ -2480,7 +2480,7 @@ esodbc_estype_st *lookup_es_type(esodbc_dbc_st *dbc, if ((SQLINTEGER)col_size <= sz) { return &dbc->es_types[i]; } - if (es_type == SQL_FLOAT && + if (es_type == SQL_DOUBLE && sz == dbc->max_float_type->column_size) { return dbc->max_float_type; } @@ -2497,25 +2497,17 @@ esodbc_estype_st *lookup_es_type(esodbc_dbc_st *dbc, static esodbc_estype_st *match_es_type(esodbc_rec_st *irec) { SQLULEN i; - SQLINTEGER col_sz; esodbc_dbc_st *dbc = irec->desc->hdr.stmt->hdr.dbc; for (i = 0; i < dbc->no_types; i ++) { if (dbc->es_types[i].data_type == irec->concise_type) { switch (irec->concise_type) { - /* For SQL types mapping to more than one ES/SQL type, choose - * the ES/SQL type with smallest "size" that covers user given - * precision OR that has maximum precision (in case user's is - * larger than max ES/SQL offers. */ - case SQL_FLOAT: /* HALF_FLOAT, SCALED_FLOAT */ - col_sz = dbc->es_types[i].column_size; - if (irec->precision <= col_sz || - col_sz == dbc->max_float_type->column_size) { - return &dbc->es_types[i]; - } + case SQL_DOUBLE: /* DOUBLE, SCALED_FLOAT */ + return dbc->max_float_type; break; - case SQL_VARCHAR: /* IP, CONSTANT_KEYWORD, KEYWORD, TEXT */ - return lookup_es_type(dbc, SQL_VARCHAR, irec->precision); + case ES_WVARCHAR_SQL: /* CONSTANT_KEYWORD, KEYWORD, TEXT */ + case ES_VARCHAR_SQL: /* IP, GEO+ */ + return dbc->max_varchar_type; default: /* unequivocal match */ return &dbc->es_types[i]; @@ -2528,10 +2520,10 @@ static esodbc_estype_st *match_es_type(esodbc_rec_st *irec) case METATYPE_EXACT_NUMERIC: assert(irec->concise_type == SQL_DECIMAL || irec->concise_type == SQL_NUMERIC); - return lookup_es_type(dbc, SQL_FLOAT, irec->precision); + return lookup_es_type(dbc, SQL_DOUBLE, irec->precision); case METATYPE_STRING: - return lookup_es_type(dbc, SQL_VARCHAR, irec->precision); + return lookup_es_type(dbc, ES_TEXT_TO_SQL, irec->precision); case METATYPE_BIN: return lookup_es_type(dbc, SQL_BINARY, /*no prec*/0); case METATYPE_DATE_TIME: @@ -2539,9 +2531,9 @@ static esodbc_estype_st *match_es_type(esodbc_rec_st *irec) irec->concise_type == SQL_TYPE_TIME); return lookup_es_type(dbc, SQL_TYPE_TIMESTAMP, /*no prec*/0); case METATYPE_BIT: - return lookup_es_type(dbc, SQL_BIT, /*no prec*/0); + return lookup_es_type(dbc, ES_BOOLEAN_TO_SQL, /*no prec*/0); case METATYPE_UID: - return lookup_es_type(dbc, SQL_VARCHAR, /*no prec: TEXT*/0); + return lookup_es_type(dbc, ES_TEXT_TO_SQL, /*no prec: TEXT*/0); case METATYPE_INTERVAL_WSEC: case METATYPE_INTERVAL_WOSEC: @@ -2832,8 +2824,8 @@ static SQLRETURN convert_param_val(esodbc_rec_st *arec, esodbc_rec_st *irec, max = FLT_MAX; fixed = FALSE; break; - case SQL_FLOAT: /* HALF_FLOAT, SCALED_FLOAT */ - case SQL_DOUBLE: /* DOUBLE */ + case SQL_FLOAT: /* HALF_FLOAT */ + case SQL_DOUBLE: /* DOUBLE, SCALED_FLOAT */ min = DBL_MIN; max = DBL_MAX; fixed = FALSE; @@ -2842,7 +2834,8 @@ static SQLRETURN convert_param_val(esodbc_rec_st *arec, esodbc_rec_st *irec, return c2sql_number(arec, irec, pos, &min, &max, fixed, dest, len); /* JSON string */ - case SQL_VARCHAR: /* KEYWORD, TEXT */ + case ES_WVARCHAR_SQL: /* KEYWORD, TEXT, CONSTANT_KEYWORD */ + case ES_VARCHAR_SQL: /* IP, GEO+ */ return c2sql_varchar(arec, irec, pos, dest, len); case SQL_TYPE_DATE: diff --git a/test/connected_dbc.h b/test/connected_dbc.h index a963ce6f..ee4557c5 100644 --- a/test/connected_dbc.h +++ b/test/connected_dbc.h @@ -41,64 +41,69 @@ extern "C" { */ #define SYSTYPES_ANSWER "\ {\ - \"columns\":[\ - {\"name\":\"TYPE_NAME\",\"type\":\"keyword\",\"display_size\":32766},\ - {\"name\":\"DATA_TYPE\",\"type\":\"integer\",\"display_size\":11},\ - {\"name\":\"PRECISION\",\"type\":\"integer\",\"display_size\":11},\ - {\"name\":\"LITERAL_PREFIX\",\"type\":\"keyword\",\"display_size\":32766},\ - {\"name\":\"LITERAL_SUFFIX\",\"type\":\"keyword\",\"display_size\":32766},\ - {\"name\":\"CREATE_PARAMS\",\"type\":\"keyword\",\"display_size\":32766},\ - {\"name\":\"NULLABLE\",\"type\":\"short\",\"display_size\":6},\ - {\"name\":\"CASE_SENSITIVE\",\"type\":\"boolean\",\"display_size\":1},\ - {\"name\":\"SEARCHABLE\",\"type\":\"short\",\"display_size\":6},\ - {\"name\":\"UNSIGNED_ATTRIBUTE\",\"type\":\"boolean\",\"display_size\":1},\ - {\"name\":\"FIXED_PREC_SCALE\",\"type\":\"boolean\",\"display_size\":1},\ - {\"name\":\"AUTO_INCREMENT\",\"type\":\"boolean\",\"display_size\":1},\ - {\"name\":\"LOCAL_TYPE_NAME\",\"type\":\"keyword\",\"display_size\":32766},\ - {\"name\":\"MINIMUM_SCALE\",\"type\":\"short\",\"display_size\":6},\ - {\"name\":\"MAXIMUM_SCALE\",\"type\":\"short\",\"display_size\":6},\ - {\"name\":\"SQL_DATA_TYPE\",\"type\":\"integer\",\"display_size\":11},\ - {\"name\":\"SQL_DATETIME_SUB\",\"type\":\"integer\",\"display_size\":11},\ - {\"name\":\"NUM_PREC_RADIX\",\"type\":\"integer\",\"display_size\":11},\ - {\"name\":\"INTERVAL_PRECISION\",\"type\":\"integer\",\"display_size\":11}\ - ],\ - \"rows\":[\ - [\"BYTE\",-6,3,\"'\",\"'\",null,2,false,3,false,false,false,null,0,0,-6,0,10,null],\ - [\"LONG\",-5,19,\"'\",\"'\",null,2,false,3,false,false,false,null,0,0,-5,0,10,null],\ - [\"BINARY\",-2,2147483647,\"'\",\"'\",null,2,false,3,true,false,false,null,null,null,-3,0,null,null],\ - [\"NULL\",0,0,\"'\",\"'\",null,2,false,3,true,false,false,null,null,null,0,0,null,null],\ - [\"INTEGER\",4,10,\"'\",\"'\",null,2,false,3,false,false,false,null,0,0,4,0,10,null],\ - [\"SHORT\",5,5,\"'\",\"'\",null,2,false,3,false,false,false,null,0,0,5,0,10,null],\ - [\"HALF_FLOAT\",6,3,\"'\",\"'\",null,2,false,3,false,false,false,null,3,3,6,0,2,null],\ - [\"FLOAT\",7,7,\"'\",\"'\",null,2,false,3,false,false,false,null,7,7,7,0,2,null],\ - [\"DOUBLE\",8,15,\"'\",\"'\",null,2,false,3,false,false,false,null,15,15,8,0,2,null],\ - [\"SCALED_FLOAT\",8,15,\"'\",\"'\",null,2,false,3,false,false,false,null,15,15,8,0,2,null],\ - [\"KEYWORD\",12,32766,\"'\",\"'\",null,2,true,3,true,false,false,null,null,null,12,0,null,null],\ - [\"TEXT\",12,2147483647,\"'\",\"'\",null,2,true,3,true,false,false,null,null,null,12,0,null,null],\ - [\"IP\",12,0,\"'\",\"'\",null,2,false,3,true,false,false,null,null,null,12,0,null,null],\ - [\"BOOLEAN\",16,1,\"'\",\"'\",null,2,false,3,true,false,false,null,null,null,16,0,null,null],\ - [\"DATE\",91,29,\"'\",\"'\",null,2,false,3,true,false,false,null,null,null,91,1,null,null],\ - [\"TIME\",92,18,\"'\",\"'\",null,2,false,3,true,false,false,null,3,3,92,2,null,null],\ - [\"DATETIME\",93,29,\"'\",\"'\",null,2,false,3,true,false,false,null,3,3,9,3,null,null],\ - [\"INTERVAL_YEAR\",101,7,\"'\",\"'\",null,2,false,3,true,false,false,null,null,null,101,0,null,null],\ - [\"INTERVAL_MONTH\",102,7,\"'\",\"'\",null,2,false,3,true,false,false,null,null,null,102,0,null,null],\ - [\"INTERVAL_DAY\",103,23,\"'\",\"'\",null,2,false,3,true,false,false,null,null,null,103,0,null,null],\ - [\"INTERVAL_HOUR\",104,23,\"'\",\"'\",null,2,false,3,true,false,false,null,null,null,104,0,null,null],\ - [\"INTERVAL_MINUTE\",105,23,\"'\",\"'\",null,2,false,3,true,false,false,null,null,null,105,0,null,null],\ - [\"INTERVAL_SECOND\",106,23,\"'\",\"'\",null,2,false,3,true,false,false,null,null,null,106,0,null,null],\ - [\"INTERVAL_YEAR_TO_MONTH\",107,7,\"'\",\"'\",null,2,false,3,true,false,false,null,null,null,107,0,null,null],\ - [\"INTERVAL_DAY_TO_HOUR\",108,23,\"'\",\"'\",null,2,false,3,true,false,false,null,null,null,108,0,null,null],\ - [\"INTERVAL_DAY_TO_MINUTE\",109,23,\"'\",\"'\",null,2,false,3,true,false,false,null,null,null,109,0,null,null],\ - [\"INTERVAL_DAY_TO_SECOND\",110,23,\"'\",\"'\",null,2,false,3,true,false,false,null,null,null,110,0,null,null],\ - [\"INTERVAL_HOUR_TO_MINUTE\",111,23,\"'\",\"'\",null,2,false,3,true,false,false,null,null,null,111,0,null,null],\ - [\"INTERVAL_HOUR_TO_SECOND\",112,23,\"'\",\"'\",null,2,false,3,true,false,false,null,null,null,112,0,null,null],\ - [\"INTERVAL_MINUTE_TO_SECOND\",113,23,\"'\",\"'\",null,2,false,3,true,false,false,null,null,null,113,0,null,null],\ - [\"UNSUPPORTED\",1111,0,\"'\",\"'\",null,2,false,3,true,false,false,null,null,null,1111,0,null,null],\ - [\"OBJECT\",2002,0,\"'\",\"'\",null,2,false,3,true,false,false,null,null,null,2002,0,null,null],\ - [\"NESTED\",2002,0,\"'\",\"'\",null,2,false,3,true,false,false,null,null,null,2002,0,null,null]\ - ]\ + \"columns\" : [\ + {\"name\" : \"TYPE_NAME\", \"type\" : \"keyword\", \"display_size\" : 32766},\ + {\"name\" : \"DATA_TYPE\", \"type\" : \"integer\", \"display_size\" : 11},\ + {\"name\" : \"PRECISION\", \"type\" : \"integer\", \"display_size\" : 11},\ + {\"name\" : \"LITERAL_PREFIX\", \"type\" : \"keyword\", \"display_size\" : 32766},\ + {\"name\" : \"LITERAL_SUFFIX\", \"type\" : \"keyword\", \"display_size\" : 32766},\ + {\"name\" : \"CREATE_PARAMS\", \"type\" : \"keyword\", \"display_size\" : 32766},\ + {\"name\" : \"NULLABLE\", \"type\" : \"short\", \"display_size\" : 6},\ + {\"name\" : \"CASE_SENSITIVE\", \"type\" : \"boolean\", \"display_size\" : 1},\ + {\"name\" : \"SEARCHABLE\", \"type\" : \"short\", \"display_size\" : 6},\ + {\"name\" : \"UNSIGNED_ATTRIBUTE\", \"type\" : \"boolean\", \"display_size\" : 1},\ + {\"name\" : \"FIXED_PREC_SCALE\", \"type\" : \"boolean\", \"display_size\" : 1},\ + {\"name\" : \"AUTO_INCREMENT\", \"type\" : \"boolean\", \"display_size\" : 1},\ + {\"name\" : \"LOCAL_TYPE_NAME\", \"type\" : \"keyword\", \"display_size\" : 32766},\ + {\"name\" : \"MINIMUM_SCALE\", \"type\" : \"short\", \"display_size\" : 6},\ + {\"name\" : \"MAXIMUM_SCALE\", \"type\" : \"short\", \"display_size\" : 6},\ + {\"name\" : \"SQL_DATA_TYPE\", \"type\" : \"integer\", \"display_size\" : 11},\ + {\"name\" : \"SQL_DATETIME_SUB\", \"type\" : \"integer\", \"display_size\" : 11},\ + {\"name\" : \"NUM_PREC_RADIX\", \"type\" : \"integer\", \"display_size\" : 11},\ + {\"name\" : \"INTERVAL_PRECISION\", \"type\" : \"integer\", \"display_size\" : 11}\ + ],\ + \"rows\" : [\ + [\"BYTE\", -6, 3, \"'\", \"'\", null, 2, false, 3, false, false, false, null, 0, 0, -6, 0, 10, null],\ + [\"LONG\", -5, 19, \"'\", \"'\", null, 2, false, 3, false, false, false, null, 0, 0, -5, 0, 10, null],\ + [\"BINARY\", -2, 2147483647, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, -2, 0, null, null],\ + [\"NULL\", 0, 0, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 0, 0, null, null],\ + [\"INTEGER\", 4, 10, \"'\", \"'\", null, 2, false, 3, false, false, false, null, 0, 0, 4, 0, 10, null],\ + [\"SHORT\", 5, 5, \"'\", \"'\", null, 2, false, 3, false, false, false, null, 0, 0, 5, 0, 10, null],\ + [\"HALF_FLOAT\", 6, 3, \"'\", \"'\", null, 2, false, 3, false, false, false, null, 3, 3, 6, 0, 2, null],\ + [\"FLOAT\", 7, 7, \"'\", \"'\", null, 2, false, 3, false, false, false, null, 7, 7, 7, 0, 2, null],\ + [\"DOUBLE\", 8, 15, \"'\", \"'\", null, 2, false, 3, false, false, false, null, 15, 15, 8, 0, 2, null],\ + [\"SCALED_FLOAT\", 8, 15, \"'\", \"'\", null, 2, false, 3, false, false, false, null, 15, 15, 8, 0, 2, null],\ + [\"CONSTANT_KEYWORD\", 12, 32766, \"'\", \"'\", null, 2, true, 3, true, false, false, null, null, null, 12, 0, null, null],\ + [\"IP\", 12, 45, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 12, 0, null, null],\ + [\"KEYWORD\", 12, 32766, \"'\", \"'\", null, 2, true, 3, true, false, false, null, null, null, 12, 0, null, null],\ + [\"TEXT\", 12, 2147483647, \"'\", \"'\", null, 2, true, 3, true, false, false, null, null, null, 12, 0, null, null],\ + [\"BOOLEAN\", 16, 1, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 16, 0, null, null],\ + [\"DATE\", 91, 29, \"'\", \"'\", null, 2, false, 3, true, false, false, null, 3, 3, 91, 0, null, null],\ + [\"TIME\", 92, 18, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 92, 0, null, null],\ + [\"DATETIME\", 93, 29, \"'\", \"'\", null, 2, false, 3, true, false, false, null, 3, 3, 9, 3, null, null],\ + [\"INTERVAL_YEAR\", 101, 7, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 101, 0, null, null],\ + [\"INTERVAL_MONTH\", 102, 7, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 102, 0, null, null],\ + [\"INTERVAL_DAY\", 103, 23, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 103, 0, null, null],\ + [\"INTERVAL_HOUR\", 104, 23, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 104, 0, null, null],\ + [\"INTERVAL_MINUTE\", 105, 23, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 105, 0, null, null],\ + [\"INTERVAL_SECOND\", 106, 23, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 106, 0, null, null],\ + [\"INTERVAL_YEAR_TO_MONTH\", 107, 7, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 107, 0, null, null],\ + [\"INTERVAL_DAY_TO_HOUR\", 108, 23, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 108, 0, null, null],\ + [\"INTERVAL_DAY_TO_MINUTE\", 109, 23, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 109, 0, null, null],\ + [\"INTERVAL_DAY_TO_SECOND\", 110, 23, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 110, 0, null, null],\ + [\"INTERVAL_HOUR_TO_MINUTE\", 111, 23, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 111, 0, null, null],\ + [\"INTERVAL_HOUR_TO_SECOND\", 112, 23, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 112, 0, null, null],\ + [\"INTERVAL_MINUTE_TO_SECOND\", 113, 23, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 113, 0, null, null],\ + [\"GEO_POINT\", 114, 58, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 114, 0, null, null],\ + [\"GEO_SHAPE\", 114, 2147483647, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 114, 0, null, null],\ + [\"SHAPE\", 114, 2147483647, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 114, 0, null, null],\ + [\"UNSUPPORTED\", 1111, 0, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 1111, 0, null, null],\ + [\"NESTED\", 2002, 0, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 2002, 0, null, null],\ + [\"OBJECT\", 2002, 0, \"'\", \"'\", null, 2, false, 3, true, false, false, null, null, null, 2002, 0, null, null] \ + ]\ }" + /* minimal, valid connection string */ #define CONNECT_STRING L"Driver=ElasticODBC;Packing=JSON;" diff --git a/test/test_queries.cc b/test/test_queries.cc index fea8c716..13018df4 100644 --- a/test/test_queries.cc +++ b/test/test_queries.cc @@ -208,6 +208,66 @@ TEST_F(Queries, SQLNumParams_duplicates_escape) { ASSERT_EQ(params, 2); } +TEST_F(Queries, SQLDescribeCol_wchar) { + +# define COL_NAME "SQLDescribeCol_wchar" + + const char json_answer[] = "\ +{\ + \"columns\": [\ + {\"name\": \"" COL_NAME "\", \"type\": \"text\"}\ + ],\ + \"rows\": [\ + [\"bar\"]\ + ]\ +}\ +"; + prepareStatement(json_answer); + + SQLWCHAR col_name[sizeof(COL_NAME)]; + SQLSMALLINT col_name_len, sql_type, scale, nullable; + SQLULEN col_size; + ret = SQLDescribeCol(stmt, /*col#*/1, col_name, sizeof(col_name), + &col_name_len, &sql_type, &col_size, &scale, &nullable); + ASSERT_TRUE(SQL_SUCCEEDED(ret)); + ASSERT_EQ(col_name_len, sizeof(COL_NAME) - 1); + ASSERT_STREQ(col_name, MK_WPTR(COL_NAME)); + ASSERT_EQ(sql_type, ES_WVARCHAR_SQL); + ASSERT_EQ(col_size, INT_MAX); + ASSERT_EQ(nullable, SQL_NULLABLE_UNKNOWN); +} + +TEST_F(Queries, SQLDescribeCol_char) { + +# undef COL_NAME +# define COL_NAME "SQLDescribeCol_char" + + const char json_answer[] = "\ +{\ + \"columns\": [\ + {\"name\": \"" COL_NAME "\", \"type\": \"IP\"}\ + ],\ + \"rows\": [\ + [\"1.2.3.4\"]\ + ]\ +}\ +"; + prepareStatement(json_answer); + + SQLWCHAR col_name[sizeof(COL_NAME)]; + SQLSMALLINT col_name_len, sql_type, scale, nullable; + SQLULEN col_size; + ret = SQLDescribeCol(stmt, /*col#*/1, col_name, sizeof(col_name), + &col_name_len, &sql_type, &col_size, &scale, &nullable); + ASSERT_TRUE(SQL_SUCCEEDED(ret)); + ASSERT_EQ(col_name_len, sizeof(COL_NAME) - 1); + ASSERT_STREQ(col_name, MK_WPTR(COL_NAME)); + ASSERT_EQ(sql_type, ES_VARCHAR_SQL); + ASSERT_EQ(col_size, 45); + ASSERT_EQ(nullable, SQL_NULLABLE_UNKNOWN); +} + + } // test namespace /* vim: set noet fenc=utf-8 ff=dos sts=0 sw=4 ts=4 : */