From 065a54e7a0be98e8dc9842616b267c0e8fbeb318 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Tue, 9 Mar 2010 13:11:42 +0000 Subject: OTP-7452 Support for SQL_WCHAR, SQL_WVARCHAR and strings as binaries ODBC now handles the types SQL_WCHAR and SQL_WVARCHAR. ODBC also has a new connection option to return all strings as binaries and also expect strings to be binaries in the param_query function. This provides some but not a full unicode support. --- lib/odbc/AUTHORS | 3 +- lib/odbc/c_src/odbcserver.c | 144 ++++++++++++++++++++++++++++-------- lib/odbc/c_src/odbcserver.h | 14 ++-- lib/odbc/doc/src/databases.xml | 26 ++++--- lib/odbc/doc/src/error_handling.xml | 16 +--- lib/odbc/doc/src/notes.xml | 19 +++++ lib/odbc/doc/src/odbc.xml | 41 ++++++---- lib/odbc/src/odbc.erl | 57 ++++++++------ lib/odbc/src/odbc_internal.hrl | 12 +-- lib/odbc/vsn.mk | 5 +- 10 files changed, 233 insertions(+), 104 deletions(-) diff --git a/lib/odbc/AUTHORS b/lib/odbc/AUTHORS index d1ed32bde1..22813f36ce 100644 --- a/lib/odbc/AUTHORS +++ b/lib/odbc/AUTHORS @@ -5,4 +5,5 @@ Original Authors: Contributors: Scott Lystig Fritchie - input/output variables for stored procedures -willi@talk24.com - Some 64 bits adjustments \ No newline at end of file +willi@talk24.com - Some 64 bits adjustments +Juhani Ränkimies - SQL_WCHAR and SQL_WVARCHAR support \ No newline at end of file diff --git a/lib/odbc/c_src/odbcserver.c b/lib/odbc/c_src/odbcserver.c index aaaea20a10..5865cddcda 100644 --- a/lib/odbc/c_src/odbcserver.c +++ b/lib/odbc/c_src/odbcserver.c @@ -59,7 +59,7 @@ they are converted to string values. [?OPEN_CONNECTION, C_AutoCommitMode, C_TraceDriver, C_SrollableCursors, - C_TupelRow, ConnectionStr] + C_TupelRow, BinaryStrings, ConnectionStr] [?CLOSE_CONNECTION] [?COMMIT_TRANSACTION, CommitMode] [?QUERY, SQLQuery] @@ -76,6 +76,7 @@ C_TraceDriver - ?ON | ?OFF C_SrollableCursors - ?ON | ?OFF C_TupelRow - - ?ON | ?OFF + BinaryStrings - ?ON | ?OFF ConnectionStr - String CommitMode - ?COMMIT | ?ROLLBACK SQLQuery - String @@ -88,7 +89,7 @@ InOrOut = [ERL_ODBC_IN | ERL_ODBC_OUT | ERL_ODBC_INOUT] Datatype - USER_INT | USER_SMALL_INT | {USER_DECIMAL, Precision, Scale} | {USER_NMERIC, Precision, Scale} | {USER_CHAR, Max} | {USER_VARCHAR, Max} | - {USER_FLOAT, Precision} | USER_REAL | USER_DOUBLE + {USER_WVARCHAR, Max} | {USER_FLOAT, Precision} | USER_REAL | USER_DOUBLE Scale - integer Precision - integer Max - integer @@ -173,7 +174,7 @@ static void encode_column_dyn(db_column column, int column_nr, db_state *state); static void encode_data_type(SQLINTEGER sql_type, SQLINTEGER size, SQLSMALLINT decimal_digits, db_state *state); -static Boolean decode_params(byte *buffer, int *index, param_array **params, +static Boolean decode_params(db_state *state, byte *buffer, int *index, param_array **params, int i, int j); /*------------- Erlang port communication functions ----------------------*/ @@ -433,26 +434,33 @@ static db_result_msg db_connect(byte *args, db_state *state) diagnos diagnos; byte *connStrIn; int erl_auto_commit_mode, erl_trace_driver, - use_srollable_cursors, tuple_row_state; + use_srollable_cursors, tuple_row_state, binary_strings; erl_auto_commit_mode = args[0]; erl_trace_driver = args[1]; use_srollable_cursors = args[2]; tuple_row_state = args[3]; - connStrIn = args + 4 * sizeof(byte); + binary_strings = args[4]; + connStrIn = args + 5 * sizeof(byte); if(tuple_row_state == ON) { - tuple_row(state) = TRUE; + tuple_row(state) = TRUE; } else { - tuple_row(state) = FALSE; + tuple_row(state) = FALSE; } - + + if(binary_strings == ON) { + binary_strings(state) = TRUE; + } else { + binary_strings(state) = FALSE; + } + if(use_srollable_cursors == ON) { - use_srollable_cursors(state) = TRUE; + use_srollable_cursors(state) = TRUE; } else { - use_srollable_cursors(state) = FALSE; + use_srollable_cursors(state) = FALSE; } - + init_driver(erl_auto_commit_mode, erl_trace_driver, state); connlen = (SQLSMALLINT)strlen((const char*)connStrIn); @@ -1102,8 +1110,21 @@ static db_result_msg encode_out_params(db_state *state, void* values = retrive_param_values(&column); switch(column.type.c) { case SQL_C_CHAR: - ei_x_encode_string(&dynamic_buffer(state), ((char*)values)+j*column.type.len); - break; + if binary_strings(state) { + ei_x_encode_binary(&dynamic_buffer(state), + ((char*)values)+j*column.type.len, + (column.type.strlen_or_indptr_array[j])); + } + else { + ei_x_encode_string(&dynamic_buffer(state), + ((char*)values)+j*column.type.len); + } + break; + case SQL_C_WCHAR: + ei_x_encode_binary(&dynamic_buffer(state), + ((char*)values)+j*column.type.len, + (column.type.strlen_or_indptr_array[j])); + break; case SQL_C_SLONG: ei_x_encode_long(&dynamic_buffer(state), ((long*)values)[j]); break; @@ -1365,7 +1386,16 @@ static void encode_column_dyn(db_column column, int column_nr, } else { switch(column.type.c) { case SQL_C_CHAR: - ei_x_encode_string(&dynamic_buffer(state), column.buffer); + if binary_strings(state) { + ei_x_encode_binary(&dynamic_buffer(state), + column.buffer,column.type.strlen_or_indptr); + } else { + ei_x_encode_string(&dynamic_buffer(state), column.buffer); + } + break; + case SQL_C_WCHAR: + ei_x_encode_binary(&dynamic_buffer(state), + column.buffer,column.type.strlen_or_indptr); break; case SQL_C_SLONG: ei_x_encode_long(&dynamic_buffer(state), @@ -1379,9 +1409,14 @@ static void encode_column_dyn(db_column column, int column_nr, ei_x_encode_atom(&dynamic_buffer(state), column.buffer[0]?"true":"false"); break; - case SQL_C_BINARY: + case SQL_C_BINARY: column = retrive_binary_data(column, column_nr, state); - ei_x_encode_string(&dynamic_buffer(state), (void *)column.buffer); + if binary_strings(state) { + ei_x_encode_binary(&dynamic_buffer(state), + column.buffer,column.type.strlen_or_indptr); + } else { + ei_x_encode_string(&dynamic_buffer(state), (void *)column.buffer); + } break; default: ei_x_encode_atom(&dynamic_buffer(state), "error"); @@ -1404,6 +1439,16 @@ static void encode_data_type(SQLINTEGER sql_type, SQLINTEGER size, ei_x_encode_atom(&dynamic_buffer(state), "sql_varchar"); ei_x_encode_long(&dynamic_buffer(state), size); break; + case SQL_WCHAR: + ei_x_encode_tuple_header(&dynamic_buffer(state), 2); + ei_x_encode_atom(&dynamic_buffer(state), "sql_wchar"); + ei_x_encode_long(&dynamic_buffer(state), size); + break; + case SQL_WVARCHAR: + ei_x_encode_tuple_header(&dynamic_buffer(state), 2); + ei_x_encode_atom(&dynamic_buffer(state), "sql_wvarchar"); + ei_x_encode_long(&dynamic_buffer(state), size); + break; case SQL_NUMERIC: ei_x_encode_tuple_header(&dynamic_buffer(state), 3); ei_x_encode_atom(&dynamic_buffer(state), "sql_numeric"); @@ -1492,7 +1537,7 @@ static void encode_data_type(SQLINTEGER sql_type, SQLINTEGER size, } } -static Boolean decode_params(byte *buffer, int *index, param_array **params, +static Boolean decode_params(db_state *state, byte *buffer, int *index, param_array **params, int i, int j) { int erl_type, size; @@ -1504,15 +1549,25 @@ static Boolean decode_params(byte *buffer, int *index, param_array **params, switch (param->type.c) { case SQL_C_CHAR: - if(erl_type != ERL_STRING_EXT) { - return FALSE; - } - - ei_decode_string(buffer, index, &(param->values.string[param->offset])); - param->offset += param->type.len; - param->type.strlen_or_indptr_array[j] = SQL_NTS; + if (binary_strings(state)) { + ei_decode_binary(buffer, index, + &(param->values.string[param->offset]), &bin_size); + param->offset += param->type.len; + param->type.strlen_or_indptr_array[j] = SQL_NTS; + } else { + if(erl_type != ERL_STRING_EXT) { + return FALSE; + } + ei_decode_string(buffer, index, &(param->values.string[param->offset])); + param->offset += param->type.len; + param->type.strlen_or_indptr_array[j] = SQL_NTS; + } + break; + case SQL_C_WCHAR: + ei_decode_binary(buffer, index, &(param->values.string[param->offset]), &bin_size); + param->offset += param->type.len; + param->type.strlen_or_indptr_array[j] = SQL_NTS; break; - case SQL_C_SLONG: if(!((erl_type == ERL_SMALL_INTEGER_EXT) || (erl_type == ERL_INTEGER_EXT) || @@ -2052,6 +2107,24 @@ static void init_param_column(param_array *params, byte *buffer, int *index, (byte *)safe_malloc(num_param_values * sizeof(byte)* params->type.len); + break; + case USER_WCHAR: + case USER_WVARCHAR: + if(user_type == USER_WCHAR) { + params->type.sql = SQL_WCHAR; + } else { + params->type.sql = SQL_WVARCHAR; + } + ei_decode_long(buffer, index, &length); + /* Max string length + string terminator */ + params->type.len = (length+1)*sizeof(SQLWCHAR); + params->type.c = SQL_C_WCHAR; + params->type.col_size = (SQLUINTEGER)length; + params->type.strlen_or_indptr_array = + (SQLLEN*)safe_malloc(num_param_values * sizeof(SQLINTEGER)); + params->values.string = + (byte *)safe_malloc(num_param_values * sizeof(byte) * params->type.len); + break; case USER_FLOAT: params->type.sql = SQL_FLOAT; @@ -2190,11 +2263,17 @@ static db_result_msg map_sql_2_c_column(db_column* column) case SQL_LONGVARCHAR: case SQL_VARBINARY: case SQL_LONGVARBINARY: - column -> type.len = (column -> type.col_size) + - /* Make place for NULL termination */ - sizeof(byte); - column -> type.c = SQL_C_CHAR; - column -> type.strlen_or_indptr = SQL_NTS; + column -> type.len = (column -> type.col_size) + + /* Make place for NULL termination */ + sizeof(byte); + column -> type.c = SQL_C_CHAR; + column -> type.strlen_or_indptr = SQL_NTS; + break; + case SQL_WCHAR: + case SQL_WVARCHAR: + column -> type.len = (column -> type.col_size + 1)*sizeof(SQLWCHAR); + column -> type.c = SQL_C_WCHAR; + column -> type.strlen_or_indptr = SQL_NTS; break; case SQL_NUMERIC: case SQL_DECIMAL: @@ -2280,7 +2359,7 @@ static param_array * bind_parameter_arrays(byte *buffer, int *index, } for (j = 0; j < num_param_values; j++) { - if(!decode_params(buffer, index, ¶ms, i, j)) { + if(!decode_params(state, buffer, index, ¶ms, i, j)) { /* An input parameter was not of the expected type */ free_params(¶ms, i); return params; @@ -2309,7 +2388,8 @@ static void * retrive_param_values(param_array *Param) { switch(Param->type.c) { case SQL_C_CHAR: - return (void *)Param->values.string; + case SQL_C_WCHAR: + return (void *)Param->values.string; case SQL_C_SLONG: return (void *)Param->values.integer; case SQL_C_DOUBLE: diff --git a/lib/odbc/c_src/odbcserver.h b/lib/odbc/c_src/odbcserver.h index ccd694a985..3b5a2b4d4d 100644 --- a/lib/odbc/c_src/odbcserver.h +++ b/lib/odbc/c_src/odbcserver.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2002-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2002-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% * @@ -111,6 +111,8 @@ #define USER_DOUBLE 9 #define USER_BOOLEAN 10 #define USER_TINY_INT 11 +#define USER_WCHAR 12 +#define USER_WVARCHAR 13 /*------------------------ TYPDEFS ----------------------------------*/ @@ -170,6 +172,7 @@ typedef struct { Boolean associated_result_set; Boolean use_srollable_cursors; Boolean tuple_row; + Boolean binary_strings; Boolean exists_more_result_sets; Boolean param_query; Boolean out_params; @@ -188,6 +191,7 @@ typedef enum { #define associated_result_set(db_state) (db_state -> associated_result_set) #define use_srollable_cursors(db_state) (db_state -> use_srollable_cursors) #define tuple_row(db_state) (db_state -> tuple_row) +#define binary_strings(db_state) (db_state -> binary_strings) #define exists_more_result_sets(db_state) (db_state -> exists_more_result_sets) #define param_query(db_state) (db_state -> param_query) #define out_params(db_state) (db_state -> out_params) diff --git a/lib/odbc/doc/src/databases.xml b/lib/odbc/doc/src/databases.xml index c06327e11d..2c1b932084 100644 --- a/lib/odbc/doc/src/databases.xml +++ b/lib/odbc/doc/src/databases.xml @@ -4,7 +4,7 @@
- 20022009 + 20022010 Ericsson AB. All Rights Reserved. @@ -13,12 +13,12 @@ compliance with the License. You should have received a copy of the Erlang Public License along with this software. If not, it can be retrieved online at http://www.erlang.org/. - + Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. - + Databases @@ -117,7 +117,11 @@ SQL_CHAR(size) - String + String | Binary (configurable) + + + SQL_WCHAR(size) + Unicode binary encoded as UTF16 little endian. SQL_NUMERIC(p,s)

@@ -171,7 +175,11 @@ when p >= 16
SQL_VARCHAR(size) - String + String | Binary (configurable) + + + SQL_WVARCHAR(size) + Unicode binary encoded as UTF16 little endian. Mapping of ODBC data types to the Erlang data types returned to the Erlang application. @@ -194,19 +202,19 @@ when p >= 16 SQL_LONGVARCHAR - String + String | Binary (configurable) SQL_BINARY - String + String | Binary (configurable) SQL_VARBINARY - String + String | Binary (configurable) SQL_LONGVARBINARY - String + String | Binary (configurable) SQL_TINYINT diff --git a/lib/odbc/doc/src/error_handling.xml b/lib/odbc/doc/src/error_handling.xml index 26ad7f9848..c30acc5fdc 100644 --- a/lib/odbc/doc/src/error_handling.xml +++ b/lib/odbc/doc/src/error_handling.xml @@ -4,7 +4,7 @@
- 20032009 + 20032010 Ericsson AB. All Rights Reserved. @@ -13,12 +13,12 @@ compliance with the License. You should have received a copy of the Erlang Public License along with this software. If not, it can be retrieved online at http://www.erlang.org/. - + Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. - + Error handling @@ -126,15 +126,7 @@ c-process will exit. If the c-process crashes/exits it will bring the erlang-process down too and vice versa i.e. the connection is terminated.

- -

The function connect/2 will start the odbc application if - that is not already done. In this case a supervisor information - log will be produced stating that the odbc application was started - as a temporary application. It is really the responsibility of the - application that uses the API too make sure it is started in the - desired way.

-
- +
Error types

The types of errors that may occur can be divide into the diff --git a/lib/odbc/doc/src/notes.xml b/lib/odbc/doc/src/notes.xml index 99584efec9..29fed0e286 100644 --- a/lib/odbc/doc/src/notes.xml +++ b/lib/odbc/doc/src/notes.xml @@ -30,6 +30,25 @@

This document describes the changes made to the odbc application.

+ +
ODBC 2.10.8 + +
Improvements and New Features + + +

+ ODBC now handles the types SQL_WCHAR and SQL_WVARCHAR. + ODBC also has a new connection option to return all + strings as binaries and also expect strings to be + binaries in the param_query function. This provides some + but not a full unicode support.

+

+ Own Id: OTP-7452

+
+
+
+ +
ODBC 2.10.7 diff --git a/lib/odbc/doc/src/odbc.xml b/lib/odbc/doc/src/odbc.xml index 450531c81c..3efbac8dd4 100644 --- a/lib/odbc/doc/src/odbc.xml +++ b/lib/odbc/doc/src/odbc.xml @@ -4,7 +4,7 @@
- 19992009 + 19992010 Ericsson AB. All Rights Reserved. @@ -13,12 +13,12 @@ compliance with the License. You should have received a copy of the Erlang Public License along with this software. If not, it can be retrieved online at http://www.erlang.org/. - + Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. - + odbc @@ -101,7 +101,7 @@ odbc_data_type() = sql_integer | sql_smallint | sql_tinyint | {sql_decimal, precision(), scale()} | {sql_numeric, precision(), scale()} | - {sql_char, size()} | {sql_varchar, size()} | {sql_float, precision()} | + {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() @@ -141,16 +141,9 @@ An example of a connection string:"DSN=sql-server;UID=aladdin;PWD=sesame"where DSN is your ODBC Data Source Name, UID is a database user id and PWD is the password for that user. These are usually the attributes required in the connection string, but some drivers have other driver specific attributes, for example"DSN=Oracle8;DBQ=gandalf;UID=aladdin;PWD=sesame"where DBQ is your TNSNAMES.ORA entry name e.g. some Oracle specific configuration attribute. Options = [] | [option()] All options has default values. - option() = {auto_commit, auto_commit_mode()} | {timeout, milliseconds()} | {tuple_row, tuple_mode()} | {scrollable_cursors, use_scrollable_cursors()} | {trace_driver, trace_mode()} - The default timeout is infinity - auto_commit_mode() = on | off - Default is on. - tuple_mode() = on | off - Default is on. The option is deprecated and should not be used in new code. - use_scrollable_cursors() = on | off - Default is on. - trace_mode() = on | off - Default is off. + option() = {auto_commit, on | off} | {timeout, milliseconds()} + | {binary_strings, on | off} | {tuple_row, on | off} | {scrollable_cursors, on | off} | + {trace_driver, on | off} Ref = connection_reference() - should be used to access the connection. Reason = port_program_executable_not_found | common_reason() @@ -161,21 +154,36 @@ to handle the connection. These processes will terminate if the process that created the connection dies or if you call disconnect/1.

-

If automatic commit mode is turned on, each query will be + +

If automatic commit mode is turned on, each query will be considered as an individual transaction and will be automatically committed after it has been executed. If you want more than one query to be part of the same transaction the automatic commit mode should be turned off. Then you will have to call commit/3 explicitly to end a transaction.

+ +

The default timeout is infinity

+ +

>If the option binary_strings is turned on all strings + will be returned as binaries and strings inputed to + param_query will be expected to be binaries. The user needs + to ensure that the binary is in an encoding that the + database expects. By default this option is turned off.

+

As default result sets are returned as a lists of tuples. The TupleMode option still exists to keep some degree of backwards compatibility. If the option is set to off, result sets will be returned as a lists of lists instead of a lists of tuples.

+

Scrollable cursors are nice but causes some overhead. For some connections speed might be more important than flexible data access and then you can disable scrollable cursor for a - connection, limiting the API but gaining speed

+ connection, limiting the API but gaining speed.

+ +

Turning the scrollable_cursors option off is noted + to make old odbc-drivers able to connect that will otherwhise fail.

+

If trace mode is turned on this tells the ODBC driver to write a trace log to the file SQL.LOG that is placed in the current directory of the erlang emulator. This information @@ -183,6 +191,7 @@ erlang ODBC application, and it might be relevant for you to send this file to our support. Otherwise you will probably not have much use of this.

+

For more information about the ConnectStr see description of the function SQLDriverConnect in [1].

diff --git a/lib/odbc/src/odbc.erl b/lib/odbc/src/odbc.erl index 8178accf6d..f8914639e6 100644 --- a/lib/odbc/src/odbc.erl +++ b/lib/odbc/src/odbc.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1999-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1999-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -186,7 +186,7 @@ sql_query(ConnectionReference, SQLQuery, infinity) when call(ConnectionReference, {sql_query, ODBCCmd}, infinity); sql_query(ConnectionReference, SQLQuery, TimeOut) - when is_pid(ConnectionReference),is_list(SQLQuery),integer(TimeOut),TimeOut>0 -> + when is_pid(ConnectionReference),is_list(SQLQuery),is_integer(TimeOut),TimeOut>0 -> ODBCCmd = [?QUERY, SQLQuery], call(ConnectionReference, {sql_query, ODBCCmd}, TimeOut). @@ -397,7 +397,7 @@ describe_table(ConnectionReference, Table, infinity) when call(ConnectionReference, {describe_table, ODBCCmd}, infinity); describe_table(ConnectionReference, Table, TimeOut) - when is_pid(ConnectionReference),is_list(Table),integer(TimeOut),TimeOut>0 -> + when is_pid(ConnectionReference),is_list(Table),is_integer(TimeOut),TimeOut>0 -> ODBCCmd = [?DESCRIBE, "SELECT * FROM " ++ Table], call(ConnectionReference, {describe_table, ODBCCmd}, TimeOut). %%%========================================================================= @@ -801,9 +801,11 @@ connect(ConnectionReferense, ConnectionStr, Options) -> connection_config(scrollable_cursors, Options), {C_TupleRow, _} = connection_config(tuple_row, Options), + {BinaryStrings, _} = connection_config(binary_strings, Options), + ODBCCmd = [?OPEN_CONNECTION, C_AutoCommitMode, C_TraceDriver, - C_SrollableCursors, C_TupleRow, ConnectionStr], + C_SrollableCursors, C_TupleRow, BinaryStrings, ConnectionStr], %% Send request, to open a database connection, to the control process. case call(ConnectionReferense, @@ -848,7 +850,9 @@ connection_default(trace_driver) -> {?OFF, off}; connection_default(scrollable_cursors) -> - {?ON, on}. + {?ON, on}; +connection_default(binary_strings) -> + {?OFF, off}. %%------------------------------------------------------------------------- call(ConnectionReference, Msg, Timeout) -> @@ -858,7 +862,7 @@ call(ConnectionReference, Msg, Timeout) -> case Result of %% Normal case, the result from the port-program has directly %% been forwarded to the client - Binary when binary(Binary) -> + Binary when is_binary(Binary) -> decode(Binary); timeout -> exit(timeout); @@ -908,21 +912,17 @@ fix_params({{sql_numeric, Precision, 0}, InOut, fix_params({{sql_numeric, Precision, Scale}, InOut, Values}) -> {?USER_NUMERIC, Precision, Scale, fix_inout(InOut), Values}; fix_params({{sql_char, Max}, InOut, Values}) -> - NewValues = - case (catch - lists:map(fun(Str) -> Str ++ [?STR_TERMINATOR] end, Values)) of - Result -> - Result - end, + NewValues = string_terminate(Values), {?USER_CHAR, Max, fix_inout(InOut), NewValues}; fix_params({{sql_varchar, Max}, InOut, Values}) -> - NewValues = - case (catch - lists:map(fun(Str) -> Str ++ [?STR_TERMINATOR] end, Values)) of - Result -> - Result - end, + NewValues = string_terminate(Values), {?USER_VARCHAR, Max, fix_inout(InOut), NewValues}; +fix_params({{sql_wchar, Max}, InOut, Values}) -> + NewValues = string_terminate(Values), + {?USER_WCHAR, Max, fix_inout(InOut), NewValues}; +fix_params({{sql_wvarchar, Max}, InOut, Values}) -> + NewValues = string_terminate(Values), + {?USER_WVARCHAR, 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}) -> @@ -941,3 +941,16 @@ fix_inout(out) -> ?OUT; fix_inout(inout) -> ?INOUT. + +string_terminate([Value| _ ] = Values) when is_list(Value)-> + case (catch + lists:map(fun(Str) -> Str ++ [?STR_TERMINATOR] end, Values)) of + Result -> + Result + end; +string_terminate([Value| _ ] = Values) when is_binary(Value)-> + case (catch + lists:map(fun(B) -> <> end, Values)) of + Result -> + Result + end. diff --git a/lib/odbc/src/odbc_internal.hrl b/lib/odbc/src/odbc_internal.hrl index 144e3cd176..10ed139338 100644 --- a/lib/odbc/src/odbc_internal.hrl +++ b/lib/odbc/src/odbc_internal.hrl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2002-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2002-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -69,6 +69,8 @@ -define(USER_DOUBLE, 9). -define(USER_BOOLEAN, 10). -define(USER_TINY_INT, 11). +-define(USER_WCHAR, 12). +-define(USER_WVARCHAR, 13). %% INPUT & OUTPUT TYPE -define(IN, 0). diff --git a/lib/odbc/vsn.mk b/lib/odbc/vsn.mk index 92540d90f8..7af25db25b 100644 --- a/lib/odbc/vsn.mk +++ b/lib/odbc/vsn.mk @@ -1,10 +1,11 @@ -ODBC_VSN = 2.10.7 +ODBC_VSN = 2.10.8 + +TICKETS = OTP-7452 TICKETS_2.10.6 = \ OTP-8250 \ OTP-8291 - TICKETS_2.10.5 = \ OTP-7978 -- cgit v1.2.3