diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2014, Shohei Murayama
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Shohei Murayama nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/relational-postgresql8.cabal b/relational-postgresql8.cabal
new file mode 100644
--- /dev/null
+++ b/relational-postgresql8.cabal
@@ -0,0 +1,42 @@
+name:                relational-postgresql8
+version:             0.1.0.0
+synopsis:            PostgreSQL v8.x driver for haskell-relational-record
+description:         This package contains a driver of old PostgreSQL for haskell-relational-record.
+homepage:            https://github.com/yuga/haskell-relational-record-driver-postgresql8
+license:             BSD3
+license-file:        LICENSE
+author:              Shohei Murayama
+maintainer:          shohei.murayama@gmail.com
+copyright:           Copyright (c) 2014 Shohei Murayama
+category:            Database
+build-type:          Simple
+cabal-version:       >=1.8
+
+source-repository    head
+  type:              git
+  location:          https://github.com/yuga/haskell-relational-record-driver-postgresql8
+
+library
+  exposed-modules:
+                       Database.HDBC.Schema.PostgreSQL8
+                       Database.Relational.Schema.PostgreSQL8
+                       Database.Relational.Schema.PgCatalog8.Config
+                       Database.Relational.Schema.PgCatalog8.PgAttribute
+                       Database.Relational.Schema.PgCatalog8.PgClass
+                       Database.Relational.Schema.PgCatalog8.PgConstraint
+                       Database.Relational.Schema.PgCatalog8.PgNamespace
+                       Database.Relational.Schema.PgCatalog8.PgType
+
+  build-depends:       base <5
+                     , containers
+                     , time
+                     , persistable-record
+                     , HDBC >=2
+                     , names-th
+                     , relational-query
+                     , relational-query-HDBC
+                     , template-haskell
+
+  hs-source-dirs:      src
+  
+  ghc-options:         -Wall
diff --git a/src/Database/HDBC/Schema/PostgreSQL8.hs b/src/Database/HDBC/Schema/PostgreSQL8.hs
new file mode 100644
--- /dev/null
+++ b/src/Database/HDBC/Schema/PostgreSQL8.hs
@@ -0,0 +1,112 @@
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+
+-- |
+-- Module      : Database.HDBC.Schema.PostgreSQL8
+-- Copyright   : 2013 Kei Hibino, 2014 Shohei Murayama
+-- License     : BSD3
+--
+-- Maintainer  : shohei.murayama@gmail.com
+-- Stability   : experimental
+-- Portability : unknown
+--
+-- This module provides driver implementation
+-- to load PostgreSQL system catalog via HDBC.
+module Database.HDBC.Schema.PostgreSQL8 (
+  driverPostgreSQL
+  ) where
+
+import Language.Haskell.TH (TypeQ)
+import qualified Language.Haskell.TH.Lib.Extra as TH
+
+import Data.Char (toLower)
+import Data.Map (fromList)
+
+import Database.HDBC (IConnection, SqlValue)
+
+import Database.Record.TH (makeRecordPersistableWithSqlTypeDefaultFromDefined)
+
+import Database.HDBC.Record.Query (runQuery')
+import Database.HDBC.Record.Persistable ()
+
+import Database.Relational.Schema.PostgreSQL8
+  (normalizeColumn, notNull, getType, columnQuerySQL,
+   primaryKeyLengthQuerySQL, primaryKeyQuerySQL)
+import Database.Relational.Schema.PgCatalog8.PgAttribute (PgAttribute)
+import Database.Relational.Schema.PgCatalog8.PgType (PgType)
+import qualified Database.Relational.Schema.PgCatalog8.PgType as Type
+
+import Database.HDBC.Schema.Driver
+  (TypeMap, Driver, getFieldsWithMap, getPrimaryKey, emptyDriver)
+
+
+$(makeRecordPersistableWithSqlTypeDefaultFromDefined
+  [t| SqlValue |] ''PgAttribute)
+
+$(makeRecordPersistableWithSqlTypeDefaultFromDefined
+  [t| SqlValue |] ''PgType)
+
+logPrefix :: String -> String
+logPrefix =  ("PostgreSQL: " ++)
+
+putLog :: String -> IO ()
+putLog =  TH.reportMessage . logPrefix
+
+compileErrorIO :: String -> IO a
+compileErrorIO =  fail . logPrefix
+
+getPrimaryKey' :: IConnection conn
+              => conn
+              -> String
+              -> String
+              -> IO [String]
+getPrimaryKey' conn scm' tbl' = do
+  let scm = map toLower scm'
+      tbl = map toLower tbl'
+  mayKeyLen <- runQuery' conn primaryKeyLengthQuerySQL (scm, tbl)
+  case mayKeyLen of
+    []        -> do
+      putLog   "getPrimaryKey: Primary key not found."
+      return []
+    [keyLen]  -> do
+      primCols <- runQuery' conn (primaryKeyQuerySQL keyLen) (scm, tbl)
+      let primaryKeyCols = normalizeColumn `fmap` primCols
+      putLog $ "getPrimaryKey: primary key = " ++ show primaryKeyCols
+      return primaryKeyCols
+    _:_:_     -> do
+      putLog   "getPrimaryKey: Fail to detect primary key. Something wrong."
+      return []
+
+getFields' :: IConnection conn
+          => TypeMap
+          -> conn
+          -> String
+          -> String
+          -> IO ([(String, TypeQ)], [Int])
+getFields' tmap conn scm' tbl' = do
+  let scm = map toLower scm'
+      tbl = map toLower tbl'
+  cols <- runQuery' conn columnQuerySQL (scm, tbl)
+  case cols of
+    [] ->  compileErrorIO
+           $ "getFields: No columns found: schema = " ++ scm ++ ", table = " ++ tbl
+    _  ->  return ()
+
+  let notNullIdxs = map fst . filter (notNull . snd) . zip [0..] $ cols
+  putLog
+    $  "getFields: num of columns = " ++ show (length cols)
+    ++ ", not null columns = " ++ show notNullIdxs
+  let getType' col = case getType (fromList tmap) col of
+        Nothing -> compileErrorIO
+                   $ "Type mapping is not defined against PostgreSQL type: " ++ Type.typname (snd col)
+        Just p  -> return p
+
+  types <- mapM getType' cols
+  return (types, notNullIdxs)
+
+-- | Driver implementation
+driverPostgreSQL :: IConnection conn => Driver conn
+driverPostgreSQL =
+  emptyDriver { getFieldsWithMap = getFields' }
+              { getPrimaryKey    = getPrimaryKey' }
diff --git a/src/Database/Relational/Schema/PgCatalog8/Config.hs b/src/Database/Relational/Schema/PgCatalog8/Config.hs
new file mode 100644
--- /dev/null
+++ b/src/Database/Relational/Schema/PgCatalog8/Config.hs
@@ -0,0 +1,17 @@
+-- |
+-- Module      : Database.Relational.Schema.PgCatalog8.Config
+-- Copyright   : 2013 Kei Hibino, 2014 Shohei Murayama
+-- License     : BSD3
+--
+-- Maintainer  : shohei.murayama@gmail.com
+-- Stability   : experimental
+-- Portability : unknown
+module Database.Relational.Schema.PgCatalog8.Config (config) where
+
+import Database.Relational.Query (Config, defaultConfig)
+
+
+-- | Configuration parameter against PostgreSQL v8.x
+config :: Config
+config =  defaultConfig
+
diff --git a/src/Database/Relational/Schema/PgCatalog8/PgAttribute.hs b/src/Database/Relational/Schema/PgCatalog8/PgAttribute.hs
new file mode 100644
--- /dev/null
+++ b/src/Database/Relational/Schema/PgCatalog8/PgAttribute.hs
@@ -0,0 +1,71 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE FlexibleInstances #-}
+
+-- |
+-- Module      : Database.HDBC.Schema.PgCatalog8.PgAttribute
+-- Copyright   : 2013 Kei Hibino, 2014 Shohei Murayama
+-- License     : BSD3
+--
+-- Maintainer  : shohei.murayama@gmail.com
+-- Stability   : experimental
+-- Portability : unknown
+module Database.Relational.Schema.PgCatalog8.PgAttribute where
+
+import Data.Int (Int16, Int32)
+
+import Database.Record.TH (derivingShow)
+import Database.Relational.Query.TH (defineTableTypesAndRecordDefault)
+
+import Database.Relational.Schema.PgCatalog8.Config (config)
+
+$(defineTableTypesAndRecordDefault config
+  "PG_CATALOG" "pg_attribute"
+
+  [
+-- Table "pg_catalog.pg_attribute"
+--     Column     |   Type    | Modifiers
+-- ---------------+-----------+-----------
+--  attrelid      | oid       | not null
+    ("attrelid"     , [t|Int32|]),
+--  attname       | name      | not null
+    ("attname"      , [t|String|]),
+--  atttypid      | oid       | not null
+    ("atttypid"     , [t|Int32|]),
+--  attstattarget | integer   | not null
+    ("attstattarget", [t|Int32|]),
+--  attlen        | smallint  | not null
+    ("attlen"       , [t|Int16|]),
+--  attnum        | smallint  | not null
+    ("attnum"      , [t|Int16|]),
+--  attndims      | integer   | not null
+    ("attndims"    , [t|Int32|]),
+--  attcacheoff   | integer   | not null
+    ("attcacheoff" , [t|Int32|]),
+--  atttypmod     | integer   | not null
+    ("atttypmod"   , [t|Int32|]),
+--  attbyval      | boolean   | not null
+    ("attbyval"    , [t|Bool|]),
+--  attstorage    | "char"    | not null
+    ("attstorage"  , [t|Char|]),
+--  attalign      | "char"    | not null
+    ("attalign"    , [t|Char|]),
+--  attnotnull    | boolean   | not null
+    ("attnotnull"  , [t|Bool|]),
+--  atthasdef     | boolean   | not null
+    ("atthasdef"   , [t|Bool|]),
+--  attisdropped  | boolean   | not null
+    ("attisdropped", [t|Bool|]),
+--  attislocal    | boolean   | not null
+    ("attislocal"  , [t|Bool|]),
+--  attinhcount   | integer   | not null
+    ("attinhcount" , [t|Int32|])
+--  attcollation  | oid       | not null  <= since 9.1
+    -- ("attcollation", [t|Int32|]),
+--  attacl        | aclitem[] |           <= since 8.4
+    -- ("attacl"      , [t|String|]),
+--  attoptions    | text[]    |           <= since 9.0
+    -- ("attoptions"  , [t|String|]),
+--  attfdwoptions | text[]    |           <- since 9.2
+    -- ("attfdwoptions", [t|String|])
+  ]
+  [derivingShow])
diff --git a/src/Database/Relational/Schema/PgCatalog8/PgClass.hs b/src/Database/Relational/Schema/PgCatalog8/PgClass.hs
new file mode 100644
--- /dev/null
+++ b/src/Database/Relational/Schema/PgCatalog8/PgClass.hs
@@ -0,0 +1,58 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE FlexibleInstances #-}
+
+-- |
+-- Module      : Database.Relational.Schema.PgCatalog8.PgClass
+-- Copyright   : 2013 Kei Hibino, 2014 Sohei Murayama
+-- License     : BSD3
+--
+-- Maintainer  : shohei.murayama@gmail.com
+-- Stability   : experimental
+-- Portability : unknown
+module Database.Relational.Schema.PgCatalog8.PgClass where
+
+import Data.Int (Int32)
+
+import Database.Record.TH (derivingShow)
+import Database.Relational.Query.TH (defineTableTypesAndRecordDefault)
+
+import Database.Relational.Schema.PgCatalog8.Config (config)
+
+$(defineTableTypesAndRecordDefault config
+  "PG_CATALOG" "pg_class"
+  [("oid"         , [t| Int32 |]),
+ -- relname        | name      | not null
+   ("relname"     , [t| String |]),
+ -- relnamespace   | oid       | not null
+   ("relnamespace", [t| Int32 |])
+ -- reltype        | oid       | not null
+ -- reloftype      | oid       | not null <= since 9.0
+ -- relowner       | oid       | not null
+ -- relam          | oid       | not null
+ -- relfilenode    | oid       | not null
+ -- reltablespace  | oid       | not null
+ -- relpages       | integer   | not null
+ -- reltuples      | real      | not null
+ -- reltoastrelid  | oid       | not null
+ -- reltoastidxid  | oid       | not null
+ -- relhasindex    | boolean   | not null
+ -- relisshared    | boolean   | not null
+ -- relpersistence | "char"    | not null <= since 9.1
+ -- relkind        | "char"    | not null
+ -- relnatts       | smallint  | not null
+ -- relchecks      | smallint  | not null
+ -- reltriggers    | smallint  | not null <= until 8.3
+ -- relukeys       | smallint  | not null <= until 8.3
+ -- relfkeys       | smallint  | not null <= until 8.3
+ -- relrefs        | smallint  | not null <= until 8.3
+ -- relhasoids     | boolean   | not null
+ -- relhaspkey     | boolean   | not null
+ -- relhasrules    | boolean   | not null
+ -- relhastriggers | boolean   | not null <= since 8.4
+ -- relhassubclass | boolean   | not null
+ -- relfrozenxid   | xid       | not null <= since 8.2
+ -- relminmxid     | xid       | not null <= since 9.3
+ -- relacl         | aclitem[] |
+ -- reloptions     | text[]    |          <= since 8.2
+  ]
+  [derivingShow])
diff --git a/src/Database/Relational/Schema/PgCatalog8/PgConstraint.hs b/src/Database/Relational/Schema/PgCatalog8/PgConstraint.hs
new file mode 100644
--- /dev/null
+++ b/src/Database/Relational/Schema/PgCatalog8/PgConstraint.hs
@@ -0,0 +1,52 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE FlexibleInstances #-}
+
+-- |
+-- Module      : Database.Relational.Schema.PgCatalog8.PgConstraint
+-- Copyright   : 2013 Kei Hibino, 2014 Shohei Murayama
+-- License     : BSD3
+--
+-- Maintainer  : shohei.murayama@gmail.com
+-- Stability   : experimental
+-- Portability : unknown
+module Database.Relational.Schema.PgCatalog8.PgConstraint where
+
+import Data.Int (Int32)
+
+import Database.Record.TH (derivingShow)
+import Database.Relational.Query.TH (defineTableTypesAndRecordDefault)
+
+import Database.Relational.Schema.PgCatalog8.Config (config)
+
+$(defineTableTypesAndRecordDefault config
+  "PG_CATALOG" "pg_constraint"
+  [ -- ("oid"    , [t| Int32 |]),
+ -- conname       | name         | not null
+ -- connamespace  | oid          | not null
+ -- contype       | "char"       | not null
+    ("contype",   [t| Char |]),
+ -- condeferrable | boolean      | not null
+ -- condeferred   | boolean      | not null
+ -- convalidated  | boolean      | not null <= since 9.1
+ -- conrelid      | oid          | not null
+    ("conrelid",  [t| Int32 |])
+ -- contypid      | oid          | not null
+ -- conindid      | oid          | not null <= since 9.0
+ -- confrelid     | oid          | not null
+ -- confupdtype   | "char"       | not null
+ -- confdeltype   | "char"       | not null
+ -- confmatchtype | "char"       | not null
+ -- conislocal    | boolean      | not null <= since 8.4
+ -- coninhcount   | integer      | not null <= since 8.4
+ -- connoinherit  | bool         | not null <= since 9.3
+ -- conkey        | smallint[]   |
+    -- ("conkey",  ???),
+ -- confkey       | smallint[]   |
+ -- conpfeqop     | oid[]        |          <= since 8.3
+ -- conppeqop     | oid[]        |          <= since 8.3
+ -- conffeqop     | oid[]        |          <= since 8.3
+ -- conexclop     | oid[]        |          <= since 9.0
+ -- conbin        | pg_node_tree |
+ -- consrc        | text         |
+  ]
+  [derivingShow])
diff --git a/src/Database/Relational/Schema/PgCatalog8/PgNamespace.hs b/src/Database/Relational/Schema/PgCatalog8/PgNamespace.hs
new file mode 100644
--- /dev/null
+++ b/src/Database/Relational/Schema/PgCatalog8/PgNamespace.hs
@@ -0,0 +1,29 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE FlexibleInstances #-}
+
+-- |
+-- Module      : Database.Relational.Schema.PgCatalog8.PgNamespace
+-- Copyright   : 2013 Kei Hibino, 2014 Shohei Murayama
+-- License     : BSD3
+--
+-- Maintainer  : shohei.murayama@gmail.com
+-- Stability   : experimental
+-- Portability : unknown
+module Database.Relational.Schema.PgCatalog8.PgNamespace where
+
+import Data.Int (Int32)
+
+import Database.Record.TH (derivingShow)
+import Database.Relational.Query.TH (defineTableTypesAndRecordDefault)
+
+import Database.Relational.Schema.PgCatalog8.Config (config)
+
+$(defineTableTypesAndRecordDefault config
+  "PG_CATALOG" "pg_namespace"
+  [("oid"    , [t| Int32 |]),
+ -- nspname  | name      | not null
+   ("nspname", [t| String |])
+ -- nspowner | oid       | not null
+ -- nspacl   | aclitem[] |
+  ]
+  [derivingShow])
diff --git a/src/Database/Relational/Schema/PgCatalog8/PgType.hs b/src/Database/Relational/Schema/PgCatalog8/PgType.hs
new file mode 100644
--- /dev/null
+++ b/src/Database/Relational/Schema/PgCatalog8/PgType.hs
@@ -0,0 +1,90 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE FlexibleInstances #-}
+
+-- |
+-- Module      : Database.Relational.Schema.PgCatalog8.PgType
+-- Copyright   : 2013 Kei Hibino, 2014 Shohei Murayama
+-- License     : BSD3
+--
+-- Maintainer  : shohei.murayama@gmail.com
+-- Stability   : experimental
+-- Portability : unknown
+module Database.Relational.Schema.PgCatalog8.PgType where
+
+import Data.Int (Int16, Int32)
+
+import Database.Record.TH (derivingShow)
+import Database.Relational.Query.TH (defineTableTypesAndRecordDefault)
+
+import Database.Relational.Schema.PgCatalog8.Config (config)
+
+$(defineTableTypesAndRecordDefault config
+  "PG_CATALOG" "pg_type"
+
+  [
+    ("oid", [t|Int32|]),
+-- Table "pg_catalog.pg_type"
+--      Column     |     Type     | Modifiers
+-- ----------------+--------------+-----------
+--  oid            | oid          | not null <= since 9.3
+--  typname        | name         | not null
+    ("typname", [t|String|]),
+--  typnamespace   | oid          | not null
+    ("typnamespace", [t|Int32|]),
+--  typowner       | oid          | not null
+    ("typowner", [t|Int32|]),
+--  typlen         | smallint     | not null
+    ("typlen", [t|Int16|]),
+--  typbyval       | boolean      | not null
+    ("typbyval", [t|Bool|]),
+--  typtype        | "char"       | not null
+    ("typtype", [t|Char|]),
+--  typcategory    | "char"       | not null <= since 8.4
+    --("typcategory", [t|Char|]),
+--  typispreferred | boolean      | not null <= since 8.4
+    --("typispreferred", [t|Bool|]),
+--  typisdefined   | boolean      | not null
+    ("typisdefined", [t|Bool|]),
+--  typdelim       | "char"       | not null
+    ("typdelim", [t|Char|]),
+--  typrelid       | oid          | not null
+    ("typrelid", [t|Int32|]),
+--  typelem        | oid          | not null
+    ("typelem", [t|Int32|]),
+--  typarray       | oid          | not null <= since 8.3
+    --("typarray", [t|Int32|]),
+--  typinput       | regproc      | not null
+    -- ("typinput", [t||]),
+--  typoutput      | regproc      | not null
+    -- ("typoutput", [t||]),
+--  typreceive     | regproc      | not null
+    -- ("typreceive", [t||]),
+--  typsend        | regproc      | not null
+    -- ("typsend", [t||]),
+--  typmodin       | regproc      | not null <= since 8.3
+    -- ("typmodin", [t||]),
+--  typmodout      | regproc      | not null <= since 8.3
+    -- ("typmodout", [t||]),
+--  typanalyze     | regproc      | not null
+    -- ("typanalyze", [t||]),
+--  typalign       | "char"       | not null
+    ("typalign", [t|Char|]),
+--  typstorage     | "char"       | not null
+    ("typstorage", [t|Char|]),
+--  typnotnull     | boolean      | not null
+    ("typnotnull", [t|Bool|]),
+--  typbasetype    | oid          | not null
+    ("typbasetype", [t|Int32|]),
+--  typtypmod      | integer      | not null
+    ("typtypmod", [t|Int32|]),
+--  typndims       | integer      | not null
+    ("typndims", [t|Int32|]),
+--  typcollation   | oid          | not null <= since 9.1
+    --("typcollation", [t|Int32|]),
+--  typdefaultbin  | pg_node_tree |
+    -- ("typdefaultbin", [t||]),
+--  typdefault     | text         |
+    ("typdefault", [t|Maybe String|])
+--  typacl         | aclitem[]    |          <= since 9.2
+  ]
+  [derivingShow])
diff --git a/src/Database/Relational/Schema/PostgreSQL8.hs b/src/Database/Relational/Schema/PostgreSQL8.hs
new file mode 100644
--- /dev/null
+++ b/src/Database/Relational/Schema/PostgreSQL8.hs
@@ -0,0 +1,222 @@
+{-# LANGUAGE TemplateHaskell #-}
+
+-- |
+-- Module      : Database.Relational.Schema.PostgreSQL8
+-- Copyright   : 2013 Kei Hibino, 2014 Shohei Murayama
+-- License     : BSD3
+--
+-- Maintainer  : shohei.murayama@gmail.com
+-- Stability   : experimental
+-- Portability : unknown
+--
+-- This module implements queries to get
+-- table schema and table constraint informations
+-- from system catalog of PostgreSQL.
+module Database.Relational.Schema.PostgreSQL8 (
+  Column,
+
+  normalizeColumn, notNull, getType,
+
+  columnQuerySQL,
+  primaryKeyLengthQuerySQL, primaryKeyQuerySQL
+  ) where
+
+import Prelude hiding (or)
+
+import Language.Haskell.TH (TypeQ)
+
+import Data.Int (Int16, Int32, Int64)
+import Data.Char (toLower)
+import Data.List (foldl1')
+import Data.Map (Map, fromList)
+import qualified Data.Map as Map
+import Data.Time
+  (DiffTime, NominalDiffTime,
+   LocalTime, ZonedTime, Day, TimeOfDay)
+
+import Database.Relational.Query.Type (relationalQuery)
+import Database.Relational.Query
+  (Query, Relation, query, query', relation', relation, union,
+   wheres, (.=.), (.>.), in', values, (!), fst', snd',
+   placeholder, asc, value, unsafeProjectSql, (><))
+
+import Database.Relational.Schema.PgCatalog8.PgNamespace (pgNamespace)
+import qualified Database.Relational.Schema.PgCatalog8.PgNamespace as Namespace
+import Database.Relational.Schema.PgCatalog8.PgClass (pgClass)
+import qualified Database.Relational.Schema.PgCatalog8.PgClass as Class
+import Database.Relational.Schema.PgCatalog8.PgConstraint (PgConstraint, pgConstraint)
+import qualified Database.Relational.Schema.PgCatalog8.PgConstraint as Constraint
+
+import Database.Relational.Schema.PgCatalog8.PgAttribute (PgAttribute, pgAttribute)
+import qualified Database.Relational.Schema.PgCatalog8.PgAttribute as Attr
+import Database.Relational.Schema.PgCatalog8.PgType (PgType(..), pgType)
+import qualified Database.Relational.Schema.PgCatalog8.PgType as Type
+
+import Control.Applicative ((<|>))
+
+
+-- | Mapping between type in PostgreSQL and Haskell type.
+mapFromSqlDefault :: Map String TypeQ
+mapFromSqlDefault =
+  fromList [("bool",         [t| Bool |]),
+            ("char",         [t| Char |]),
+            ("name",         [t| String |]),
+            ("int8",         [t| Int64 |]),
+            ("int2",         [t| Int16 |]),
+            ("int4",         [t| Int32 |]),
+            -- ("regproc",      [t| Int32 |]),
+            ("text",         [t| String |]),
+            ("oid",          [t| Int32 |]),
+            -- ("pg_node_tree", [t| String |]),
+            ("float4",       [t| Float |]),
+            ("float8",       [t| Double |]),
+            ("abstime",      [t| LocalTime |]),
+            ("reltime",      [t| NominalDiffTime |]),
+            ("tinterval",    [t| DiffTime |]),
+            -- ("money",        [t| Decimal |]),
+            ("bpchar",       [t| String |]),
+            ("varchar",      [t| String |]),
+            ("date",         [t| Day |]),
+            ("time",         [t| TimeOfDay |]),
+            ("timestamp",    [t| LocalTime |]),
+            ("timestamptz",  [t| ZonedTime |]),
+            ("interval",     [t| DiffTime |]),
+            ("timetz",       [t| ZonedTime |])
+
+            -- ("bit", [t|  |]),
+            -- ("varbit", [t|  |]),
+            -- ("numeric", [t| Decimal |])
+           ]
+
+-- | Normalize column name string to query PostgreSQL system catalog.
+normalizeColumn :: String -> String
+normalizeColumn =  map toLower
+
+-- | Type to represent Column information.
+type Column = (PgAttribute, PgType)
+
+-- | Not-null attribute information of column.
+notNull :: Column -> Bool
+notNull =  Attr.attnotnull . fst
+
+-- | Get column normalized name and column Haskell type.
+getType :: Map String TypeQ      -- ^ Type mapping specified by user
+        -> Column                -- ^ Column info in system catalog
+        -> Maybe (String, TypeQ) -- ^ Result normalized name and mapped Haskell type
+getType mapFromSql column@(pgAttr, pgTyp) = do
+  typ <- (Map.lookup key mapFromSql
+          <|>
+          Map.lookup key mapFromSqlDefault)
+  return (normalizeColumn $ Attr.attname pgAttr,
+          mayNull typ)
+  where key = Type.typname pgTyp
+        mayNull typ = if notNull column
+                      then typ
+                      else [t| Maybe $typ |]
+
+-- | 'Relation' to query PostgreSQL relation oid from schema name and table name.
+relOidRelation :: Relation (String, String) Int32
+relOidRelation = relation' $ do
+  nsp <- query pgNamespace
+  cls <- query pgClass
+
+  wheres $ cls ! Class.relnamespace' .=. nsp ! Namespace.oid'
+  (nspP, ()) <- placeholder (\ph -> wheres $ nsp ! Namespace.nspname'  .=. ph)
+  (relP, ()) <- placeholder (\ph -> wheres $ cls ! Class.relname'      .=. ph)
+
+  return   (nspP >< relP, cls ! Class.oid')
+
+-- | 'Relation' to query column attribute from schema name and table name.
+attributeRelation :: Relation (String, String) PgAttribute
+attributeRelation =  relation' $ do
+  (ph, reloid) <- query' relOidRelation
+  att          <- query  pgAttribute
+
+  wheres $ att ! Attr.attrelid' .=. reloid
+  wheres $ att ! Attr.attnum'   .>. value 0
+
+  return   (ph, att)
+
+-- | 'Relation' to query 'Column' from schema name and table name.
+columnRelation :: Relation (String, String) Column
+columnRelation = relation' $ do
+  (ph, att) <- query' attributeRelation
+  typ       <- query  pgType
+
+  wheres $ att ! Attr.atttypid'    .=. typ ! Type.oid'
+  wheres $ typ ! Type.typtype'     .=. value 'b'  -- 'b': base type only
+
+--wheres $ typ ! Type.typcategory' `in'` values [ 'B' -- Boolean types
+--                                              , 'D' -- Date/time types
+--                                              , 'N' -- Numeric types
+--                                              , 'S' -- String types
+--                                              , 'T' -- typespan types
+--                                              ]
+
+  wheres $ typ ! Type.typname'  `in'` values
+      [ "bool", "char", "name", "int8", "int2", "int4" , "regproc" , "text"
+      , "oid" , "pg_node_tree" , "float4" , "float8" , "abstime" , "reltime"
+      , "tinterval" , "money" , "bpchar" , "varchar" , "date" , "time"
+      , "timestamp" , "timestamptz" , "interval" , "timetz" , "numeric"
+      , "regprocedure" , "regoper" , "regoperator" , "regclass" , "regtype"
+      , "regconfig" , "regdictionary"
+      ]
+
+  asc $ att ! Attr.attnum'
+
+  return (ph, att >< typ)
+
+-- | Phantom typed 'Query' to get 'Column' from schema name and table name.
+columnQuerySQL :: Query (String, String) Column
+columnQuerySQL =  relationalQuery columnRelation
+
+-- | 'Relation' to query primary key length from schema name and table name.
+primaryKeyLengthRelation :: Relation (String, String) Int32
+primaryKeyLengthRelation =  relation' $ do
+  (ph, reloid) <- query' relOidRelation
+  con       <- query  pgConstraint
+
+  wheres $ con ! Constraint.conrelid' .=. reloid
+  wheres $ con ! Constraint.contype'  .=. value 'p'  -- 'p': primary key constraint type
+
+  --return (ph, unsafeProjectSql "array_length (conkey, 1)")
+  return (ph, unsafeProjectSql "array_upper (conkey, 1) - array_lower (conkey, 1) + 1")
+
+-- | Phantom typed 'Query' to get primary key length from schema name and table name.
+primaryKeyLengthQuerySQL :: Query (String, String) Int32
+primaryKeyLengthQuerySQL =  relationalQuery primaryKeyLengthRelation
+
+-- | One column which is nth column of composite primary key.
+constraintColRelation :: Int32 -> Relation () (PgConstraint, (Int16, Int32))
+constraintColRelation i = relation $ do
+  con <- query pgConstraint
+
+  return $ con >< (unsafeProjectSql ("conkey[" ++ show i ++ "]") >< value i)
+
+-- | Make composite primary key relation from primary key length.
+constraintColExpandRelation :: Int32 -> Relation () (PgConstraint, (Int16, Int32))
+constraintColExpandRelation n =
+  foldl1' union [constraintColRelation i | i <- [1..n] ]
+
+-- | 'Relation' to query primary key name from schema name and table name.
+primaryKeyRelation :: Int32 -> Relation (String, String) String
+primaryKeyRelation n = relation' $ do
+  (ph, att) <- query' attributeRelation
+  conEx     <- query  (constraintColExpandRelation n)
+
+  let con = conEx ! fst'
+      col' = conEx ! snd'
+      keyIx = col' ! fst'
+      keyN  = col' ! snd'
+
+  wheres $ con ! Constraint.conrelid' .=. att ! Attr.attrelid'
+  wheres $ keyIx .=. att ! Attr.attnum'
+  wheres $ con ! Constraint.contype'  .=. value 'p'  -- 'p': primary key constraint type
+
+  asc  $ keyN
+
+  return (ph, att ! Attr.attname')
+
+-- | Phantom typed 'Query' to get primary key name from schema name and table name.
+primaryKeyQuerySQL :: Int32 -> Query (String, String) String
+primaryKeyQuerySQL =  relationalQuery . primaryKeyRelation
