{-# LANGUAGE OverloadedStrings #-}

module IpeDb.Table (
  InfoProvRow (..),
  dropStringTableStmt,
  dropInfoProvTableStmt,
  dropInfoProvTableViewStmt,
  stringTableStmt,
  infoProvTableStmt,
  infoProvTableViewStmt,
  findInfoTableQuery,
  findAllInfoTablesQuery,
  insertInfoTableQuery,
  insertOrIgnoreString,
  getStringEntry,
  getIpeStrings,
) where

import Data.Int
import qualified Database.SQLite.Simple as Sqlite
import IpeDb.InfoProv
import GHC.Generics (Generic)

data InfoProvRow = InfoProvRow
  { InfoProvRow -> IpeId
infoId :: !IpeId
  , InfoProvRow -> Int64
tableName :: !Int64
  , InfoProvRow -> Int64
closureDesc :: !Int64
  , InfoProvRow -> Int64
typeDesc :: !Int64
  , InfoProvRow -> Int64
label :: !Int64
  , InfoProvRow -> Int64
moduleName :: !Int64
  , InfoProvRow -> Int64
srcLoc :: !Int64
  }
  deriving (Int -> InfoProvRow -> ShowS
[InfoProvRow] -> ShowS
InfoProvRow -> String
(Int -> InfoProvRow -> ShowS)
-> (InfoProvRow -> String)
-> ([InfoProvRow] -> ShowS)
-> Show InfoProvRow
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> InfoProvRow -> ShowS
showsPrec :: Int -> InfoProvRow -> ShowS
$cshow :: InfoProvRow -> String
show :: InfoProvRow -> String
$cshowList :: [InfoProvRow] -> ShowS
showList :: [InfoProvRow] -> ShowS
Show, InfoProvRow -> InfoProvRow -> Bool
(InfoProvRow -> InfoProvRow -> Bool)
-> (InfoProvRow -> InfoProvRow -> Bool) -> Eq InfoProvRow
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: InfoProvRow -> InfoProvRow -> Bool
== :: InfoProvRow -> InfoProvRow -> Bool
$c/= :: InfoProvRow -> InfoProvRow -> Bool
/= :: InfoProvRow -> InfoProvRow -> Bool
Eq, Eq InfoProvRow
Eq InfoProvRow =>
(InfoProvRow -> InfoProvRow -> Ordering)
-> (InfoProvRow -> InfoProvRow -> Bool)
-> (InfoProvRow -> InfoProvRow -> Bool)
-> (InfoProvRow -> InfoProvRow -> Bool)
-> (InfoProvRow -> InfoProvRow -> Bool)
-> (InfoProvRow -> InfoProvRow -> InfoProvRow)
-> (InfoProvRow -> InfoProvRow -> InfoProvRow)
-> Ord InfoProvRow
InfoProvRow -> InfoProvRow -> Bool
InfoProvRow -> InfoProvRow -> Ordering
InfoProvRow -> InfoProvRow -> InfoProvRow
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: InfoProvRow -> InfoProvRow -> Ordering
compare :: InfoProvRow -> InfoProvRow -> Ordering
$c< :: InfoProvRow -> InfoProvRow -> Bool
< :: InfoProvRow -> InfoProvRow -> Bool
$c<= :: InfoProvRow -> InfoProvRow -> Bool
<= :: InfoProvRow -> InfoProvRow -> Bool
$c> :: InfoProvRow -> InfoProvRow -> Bool
> :: InfoProvRow -> InfoProvRow -> Bool
$c>= :: InfoProvRow -> InfoProvRow -> Bool
>= :: InfoProvRow -> InfoProvRow -> Bool
$cmax :: InfoProvRow -> InfoProvRow -> InfoProvRow
max :: InfoProvRow -> InfoProvRow -> InfoProvRow
$cmin :: InfoProvRow -> InfoProvRow -> InfoProvRow
min :: InfoProvRow -> InfoProvRow -> InfoProvRow
Ord, (forall x. InfoProvRow -> Rep InfoProvRow x)
-> (forall x. Rep InfoProvRow x -> InfoProvRow)
-> Generic InfoProvRow
forall x. Rep InfoProvRow x -> InfoProvRow
forall x. InfoProvRow -> Rep InfoProvRow x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. InfoProvRow -> Rep InfoProvRow x
from :: forall x. InfoProvRow -> Rep InfoProvRow x
$cto :: forall x. Rep InfoProvRow x -> InfoProvRow
to :: forall x. Rep InfoProvRow x -> InfoProvRow
Generic)
  deriving anyclass (RowParser InfoProvRow
RowParser InfoProvRow -> FromRow InfoProvRow
forall a. RowParser a -> FromRow a
$cfromRow :: RowParser InfoProvRow
fromRow :: RowParser InfoProvRow
Sqlite.FromRow, InfoProvRow -> [SQLData]
(InfoProvRow -> [SQLData]) -> ToRow InfoProvRow
forall a. (a -> [SQLData]) -> ToRow a
$ctoRow :: InfoProvRow -> [SQLData]
toRow :: InfoProvRow -> [SQLData]
Sqlite.ToRow)

dropStringTableStmt :: Sqlite.Query
dropStringTableStmt :: Query
dropStringTableStmt = Query
"DROP TABLE IF EXISTS strings;"

dropInfoProvTableStmt :: Sqlite.Query
dropInfoProvTableStmt :: Query
dropInfoProvTableStmt = Query
"DROP TABLE IF EXISTS info_prov;"

dropInfoProvTableViewStmt :: Sqlite.Query
dropInfoProvTableViewStmt :: Query
dropInfoProvTableViewStmt = Query
"DROP VIEW IF EXISTS view_info_prov;"

stringTableStmt :: Sqlite.Query
stringTableStmt :: Query
stringTableStmt =
  Query
"\
  \ CREATE TABLE strings (                        \
  \    id INTEGER PRIMARY KEY,                    \
  \    value TEXT NOT NULL UNIQUE                 \
  \);"

infoProvTableStmt :: Sqlite.Query
infoProvTableStmt :: Query
infoProvTableStmt =
  Query
"\
  \ CREATE TABLE info_prov (                                \
  \    info_id      INTEGER PRIMARY KEY,                    \
  \    table_name   INTEGER NOT NULL REFERENCES strings(id),\
  \    closure_desc INTEGER NOT NULL,                       \
  \    type_desc    INTEGER NOT NULL REFERENCES strings(id),\
  \    label        INTEGER NOT NULL REFERENCES strings(id),\
  \    module_name  INTEGER NOT NULL REFERENCES strings(id),\
  \    src_loc      INTEGER NOT NULL REFERENCES strings(id) \
  \);"

infoProvTableViewStmt :: Sqlite.Query
infoProvTableViewStmt :: Query
infoProvTableViewStmt =
  Query
"\
  \ CREATE VIEW view_info_prov AS                                  \
  \ SELECT                                                         \
  \   i.info_id,                                                   \
  \   table_name.value AS table_name,                              \
  \   i.closure_desc,                                              \
  \   type_desc.value AS type_desc,                                \
  \   label.value AS label,                                        \
  \   module_name.value AS module_name,                            \
  \   src_loc.value AS src_loc                                     \
  \ FROM info_prov i                                               \
  \ JOIN strings AS table_name   ON i.table_name = table_name.id   \
  \ JOIN strings AS type_desc    ON i.type_desc = type_desc.id     \
  \ JOIN strings AS label        ON i.label = label.id             \
  \ JOIN strings AS module_name  ON i.module_name = module_name.id \
  \ JOIN strings AS src_loc      ON i.src_loc = src_loc.id;"

findInfoTableQuery :: Sqlite.Query
findInfoTableQuery :: Query
findInfoTableQuery = Query
"SELECT * FROM view_info_prov WHERE info_id = ?;"

findAllInfoTablesQuery :: Sqlite.Query
findAllInfoTablesQuery :: Query
findAllInfoTablesQuery = Query
"SELECT * FROM view_info_prov;"

insertInfoTableQuery :: Sqlite.Query
insertInfoTableQuery :: Query
insertInfoTableQuery =
  Query
"\
  \ INSERT INTO info_prov\
  \   (info_id, table_name, closure_desc, type_desc, label, module_name, src_loc)\
  \ VALUES (?, ?, ?, ?, ?, ?, ?);"

insertOrIgnoreString :: Sqlite.Query
insertOrIgnoreString :: Query
insertOrIgnoreString = Query
"INSERT OR IGNORE INTO strings(value) VALUES (?);"

getIpeStrings :: Sqlite.Query
getIpeStrings :: Query
getIpeStrings =
  Query
"\
  \ SELECT                                             \
  \   table_name.id AS table_name,                     \
  \   type_desc.id AS type_desc,                       \
  \   label.id AS label,                               \
  \   module_name.id AS module_name,                   \
  \   src_loc.id AS src_loc                            \
  \ FROM strings AS table_name    \
  \ JOIN strings AS type_desc    ON ? = type_desc.value   \
  \ JOIN strings AS label        ON ? = label.value       \
  \ JOIN strings AS module_name  ON ? = module_name.value \
  \ JOIN strings AS src_loc      ON ? = src_loc.value\
  \  WHERE ? = table_name.value ;"

getStringEntry :: Sqlite.Query
getStringEntry :: Query
getStringEntry = Query
"SELECT id, value FROM strings WHERE value = ?;"