module Database.PostgreSQL.Describe (
ColumnInfo(..), describeTable
) where
import Control.Monad
import qualified Data.ByteString as S
import Data.Int
import qualified Data.Vector as V
import qualified Database.PostgreSQL.Simple.TypeInfo.Static as PG
import Database.PostgreSQL.Simple
import Database.PostgreSQL.Simple.TypeInfo
import Database.PostgreSQL.Simple.Types
data ColumnInfo = ColumnInfo {
colNum :: !Int16
, colName :: S.ByteString
, colType :: !TypeInfo
, colNotNull :: !Bool
, colPrimary :: !Bool
, colUnique :: !Bool
, colReferences :: !(Maybe S.ByteString)
} deriving (Show)
defColInfo :: ColumnInfo
defColInfo = ColumnInfo {
colNum = 0
, colName = S.empty
, colType = PG.void
, colNotNull = False
, colPrimary = False
, colUnique = False
, colReferences = Nothing
}
describeTable :: Connection -> S.ByteString -> IO [ColumnInfo]
describeTable cn t = do
[(Only tbloid)] <- query cn "select oid from pg_class where relname = ?"
(Only t)
cs0 <- query cn "select attnum, attname, atttypid, attnotnull\
\ from pg_attribute\
\ where attrelid = ? and attisdropped = 'f' and attnum > 0\
\ order by attnum"
(Only (tbloid :: Oid))
cs1 <- forM cs0 $ \ (num, name, typ, notnull) -> do
ti <- getTypeInfo cn typ
return defColInfo {
colNum = num, colName = name, colType = ti, colNotNull = notnull
}
constraints <- query cn "select contype, conkey, relname\
\ from pg_constraint left join pg_class\
\ on confrelid = pg_class.oid\
\ where conrelid = ?"
(Only tbloid)
let _ = constraints :: [(String, V.Vector Int16, Maybe S.ByteString)]
return $ map (\c -> foldl appConstr c constraints) cs1
where appConstr ci (ct, ck, mn)
| V.length ck == 1, colNum ci == ck V.! 0 = appConstr1 ci ct mn
| otherwise = ci
appConstr1 ci "p" _ = ci { colPrimary = True }
appConstr1 ci "u" _ = ci { colUnique = True }
appConstr1 ci "f" n@(Just _) = ci { colReferences = n }
appConstr1 ci _ _ = ci