module Language.SQL.SQLite.Tools (
changeTableSchema
)
where
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Maybe
import Data.Set (Set)
import qualified Data.Set as Set
import Language.SQL.SQLite.Syntax
import Language.SQL.SQLite.Types
changeTableSchema
:: CreateTable
-> CreateTable
-> (Map UnqualifiedIdentifier Expression)
-> StatementList
changeTableSchema oldDefinition newDefinition columnDefaultMap
= let tableColumnNames :: CreateTable -> Set UnqualifiedIdentifier
tableColumnNames (CreateTable _ _ _ (ColumnsAndConstraints columns _))
= Set.fromList $ map columnDefinitionName $ fromOneOrMore columns
columnDefinitionName (ColumnDefinition name _ _) = name
oldColumns = tableColumnNames oldDefinition
newColumns = tableColumnNames newDefinition
removedColumns = Set.difference oldColumns newColumns
addedColumns = Set.difference newColumns oldColumns
preservedColumns = Set.intersection oldColumns newColumns
tableName :: CreateTable -> SinglyQualifiedIdentifier
tableName (CreateTable _ _ name _) = name
oldName = tableName oldDefinition
newName = tableName newDefinition
temporaryName = SinglyQualifiedIdentifier Nothing
$ "temporary_" ++ (identifierProperName oldName)
++ "_redefined_as_" ++ (identifierProperName newName)
columnDefault column = maybe ExpressionLiteralNull
id
$ Map.lookup column columnDefaultMap
beginTransactionStatement = Begin NoTransactionType Transaction
createTemporaryStatement
= CreateTable
Temporary
NoIfNotExists
temporaryName
(AsSelect
$ Select (SelectCore NoDistinctness
(fromJust $ mkOneOrMore [Star])
(Just
$ From
$ JoinSource (TableSource oldName
NoAs
NoIndexedBy)
[])
Nothing
Nothing)
[] Nothing Nothing)
dropStatement = DropTable NoIfExists oldName
recreateStatement = newDefinition
reinsertStatement
= Insert InsertNoAlternative
newName
$ InsertSelect
(concat [Set.toList preservedColumns,
Set.toList addedColumns])
(Select (SelectCore NoDistinctness
(fromJust
$ mkOneOrMore
$ map (\result -> Result result NoAs)
$ concat
[map (ExpressionIdentifier
. toDoublyQualifiedIdentifier)
$ Set.toList preservedColumns,
map columnDefault
$ Set.toList addedColumns])
(Just
$ From
$ JoinSource
(TableSource temporaryName
NoAs
NoIndexedBy)
[])
Nothing
Nothing)
[] Nothing Nothing)
dropTemporaryStatement = DropTable NoIfExists temporaryName
commitTransactionStatement = Commit CommitCommit Transaction
statementList = StatementList [Statement beginTransactionStatement,
Statement createTemporaryStatement,
Statement dropStatement,
Statement recreateStatement,
Statement reinsertStatement,
Statement dropTemporaryStatement,
Statement commitTransactionStatement]
in statementList