{-|
Module: Squeal.PostgreSQL.Definition.Table
Description: create, drop and alter tables
Copyright: (c) Eitan Chatav, 2019
Maintainer: eitan@morphism.tech
Stability: experimental

create, drop and alter tables
-}

{-# LANGUAGE
    AllowAmbiguousTypes
  , ConstraintKinds
  , DeriveAnyClass
  , DeriveGeneric
  , DerivingStrategies
  , FlexibleContexts
  , FlexibleInstances
  , GADTs
  , LambdaCase
  , MultiParamTypeClasses
  , OverloadedLabels
  , OverloadedStrings
  , RankNTypes
  , ScopedTypeVariables
  , TypeApplications
  , TypeInType
  , TypeOperators
  , UndecidableSuperClasses
#-}

module Squeal.PostgreSQL.Definition.Table
  ( -- * Create
    createTable
  , createTableIfNotExists
    -- * Drop
  , dropTable
  , dropTableIfExists
    -- * Alter
  , alterTable
  , alterTableIfExists
  , alterTableRename
  , alterTableIfExistsRename
  , alterTableSetSchema
  , AlterTable (..)
    -- ** Constraints
  , addConstraint
  , dropConstraint
    -- ** Columns
  , AddColumn (..)
  , dropColumn
  , renameColumn
  , alterColumn
  , AlterColumn (..)
  , setDefault
  , dropDefault
  , setNotNull
  , dropNotNull
  , alterType
  ) where

import Control.DeepSeq
import Data.ByteString
import GHC.TypeLits

import qualified Generics.SOP as SOP
import qualified GHC.Generics as GHC

import Squeal.PostgreSQL.Type.Alias
import Squeal.PostgreSQL.Definition
import Squeal.PostgreSQL.Definition.Constraint
import Squeal.PostgreSQL.Expression
import Squeal.PostgreSQL.Expression.Type
import Squeal.PostgreSQL.Type.List
import Squeal.PostgreSQL.Render
import Squeal.PostgreSQL.Type.Schema

-- $setup
-- >>> import Squeal.PostgreSQL

{- | `createTable` adds a table to the schema.

>>> :set -XOverloadedLabels
>>> :{
type Table = '[] :=>
  '[ "a" ::: 'NoDef :=> 'Null 'PGint4
   , "b" ::: 'NoDef :=> 'Null 'PGfloat4 ]
:}

>>> :{
let
  setup :: Definition (Public '[]) (Public '["tab" ::: 'Table Table])
  setup = createTable #tab
    (nullable int `as` #a :* nullable real `as` #b) Nil
in printSQL setup
:}
CREATE TABLE "tab" ("a" int NULL, "b" real NULL);
-}
createTable
  :: ( KnownSymbol sch
     , KnownSymbol tab
     , columns ~ (col ': cols)
     , SOP.SListI columns
     , SOP.SListI constraints
     , Has sch db0 schema0
     , db1 ~ Alter sch (Create tab ('Table (constraints :=> columns)) schema0) db0 )
  => QualifiedAlias sch tab -- ^ the name of the table to add
  -> NP (Aliased (ColumnTypeExpression db0)) columns
    -- ^ the names and datatype of each column
  -> NP (Aliased (TableConstraintExpression sch tab db1)) constraints
    -- ^ constraints that must hold for the table
  -> Definition db0 db1
createTable :: QualifiedAlias sch tab
-> NP (Aliased (ColumnTypeExpression db0)) columns
-> NP (Aliased (TableConstraintExpression sch tab db1)) constraints
-> Definition db0 db1
createTable QualifiedAlias sch tab
tab NP (Aliased (ColumnTypeExpression db0)) columns
columns NP (Aliased (TableConstraintExpression sch tab db1)) constraints
constraints = ByteString -> Definition db0 db1
forall (db0 :: SchemasType) (db1 :: SchemasType).
ByteString -> Definition db0 db1
UnsafeDefinition (ByteString -> Definition db0 db1)
-> ByteString -> Definition db0 db1
forall a b. (a -> b) -> a -> b
$
  ByteString
"CREATE TABLE" ByteString -> ByteString -> ByteString
<+> QualifiedAlias sch tab
-> NP (Aliased (ColumnTypeExpression db0)) columns
-> NP (Aliased (TableConstraintExpression sch tab db1)) constraints
-> ByteString
forall (sch :: Symbol) (tab :: Symbol)
       (columns :: [(Symbol, ColumnType)])
       (constraints :: [(Symbol, TableConstraint)]) (db0 :: SchemasType)
       (db1 :: SchemasType).
(KnownSymbol sch, KnownSymbol tab, SListI columns,
 SListI constraints) =>
QualifiedAlias sch tab
-> NP (Aliased (ColumnTypeExpression db0)) columns
-> NP (Aliased (TableConstraintExpression sch tab db1)) constraints
-> ByteString
renderCreation QualifiedAlias sch tab
tab NP (Aliased (ColumnTypeExpression db0)) columns
columns NP (Aliased (TableConstraintExpression sch tab db1)) constraints
constraints

{-| `createTableIfNotExists` creates a table if it doesn't exist, but does not add it to the schema.
Instead, the schema already has the table so if the table did not yet exist, the schema was wrong.
`createTableIfNotExists` fixes this. Interestingly, this property makes it an idempotent in
the `Control.Category.Category` of `Definition`s.

>>> :set -XOverloadedLabels -XTypeApplications
>>> :{
type Table = '[] :=>
  '[ "a" ::: 'NoDef :=> 'Null 'PGint4
   , "b" ::: 'NoDef :=> 'Null 'PGfloat4 ]
:}

>>> type Schemas = Public '["tab" ::: 'Table Table]

>>> :{
let
  setup :: Definition Schemas Schemas
  setup = createTableIfNotExists #tab
    (nullable int `as` #a :* nullable real `as` #b) Nil
in printSQL setup
:}
CREATE TABLE IF NOT EXISTS "tab" ("a" int NULL, "b" real NULL);
-}
createTableIfNotExists
  :: ( KnownSymbol sch
     , KnownSymbol tab
     , columns ~ (col ': cols)
     , SOP.SListI columns
     , SOP.SListI constraints
     , Has sch db0 schema0
     , db1 ~ Alter sch (CreateIfNotExists tab ('Table (constraints :=> columns)) schema0) db0 )
  => QualifiedAlias sch tab -- ^ the name of the table to add
  -> NP (Aliased (ColumnTypeExpression db0)) columns
    -- ^ the names and datatype of each column
  -> NP (Aliased (TableConstraintExpression sch tab db1)) constraints
    -- ^ constraints that must hold for the table
  -> Definition db0 db1
createTableIfNotExists :: QualifiedAlias sch tab
-> NP (Aliased (ColumnTypeExpression db0)) columns
-> NP (Aliased (TableConstraintExpression sch tab db1)) constraints
-> Definition db0 db1
createTableIfNotExists QualifiedAlias sch tab
tab NP (Aliased (ColumnTypeExpression db0)) columns
columns NP (Aliased (TableConstraintExpression sch tab db1)) constraints
constraints = ByteString -> Definition db0 db1
forall (db0 :: SchemasType) (db1 :: SchemasType).
ByteString -> Definition db0 db1
UnsafeDefinition (ByteString -> Definition db0 db1)
-> ByteString -> Definition db0 db1
forall a b. (a -> b) -> a -> b
$
  ByteString
"CREATE TABLE IF NOT EXISTS"
  ByteString -> ByteString -> ByteString
<+> QualifiedAlias sch tab
-> NP (Aliased (ColumnTypeExpression db0)) columns
-> NP (Aliased (TableConstraintExpression sch tab db1)) constraints
-> ByteString
forall (sch :: Symbol) (tab :: Symbol)
       (columns :: [(Symbol, ColumnType)])
       (constraints :: [(Symbol, TableConstraint)]) (db0 :: SchemasType)
       (db1 :: SchemasType).
(KnownSymbol sch, KnownSymbol tab, SListI columns,
 SListI constraints) =>
QualifiedAlias sch tab
-> NP (Aliased (ColumnTypeExpression db0)) columns
-> NP (Aliased (TableConstraintExpression sch tab db1)) constraints
-> ByteString
renderCreation QualifiedAlias sch tab
tab NP (Aliased (ColumnTypeExpression db0)) columns
columns NP (Aliased (TableConstraintExpression sch tab db1)) constraints
constraints

-- helper function for `createTable` and `createTableIfNotExists`
renderCreation
  :: ( KnownSymbol sch
     , KnownSymbol tab
     , SOP.SListI columns
     , SOP.SListI constraints )
  => QualifiedAlias sch tab -- ^ the name of the table to add
  -> NP (Aliased (ColumnTypeExpression db0)) columns
    -- ^ the names and datatype of each column
  -> NP (Aliased (TableConstraintExpression sch tab db1)) constraints
    -- ^ constraints that must hold for the table
  -> ByteString
renderCreation :: QualifiedAlias sch tab
-> NP (Aliased (ColumnTypeExpression db0)) columns
-> NP (Aliased (TableConstraintExpression sch tab db1)) constraints
-> ByteString
renderCreation QualifiedAlias sch tab
tab NP (Aliased (ColumnTypeExpression db0)) columns
columns NP (Aliased (TableConstraintExpression sch tab db1)) constraints
constraints = QualifiedAlias sch tab -> ByteString
forall sql. RenderSQL sql => sql -> ByteString
renderSQL QualifiedAlias sch tab
tab
  ByteString -> ByteString -> ByteString
<+> ByteString -> ByteString
parenthesized
    ( (forall (x :: (Symbol, ColumnType)).
 Aliased (ColumnTypeExpression db0) x -> ByteString)
-> NP (Aliased (ColumnTypeExpression db0)) columns -> ByteString
forall k (xs :: [k]) (expression :: k -> *).
SListI xs =>
(forall (x :: k). expression x -> ByteString)
-> NP expression xs -> ByteString
renderCommaSeparated forall (db :: SchemasType) (x :: (Symbol, ColumnType)).
Aliased (ColumnTypeExpression db) x -> ByteString
forall (x :: (Symbol, ColumnType)).
Aliased (ColumnTypeExpression db0) x -> ByteString
renderColumnDef NP (Aliased (ColumnTypeExpression db0)) columns
columns
      ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ( case NP (Aliased (TableConstraintExpression sch tab db1)) constraints
constraints of
             NP (Aliased (TableConstraintExpression sch tab db1)) constraints
Nil -> ByteString
""
             NP (Aliased (TableConstraintExpression sch tab db1)) constraints
_ -> ByteString
", " ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<>
               (forall (x :: (Symbol, TableConstraint)).
 Aliased (TableConstraintExpression sch tab db1) x -> ByteString)
-> NP (Aliased (TableConstraintExpression sch tab db1)) constraints
-> ByteString
forall k (xs :: [k]) (expression :: k -> *).
SListI xs =>
(forall (x :: k). expression x -> ByteString)
-> NP expression xs -> ByteString
renderCommaSeparated forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (constraint :: (Symbol, TableConstraint)).
Aliased (TableConstraintExpression sch tab db) constraint
-> ByteString
forall (x :: (Symbol, TableConstraint)).
Aliased (TableConstraintExpression sch tab db1) x -> ByteString
renderConstraint NP (Aliased (TableConstraintExpression sch tab db1)) constraints
constraints ) )
  ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
";"
  where
    renderColumnDef :: Aliased (ColumnTypeExpression db) x -> ByteString
    renderColumnDef :: Aliased (ColumnTypeExpression db) x -> ByteString
renderColumnDef (ColumnTypeExpression db ty
ty `As` Alias alias
column) =
      Alias alias -> ByteString
forall sql. RenderSQL sql => sql -> ByteString
renderSQL Alias alias
column ByteString -> ByteString -> ByteString
<+> ColumnTypeExpression db ty -> ByteString
forall (db :: SchemasType) (ty :: ColumnType).
ColumnTypeExpression db ty -> ByteString
renderColumnTypeExpression ColumnTypeExpression db ty
ty
    renderConstraint
      :: Aliased (TableConstraintExpression sch tab db) constraint
      -> ByteString
    renderConstraint :: Aliased (TableConstraintExpression sch tab db) constraint
-> ByteString
renderConstraint (TableConstraintExpression sch tab db ty
constraint `As` Alias alias
alias) =
      ByteString
"CONSTRAINT" ByteString -> ByteString -> ByteString
<+> Alias alias -> ByteString
forall sql. RenderSQL sql => sql -> ByteString
renderSQL Alias alias
alias ByteString -> ByteString -> ByteString
<+> TableConstraintExpression sch tab db ty -> ByteString
forall sql. RenderSQL sql => sql -> ByteString
renderSQL TableConstraintExpression sch tab db ty
constraint

-- | `dropTable` removes a table from the schema.
--
-- >>> :{
-- let
--   definition :: Definition '["public" ::: '["muh_table" ::: 'Table t]] (Public '[])
--   definition = dropTable #muh_table
-- :}
--
-- >>> printSQL definition
-- DROP TABLE "muh_table";
dropTable
  :: ( Has sch db schema
     , KnownSymbol tab )
  => QualifiedAlias sch tab -- ^ table to remove
  -> Definition db (Alter sch (DropSchemum tab 'Table schema) db)
dropTable :: QualifiedAlias sch tab
-> Definition db (Alter sch (DropSchemum tab 'Table schema) db)
dropTable QualifiedAlias sch tab
tab = ByteString
-> Definition db (Alter sch (DropSchemum tab 'Table schema) db)
forall (db0 :: SchemasType) (db1 :: SchemasType).
ByteString -> Definition db0 db1
UnsafeDefinition (ByteString
 -> Definition db (Alter sch (DropSchemum tab 'Table schema) db))
-> ByteString
-> Definition db (Alter sch (DropSchemum tab 'Table schema) db)
forall a b. (a -> b) -> a -> b
$ ByteString
"DROP TABLE" ByteString -> ByteString -> ByteString
<+> QualifiedAlias sch tab -> ByteString
forall sql. RenderSQL sql => sql -> ByteString
renderSQL QualifiedAlias sch tab
tab ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
";"

-- | Drop a table if it exists.
dropTableIfExists
  :: ( Has sch db schema
     , KnownSymbol tab)
  => QualifiedAlias sch tab -- ^ table to remove
  -> Definition db (Alter sch (DropSchemumIfExists tab 'Table schema) db)
dropTableIfExists :: QualifiedAlias sch tab
-> Definition
     db (Alter sch (DropSchemumIfExists tab 'Table schema) db)
dropTableIfExists QualifiedAlias sch tab
tab = ByteString
-> Definition
     db (Alter sch (DropSchemumIfExists tab 'Table schema) db)
forall (db0 :: SchemasType) (db1 :: SchemasType).
ByteString -> Definition db0 db1
UnsafeDefinition (ByteString
 -> Definition
      db (Alter sch (DropSchemumIfExists tab 'Table schema) db))
-> ByteString
-> Definition
     db (Alter sch (DropSchemumIfExists tab 'Table schema) db)
forall a b. (a -> b) -> a -> b
$
  ByteString
"DROP TABLE IF EXISTS" ByteString -> ByteString -> ByteString
<+> QualifiedAlias sch tab -> ByteString
forall sql. RenderSQL sql => sql -> ByteString
renderSQL QualifiedAlias sch tab
tab ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
";"

-- | `alterTable` changes the definition of a table from the schema.
alterTable
  :: (Has sch db schema, KnownSymbol tab)
  => QualifiedAlias sch tab -- ^ table to alter
  -> AlterTable sch tab db table -- ^ alteration to perform
  -> Definition db (Alter sch (Alter tab ('Table table) schema) db)
alterTable :: QualifiedAlias sch tab
-> AlterTable sch tab db table
-> Definition db (Alter sch (Alter tab ('Table table) schema) db)
alterTable QualifiedAlias sch tab
tab AlterTable sch tab db table
alteration = ByteString
-> Definition db (Alter sch (Alter tab ('Table table) schema) db)
forall (db0 :: SchemasType) (db1 :: SchemasType).
ByteString -> Definition db0 db1
UnsafeDefinition (ByteString
 -> Definition db (Alter sch (Alter tab ('Table table) schema) db))
-> ByteString
-> Definition db (Alter sch (Alter tab ('Table table) schema) db)
forall a b. (a -> b) -> a -> b
$
  ByteString
"ALTER TABLE"
  ByteString -> ByteString -> ByteString
<+> QualifiedAlias sch tab -> ByteString
forall sql. RenderSQL sql => sql -> ByteString
renderSQL QualifiedAlias sch tab
tab
  ByteString -> ByteString -> ByteString
<+> AlterTable sch tab db table -> ByteString
forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
AlterTable sch tab db table -> ByteString
renderAlterTable AlterTable sch tab db table
alteration
  ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
";"

-- | `alterTable` changes the definition of a table from the schema.
alterTableIfExists
  :: (Has sch db schema, KnownSymbol tab)
  => QualifiedAlias sch tab -- ^ table to alter
  -> AlterTable sch tab db table -- ^ alteration to perform
  -> Definition db (Alter sch (AlterIfExists tab ('Table table) schema) db)
alterTableIfExists :: QualifiedAlias sch tab
-> AlterTable sch tab db table
-> Definition
     db (Alter sch (AlterIfExists tab ('Table table) schema) db)
alterTableIfExists QualifiedAlias sch tab
tab AlterTable sch tab db table
alteration = ByteString
-> Definition
     db (Alter sch (AlterIfExists tab ('Table table) schema) db)
forall (db0 :: SchemasType) (db1 :: SchemasType).
ByteString -> Definition db0 db1
UnsafeDefinition (ByteString
 -> Definition
      db (Alter sch (AlterIfExists tab ('Table table) schema) db))
-> ByteString
-> Definition
     db (Alter sch (AlterIfExists tab ('Table table) schema) db)
forall a b. (a -> b) -> a -> b
$
  ByteString
"ALTER TABLE IF EXISTS"
  ByteString -> ByteString -> ByteString
<+> QualifiedAlias sch tab -> ByteString
forall sql. RenderSQL sql => sql -> ByteString
renderSQL QualifiedAlias sch tab
tab
  ByteString -> ByteString -> ByteString
<+> AlterTable sch tab db table -> ByteString
forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
AlterTable sch tab db table -> ByteString
renderAlterTable AlterTable sch tab db table
alteration
  ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
";"

-- | `alterTableRename` changes the name of a table from the schema.
--
-- >>> type Schemas = '[ "public" ::: '[ "foo" ::: 'Table ('[] :=> '[]) ] ]
-- >>> :{
--  let migration :: Definition Schemas '["public" ::: '["bar" ::: 'Table ('[] :=> '[]) ] ]
--      migration = alterTableRename #foo #bar
--  in printSQL migration
-- :}
-- ALTER TABLE "foo" RENAME TO "bar";
alterTableRename
  :: ( Has sch db schema
     , KnownSymbol tab1
     , Has tab0 schema ('Table table))
  => QualifiedAlias sch tab0 -- ^ table to rename
  -> Alias tab1 -- ^ what to rename it
  -> Definition db (Alter sch (Rename tab0 tab1 schema) db )
alterTableRename :: QualifiedAlias sch tab0
-> Alias tab1
-> Definition db (Alter sch (Rename tab0 tab1 schema) db)
alterTableRename QualifiedAlias sch tab0
tab0 Alias tab1
tab1 = ByteString
-> Definition db (Alter sch (Rename tab0 tab1 schema) db)
forall (db0 :: SchemasType) (db1 :: SchemasType).
ByteString -> Definition db0 db1
UnsafeDefinition (ByteString
 -> Definition db (Alter sch (Rename tab0 tab1 schema) db))
-> ByteString
-> Definition db (Alter sch (Rename tab0 tab1 schema) db)
forall a b. (a -> b) -> a -> b
$
  ByteString
"ALTER TABLE" ByteString -> ByteString -> ByteString
<+> QualifiedAlias sch tab0 -> ByteString
forall sql. RenderSQL sql => sql -> ByteString
renderSQL QualifiedAlias sch tab0
tab0
  ByteString -> ByteString -> ByteString
<+> ByteString
"RENAME TO" ByteString -> ByteString -> ByteString
<+> Alias tab1 -> ByteString
forall sql. RenderSQL sql => sql -> ByteString
renderSQL Alias tab1
tab1 ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
";"

-- | `alterTableIfExistsRename` changes the name of a table from the schema if it exists.
--
-- >>> type Schemas = '[ "public" ::: '[ "foo" ::: 'Table ('[] :=> '[]) ] ]
-- >>> :{
--  let migration :: Definition Schemas Schemas
--      migration = alterTableIfExistsRename #goo #gar
--  in printSQL migration
-- :}
-- ALTER TABLE IF EXISTS "goo" RENAME TO "gar";
alterTableIfExistsRename
  :: ( Has sch db schema
     , KnownSymbol tab0
     , KnownSymbol tab1 )
  => QualifiedAlias sch tab0 -- ^ table to rename
  -> Alias tab1 -- ^ what to rename it
  -> Definition db (Alter sch (RenameIfExists tab0 tab1 schema) db )
alterTableIfExistsRename :: QualifiedAlias sch tab0
-> Alias tab1
-> Definition db (Alter sch (RenameIfExists tab0 tab1 schema) db)
alterTableIfExistsRename QualifiedAlias sch tab0
tab0 Alias tab1
tab1 = ByteString
-> Definition db (Alter sch (RenameIfExists tab0 tab1 schema) db)
forall (db0 :: SchemasType) (db1 :: SchemasType).
ByteString -> Definition db0 db1
UnsafeDefinition (ByteString
 -> Definition db (Alter sch (RenameIfExists tab0 tab1 schema) db))
-> ByteString
-> Definition db (Alter sch (RenameIfExists tab0 tab1 schema) db)
forall a b. (a -> b) -> a -> b
$
  ByteString
"ALTER TABLE IF EXISTS" ByteString -> ByteString -> ByteString
<+> QualifiedAlias sch tab0 -> ByteString
forall sql. RenderSQL sql => sql -> ByteString
renderSQL QualifiedAlias sch tab0
tab0
  ByteString -> ByteString -> ByteString
<+> ByteString
"RENAME TO" ByteString -> ByteString -> ByteString
<+> Alias tab1 -> ByteString
forall sql. RenderSQL sql => sql -> ByteString
renderSQL Alias tab1
tab1 ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
";"

{- | This form moves the table into another schema.

>>> type DB0 = '[ "sch0" ::: '[ "tab" ::: 'Table ('[] :=> '[]) ], "sch1" ::: '[] ]
>>> type DB1 = '[ "sch0" ::: '[], "sch1" ::: '[ "tab" ::: 'Table ('[] :=> '[]) ] ]
>>> :{
let def :: Definition DB0 DB1
    def = alterTableSetSchema (#sch0 ! #tab) #sch1
in printSQL def
:}
ALTER TABLE "sch0"."tab" SET SCHEMA "sch1";
-}
alterTableSetSchema
  :: ( Has sch0 db schema0
     , Has tab schema0 ('Table table)
     , Has sch1 db schema1 )
  => QualifiedAlias sch0 tab -- ^ table to move
  -> Alias sch1 -- ^ where to move it
  -> Definition db (SetSchema sch0 sch1 schema0 schema1 tab 'Table table db)
alterTableSetSchema :: QualifiedAlias sch0 tab
-> Alias sch1
-> Definition
     db (SetSchema sch0 sch1 schema0 schema1 tab 'Table table db)
alterTableSetSchema QualifiedAlias sch0 tab
tab Alias sch1
sch = ByteString
-> Definition
     db
     (Alter
        sch1
        (Create tab ('Table table) schema1)
        (Alter sch0 (DropSchemum tab 'Table schema0) db))
forall (db0 :: SchemasType) (db1 :: SchemasType).
ByteString -> Definition db0 db1
UnsafeDefinition (ByteString
 -> Definition
      db
      (Alter
         sch1
         (Create tab ('Table table) schema1)
         (Alter sch0 (DropSchemum tab 'Table schema0) db)))
-> ByteString
-> Definition
     db
     (Alter
        sch1
        (Create tab ('Table table) schema1)
        (Alter sch0 (DropSchemum tab 'Table schema0) db))
forall a b. (a -> b) -> a -> b
$
  ByteString
"ALTER TABLE" ByteString -> ByteString -> ByteString
<+> QualifiedAlias sch0 tab -> ByteString
forall sql. RenderSQL sql => sql -> ByteString
renderSQL QualifiedAlias sch0 tab
tab ByteString -> ByteString -> ByteString
<+> ByteString
"SET SCHEMA" ByteString -> ByteString -> ByteString
<+> Alias sch1 -> ByteString
forall sql. RenderSQL sql => sql -> ByteString
renderSQL Alias sch1
sch ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
";"

-- | An `AlterTable` describes the alteration to perform on the columns
-- of a table.
newtype AlterTable
  (sch :: Symbol)
  (tab :: Symbol)
  (db :: SchemasType)
  (table :: TableType) =
    UnsafeAlterTable {AlterTable sch tab db table -> ByteString
renderAlterTable :: ByteString}
  deriving ((forall x.
 AlterTable sch tab db table -> Rep (AlterTable sch tab db table) x)
-> (forall x.
    Rep (AlterTable sch tab db table) x -> AlterTable sch tab db table)
-> Generic (AlterTable sch tab db table)
forall x.
Rep (AlterTable sch tab db table) x -> AlterTable sch tab db table
forall x.
AlterTable sch tab db table -> Rep (AlterTable sch tab db table) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType) x.
Rep (AlterTable sch tab db table) x -> AlterTable sch tab db table
forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType) x.
AlterTable sch tab db table -> Rep (AlterTable sch tab db table) x
$cto :: forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType) x.
Rep (AlterTable sch tab db table) x -> AlterTable sch tab db table
$cfrom :: forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType) x.
AlterTable sch tab db table -> Rep (AlterTable sch tab db table) x
GHC.Generic,Int -> AlterTable sch tab db table -> ShowS
[AlterTable sch tab db table] -> ShowS
AlterTable sch tab db table -> String
(Int -> AlterTable sch tab db table -> ShowS)
-> (AlterTable sch tab db table -> String)
-> ([AlterTable sch tab db table] -> ShowS)
-> Show (AlterTable sch tab db table)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
Int -> AlterTable sch tab db table -> ShowS
forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
[AlterTable sch tab db table] -> ShowS
forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
AlterTable sch tab db table -> String
showList :: [AlterTable sch tab db table] -> ShowS
$cshowList :: forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
[AlterTable sch tab db table] -> ShowS
show :: AlterTable sch tab db table -> String
$cshow :: forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
AlterTable sch tab db table -> String
showsPrec :: Int -> AlterTable sch tab db table -> ShowS
$cshowsPrec :: forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
Int -> AlterTable sch tab db table -> ShowS
Show,AlterTable sch tab db table -> AlterTable sch tab db table -> Bool
(AlterTable sch tab db table
 -> AlterTable sch tab db table -> Bool)
-> (AlterTable sch tab db table
    -> AlterTable sch tab db table -> Bool)
-> Eq (AlterTable sch tab db table)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
AlterTable sch tab db table -> AlterTable sch tab db table -> Bool
/= :: AlterTable sch tab db table -> AlterTable sch tab db table -> Bool
$c/= :: forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
AlterTable sch tab db table -> AlterTable sch tab db table -> Bool
== :: AlterTable sch tab db table -> AlterTable sch tab db table -> Bool
$c== :: forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
AlterTable sch tab db table -> AlterTable sch tab db table -> Bool
Eq,Eq (AlterTable sch tab db table)
Eq (AlterTable sch tab db table)
-> (AlterTable sch tab db table
    -> AlterTable sch tab db table -> Ordering)
-> (AlterTable sch tab db table
    -> AlterTable sch tab db table -> Bool)
-> (AlterTable sch tab db table
    -> AlterTable sch tab db table -> Bool)
-> (AlterTable sch tab db table
    -> AlterTable sch tab db table -> Bool)
-> (AlterTable sch tab db table
    -> AlterTable sch tab db table -> Bool)
-> (AlterTable sch tab db table
    -> AlterTable sch tab db table -> AlterTable sch tab db table)
-> (AlterTable sch tab db table
    -> AlterTable sch tab db table -> AlterTable sch tab db table)
-> Ord (AlterTable sch tab db table)
AlterTable sch tab db table -> AlterTable sch tab db table -> Bool
AlterTable sch tab db table
-> AlterTable sch tab db table -> Ordering
AlterTable sch tab db table
-> AlterTable sch tab db table -> AlterTable sch tab db table
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
forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
Eq (AlterTable sch tab db table)
forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
AlterTable sch tab db table -> AlterTable sch tab db table -> Bool
forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
AlterTable sch tab db table
-> AlterTable sch tab db table -> Ordering
forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
AlterTable sch tab db table
-> AlterTable sch tab db table -> AlterTable sch tab db table
min :: AlterTable sch tab db table
-> AlterTable sch tab db table -> AlterTable sch tab db table
$cmin :: forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
AlterTable sch tab db table
-> AlterTable sch tab db table -> AlterTable sch tab db table
max :: AlterTable sch tab db table
-> AlterTable sch tab db table -> AlterTable sch tab db table
$cmax :: forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
AlterTable sch tab db table
-> AlterTable sch tab db table -> AlterTable sch tab db table
>= :: AlterTable sch tab db table -> AlterTable sch tab db table -> Bool
$c>= :: forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
AlterTable sch tab db table -> AlterTable sch tab db table -> Bool
> :: AlterTable sch tab db table -> AlterTable sch tab db table -> Bool
$c> :: forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
AlterTable sch tab db table -> AlterTable sch tab db table -> Bool
<= :: AlterTable sch tab db table -> AlterTable sch tab db table -> Bool
$c<= :: forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
AlterTable sch tab db table -> AlterTable sch tab db table -> Bool
< :: AlterTable sch tab db table -> AlterTable sch tab db table -> Bool
$c< :: forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
AlterTable sch tab db table -> AlterTable sch tab db table -> Bool
compare :: AlterTable sch tab db table
-> AlterTable sch tab db table -> Ordering
$ccompare :: forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
AlterTable sch tab db table
-> AlterTable sch tab db table -> Ordering
$cp1Ord :: forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
Eq (AlterTable sch tab db table)
Ord,AlterTable sch tab db table -> ()
(AlterTable sch tab db table -> ())
-> NFData (AlterTable sch tab db table)
forall a. (a -> ()) -> NFData a
forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
AlterTable sch tab db table -> ()
rnf :: AlterTable sch tab db table -> ()
$crnf :: forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
AlterTable sch tab db table -> ()
NFData)

-- | An `addConstraint` adds a table constraint.
--
-- >>> :{
-- let
--   definition :: Definition
--     '["public" ::: '["tab" ::: 'Table ('[] :=> '["col" ::: 'NoDef :=> 'NotNull 'PGint4])]]
--     '["public" ::: '["tab" ::: 'Table ('["positive" ::: 'Check '["col"]] :=> '["col" ::: 'NoDef :=> 'NotNull 'PGint4])]]
--   definition = alterTable #tab (addConstraint #positive (check #col (#col .> 0)))
-- in printSQL definition
-- :}
-- ALTER TABLE "tab" ADD CONSTRAINT "positive" CHECK (("col" > (0 :: int4)));
addConstraint
  :: ( KnownSymbol alias
     , Has sch db schema
     , Has tab schema ('Table (constraints :=> columns)) )
  => Alias alias
  -> TableConstraintExpression sch tab db constraint
  -- ^ constraint to add
  -> AlterTable sch tab db (Create alias constraint constraints :=> columns)
addConstraint :: Alias alias
-> TableConstraintExpression sch tab db constraint
-> AlterTable
     sch tab db (Create alias constraint constraints :=> columns)
addConstraint Alias alias
alias TableConstraintExpression sch tab db constraint
constraint = ByteString
-> AlterTable
     sch tab db (Create alias constraint constraints :=> columns)
forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
ByteString -> AlterTable sch tab db table
UnsafeAlterTable (ByteString
 -> AlterTable
      sch tab db (Create alias constraint constraints :=> columns))
-> ByteString
-> AlterTable
     sch tab db (Create alias constraint constraints :=> columns)
forall a b. (a -> b) -> a -> b
$
  ByteString
"ADD" ByteString -> ByteString -> ByteString
<+> ByteString
"CONSTRAINT" ByteString -> ByteString -> ByteString
<+> Alias alias -> ByteString
forall sql. RenderSQL sql => sql -> ByteString
renderSQL Alias alias
alias
    ByteString -> ByteString -> ByteString
<+> TableConstraintExpression sch tab db constraint -> ByteString
forall sql. RenderSQL sql => sql -> ByteString
renderSQL TableConstraintExpression sch tab db constraint
constraint

-- | A `dropConstraint` drops a table constraint.
--
-- >>> :{
-- let
--   definition :: Definition
--     '["public" ::: '["tab" ::: 'Table ('["positive" ::: Check '["col"]] :=> '["col" ::: 'NoDef :=> 'NotNull 'PGint4])]]
--     '["public" ::: '["tab" ::: 'Table ('[] :=> '["col" ::: 'NoDef :=> 'NotNull 'PGint4])]]
--   definition = alterTable #tab (dropConstraint #positive)
-- in printSQL definition
-- :}
-- ALTER TABLE "tab" DROP CONSTRAINT "positive";
dropConstraint
  :: ( KnownSymbol constraint
     , Has sch db schema
     , Has tab schema ('Table (constraints :=> columns)) )
  => Alias constraint
  -- ^ constraint to drop
  -> AlterTable sch tab db (Drop constraint constraints :=> columns)
dropConstraint :: Alias constraint
-> AlterTable sch tab db (Drop constraint constraints :=> columns)
dropConstraint Alias constraint
constraint = ByteString
-> AlterTable sch tab db (Drop constraint constraints :=> columns)
forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
ByteString -> AlterTable sch tab db table
UnsafeAlterTable (ByteString
 -> AlterTable sch tab db (Drop constraint constraints :=> columns))
-> ByteString
-> AlterTable sch tab db (Drop constraint constraints :=> columns)
forall a b. (a -> b) -> a -> b
$
  ByteString
"DROP" ByteString -> ByteString -> ByteString
<+> ByteString
"CONSTRAINT" ByteString -> ByteString -> ByteString
<+> Alias constraint -> ByteString
forall sql. RenderSQL sql => sql -> ByteString
renderSQL Alias constraint
constraint

-- | An `AddColumn` is either @NULL@ or has @DEFAULT@.
class AddColumn ty where
  -- | `addColumn` adds a new column, initially filled with whatever
  -- default value is given or with @NULL@.
  --
  -- >>> :{
  -- let
  --   definition :: Definition
  --     '["public" ::: '["tab" ::: 'Table ('[] :=> '["col1" ::: 'NoDef :=> 'Null 'PGint4])]]
  --     '["public" ::: '["tab" ::: 'Table ('[] :=>
  --        '[ "col1" ::: 'NoDef :=> 'Null 'PGint4
  --         , "col2" ::: 'Def :=> 'Null 'PGtext ])]]
  --   definition = alterTable #tab (addColumn #col2 (text & nullable & default_ "foo"))
  -- in printSQL definition
  -- :}
  -- ALTER TABLE "tab" ADD COLUMN "col2" text NULL DEFAULT (E'foo' :: text);
  --
  -- >>> :{
  -- let
  --   definition :: Definition
  --     '["public" ::: '["tab" ::: 'Table ('[] :=> '["col1" ::: 'NoDef :=> 'Null 'PGint4])]]
  --     '["public" ::: '["tab" ::: 'Table ('[] :=>
  --        '[ "col1" ::: 'NoDef :=> 'Null 'PGint4
  --         , "col2" ::: 'NoDef :=> 'Null 'PGtext ])]]
  --   definition = alterTable #tab (addColumn #col2 (text & nullable))
  -- in printSQL definition
  -- :}
  -- ALTER TABLE "tab" ADD COLUMN "col2" text NULL;
  addColumn
    :: ( KnownSymbol column
       , Has sch db schema
       , Has tab schema ('Table (constraints :=> columns)) )
    => Alias column -- ^ column to add
    -> ColumnTypeExpression db ty -- ^ type of the new column
    -> AlterTable sch tab db (constraints :=> Create column ty columns)
  addColumn Alias column
column ColumnTypeExpression db ty
ty = ByteString
-> AlterTable sch tab db (constraints :=> Create column ty columns)
forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
ByteString -> AlterTable sch tab db table
UnsafeAlterTable (ByteString
 -> AlterTable
      sch tab db (constraints :=> Create column ty columns))
-> ByteString
-> AlterTable sch tab db (constraints :=> Create column ty columns)
forall a b. (a -> b) -> a -> b
$
    ByteString
"ADD COLUMN" ByteString -> ByteString -> ByteString
<+> Alias column -> ByteString
forall sql. RenderSQL sql => sql -> ByteString
renderSQL Alias column
column ByteString -> ByteString -> ByteString
<+> ColumnTypeExpression db ty -> ByteString
forall (db :: SchemasType) (ty :: ColumnType).
ColumnTypeExpression db ty -> ByteString
renderColumnTypeExpression ColumnTypeExpression db ty
ty
instance {-# OVERLAPPING #-} AddColumn ('Def :=> ty)
instance {-# OVERLAPPABLE #-} AddColumn ('NoDef :=> 'Null ty)

-- | A `dropColumn` removes a column. Whatever data was in the column
-- disappears. Table constraints involving the column are dropped, too.
-- However, if the column is referenced by a foreign key constraint of
-- another table, PostgreSQL will not silently drop that constraint.
--
-- >>> :{
-- let
--   definition :: Definition
--     '["public" ::: '["tab" ::: 'Table ('[] :=>
--        '[ "col1" ::: 'NoDef :=> 'Null 'PGint4
--         , "col2" ::: 'NoDef :=> 'Null 'PGtext ])]]
--     '["public" ::: '["tab" ::: 'Table ('[] :=> '["col1" ::: 'NoDef :=> 'Null 'PGint4])]]
--   definition = alterTable #tab (dropColumn #col2)
-- in printSQL definition
-- :}
-- ALTER TABLE "tab" DROP COLUMN "col2";
dropColumn
  :: ( KnownSymbol column
     , Has sch db schema
     , Has tab schema ('Table (constraints :=> columns)) )
  => Alias column -- ^ column to remove
  -> AlterTable sch tab db (constraints :=> Drop column columns)
dropColumn :: Alias column
-> AlterTable sch tab db (constraints :=> Drop column columns)
dropColumn Alias column
column = ByteString
-> AlterTable sch tab db (constraints :=> Drop column columns)
forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
ByteString -> AlterTable sch tab db table
UnsafeAlterTable (ByteString
 -> AlterTable sch tab db (constraints :=> Drop column columns))
-> ByteString
-> AlterTable sch tab db (constraints :=> Drop column columns)
forall a b. (a -> b) -> a -> b
$
  ByteString
"DROP COLUMN" ByteString -> ByteString -> ByteString
<+> Alias column -> ByteString
forall sql. RenderSQL sql => sql -> ByteString
renderSQL Alias column
column

-- | A `renameColumn` renames a column.
--
-- >>> :{
-- let
--   definition :: Definition
--     '["public" ::: '["tab" ::: 'Table ('[] :=> '["foo" ::: 'NoDef :=> 'Null 'PGint4])]]
--     '["public" ::: '["tab" ::: 'Table ('[] :=> '["bar" ::: 'NoDef :=> 'Null 'PGint4])]]
--   definition = alterTable #tab (renameColumn #foo #bar)
-- in printSQL definition
-- :}
-- ALTER TABLE "tab" RENAME COLUMN "foo" TO "bar";
renameColumn
  :: ( KnownSymbol column0
     , KnownSymbol column1
     , Has sch db schema
     , Has tab schema ('Table (constraints :=> columns)) )
  => Alias column0 -- ^ column to rename
  -> Alias column1 -- ^ what to rename the column
  -> AlterTable sch tab db (constraints :=> Rename column0 column1 columns)
renameColumn :: Alias column0
-> Alias column1
-> AlterTable
     sch tab db (constraints :=> Rename column0 column1 columns)
renameColumn Alias column0
column0 Alias column1
column1 = ByteString
-> AlterTable
     sch tab db (constraints :=> Rename column0 column1 columns)
forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
ByteString -> AlterTable sch tab db table
UnsafeAlterTable (ByteString
 -> AlterTable
      sch tab db (constraints :=> Rename column0 column1 columns))
-> ByteString
-> AlterTable
     sch tab db (constraints :=> Rename column0 column1 columns)
forall a b. (a -> b) -> a -> b
$
  ByteString
"RENAME COLUMN" ByteString -> ByteString -> ByteString
<+> Alias column0 -> ByteString
forall sql. RenderSQL sql => sql -> ByteString
renderSQL Alias column0
column0  ByteString -> ByteString -> ByteString
<+> ByteString
"TO" ByteString -> ByteString -> ByteString
<+> Alias column1 -> ByteString
forall sql. RenderSQL sql => sql -> ByteString
renderSQL Alias column1
column1

-- | An `alterColumn` alters a single column.
alterColumn
  :: ( KnownSymbol column
     , Has sch db schema
     , Has tab schema ('Table (constraints :=> columns))
     , Has column columns ty0 )
  => Alias column -- ^ column to alter
  -> AlterColumn db ty0 ty1 -- ^ alteration to perform
  -> AlterTable sch tab db (constraints :=> Alter column ty1 columns)
alterColumn :: Alias column
-> AlterColumn db ty0 ty1
-> AlterTable sch tab db (constraints :=> Alter column ty1 columns)
alterColumn Alias column
column AlterColumn db ty0 ty1
alteration = ByteString
-> AlterTable sch tab db (constraints :=> Alter column ty1 columns)
forall (sch :: Symbol) (tab :: Symbol) (db :: SchemasType)
       (table :: TableType).
ByteString -> AlterTable sch tab db table
UnsafeAlterTable (ByteString
 -> AlterTable
      sch tab db (constraints :=> Alter column ty1 columns))
-> ByteString
-> AlterTable sch tab db (constraints :=> Alter column ty1 columns)
forall a b. (a -> b) -> a -> b
$
  ByteString
"ALTER COLUMN" ByteString -> ByteString -> ByteString
<+> Alias column -> ByteString
forall sql. RenderSQL sql => sql -> ByteString
renderSQL Alias column
column ByteString -> ByteString -> ByteString
<+> AlterColumn db ty0 ty1 -> ByteString
forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
AlterColumn db ty0 ty1 -> ByteString
renderAlterColumn AlterColumn db ty0 ty1
alteration

-- | An `AlterColumn` describes the alteration to perform on a single column.
newtype AlterColumn (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType) =
  UnsafeAlterColumn {AlterColumn db ty0 ty1 -> ByteString
renderAlterColumn :: ByteString}
  deriving ((forall x.
 AlterColumn db ty0 ty1 -> Rep (AlterColumn db ty0 ty1) x)
-> (forall x.
    Rep (AlterColumn db ty0 ty1) x -> AlterColumn db ty0 ty1)
-> Generic (AlterColumn db ty0 ty1)
forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType)
       x.
Rep (AlterColumn db ty0 ty1) x -> AlterColumn db ty0 ty1
forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType)
       x.
AlterColumn db ty0 ty1 -> Rep (AlterColumn db ty0 ty1) x
forall x. Rep (AlterColumn db ty0 ty1) x -> AlterColumn db ty0 ty1
forall x. AlterColumn db ty0 ty1 -> Rep (AlterColumn db ty0 ty1) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType)
       x.
Rep (AlterColumn db ty0 ty1) x -> AlterColumn db ty0 ty1
$cfrom :: forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType)
       x.
AlterColumn db ty0 ty1 -> Rep (AlterColumn db ty0 ty1) x
GHC.Generic,Int -> AlterColumn db ty0 ty1 -> ShowS
[AlterColumn db ty0 ty1] -> ShowS
AlterColumn db ty0 ty1 -> String
(Int -> AlterColumn db ty0 ty1 -> ShowS)
-> (AlterColumn db ty0 ty1 -> String)
-> ([AlterColumn db ty0 ty1] -> ShowS)
-> Show (AlterColumn db ty0 ty1)
forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
Int -> AlterColumn db ty0 ty1 -> ShowS
forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
[AlterColumn db ty0 ty1] -> ShowS
forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
AlterColumn db ty0 ty1 -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AlterColumn db ty0 ty1] -> ShowS
$cshowList :: forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
[AlterColumn db ty0 ty1] -> ShowS
show :: AlterColumn db ty0 ty1 -> String
$cshow :: forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
AlterColumn db ty0 ty1 -> String
showsPrec :: Int -> AlterColumn db ty0 ty1 -> ShowS
$cshowsPrec :: forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
Int -> AlterColumn db ty0 ty1 -> ShowS
Show,AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Bool
(AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Bool)
-> (AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Bool)
-> Eq (AlterColumn db ty0 ty1)
forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Bool
$c/= :: forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Bool
== :: AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Bool
$c== :: forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Bool
Eq,Eq (AlterColumn db ty0 ty1)
Eq (AlterColumn db ty0 ty1)
-> (AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Ordering)
-> (AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Bool)
-> (AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Bool)
-> (AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Bool)
-> (AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Bool)
-> (AlterColumn db ty0 ty1
    -> AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1)
-> (AlterColumn db ty0 ty1
    -> AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1)
-> Ord (AlterColumn db ty0 ty1)
AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Bool
AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Ordering
AlterColumn db ty0 ty1
-> AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1
forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
Eq (AlterColumn db ty0 ty1)
forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Bool
forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Ordering
forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
AlterColumn db ty0 ty1
-> AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1
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
min :: AlterColumn db ty0 ty1
-> AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1
$cmin :: forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
AlterColumn db ty0 ty1
-> AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1
max :: AlterColumn db ty0 ty1
-> AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1
$cmax :: forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
AlterColumn db ty0 ty1
-> AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1
>= :: AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Bool
$c>= :: forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Bool
> :: AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Bool
$c> :: forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Bool
<= :: AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Bool
$c<= :: forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Bool
< :: AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Bool
$c< :: forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Bool
compare :: AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Ordering
$ccompare :: forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
AlterColumn db ty0 ty1 -> AlterColumn db ty0 ty1 -> Ordering
$cp1Ord :: forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
Eq (AlterColumn db ty0 ty1)
Ord,AlterColumn db ty0 ty1 -> ()
(AlterColumn db ty0 ty1 -> ()) -> NFData (AlterColumn db ty0 ty1)
forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
AlterColumn db ty0 ty1 -> ()
forall a. (a -> ()) -> NFData a
rnf :: AlterColumn db ty0 ty1 -> ()
$crnf :: forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
AlterColumn db ty0 ty1 -> ()
NFData)

-- | A `setDefault` sets a new default for a column. Note that this doesn't
-- affect any existing rows in the table, it just changes the default for
-- future insert and update commands.
--
-- >>> :{
-- let
--   definition :: Definition
--     '["public" ::: '["tab" ::: 'Table ('[] :=> '["col" ::: 'NoDef :=> 'Null 'PGint4])]]
--     '["public" ::: '["tab" ::: 'Table ('[] :=> '["col" ::: 'Def :=> 'Null 'PGint4])]]
--   definition = alterTable #tab (alterColumn #col (setDefault 5))
-- in printSQL definition
-- :}
-- ALTER TABLE "tab" ALTER COLUMN "col" SET DEFAULT (5 :: int4);
setDefault
  :: Expression 'Ungrouped '[] '[] db '[] '[] ty -- ^ default value to set
  -> AlterColumn db (constraint :=> ty) ('Def :=> ty)
setDefault :: Expression 'Ungrouped '[] '[] db '[] '[] ty
-> AlterColumn db (constraint :=> ty) ('Def :=> ty)
setDefault Expression 'Ungrouped '[] '[] db '[] '[] ty
expression = ByteString -> AlterColumn db (constraint :=> ty) ('Def :=> ty)
forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
ByteString -> AlterColumn db ty0 ty1
UnsafeAlterColumn (ByteString -> AlterColumn db (constraint :=> ty) ('Def :=> ty))
-> ByteString -> AlterColumn db (constraint :=> ty) ('Def :=> ty)
forall a b. (a -> b) -> a -> b
$
  ByteString
"SET DEFAULT" ByteString -> ByteString -> ByteString
<+> Expression 'Ungrouped '[] '[] db '[] '[] ty -> ByteString
forall (grp :: Grouping) (lat :: FromType) (with :: FromType)
       (db :: SchemasType) (params :: [NullType]) (from :: FromType)
       (ty :: NullType).
Expression grp lat with db params from ty -> ByteString
renderExpression Expression 'Ungrouped '[] '[] db '[] '[] ty
expression

-- | A `dropDefault` removes any default value for a column.
--
-- >>> :{
-- let
--   definition :: Definition
--     '["public" ::: '["tab" ::: 'Table ('[] :=> '["col" ::: 'Def :=> 'Null 'PGint4])]]
--     '["public" ::: '["tab" ::: 'Table ('[] :=> '["col" ::: 'NoDef :=> 'Null 'PGint4])]]
--   definition = alterTable #tab (alterColumn #col dropDefault)
-- in printSQL definition
-- :}
-- ALTER TABLE "tab" ALTER COLUMN "col" DROP DEFAULT;
dropDefault :: AlterColumn db ('Def :=> ty) ('NoDef :=> ty)
dropDefault :: AlterColumn db ('Def :=> ty) ('NoDef :=> ty)
dropDefault = ByteString -> AlterColumn db ('Def :=> ty) ('NoDef :=> ty)
forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
ByteString -> AlterColumn db ty0 ty1
UnsafeAlterColumn (ByteString -> AlterColumn db ('Def :=> ty) ('NoDef :=> ty))
-> ByteString -> AlterColumn db ('Def :=> ty) ('NoDef :=> ty)
forall a b. (a -> b) -> a -> b
$ ByteString
"DROP DEFAULT"

-- | A `setNotNull` adds a @NOT NULL@ constraint to a column.
-- The constraint will be checked immediately, so the table data must satisfy
-- the constraint before it can be added.
--
-- >>> :{
-- let
--   definition :: Definition
--     '["public" ::: '["tab" ::: 'Table ('[] :=> '["col" ::: 'NoDef :=> 'Null 'PGint4])]]
--     '["public" ::: '["tab" ::: 'Table ('[] :=> '["col" ::: 'NoDef :=> 'NotNull 'PGint4])]]
--   definition = alterTable #tab (alterColumn #col setNotNull)
-- in printSQL definition
-- :}
-- ALTER TABLE "tab" ALTER COLUMN "col" SET NOT NULL;
setNotNull
  :: AlterColumn db (constraint :=> 'Null ty) (constraint :=> 'NotNull ty)
setNotNull :: AlterColumn
  db (constraint :=> 'Null ty) (constraint :=> 'NotNull ty)
setNotNull = ByteString
-> AlterColumn
     db (constraint :=> 'Null ty) (constraint :=> 'NotNull ty)
forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
ByteString -> AlterColumn db ty0 ty1
UnsafeAlterColumn (ByteString
 -> AlterColumn
      db (constraint :=> 'Null ty) (constraint :=> 'NotNull ty))
-> ByteString
-> AlterColumn
     db (constraint :=> 'Null ty) (constraint :=> 'NotNull ty)
forall a b. (a -> b) -> a -> b
$ ByteString
"SET NOT NULL"

-- | A `dropNotNull` drops a @NOT NULL@ constraint from a column.
--
-- >>> :{
-- let
--   definition :: Definition
--     '["public" ::: '["tab" ::: 'Table ('[] :=> '["col" ::: 'NoDef :=> 'NotNull 'PGint4])]]
--     '["public" ::: '["tab" ::: 'Table ('[] :=> '["col" ::: 'NoDef :=> 'Null 'PGint4])]]
--   definition = alterTable #tab (alterColumn #col dropNotNull)
-- in printSQL definition
-- :}
-- ALTER TABLE "tab" ALTER COLUMN "col" DROP NOT NULL;
dropNotNull
  :: AlterColumn db (constraint :=> 'NotNull ty) (constraint :=> 'Null ty)
dropNotNull :: AlterColumn
  db (constraint :=> 'NotNull ty) (constraint :=> 'Null ty)
dropNotNull = ByteString
-> AlterColumn
     db (constraint :=> 'NotNull ty) (constraint :=> 'Null ty)
forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
ByteString -> AlterColumn db ty0 ty1
UnsafeAlterColumn (ByteString
 -> AlterColumn
      db (constraint :=> 'NotNull ty) (constraint :=> 'Null ty))
-> ByteString
-> AlterColumn
     db (constraint :=> 'NotNull ty) (constraint :=> 'Null ty)
forall a b. (a -> b) -> a -> b
$ ByteString
"DROP NOT NULL"

-- | An `alterType` converts a column to a different data type.
-- This will succeed only if each existing entry in the column can be
-- converted to the new type by an implicit cast.
--
-- >>> :{
-- let
--   definition :: Definition
--     '["public" ::: '["tab" ::: 'Table ('[] :=> '["col" ::: 'NoDef :=> 'NotNull 'PGint4])]]
--     '["public" ::: '["tab" ::: 'Table ('[] :=> '["col" ::: 'NoDef :=> 'NotNull 'PGnumeric])]]
--   definition =
--     alterTable #tab (alterColumn #col (alterType (numeric & notNullable)))
-- in printSQL definition
-- :}
-- ALTER TABLE "tab" ALTER COLUMN "col" TYPE numeric NOT NULL;
alterType :: ColumnTypeExpression db ty -> AlterColumn db ty0 ty
alterType :: ColumnTypeExpression db ty -> AlterColumn db ty0 ty
alterType ColumnTypeExpression db ty
ty = ByteString -> AlterColumn db ty0 ty
forall (db :: SchemasType) (ty0 :: ColumnType) (ty1 :: ColumnType).
ByteString -> AlterColumn db ty0 ty1
UnsafeAlterColumn (ByteString -> AlterColumn db ty0 ty)
-> ByteString -> AlterColumn db ty0 ty
forall a b. (a -> b) -> a -> b
$ ByteString
"TYPE" ByteString -> ByteString -> ByteString
<+> ColumnTypeExpression db ty -> ByteString
forall (db :: SchemasType) (ty :: ColumnType).
ColumnTypeExpression db ty -> ByteString
renderColumnTypeExpression ColumnTypeExpression db ty
ty