{-# 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

sql_attr_connection_pooling :: Num a => a
sql_attr_connection_pooling = 201

sql_attr_cp_match :: Num a => a
sql_attr_cp_match = 202

-- unixODBC additions
sql_attr_unixodbc_syspath :: Num a => a
sql_attr_unixodbc_syspath = 65001

sql_attr_unixodbc_version :: Num a => a
sql_attr_unixodbc_version = 65002

sql_attr_unixodbc_envattr :: Num a => a
sql_attr_unixodbc_envattr = 65003


-- values for SQL_ATTR_CONNECTION_POOLING
sql_cp_off :: CULong
sql_cp_off = 0

sql_cp_one_per_driver :: CULong
sql_cp_one_per_driver = 1

sql_cp_one_per_henv :: CULong
sql_cp_one_per_henv = 2

sql_cp_default :: CULong
sql_cp_default = sql_cp_off

-- values for SQL_ATTR_CP_MATCH
sql_cp_strict_match :: CULong
sql_cp_strict_match = 0

sql_cp_relaxed_match :: CULong
sql_cp_relaxed_match = 1

sql_cp_match_default :: CULong
sql_cp_match_default = sql_cp_strict_match

-- values for SQL_ATTR_ODBC_VERSION
sql_ov_odbc2 :: CULong
sql_ov_odbc2 = 2

sql_ov_odbc3 :: CULong
sql_ov_odbc3 = 3

-- 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