generic-persistence-0.2.0.0: src/Database/GP/SqlGenerator.hs
module Database.GP.SqlGenerator
( insertStmtFor,
updateStmtFor,
selectStmtFor,
deleteStmtFor,
selectAllStmtFor,
selectAllWhereStmtFor,
createTableStmtFor,
dropTableStmtFor,
)
where
import Data.List (intercalate)
import Database.GP.Entity
import Database.GP.TypeInfo
-- | A function that returns an SQL insert statement for an entity. Type 'a' must be an instance of Data.
-- The function will use the field names of the data type to generate the column names in the insert statement.
-- The values of the fields will be used as the values in the insert statement.
-- Output example: INSERT INTO Person (id, name, age, address) VALUES (123456, "Alice", 25, "123 Main St");
insertStmtFor :: Entity a => a -> String
insertStmtFor x =
"INSERT INTO "
++ tableName x
++ " ("
++ intercalate ", " columns
++ ") VALUES ("
++ intercalate ", " (params (length columns))
++ ");"
where
columns = columnNamesFor x
columnNamesFor :: Entity a => a -> [String]
columnNamesFor x = map snd fieldColumnPairs
where
fieldColumnPairs = fieldsToColumns x
params :: Int -> [String]
params n = replicate n "?"
-- | A function that returns an SQL update statement for an entity. Type 'a' must be an instance of Entity.
updateStmtFor :: Entity a => a -> String
updateStmtFor x =
"UPDATE "
++ tableName x
++ " SET "
++ intercalate ", " updatePairs
++ " WHERE "
++ idColumn x
++ " = ?"
++ ";"
where
updatePairs = map (++ " = ?") (columnNamesFor x)
idColumn :: Entity a => a -> String
idColumn x = columnNameFor x (idField x)
-- | A function that returns an SQL select statement for entity type `a` with primary key `id`.
selectStmtFor :: forall a. (Entity a) => TypeInfo a -> String
selectStmtFor ti =
"SELECT "
++ intercalate ", " (columnNamesFor x)
++ " FROM "
++ tableName x
++ " WHERE "
++ idColumn x
++ " = ?;"
where
x = evidenceFrom ti :: a
selectAllStmtFor :: forall a. (Entity a) => TypeInfo a -> String
selectAllStmtFor ti =
"SELECT "
++ intercalate ", " (columnNamesFor x)
++ " FROM "
++ tableName x
++ ";"
where
x = evidenceFrom ti :: a
selectAllWhereStmtFor :: forall a. (Entity a) => TypeInfo a -> String -> String
selectAllWhereStmtFor ti field =
"SELECT "
++ intercalate ", " (columnNamesFor x)
++ " FROM "
++ tableName x
++ " WHERE "
++ column
++ " = ?;"
where
x = evidenceFrom ti :: a
column = columnNameFor x field
deleteStmtFor :: Entity a => a -> String
deleteStmtFor x =
"DELETE FROM "
++ tableName x
++ " WHERE "
++ idColumn x
++ " = ?;"
createTableStmtFor :: forall a. (Entity a) => TypeInfo a -> String
createTableStmtFor ti =
"CREATE TABLE "
++ tableName x
++ " ("
++ intercalate ", " (map (\(f,c) -> c ++ " " ++ columnTypeFor x f ++ optionalPK f) (fieldsToColumns x))
++ ");"
where
x = evidenceFrom ti :: a
isIdField f = f == idField x
optionalPK f = if isIdField f then " PRIMARY KEY" else ""
columnTypeFor :: forall a. (Entity a) => a -> String -> String
columnTypeFor x field =
case fType of
"Int" -> "INTEGER"
"String" -> "TEXT"
"Double" -> "REAL"
"Float" -> "REAL"
"Bool" -> "INT"
_ -> "TEXT"
where
maybeFType = maybeFieldTypeFor x field
fType = maybe "OTHER" show maybeFType
dropTableStmtFor :: forall a. (Entity a) => TypeInfo a -> String
dropTableStmtFor ti =
"DROP TABLE IF EXISTS "
++ tableName x
++ ";"
where
x = evidenceFrom ti :: a