HDBC-odbc 2.4.0.0 → 2.4.0.1
raw patch · 4 files changed
+36/−4 lines, 4 files
Files
- Database/HDBC/ODBC/Statement.hsc +23/−1
- HDBC-odbc.cabal +1/−1
- changelog.txt +5/−0
- hdbc-odbc-helper.c +7/−2
Database/HDBC/ODBC/Statement.hsc view
@@ -315,8 +315,14 @@ bindSqlValue :: SqlValue -> IO BoundValue bindSqlValue sqlValue = case sqlValue of SqlString s -> do +-- GHC for Windows strings are implemented with wchar_t symbols, which are 16-bit UCS-2 and ODBC +-- driver expects exactly that type. On Linux machines things get harder because wchar_t is 32-bit +-- (UTF-32) while ODBC WCHAR might be either 16 or 32 bit. So on Linux we convert our string to +-- UTF-8 and pass it to the driver telling it that we are passing SQL_C_CHAR data for a SQL_WCHAR +-- column and hoping that the driver will convert back from UTF-8 to appropriate representation. +#ifdef mingw32_HOST_OS (wstrPtr, wstrLen) <- newCWStringLen s - let result = BoundValue + let result = BoundValue { bvValueType = #{const SQL_C_WCHAR} , bvDefaultColumnType = #{const SQL_WCHAR} , bvDefaultColumnSize = fromIntegral wstrLen @@ -326,6 +332,22 @@ } l $ "bind SqlString " ++ s ++ ": " ++ show result return result +#else + let utf8ByteString = BUTF8.fromString s + B.unsafeUseAsCStringLen utf8ByteString $ \(unsafeStrPtr, strLen) -> do + safeStrPtr <- mallocBytes strLen + copyBytes safeStrPtr unsafeStrPtr strLen + let result = BoundValue + { bvValueType = #{const SQL_C_CHAR} + , bvDefaultColumnType = #{const SQL_WCHAR} + , bvDefaultColumnSize = fromIntegral strLen + , bvDefaultDecDigits = 0 + , bvBuffer = castPtr safeStrPtr + , bvBufferSize = fromIntegral strLen + } + l $ "bind SqlString " ++ s ++ ": " ++ show result + return result +#endif SqlByteString bs -> B.unsafeUseAsCStringLen bs $ \(s,len) -> do res <- mallocBytes len copyBytes res s len
HDBC-odbc.cabal view
@@ -1,5 +1,5 @@ Name: HDBC-odbc -Version: 2.4.0.0 +Version: 2.4.0.1 Cabal-Version: >=1.8 Build-type: Simple License: BSD3
changelog.txt view
@@ -1,3 +1,8 @@+2.4.0.1 - 15 May 2015 + + * Switched to using UTF-8 encoding for binding WCHAR_T values on Linux. Earlier version tried + to use C wchar_t type, which confused some (in particular PostgreSQL) drivers. + 2.4.0.0 - 12 Nov 2014 * Changed parameter binding implementation to fix bugs with wide character strings and binary
hdbc-odbc-helper.c view
@@ -49,7 +49,7 @@ newobj->extrainfo = NULL; newobj->parent = parentobj; if (parentobj != NULL) { - __sync_add_and_fetch(&parentobj->refcount, 1); + odbc_atomic_increment(&parentobj->refcount); } #ifdef HDBC_DEBUG fprintf(stderr, "\nWrapped %p at %p\n", obj, newobj); @@ -72,6 +72,8 @@ int isFinalized = odbc_sync_val_compare_and_swap(&res->isfinalized, 0, 1); if (isFinalized) return; + if (!res->encapobj) + return; // Microsoft SQL Server driver might deadlock if calling SQLCloseCursor on a statement that is in the // process of fetching data via network. So we cancel it first. SQLCancel((SQLHSTMT) (res->encapobj)); @@ -104,6 +106,9 @@ int isFinalized = odbc_sync_val_compare_and_swap(&res->isfinalized, 0, 1); if (isFinalized) return 0; + if (!res->encapobj) + return SQL_SUCCESS; + retval = SQLDisconnect((SQLHDBC) (res->encapobj)); if (SQL_SUCCEEDED(retval)) { SQLFreeHandle(SQL_HANDLE_DBC, (SQLHANDLE) (res->encapobj)); @@ -127,7 +132,7 @@ /* Don't use sqlFreeHandleDbc_app here, because we want to clear it out regardless of the success or failues of SQLDisconnect. */ int isFinalized = odbc_sync_val_compare_and_swap(&res->isfinalized, 0, 1); - if (!isFinalized) { + if (!isFinalized && res->encapobj) { SQLDisconnect((SQLHDBC) (res->encapobj)); SQLFreeHandle(SQL_HANDLE_DBC, (SQLHANDLE) (res->encapobj)); SQLFreeHandle(SQL_HANDLE_ENV, (SQLHANDLE) (res->extrainfo));