Files
postgrest/Main.hs
T
2014-06-22 12:56:19 -07:00

107 lines
2.9 KiB
Haskell

{-# LANGUAGE OverloadedStrings #-}
module Main where
import Data.ByteString.Lazy
import Data.Text
import Data.Text.Encoding (encodeUtf8)
import Text.Read
import Database.PostgreSQL.Simple
import Database.PostgreSQL.Simple.FromRow
import Control.Applicative
import Network.Wai
import Network.Wai.Handler.Warp hiding (Connection)
import Network.HTTP.Types.Status
import qualified Data.Aeson as JSON
import Data.Aeson ((.=))
data Table = Table {
viewSchema :: String
, viewName :: String
, viewInsertable :: Bool
} deriving (Show)
instance FromRow Table where
fromRow = Table <$> field <*> field <*> fmap toBool field
instance JSON.ToJSON Table where
toJSON v = JSON.object [
"schema" .= viewSchema v
, "name" .= viewName v
, "insertable" .= viewInsertable v ]
toBool :: String -> Bool
toBool = (== "YES")
data Column = Column {
colSchema :: String
, colTable :: String
, colName :: String
, colPosition :: Int
, colNullable :: Bool
, colType :: String
, colUpdatable :: Bool
, colMaxLen :: Maybe Int
, colPrecision :: Maybe Int
} deriving (Show)
instance FromRow Column where
fromRow = Column <$> field <*> field <*> field <*> field <*>
fmap toBool field <*> field <*>
fmap toBool field <*>
field <*> field
instance JSON.ToJSON Column where
toJSON c = JSON.object [
"schema" .= colSchema c
, "name" .= colName c
, "position" .= colPosition c
, "nullable" .= colNullable c
, "type" .= colType c
, "updatable" .= colUpdatable c
, "maxLen" .= colMaxLen c
, "precision" .= colPrecision c ]
tables :: String -> Connection -> IO [Table]
tables s conn = query conn q $ Only s
where q = "select table_schema, table_name,\
\ is_insertable_into \
\ from information_schema.tables\
\ where table_schema = ?"
columns :: Text -> Connection -> IO [Column]
columns t conn = query conn q $ Only t
where q = "select table_schema, table_name, column_name, ordinal_position,\
\ is_nullable, data_type, is_updatable,\
\ character_maximum_length, numeric_precision\
\ from information_schema.columns\
\ where table_name = ?"
main :: IO ()
main = do
let port = 3000
Prelude.putStrLn $ "Listening on port " ++ show port
run port app
printTables :: Connection -> IO ByteString
printTables conn = JSON.encode <$> tables "base" conn
printColumns :: Text -> Connection -> IO ByteString
printColumns tableName conn = JSON.encode <$> columns tableName conn
app :: Application
app req respond =
case path of
[] -> respond =<< responseLBS status200 [] <$> (printTables =<< conn)
[table] -> respond =<< responseLBS status200 [] <$> (printColumns table =<< conn)
_ -> respond $ responseLBS status404 [] ""
where
path = pathInfo req
conn = connect defaultConnectInfo {
connectDatabase = "dbapi_test"
}