From 64633846cc6959eca307d37e7b879ac14182f3c3 Mon Sep 17 00:00:00 2001 From: Hanfei Shen Date: Wed, 4 May 2011 00:21:57 +0800 Subject: Add support for SQL_WLONGVARCHAR --- lib/odbc/c_src/odbcserver.c | 22 ++++++++++++++++------ lib/odbc/c_src/odbcserver.h | 1 + lib/odbc/doc/src/databases.xml | 4 ++++ lib/odbc/doc/src/odbc.xml | 2 +- lib/odbc/src/odbc.erl | 3 +++ lib/odbc/src/odbc_internal.hrl | 1 + lib/odbc/test/odbc_data_type_SUITE.erl | 8 +++++--- 7 files changed, 31 insertions(+), 10 deletions(-) diff --git a/lib/odbc/c_src/odbcserver.c b/lib/odbc/c_src/odbcserver.c index 3dd7da08b9..11e311d72d 100644 --- a/lib/odbc/c_src/odbcserver.c +++ b/lib/odbc/c_src/odbcserver.c @@ -90,7 +90,7 @@ Datatype - USER_INT | USER_SMALL_INT | {USER_DECIMAL, Precision, Scale} | {USER_NMERIC, Precision, Scale} | {USER_CHAR, Max} | {USER_VARCHAR, Max} | {USER_WVARCHAR, Max} | {USER_FLOAT, Precision} | USER_REAL | USER_DOUBLE | - USER_TIMESTAMP + USER_TIMESTAMP | {USER_WLONGVARCHAR, Max} Scale - integer Precision - integer Max - integer @@ -1228,7 +1228,7 @@ static db_result_msg encode_column_name_list(SQLSMALLINT num_of_columns, &nullable))) DO_EXIT(EXIT_DESC); - if(sql_type == SQL_LONGVARCHAR || sql_type == SQL_LONGVARBINARY) + if(sql_type == SQL_LONGVARCHAR || sql_type == SQL_LONGVARBINARY || sql_type == SQL_WLONGVARCHAR) size = MAXCOLSIZE; (columns(state)[i]).type.decimal_digits = dec_digits; @@ -1537,6 +1537,11 @@ static void encode_data_type(SQLSMALLINT sql_type, SQLINTEGER size, case SQL_LONGVARCHAR: ei_x_encode_atom(&dynamic_buffer(state), "SQL_LONGVARCHAR"); break; + case SQL_WLONGVARCHAR: + ei_x_encode_tuple_header(&dynamic_buffer(state), 2); + ei_x_encode_atom(&dynamic_buffer(state), "sql_wlongvarchar"); + ei_x_encode_long(&dynamic_buffer(state), size); + break; case SQL_VARBINARY: ei_x_encode_atom(&dynamic_buffer(state), "SQL_VARBINARY"); break; @@ -2139,10 +2144,14 @@ static void init_param_column(param_array *params, byte *buffer, int *index, break; case USER_WCHAR: case USER_WVARCHAR: - if(user_type == USER_WCHAR) { - params->type.sql = SQL_WCHAR; - } else { - params->type.sql = SQL_WVARCHAR; + case USER_WLONGVARCHAR: + switch (user_type) { + case USER_WCHAR: + params->type.sql = SQL_WCHAR; break; + case USER_WVARCHAR: + params->type.sql = SQL_WVARCHAR; break; + default: + params->type.sql = SQL_WLONGVARCHAR; break; } ei_decode_long(buffer, index, &length); /* Max string length + string terminator */ @@ -2308,6 +2317,7 @@ static db_result_msg map_sql_2_c_column(db_column* column) break; case SQL_WCHAR: case SQL_WVARCHAR: + case SQL_WLONGVARCHAR: column -> type.len = (column -> type.col_size + 1)*sizeof(SQLWCHAR); column -> type.c = SQL_C_WCHAR; column -> type.strlen_or_indptr = SQL_NTS; diff --git a/lib/odbc/c_src/odbcserver.h b/lib/odbc/c_src/odbcserver.h index 3e2b22ab7d..314fbf32c6 100644 --- a/lib/odbc/c_src/odbcserver.h +++ b/lib/odbc/c_src/odbcserver.h @@ -115,6 +115,7 @@ #define USER_WCHAR 12 #define USER_WVARCHAR 13 #define USER_TIMESTAMP 14 +#define USER_WLONGVARCHAR 15 /*------------------------ TYPDEFS ----------------------------------*/ diff --git a/lib/odbc/doc/src/databases.xml b/lib/odbc/doc/src/databases.xml index a6ba0e5245..09f5a5af5b 100644 --- a/lib/odbc/doc/src/databases.xml +++ b/lib/odbc/doc/src/databases.xml @@ -204,6 +204,10 @@ when p >= 16 SQL_LONGVARCHAR String | Binary (configurable) + + SQL_WLONGVARCHAR(size) + Unicode binary encoded as UTF16 little endian. + SQL_BINARY String | Binary (configurable) diff --git a/lib/odbc/doc/src/odbc.xml b/lib/odbc/doc/src/odbc.xml index 70d8cfbe22..11ca97f743 100644 --- a/lib/odbc/doc/src/odbc.xml +++ b/lib/odbc/doc/src/odbc.xml @@ -102,7 +102,7 @@ {sql_decimal, precision(), scale()} | {sql_numeric, precision(), scale()} | {sql_char, size()} | {sql_wchar, size()} | {sql_varchar, size()} | {sql_wvarchar, size()}| {sql_float, precision()} | - {sql_float, precision()} | sql_real | sql_double | sql_bit | atom() + {sql_wlongvarchar, size()} | {sql_float, precision()} | sql_real | sql_double | sql_bit | atom() precision() = integer() diff --git a/lib/odbc/src/odbc.erl b/lib/odbc/src/odbc.erl index 2634450d4a..68497292db 100644 --- a/lib/odbc/src/odbc.erl +++ b/lib/odbc/src/odbc.erl @@ -925,6 +925,9 @@ fix_params({{sql_wchar, Max}, InOut, Values}) -> fix_params({{sql_wvarchar, Max}, InOut, Values}) -> NewValues = string_terminate(Values), {?USER_WVARCHAR, Max, fix_inout(InOut), NewValues}; +fix_params({{sql_wlongvarchar, Max}, InOut, Values}) -> + NewValues = string_terminate(Values), + {?USER_WLONGVARCHAR, Max, fix_inout(InOut), NewValues}; fix_params({{sql_float, Precision}, InOut, Values}) -> {?USER_FLOAT, Precision, fix_inout(InOut), Values}; fix_params({sql_real, InOut, Values}) -> diff --git a/lib/odbc/src/odbc_internal.hrl b/lib/odbc/src/odbc_internal.hrl index aa60120f9a..c0e7d9657b 100644 --- a/lib/odbc/src/odbc_internal.hrl +++ b/lib/odbc/src/odbc_internal.hrl @@ -72,6 +72,7 @@ -define(USER_WCHAR, 12). -define(USER_WVARCHAR, 13). -define(USER_TIMESTAMP, 14). +-define(USER_WLONGVARCHAR, 15). %% INPUT & OUTPUT TYPE -define(IN, 0). diff --git a/lib/odbc/test/odbc_data_type_SUITE.erl b/lib/odbc/test/odbc_data_type_SUITE.erl index 84c99e183b..63aa32496c 100644 --- a/lib/odbc/test/odbc_data_type_SUITE.erl +++ b/lib/odbc/test/odbc_data_type_SUITE.erl @@ -1461,7 +1461,9 @@ unicode(Config) when is_list(Config) -> case ?RDBMS of sqlserver -> - w_char_support_win(Ref, Table, Latin1Data); + w_char_support_win(Ref, Table, Latin1Data, sql_wvarchar), + {updated, _} = odbc:sql_query(Ref, "DROP TABLE " ++ Table), + w_char_support_win(Ref, Table, Latin1Data, sql_wlongvarchar); postgres -> direct_utf8(Ref, Table, Latin1Data); mysql -> @@ -1470,7 +1472,7 @@ unicode(Config) when is_list(Config) -> {skip, "not currently supported"} end. -w_char_support_win(Ref, Table, Latin1Data) -> +w_char_support_win(Ref, Table, Latin1Data, CharType) -> UnicodeIn = lists:map(fun(S) -> unicode:characters_to_binary(S,latin1,{utf16,little}) end, @@ -1479,7 +1481,7 @@ w_char_support_win(Ref, Table, Latin1Data) -> test_server:format("UnicodeIn (utf 16): ~p ~n",[UnicodeIn]), {updated, _} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++ "(FIELD) values(?)", - [{{sql_wvarchar,50},UnicodeIn}]), + [{{CharType,50},UnicodeIn}]), {selected,_,UnicodeOut} = odbc:sql_query(Ref,"SELECT * FROM " ++ Table), -- cgit v1.2.3 From 8cc6a0498ae74d6e2bb3132ff2f420c2e0401fad Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Mon, 13 Jun 2011 15:06:35 +0200 Subject: Rewrote test case so that it works --- lib/odbc/test/mysql.erl | 4 - lib/odbc/test/odbc_data_type_SUITE.erl | 154 ++++++++++++++++++++++----------- lib/odbc/test/oracle.erl | 4 - lib/odbc/test/postgres.erl | 4 - lib/odbc/test/sqlserver.erl | 4 - 5 files changed, 105 insertions(+), 65 deletions(-) diff --git a/lib/odbc/test/mysql.erl b/lib/odbc/test/mysql.erl index 76ffd3ecc9..49068c4356 100644 --- a/lib/odbc/test/mysql.erl +++ b/lib/odbc/test/mysql.erl @@ -97,10 +97,6 @@ text_max() -> create_text_table() -> " (FIELD text)". -%------------------------------------------------------------------------- -create_unicode_table() -> - " (FIELD text)". - %------------------------------------------------------------------------- create_timestamp_table() -> " (FIELD TIMESTAMP)". diff --git a/lib/odbc/test/odbc_data_type_SUITE.erl b/lib/odbc/test/odbc_data_type_SUITE.erl index 63aa32496c..099ae0aa7d 100644 --- a/lib/odbc/test/odbc_data_type_SUITE.erl +++ b/lib/odbc/test/odbc_data_type_SUITE.erl @@ -45,7 +45,7 @@ all() -> case odbc_test_lib:odbc_check() of ok -> [{group, char},{group, fixed_char}, {group, binary_char}, - {group, fixed_binary_char}, + {group, fixed_binary_char}, {group, unicode}, {group, int}, {group, floats}, {group, dec_and_num}, timestamp]; Other -> {skip, Other} @@ -55,18 +55,18 @@ groups() -> [{char, [], [varchar_lower_limit, varchar_upper_limit, varchar_no_padding, - text_lower_limit, text_upper_limit, unicode]}, + text_lower_limit, text_upper_limit]}, {fixed_char, [], [char_fixed_lower_limit, char_fixed_upper_limit, char_fixed_padding]}, {binary_char, [], [binary_varchar_lower_limit, binary_varchar_upper_limit, binary_varchar_no_padding, - binary_text_lower_limit, binary_text_upper_limit, - unicode]}, + binary_text_lower_limit, binary_text_upper_limit]}, {fixed_binary_char, [], [binary_char_fixed_lower_limit, binary_char_fixed_upper_limit, binary_char_fixed_padding]}, + {unicode, [], [utf8, nchar, nvarchar]}, {int, [], [tiny_int_lower_limit, tiny_int_upper_limit, small_int_lower_limit, small_int_upper_limit, @@ -88,14 +88,24 @@ init_per_group(GroupName, Config) when GroupName == fixed_char; Config end; +init_per_group(unicode, Config) -> + %% Uses parameterized queries + case {os:type(), erlang:system_info(wordsize)} of + {{unix, _}, 4} -> + Config; + {{unix, _}, _} -> + {skip, "Not supported by driver"}; + _ -> + Config + end; + + init_per_group(_GroupName, Config) -> Config. end_per_group(_GroupName, Config) -> Config. - - %%-------------------------------------------------------------------- %% Function: init_per_suite(Config) -> Config %% Config - [tuple()] @@ -164,6 +174,16 @@ init_per_testcase(param_insert_tiny_int = Case, Config) -> false -> {skip, "Not supported by driver"} end; + +init_per_testcase(Case, Config) when Case == nchar; + Case == nvarchar -> + case ?RDBMS of + sqlserver -> + common_init_per_testcase(Case, Config); + _ -> + {skip, "Not supported by driver"} + end; + init_per_testcase(Case, Config) -> common_init_per_testcase(Case, Config). @@ -173,7 +193,9 @@ common_init_per_testcase(Case, Config) -> "binary" ++ _ -> {ok, Ref} = odbc:connect(?RDBMS:connection_string(), [{binary_strings, on}] ++ PlatformOptions); - "unicode" -> + LCase when LCase == "utf8"; + LCase == "nchar"; + LCase == "nvarchar" -> {ok, Ref} = odbc:connect(?RDBMS:connection_string(), [{binary_strings, on}] ++ PlatformOptions); _ -> @@ -1435,17 +1457,16 @@ num_bignum(Config) when is_list(Config) -> ["FIELD"] = odbc_test_lib:to_upper(Fields1). %%------------------------------------------------------------------------ -unicode(doc) -> +utf8(doc) -> ["Test unicode support"]; -unicode(suit) -> +utf8(suit) -> []; -unicode(Config) when is_list(Config) -> +utf8(Config) when is_list(Config) -> Ref = ?config(connection_ref, Config), Table = ?config(tableName, Config), - {updated, _} = % Value == 0 || -1 driver dependent! - odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++ - ?RDBMS:create_unicode_table()), + odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++ "(FIELD text)"), + Latin1Data = ["ÖÄÅÄÖÅäöå", "testasdf", "Row 3", @@ -1458,43 +1479,7 @@ unicode(Config) when is_list(Config) -> "Row 10", "Row 11", "Row 12"], - - case ?RDBMS of - sqlserver -> - w_char_support_win(Ref, Table, Latin1Data, sql_wvarchar), - {updated, _} = odbc:sql_query(Ref, "DROP TABLE " ++ Table), - w_char_support_win(Ref, Table, Latin1Data, sql_wlongvarchar); - postgres -> - direct_utf8(Ref, Table, Latin1Data); - mysql -> - direct_utf8(Ref, Table, Latin1Data); - oracle -> - {skip, "not currently supported"} - end. - -w_char_support_win(Ref, Table, Latin1Data, CharType) -> - UnicodeIn = lists:map(fun(S) -> - unicode:characters_to_binary(S,latin1,{utf16,little}) - end, - Latin1Data), - - test_server:format("UnicodeIn (utf 16): ~p ~n",[UnicodeIn]), - - {updated, _} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++ "(FIELD) values(?)", - [{{CharType,50},UnicodeIn}]), - - {selected,_,UnicodeOut} = odbc:sql_query(Ref,"SELECT * FROM " ++ Table), - - test_server:format("UnicodeOut: ~p~n", [UnicodeOut]), - Result = lists:map(fun({Unicode}) -> - unicode:characters_to_list(Unicode,{utf16,little}) - end, - UnicodeOut), - Latin1Data = Result. - - -direct_utf8(Ref, Table, Latin1Data) -> UnicodeIn = lists:map(fun(String) -> unicode:characters_to_binary(String,latin1,utf8) end, @@ -1515,6 +1500,37 @@ direct_utf8(Ref, Table, Latin1Data) -> test_server:format("Result: ~p ~n", [Result]), Latin1Data = Result. +%%------------------------------------------------------------------------ + +nchar(doc) -> + ["Test unicode nchar support in sqlserver"]; +nchar(suit) -> + []; +nchar(Config) when is_list(Config) -> + Ref = ?config(connection_ref, Config), + Table = ?config(tableName, Config), + + {updated, _} = % Value == 0 || -1 driver dependent! + odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++ + "(FIELD nchar(50))"), + + w_char_support(Ref, Table, sql_wvarchar, 50). + +%%------------------------------------------------------------------------ + +nvarchar(doc) -> + ["Test 'unicode' nvarchar support"]; +nvarchar(suit) -> + []; +nvarchar(Config) when is_list(Config) -> + Ref = ?config(connection_ref, Config), + Table = ?config(tableName, Config), + + {updated, _} = % Value == 0 || -1 driver dependent! + odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++ + "(FIELD nvarchar(50))"), + + w_char_support(Ref, Table, sql_wlongvarchar, 50). %%------------------------------------------------------------------------ timestamp(doc) -> @@ -1543,3 +1559,43 @@ timestamp(Config) when is_list(Config) -> TimeStamps = lists:map(fun(Value) -> {Value} end, Data), {selected,_, TimeStamps} = odbc:sql_query(Ref, "SELECT * FROM " ++ Table). +%%------------------------------------------------------------------------ + +w_char_support(Ref, Table, CharType, Size) -> + Latin1Data = ["ÖÄÅÄÖÅäöå", + "testasdf", + "Row 3", + "Row 4", + "Row 5", + "Row 6", + "Row 7", + "Row 8", + "Row 9", + "Row 10", + "Row 11", + "Row 12"], + + UnicodeIn = lists:map(fun(S) -> + unicode:characters_to_binary(S,latin1,{utf16,little}) + end, + Latin1Data), + + test_server:format("UnicodeIn (utf 16): ~p ~n",[UnicodeIn]), + + {updated, _} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++ "(FIELD) values(?)", + [{{CharType, Size},UnicodeIn}]), + + {selected,_,UnicodeOut} = odbc:sql_query(Ref,"SELECT * FROM " ++ Table), + + test_server:format("UnicodeOut: ~p~n", [UnicodeOut]), + + PadResult = lists:map(fun({Unicode}) -> + unicode:characters_to_list(Unicode,{utf16,little}) + end, + UnicodeOut), + + test_server:format("Result: ~p~n", [PadResult]), + + Result = lists:map(fun(Str) -> string:strip(Str) end, PadResult), + + Latin1Data = Result. diff --git a/lib/odbc/test/oracle.erl b/lib/odbc/test/oracle.erl index 786280701d..d74863d8c1 100644 --- a/lib/odbc/test/oracle.erl +++ b/lib/odbc/test/oracle.erl @@ -107,10 +107,6 @@ text_max() -> create_text_table() -> " (FIELD long)". %Oracle long is variable length char data -%------------------------------------------------------------------------- -create_unicode_table() -> - " (FIELD nvarchar(50))". - %------------------------------------------------------------------------- create_timestamp_table() -> " (FIELD DATETIME)". diff --git a/lib/odbc/test/postgres.erl b/lib/odbc/test/postgres.erl index 9c7eed271f..26a2913d46 100644 --- a/lib/odbc/test/postgres.erl +++ b/lib/odbc/test/postgres.erl @@ -134,10 +134,6 @@ text_max() -> create_text_table() -> " (FIELD text)". -%------------------------------------------------------------------------- -create_unicode_table() -> - " (FIELD text)". - %------------------------------------------------------------------------- create_timestamp_table() -> " (FIELD TIMESTAMP)". diff --git a/lib/odbc/test/sqlserver.erl b/lib/odbc/test/sqlserver.erl index 13930cd5ae..59252d4276 100644 --- a/lib/odbc/test/sqlserver.erl +++ b/lib/odbc/test/sqlserver.erl @@ -122,10 +122,6 @@ text_max() -> create_text_table() -> " (FIELD text)". -%------------------------------------------------------------------------- -create_unicode_table() -> - " (FIELD nvarchar(50))". - %------------------------------------------------------------------------- create_timestamp_table() -> " (FIELD DATETIME)". -- cgit v1.2.3