packages feed

beam-postgres 0.5.4.2 → 0.5.4.3

raw patch · 10 files changed

+193/−131 lines, 10 filesdep −haskell-src-extsdep ~basedep ~timePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies removed: haskell-src-exts

Dependency ranges changed: base, time

API changes (from Hackage documentation)

- 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: 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 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.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.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.Full: pgSelectWith :: forall (db :: (Type -> Type) -> Type) s res. Projectible Postgres res => With Postgres db (Q Postgres db s res) -> Q Postgres db s res
+ 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

Files

ChangeLog.md view
@@ -1,3 +1,14 @@+# 0.5.4.3++## Added features++ * Added `pgSelectWith`, a combinator like `selectWith` which allows to nest common table expressions in subqueries (#720).++## Bug fixes++ * Added the ability to migrate Postgres' array types (#354).+ * Remove dependency on `haskell-src-exts`, which was not in use anymore.+ # 0.5.4.2  ## Bug fixes@@ -18,7 +29,7 @@  * Added support for creating and dropping database schemas and associated tables with `createDatabaseSchema`, `dropDatabaseSchema`, and `createTableWithSchema` (#716).  ## Documentation- +  * Make `runBeamPostgres` and `runBeamPostgresDebug` easier to find (#663).  # 0.5.3.1
Database/Beam/Postgres/Conduit.hs view
@@ -48,9 +48,6 @@ import qualified Conduit as C import           Data.Int (Int64) import           Data.Maybe (fromMaybe)-#if !MIN_VERSION_base(4, 11, 0)-import           Data.Semigroup-#endif  import qualified Control.Monad.Fail as Fail 
Database/Beam/Postgres/Connection.hs view
@@ -67,9 +67,6 @@ import qualified Data.Text as T import           Data.Text.Encoding (decodeUtf8) import           Data.Typeable (cast)-#if !MIN_VERSION_base(4, 11, 0)-import           Data.Semigroup-#endif  import           Foreign.C.Types @@ -155,13 +152,13 @@                             Pg.ConversionFailed { Pg.errSQLType = sql                                                 , Pg.errHaskellType = hs                                                 , Pg.errMessage = msg-                                                , Pg.errSQLField = field } ->-                              pure (ColumnTypeMismatch hs sql ("Conversion failed for field'" <> field <> "': " <> msg))+                                                , Pg.errSQLField = errField } ->+                              pure (ColumnTypeMismatch hs sql ("Conversion failed for field'" <> errField <> "': " <> msg))                             Pg.Incompatible { Pg.errSQLType = sql                                             , Pg.errHaskellType = hs                                             , Pg.errMessage = msg-                                            , Pg.errSQLField = field } ->-                              pure (ColumnTypeMismatch hs sql ("Incompatible field: '" <> field <> "': " <> msg))+                                            , Pg.errSQLField = errField } ->+                              pure (ColumnTypeMismatch hs sql ("Incompatible field: '" <> errField <> "': " <> msg))                             Pg.UnexpectedNull {} ->                               pure ColumnUnexpectedNull              in pure (Left (BeamRowReadError (Just (fromIntegral curCol)) err))
Database/Beam/Postgres/Extensions.hs view
@@ -27,9 +27,6 @@ import           Data.Hashable (Hashable) import           Data.Proxy import           Data.Text (Text)-#if !MIN_VERSION_base(4, 11, 0)-import           Data.Semigroup-#endif  -- *** Embedding extensions in databases 
Database/Beam/Postgres/Full.hs view
@@ -20,6 +20,9 @@    , locked_, lockAll_, withLocks_ +  -- ** Inner WITH queries+  , pgSelectWith+   -- ** Lateral joins   , lateral_ @@ -55,22 +58,22 @@   ) where  import           Database.Beam hiding (insert, insertValues)-import           Database.Beam.Query.Internal import           Database.Beam.Backend.SQL import           Database.Beam.Backend.SQL.BeamExtensions+import qualified Database.Beam.Query.CTE as CTE+import           Database.Beam.Query.Internal import           Database.Beam.Schema.Tables  import           Database.Beam.Postgres.Types import           Database.Beam.Postgres.Syntax  import           Control.Monad.Free.Church+import           Control.Monad.State.Strict (evalState)+import           Control.Monad.Writer (runWriterT)  import           Data.Kind (Type) import           Data.Proxy (Proxy(..)) import qualified Data.Text as T-#if !MIN_VERSION_base(4, 11, 0)-import           Data.Semigroup-#endif  -- * @SELECT@ @@ -273,6 +276,41 @@                                   fromPgFrom a <> emit " JOIN LATERAL " <> fromPgFrom b <> emit " ON " <> fromPgExpression on'')                            (\_ -> Nothing)                            (rewriteThread (Proxy @s))))++-- | The SQL standard only allows CTE expressions (WITH expressions)+-- at the top-level. Postgres allows you to embed these within a+-- subquery.+--+-- For example,+--+-- @+-- SELECT a.column1, b.column2 FROM (WITH RECURSIVE ... ) a JOIN b+-- @+--+-- @beam-core@ offers 'selectWith' to produce a top-level 'SqlSelect'+-- but these cannot be turned into 'Q' objects for use within joins.+--+-- The 'pgSelectWith' function is more flexible and indeed+-- 'selectWith' for @beam-postgres@ is equivalent to se+pgSelectWith :: forall db s res+              . Projectible Postgres res+             => With Postgres db (Q Postgres db s res) -> Q Postgres db s res+pgSelectWith (CTE.With mkQ) =+    let (q, (recursiveness, ctes)) = evalState (runWriterT mkQ) 0+        fromSyntax tblPfx =+            case recursiveness of+              CTE.Nonrecursive -> withSyntax ctes (buildSqlQuery tblPfx q)+              CTE.Recursive -> withRecursiveSyntax ctes (buildSqlQuery tblPfx q)+    in Q (liftF (QAll (\tblPfx tName ->+                           let (_, names) = mkFieldNames @Postgres @res (qualifiedField tName)+                           in fromTable (PgTableSourceSyntax $+                                         mconcat [ emit "(", fromPgSelect (fromSyntax tblPfx), emit ")" ])+                                        (Just (tName, Just names)))+                      (\tName ->+                           let (projection, _) = mkFieldNames @Postgres @res (qualifiedField tName)+                           in projection)+                      (\_ -> Nothing)+                      snd))  -- | By default, Postgres will throw an error when a conflict is detected. This -- preserves that functionality.
Database/Beam/Postgres/Migrate.hs view
@@ -55,7 +55,7 @@  import           Control.Applicative ((<|>)) import           Control.Arrow-import           Control.Exception (bracket)+import           Control.Exception.Lifted (mask, onException) import           Control.Monad  import           Data.Aeson hiding (json)@@ -72,11 +72,7 @@ import           Data.Typeable import           Data.UUID.Types (UUID) import qualified Data.Vector as V-#if !MIN_VERSION_base(4, 11, 0) import           Data.Semigroup-#else-import           Data.Monoid (Endo(..))-#endif import           Data.Word (Word64)  import           GHC.Generics ( Generic )@@ -84,30 +80,46 @@ -- | Top-level migration backend for use by @beam-migrate@ tools migrationBackend :: Tool.BeamMigrationBackend Postgres Pg migrationBackend = Tool.BeamMigrationBackend-                        "postgres"-                        (unlines [ "For beam-postgres, this is a libpq connection string which can either be a list of key value pairs or a URI"-                                 , ""-                                 , "For example, 'host=localhost port=5432 dbname=mydb connect_timeout=10' or 'dbname=mydb'"-                                 , ""-                                 , "Or use URIs, for which the general form is:"-                                 , "  postgresql://[user[:password]@][netloc][:port][/dbname][?param1=value1&...]"-                                 , ""-                                 , "See <https://www.postgresql.org/docs/9.5/static/libpq-connect.html#LIBPQ-CONNSTRING> for more information" ])-                        (liftIOWithHandle getDbConstraints)-                        (Db.sql92Deserializers <> Db.sql99DataTypeDeserializers <>-                         Db.sql2008BigIntDataTypeDeserializers <>-                         postgresDataTypeDeserializers <>-                         Db.beamCheckDeserializers)-                        (BCL.unpack . (<> ";") . pgRenderSyntaxScript . fromPgCommand) "postgres.sql"-                        pgPredConverter (mconcat [ defaultActionProvider-                                                 , defaultSchemaActionProvider-                                                 , pgExtensionActionProvider-                                                 , pgCustomEnumActionProvider-                                                 ]-                                        )-                        (\options action ->-                            bracket (Pg.connectPostgreSQL (fromString options)) Pg.close $ \conn ->-                              left show <$> withPgDebug (\_ -> pure ()) conn action)+                   { Tool.backendName = "postgres"+                   , Tool.backendConnStringExplanation =+                       unlines [ "For beam-postgres, this is a libpq connection string which can either be a list of key value pairs or a URI"+                               , ""+                               , "For example, 'host=localhost port=5432 dbname=mydb connect_timeout=10' or 'dbname=mydb'"+                               , ""+                               , "Or use URIs, for which the general form is:"+                               , "  postgresql://[user[:password]@][netloc][:port][/dbname][?param1=value1&...]"+                               , ""+                               , "See <https://www.postgresql.org/docs/9.5/static/libpq-connect.html#LIBPQ-CONNSTRING> for more information" ]+                   , Tool.backendGetDbConstraints = liftIOWithHandle getDbConstraints+                   , Tool.backendPredicateParsers =+                       Db.sql92Deserializers <> Db.sql99DataTypeDeserializers <>+                       Db.sql2008BigIntDataTypeDeserializers <>+                       postgresDataTypeDeserializers <>+                       Db.beamCheckDeserializers+                   , Tool.backendRenderSyntax = (BCL.unpack . (<> ";") . pgRenderSyntaxScript . fromPgCommand)+                   , Tool.backendFileExtension = "postgres.sql"+                   , Tool.backendConvertToHaskell = pgPredConverter+                   , Tool.backendActionProvider =+                       mconcat [ defaultActionProvider+                               , defaultSchemaActionProvider+                               , pgExtensionActionProvider+                               , pgCustomEnumActionProvider+                               ]+                   , Tool.backendRunSqlScript = \t -> liftIOWithHandle (\hdl -> void $ Pg.execute_ hdl (Pg.Query (TE.encodeUtf8 t)))+                   , Tool.backendWithTransaction =+                       \go -> mask $ \unmask -> do+                                liftIOWithHandle Pg.begin+                                x <- unmask go `onException` liftIOWithHandle Pg.rollback+                                liftIOWithHandle Pg.commit+                                pure x+                   , Tool.backendConnect = \options -> do+                        conn <- Pg.connectPostgreSQL (fromString options)+                        pure Tool.BeamMigrateConnection+                             { Tool.backendRun = \action ->+                                 left show <$> withPgDebug (\_ -> pure ()) conn action+                             , Tool.backendClose = Pg.close conn+                             }+                   }  -- | 'BeamDeserializers' for postgres-specific types: --
Database/Beam/Postgres/PgSpecific.hs view
@@ -150,9 +150,6 @@ import           Data.Time (LocalTime, NominalDiffTime) import           Data.Type.Bool import qualified Data.Vector as V-#if !MIN_VERSION_base(4, 11, 0)-import           Data.Semigroup-#endif  import qualified Database.PostgreSQL.Simple.FromField as Pg import qualified Database.PostgreSQL.Simple.ToField as Pg
Database/Beam/Postgres/Syntax.hs view
@@ -111,9 +111,6 @@ import           Data.Hashable import           Data.Int import           Data.Maybe-#if !MIN_VERSION_base(4, 11, 0)-import           Data.Semigroup-#endif import           Data.Scientific (Scientific) import           Data.String (IsString(..), fromString) import qualified Data.Text as T@@ -580,8 +577,8 @@   binaryLargeObjectType = pgByteaType { pgDataTypeSerialized = binaryLargeObjectType }   booleanType = PgDataTypeSyntax (PgDataTypeDescrOid (Pg.typoid Pg.bool) Nothing) (emit "BOOLEAN")                                  booleanType-  arrayType (PgDataTypeSyntax _ syntax serialized) sz =-    PgDataTypeSyntax (error "TODO: array migrations")+  arrayType (PgDataTypeSyntax descr syntax serialized) sz =+    PgDataTypeSyntax (PgDataTypeDescrOid (fromMaybe (error "Unsupported array type") (arrayTypeDescr descr)) Nothing)                      (syntax <> emit "[" <> emit (fromString (show sz)) <> emit "]")                      (arrayType serialized sz)   rowType = error "rowType"@@ -647,11 +644,72 @@ pgLineSegmentType = PgDataTypeSyntax (PgDataTypeDescrOid (Pg.typoid Pg.lseg) Nothing) (emit "LSEG") (pgDataTypeJSON "lseg") pgBoxType = PgDataTypeSyntax (PgDataTypeDescrOid (Pg.typoid Pg.box) Nothing) (emit "BOX") (pgDataTypeJSON "box") +-- TODO: better mechanism to tell, at compile time, that some type+-- cannot be placed in an array pgUnboundedArrayType :: PgDataTypeSyntax -> PgDataTypeSyntax-pgUnboundedArrayType (PgDataTypeSyntax _ syntax serialized) =-    PgDataTypeSyntax (error "Can't do array migrations yet")+pgUnboundedArrayType (PgDataTypeSyntax descr syntax serialized) =+    PgDataTypeSyntax (PgDataTypeDescrOid (fromMaybe (error "Unsupported array type") (arrayTypeDescr descr)) Nothing)                      (syntax <> emit "[]")                      (pgDataTypeJSON (object [ "unbounded-array" .= fromBeamSerializedDataType serialized ]))++-- TODO: define CPP macro to make sure the left hand side (e.g. `Pg.recordOid`) +--       always matches right hand side (e.g. `Pg.array_recordOid)++-- | Get the Oid of Pg arrays which contains elements of a certain type+arrayTypeDescr :: PgDataTypeDescr -> Maybe Pg.Oid+arrayTypeDescr (PgDataTypeDescrDomain _) = Nothing+arrayTypeDescr (PgDataTypeDescrOid elemOid _)+  | elemOid == Pg.recordOid    = Just $ Pg.array_recordOid+  | elemOid == Pg.xmlOid    = Just $ Pg.array_xmlOid+  | elemOid == Pg.jsonOid   = Just $ Pg.array_jsonOid+  | elemOid == Pg.lineOid   = Just $ Pg.array_lineOid+  | elemOid == Pg.cidrOid   = Just $ Pg.array_cidOid+  | elemOid == Pg.circleOid = Just $ Pg.array_circleOid+  | elemOid == Pg.moneyOid  = Just $ Pg.array_moneyOid+  | elemOid == Pg.boolOid   = Just $ Pg.array_boolOid+  | elemOid == Pg.byteaOid  = Just $ Pg.array_byteaOid+  | elemOid == Pg.charOid   = Just $ Pg.array_charOid+  | elemOid == Pg.nameOid   = Just $ Pg.array_nameOid+  | elemOid == Pg.int2Oid   = Just $ Pg.array_int2Oid+  | elemOid == Pg.int2vectorOid = Just $ Pg.array_int2vectorOid+  | elemOid == Pg.int4Oid   = Just $ Pg.array_int4Oid+  | elemOid == Pg.regprocOid = Just $ Pg.array_regprocOid+  | elemOid == Pg.textOid   = Just $ Pg.array_textOid+  | elemOid == Pg.tidOid   = Just $ Pg.array_tidOid+  | elemOid == Pg.xidOid   = Just $ Pg.array_xidOid+  | elemOid == Pg.cidOid   = Just $ Pg.array_cidOid+  | elemOid == Pg.bpcharOid = Just $ Pg.array_bpcharOid+  | elemOid == Pg.varcharOid = Just $ Pg.array_varcharOid+  | elemOid == Pg.int8Oid = Just $ Pg.array_int8Oid+  | elemOid == Pg.pointOid = Just $ Pg.array_pointOid+  | elemOid == Pg.lsegOid = Just $ Pg.array_lsegOid+  | elemOid == Pg.pathOid = Just $ Pg.array_pathOid+  | elemOid == Pg.boxOid = Just $ Pg.array_boxOid+  | elemOid == Pg.float4Oid = Just $ Pg.array_float4Oid+  | elemOid == Pg.float8Oid = Just $ Pg.array_float8Oid+  | elemOid == Pg.polygonOid = Just $ Pg.array_polygonOid+  | elemOid == Pg.oidOid = Just $ Pg.array_oidOid+  | elemOid == Pg.macaddrOid = Just $ Pg.array_macaddrOid+  | elemOid == Pg.inetOid = Just $ Pg.array_inetOid+  | elemOid == Pg.timestampOid = Just $ Pg.array_timestampOid+  | elemOid == Pg.dateOid = Just $ Pg.array_dateOid+  | elemOid == Pg.timeOid = Just $ Pg.array_timeOid+  | elemOid == Pg.timestamptzOid = Just $ Pg.array_timestamptzOid+  | elemOid == Pg.intervalOid = Just $ Pg.array_intervalOid+  | elemOid == Pg.numericOid = Just $ Pg.array_numericOid+  | elemOid == Pg.timetzOid = Just $ Pg.array_timetzOid+  | elemOid == Pg.bitOid = Just $ Pg.array_bitOid+  | elemOid == Pg.varbitOid = Just $ Pg.array_varbitOid+  | elemOid == Pg.refcursorOid = Just $ Pg.array_refcursorOid+  | elemOid == Pg.regprocedureOid = Just $ Pg.array_regprocedureOid+  | elemOid == Pg.regoperOid = Just $ Pg.array_regoperOid+  | elemOid == Pg.regoperatorOid = Just $ Pg.array_regoperatorOid+  | elemOid == Pg.regclassOid = Just $ Pg.array_regclassOid+  | elemOid == Pg.regtypeOid = Just $ Pg.array_regtypeOid+  | elemOid == Pg.uuidOid = Just $ Pg.array_uuidOid+  | elemOid == Pg.jsonbOid = Just $ Pg.array_jsonbOid+  | otherwise = Nothing+  pgTsQueryTypeInfo :: Pg.TypeInfo pgTsQueryTypeInfo = Pg.Basic (Pg.Oid 3615) 'U' ',' "tsquery"
beam-postgres.cabal view
@@ -1,5 +1,5 @@ name:                 beam-postgres-version:              0.5.4.2+version:              0.5.4.3 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@@ -32,7 +32,7 @@                       Database.Beam.Postgres.PgSpecific                       Database.Beam.Postgres.Types -  build-depends:      base                 >=4.9  && <5.0,+  build-depends:      base                 >=4.11 && <5.0,                       beam-core            >=0.10 && <0.11,                       beam-migrate         >=0.5  && <0.6, @@ -58,14 +58,18 @@                       network-uri          >=2.6  && <2.7,                       unordered-containers >= 0.2 && <0.3,                       tagged               >=0.8  && <0.9,-                      transformers-base    >=0.4  && <0.5,+                      transformers-base    >=0.4  && <0.5 -                      haskell-src-exts     >=1.18 && <1.24   default-language:   Haskell2010   default-extensions: ScopedTypeVariables, OverloadedStrings, MultiParamTypeClasses, RankNTypes, FlexibleInstances,                       DeriveDataTypeable, DeriveGeneric, StandaloneDeriving, TypeFamilies, GADTs, OverloadedStrings,                       CPP, TypeApplications, FlexibleContexts   ghc-options:        -Wall+                      -Widentities+                      -Wincomplete-uni-patterns+                      -Wincomplete-record-updates+  if impl(ghc >= 8.10)+    ghc-options: -Wunused-packages   if flag(werror)     ghc-options: -Werror 
test/Database/Beam/Postgres/Test/Marshal.hs view
@@ -51,6 +51,10 @@             pure (PgBox (PgPoint (min x1 x2) (min y1 y2))                         (PgPoint (max x1 x2) (max y1 y2))) +arrayGen :: Hedgehog.Gen a -> Hedgehog.Gen (Vector.Vector a)+arrayGen = fmap Vector.fromList +         . Gen.list (Range.linear 0 5) -- small arrays == quick tests+ boxCmp :: PgBox -> PgBox -> Bool boxCmp (PgBox a1 b1) (PgBox a2 b2) =     (a1 `ptCmp` a2 && b1 `ptCmp` b2) ||@@ -90,13 +94,27 @@     , marshalTest (Gen.maybe (Gen.integral (Range.constantBounded @Word64))) postgresConn     , marshalTest (Gen.maybe textGen) postgresConn     , marshalTest (Gen.maybe uuidGen) postgresConn-    , marshalTest692 postgresConn      , marshalTest' (\a b -> Hedgehog.assert (liftEq ptCmp a b))  (Gen.maybe pointGen) postgresConn     , marshalTest' (\a b -> Hedgehog.assert (liftEq boxCmp a b)) (Gen.maybe boxGen) postgresConn ---    , marshalTest (Gen.double  (Range.exponentialFloat 0 1e40))  postgresConn---    , marshalTest (Gen.integral (Range.constantBounded @Word))   postgresConn+    -- Arrays+    --+    -- Testing lots of element types for arrays is important, because +    -- the mapping between array Oid and element Oid is not type +    -- safe, and hence error-prone.+    , marshalTest (arrayGen textGen) postgresConn+    , marshalTest (arrayGen (Gen.double (Range.exponentialFloat 0 1e40))) postgresConn+    , marshalTest (arrayGen ((Gen.integral (Range.constantBounded @Int16)))) postgresConn+    , marshalTest (arrayGen ((Gen.integral (Range.constantBounded @Int32)))) postgresConn+    , marshalTest (arrayGen ((Gen.integral (Range.constantBounded @Int64)))) postgresConn+    , marshalTest (Gen.maybe (arrayGen textGen)) postgresConn+    , marshalTest (Gen.maybe (arrayGen (Gen.double (Range.exponentialFloat 0 1e40)))) postgresConn+    , marshalTest (Gen.maybe (arrayGen ((Gen.integral (Range.constantBounded @Int16))))) postgresConn+    , marshalTest (Gen.maybe (arrayGen ((Gen.integral (Range.constantBounded @Int32))))) postgresConn+    , marshalTest (Gen.maybe (arrayGen ((Gen.integral (Range.constantBounded @Int64))))) postgresConn++    , marshalTest (Gen.double  (Range.exponentialFloat 0 1e40))  postgresConn --    , marshalTest (Gen.integral (Range.constantBounded @Int))    postgresConn  --    , marshalTest @Int8    postgresConn@@ -164,70 +182,3 @@       v' `cmp` a      assertBool "Hedgehog test failed" passes----- Ensure that both `Vector Text` and `Maybe (Vector Text)` can be --- marshalled correctly (see issue 692).------ At this time, the postgres migration backend can't create columns of arrays,--- and hence this test does not use `marshalTest`.-marshalTest692 :: IO ByteString -> TestTree-marshalTest692 postgresConn = -  testCase "Can marshal Vector Text and Maybe (Vector Text) (#692)" $ -  withTestPostgres ("db_marshal_maybe_vector_text_issue_692") postgresConn $ \conn -> do-    liftIO $ execute_ conn $ "CREATE TABLE mytable (\nmyid SERIAL PRIMARY KEY, mycolumn text[], mynullablecolumn text[]\n);"--    passes <- Hedgehog.check . Hedgehog.property $ do-      nullable <- Hedgehog.forAll (Gen.maybe (Vector.fromList <$> (Gen.list (Range.linear 0 10) textGen)))-      nonnull <- Hedgehog.forAll (Vector.fromList <$> (Gen.list (Range.linear 0 10) textGen))--      [MkTbl692 rowId v vnull] <--        liftIO . runBeamPostgres conn -          $ runInsertReturningList -            $ insert (_myTable myDB) -              $ insertExpressions [ MkTbl692 default_ (val_ nonnull) (val_ nullable) ]--      v === nonnull-      vnull === nullable--      Just (MkTbl692 _ v' vnull') <--          liftIO . runBeamPostgres conn -            $ runSelectReturningOne (lookup_ (_myTable myDB) (Tbl692Key rowId))-      v' === nonnull-      vnull' === nullable--    assertBool "Hedgehog test failed" passes-  where-    myDB :: DatabaseSettings Postgres MyDB692-    myDB = defaultDbSettings `withDbModification`-            MkMyDB692 {-              _myTable =-                setEntityName "mytable" <>-                modifyTableFields-                  tableModification {-                    myid = fieldNamed "myid",-                    mycolumn = fieldNamed "mycolumn",-                    mynullablecolumn = fieldNamed "mynullablecolumn"-                  }-            }--data Tbl692 f-    = MkTbl692 -    { myid             :: C f (SqlSerial Int32)-    , mycolumn         :: C f (Vector.Vector T.Text)-    , mynullablecolumn :: C f (Maybe (Vector.Vector T.Text)) -    }-      deriving (Generic, Beamable)--deriving instance Show (Tbl692 Identity)-deriving instance Eq (Tbl692 Identity)--instance Table Tbl692 where-    data PrimaryKey Tbl692 f = Tbl692Key (C f (SqlSerial Int32))-      deriving (Generic, Beamable)-    primaryKey = Tbl692Key <$> myid-data MyDB692 entity-    = MkMyDB692-    { _myTable :: entity (TableEntity Tbl692)-    } deriving (Generic)-instance Database Postgres MyDB692