beam-automigrate-0.1.6.0: DB migration library for beam, targeting Postgres.
Safe HaskellNone
LanguageHaskell2010

Database.Beam.AutoMigrate

Description

This module provides the high-level API to migrate a database.

Synopsis

Annotating a database

The first thing to do in order to be able to use this library is to convert a Beam's DatabaseSettings into an AnnotatedDatabaseSettings. You typically have two options in order to do that:

  1. If you don't have an existing DatabaseSettings from a previous application, you can simply call defaultAnnotatedDbSettings with defaultDbSettings, as in defaultAnnotatedDbSettings defaultDbSettings;
  2. If you are starting from an existing DatabaseSettings, then simply call defaultAnnotatedDbSettings passing your existing DatabaseSettings.

Generating a Schema

Once you have an AnnotatedDatabaseSettings, you can produce a Schema simply by calling fromAnnotatedDbSettings. The second parameter can be used to selectively turn off automatic FK-discovery for one or more tables. For more information about specifying your own table constraints, refer to the Annotated module.

fromAnnotatedDbSettings :: (FromAnnotated be db DatabaseEntity AnnotatedDatabaseEntity, GSchema be db anns (Rep (AnnotatedDatabaseSettings be db))) => AnnotatedDatabaseSettings be db -> Proxy (anns :: [Annotation]) -> Schema Source #

Turns an AnnotatedDatabaseSettings into a Schema. Under the hood, this function will do the following:

  • It will turn each TableEntity of your database into a Table;
  • It will turn each PgEnum enumeration type into an Enumeration, which will map to an ENUM type in the DB;
  • It will run what we call the automatic FK-discovery algorithm. What this means practically speaking is that if a reference to an external PrimaryKey is found, and such PrimaryKey uniquely identifies another TableEntity in your database, the automatic FK-discovery algorithm will turn into into a ForeignKey TableConstraint, without any user intervention. In case there is ambiguity instead, the library will fail with a static error until the user won't disable the relevant tables (via the provided Proxy type) and annotate them to do the "right thing".

Downcasting an AnnotatedDatabaseSettings into a simple DatabaseSettings

Generating and running migrations

type Migration m = ExceptT MigrationError (StateT [WithPriority Edit] m) () Source #

A database Migration.

migrate :: MonadIO m => Connection -> Schema -> Migration m Source #

Given a Connection to a database and a Schema (which can be generated using fromAnnotatedDbSettings) it returns a Migration, which can then be executed via runMigration.

runMigrationUnsafe :: MonadBeam Postgres Pg => Connection -> Migration Pg -> IO () Source #

Runs the input Migration in a concrete Postgres backend.

runMigrationWithEditUpdate :: MonadBeam Postgres Pg => ([WithPriority Edit] -> [WithPriority Edit]) -> Connection -> Schema -> IO () Source #

Run the steps of the migration in priority order, providing a hook to allow the user to take action for Unsafe edits. The given function is only called for unsafe edits.

This allows you to perform some checks for when the edit safe in some circumstances.

  • Deleting an empty table/column
  • Making an empty column non-nullable

tryRunMigrationsWithEditUpdate :: (Generic (db (DatabaseEntity be db)), Generic (db (AnnotatedDatabaseEntity be db)), Database be db, GZipDatabase be (AnnotatedDatabaseEntity be db) (AnnotatedDatabaseEntity be db) (DatabaseEntity be db) (Rep (db (AnnotatedDatabaseEntity be db))) (Rep (db (AnnotatedDatabaseEntity be db))) (Rep (db (DatabaseEntity be db))), GSchema be db '[] (Rep (db (AnnotatedDatabaseEntity be db)))) => AnnotatedDatabaseSettings be db -> Connection -> IO () Source #

Compare the existing schema in the database with the expected schema in Haskell and try to edit the existing schema as necessary

calcMigrationSteps :: (Generic (db (DatabaseEntity be db)), Generic (db (AnnotatedDatabaseEntity be db)), Database be db, GZipDatabase be (AnnotatedDatabaseEntity be db) (AnnotatedDatabaseEntity be db) (DatabaseEntity be db) (Rep (db (AnnotatedDatabaseEntity be db))) (Rep (db (AnnotatedDatabaseEntity be db))) (Rep (db (DatabaseEntity be db))), GSchema be db '[] (Rep (db (AnnotatedDatabaseEntity be db)))) => AnnotatedDatabaseSettings be db -> Connection -> IO Diff Source #

Compute the Diff consisting of the steps that would be taken to migrate from the current actual database schema to the given one, without actually performing the migration.

Creating a migration from a Diff

createMigration :: Monad m => Diff -> Migration m Source #

Create the migration from a Diff.

Migration utility functions

splitEditsOnSafety :: [WithPriority Edit] -> ([WithPriority Edit], [WithPriority Edit]) Source #

Split the given list of Edits based on their EditSafety setting.

fastApproximateRowCountFor :: TableName -> Pg (Maybe Int64) Source #

Helper query to retrieve the approximate row count from the pg_class table.

Number of live rows in the table. This is only an estimate used by the planner. It is updated by VACUUM, ANALYZE, and a few DDL commands such as CREATE INDEX.

This can be used as a check to see if an otherwise Unsafe EditAction is safe to execute.

See: * PostgreSQL Wiki Count Estimate and * PostgreSQL Manual for @pg_class@ for more information.

Printing migrations for debugging purposes

showMigration :: MonadIO m => Migration m -> m String Source #

Pretty-prints the migration. Useful for debugging and diagnostic.

printMigration :: MonadIO m => Migration m -> m () Source #

Prints the migration to stdout. Useful for debugging and diagnostic.

Unsafe functions

unsafeRunMigration :: (MonadBeam Postgres m, MonadIO m) => Migration m -> m () Source #

Runs the input Migration in a concrete Postgres backend.

IMPORTANT: This function does not run inside a SQL transaction, hence the unsafe prefix.

Handy re-exports

Internals

type FromAnnotated (be :: *) (db :: DatabaseKind) e1 e2 = (Generic (db (e1 be db)), Generic (db (e2 be db)), Database be db, GZipDatabase be (e2 be db) (e2 be db) (e1 be db) (Rep (db (e2 be db))) (Rep (db (e2 be db))) (Rep (db (e1 be db)))) Source #

Simple class to make the signatures for defaultAnnotatedDbSettings and fromAnnotatedDbSettings less scary. From a user's standpoint, there is nothing you have to implement.

type ToAnnotated (be :: *) (db :: DatabaseKind) e1 e2 = (Generic (db (e1 be db)), Generic (db (e2 be db)), Database be db, GZipDatabase be (e1 be db) (e2 be db) (e2 be db) (Rep (db (e1 be db))) (Rep (db (e2 be db))) (Rep (db (e2 be db)))) Source #

Simple synonym to make the signatures for defaultAnnotatedDbSettings and fromAnnotatedDbSettings less scary. From a user's standpoint, there is nothing you have to implement.

sqlEscaped :: Text -> Text Source #

Escape a sql identifier according to the rules defined in the postgres manual