Skip to content

Commit 88c225d

Browse files
committed
Fix varchar type definition (#232)
* Fix ES varchar types mappings to ODBC types This commit fixes the mappings of the varchar types to the ODBC data types: - the KEYWORD, CONSTANT_KEYWORD and TEXT types are now SQL_WVARCHAR, which allows certain applications to correctly read the UTF8 content. - IP and the other string types (like GEO ones) remain to the previous SQL_VARCHAR types. The handling of double types has also been fixed to reflect the correction in Elasticsearch/SQL that now maps DOUBLE and SCALED_FLOAT to the same type (SQL_DOUBLE). * Supplement tests for the varchar type change add tests querying for SQL source type. * update types defs for unit test update the definition of the ES/SQL types used in unit tests. (cherry picked from commit 45a82b1)
1 parent 9fe5cba commit 88c225d

File tree

7 files changed

+260
-203
lines changed

7 files changed

+260
-203
lines changed

driver/connect.c

Lines changed: 25 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2290,12 +2290,11 @@ static void set_display_size(esodbc_estype_st *es_type)
22902290
{
22912291
switch (es_type->data_type) {
22922292
case SQL_CHAR:
2293-
case SQL_VARCHAR: /* KEYWORD, TEXT */
2293+
case SQL_VARCHAR:
22942294
case SQL_LONGVARCHAR:
22952295
case SQL_WCHAR:
22962296
case SQL_WVARCHAR:
22972297
case SQL_WLONGVARCHAR:
2298-
// TODO: 45 if IP?
22992298
es_type->display_size = es_type->column_size;
23002299
break;
23012300

@@ -2465,7 +2464,7 @@ static void *copy_types_rows(esodbc_dbc_st *dbc, estype_row_st *type_row,
24652464
SQLWCHAR *pos;
24662465
int c;
24672466
SQLULEN i;
2468-
SQLSMALLINT sql_type, sec_prec;
2467+
SQLSMALLINT sec_prec;
24692468

24702469
/* pointer to start position where the strings will be copied in */
24712470
pos = (SQLWCHAR *)&types[rows_fetched];
@@ -2548,35 +2547,16 @@ static void *copy_types_rows(esodbc_dbc_st *dbc, estype_row_st *type_row,
25482547

25492548
/* resolve ES type to SQL and SQL C type */
25502549
if (! elastic_name2types(&types[i].type_name, &types[i].c_concise_type,
2551-
&sql_type)) {
2550+
&types[i].data_type)) {
25522551
/* ES version newer than driver's? */
25532552
ERRH(dbc, "failed to convert type name `" LWPDL "` to SQL C type.",
25542553
LWSTR(&types[i].type_name));
25552554
return NULL;
25562555
}
2557-
DBGH(dbc, "ES type `" LWPDL "` resolved to C concise: %hd, SQL: %hd.",
2558-
LWSTR(&types[i].type_name), types[i].c_concise_type, sql_type);
2559-
2560-
/* BOOLEAN is used in catalog calls (like SYS TYPES / SQLGetTypeInfo),
2561-
* and the data type is piped through to the app (just like with any
2562-
* other statement), which causes issues, since it's not a standard
2563-
* type => change it to SQL_BIT */
2564-
if (types[i].data_type == ESODBC_SQL_BOOLEAN) {
2565-
types[i].data_type = ES_BOOLEAN_TO_SQL;
2566-
}
2567-
/* GEO (SHAPE, POINT), SHAPE types are WKT encodings */
2568-
if (types[i].data_type == ESODBC_SQL_GEO) {
2569-
types[i].data_type = ES_GEO_TO_SQL;
2570-
}
2556+
DBGH(dbc, "ES type `" LWPDL "` resolved to concise: C=%hd, SQL=%hd.",
2557+
LWSTR(&types[i].type_name), types[i].c_concise_type,
2558+
types[i].data_type);
25712559

2572-
/* .data_type is used in data conversions -> make sure the SQL type
2573-
* derived from type's name is the same with type reported value */
2574-
if (sql_type != types[i].data_type) {
2575-
ERRH(dbc, "type `" LWPDL "` derived (%d) and reported (%d) SQL "
2576-
"type identifiers differ.", LWSTR(&types[i].type_name),
2577-
sql_type, types[i].data_type);
2578-
return NULL;
2579-
}
25802560
/* set meta type */
25812561
types[i].meta_type = concise_to_meta(types[i].c_concise_type,
25822562
/*C type -> AxD*/DESC_TYPE_ARD);
@@ -2585,8 +2565,9 @@ static void *copy_types_rows(esodbc_dbc_st *dbc, estype_row_st *type_row,
25852565
concise_to_type_code(types[i].data_type, &types[i].sql_data_type,
25862566
&types[i].sql_datetime_sub);
25872567

2588-
/* if there's a varchar limit, apply it to string types */
2589-
if (types[i].sql_data_type == ESODBC_SQL_STRING) {
2568+
/* if there's a set varchar limit, apply it to the string types */
2569+
if (types[i].data_type == ES_WVARCHAR_SQL ||
2570+
types[i].data_type == ES_VARCHAR_SQL) {
25902571
assert(0 <= types[i].column_size);
25912572
if (dbc->varchar_limit &&
25922573
dbc->varchar_limit < (SQLUINTEGER)types[i].column_size) {
@@ -2632,26 +2613,29 @@ static void set_es_types(esodbc_dbc_st *dbc, SQLULEN rows_fetched,
26322613
assert(dbc->max_varchar_type == NULL);
26332614

26342615
for (i = 0; i < rows_fetched; i ++) {
2635-
if (types[i].data_type == SQL_FLOAT) {
2636-
max_float_size = dbc->max_float_type ?
2637-
dbc->max_float_type->column_size : 0;
2638-
if (max_float_size < types[i].column_size) {
2639-
dbc->max_float_type = &types[i];
2640-
}
2641-
} else if (types[i].data_type == SQL_VARCHAR) {
2642-
max_varchar_size = dbc->max_varchar_type ?
2643-
dbc->max_varchar_type->column_size : 0;
2644-
if (max_varchar_size < types[i].column_size) {
2645-
dbc->max_varchar_type = &types[i];
2646-
}
2616+
switch (types[i].data_type) {
2617+
case SQL_DOUBLE:
2618+
max_float_size = dbc->max_float_type ?
2619+
dbc->max_float_type->column_size : 0;
2620+
if (max_float_size < types[i].column_size) {
2621+
dbc->max_float_type = &types[i];
2622+
}
2623+
break;
2624+
case ES_VARCHAR_SQL:
2625+
case ES_WVARCHAR_SQL:
2626+
max_varchar_size = dbc->max_varchar_type ?
2627+
dbc->max_varchar_type->column_size : 0;
2628+
if (max_varchar_size < types[i].column_size) {
2629+
dbc->max_varchar_type = &types[i];
2630+
}
26472631
}
26482632
}
26492633

26502634
assert(dbc->max_float_type);
26512635
assert(dbc->max_varchar_type);
26522636

26532637
DBGH(dbc, "%lu ES/SQL types available, maximum sizes supported for: "
2654-
"SQL_FLOAT: %ld, SQL_VARCHAR: %ld.", (unsigned long)rows_fetched,
2638+
"floats: %ld, varchar: %ld.", (unsigned long)rows_fetched,
26552639
dbc->max_float_type->column_size, dbc->max_varchar_type->column_size);
26562640
}
26572641

driver/connect.h

Lines changed: 0 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -12,82 +12,6 @@
1212
#include "dsn.h"
1313

1414

15-
/*
16-
* ES-to-C-SQL mappings.
17-
* DATA_TYPE(SYS TYPES) : SQL_<type> -> SQL_C_<type>
18-
* Intervals not covered, since C==SQL, with no ES customization.
19-
*/
20-
/* -6: SQL_TINYINT -> SQL_C_TINYINT */
21-
#define ES_BYTE_TO_CSQL SQL_C_TINYINT
22-
#define ES_BYTE_TO_SQL SQL_TINYINT
23-
/* 5: SQL_SMALLINT -> SQL_C_SHORT */
24-
#define ES_SHORT_TO_CSQL SQL_C_SSHORT
25-
#define ES_SHORT_TO_SQL SQL_SMALLINT
26-
/* 4: SQL_INTEGER -> SQL_C_LONG */
27-
#define ES_INTEGER_TO_CSQL SQL_C_SLONG
28-
#define ES_INTEGER_TO_SQL SQL_INTEGER
29-
/* -5: SQL_BIGINT -> SQL_C_SBIGINT */
30-
#define ES_LONG_TO_CSQL SQL_C_SBIGINT
31-
#define ES_LONG_TO_SQL SQL_BIGINT
32-
/* 6: SQL_FLOAT -> SQL_C_DOUBLE */
33-
#define ES_HALF_TO_CSQL_FLOAT SQL_C_DOUBLE
34-
#define ES_HALF_TO_SQL_FLOAT SQL_FLOAT
35-
/* 6: SQL_FLOAT -> SQL_C_DOUBLE */
36-
#define ES_SCALED_TO_CSQL_FLOAT SQL_C_DOUBLE
37-
#define ES_SCALED_TO_SQL_FLOAT SQL_DOUBLE
38-
/* 7: SQL_REAL -> SQL_C_DOUBLE */
39-
#define ES_FLOAT_TO_CSQL SQL_C_FLOAT
40-
#define ES_FLOAT_TO_SQL SQL_REAL
41-
/* 8: SQL_DOUBLE -> SQL_C_FLOAT */
42-
#define ES_DOUBLE_TO_CSQL SQL_C_DOUBLE
43-
#define ES_DOUBLE_TO_SQL SQL_DOUBLE
44-
/* 16: ??? -> SQL_C_TINYINT */
45-
#define ES_BOOLEAN_TO_CSQL SQL_C_BIT
46-
#define ES_BOOLEAN_TO_SQL SQL_BIT
47-
/* 12: SQL_VARCHAR -> SQL_C_WCHAR */
48-
#define ES_KEYWORD_TO_CSQL SQL_C_WCHAR
49-
#define ES_KEYWORD_TO_SQL SQL_VARCHAR
50-
/* 12: SQL_VARCHAR -> SQL_C_WCHAR */
51-
#define ES_CKEYWORD_TO_CSQL SQL_C_WCHAR
52-
#define ES_CKEYWORD_TO_SQL SQL_VARCHAR
53-
/* 12: SQL_VARCHAR -> SQL_C_WCHAR */
54-
#define ES_TEXT_TO_CSQL SQL_C_WCHAR
55-
#define ES_TEXT_TO_SQL SQL_VARCHAR
56-
/* 12: SQL_VARCHAR -> SQL_C_WCHAR */
57-
#define ES_IP_TO_CSQL SQL_C_WCHAR
58-
#define ES_IP_TO_SQL SQL_VARCHAR
59-
/* 92: SQL_TYPE_TIME -> SQL_C_TYPE_TIME */
60-
#define ES_TIME_TO_CSQL SQL_C_TYPE_TIME
61-
#define ES_TIME_TO_SQL SQL_TYPE_TIME
62-
/* 91: SQL_TYPE_DATE -> SQL_C_TYPE_DATE */
63-
#define ES_DATE_TO_CSQL SQL_C_TYPE_DATE
64-
#define ES_DATE_TO_SQL SQL_TYPE_DATE
65-
/* 93: SQL_TYPE_TIMESTAMP -> SQL_C_TYPE_TIMESTAMP */
66-
#define ES_DATETIME_TO_CSQL SQL_C_TYPE_TIMESTAMP
67-
#define ES_DATETIME_TO_SQL SQL_TYPE_TIMESTAMP
68-
/* -3: SQL_VARBINARY -> SQL_C_BINARY */
69-
#define ES_BINARY_TO_CSQL SQL_C_BINARY
70-
#define ES_BINARY_TO_SQL SQL_BINARY
71-
/* 0: SQL_TYPE_NULL -> SQL_C_TINYINT */
72-
#define ES_NULL_TO_CSQL SQL_C_STINYINT // ???
73-
#define ES_NULL_TO_SQL SQL_TYPE_NULL
74-
/*
75-
* ES-non mappable
76-
*/
77-
/* 114: ??? -> SQL_C_WCHAR */
78-
#define ES_GEO_TO_CSQL SQL_C_WCHAR /* XXX: CBOR needs _CHAR */
79-
#define ES_GEO_TO_SQL SQL_VARCHAR
80-
81-
/* 1111: ??? -> SQL_C_BINARY */
82-
#define ES_UNSUPPORTED_TO_CSQL SQL_C_BINARY
83-
#define ES_UNSUPPORTED_TO_SQL ESODBC_SQL_UNSUPPORTED
84-
/* 2002: ??? -> SQL_C_BINARY */
85-
#define ES_OBJECT_TO_CSQL SQL_C_BINARY
86-
#define ES_OBJECT_TO_SQL ESODBC_SQL_OBJECT
87-
/* 2002: ??? -> SQL_C_BINARY */
88-
#define ES_NESTED_TO_CSQL SQL_C_BINARY
89-
#define ES_NESTED_TO_SQL ESODBC_SQL_NESTED
90-
9115

9216
BOOL connect_init();
9317
void connect_cleanup();

driver/convert.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1859,7 +1859,8 @@ static SQLRETURN wstr_to_timestamp_struct(esodbc_rec_st *arec,
18591859
}
18601860
break;
18611861
case SQL_TYPE_TIME:
1862-
case SQL_VARCHAR:
1862+
case ES_VARCHAR_SQL:
1863+
case ES_WVARCHAR_SQL:
18631864
ret = parse_date_time_ts(stmt, &xstr, /*sql2c*/TRUE, tss,
18641865
format);
18651866
if (! SQL_SUCCEEDED(ret)) {
@@ -2783,7 +2784,7 @@ static SQLRETURN sql2c_interval(esodbc_rec_st *arec,
27832784
}
27842785

27852786
/* split processing by the source type */
2786-
if (sqltype == SQL_VARCHAR) {
2787+
if (sqltype == ES_WVARCHAR_SQL || sqltype == ES_VARCHAR_SQL) {
27872788
ret = parse_interval_literal(arec, wstr, &ivl);
27882789
assert(0 <= ivl.interval_type && ivl.interval_type <=
27892790
sizeof(ivl_type2c_type)/sizeof(ivl_type2c_type[0]));

driver/defs.h

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -404,9 +404,6 @@
404404
#define ODBC_SQL92_VALUE_EXPRESSIONS (0LU | \
405405
SQL_SVE_CASE | SQL_SVE_CAST | SQL_SVE_COALESCE | SQL_SVE_NULLIF)
406406

407-
/* the type ES/SQL uses for string types (KEYWORD, TEXT, CONSTANT_KEYWORD),
408-
* plus IP and GEO */
409-
#define ESODBC_SQL_STRING SQL_VARCHAR
410407
/*
411408
* ES specific data types
412409
*/
@@ -417,6 +414,99 @@
417414
#define ESODBC_SQL_OBJECT 2002
418415
#define ESODBC_SQL_NESTED 2002
419416

417+
/* the SQL type ES/SQL uses for string types (KEYWORD, TEXT, CONSTANT_KEYWORD),
418+
* plus IP and GEO */
419+
#define ESODBC_SQL_VARCHAR SQL_VARCHAR
420+
421+
/* C SQL and SQL types for ES types that
422+
* - contain UTF8 chars */
423+
#define ES_WVARCHAR_CSQL SQL_C_WCHAR
424+
#define ES_WVARCHAR_SQL SQL_WVARCHAR
425+
/* - contain ANSI chars */
426+
#define ES_VARCHAR_CSQL SQL_C_CHAR
427+
#define ES_VARCHAR_SQL SQL_VARCHAR
428+
/*
429+
* ES-to-C-SQL mappings.
430+
* DATA_TYPE(SYS TYPES) : SQL_<type> -> SQL_C_<type>
431+
* Intervals not covered, since C==SQL, with no ES customization.
432+
*/
433+
/* -6: BYTE */
434+
#define ES_BYTE_TO_CSQL SQL_C_TINYINT
435+
#define ES_BYTE_TO_SQL SQL_TINYINT
436+
/* 5: SHORT */
437+
#define ES_SHORT_TO_CSQL SQL_C_SSHORT
438+
#define ES_SHORT_TO_SQL SQL_SMALLINT
439+
/* 4: INTEGER */
440+
#define ES_INTEGER_TO_CSQL SQL_C_SLONG
441+
#define ES_INTEGER_TO_SQL SQL_INTEGER
442+
/* -5: LONG */
443+
#define ES_LONG_TO_CSQL SQL_C_SBIGINT
444+
#define ES_LONG_TO_SQL SQL_BIGINT
445+
/* 6: HALF_FLOAT */
446+
#define ES_HALF_TO_CSQL_FLOAT SQL_C_DOUBLE
447+
#define ES_HALF_TO_SQL_FLOAT SQL_FLOAT
448+
/* 7: FLOAT */
449+
#define ES_FLOAT_TO_CSQL SQL_C_FLOAT
450+
#define ES_FLOAT_TO_SQL SQL_REAL
451+
/* 8: DOUBLE */
452+
#define ES_DOUBLE_TO_CSQL SQL_C_DOUBLE
453+
#define ES_DOUBLE_TO_SQL SQL_DOUBLE
454+
/* 8: SCALED_FLOAT */
455+
#define ES_SCALED_TO_CSQL_FLOAT SQL_C_DOUBLE
456+
#define ES_SCALED_TO_SQL_FLOAT SQL_DOUBLE
457+
/* 16: BOOLEAN */
458+
#define ES_BOOLEAN_TO_CSQL SQL_C_BIT
459+
/* BOOLEAN is used in catalog calls (like SYS TYPES / SQLGetTypeInfo), and the
460+
* data type is piped through to the app (just like with any other statement),
461+
* which causes issues, since it's not a standard type => use ODBC's SQL_BIT */
462+
#define ES_BOOLEAN_TO_SQL SQL_BIT
463+
/* 12: KEYWORD */
464+
#define ES_KEYWORD_TO_CSQL ES_WVARCHAR_CSQL
465+
#define ES_KEYWORD_TO_SQL ES_WVARCHAR_SQL
466+
/* 12: CONSTANT_KEYWORD */
467+
#define ES_CKEYWORD_TO_CSQL ES_WVARCHAR_CSQL
468+
#define ES_CKEYWORD_TO_SQL ES_WVARCHAR_SQL
469+
/* 12: TEXT */
470+
#define ES_TEXT_TO_CSQL ES_WVARCHAR_CSQL
471+
#define ES_TEXT_TO_SQL ES_WVARCHAR_SQL
472+
/* 12: IP */
473+
#define ES_IP_TO_CSQL ES_VARCHAR_CSQL
474+
#define ES_IP_TO_SQL ES_VARCHAR_SQL
475+
/* 92: TIME */
476+
#define ES_TIME_TO_CSQL SQL_C_TYPE_TIME
477+
#define ES_TIME_TO_SQL SQL_TYPE_TIME
478+
/* 91: DATE */
479+
#define ES_DATE_TO_CSQL SQL_C_TYPE_DATE
480+
#define ES_DATE_TO_SQL SQL_TYPE_DATE
481+
/* 93: DATETIME (TIMESTAMP) */
482+
#define ES_DATETIME_TO_CSQL SQL_C_TYPE_TIMESTAMP
483+
#define ES_DATETIME_TO_SQL SQL_TYPE_TIMESTAMP
484+
/* -3: BINARY */
485+
#define ES_BINARY_TO_CSQL SQL_C_BINARY
486+
#define ES_BINARY_TO_SQL SQL_BINARY
487+
/* 0: NULL */
488+
/* there's no standard C SQL ID for a NULL type (but there's a SQL one); so
489+
* map it to a valid C SQL ID (though it should actually be used). */
490+
#define ES_NULL_TO_CSQL SQL_C_STINYINT
491+
#define ES_NULL_TO_SQL SQL_TYPE_NULL
492+
/*
493+
* ES-non mappable
494+
*/
495+
/* 114: GEO_POINT/_SHAPE, SHAPE */
496+
#define ES_GEO_TO_CSQL ES_VARCHAR_CSQL
497+
/* WKT encodings */
498+
#define ES_GEO_TO_SQL ES_VARCHAR_SQL
499+
500+
/* 1111: UNSUPPORTED */
501+
#define ES_UNSUPPORTED_TO_CSQL SQL_C_BINARY
502+
#define ES_UNSUPPORTED_TO_SQL ESODBC_SQL_UNSUPPORTED
503+
/* 2002: OBJECT */
504+
#define ES_OBJECT_TO_CSQL SQL_C_BINARY
505+
#define ES_OBJECT_TO_SQL ESODBC_SQL_OBJECT
506+
/* 2002: NESTED */
507+
#define ES_NESTED_TO_CSQL SQL_C_BINARY
508+
#define ES_NESTED_TO_SQL ESODBC_SQL_NESTED
509+
420510

421511
#endif /* __DEFS_H__ */
422512

0 commit comments

Comments
 (0)