packages feed

sqlcli-odbc 0.1.0.1 → 0.2.0.0

raw patch · 3 files changed

+530/−13 lines, 3 filesdep +loggingdep ~sqlcli

Dependencies added: logging

Dependency ranges changed: sqlcli

Files

sqlcli-odbc.cabal view
@@ -1,5 +1,5 @@ name:                sqlcli-odbc-version:             0.1.0.1+version:             0.2.0.0 synopsis:            Specific ODBC definitions to be used by SQL CLI clients. description:         You should use this package if you intend to use sqlcli package                      to connect to ODBC datasources.@@ -19,7 +19,8 @@   exposed-modules:     SQL.ODBC,                        SQL.CLI.ODBC   build-depends:       base >= 4.7 && < 5,-                       sqlcli >= 0.1 && < 0.2+                       logging >= 3.0 && < 4,+                       sqlcli >= 0.2 && < 0.3   default-language:    Haskell2010  source-repository head
src/SQL/CLI/ODBC.hs view
@@ -1,17 +1,27 @@ module SQL.CLI.ODBC where
 
-import Prelude hiding (fail)
+import Prelude hiding (fail, log)
 
+import Control.Logging (log)
+
 import Control.Monad.IO.Class (MonadIO, liftIO)
 import Control.Monad.Fail (MonadFail, fail)
 
+import Data.String (fromString)
+
 import System.IO (hPutStrLn, stderr)
 
 import Foreign.Ptr (wordPtrToPtr)
 
-import SQL.ODBC (sql_attr_odbc_version, sql_ov_odbc3)
-import SQL.CLI (SQLHENV, sqlsetenvattr, sql_handle_env, sql_null_handle, sql_success, sql_success_with_info, sql_invalid_handle, sql_error)
-import SQL.CLI.Utils (SQLConfig(SQLConfig), allocHandle, displayDiagInfo)
+import SQL.ODBC (sql_attr_odbc_version,
+                 sql_ov_odbc3,
+                 sql_longvarchar,
+                 sql_binary,
+                 sql_longvarbinary,
+                 sql_varbinary,
+                 sql_interval)
+import SQL.CLI (SQLHENV, SQLSMALLINT, sqlsetenvattr, sql_handle_env, sql_null_handle, sql_success, sql_success_with_info, sql_invalid_handle, sql_error, sql_char)
+import SQL.CLI.Utils (SQLConfig(SQLConfig), allocHandle, displayDiagInfo, toCLIType)
 
 -- | holds information specific to ODBC implementation
 odbcImplementation :: SQLConfig
@@ -22,24 +32,38 @@ -- or setting the environment failed; it requires ODBC 3 implementation
 setupEnv :: (MonadIO m, MonadFail m) => m SQLHENV
 setupEnv = do
-  liftIO $ hPutStrLn stderr "alloc env handle"
+  liftIO $ log $ fromString "alloc env handle"
   henv <- allocHandle sql_handle_env sql_null_handle
-  liftIO $ hPutStrLn stderr "odbc specific - set odbc version env attr"
+  liftIO $ log $ fromString $ "allocated environment handle: " ++ (show henv)
+  liftIO $ log $ fromString "odbc specific - set odbc version env attr"
   resultSetEnvOV <- liftIO $ sqlsetenvattr henv sql_attr_odbc_version (wordPtrToPtr $ fromIntegral sql_ov_odbc3) 0
   case resultSetEnvOV of x | x == sql_success -> return henv
                            | x == sql_success_with_info -> do
                                liftIO $ do
-                                 hPutStrLn stderr "Set ODBC version generated warnings"
+                                 log $ fromString "Set ODBC version generated warnings"
                                  displayDiagInfo sql_handle_env henv
                                return henv
                            | x == sql_invalid_handle -> do
-                               liftIO $ hPutStrLn stderr "Set ODBC version failed because invalid handle was passed to SetEnvAttr function."
+                               liftIO $ log $ fromString "Set ODBC version failed because invalid handle was passed to SetEnvAttr function."
                                fail "Set ODBC version failed"
                            | x == sql_error -> do
                                liftIO $ do
-                                 hPutStrLn stderr "Set ODBC version failed. Error diagnostics follow:"
+                                 log $ fromString "Set ODBC version failed. Error diagnostics follow:"
                                  displayDiagInfo sql_handle_env henv
                                fail "Set ODBC version failed"
                            | otherwise -> do
-                               liftIO $ hPutStrLn stderr $ "SetEnvAttr returned unexpected return code: " ++ (show x)
+                               liftIO $ log $ fromString $ "SetEnvAttr returned unexpected return code: " ++ (show x)
                                fail "Set ODBC version failed"
+
+-- | convert an implementation type identifier to an ODBC known type
+toODBCType :: SQLSMALLINT -> SQLSMALLINT
+toODBCType t = if t == sql_char
+               then sql_char
+               else if clitype == sql_char
+                    then odbctype
+                    else clitype
+  where
+    clitype  = toCLIType t
+    odbctype = if elem t [sql_longvarchar, sql_binary, sql_longvarbinary, sql_varbinary, sql_interval]
+               then t
+               else sql_char
src/SQL/ODBC.hs view
@@ -1,7 +1,11 @@-module SQL.ODBC where+{-# LANGUAGE CPP #-} +module SQL.ODBC (module SQL.ODBC, module SQL.CLI) where+ import Foreign.C.Types +import SQL.CLI+ -- env attribute sql_attr_odbc_version :: Num a => a sql_attr_odbc_version = 200@@ -56,3 +60,491 @@ -- From ODBC 3.8 onwards, we should use <major version> * 100 + <minor version> sql_ov_odbc3_80 :: CULong sql_ov_odbc3_80 = 380+++-- connection attributes+sql_attr_access_mode :: Num a => a+sql_attr_access_mode = 101++sql_attr_autocommit :: Num a => a+sql_attr_autocommit = 102++sql_attr_connection_timeout :: Num a => a+sql_attr_connection_timeout = 113++sql_attr_current_catalog :: Num a => a+sql_attr_current_catalog = 109++sql_attr_disconnect_behavior :: Num a => a+sql_attr_disconnect_behavior = 114++sql_attr_enlist_in_dtc :: Num a => a+sql_attr_enlist_in_dtc = 1207++sql_attr_enlist_in_xa :: Num a => a+sql_attr_enlist_in_xa = 1208++sql_attr_login_timeout :: Num a => a+sql_attr_login_timeout = 103++sql_attr_odbc_cursors :: Num a => a+sql_attr_odbc_cursors = 110++sql_attr_packet_size :: Num a => a+sql_attr_packet_size = 112++sql_attr_quiet_mode :: Num a => a+sql_attr_quiet_mode = 111++sql_attr_trace :: Num a => a+sql_attr_trace = 104++sql_attr_tracefile :: Num a => a+sql_attr_tracefile = 105++sql_attr_translate_lib :: Num a => a+sql_attr_translate_lib = 106++sql_attr_translate_option :: Num a => a+sql_attr_translate_option = 107++sql_attr_txn_isolation :: Num a => a+sql_attr_txn_isolation = 108++sql_attr_connection_dead :: Num a => a+sql_attr_connection_dead = 1209    -- GetConnectAttr only++sql_attr_driver_threading :: Num a => a+sql_attr_driver_threading = 1028    -- Driver threading level++{--+if (ODBCVER >= 0x0351)+        ODBC Driver Manager sets this connection attribute to a unicode driver+        (which supports SQLConnectW) when the application is an ANSI application+        (which calls SQLConnect, SQLDriverConnect, or SQLBrowseConnect).+        This is SetConnectAttr only and application does not set this attribute+        This attribute was introduced because some unicode driver's some APIs may+        need to behave differently on ANSI or Unicode applications. A unicode+        driver, which  has same behavior for both ANSI or Unicode applications,+        should return SQL_ERROR when the driver manager sets this connection+        attribute. When a unicode driver returns SQL_SUCCESS on this attribute,+        the driver manager treates ANSI and Unicode connections differently in+        connection pooling.+--}++sql_attr_ansi_app :: Num a => a+sql_attr_ansi_app = 115++{--+endif+--}++sql_attr_reset_connection :: Num a => a+sql_attr_reset_connection = 116++sql_attr_async_dbc_functions_enable :: Num a => a+sql_attr_async_dbc_functions_enable = 117++-- SQL_CONNECT_OPT_DRVR_START is not meaningful for 3.0 driver+sql_connect_opt_drvr_start :: Num a => a+sql_connect_opt_drvr_start = 1000++sql_conn_opt_max :: Num a => a+sql_conn_opt_max = sql_attr_packet_size++sql_conn_opt_min :: Num a => a+sql_conn_opt_min = sql_attr_access_mode++-- SQL_ACCESS_MODE options+sql_mode_read_write :: Num a => a+sql_mode_read_write = 0++sql_mode_read_only :: Num a => a+sql_mode_read_only = 1++sql_mode_default :: Num a => a+sql_mode_default = sql_mode_read_write++-- SQL_AUTOCOMMIT options+sql_autocommit_off :: Num a => a+sql_autocommit_off = 0++sql_autocommit_on :: Num a => a+sql_autocommit_on = 1++sql_autocommit_default :: Num a => a+sql_autocommit_default = sql_autocommit_on++-- SQL_LOGIN_TIMEOUT options+sql_login_timeout_default :: Num a => a+sql_login_timeout_default = 15++-- SQL_OPT_TRACE options+sql_opt_trace_off :: Num a => a+sql_opt_trace_off = 0++sql_opt_trace_on :: Num a => a+sql_opt_trace_on = 1++sql_opt_trace_default :: Num a => a+sql_opt_trace_default = sql_opt_trace_off++sql_opt_trace_file_default :: String+#ifdef _WINDOWS_+sql_opt_trace_file_default = "\\temp\\SQL.LOG"+#else+sql_opt_trace_file_default = "/tmp/SQL.LOG"+#endif++-- SQL_ODBC_CURSORS options +sql_cur_use_if_needed :: Num a => a+sql_cur_use_if_needed = 0++sql_cur_use_odbc :: Num a => a+sql_cur_use_odbc = 1++sql_cur_use_driver :: Num a => a+sql_cur_use_driver = 2++sql_cur_default :: Num a => a+sql_cur_default = sql_cur_use_driver++-- values for SQL_ATTR_DISCONNECT_BEHAVIOR+sql_db_return_to_pool :: Num a => a+sql_db_return_to_pool = 0++sql_db_disconnect :: Num a => a+sql_db_disconnect = 1++sql_db_default :: Num a => a+sql_db_default = sql_db_return_to_pool++-- values for SQL_ATTR_ENLIST_IN_DTC+sql_dtc_done :: Num a => a+sql_dtc_done = 0+++-- values for SQL_ATTR_CONNECTION_DEAD+sql_cd_true :: Num a => a+sql_cd_true = 1              -- Connection is closed/dead++sql_cd_false :: Num a => a+sql_cd_false = 0             -- Connection is open/available++-- values for SQL_ATTR_ANSI_APP+sql_aa_true :: Num a => a+sql_aa_true = 1++sql_aa_false :: Num a => a+sql_aa_false = 0      -- the application is a Unicode app+++-- values for SQL_ATTR_RESET_CONNECTION+sql_reset_connection_yes :: Num a => a+sql_reset_connection_yes = 1++-- values for SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE+sql_async_dbc_enable_on :: Num a => a+sql_async_dbc_enable_on = 1++sql_async_dbc_enable_off :: Num a => a+sql_async_dbc_enable_off = 0++sql_async_dbc_enable_default :: Num a => a+sql_async_dbc_enable_default = sql_async_dbc_enable_off++++-- types specific to ODBC+sql_date :: (Num a) => a+sql_date = 9++sql_interval :: (Num a) => a+sql_interval = 10++sql_time :: (Num a) => a+sql_time = 10++sql_timestamp :: (Num a) => a+sql_timestamp = 11++sql_longvarchar :: (Num a) => a+sql_longvarchar = -1++sql_binary :: (Num a) => a+sql_binary = -2++sql_varbinary :: (Num a) => a+sql_varbinary = -3++sql_longvarbinary :: (Num a) => a+sql_longvarbinary = -4++sql_bigint :: (Num a) => a+sql_bigint = -5++sql_tinyint :: (Num a) => a+sql_tinyint = -6++sql_bit :: (Num a) => a+sql_bit = -7++sql_guid :: (Num a) => a+sql_guid = -11++sql_code_year :: (Num a) => a+sql_code_year = 1++sql_code_month :: (Num a) => a+sql_code_month = 2++sql_code_day :: (Num a) => a+sql_code_day = 3++sql_code_hour :: (Num a) => a+sql_code_hour = 4++sql_code_minute :: (Num a) => a+sql_code_minute = 5++sql_code_second :: (Num a) => a+sql_code_second = 6++sql_code_year_to_month :: (Num a) => a+sql_code_year_to_month = 7++sql_code_day_to_hour :: (Num a) => a+sql_code_day_to_hour = 8++sql_code_day_to_minute :: (Num a) => a+sql_code_day_to_minute = 9++sql_code_day_to_second :: (Num a) => a+sql_code_day_to_second = 10++sql_code_hour_to_minute :: (Num a) => a+sql_code_hour_to_minute = 11++sql_code_hour_to_second :: (Num a) => a+sql_code_hour_to_second = 12++sql_code_minute_to_second :: (Num a) => a+sql_code_minute_to_second = 13++sql_interval_year :: (Num a) => a+sql_interval_year = 100 + sql_code_year++sql_interval_month :: (Num a) => a+sql_interval_month = 100 + sql_code_month++sql_interval_day :: (Num a) => a+sql_interval_day = 100 + sql_code_day++sql_interval_hour :: (Num a) => a+sql_interval_hour = 100 + sql_code_hour++sql_interval_minute :: (Num a) => a+sql_interval_minute = 100 + sql_code_minute++sql_interval_second :: (Num a) => a+sql_interval_second = 100 + sql_code_second++sql_interval_year_to_month :: (Num a) => a+sql_interval_year_to_month = 100 + sql_code_year_to_month++sql_interval_day_to_hour :: (Num a) => a+sql_interval_day_to_hour = 100 + sql_code_day_to_hour++sql_interval_day_to_minute :: (Num a) => a+sql_interval_day_to_minute = 100 + sql_code_day_to_minute++sql_interval_day_to_second :: (Num a) => a+sql_interval_day_to_second = 100 + sql_code_day_to_second++sql_interval_hour_to_minute :: (Num a) => a+sql_interval_hour_to_minute = 100 + sql_code_hour_to_minute++sql_interval_hour_to_second :: (Num a) => a+sql_interval_hour_to_second = 100 + sql_code_hour_to_second++sql_interval_minute_to_second :: (Num a) => a+sql_interval_minute_to_second = 100 + sql_interval_minute_to_second+++-- ODBC c data types++sql_c_char :: (Num a) => a+sql_c_char = sql_char++sql_c_long :: (Num a) => a+sql_c_long = sql_integer++sql_c_short :: (Num a) => a+sql_c_short = sql_smallint++sql_c_float :: (Num a) => a+sql_c_float = sql_real++sql_c_double :: (Num a) => a+sql_c_double = sql_double++sql_c_numeric :: (Num a) => a+sql_c_numeric = sql_numeric++sql_c_default :: (Num a) => a+sql_c_default = 99++sql_signed_offset :: (Num a) => a+sql_signed_offset = -20++sql_unsigned_offset :: (Num a) => a+sql_unsigned_offset = -22++sql_c_date :: (Num a) => a+sql_c_date = sql_date++sql_c_time :: (Num a) => a+sql_c_time = sql_time++sql_c_timestamp :: (Num a) => a+sql_c_timestamp = sql_timestamp++sql_c_type_date :: (Num a) => a+sql_c_type_date = sql_type_date++sql_c_type_time :: (Num a) => a+sql_c_type_time = sql_type_time++sql_c_type_timestamp :: (Num a) => a+sql_c_type_timestamp = sql_type_timestamp++sql_c_interval_year :: (Num a) => a+sql_c_interval_year = sql_interval_year++sql_c_interval_month :: (Num a) => a+sql_c_interval_month = sql_interval_month++sql_c_interval_day :: (Num a) => a+sql_c_interval_day = sql_interval_day++sql_c_interval_hour :: (Num a) => a+sql_c_interval_hour = sql_interval_hour++sql_c_interval_minute :: (Num a) => a+sql_c_interval_minute = sql_interval_minute++sql_c_interval_second :: (Num a) => a+sql_c_interval_second = sql_interval_second++sql_c_interval_year_to_month :: (Num a) => a+sql_c_interval_year_to_month = sql_interval_year_to_month++sql_c_interval_day_to_hour :: (Num a) => a+sql_c_interval_day_to_hour = sql_interval_day_to_hour++sql_c_interval_day_to_minute :: (Num a) => a+sql_c_interval_day_to_minute = sql_interval_day_to_minute++sql_c_interval_day_to_second :: (Num a) => a+sql_c_interval_day_to_second = sql_interval_day_to_second++sql_c_interval_hour_to_minute :: (Num a) => a+sql_c_interval_hour_to_minute = sql_interval_hour_to_minute++sql_c_interval_hour_to_second :: (Num a) => a+sql_c_interval_hour_to_second = sql_interval_hour_to_second++sql_c_interval_minute_to_second :: (Num a) => a+sql_c_interval_minute_to_second = sql_interval_minute_to_second++sql_c_binary :: (Num a) => a+sql_c_binary = sql_binary++sql_c_bit :: (Num a) => a+sql_c_bit = sql_bit++sql_c_sbigint :: (Num a) => a+sql_c_sbigint = sql_bigint + sql_signed_offset++sql_c_ubigint :: (Num a) => a+sql_c_ubigint = sql_bigint + sql_unsigned_offset++sql_c_tinyint :: (Num a) => a+sql_c_tinyint = sql_tinyint++sql_c_slong :: (Num a) => a+sql_c_slong = sql_c_long + sql_signed_offset++sql_c_sshort :: (Num a) => a+sql_c_sshort = sql_c_short + sql_signed_offset++sql_c_stinyint :: (Num a) => a+sql_c_stinyint = sql_tinyint + sql_signed_offset++sql_c_ulong :: (Num a) => a+sql_c_ulong = sql_c_long + sql_unsigned_offset++sql_c_ushort :: (Num a) => a+sql_c_ushort = sql_c_short + sql_unsigned_offset++sql_c_utinyint :: (Num a) => a+sql_c_utinyint = sql_tinyint + sql_unsigned_offset++sql_c_bookmark :: (Num a) => a+sql_c_bookmark = sql_c_ubigint++sql_c_guid :: (Num a) => a+sql_c_guid = sql_guid++sql_wchar :: (Num a) => a+sql_wchar = -8++sql_wvarchar :: (Num a) => a+sql_wvarchar = -9++sql_wlongvarchar :: (Num a) => a+sql_wlongvarchar = -10++sql_c_wchar :: (Num a) => a+sql_c_wchar = sql_wchar++++-- | returns the length of the buffer for odbc C types; returns Nothing for+-- variable length fields or unknown fields, otherwise returns the number of+-- octets needed to hold the value of that type+odbcCTypeLen :: (Num a) => SQLSMALLINT -> Maybe a+odbcCTypeLen dataType =+  case dataType of+    _ | dataType == sql_c_bit                           -> Just  1+      | dataType == sql_c_tinyint                       -> Just  1+      | dataType == sql_c_stinyint                      -> Just  1+      | dataType == sql_c_utinyint                      -> Just  1+      | dataType == sql_c_short                         -> Just  2+      | dataType == sql_c_sshort                        -> Just  2+      | dataType == sql_c_ushort                        -> Just  2+      | dataType == sql_c_long                          -> Just  4+      | dataType == sql_c_slong                         -> Just  4+      | dataType == sql_c_ulong                         -> Just  4+      | dataType == sql_c_sbigint                       -> Just  8+      | dataType == sql_c_ubigint                       -> Just  8+      | dataType == sql_c_float                         -> Just  4+      | dataType == sql_c_double                        -> Just  8+      | dataType == sql_c_type_date                     -> Just  6+      | dataType == sql_c_type_time                     -> Just  6+      | dataType == sql_c_type_timestamp                -> Just 16+      | dataType == sql_c_interval_year                 -> Just 34+      | dataType == sql_c_interval_month                -> Just 34+      | dataType == sql_c_interval_day                  -> Just 34+      | dataType == sql_c_interval_hour                 -> Just 34+      | dataType == sql_c_interval_minute               -> Just 34+      | dataType == sql_c_interval_second               -> Just 34+      | dataType == sql_c_interval_year_to_month        -> Just 34+      | dataType == sql_c_interval_day_to_hour          -> Just 34+      | dataType == sql_c_interval_day_to_minute        -> Just 34+      | dataType == sql_c_interval_day_to_second        -> Just 34+      | dataType == sql_c_interval_hour_to_minute       -> Just 34+      | dataType == sql_c_interval_hour_to_second       -> Just 34+      | dataType == sql_c_interval_minute_to_second     -> Just 34+      | dataType == sql_c_guid                          -> Just 16+      | otherwise                                       -> Nothing