module Database.MetaHDBC.OdbcInferTypes
    ( dbInferTypes, strictList
    )
where

import Database.HDBC
import Database.HDBC.ODBC

-- import Control.Exception

-- |Asks a ODBC database to infer selected types and placeholder types.
dbInferTypes :: String                            -- ^Data source name
             -> String                            -- ^SQL
             -> IO ([SqlColDesc], [SqlColDesc])   -- ^(parameter/input -info, return/column/output -info)
dbInferTypes dsn sqlExpr =
    do c <- connectODBC dsn                                 `catchSql` connectError
       (paramInfo', description') <- getQueryInfo c sqlExpr `catchSql` queryInfoError
       -- print (paramInfo, description)
       paramInfo <- strictList paramInfo'
       description <- strictList description'
       let desc = map snd description
       -- print (paramInfo, description) -- FIXME
       -- commit c
       -- disconnect c --                          `rethrowDoing` "disconnecting"
       -- FIXME: discornect, but make sure everything is evaluated before discornnecting
       -- DB2 gives us problem if we disconnect explicitly. Thus we drop it for now.
       return (paramInfo, desc)
    where
      connectError e   = fail ("Could not connect to: " ++ dsn ++ ".\n" ++
                               "Error message ODBC: " ++ seErrorMsg e)
      queryInfoError e = fail ("Error while getting type information from the database server.\n" ++
                               "Error message from database: " ++ seErrorMsg e ++
                               "\nThe error orcurred while preparing:\n" ++
                               sqlExpr ++ "\n")

strictList :: [a] -> IO [a]
strictList [] = return []
strictList ys = (last ys) `seq` (return ys)