beam-postgres 0.5.4.4 → 0.5.5.0
raw patch · 6 files changed
+150/−8 lines, 6 filesdep ~beam-migratePVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: beam-migrate
API changes (from Hackage documentation)
- Database.Beam.Postgres.Full: instance GHC.Base.Monoid (Database.Beam.Postgres.Full.PgLockedTables s)
- Database.Beam.Postgres.Full: instance GHC.Base.Semigroup (Database.Beam.Postgres.Full.PgLockedTables s)
- Database.Beam.Postgres.Migrate: instance GHC.Generics.Generic Database.Beam.Postgres.Migrate.SchemaName
- Database.Beam.Postgres.Syntax: instance Data.String.IsString (Database.Beam.Query.CustomSQL.CustomSqlSyntax Database.Beam.Postgres.Syntax.PgExpressionSyntax)
- Database.Beam.Postgres.Syntax: instance Data.String.IsString Database.Beam.Postgres.Syntax.PgSyntaxPrim
- Database.Beam.Postgres.Syntax: instance Database.Beam.Backend.SQL.SQL92.HasSqlValueSyntax Database.Beam.Postgres.Syntax.PgValueSyntax GHC.Int.Int16
- Database.Beam.Postgres.Syntax: instance Database.Beam.Backend.SQL.SQL92.HasSqlValueSyntax Database.Beam.Postgres.Syntax.PgValueSyntax GHC.Int.Int32
- Database.Beam.Postgres.Syntax: instance Database.Beam.Backend.SQL.SQL92.HasSqlValueSyntax Database.Beam.Postgres.Syntax.PgValueSyntax GHC.Int.Int64
- Database.Beam.Postgres.Syntax: instance Database.Beam.Backend.SQL.SQL92.HasSqlValueSyntax Database.Beam.Postgres.Syntax.PgValueSyntax GHC.Int.Int8
- Database.Beam.Postgres.Syntax: instance Database.Beam.Backend.SQL.SQL92.HasSqlValueSyntax Database.Beam.Postgres.Syntax.PgValueSyntax GHC.Word.Word16
- Database.Beam.Postgres.Syntax: instance Database.Beam.Backend.SQL.SQL92.HasSqlValueSyntax Database.Beam.Postgres.Syntax.PgValueSyntax GHC.Word.Word32
- Database.Beam.Postgres.Syntax: instance Database.Beam.Backend.SQL.SQL92.HasSqlValueSyntax Database.Beam.Postgres.Syntax.PgValueSyntax GHC.Word.Word64
- Database.Beam.Postgres.Syntax: instance Database.Beam.Backend.SQL.SQL92.HasSqlValueSyntax Database.Beam.Postgres.Syntax.PgValueSyntax GHC.Word.Word8
- Database.Beam.Postgres.Syntax: instance Database.Beam.Backend.SQL.SQL92.HasSqlValueSyntax Database.Beam.Postgres.Syntax.PgValueSyntax x => Database.Beam.Backend.SQL.SQL92.HasSqlValueSyntax Database.Beam.Postgres.Syntax.PgValueSyntax (GHC.Maybe.Maybe x)
- Database.Beam.Postgres.Syntax: instance GHC.Base.Functor Database.Beam.Postgres.Syntax.PgSyntaxF
- Database.Beam.Postgres.Syntax: instance GHC.Base.Monoid (Database.Beam.Query.CustomSQL.CustomSqlSyntax Database.Beam.Postgres.Syntax.PgExpressionSyntax)
- Database.Beam.Postgres.Syntax: instance GHC.Base.Monoid Database.Beam.Postgres.Syntax.PgSyntax
- Database.Beam.Postgres.Syntax: instance GHC.Base.Semigroup (Database.Beam.Query.CustomSQL.CustomSqlSyntax Database.Beam.Postgres.Syntax.PgExpressionSyntax)
- Database.Beam.Postgres.Syntax: instance GHC.Base.Semigroup Database.Beam.Postgres.Syntax.PgSyntax
- Database.Beam.Postgres.Syntax: instance GHC.Enum.Bounded Database.Beam.Postgres.Syntax.PgEscapeType
- Database.Beam.Postgres.Syntax: instance GHC.Enum.Enum Database.Beam.Postgres.Syntax.PgEscapeType
- Database.Beam.Postgres.Syntax: instance GHC.Generics.Generic Database.Beam.Postgres.Syntax.PgDataTypeDescr
- Database.Beam.Postgres.Syntax: instance GHC.Generics.Generic Database.Beam.Postgres.Syntax.PgHasEnum
- Database.Beam.Postgres.Syntax: instance GHC.Generics.Generic Database.Beam.Postgres.Syntax.PgNullOrdering
- Database.Beam.Postgres.Syntax: instance GHC.Generics.Generic Database.Beam.Postgres.Syntax.PgSelectLockingOptions
- Database.Beam.Postgres.Syntax: instance GHC.Generics.Generic Database.Beam.Postgres.Syntax.PgSelectLockingStrength
- Database.Beam.Postgres.Syntax: instance GHC.Show.Show Database.Beam.Postgres.Syntax.PgColumnConstraintDefinitionSyntax
- Database.Beam.Postgres.Syntax: instance GHC.Show.Show Database.Beam.Postgres.Syntax.PgColumnSchemaSyntax
- Database.Beam.Postgres.Syntax: instance GHC.Show.Show Database.Beam.Postgres.Syntax.PgCommandType
- Database.Beam.Postgres.Syntax: instance GHC.Show.Show Database.Beam.Postgres.Syntax.PgDataTypeDescr
- Database.Beam.Postgres.Syntax: instance GHC.Show.Show Database.Beam.Postgres.Syntax.PgDataTypeSyntax
- Database.Beam.Postgres.Syntax: instance GHC.Show.Show Database.Beam.Postgres.Syntax.PgEscapeType
- Database.Beam.Postgres.Syntax: instance GHC.Show.Show Database.Beam.Postgres.Syntax.PgHasEnum
- Database.Beam.Postgres.Syntax: instance GHC.Show.Show Database.Beam.Postgres.Syntax.PgNullOrdering
- Database.Beam.Postgres.Syntax: instance GHC.Show.Show Database.Beam.Postgres.Syntax.PgSelectLockingOptions
- Database.Beam.Postgres.Syntax: instance GHC.Show.Show Database.Beam.Postgres.Syntax.PgSelectLockingStrength
- Database.Beam.Postgres.Syntax: instance GHC.Show.Show Database.Beam.Postgres.Syntax.PgSyntax
- Database.Beam.Postgres.Syntax: instance GHC.Show.Show Database.Beam.Postgres.Syntax.PgSyntaxPrim
+ Database.Beam.Postgres.Full: instance GHC.Internal.Base.Monoid (Database.Beam.Postgres.Full.PgLockedTables s)
+ Database.Beam.Postgres.Full: instance GHC.Internal.Base.Semigroup (Database.Beam.Postgres.Full.PgLockedTables s)
+ Database.Beam.Postgres.Migrate: instance GHC.Internal.Generics.Generic Database.Beam.Postgres.Migrate.SchemaName
+ Database.Beam.Postgres.Syntax: PgIndexOptions :: Bool -> PgIndexOptions
+ Database.Beam.Postgres.Syntax: [pgIndexUnique] :: PgIndexOptions -> Bool
+ Database.Beam.Postgres.Syntax: instance Data.Hashable.Class.Hashable Database.Beam.Postgres.Syntax.PgIndexOptions
+ Database.Beam.Postgres.Syntax: instance Database.Beam.Backend.SQL.SQL92.HasSqlValueSyntax Database.Beam.Postgres.Syntax.PgValueSyntax GHC.Internal.Int.Int16
+ Database.Beam.Postgres.Syntax: instance Database.Beam.Backend.SQL.SQL92.HasSqlValueSyntax Database.Beam.Postgres.Syntax.PgValueSyntax GHC.Internal.Int.Int32
+ Database.Beam.Postgres.Syntax: instance Database.Beam.Backend.SQL.SQL92.HasSqlValueSyntax Database.Beam.Postgres.Syntax.PgValueSyntax GHC.Internal.Int.Int64
+ Database.Beam.Postgres.Syntax: instance Database.Beam.Backend.SQL.SQL92.HasSqlValueSyntax Database.Beam.Postgres.Syntax.PgValueSyntax GHC.Internal.Int.Int8
+ Database.Beam.Postgres.Syntax: instance Database.Beam.Backend.SQL.SQL92.HasSqlValueSyntax Database.Beam.Postgres.Syntax.PgValueSyntax GHC.Internal.Word.Word16
+ Database.Beam.Postgres.Syntax: instance Database.Beam.Backend.SQL.SQL92.HasSqlValueSyntax Database.Beam.Postgres.Syntax.PgValueSyntax GHC.Internal.Word.Word32
+ Database.Beam.Postgres.Syntax: instance Database.Beam.Backend.SQL.SQL92.HasSqlValueSyntax Database.Beam.Postgres.Syntax.PgValueSyntax GHC.Internal.Word.Word64
+ Database.Beam.Postgres.Syntax: instance Database.Beam.Backend.SQL.SQL92.HasSqlValueSyntax Database.Beam.Postgres.Syntax.PgValueSyntax GHC.Internal.Word.Word8
+ Database.Beam.Postgres.Syntax: instance Database.Beam.Backend.SQL.SQL92.HasSqlValueSyntax Database.Beam.Postgres.Syntax.PgValueSyntax x => Database.Beam.Backend.SQL.SQL92.HasSqlValueSyntax Database.Beam.Postgres.Syntax.PgValueSyntax (GHC.Internal.Maybe.Maybe x)
+ Database.Beam.Postgres.Syntax: instance Database.Beam.Migrate.SQL.SQL92.IsSql92CreateDropIndexSyntax Database.Beam.Postgres.Syntax.PgCommandSyntax
+ Database.Beam.Postgres.Syntax: instance Database.Beam.Migrate.SQL.SQL92.IsSql92UniqueIndexSyntax Database.Beam.Postgres.Syntax.PgCommandSyntax
+ Database.Beam.Postgres.Syntax: instance GHC.Classes.Eq Database.Beam.Postgres.Syntax.PgIndexOptions
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Base.Functor Database.Beam.Postgres.Syntax.PgSyntaxF
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Base.Monoid (Database.Beam.Query.CustomSQL.CustomSqlSyntax Database.Beam.Postgres.Syntax.PgExpressionSyntax)
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Base.Monoid Database.Beam.Postgres.Syntax.PgSyntax
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Base.Semigroup (Database.Beam.Query.CustomSQL.CustomSqlSyntax Database.Beam.Postgres.Syntax.PgExpressionSyntax)
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Base.Semigroup Database.Beam.Postgres.Syntax.PgSyntax
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Data.String.IsString (Database.Beam.Query.CustomSQL.CustomSqlSyntax Database.Beam.Postgres.Syntax.PgExpressionSyntax)
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Data.String.IsString Database.Beam.Postgres.Syntax.PgSyntaxPrim
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Enum.Bounded Database.Beam.Postgres.Syntax.PgEscapeType
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Enum.Enum Database.Beam.Postgres.Syntax.PgEscapeType
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Generics.Generic Database.Beam.Postgres.Syntax.PgDataTypeDescr
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Generics.Generic Database.Beam.Postgres.Syntax.PgHasEnum
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Generics.Generic Database.Beam.Postgres.Syntax.PgNullOrdering
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Generics.Generic Database.Beam.Postgres.Syntax.PgSelectLockingOptions
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Generics.Generic Database.Beam.Postgres.Syntax.PgSelectLockingStrength
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Show.Show Database.Beam.Postgres.Syntax.PgColumnConstraintDefinitionSyntax
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Show.Show Database.Beam.Postgres.Syntax.PgColumnSchemaSyntax
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Show.Show Database.Beam.Postgres.Syntax.PgCommandType
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Show.Show Database.Beam.Postgres.Syntax.PgDataTypeDescr
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Show.Show Database.Beam.Postgres.Syntax.PgDataTypeSyntax
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Show.Show Database.Beam.Postgres.Syntax.PgEscapeType
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Show.Show Database.Beam.Postgres.Syntax.PgHasEnum
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Show.Show Database.Beam.Postgres.Syntax.PgIndexOptions
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Show.Show Database.Beam.Postgres.Syntax.PgNullOrdering
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Show.Show Database.Beam.Postgres.Syntax.PgSelectLockingOptions
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Show.Show Database.Beam.Postgres.Syntax.PgSelectLockingStrength
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Show.Show Database.Beam.Postgres.Syntax.PgSyntax
+ Database.Beam.Postgres.Syntax: instance GHC.Internal.Show.Show Database.Beam.Postgres.Syntax.PgSyntaxPrim
+ Database.Beam.Postgres.Syntax: newtype PgIndexOptions
Files
- ChangeLog.md +9/−0
- Database/Beam/Postgres/CustomTypes.hs +0/−3
- Database/Beam/Postgres/Migrate.hs +50/−2
- Database/Beam/Postgres/Syntax.hs +34/−1
- beam-postgres.cabal +2/−2
- test/Database/Beam/Postgres/Test/Migrate.hs +55/−0
ChangeLog.md view
@@ -1,3 +1,12 @@+# 0.5.5.0++## Added features++* Add support for creating secondary indices, supporting both `CREATE INDEX` and+ `CREATE UNIQUE INDEX`. `getDbConstraintsForSchemas` now discovers user-created+ secondary indices via `pg_index` (excluding primary keys and+ constraint-backing indices).+ # 0.5.4.4 ## Added features
Database/Beam/Postgres/CustomTypes.hs view
@@ -40,9 +40,6 @@ import Data.Functor.Const import qualified Data.HashSet as HS import Data.Proxy (Proxy(..))-#if !MIN_VERSION_base(4,11,0)-import Data.Semigroup-#endif import Data.Text (Text) import qualified Data.Text.Encoding as TE
Database/Beam/Postgres/Migrate.hs view
@@ -31,7 +31,8 @@ ) where import Database.Beam.Backend.SQL-import Database.Beam.Migrate.Actions (defaultActionProvider, defaultSchemaActionProvider)+import Database.Beam.Migrate.Actions (defaultActionProvider, defaultSchemaActionProvider,+ createIndexActionProvider, dropIndexActionProvider) import qualified Database.Beam.Migrate.Backend as Tool import qualified Database.Beam.Migrate.Checks as Db import qualified Database.Beam.Migrate.SQL as Db@@ -65,6 +66,7 @@ import qualified Data.ByteString.Lazy.Char8 as BCL import qualified Data.HashMap.Strict as HM import Data.Int+import qualified Data.List.NonEmpty as NE (nonEmpty) import Data.Maybe import Data.String import qualified Data.Text as T@@ -102,6 +104,8 @@ , Tool.backendActionProvider = mconcat [ defaultActionProvider , defaultSchemaActionProvider+ , createIndexActionProvider+ , dropIndexActionProvider , pgExtensionActionProvider , pgCustomEnumActionProvider ]@@ -402,6 +406,50 @@ -- Recall that schema of the form 'pg_' are Postgres internal tables that should not be taken into account , "WHERE nspname NOT LIKE '%pg_%' AND c.relkind='r' AND i.indisprimary GROUP BY nspname, relname, i.indrelid" ])) + -- Collect user-created secondary indices.+ --+ -- Excludes:+ -- - primary keys+ -- - indices that back a constraint (i.e. those created implicitly by UNIQUE/EXCLUDE)+ -- - expression indices e.g. CREATE INDEX ON users (LOWER(email))+ secondaryIndices <-+ mapMaybe (\(schema, tblNm, idxNm, isUniq, cols) ->+ case NE.nonEmpty (V.toList cols) of+ Nothing -> Nothing+ Just colsNE ->+ let opts = Db.setUniqueIndexOptions @(BeamSqlBackendSyntax Postgres) isUniq+ $ Db.defaultIndexOptions @(BeamSqlBackendSyntax Postgres)+ in+ Just $+ Db.SomeDatabasePredicate @(Db.TableHasIndex Postgres)+ (Db.TableHasIndex (Db.QualifiedName schema tblNm) idxNm colsNE opts)) <$>+ Pg.query_ conn (fromString (unlines+ [ -- NULL out 'public' since it is the implicit default schema in Postgres+ "SELECT NULLIF(ns.nspname, 'public'), c.relname, i.relname, ix.indisunique,"+ -- re-aggregate column names in index-key order (see ORDINALITY below)+ , " array_agg(a.attname ORDER BY k.n ASC)"+ , "FROM pg_index ix"+ , "JOIN pg_class c ON c.oid = ix.indrelid"+ , "JOIN pg_class i ON i.oid = ix.indexrelid"+ , "JOIN pg_namespace ns ON ns.oid = c.relnamespace"+ -- ORDINALITY allows retaining ordering of index columns+ , "CROSS JOIN unnest(ix.indkey) WITH ORDINALITY k(attid, n)"+ , "JOIN pg_attribute a ON a.attnum = k.attid AND a.attrelid = ix.indrelid"+ -- only regular tables (not views, sequences, etc.)+ , "WHERE c.relkind = 'r'"+ -- exclude Postgres system schemas+ , " AND ns.nspname NOT LIKE 'pg_%'"+ , " AND ns.nspname != 'information_schema'"+ -- exclude primary key indices+ , " AND NOT ix.indisprimary"+ -- exclude indices created implicitly by a UNIQUE or EXCLUDE constraint+ , " AND NOT EXISTS (SELECT 1 FROM pg_constraint con WHERE con.conindid = ix.indexrelid)"+ -- exclude expression indices: a key column number of 0 means that+ -- position is an expression (e.g. lower(col)) rather than a plain+ -- column reference, which TableHasIndex cannot represent+ , " AND NOT EXISTS (SELECT 1 FROM unnest(ix.indkey) AS k(attnum) WHERE k.attnum = 0)"+ , "GROUP BY ns.nspname, c.relname, i.relname, ix.indisunique" ]))+ let enumerations = map (\(enumNm, _, options) -> Db.SomeDatabasePredicate (PgHasEnum enumNm (V.toList options))) enumerationData @@ -409,7 +457,7 @@ map (\(Pg.Only extname) -> Db.SomeDatabasePredicate (PgHasExtension extname)) <$> Pg.query_ conn "SELECT extname from pg_extension" - pure (tblsExist ++ columnChecks ++ primaryKeys ++ enumerations ++ extensions)+ pure (tblsExist ++ columnChecks ++ primaryKeys ++ secondaryIndices ++ enumerations ++ extensions) -- * Postgres-specific data types
Database/Beam/Postgres/Syntax.hs view
@@ -46,6 +46,7 @@ , PgAlterTableSyntax(..), PgAlterTableActionSyntax(..), PgAlterColumnActionSyntax(..) + , PgWindowFrameSyntax(..), PgWindowFrameBoundsSyntax(..), PgWindowFrameBoundSyntax(..) , PgSelectLockingClauseSyntax(..)@@ -58,6 +59,8 @@ , PgDataTypeDescr(..) , PgHasEnum(..) + , PgIndexOptions(..)+ , pgCreateExtensionSyntax, pgDropExtensionSyntax , pgCreateEnumSyntax, pgDropTypeSyntax @@ -97,7 +100,7 @@ import Control.Monad.Free import Control.Monad.Free.Church -import Data.Aeson (Value, object, (.=))+import Data.Aeson (Value, object, withObject, (.=), (.:)) import Data.Bits import Data.ByteString (ByteString) import Data.ByteString.Builder (Builder, doubleDec, floatDec, byteString, char8, toLazyByteString)@@ -110,6 +113,7 @@ import Data.Functor.Classes import Data.Hashable import Data.Int+import qualified Data.List.NonEmpty as NE (toList) import Data.Maybe import Data.Scientific (Scientific) import Data.String (IsString(..), fromString)@@ -426,6 +430,35 @@ createTableCmd = PgCommandSyntax PgCommandTypeDdl . coerce dropTableCmd = PgCommandSyntax PgCommandTypeDdl . coerce alterTableCmd = PgCommandSyntax PgCommandTypeDdl . coerce++newtype PgIndexOptions = PgIndexOptions { pgIndexUnique :: Bool }+ deriving (Show, Eq, Hashable)++instance IsSql92CreateDropIndexSyntax PgCommandSyntax where+ type instance Sql92CreateIndexOptionsSyntax PgCommandSyntax = PgIndexOptions++ defaultIndexOptions = PgIndexOptions { pgIndexUnique = False }++ createIndexCmd idxNm tblNm cols opts =+ PgCommandSyntax PgCommandTypeDdl $+ emit (if pgIndexUnique opts then "CREATE UNIQUE INDEX " else "CREATE INDEX ") <>+ pgQuotedIdentifier idxNm <>+ emit " ON " <> fromPgTableName tblNm <>+ pgParens (pgSepBy (emit ", ") (NE.toList $ fmap pgQuotedIdentifier cols))++ dropIndexCmd idxNm =+ PgCommandSyntax PgCommandTypeDdl (emit "DROP INDEX " <> pgQuotedIdentifier idxNm)++ serializeIndexOptions opts =+ object ["unique" .= pgIndexUnique opts]++ deserializeIndexOptions =+ withObject "PgIndexOptions" $ \v ->+ PgIndexOptions <$> v .: "unique"++instance IsSql92UniqueIndexSyntax PgCommandSyntax where+ setUniqueIndexOptions u opts = opts { pgIndexUnique = u }+ indexIsUnique opts = pgIndexUnique opts instance IsSql92SchemaNameSyntax PgSchemaNameSyntax where schemaName s = PgSchemaNameSyntax (pgQuotedIdentifier s)
beam-postgres.cabal view
@@ -1,5 +1,5 @@ name: beam-postgres-version: 0.5.4.4+version: 0.5.5.0 synopsis: Connection layer between beam and postgres description: Beam driver for <https://www.postgresql.org/ PostgreSQL>, an advanced open-source RDBMS homepage: https://haskell-beam.github.io/beam/user-guide/backends/beam-postgres@@ -34,7 +34,7 @@ build-depends: base >=4.11 && <5.0, beam-core >=0.10 && <0.11,- beam-migrate >=0.5 && <0.6,+ beam-migrate >=0.5.4.0 && <0.6, postgresql-libpq >=0.8 && <0.12, postgresql-simple >=0.5 && <0.8,
test/Database/Beam/Postgres/Test/Migrate.hs view
@@ -10,8 +10,12 @@ import Database.Beam.Migrate.Simple import Data.ByteString (ByteString)+import Data.Int (Int32)+import qualified Data.List.NonEmpty as NE import Data.Text (Text) +import qualified Database.PostgreSQL.Simple as Pg+ import Test.Tasty import Test.Tasty.HUnit @@ -25,6 +29,8 @@ , extensionVerification postgresConn , createTableWithSchemaWorks postgresConn , dropSchemaWorks postgresConn+ , indexVerification postgresConn+ , uniqueIndexVerification postgresConn ] data CharT f@@ -137,3 +143,52 @@ verifySchema migrationBackend db >>= \case VerificationFailed failures -> fail ("Verification failed: " ++ show failures) VerificationSucceeded -> pure ()++-- Shared table type for index tests++newtype IdxT f = IdxT+ { _idx_value :: C f Int32+ } deriving (Generic, Beamable)++instance Table IdxT where+ newtype PrimaryKey IdxT f = IdxPk (C f Int32)+ deriving (Generic, Beamable)+ primaryKey = IdxPk . _idx_value++data IdxDb entity = IdxDb+ { _idx_tbl :: entity (TableEntity IdxT)+ } deriving (Generic, Database Postgres)++-- | Verifies that 'verifySchema' correctly detects a secondary index+indexVerification :: IO ByteString -> TestTree+indexVerification pgConn =+ testCase "verifySchema correctly detects a secondary index" $+ withTestPostgres "db_index" pgConn $ \conn -> do+ Pg.execute_ conn "CREATE TABLE idx_tbl (idx_value integer NOT NULL PRIMARY KEY)"+ Pg.execute_ conn "CREATE INDEX idx_tbl_value ON idx_tbl (idx_value)"+ let db :: CheckedDatabaseSettings Postgres IdxDb+ db = defaultMigratableDbSettings `withDbModification`+ (dbModification @_ @Postgres)+ { _idx_tbl = addTableIndex "idx_tbl_value" (defaultIndexOptions @PgCommandSyntax)+ (\t -> selectorColumnName _idx_value t NE.:| []) }+ runBeamPostgres conn (verifySchema migrationBackend db) >>= \case+ VerificationSucceeded -> return ()+ VerificationFailed failures -> fail ("Verification failed: " ++ show failures)++-- | Verifies that 'verifySchema' correctly detects a UNIQUE secondary index+uniqueIndexVerification :: IO ByteString -> TestTree+uniqueIndexVerification pgConn =+ testCase "verifySchema correctly detects a UNIQUE secondary index" $+ withTestPostgres "db_unique_index" pgConn $ \conn -> do+ Pg.execute_ conn "CREATE TABLE idx_tbl (idx_value integer NOT NULL PRIMARY KEY)"+ Pg.execute_ conn "CREATE UNIQUE INDEX idx_tbl_value_uniq ON idx_tbl (idx_value)"+ let idxOpts = setUniqueIndexOptions @PgCommandSyntax True+ $ defaultIndexOptions @PgCommandSyntax+ db :: CheckedDatabaseSettings Postgres IdxDb+ db = defaultMigratableDbSettings `withDbModification`+ (dbModification @_ @Postgres)+ { _idx_tbl = addTableIndex "idx_tbl_value_uniq" idxOpts+ (\t -> selectorColumnName _idx_value t NE.:| []) }+ runBeamPostgres conn (verifySchema migrationBackend db) >>= \case+ VerificationSucceeded -> return ()+ VerificationFailed failures -> fail ("Verification failed: " ++ show failures)