{-|
Module: IHP.IDE.SchemaDesigner.Compiler
Description: Compiles AST of SQL to DDL
Copyright: (c) digitally induced GmbH, 2020
-}
module IHP.IDE.SchemaDesigner.Compiler (compileSql, writeSchema, compileIdentifier, compileExpression, compilePostgresType, compileIndexColumn) where

import IHP.Prelude
import IHP.IDE.SchemaDesigner.Types
import Data.Maybe (fromJust)
import qualified Data.Text.IO as Text
import qualified Data.Text as Text

writeSchema :: [Statement] -> IO ()
writeSchema :: [Statement] -> IO ()
writeSchema ![Statement]
statements = do
    let sortedStatements :: [Statement]
sortedStatements = (Statement -> Statement -> Ordering) -> [Statement] -> [Statement]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy Statement -> Statement -> Ordering
compareStatement [Statement]
statements
    FilePath -> Text -> IO ()
Text.writeFile FilePath
"Application/Schema.sql" ([Statement] -> Text
compileSql [Statement]
sortedStatements)

compileSql :: [Statement] -> Text
compileSql :: [Statement] -> Text
compileSql [Statement]
statements = [Statement]
statements
    [Statement] -> ([Statement] -> [Text]) -> [Text]
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> (Statement -> Text) -> [Statement] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Statement -> Text
compileStatement
    [Text] -> ([Text] -> Text) -> Text
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> [Text] -> Text
unlines

compileStatement :: Statement -> Text
compileStatement :: Statement -> Text
compileStatement (StatementCreateTable CreateTable { Text
name :: Text
$sel:name:CreateTable :: CreateTable -> Text
name, [Column]
columns :: [Column]
$sel:columns:CreateTable :: CreateTable -> [Column]
columns, PrimaryKeyConstraint
primaryKeyConstraint :: PrimaryKeyConstraint
$sel:primaryKeyConstraint:CreateTable :: CreateTable -> PrimaryKeyConstraint
primaryKeyConstraint, [Constraint]
constraints :: [Constraint]
$sel:constraints:CreateTable :: CreateTable -> [Constraint]
constraints, Bool
unlogged :: Bool
$sel:unlogged:CreateTable :: CreateTable -> Bool
unlogged }) = Text
"CREATE" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (if Bool
unlogged then Text
" UNLOGGED" else Text
"") Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" TABLE " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" (\n" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
intercalate Text
",\n" ((Column -> Text) -> [Column] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (\Column
col -> Text
"    " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> PrimaryKeyConstraint -> Column -> Text
compileColumn PrimaryKeyConstraint
primaryKeyConstraint Column
col) [Column]
columns [Text] -> [Text] -> [Text]
forall a. Semigroup a => a -> a -> a
<> [Text] -> (Text -> [Text]) -> Maybe Text -> [Text]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] ((Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
:[]) (Text -> [Text]) -> (Text -> Text) -> Text -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Text -> Text
forall {a}. (Semigroup a, IsString a) => a -> a
indent) (PrimaryKeyConstraint -> Maybe Text
compilePrimaryKeyConstraint PrimaryKeyConstraint
primaryKeyConstraint) [Text] -> [Text] -> [Text]
forall a. Semigroup a => a -> a -> a
<> (Constraint -> Text) -> [Constraint] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (Text -> Text
forall {a}. (Semigroup a, IsString a) => a -> a
indent (Text -> Text) -> (Constraint -> Text) -> Constraint -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Constraint -> Text
compileConstraint) [Constraint]
constraints) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\n);"
compileStatement CreateEnumType { Text
name :: Text
$sel:name:StatementCreateTable :: Statement -> Text
name, [Text]
values :: [Text]
$sel:values:StatementCreateTable :: Statement -> [Text]
values } = Text
"CREATE TYPE " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" AS ENUM (" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
intercalate Text
", " ([Text]
values [Text] -> ([Text] -> [Expression]) -> [Expression]
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> (Text -> Expression) -> [Text] -> [Expression]
forall a b. (a -> b) -> [a] -> [b]
map Text -> Expression
TextExpression [Expression] -> ([Expression] -> [Text]) -> [Text]
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> (Expression -> Text) -> [Expression] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Expression -> Text
compileExpression) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
");"
compileStatement CreateExtension { Text
$sel:name:StatementCreateTable :: Statement -> Text
name :: Text
name, Bool
ifNotExists :: Bool
$sel:ifNotExists:StatementCreateTable :: Statement -> Bool
ifNotExists } = Text
"CREATE EXTENSION " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (if Bool
ifNotExists then Text
"IF NOT EXISTS " else Text
"") Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement AddConstraint { Text
tableName :: Text
$sel:tableName:StatementCreateTable :: Statement -> Text
tableName, $sel:constraint:StatementCreateTable :: Statement -> Constraint
constraint = UniqueConstraint { $sel:name:ForeignKeyConstraint :: Constraint -> Maybe Text
name = Maybe Text
Nothing, [Text]
columnNames :: [Text]
$sel:columnNames:ForeignKeyConstraint :: Constraint -> [Text]
columnNames } } = Text
"ALTER TABLE " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
tableName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" ADD UNIQUE (" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
intercalate Text
", " [Text]
columnNames Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement AddConstraint { Text
$sel:tableName:StatementCreateTable :: Statement -> Text
tableName :: Text
tableName, Constraint
$sel:constraint:StatementCreateTable :: Statement -> Constraint
constraint :: Constraint
constraint, Maybe Bool
deferrable :: Maybe Bool
$sel:deferrable:StatementCreateTable :: Statement -> Maybe Bool
deferrable, Maybe DeferrableType
deferrableType :: Maybe DeferrableType
$sel:deferrableType:StatementCreateTable :: Statement -> Maybe DeferrableType
deferrableType } = Text
"ALTER TABLE " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
tableName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" ADD CONSTRAINT " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier (Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe (Text -> Text
forall a. Text -> a
error Text
"compileStatement: Expected constraint name") (Constraint
constraint.name)) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Constraint -> Text
compileConstraint Constraint
constraint Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Maybe Bool -> Maybe DeferrableType -> Text
compileDeferrable Maybe Bool
deferrable Maybe DeferrableType
deferrableType Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement AddColumn { Text
$sel:tableName:StatementCreateTable :: Statement -> Text
tableName :: Text
tableName, Column
column :: Column
$sel:column:StatementCreateTable :: Statement -> Column
column } = Text
"ALTER TABLE " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
tableName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" ADD COLUMN " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (PrimaryKeyConstraint -> Column -> Text
compileColumn ([Text] -> PrimaryKeyConstraint
PrimaryKeyConstraint []) Column
column) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement DropColumn { Text
$sel:tableName:StatementCreateTable :: Statement -> Text
tableName :: Text
tableName, Text
columnName :: Text
$sel:columnName:StatementCreateTable :: Statement -> Text
columnName } = Text
"ALTER TABLE " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
tableName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" DROP COLUMN " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
columnName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement RenameColumn { Text
$sel:tableName:StatementCreateTable :: Statement -> Text
tableName :: Text
tableName, Text
from :: Text
$sel:from:StatementCreateTable :: Statement -> Text
from, Text
to :: Text
$sel:to:StatementCreateTable :: Statement -> Text
to } = Text
"ALTER TABLE " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
tableName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" RENAME COLUMN " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
from Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" TO " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
to Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement DropTable { Text
$sel:tableName:StatementCreateTable :: Statement -> Text
tableName :: Text
tableName } = Text
"DROP TABLE " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
tableName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement Comment { Text
content :: Text
$sel:content:StatementCreateTable :: Statement -> Text
content } = Text
"--" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
content
compileStatement CreateIndex { Text
indexName :: Text
$sel:indexName:StatementCreateTable :: Statement -> Text
indexName, Bool
unique :: Bool
$sel:unique:StatementCreateTable :: Statement -> Bool
unique, Text
$sel:tableName:StatementCreateTable :: Statement -> Text
tableName :: Text
tableName, [IndexColumn]
columns :: [IndexColumn]
$sel:columns:StatementCreateTable :: Statement -> [IndexColumn]
columns, Maybe Expression
whereClause :: Maybe Expression
$sel:whereClause:StatementCreateTable :: Statement -> Maybe Expression
whereClause, Maybe IndexType
indexType :: Maybe IndexType
$sel:indexType:StatementCreateTable :: Statement -> Maybe IndexType
indexType } = Text
"CREATE" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (if Bool
unique then Text
" UNIQUE " else Text
" ") Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"INDEX " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
indexName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" ON " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
tableName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (Text -> (IndexType -> Text) -> Maybe IndexType -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" (\IndexType
indexType -> Text
" USING " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> IndexType -> Text
compileIndexType IndexType
indexType) Maybe IndexType
indexType) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" (" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (Text -> [Text] -> Text
intercalate Text
", " ((IndexColumn -> Text) -> [IndexColumn] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map IndexColumn -> Text
compileIndexColumn [IndexColumn]
columns)) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (case Maybe Expression
whereClause of Just Expression
expression -> Text
" WHERE " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpression Expression
expression; Maybe Expression
Nothing -> Text
"") Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement CreateFunction { Text
functionName :: Text
$sel:functionName:StatementCreateTable :: Statement -> Text
functionName, [(Text, PostgresType)]
functionArguments :: [(Text, PostgresType)]
$sel:functionArguments:StatementCreateTable :: Statement -> [(Text, PostgresType)]
functionArguments, Text
functionBody :: Text
$sel:functionBody:StatementCreateTable :: Statement -> Text
functionBody, Bool
orReplace :: Bool
$sel:orReplace:StatementCreateTable :: Statement -> Bool
orReplace, PostgresType
returns :: PostgresType
$sel:returns:StatementCreateTable :: Statement -> PostgresType
returns, Text
language :: Text
$sel:language:StatementCreateTable :: Statement -> Text
language } = Text
"CREATE " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (if Bool
orReplace then Text
"OR REPLACE " else Text
"") Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"FUNCTION " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
functionName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ([(Text, PostgresType)]
functionArguments [(Text, PostgresType)]
-> ([(Text, PostgresType)] -> [Text]) -> [Text]
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> ((Text, PostgresType) -> Text) -> [(Text, PostgresType)] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (\(Text
argName, PostgresType
argType) -> Text
argName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
++ Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
++ PostgresType -> Text
compilePostgresType PostgresType
argType) [Text] -> ([Text] -> Text) -> Text
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> Text -> [Text] -> Text
intercalate  Text
", ") Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" RETURNS " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> PostgresType -> Text
compilePostgresType PostgresType
returns Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" AS $$" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
functionBody Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"$$ language " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
language Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement EnableRowLevelSecurity { Text
$sel:tableName:StatementCreateTable :: Statement -> Text
tableName :: Text
tableName } = Text
"ALTER TABLE " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
tableName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" ENABLE ROW LEVEL SECURITY;"
compileStatement CreatePolicy { Text
$sel:name:StatementCreateTable :: Statement -> Text
name :: Text
name, Maybe PolicyAction
action :: Maybe PolicyAction
$sel:action:StatementCreateTable :: Statement -> Maybe PolicyAction
action, Text
$sel:tableName:StatementCreateTable :: Statement -> Text
tableName :: Text
tableName, Maybe Expression
using :: Maybe Expression
$sel:using:StatementCreateTable :: Statement -> Maybe Expression
using, Maybe Expression
check :: Maybe Expression
$sel:check:StatementCreateTable :: Statement -> Maybe Expression
check } = Text
"CREATE POLICY " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" ON " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
tableName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> (PolicyAction -> Text) -> Maybe PolicyAction -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" (\PolicyAction
action -> Text
" FOR " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> PolicyAction -> Text
compilePolicyAction PolicyAction
action) Maybe PolicyAction
action  Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> (Expression -> Text) -> Maybe Expression -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" (\Expression
expr -> Text
" USING (" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpression Expression
expr Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")") Maybe Expression
using Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> (Expression -> Text) -> Maybe Expression -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" (\Expression
expr -> Text
" WITH CHECK (" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpression Expression
expr Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")") Maybe Expression
check Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement CreateSequence { Text
$sel:name:StatementCreateTable :: Statement -> Text
name :: Text
name } = Text
"CREATE SEQUENCE " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement DropConstraint { Text
$sel:tableName:StatementCreateTable :: Statement -> Text
tableName :: Text
tableName, Text
constraintName :: Text
$sel:constraintName:StatementCreateTable :: Statement -> Text
constraintName } = Text
"ALTER TABLE " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
tableName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" DROP CONSTRAINT " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
constraintName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement DropEnumType { Text
$sel:name:StatementCreateTable :: Statement -> Text
name :: Text
name } = Text
"DROP TYPE " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement DropIndex { Text
$sel:indexName:StatementCreateTable :: Statement -> Text
indexName :: Text
indexName } = Text
"DROP INDEX " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
indexName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement DropNotNull { Text
$sel:tableName:StatementCreateTable :: Statement -> Text
tableName :: Text
tableName, Text
$sel:columnName:StatementCreateTable :: Statement -> Text
columnName :: Text
columnName } = Text
"ALTER TABLE " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
tableName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" ALTER COLUMN " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
columnName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" DROP NOT NULL;"
compileStatement SetNotNull { Text
$sel:tableName:StatementCreateTable :: Statement -> Text
tableName :: Text
tableName, Text
$sel:columnName:StatementCreateTable :: Statement -> Text
columnName :: Text
columnName } = Text
"ALTER TABLE " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
tableName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" ALTER COLUMN " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
columnName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" SET NOT NULL;"
compileStatement RenameTable { Text
$sel:from:StatementCreateTable :: Statement -> Text
from :: Text
from, Text
$sel:to:StatementCreateTable :: Statement -> Text
to :: Text
to } = Text
"ALTER TABLE " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
from Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" RENAME TO " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
to Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement DropPolicy { Text
$sel:tableName:StatementCreateTable :: Statement -> Text
tableName :: Text
tableName, Text
policyName :: Text
$sel:policyName:StatementCreateTable :: Statement -> Text
policyName } =  Text
"DROP POLICY " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
policyName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" ON " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
tableName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement SetDefaultValue { Text
$sel:tableName:StatementCreateTable :: Statement -> Text
tableName :: Text
tableName, Text
$sel:columnName:StatementCreateTable :: Statement -> Text
columnName :: Text
columnName, Expression
value :: Expression
$sel:value:StatementCreateTable :: Statement -> Expression
value } = Text
"ALTER TABLE " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
tableName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" ALTER COLUMN " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
columnName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" SET DEFAULT " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpression Expression
value Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement DropDefaultValue { Text
$sel:tableName:StatementCreateTable :: Statement -> Text
tableName :: Text
tableName, Text
$sel:columnName:StatementCreateTable :: Statement -> Text
columnName :: Text
columnName } = Text
"ALTER TABLE " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
tableName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" ALTER COLUMN " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
columnName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" DROP DEFAULT;"
compileStatement AddValueToEnumType { Text
enumName :: Text
$sel:enumName:StatementCreateTable :: Statement -> Text
enumName, Text
newValue :: Text
$sel:newValue:StatementCreateTable :: Statement -> Text
newValue } = Text
"ALTER TYPE " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
enumName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" ADD VALUE " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpression (Text -> Expression
TextExpression Text
newValue) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement CreateTrigger { Text
$sel:name:StatementCreateTable :: Statement -> Text
name :: Text
name, TriggerEventWhen
eventWhen :: TriggerEventWhen
$sel:eventWhen:StatementCreateTable :: Statement -> TriggerEventWhen
eventWhen, TriggerEvent
event :: TriggerEvent
$sel:event:StatementCreateTable :: Statement -> TriggerEvent
event, Text
$sel:tableName:StatementCreateTable :: Statement -> Text
tableName :: Text
tableName, TriggerFor
for :: TriggerFor
$sel:for:StatementCreateTable :: Statement -> TriggerFor
for, Maybe Expression
whenCondition :: Maybe Expression
$sel:whenCondition:StatementCreateTable :: Statement -> Maybe Expression
whenCondition, Text
$sel:functionName:StatementCreateTable :: Statement -> Text
functionName :: Text
functionName, [Expression]
arguments :: [Expression]
$sel:arguments:StatementCreateTable :: Statement -> [Expression]
arguments } = Text
"CREATE TRIGGER " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> TriggerEventWhen -> Text
compileTriggerEventWhen TriggerEventWhen
eventWhen Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> TriggerEvent -> Text
compileTriggerEvent TriggerEvent
event Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" ON " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
tableName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> TriggerFor -> Text
compileTriggerFor TriggerFor
for Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" EXECUTE FUNCTION " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpression (Text -> [Expression] -> Expression
CallExpression Text
functionName [Expression]
arguments) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement Statement
Begin = Text
"BEGIN;"
compileStatement Statement
Commit = Text
"COMMIT;"
compileStatement DropFunction { Text
$sel:functionName:StatementCreateTable :: Statement -> Text
functionName :: Text
functionName } = Text
"DROP FUNCTION " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
functionName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement UnknownStatement { Text
raw :: Text
$sel:raw:StatementCreateTable :: Statement -> Text
raw } = Text
raw Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement Set { Text
$sel:name:StatementCreateTable :: Statement -> Text
name :: Text
name, Expression
$sel:value:StatementCreateTable :: Statement -> Expression
value :: Expression
value } = Text
"SET " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" = " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpression Expression
value Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement SelectStatement { Text
query :: Text
$sel:query:StatementCreateTable :: Statement -> Text
query } = Text
"SELECT " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
query Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
compileStatement DropTrigger { Text
$sel:name:StatementCreateTable :: Statement -> Text
name :: Text
name, Text
$sel:tableName:StatementCreateTable :: Statement -> Text
tableName :: Text
tableName } = Text
"DROP TRIGGER " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" ON " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
tableName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"

-- | Emit a PRIMARY KEY constraint when there are multiple primary key columns
compilePrimaryKeyConstraint :: PrimaryKeyConstraint -> Maybe Text
compilePrimaryKeyConstraint :: PrimaryKeyConstraint -> Maybe Text
compilePrimaryKeyConstraint PrimaryKeyConstraint { [Text]
primaryKeyColumnNames :: [Text]
$sel:primaryKeyColumnNames:PrimaryKeyConstraint :: PrimaryKeyConstraint -> [Text]
primaryKeyColumnNames } =
    case [Text]
primaryKeyColumnNames of
        [] -> Maybe Text
forall a. Maybe a
Nothing
        [Text
_] -> Maybe Text
forall a. Maybe a
Nothing
        [Text]
names -> Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
"PRIMARY KEY(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
intercalate Text
", " [Text]
names Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")"

compileConstraint :: Constraint -> Text
compileConstraint :: Constraint -> Text
compileConstraint ForeignKeyConstraint { Text
columnName :: Text
$sel:columnName:ForeignKeyConstraint :: Constraint -> Text
columnName, Text
referenceTable :: Text
$sel:referenceTable:ForeignKeyConstraint :: Constraint -> Text
referenceTable, Maybe Text
referenceColumn :: Maybe Text
$sel:referenceColumn:ForeignKeyConstraint :: Constraint -> Maybe Text
referenceColumn, Maybe OnDelete
onDelete :: Maybe OnDelete
$sel:onDelete:ForeignKeyConstraint :: Constraint -> Maybe OnDelete
onDelete } = Text
"FOREIGN KEY (" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
columnName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
") REFERENCES " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
referenceTable Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (if Maybe Text -> Bool
forall a. Maybe a -> Bool
isJust Maybe Text
referenceColumn then Text
" (" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Maybe Text -> Text
forall a. HasCallStack => Maybe a -> a
fromJust Maybe Text
referenceColumn Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")" else Text
"") Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Maybe OnDelete -> Text
compileOnDelete Maybe OnDelete
onDelete
compileConstraint UniqueConstraint { [Text]
$sel:columnNames:ForeignKeyConstraint :: Constraint -> [Text]
columnNames :: [Text]
columnNames } = Text
"UNIQUE(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
intercalate Text
", " [Text]
columnNames Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")"
compileConstraint CheckConstraint { Expression
checkExpression :: Expression
$sel:checkExpression:ForeignKeyConstraint :: Constraint -> Expression
checkExpression } = Text
"CHECK (" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpression Expression
checkExpression Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")"
compileConstraint ExcludeConstraint { [ExcludeConstraintElement]
excludeElements :: [ExcludeConstraintElement]
$sel:excludeElements:ForeignKeyConstraint :: Constraint -> [ExcludeConstraintElement]
excludeElements, Maybe Expression
predicate :: Maybe Expression
$sel:predicate:ForeignKeyConstraint :: Constraint -> Maybe Expression
predicate, Maybe IndexType
indexType :: Maybe IndexType
$sel:indexType:ForeignKeyConstraint :: Constraint -> Maybe IndexType
indexType } = Text
"EXCLUDE" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
compiledIndexType Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" (" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
compiledExcludeElements Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> case Maybe Expression
predicate of
    Just Expression
expression -> Text
" WHERE (" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpression Expression
expression Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")"
    Maybe Expression
Nothing -> Text
""
    where
        compiledExcludeElements :: Text
compiledExcludeElements = Text -> [Text] -> Text
intercalate Text
", " ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ (ExcludeConstraintElement -> Text)
-> [ExcludeConstraintElement] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map ExcludeConstraintElement -> Text
compileExcludeElement [ExcludeConstraintElement]
excludeElements

        compileExcludeElement :: ExcludeConstraintElement -> Text
compileExcludeElement ExcludeConstraintElement { Text
element :: Text
$sel:element:ExcludeConstraintElement :: ExcludeConstraintElement -> Text
element, Text
operator :: Text
$sel:operator:ExcludeConstraintElement :: ExcludeConstraintElement -> Text
operator } = Text
element Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" WITH " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
operator

        compiledIndexType :: Text
compiledIndexType = case Maybe IndexType
indexType of
            Maybe IndexType
Nothing -> Text
""
            Just IndexType
indexType -> Text
" USING " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> IndexType -> Text
compileIndexType IndexType
indexType

compileDeferrable :: Maybe Bool -> Maybe DeferrableType -> Text
compileDeferrable :: Maybe Bool -> Maybe DeferrableType -> Text
compileDeferrable Maybe Bool
deferrable Maybe DeferrableType
deferrableType = [Text] -> Text
Text.concat ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ (Text -> Text) -> [Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
(<>) Text
" ") ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ [Maybe Text] -> [Text]
forall a. [Maybe a] -> [a]
catMaybes [Bool -> Text
forall {a}. IsString a => Bool -> a
compileIsDeferrable (Bool -> Text) -> Maybe Bool -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Bool
deferrable, DeferrableType -> Text
forall {a}. IsString a => DeferrableType -> a
compileDeferrableType (DeferrableType -> Text) -> Maybe DeferrableType -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe DeferrableType
deferrableType]
    where
        compileIsDeferrable :: Bool -> a
compileIsDeferrable Bool
True = a
"DEFERRABLE"
        compileIsDeferrable Bool
False = a
"NOT DEFERRABLE"
        compileDeferrableType :: DeferrableType -> a
compileDeferrableType DeferrableType
InitiallyImmediate = a
"INITIALLY IMMEDIATE"
        compileDeferrableType DeferrableType
InitiallyDeferred = a
"INITIALLY DEFERRED"

compileOnDelete :: Maybe OnDelete -> Text
compileOnDelete :: Maybe OnDelete -> Text
compileOnDelete Maybe OnDelete
Nothing = Text
""
compileOnDelete (Just OnDelete
NoAction) = Text
"ON DELETE NO ACTION"
compileOnDelete (Just OnDelete
Restrict) = Text
"ON DELETE RESTRICT"
compileOnDelete (Just OnDelete
SetNull) = Text
"ON DELETE SET NULL"
compileOnDelete (Just OnDelete
SetDefault) = Text
"ON DELETE SET DEFAULT"
compileOnDelete (Just OnDelete
Cascade) = Text
"ON DELETE CASCADE"

compileColumn :: PrimaryKeyConstraint -> Column -> Text
compileColumn :: PrimaryKeyConstraint -> Column -> Text
compileColumn PrimaryKeyConstraint
primaryKeyConstraint Column { Text
name :: Text
$sel:name:Column :: Column -> Text
name, PostgresType
columnType :: PostgresType
$sel:columnType:Column :: Column -> PostgresType
columnType, Maybe Expression
defaultValue :: Maybe Expression
$sel:defaultValue:Column :: Column -> Maybe Expression
defaultValue, Bool
notNull :: Bool
$sel:notNull:Column :: Column -> Bool
notNull, Bool
isUnique :: Bool
$sel:isUnique:Column :: Column -> Bool
isUnique, Maybe ColumnGenerator
generator :: Maybe ColumnGenerator
$sel:generator:Column :: Column -> Maybe ColumnGenerator
generator } =
    [Text] -> Text
unwords ([Maybe Text] -> [Text]
forall a. [Maybe a] -> [a]
catMaybes
        [ Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Text
compileIdentifier Text
name)
        , Text -> Maybe Text
forall a. a -> Maybe a
Just (PostgresType -> Text
compilePostgresType PostgresType
columnType)
        , (Expression -> Text) -> Maybe Expression -> Maybe Text
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Expression -> Text
compileDefaultValue Maybe Expression
defaultValue
        , (ColumnGenerator -> Text) -> Maybe ColumnGenerator -> Maybe Text
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ColumnGenerator -> Text
compileGenerator Maybe ColumnGenerator
generator
        , Maybe Text
primaryKeyColumnConstraint
        , if Bool
notNull then Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"NOT NULL" else Maybe Text
forall a. Maybe a
Nothing
        , if Bool
isUnique then Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"UNIQUE" else Maybe Text
forall a. Maybe a
Nothing
        ])
    where
        -- Emit a PRIMARY KEY column constraint if this is the only primary key column
        primaryKeyColumnConstraint :: Maybe Text
primaryKeyColumnConstraint = case PrimaryKeyConstraint
primaryKeyConstraint of
            PrimaryKeyConstraint [Text
primaryKeyColumn]
                | Text
name Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
primaryKeyColumn -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"PRIMARY KEY"
                | Bool
otherwise -> Maybe Text
forall a. Maybe a
Nothing
            PrimaryKeyConstraint [Text]
_ -> Maybe Text
forall a. Maybe a
Nothing

compileDefaultValue :: Expression -> Text
compileDefaultValue :: Expression -> Text
compileDefaultValue Expression
value = Text
"DEFAULT " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpression Expression
value

compileExpression :: Expression -> Text
compileExpression :: Expression -> Text
compileExpression (TextExpression Text
value) = Text
"'" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
value Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"'"
compileExpression (VarExpression Text
name) =
        if Bool
nameContainsSpaces
            then Text -> Text
compileIdentifier Text
name
            else Text
name
    where
        nameContainsSpaces :: Bool
nameContainsSpaces = (Char -> Bool) -> Text -> Bool
Text.any (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
' ') Text
name
compileExpression (CallExpression Text
func [Expression]
args) = Text
func Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
intercalate Text
", " ((Expression -> Text) -> [Expression] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Expression -> Text
compileExpressionWithOptionalParenthese [Expression]
args) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")"
compileExpression (NotEqExpression Expression
a Expression
b) = Expression -> Text
compileExpression Expression
a Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" <> " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpression Expression
b
compileExpression (EqExpression Expression
a Expression
b) = Expression -> Text
compileExpressionWithOptionalParenthese Expression
a Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" = " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpressionWithOptionalParenthese Expression
b
compileExpression (IsExpression Expression
a (NotExpression Expression
b)) = Expression -> Text
compileExpressionWithOptionalParenthese Expression
a Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" IS NOT " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpressionWithOptionalParenthese Expression
b -- 'IS (NOT NULL)' => 'IS NOT NULL'
compileExpression (IsExpression Expression
a Expression
b) = Expression -> Text
compileExpressionWithOptionalParenthese Expression
a Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" IS " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpressionWithOptionalParenthese Expression
b
compileExpression (InExpression Expression
a Expression
b) = Expression -> Text
compileExpressionWithOptionalParenthese Expression
a Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" IN " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpressionWithOptionalParenthese Expression
b
compileExpression (NotExpression Expression
a) = Text
"NOT " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpressionWithOptionalParenthese Expression
a
compileExpression (AndExpression Expression
a Expression
b) = Expression -> Text
compileExpressionWithOptionalParenthese Expression
a Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" AND " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpressionWithOptionalParenthese Expression
b
compileExpression (OrExpression Expression
a Expression
b) = Expression -> Text
compileExpressionWithOptionalParenthese Expression
a Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" OR " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpressionWithOptionalParenthese Expression
b
compileExpression (LessThanExpression Expression
a Expression
b) = Expression -> Text
compileExpressionWithOptionalParenthese Expression
a Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" < " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpressionWithOptionalParenthese Expression
b
compileExpression (LessThanOrEqualToExpression Expression
a Expression
b) = Expression -> Text
compileExpressionWithOptionalParenthese Expression
a Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" <= " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpressionWithOptionalParenthese Expression
b
compileExpression (GreaterThanExpression Expression
a Expression
b) = Expression -> Text
compileExpressionWithOptionalParenthese Expression
a Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" > " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpressionWithOptionalParenthese Expression
b
compileExpression (GreaterThanOrEqualToExpression Expression
a Expression
b) = Expression -> Text
compileExpressionWithOptionalParenthese Expression
a Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" >= " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpressionWithOptionalParenthese Expression
b
compileExpression (DoubleExpression Double
double) = Double -> Text
forall a. Show a => a -> Text
tshow Double
double
compileExpression (IntExpression Int
integer) = Int -> Text
forall a. Show a => a -> Text
tshow Int
integer
compileExpression (TypeCastExpression Expression
value PostgresType
type_) = Expression -> Text
compileExpression Expression
value Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"::" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> PostgresType -> Text
compilePostgresType PostgresType
type_
compileExpression (SelectExpression Select { [Expression]
columns :: [Expression]
$sel:columns:Select :: Select -> [Expression]
columns, Expression
from :: Expression
$sel:from:Select :: Select -> Expression
from, Expression
whereClause :: Expression
$sel:whereClause:Select :: Select -> Expression
whereClause }) = Text
"SELECT " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
intercalate Text
", " ((Expression -> Text) -> [Expression] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Expression -> Text
compileExpression [Expression]
columns) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" FROM " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpression Expression
from Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" WHERE " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpression Expression
whereClause
compileExpression (ExistsExpression Expression
a) = Text
"EXISTS " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpressionWithOptionalParenthese Expression
a
compileExpression (DotExpression Expression
a Text
b) = Expression -> Text
compileExpressionWithOptionalParenthese Expression
a Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"." Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
compileIdentifier Text
b
compileExpression (ConcatenationExpression Expression
a Expression
b) = Expression -> Text
compileExpressionWithOptionalParenthese Expression
a Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" || " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpressionWithOptionalParenthese Expression
b

compileExpressionWithOptionalParenthese :: Expression -> Text
compileExpressionWithOptionalParenthese :: Expression -> Text
compileExpressionWithOptionalParenthese expr :: Expression
expr@(VarExpression {}) = Expression -> Text
compileExpression Expression
expr
compileExpressionWithOptionalParenthese expr :: Expression
expr@(IsExpression Expression
a (NotExpression Expression
b)) = Expression -> Text
compileExpression Expression
a Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" IS " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpression (Expression -> Expression
NotExpression Expression
b) -- 'IS (NOT NULL)' => 'IS NOT NULL'
compileExpressionWithOptionalParenthese expr :: Expression
expr@(IsExpression {}) = Expression -> Text
compileExpression Expression
expr
compileExpressionWithOptionalParenthese expr :: Expression
expr@(EqExpression {}) = Expression -> Text
compileExpression Expression
expr
compileExpressionWithOptionalParenthese expr :: Expression
expr@(AndExpression a :: Expression
a@(AndExpression {}) Expression
b ) = Text
"(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpression Expression
a Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" AND " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpressionWithOptionalParenthese Expression
b Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")" -- '(a AND b) AND c' => 'a AND b AND C'
compileExpressionWithOptionalParenthese expr :: Expression
expr@(AndExpression Expression
a b :: Expression
b@(AndExpression {}) ) = Text
"(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpressionWithOptionalParenthese Expression
a Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" AND " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpression Expression
b Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")" -- 'a AND (b AND c)' => 'a AND b AND C'
--compileExpressionWithOptionalParenthese expr@(OrExpression a@(IsExpression {}) b ) = compileExpressionWithOptionalParenthese a <> " OR " <> compileExpressionWithOptionalParenthese b -- '(a IS NULL) OR b' => 'A IS NULL OR b'
compileExpressionWithOptionalParenthese expr :: Expression
expr@(CallExpression {}) = Expression -> Text
compileExpression Expression
expr
compileExpressionWithOptionalParenthese expr :: Expression
expr@(TextExpression {}) = Expression -> Text
compileExpression Expression
expr
compileExpressionWithOptionalParenthese expr :: Expression
expr@(IntExpression {}) = Expression -> Text
compileExpression Expression
expr
compileExpressionWithOptionalParenthese expr :: Expression
expr@(DoubleExpression {}) = Expression -> Text
compileExpression Expression
expr
compileExpressionWithOptionalParenthese expr :: Expression
expr@(DotExpression (VarExpression {}) Text
b) = Expression -> Text
compileExpression Expression
expr
compileExpressionWithOptionalParenthese expr :: Expression
expr@(ConcatenationExpression Expression
a Expression
b ) = Expression -> Text
compileExpression Expression
expr
compileExpressionWithOptionalParenthese Expression
expression = Text
"(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpression Expression
expression Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")"

compareStatement :: Statement -> Statement -> Ordering
compareStatement (CreateEnumType {}) Statement
_ = Ordering
LT
compareStatement (StatementCreateTable CreateTable {}) (AddConstraint {}) = Ordering
LT
compareStatement (AddConstraint { $sel:constraint:StatementCreateTable :: Statement -> Constraint
constraint = Constraint
a }) (AddConstraint { $sel:constraint:StatementCreateTable :: Statement -> Constraint
constraint = Constraint
b }) = Maybe Text -> Maybe Text -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Constraint
a.name) (Constraint
b.name)
compareStatement (AddConstraint {}) Statement
_ = Ordering
GT
compareStatement Statement
_ Statement
_ = Ordering
EQ

compilePostgresType :: PostgresType -> Text
compilePostgresType :: PostgresType -> Text
compilePostgresType PostgresType
PUUID = Text
"UUID"
compilePostgresType PostgresType
PText = Text
"TEXT"
compilePostgresType PostgresType
PInt = Text
"INT"
compilePostgresType PostgresType
PSmallInt = Text
"SMALLINT"
compilePostgresType PostgresType
PBigInt = Text
"BIGINT"
compilePostgresType PostgresType
PBoolean = Text
"BOOLEAN"
compilePostgresType PostgresType
PTimestamp = Text
"TIMESTAMP WITHOUT TIME ZONE"
compilePostgresType PostgresType
PTimestampWithTimezone = Text
"TIMESTAMP WITH TIME ZONE"
compilePostgresType PostgresType
PReal = Text
"REAL"
compilePostgresType PostgresType
PDouble = Text
"DOUBLE PRECISION"
compilePostgresType PostgresType
PPoint = Text
"POINT"
compilePostgresType PostgresType
PPolygon = Text
"POLYGON"
compilePostgresType PostgresType
PDate = Text
"DATE"
compilePostgresType PostgresType
PBinary = Text
"BYTEA"
compilePostgresType PostgresType
PTime = Text
"TIME"
compilePostgresType (PInterval Maybe Text
Nothing) = Text
"INTERVAL"
compilePostgresType (PInterval (Just Text
fields)) = Text
"INTERVAL" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
fields
compilePostgresType (PNumeric (Just Int
precision) (Just Int
scale)) = Text
"NUMERIC(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
show Int
precision Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"," Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
show Int
scale Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")"
compilePostgresType (PNumeric (Just Int
precision) Maybe Int
Nothing) = Text
"NUMERIC(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
show Int
precision Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")"
compilePostgresType (PNumeric Maybe Int
Nothing Maybe Int
_) = Text
"NUMERIC"
compilePostgresType (PVaryingN (Just Int
limit)) = Text
"CHARACTER VARYING(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
show Int
limit Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")"
compilePostgresType (PVaryingN Maybe Int
Nothing) = Text
"CHARACTER VARYING"
compilePostgresType (PCharacterN Int
length) = Text
"CHARACTER(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
show Int
length Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")"
compilePostgresType PostgresType
PSingleChar = Text
"\"char\""
compilePostgresType PostgresType
PSerial = Text
"SERIAL"
compilePostgresType PostgresType
PBigserial = Text
"BIGSERIAL"
compilePostgresType PostgresType
PJSONB = Text
"JSONB"
compilePostgresType PostgresType
PInet = Text
"INET"
compilePostgresType PostgresType
PTSVector = Text
"TSVECTOR"
compilePostgresType (PArray PostgresType
type_) = PostgresType -> Text
compilePostgresType PostgresType
type_ Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"[]"
compilePostgresType PostgresType
PTrigger = Text
"TRIGGER"
compilePostgresType (PCustomType Text
theType) = Text
theType

compileIdentifier :: Text -> Text
compileIdentifier :: Text -> Text
compileIdentifier Text
identifier = if Bool
identifierNeedsQuoting then Text -> Text
forall a. Show a => a -> Text
tshow Text
identifier else Text
identifier
    where
        identifierNeedsQuoting :: Bool
identifierNeedsQuoting = Bool
isKeyword Bool -> Bool -> Bool
|| Char -> Bool
containsChar Char
' ' Bool -> Bool -> Bool
|| Char -> Bool
containsChar Char
'-' Bool -> Bool -> Bool
|| Bool
isUsingUppercase
        isKeyword :: Bool
isKeyword = Text -> Text
IHP.Prelude.toUpper Text
identifier Text -> [Text] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Text]
keywords
        containsChar :: Char -> Bool
containsChar Char
char = (Char -> Bool) -> Text -> Bool
Text.any (Char
char ==) Text
identifier
        isUsingUppercase :: Bool
isUsingUppercase = Text -> Text
Text.toLower Text
identifier Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
/= Text
identifier

        keywords :: [Text]
keywords = [ Text
"ABORT"
            , Text
"ABSOLUTE"
            , Text
"ACCESS"
            , Text
"ACTION"
            , Text
"ADD"
            , Text
"ADMIN"
            , Text
"AFTER"
            , Text
"AGGREGATE"
            , Text
"ALSO"
            , Text
"ALTER"
            , Text
"ASSERTION"
            , Text
"ASSIGNMENT"
            , Text
"AT"
            , Text
"ALL"
            , Text
"BACKWARD"
            , Text
"BEFORE"
            , Text
"BEGIN"
            , Text
"BY"
            , Text
"CACHE"
            , Text
"CALLED"
            , Text
"CASCADE"
            , Text
"CHAIN"
            , Text
"CHARACTERISTICS"
            , Text
"CHECKPOINT"
            , Text
"CLASS"
            , Text
"CLOSE"
            , Text
"CLUSTER"
            , Text
"COMMENT"
            , Text
"COMMIT"
            , Text
"COMMITTED"
            , Text
"CONNECTION"
            , Text
"CONSTRAINTS"
            , Text
"CONVERSION"
            , Text
"COPY"
            , Text
"CREATEDB"
            , Text
"CREATEROLE"
            , Text
"CREATEUSER"
            , Text
"CSV"
            , Text
"CURSOR"
            , Text
"CYCLE"
            , Text
"DATABASE"
            , Text
"DAY"
            , Text
"DEALLOCATE"
            , Text
"DECLARE"
            , Text
"DEFAULTS"
            , Text
"DEFERRED"
            , Text
"DEFINER"
            , Text
"DELETE"
            , Text
"DELIMITER"
            , Text
"DELIMITERS"
            , Text
"DISABLE"
            , Text
"DOMAIN"
            , Text
"DOUBLE"
            , Text
"DROP"
            , Text
"EACH"
            , Text
"ENABLE"
            , Text
"ENCODING"
            , Text
"ENCRYPTED"
            , Text
"ESCAPE"
            , Text
"EXCLUDING"
            , Text
"EXCLUSIVE"
            , Text
"EXECUTE"
            , Text
"EXPLAIN"
            , Text
"EXTERNAL"
            , Text
"FETCH"
            , Text
"FIRST"
            , Text
"FORCE"
            , Text
"FORWARD"
            , Text
"FUNCTION"
            , Text
"GLOBAL"
            , Text
"GRANTED"
            , Text
"HANDLER"
            , Text
"HEADER"
            , Text
"HOLD"
            , Text
"HOUR"
            , Text
"IMMEDIATE"
            , Text
"IMMUTABLE"
            , Text
"IMPLICIT"
            , Text
"INCLUDING"
            , Text
"INCREMENT"
            , Text
"INDEX"
            , Text
"INHERIT"
            , Text
"INHERITS"
            , Text
"INPUT"
            , Text
"INSENSITIVE"
            , Text
"INSERT"
            , Text
"INSTEAD"
            , Text
"INVOKER"
            , Text
"ISOLATION"
            , Text
"KEY"
            , Text
"LANCOMPILER"
            , Text
"LANGUAGE"
            , Text
"LARGE"
            , Text
"LAST"
            , Text
"LEVEL"
            , Text
"LISTEN"
            , Text
"LOAD"
            , Text
"LOCAL"
            , Text
"LOCATION"
            , Text
"LOCK"
            , Text
"LOGIN"
            , Text
"MATCH"
            , Text
"MAXVALUE"
            , Text
"MINUTE"
            , Text
"MINVALUE"
            , Text
"MODE"
            , Text
"MONTH"
            , Text
"MOVE"
            , Text
"NAMES"
            , Text
"NEXT"
            , Text
"NO"
            , Text
"NOCREATEDB"
            , Text
"NOCREATEROLE"
            , Text
"NOCREATEUSER"
            , Text
"NOINHERIT"
            , Text
"NOLOGIN"
            , Text
"NOSUPERUSER"
            , Text
"NOTHING"
            , Text
"NOTIFY"
            , Text
"NOWAIT"
            , Text
"OBJECT"
            , Text
"OF"
            , Text
"OIDS"
            , Text
"OPERATOR"
            , Text
"OPTION"
            , Text
"OWNER"
            , Text
"PARTIAL"
            , Text
"PASSWORD"
            , Text
"PREPARE"
            , Text
"PREPARED"
            , Text
"PRESERVE"
            , Text
"PRIOR"
            , Text
"PRIVILEGES"
            , Text
"PROCEDURAL"
            , Text
"PROCEDURE"
            , Text
"QUOTE"
            , Text
"READ"
            , Text
"RECHECK"
            , Text
"REINDEX"
            , Text
"RELATIVE"
            , Text
"RELEASE"
            , Text
"RENAME"
            , Text
"REPEATABLE"
            , Text
"REPLACE"
            , Text
"RESET"
            , Text
"RESTART"
            , Text
"RESTRICT"
            , Text
"RETURNS"
            , Text
"REVOKE"
            , Text
"ROLE"
            , Text
"ROLLBACK"
            , Text
"ROWS"
            , Text
"RULE"
            , Text
"SAVEPOINT"
            , Text
"SCHEMA"
            , Text
"SCROLL"
            , Text
"SECOND"
            , Text
"SECURITY"
            , Text
"SEQUENCE"
            , Text
"SERIALIZABLE"
            , Text
"SESSION"
            , Text
"SET"
            , Text
"SHARE"
            , Text
"tshow"
            , Text
"SIMPLE"
            , Text
"STABLE"
            , Text
"START"
            , Text
"STATEMENT"
            , Text
"STATISTICS"
            , Text
"STDIN"
            , Text
"STDOUT"
            , Text
"STORAGE"
            , Text
"STRICT"
            , Text
"SUPERUSER"
            , Text
"SYSID"
            , Text
"SYSTEM"
            , Text
"TABLESPACE"
            , Text
"TEMP"
            , Text
"TEMPLATE"
            , Text
"TEMPORARY"
            , Text
"TOAST"
            , Text
"TRANSACTION"
            , Text
"TRIGGER"
            , Text
"TRUNCATE"
            , Text
"TRUSTED"
            , Text
"TYPE"
            , Text
"UNCOMMITTED"
            , Text
"UNENCRYPTED"
            , Text
"UNKNOWN"
            , Text
"UNLISTEN"
            , Text
"UNTIL"
            , Text
"UPDATE"
            , Text
"VACUUM"
            , Text
"VALID"
            , Text
"VALIDATOR"
            , Text
"VALUES"
            , Text
"VARYING"
            , Text
"VIEW"
            , Text
"VOLATILE"
            , Text
"WITH"
            , Text
"WITHOUT"
            , Text
"WORK"
            , Text
"WRITE"
            , Text
"YEAR"
            , Text
"ZONE"
            , Text
"BIGINT"
            , Text
"BIT"
            , Text
"BOOLEAN"
            , Text
"CHAR"
            , Text
"CHARACTER"
            , Text
"COALESCE"
            , Text
"CONVERT"
            , Text
"DEC"
            , Text
"DECIMAL"
            , Text
"EXISTS"
            , Text
"EXTRACT"
            , Text
"FLOAT"
            , Text
"GREATEST"
            , Text
"INOUT"
            , Text
"INT"
            , Text
"INTEGER"
            , Text
"INTERVAL"
            , Text
"LEAST"
            , Text
"NATIONAL"
            , Text
"NCHAR"
            , Text
"NONE"
            , Text
"NULLIF"
            , Text
"NUMERIC"
            , Text
"OUT"
            , Text
"OVERLAY"
            , Text
"POSITION"
            , Text
"PRECISION"
            , Text
"REAL"
            , Text
"ROW"
            , Text
"SETOF"
            , Text
"SMALLINT"
            , Text
"SUBSTRING"
            , Text
"TIME"
            , Text
"TIMESTAMP"
            , Text
"TREAT"
            , Text
"TRIM"
            , Text
"VARCHAR"
            ]

indent :: a -> a
indent a
text = a
"    " a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
text

compileTriggerEventWhen :: TriggerEventWhen -> Text
compileTriggerEventWhen :: TriggerEventWhen -> Text
compileTriggerEventWhen TriggerEventWhen
Before = Text
"BEFORE"
compileTriggerEventWhen TriggerEventWhen
After = Text
"AFTER"
compileTriggerEventWhen TriggerEventWhen
InsteadOf = Text
"INSTEAD OF"

compileTriggerEvent :: TriggerEvent -> Text
compileTriggerEvent :: TriggerEvent -> Text
compileTriggerEvent TriggerEvent
TriggerOnInsert = Text
"INSERT"
compileTriggerEvent TriggerEvent
TriggerOnUpdate = Text
"UPDATE"
compileTriggerEvent TriggerEvent
TriggerOnDelete = Text
"DELETE"
compileTriggerEvent TriggerEvent
TriggerOnTruncate = Text
"TRUNCATE"

compileTriggerFor :: TriggerFor -> Text
compileTriggerFor :: TriggerFor -> Text
compileTriggerFor TriggerFor
ForEachRow = Text
"FOR EACH ROW"
compileTriggerFor TriggerFor
ForEachStatement = Text
"FOR EACH STATEMENT"

compilePolicyAction :: PolicyAction -> Text
compilePolicyAction :: PolicyAction -> Text
compilePolicyAction PolicyAction
PolicyForAll = Text
"ALL"
compilePolicyAction PolicyAction
PolicyForSelect = Text
"SELECT"
compilePolicyAction PolicyAction
PolicyForInsert = Text
"INSERT"
compilePolicyAction PolicyAction
PolicyForUpdate = Text
"UPDATE"
compilePolicyAction PolicyAction
PolicyForDelete = Text
"DELETE"

compileGenerator :: ColumnGenerator -> Text
compileGenerator :: ColumnGenerator -> Text
compileGenerator ColumnGenerator { Expression
generate :: Expression
$sel:generate:ColumnGenerator :: ColumnGenerator -> Expression
generate, Bool
stored :: Bool
$sel:stored:ColumnGenerator :: ColumnGenerator -> Bool
stored } =
    Text
"GENERATED ALWAYS AS ("
    Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expression -> Text
compileExpressionWithOptionalParenthese Expression
generate
    Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")"
    Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (if Bool
stored then Text
" STORED" else Text
"")

compileIndexType :: IndexType -> Text
compileIndexType :: IndexType -> Text
compileIndexType IndexType
Gin = Text
"GIN"
compileIndexType IndexType
Btree = Text
"BTREE"
compileIndexType IndexType
Gist = Text
"GIST"

compileIndexColumn :: IndexColumn -> Text
compileIndexColumn :: IndexColumn -> Text
compileIndexColumn IndexColumn { Expression
column :: Expression
$sel:column:IndexColumn :: IndexColumn -> Expression
column, $sel:columnOrder:IndexColumn :: IndexColumn -> [IndexColumnOrder]
columnOrder = [] } = Expression -> Text
compileExpression Expression
column
compileIndexColumn IndexColumn { Expression
$sel:column:IndexColumn :: IndexColumn -> Expression
column :: Expression
column, [IndexColumnOrder]
$sel:columnOrder:IndexColumn :: IndexColumn -> [IndexColumnOrder]
columnOrder :: [IndexColumnOrder]
columnOrder } = Expression -> Text
compileExpression Expression
column Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> [Text] -> Text
unwords ([IndexColumnOrder]
columnOrder [IndexColumnOrder] -> ([IndexColumnOrder] -> [Text]) -> [Text]
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> (IndexColumnOrder -> Text) -> [IndexColumnOrder] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map IndexColumnOrder -> Text
compileIndexColumnOrder)

compileIndexColumnOrder :: IndexColumnOrder -> Text
compileIndexColumnOrder :: IndexColumnOrder -> Text
compileIndexColumnOrder IndexColumnOrder
Asc = Text
"ASC"
compileIndexColumnOrder IndexColumnOrder
Desc = Text
"DESC"
compileIndexColumnOrder IndexColumnOrder
NullsFirst = Text
"NULLS FIRST"
compileIndexColumnOrder IndexColumnOrder
NullsLast = Text
"NULLS LAST"