pg-entity 0.0.4.4 → 0.0.5.1
raw patch · 20 files changed
+339/−197 lines, 20 filesdep ~bytestringdep ~template-haskelldep ~textPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: bytestring, template-haskell, text, text-display, time, uuid
API changes (from Hackage documentation)
- Database.PostgreSQL.Entity.DBT: instance GHC.Show.Show Database.PostgreSQL.Entity.DBT.QueryNature
- Database.PostgreSQL.Entity.Internal.Unsafe: instance Database.PostgreSQL.Entity.Internal.Unsafe.ForbiddenIsString => Data.String.IsString Database.PostgreSQL.Entity.Internal.Unsafe.Field
- Database.PostgreSQL.Entity.Internal.Unsafe: instance GHC.Show.Show Database.PostgreSQL.Entity.Internal.Unsafe.Field
- Database.PostgreSQL.Entity.Types: [$sel:fieldModifiers:Options] :: Options -> Text -> Text
- Database.PostgreSQL.Entity.Types: [$sel:getGenericEntity:GenericEntity] :: GenericEntity t e -> e
- Database.PostgreSQL.Entity.Types: [$sel:getUpdate:UpdateRow] :: UpdateRow a -> a
- Database.PostgreSQL.Entity.Types: [$sel:primaryKeyModifiers:Options] :: Options -> Text -> Text
- Database.PostgreSQL.Entity.Types: [$sel:schemaModifier:Options] :: Options -> Maybe Text
- Database.PostgreSQL.Entity.Types: [$sel:tableNameModifiers:Options] :: Options -> Text -> Text
- Database.PostgreSQL.Entity.Types: instance (Database.PostgreSQL.Entity.Types.GetFields e, Database.PostgreSQL.Entity.Types.GetFields f) => Database.PostgreSQL.Entity.Types.GetFields (e GHC.Generics.:*: f)
- Database.PostgreSQL.Entity.Types: instance (GHC.TypeLits.KnownSymbol name, Database.PostgreSQL.Entity.Types.NonEmptyText name) => Database.PostgreSQL.Entity.Types.GetName name
- Database.PostgreSQL.Entity.Types: instance (GHC.TypeLits.KnownSymbol separator, Database.PostgreSQL.Entity.Types.NonEmptyText separator) => Database.PostgreSQL.Entity.Types.TextModifier (Database.PostgreSQL.Entity.Types.CamelTo separator)
- Database.PostgreSQL.Entity.Types: instance (TypeError ...) => Database.PostgreSQL.Entity.Types.GetFields (GHC.Generics.K1 i c)
- Database.PostgreSQL.Entity.Types: instance (TypeError ...) => Database.PostgreSQL.Entity.Types.GetFields (e GHC.Generics.:+: f)
- Database.PostgreSQL.Entity.Types: instance (TypeError ...) => Database.PostgreSQL.Entity.Types.GetFields GHC.Generics.U1
- Database.PostgreSQL.Entity.Types: instance (TypeError ...) => Database.PostgreSQL.Entity.Types.GetFields GHC.Generics.V1
- Database.PostgreSQL.Entity.Types: instance (TypeError ...) => Database.PostgreSQL.Entity.Types.GetTableName (GHC.Generics.K1 i c)
- Database.PostgreSQL.Entity.Types: instance (TypeError ...) => Database.PostgreSQL.Entity.Types.GetTableName (e GHC.Generics.:*: f)
- Database.PostgreSQL.Entity.Types: instance (TypeError ...) => Database.PostgreSQL.Entity.Types.GetTableName (e GHC.Generics.:+: f)
- Database.PostgreSQL.Entity.Types: instance (TypeError ...) => Database.PostgreSQL.Entity.Types.GetTableName GHC.Generics.U1
- Database.PostgreSQL.Entity.Types: instance (TypeError ...) => Database.PostgreSQL.Entity.Types.GetTableName GHC.Generics.V1
- Database.PostgreSQL.Entity.Types: instance Database.PostgreSQL.Entity.Types.GetFields e => Database.PostgreSQL.Entity.Types.GetFields (GHC.Generics.M1 GHC.Generics.C _1 e)
- Database.PostgreSQL.Entity.Types: instance Database.PostgreSQL.Entity.Types.GetFields e => Database.PostgreSQL.Entity.Types.GetFields (GHC.Generics.M1 GHC.Generics.D ('GHC.Generics.MetaData _1 _2 _3 _4) e)
- Database.PostgreSQL.Entity.Types: instance Database.PostgreSQL.Entity.Types.GetTableName e => Database.PostgreSQL.Entity.Types.GetTableName (GHC.Generics.M1 GHC.Generics.C _1 e)
- Database.PostgreSQL.Entity.Types: instance Database.PostgreSQL.Entity.Types.GetTableName e => Database.PostgreSQL.Entity.Types.GetTableName (GHC.Generics.M1 GHC.Generics.S _1 e)
- Database.PostgreSQL.Entity.Types: instance GHC.Show.Show Database.PostgreSQL.Entity.Types.SortKeyword
- Database.PostgreSQL.Entity.Types: instance GHC.Show.Show a => GHC.Show.Show (Database.PostgreSQL.Entity.Types.UpdateRow a)
- Database.PostgreSQL.Entity.Types: instance GHC.TypeLits.KnownSymbol name => Database.PostgreSQL.Entity.Types.GetFields (GHC.Generics.M1 GHC.Generics.S ('GHC.Generics.MetaSel ('GHC.Maybe.Just name) _1 _2 _3) _4)
- Database.PostgreSQL.Entity.Types: instance GHC.TypeLits.KnownSymbol name => Database.PostgreSQL.Entity.Types.GetTableName (GHC.Generics.M1 GHC.Generics.D ('GHC.Generics.MetaData name _1 _2 _3) e)
- Database.PostgreSQL.Entity.Types: instance GHC.TypeLits.KnownSymbol prefix => Database.PostgreSQL.Entity.Types.TextModifier (Database.PostgreSQL.Entity.Types.StripPrefix prefix)
- Database.PostgreSQL.Entity.Types: instance forall k (t :: k) e. (Database.PostgreSQL.Entity.Types.EntityOptions t, Database.PostgreSQL.Entity.Types.GetTableName (GHC.Generics.Rep e), Database.PostgreSQL.Entity.Types.GetFields (GHC.Generics.Rep e)) => Database.PostgreSQL.Entity.Types.Entity (Database.PostgreSQL.Entity.Types.GenericEntity t e)
+ Database.PostgreSQL.Entity: ($dmfields) :: (Entity e, GetFields (Rep e)) => Vector Field
+ Database.PostgreSQL.Entity: ($dmprimaryKey) :: (Entity e, GetFields (Rep e)) => Field
+ Database.PostgreSQL.Entity: ($dmtableName) :: (Entity e, GetTableName (Rep e)) => Text
+ Database.PostgreSQL.Entity.DBT: instance GHC.Internal.Show.Show Database.PostgreSQL.Entity.DBT.QueryNature
+ Database.PostgreSQL.Entity.Internal.Unsafe: instance Database.PostgreSQL.Entity.Internal.Unsafe.ForbiddenIsString => GHC.Internal.Data.String.IsString Database.PostgreSQL.Entity.Internal.Unsafe.Field
+ Database.PostgreSQL.Entity.Internal.Unsafe: instance GHC.Internal.Show.Show Database.PostgreSQL.Entity.Internal.Unsafe.Field
+ Database.PostgreSQL.Entity.Types: ($dmfields) :: (Entity e, GetFields (Rep e)) => Vector Field
+ Database.PostgreSQL.Entity.Types: ($dmprimaryKey) :: (Entity e, GetFields (Rep e)) => Field
+ Database.PostgreSQL.Entity.Types: ($dmtableName) :: (Entity e, GetTableName (Rep e)) => Text
+ Database.PostgreSQL.Entity.Types: [fieldModifiers] :: Options -> Text -> Text
+ Database.PostgreSQL.Entity.Types: [getGenericEntity] :: GenericEntity (t :: k) e -> e
+ Database.PostgreSQL.Entity.Types: [getUpdate] :: UpdateRow a -> a
+ Database.PostgreSQL.Entity.Types: [primaryKeyModifiers] :: Options -> Text -> Text
+ Database.PostgreSQL.Entity.Types: [schemaModifier] :: Options -> Maybe Text
+ Database.PostgreSQL.Entity.Types: [tableNameModifiers] :: Options -> Text -> Text
+ Database.PostgreSQL.Entity.Types: instance (Database.PostgreSQL.Entity.Types.GetFields e, Database.PostgreSQL.Entity.Types.GetFields f) => Database.PostgreSQL.Entity.Types.GetFields (e GHC.Internal.Generics.:*: f)
+ Database.PostgreSQL.Entity.Types: instance (GHC.Internal.TypeLits.KnownSymbol name, Database.PostgreSQL.Entity.Types.NonEmptyText name) => Database.PostgreSQL.Entity.Types.GetName name
+ Database.PostgreSQL.Entity.Types: instance (GHC.Internal.TypeLits.KnownSymbol separator, Database.PostgreSQL.Entity.Types.NonEmptyText separator) => Database.PostgreSQL.Entity.Types.TextModifier (Database.PostgreSQL.Entity.Types.CamelTo separator)
+ Database.PostgreSQL.Entity.Types: instance (TypeError ...) => Database.PostgreSQL.Entity.Types.GetFields (GHC.Internal.Generics.K1 i c)
+ Database.PostgreSQL.Entity.Types: instance (TypeError ...) => Database.PostgreSQL.Entity.Types.GetFields (e GHC.Internal.Generics.:+: f)
+ Database.PostgreSQL.Entity.Types: instance (TypeError ...) => Database.PostgreSQL.Entity.Types.GetFields GHC.Internal.Generics.U1
+ Database.PostgreSQL.Entity.Types: instance (TypeError ...) => Database.PostgreSQL.Entity.Types.GetFields GHC.Internal.Generics.V1
+ Database.PostgreSQL.Entity.Types: instance (TypeError ...) => Database.PostgreSQL.Entity.Types.GetTableName (GHC.Internal.Generics.K1 i c)
+ Database.PostgreSQL.Entity.Types: instance (TypeError ...) => Database.PostgreSQL.Entity.Types.GetTableName (e GHC.Internal.Generics.:*: f)
+ Database.PostgreSQL.Entity.Types: instance (TypeError ...) => Database.PostgreSQL.Entity.Types.GetTableName (e GHC.Internal.Generics.:+: f)
+ Database.PostgreSQL.Entity.Types: instance (TypeError ...) => Database.PostgreSQL.Entity.Types.GetTableName GHC.Internal.Generics.U1
+ Database.PostgreSQL.Entity.Types: instance (TypeError ...) => Database.PostgreSQL.Entity.Types.GetTableName GHC.Internal.Generics.V1
+ Database.PostgreSQL.Entity.Types: instance Database.PostgreSQL.Entity.Types.GetFields e => Database.PostgreSQL.Entity.Types.GetFields (GHC.Internal.Generics.M1 GHC.Internal.Generics.C _1 e)
+ Database.PostgreSQL.Entity.Types: instance Database.PostgreSQL.Entity.Types.GetFields e => Database.PostgreSQL.Entity.Types.GetFields (GHC.Internal.Generics.M1 GHC.Internal.Generics.D ('GHC.Internal.Generics.MetaData _1 _2 _3 _4) e)
+ Database.PostgreSQL.Entity.Types: instance Database.PostgreSQL.Entity.Types.GetTableName e => Database.PostgreSQL.Entity.Types.GetTableName (GHC.Internal.Generics.M1 GHC.Internal.Generics.C _1 e)
+ Database.PostgreSQL.Entity.Types: instance Database.PostgreSQL.Entity.Types.GetTableName e => Database.PostgreSQL.Entity.Types.GetTableName (GHC.Internal.Generics.M1 GHC.Internal.Generics.S _1 e)
+ Database.PostgreSQL.Entity.Types: instance GHC.Internal.Show.Show Database.PostgreSQL.Entity.Types.SortKeyword
+ Database.PostgreSQL.Entity.Types: instance GHC.Internal.Show.Show a => GHC.Internal.Show.Show (Database.PostgreSQL.Entity.Types.UpdateRow a)
+ Database.PostgreSQL.Entity.Types: instance GHC.Internal.TypeLits.KnownSymbol name => Database.PostgreSQL.Entity.Types.GetFields (GHC.Internal.Generics.M1 GHC.Internal.Generics.S ('GHC.Internal.Generics.MetaSel ('GHC.Internal.Maybe.Just name) _1 _2 _3) _4)
+ Database.PostgreSQL.Entity.Types: instance GHC.Internal.TypeLits.KnownSymbol name => Database.PostgreSQL.Entity.Types.GetTableName (GHC.Internal.Generics.M1 GHC.Internal.Generics.D ('GHC.Internal.Generics.MetaData name _1 _2 _3) e)
+ Database.PostgreSQL.Entity.Types: instance GHC.Internal.TypeLits.KnownSymbol prefix => Database.PostgreSQL.Entity.Types.TextModifier (Database.PostgreSQL.Entity.Types.StripPrefix prefix)
+ Database.PostgreSQL.Entity.Types: instance forall k (t :: k) e. (Database.PostgreSQL.Entity.Types.EntityOptions t, Database.PostgreSQL.Entity.Types.GetTableName (GHC.Internal.Generics.Rep e), Database.PostgreSQL.Entity.Types.GetFields (GHC.Internal.Generics.Rep e)) => Database.PostgreSQL.Entity.Types.Entity (Database.PostgreSQL.Entity.Types.GenericEntity t e)
- Database.PostgreSQL.Entity: _delete :: forall e. Entity e => Query
+ Database.PostgreSQL.Entity: _delete :: Entity e => Query
- Database.PostgreSQL.Entity: _deleteWhere :: forall e. Entity e => Vector Field -> Query
+ Database.PostgreSQL.Entity: _deleteWhere :: Entity e => Vector Field -> Query
- Database.PostgreSQL.Entity: _innerJoin :: forall e. Entity e => Field -> Query
+ Database.PostgreSQL.Entity: _innerJoin :: Entity e => Field -> Query
- Database.PostgreSQL.Entity: _insert :: forall e. Entity e => Query
+ Database.PostgreSQL.Entity: _insert :: Entity e => Query
- Database.PostgreSQL.Entity: _joinSelect :: forall e1 e2. (Entity e1, Entity e2) => Query
+ Database.PostgreSQL.Entity: _joinSelect :: (Entity e1, Entity e2) => Query
- Database.PostgreSQL.Entity: _joinSelectOneByField :: forall e1 e2. (Entity e1, Entity e2) => Field -> Field -> Query
+ Database.PostgreSQL.Entity: _joinSelectOneByField :: (Entity e1, Entity e2) => Field -> Field -> Query
- Database.PostgreSQL.Entity: _joinSelectWithFields :: forall e1 e2. (Entity e1, Entity e2) => Vector Field -> Vector Field -> Query
+ Database.PostgreSQL.Entity: _joinSelectWithFields :: (Entity e1, Entity e2) => Vector Field -> Vector Field -> Query
- Database.PostgreSQL.Entity: _select :: forall e. Entity e => Query
+ Database.PostgreSQL.Entity: _select :: Entity e => Query
- Database.PostgreSQL.Entity: _selectWhere :: forall e. Entity e => Vector Field -> Query
+ Database.PostgreSQL.Entity: _selectWhere :: Entity e => Vector Field -> Query
- Database.PostgreSQL.Entity: _selectWhereIn :: forall e. Entity e => Field -> Vector Text -> Query
+ Database.PostgreSQL.Entity: _selectWhereIn :: Entity e => Field -> Vector Text -> Query
- Database.PostgreSQL.Entity: _selectWhereNotNull :: forall e. Entity e => Vector Field -> Query
+ Database.PostgreSQL.Entity: _selectWhereNotNull :: Entity e => Vector Field -> Query
- Database.PostgreSQL.Entity: _selectWhereNull :: forall e. Entity e => Vector Field -> Query
+ Database.PostgreSQL.Entity: _selectWhereNull :: Entity e => Vector Field -> Query
- Database.PostgreSQL.Entity: _selectWithFields :: forall e. Entity e => Vector Field -> Query
+ Database.PostgreSQL.Entity: _selectWithFields :: Entity e => Vector Field -> Query
- Database.PostgreSQL.Entity: _update :: forall e. Entity e => Query
+ Database.PostgreSQL.Entity: _update :: Entity e => Query
- Database.PostgreSQL.Entity: _updateBy :: forall e. Entity e => Field -> Query
+ Database.PostgreSQL.Entity: _updateBy :: Entity e => Field -> Query
- Database.PostgreSQL.Entity: _updateFields :: forall e. Entity e => Vector Field -> Query
+ Database.PostgreSQL.Entity: _updateFields :: Entity e => Vector Field -> Query
- Database.PostgreSQL.Entity: _updateFieldsBy :: forall e. Entity e => Vector Field -> Field -> Query
+ Database.PostgreSQL.Entity: _updateFieldsBy :: Entity e => Vector Field -> Field -> Query
- Database.PostgreSQL.Entity: delete :: forall e value m. (Entity e, ToRow value, MonadIO m) => value -> DBT m ()
+ Database.PostgreSQL.Entity: delete :: forall e value (m :: Type -> Type). (Entity e, ToRow value, MonadIO m) => value -> DBT m ()
- Database.PostgreSQL.Entity: deleteByField :: forall e values m. (Entity e, ToRow values, MonadIO m) => Vector Field -> values -> DBT m ()
+ Database.PostgreSQL.Entity: deleteByField :: forall e values (m :: Type -> Type). (Entity e, ToRow values, MonadIO m) => Vector Field -> values -> DBT m ()
- Database.PostgreSQL.Entity: fields :: (Entity e, GetFields (Rep e)) => Vector Field
+ Database.PostgreSQL.Entity: fields :: Entity e => Vector Field
- Database.PostgreSQL.Entity: insert :: forall e values m. (Entity e, ToRow values, MonadIO m) => values -> DBT m ()
+ Database.PostgreSQL.Entity: insert :: forall e values (m :: Type -> Type). (Entity e, ToRow values, MonadIO m) => values -> DBT m ()
- Database.PostgreSQL.Entity: insertMany :: forall e values m. (Entity e, ToRow values, MonadIO m) => [values] -> DBT m ()
+ Database.PostgreSQL.Entity: insertMany :: forall e values (m :: Type -> Type). (Entity e, ToRow values, MonadIO m) => [values] -> DBT m ()
- Database.PostgreSQL.Entity: joinSelectById :: forall e1 e2 m. (Entity e1, Entity e2, FromRow e1, MonadIO m) => DBT m (Vector e1)
+ Database.PostgreSQL.Entity: joinSelectById :: forall e1 e2 (m :: Type -> Type). (Entity e1, Entity e2, FromRow e1, MonadIO m) => DBT m (Vector e1)
- Database.PostgreSQL.Entity: joinSelectOneByField :: forall e1 e2 value m. (Entity e1, Entity e2, FromRow e1, MonadIO m, ToField value) => Field -> Field -> value -> DBT m (Vector e1)
+ Database.PostgreSQL.Entity: joinSelectOneByField :: forall e1 e2 value (m :: Type -> Type). (Entity e1, Entity e2, FromRow e1, MonadIO m, ToField value) => Field -> Field -> value -> DBT m (Vector e1)
- Database.PostgreSQL.Entity: primaryKey :: (Entity e, GetFields (Rep e)) => Field
+ Database.PostgreSQL.Entity: primaryKey :: Entity e => Field
- Database.PostgreSQL.Entity: selectById :: forall e value m. (Entity e, FromRow e, MonadIO m, ToRow value) => value -> DBT m (Maybe e)
+ Database.PostgreSQL.Entity: selectById :: forall e value (m :: Type -> Type). (Entity e, FromRow e, MonadIO m, ToRow value) => value -> DBT m (Maybe e)
- Database.PostgreSQL.Entity: selectManyByField :: forall e value m. (Entity e, FromRow e, MonadIO m, ToRow value) => Field -> value -> DBT m (Vector e)
+ Database.PostgreSQL.Entity: selectManyByField :: forall e value (m :: Type -> Type). (Entity e, FromRow e, MonadIO m, ToRow value) => Field -> value -> DBT m (Vector e)
- Database.PostgreSQL.Entity: selectOneByField :: forall e value m. (Entity e, FromRow e, MonadIO m, ToRow value) => Field -> value -> DBT m (Maybe e)
+ Database.PostgreSQL.Entity: selectOneByField :: forall e value (m :: Type -> Type). (Entity e, FromRow e, MonadIO m, ToRow value) => Field -> value -> DBT m (Maybe e)
- Database.PostgreSQL.Entity: selectOneWhereIn :: forall e m. (Entity e, FromRow e, MonadIO m) => Field -> Vector Text -> DBT m (Maybe e)
+ Database.PostgreSQL.Entity: selectOneWhereIn :: forall e (m :: Type -> Type). (Entity e, FromRow e, MonadIO m) => Field -> Vector Text -> DBT m (Maybe e)
- Database.PostgreSQL.Entity: selectOrderBy :: forall e m. (Entity e, FromRow e, MonadIO m) => Vector (Field, SortKeyword) -> DBT m (Vector e)
+ Database.PostgreSQL.Entity: selectOrderBy :: forall e (m :: Type -> Type). (Entity e, FromRow e, MonadIO m) => Vector (Field, SortKeyword) -> DBT m (Vector e)
- Database.PostgreSQL.Entity: selectWhereNotNull :: forall e m. (Entity e, FromRow e, MonadIO m) => Vector Field -> DBT m (Vector e)
+ Database.PostgreSQL.Entity: selectWhereNotNull :: forall e (m :: Type -> Type). (Entity e, FromRow e, MonadIO m) => Vector Field -> DBT m (Vector e)
- Database.PostgreSQL.Entity: selectWhereNull :: forall e m. (Entity e, FromRow e, MonadIO m) => Vector Field -> DBT m (Vector e)
+ Database.PostgreSQL.Entity: selectWhereNull :: forall e (m :: Type -> Type). (Entity e, FromRow e, MonadIO m) => Vector Field -> DBT m (Vector e)
- Database.PostgreSQL.Entity: tableName :: (Entity e, GetTableName (Rep e)) => Text
+ Database.PostgreSQL.Entity: tableName :: Entity e => Text
- Database.PostgreSQL.Entity: update :: forall e newValue m. (Entity e, ToRow newValue, MonadIO m) => newValue -> DBT m ()
+ Database.PostgreSQL.Entity: update :: forall e newValue (m :: Type -> Type). (Entity e, ToRow newValue, MonadIO m) => newValue -> DBT m ()
- Database.PostgreSQL.Entity: updateFieldsBy :: forall e v1 v2 m. (Entity e, MonadIO m, ToRow v2, ToField v1) => Vector Field -> (Field, v1) -> v2 -> DBT m Int64
+ Database.PostgreSQL.Entity: updateFieldsBy :: forall e v1 v2 (m :: Type -> Type). (Entity e, MonadIO m, ToRow v2, ToField v1) => Vector Field -> (Field, v1) -> v2 -> DBT m Int64
- Database.PostgreSQL.Entity: upsert :: forall e values m. (Entity e, ToRow values, MonadIO m) => values -> Vector Field -> DBT m ()
+ Database.PostgreSQL.Entity: upsert :: forall e values (m :: Type -> Type). (Entity e, ToRow values, MonadIO m) => values -> Vector Field -> DBT m ()
- Database.PostgreSQL.Entity.DBT: execute :: (ToRow params, MonadIO m) => QueryNature -> Query -> params -> DBT m Int64
+ Database.PostgreSQL.Entity.DBT: execute :: forall params (m :: Type -> Type). (ToRow params, MonadIO m) => QueryNature -> Query -> params -> DBT m Int64
- Database.PostgreSQL.Entity.DBT: executeMany :: (ToRow params, MonadIO m) => QueryNature -> Query -> [params] -> DBT m Int64
+ Database.PostgreSQL.Entity.DBT: executeMany :: forall params (m :: Type -> Type). (ToRow params, MonadIO m) => QueryNature -> Query -> [params] -> DBT m Int64
- Database.PostgreSQL.Entity.DBT: query :: (ToRow params, FromRow result, MonadIO m) => QueryNature -> Query -> params -> DBT m (Vector result)
+ Database.PostgreSQL.Entity.DBT: query :: forall params result (m :: Type -> Type). (ToRow params, FromRow result, MonadIO m) => QueryNature -> Query -> params -> DBT m (Vector result)
- Database.PostgreSQL.Entity.DBT: queryOne :: (ToRow params, FromRow result, MonadIO m) => QueryNature -> Query -> params -> DBT m (Maybe result)
+ Database.PostgreSQL.Entity.DBT: queryOne :: forall params result (m :: Type -> Type). (ToRow params, FromRow result, MonadIO m) => QueryNature -> Query -> params -> DBT m (Maybe result)
- Database.PostgreSQL.Entity.DBT: queryOne_ :: (FromRow result, MonadIO m) => QueryNature -> Query -> DBT m (Maybe result)
+ Database.PostgreSQL.Entity.DBT: queryOne_ :: forall result (m :: Type -> Type). (FromRow result, MonadIO m) => QueryNature -> Query -> DBT m (Maybe result)
- Database.PostgreSQL.Entity.DBT: query_ :: (FromRow result, MonadIO m) => QueryNature -> Query -> DBT m (Vector result)
+ Database.PostgreSQL.Entity.DBT: query_ :: forall result (m :: Type -> Type). (FromRow result, MonadIO m) => QueryNature -> Query -> DBT m (Vector result)
- Database.PostgreSQL.Entity.Internal: expandFields :: forall e. Entity e => Text
+ Database.PostgreSQL.Entity.Internal: expandFields :: Entity e => Text
- Database.PostgreSQL.Entity.Internal: expandQualifiedFields :: forall e. Entity e => Text
+ Database.PostgreSQL.Entity.Internal: expandQualifiedFields :: Entity e => Text
- Database.PostgreSQL.Entity.Internal: getPrimaryKey :: forall e. Entity e => Text
+ Database.PostgreSQL.Entity.Internal: getPrimaryKey :: Entity e => Text
- Database.PostgreSQL.Entity.Internal: getTableName :: forall e. Entity e => Text
+ Database.PostgreSQL.Entity.Internal: getTableName :: Entity e => Text
- Database.PostgreSQL.Entity.Internal: placeholder' :: forall e. Entity e => Field -> Text
+ Database.PostgreSQL.Entity.Internal: placeholder' :: Entity e => Field -> Text
- Database.PostgreSQL.Entity.Internal: qualifyField :: forall e. Entity e => Field -> Text
+ Database.PostgreSQL.Entity.Internal: qualifyField :: Entity e => Field -> Text
- Database.PostgreSQL.Entity.Types: GenericEntity :: e -> GenericEntity t e
+ Database.PostgreSQL.Entity.Types: GenericEntity :: e -> GenericEntity (t :: k) e
- Database.PostgreSQL.Entity.Types: class EntityOptions xs
+ Database.PostgreSQL.Entity.Types: class EntityOptions (xs :: k)
- Database.PostgreSQL.Entity.Types: class TextModifier t
+ Database.PostgreSQL.Entity.Types: class TextModifier (t :: k)
- Database.PostgreSQL.Entity.Types: data FieldModifiers ms
+ Database.PostgreSQL.Entity.Types: data FieldModifiers (ms :: k)
- Database.PostgreSQL.Entity.Types: fields :: (Entity e, GetFields (Rep e)) => Vector Field
+ Database.PostgreSQL.Entity.Types: fields :: Entity e => Vector Field
- Database.PostgreSQL.Entity.Types: newtype GenericEntity t e
+ Database.PostgreSQL.Entity.Types: newtype GenericEntity (t :: k) e
- Database.PostgreSQL.Entity.Types: primaryKey :: (Entity e, GetFields (Rep e)) => Field
+ Database.PostgreSQL.Entity.Types: primaryKey :: Entity e => Field
- Database.PostgreSQL.Entity.Types: tableName :: (Entity e, GetTableName (Rep e)) => Text
+ Database.PostgreSQL.Entity.Types: tableName :: Entity e => Text
Files
- CHANGELOG.md +9/−1
- docs/book/404.html +26/−18
- docs/book/ErrorsGuide.html +26/−18
- docs/book/Introduction.html +26/−18
- docs/book/Tutorial.html +26/−18
- docs/book/book.js +7/−13
- docs/book/css/chrome.css +1/−1
- docs/book/css/general.css +1/−0
- docs/book/css/print.css +0/−8
- docs/book/css/variables.css +10/−0
- docs/book/index.html +26/−18
- docs/book/print.html +26/−18
- docs/book/tomorrow-night.css +2/−2
- docs/src/Tutorial.hs +1/−1
- pg-entity.cabal +8/−11
- src/Database/PostgreSQL/Entity.hs +64/−35
- src/Database/PostgreSQL/Entity/Internal.hs +70/−14
- src/Database/PostgreSQL/Entity/Internal/QQ.hs +2/−2
- test/EntitySpec.hs +7/−1
- test/Utils.hs +1/−0
CHANGELOG.md view
@@ -1,6 +1,14 @@ # Revision history for Entity -## 0.0.4.4 -- 2024-12-23+## 0.0.5.1 -- 2025-04-23++* Update dependencies++## 0.0.5.0 -- 2024-01-19++* Update version of `bytestring` to 0.12, `text` to 2.1 and `postgresql-simple` to 0.7 ([#72](https://github.com/tchoutri/pg-entity/pull/72))++## 0.0.4.4 -- 2023-12-23 * Remove extraneous quoting of table name in _selectWithFields ## 0.0.4.3 -- 2023-06-26
docs/book/404.html view
@@ -71,10 +71,12 @@ <!-- Hide / unhide sidebar before it is displayed --> <script> var html = document.querySelector('html');- var sidebar = 'hidden';+ var sidebar = null; if (document.body.clientWidth >= 1080) { try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { } sidebar = sidebar || 'visible';+ } else {+ sidebar = 'hidden'; } html.classList.remove('sidebar-visible'); html.classList.add("sidebar-" + sidebar);@@ -87,11 +89,33 @@ <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div> </nav> + <!-- Track and set sidebar scroll position -->+ <script>+ var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');+ sidebarScrollbox.addEventListener('click', function(e) {+ if (e.target.tagName === 'A') {+ sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);+ }+ }, { passive: true });+ var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');+ sessionStorage.removeItem('sidebar-scroll');+ if (sidebarScrollTop) {+ // preserve sidebar scroll position when navigating via links within sidebar+ sidebarScrollbox.scrollTop = sidebarScrollTop;+ } else {+ // scroll sidebar to current active section when navigating via "next/previous chapter" buttons+ var activeSection = document.querySelector('#sidebar .active');+ if (activeSection) {+ activeSection.scrollIntoView({ block: 'center' });+ }+ }+ </script>+ <div id="page-wrapper" class="page-wrapper"> <div class="page"> <div id="menu-bar-hover-placeholder"></div>- <div id="menu-bar" class="menu-bar sticky bordered">+ <div id="menu-bar" class="menu-bar sticky"> <div class="left-buttons"> <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar"> <i class="fa fa-bars"></i>@@ -166,22 +190,6 @@ </div> - <!-- Livereload script (if served using the cli tool) -->- <script>- const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';- const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";- const socket = new WebSocket(wsAddress);- socket.onmessage = function (event) {- if (event.data === "reload") {- socket.close();- location.reload();- }- };-- window.onbeforeunload = function() {- socket.close();- }- </script>
docs/book/ErrorsGuide.html view
@@ -70,10 +70,12 @@ <!-- Hide / unhide sidebar before it is displayed --> <script> var html = document.querySelector('html');- var sidebar = 'hidden';+ var sidebar = null; if (document.body.clientWidth >= 1080) { try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { } sidebar = sidebar || 'visible';+ } else {+ sidebar = 'hidden'; } html.classList.remove('sidebar-visible'); html.classList.add("sidebar-" + sidebar);@@ -86,11 +88,33 @@ <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div> </nav> + <!-- Track and set sidebar scroll position -->+ <script>+ var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');+ sidebarScrollbox.addEventListener('click', function(e) {+ if (e.target.tagName === 'A') {+ sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);+ }+ }, { passive: true });+ var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');+ sessionStorage.removeItem('sidebar-scroll');+ if (sidebarScrollTop) {+ // preserve sidebar scroll position when navigating via links within sidebar+ sidebarScrollbox.scrollTop = sidebarScrollTop;+ } else {+ // scroll sidebar to current active section when navigating via "next/previous chapter" buttons+ var activeSection = document.querySelector('#sidebar .active');+ if (activeSection) {+ activeSection.scrollIntoView({ block: 'center' });+ }+ }+ </script>+ <div id="page-wrapper" class="page-wrapper"> <div class="page"> <div id="menu-bar-hover-placeholder"></div>- <div id="menu-bar" class="menu-bar sticky bordered">+ <div id="menu-bar" class="menu-bar sticky"> <div class="left-buttons"> <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar"> <i class="fa fa-bars"></i>@@ -241,22 +265,6 @@ </div> - <!-- Livereload script (if served using the cli tool) -->- <script>- const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';- const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";- const socket = new WebSocket(wsAddress);- socket.onmessage = function (event) {- if (event.data === "reload") {- socket.close();- location.reload();- }- };-- window.onbeforeunload = function() {- socket.close();- }- </script>
docs/book/Introduction.html view
@@ -70,10 +70,12 @@ <!-- Hide / unhide sidebar before it is displayed --> <script> var html = document.querySelector('html');- var sidebar = 'hidden';+ var sidebar = null; if (document.body.clientWidth >= 1080) { try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { } sidebar = sidebar || 'visible';+ } else {+ sidebar = 'hidden'; } html.classList.remove('sidebar-visible'); html.classList.add("sidebar-" + sidebar);@@ -86,11 +88,33 @@ <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div> </nav> + <!-- Track and set sidebar scroll position -->+ <script>+ var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');+ sidebarScrollbox.addEventListener('click', function(e) {+ if (e.target.tagName === 'A') {+ sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);+ }+ }, { passive: true });+ var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');+ sessionStorage.removeItem('sidebar-scroll');+ if (sidebarScrollTop) {+ // preserve sidebar scroll position when navigating via links within sidebar+ sidebarScrollbox.scrollTop = sidebarScrollTop;+ } else {+ // scroll sidebar to current active section when navigating via "next/previous chapter" buttons+ var activeSection = document.querySelector('#sidebar .active');+ if (activeSection) {+ activeSection.scrollIntoView({ block: 'center' });+ }+ }+ </script>+ <div id="page-wrapper" class="page-wrapper"> <div class="page"> <div id="menu-bar-hover-placeholder"></div>- <div id="menu-bar" class="menu-bar sticky bordered">+ <div id="menu-bar" class="menu-bar sticky"> <div class="left-buttons"> <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar"> <i class="fa fa-bars"></i>@@ -192,22 +216,6 @@ </div> - <!-- Livereload script (if served using the cli tool) -->- <script>- const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';- const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";- const socket = new WebSocket(wsAddress);- socket.onmessage = function (event) {- if (event.data === "reload") {- socket.close();- location.reload();- }- };-- window.onbeforeunload = function() {- socket.close();- }- </script>
docs/book/Tutorial.html view
@@ -70,10 +70,12 @@ <!-- Hide / unhide sidebar before it is displayed --> <script> var html = document.querySelector('html');- var sidebar = 'hidden';+ var sidebar = null; if (document.body.clientWidth >= 1080) { try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { } sidebar = sidebar || 'visible';+ } else {+ sidebar = 'hidden'; } html.classList.remove('sidebar-visible'); html.classList.add("sidebar-" + sidebar);@@ -86,11 +88,33 @@ <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div> </nav> + <!-- Track and set sidebar scroll position -->+ <script>+ var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');+ sidebarScrollbox.addEventListener('click', function(e) {+ if (e.target.tagName === 'A') {+ sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);+ }+ }, { passive: true });+ var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');+ sessionStorage.removeItem('sidebar-scroll');+ if (sidebarScrollTop) {+ // preserve sidebar scroll position when navigating via links within sidebar+ sidebarScrollbox.scrollTop = sidebarScrollTop;+ } else {+ // scroll sidebar to current active section when navigating via "next/previous chapter" buttons+ var activeSection = document.querySelector('#sidebar .active');+ if (activeSection) {+ activeSection.scrollIntoView({ block: 'center' });+ }+ }+ </script>+ <div id="page-wrapper" class="page-wrapper"> <div class="page"> <div id="menu-bar-hover-placeholder"></div>- <div id="menu-bar" class="menu-bar sticky bordered">+ <div id="menu-bar" class="menu-bar sticky"> <div class="left-buttons"> <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar"> <i class="fa fa-bars"></i>@@ -368,22 +392,6 @@ </div> - <!-- Livereload script (if served using the cli tool) -->- <script>- const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';- const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";- const socket = new WebSocket(wsAddress);- socket.onmessage = function (event) {- if (event.data === "reload") {- socket.close();- location.reload();- }- };-- window.onbeforeunload = function() {- socket.close();- }- </script>
docs/book/book.js view
@@ -68,7 +68,7 @@ } // updates the visibility of play button based on `no_run` class and- // used crates vs ones available on http://play.rust-lang.org+ // used crates vs ones available on https://play.rust-lang.org function update_play_button(pre_block, playground_crates) { var play_button = pre_block.querySelector(".play-button"); @@ -179,7 +179,7 @@ // even if highlighting doesn't apply code_nodes.forEach(function (block) { block.classList.add('hljs'); }); - Array.from(document.querySelectorAll("code.language-rust")).forEach(function (block) {+ Array.from(document.querySelectorAll("code.hljs")).forEach(function (block) { var lines = Array.from(block.querySelectorAll('.boring')); // If no lines were hidden, return@@ -346,7 +346,7 @@ } setTimeout(function () {- themeColorMetaTag.content = getComputedStyle(document.body).backgroundColor;+ themeColorMetaTag.content = getComputedStyle(document.documentElement).backgroundColor; }, 1); if (window.ace && window.editors) {@@ -551,13 +551,6 @@ firstContact = null; } }, { passive: true });-- // Scroll sidebar to current active section- var activeSection = document.getElementById("sidebar").querySelector(".active");- if (activeSection) {- // https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView- activeSection.scrollIntoView({ block: 'center' });- } })(); (function chapterNavigation() {@@ -676,13 +669,14 @@ }, { passive: true }); })(); (function controllBorder() {- menu.classList.remove('bordered');- document.addEventListener('scroll', function () {+ function updateBorder() { if (menu.offsetTop === 0) { menu.classList.remove('bordered'); } else { menu.classList.add('bordered'); }- }, { passive: true });+ }+ updateBorder();+ document.addEventListener('scroll', updateBorder, { passive: true }); })(); })();
docs/book/css/chrome.css view
@@ -22,7 +22,7 @@ the screen on small screens. Without it, dragging on mobile Safari will want to reposition the viewport in a weird way. */- overflow-x: hidden;+ overflow-x: clip; } /* Menu Bar */
docs/book/css/general.css view
@@ -5,6 +5,7 @@ :root { /* Browser default font-size is 16px, this way 1 rem = 10px */ font-size: 62.5%;+ color-scheme: var(--color-scheme); } html {
docs/book/css/print.css view
@@ -22,14 +22,6 @@ overflow-y: initial; } -code {- background-color: #666666;- border-radius: 5px;-- /* Force background to be printed in Chrome */- -webkit-print-color-adjust: exact;-}- pre > .buttons { z-index: 2; }
docs/book/css/variables.css view
@@ -50,6 +50,8 @@ --searchresults-border-color: #888; --searchresults-li-bg: #252932; --search-mark-bg: #e3b171;++ --color-scheme: dark; } .coal {@@ -90,6 +92,8 @@ --searchresults-border-color: #98a3ad; --searchresults-li-bg: #2b2b2f; --search-mark-bg: #355c7d;++ --color-scheme: dark; } .light {@@ -130,6 +134,8 @@ --searchresults-border-color: #888; --searchresults-li-bg: #e4f2fe; --search-mark-bg: #a2cff5;++ --color-scheme: light; } .navy {@@ -170,6 +176,8 @@ --searchresults-border-color: #5c5c68; --searchresults-li-bg: #242430; --search-mark-bg: #a2cff5;++ --color-scheme: dark; } .rust {@@ -210,6 +218,8 @@ --searchresults-border-color: #888; --searchresults-li-bg: #dec2a2; --search-mark-bg: #e69f67;++ --color-scheme: light; } @media (prefers-color-scheme: dark) {
docs/book/index.html view
@@ -70,10 +70,12 @@ <!-- Hide / unhide sidebar before it is displayed --> <script> var html = document.querySelector('html');- var sidebar = 'hidden';+ var sidebar = null; if (document.body.clientWidth >= 1080) { try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { } sidebar = sidebar || 'visible';+ } else {+ sidebar = 'hidden'; } html.classList.remove('sidebar-visible'); html.classList.add("sidebar-" + sidebar);@@ -86,11 +88,33 @@ <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div> </nav> + <!-- Track and set sidebar scroll position -->+ <script>+ var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');+ sidebarScrollbox.addEventListener('click', function(e) {+ if (e.target.tagName === 'A') {+ sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);+ }+ }, { passive: true });+ var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');+ sessionStorage.removeItem('sidebar-scroll');+ if (sidebarScrollTop) {+ // preserve sidebar scroll position when navigating via links within sidebar+ sidebarScrollbox.scrollTop = sidebarScrollTop;+ } else {+ // scroll sidebar to current active section when navigating via "next/previous chapter" buttons+ var activeSection = document.querySelector('#sidebar .active');+ if (activeSection) {+ activeSection.scrollIntoView({ block: 'center' });+ }+ }+ </script>+ <div id="page-wrapper" class="page-wrapper"> <div class="page"> <div id="menu-bar-hover-placeholder"></div>- <div id="menu-bar" class="menu-bar sticky bordered">+ <div id="menu-bar" class="menu-bar sticky"> <div class="left-buttons"> <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar"> <i class="fa fa-bars"></i>@@ -192,22 +216,6 @@ </div> - <!-- Livereload script (if served using the cli tool) -->- <script>- const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';- const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";- const socket = new WebSocket(wsAddress);- socket.onmessage = function (event) {- if (event.data === "reload") {- socket.close();- location.reload();- }- };-- window.onbeforeunload = function() {- socket.close();- }- </script>
docs/book/print.html view
@@ -71,10 +71,12 @@ <!-- Hide / unhide sidebar before it is displayed --> <script> var html = document.querySelector('html');- var sidebar = 'hidden';+ var sidebar = null; if (document.body.clientWidth >= 1080) { try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { } sidebar = sidebar || 'visible';+ } else {+ sidebar = 'hidden'; } html.classList.remove('sidebar-visible'); html.classList.add("sidebar-" + sidebar);@@ -87,11 +89,33 @@ <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div> </nav> + <!-- Track and set sidebar scroll position -->+ <script>+ var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');+ sidebarScrollbox.addEventListener('click', function(e) {+ if (e.target.tagName === 'A') {+ sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);+ }+ }, { passive: true });+ var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');+ sessionStorage.removeItem('sidebar-scroll');+ if (sidebarScrollTop) {+ // preserve sidebar scroll position when navigating via links within sidebar+ sidebarScrollbox.scrollTop = sidebarScrollTop;+ } else {+ // scroll sidebar to current active section when navigating via "next/previous chapter" buttons+ var activeSection = document.querySelector('#sidebar .active');+ if (activeSection) {+ activeSection.scrollIntoView({ block: 'center' });+ }+ }+ </script>+ <div id="page-wrapper" class="page-wrapper"> <div class="page"> <div id="menu-bar-hover-placeholder"></div>- <div id="menu-bar" class="menu-bar sticky bordered">+ <div id="menu-bar" class="menu-bar sticky"> <div class="left-buttons"> <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar"> <i class="fa fa-bars"></i>@@ -452,22 +476,6 @@ </div> - <!-- Livereload script (if served using the cli tool) -->- <script>- const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';- const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";- const socket = new WebSocket(wsAddress);- socket.onmessage = function (event) {- if (event.data === "reload") {- socket.close();- location.reload();- }- };-- window.onbeforeunload = function() {- socket.close();- }- </script>
docs/book/tomorrow-night.css view
@@ -1,7 +1,7 @@ /* Tomorrow Night Theme */-/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */+/* https://github.com/jmblog/color-themes-for-highlightjs */ /* Original theme - https://github.com/chriskempson/tomorrow-theme */-/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */+/* https://github.com/jmblog/color-themes-for-highlightjs */ /* Tomorrow Comment */ .hljs-comment {
docs/src/Tutorial.hs view
@@ -28,7 +28,7 @@ import Database.PostgreSQL.Transact (DBT) import GHC.Generics -import Control.Monad.Error+import Control.Monad.IO.Class (MonadIO (..)) import qualified Data.Time as Time import qualified Data.UUID.V4 as UUID import Database.PostgreSQL.Entity
pg-entity.cabal view
@@ -5,7 +5,7 @@ A PostgreSQL layer to safely expand your SQL queries with a lightweight eDSL. Read the tutorial at https://hackage.haskell.org/package/pg-entity/src/docs/book/index.html -version: 0.0.4.4+version: 0.0.5.1 homepage: https://hackage.haskell.org/package/pg-entity/src/docs/book/index.html @@ -15,9 +15,7 @@ category: Database license: MIT build-type: Simple-tested-with:- GHC ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.8 || ==9.4.8-+tested-with: GHC ==9.2.8 || ==9.4.8 || ==9.6.7 || ==9.8.4 || ==9.10.1 extra-source-files: CHANGELOG.md LICENSE.md@@ -105,18 +103,17 @@ hs-source-dirs: src build-depends: , base >=4.12 && <5.0- , bytestring ^>=0.11+ , bytestring ^>=0.12 , colourista ^>=0.1 , parsec ^>=3.1 , pg-transact ^>=0.3- , postgresql-simple ^>=0.6+ , postgresql-simple ^>=0.7 , resource-pool ^>=0.4- , template-haskell >=2.15.0.0 && <2.22.0.0.0- , text ^>=2.0- , text-display ^>=0.0+ , template-haskell >=2.15.0.0 && <2.23.0.0.0+ , text ^>=2.1+ , text-display ^>=1.0 , text-manipulate ^>=0.3- , time ^>=1.12- , uuid ^>=1.3+ , time ^>=1.14 , vector ^>=0.13 if flag(prod)
src/Database/PostgreSQL/Entity.hs view
@@ -98,18 +98,47 @@ import Database.PostgreSQL.Entity.Types {- $setup- >>> :set -XQuasiQuotes- >>> :set -XOverloadedStrings- >>> :set -XOverloadedLists- >>> :set -XTypeApplications- >>> import Database.PostgreSQL.Entity- >>> import Database.PostgreSQL.Entity.Types- >>> import Database.PostgreSQL.Entity.Internal- >>> import Database.PostgreSQL.Entity.Internal.BlogPost- >>> import Database.PostgreSQL.Entity.Internal.QQ- >>> import Database.PostgreSQL.Simple.Types (Query (..))- >>> import Data.Vector (Vector)- >>> import qualified Data.Vector as V+>>> :set -XQuasiQuotes+>>> :set -XOverloadedStrings+>>> :set -XOverloadedLists+>>> :set -XTypeApplications+>>> import Database.PostgreSQL.Entity+>>> import Database.PostgreSQL.Entity.Types+>>> import Database.PostgreSQL.Entity.Internal+>>> import Database.PostgreSQL.Entity.Internal.QQ+>>> import Database.PostgreSQL.Simple.Types (Query (..))+>>> import Data.Vector (Vector)+>>> import qualified Data.Vector as V+>>> import Data.Time (UTCTime)+>>> import GHC.Generics (Generic)+>>> :{+>>> data Author = Author+>>> { authorId :: Int+>>> , name :: Text+>>> , createdAt :: UTCTime+>>> }+>>> deriving stock (Eq, Generic, Ord, Show)+>>> deriving anyclass (FromRow, ToRow)+>>> deriving+>>> (Entity)+>>> via (GenericEntity '[PrimaryKey "author_id", TableName "authors"] Author)+>>>+>>> data BlogPost = BlogPost+>>> { blogPostId :: Int+>>> -- ^ Primary key+>>> , authorId :: Int+>>> -- ^ Foreign keys, for which we need an explicit type annotation+>>> , intList :: Vector Int+>>> , title :: Text+>>> , content :: Text+>>> , createdAt :: UTCTime+>>> }+>>> deriving stock (Eq, Generic, Ord, Show)+>>> deriving anyclass (FromRow, ToRow)+>>> deriving+>>> (Entity)+>>> via (GenericEntity '[PrimaryKey "blog_post_id", TableName "blogposts"] BlogPost)+>>> :} -} {- $highlevel@@ -348,7 +377,7 @@ __Examples__ >>> _select @BlogPost- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\""+ "SELECT blogposts.\"blog_post_id\", blogposts.\"author_id\", blogposts.\"int_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\"" @since 0.0.1.0 -}@@ -359,8 +388,8 @@ __Examples__ - >>> _selectWithFields @BlogPost [ [field| blogpost_id |], [field| created_at |] ]- "SELECT \"blogposts\".\"blogpost_id\", \"blogposts\".\"created_at\" FROM \"\"blogposts\"\""+ >>> _selectWithFields @BlogPost [ [field| blog_post_id |], [field| created_at |] ]+ "SELECT \"blogposts\".\"blog_post_id\", \"blogposts\".\"created_at\" FROM \"blogposts\"" @since 0.0.1.0 -}@@ -379,11 +408,11 @@ __Examples__ - >>> _select @BlogPost <> _where [[field| blogpost_id |]]- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"blogpost_id\" = ?"+ >>> _select @BlogPost <> _where [[field| blog_post_id |]]+ "SELECT blogposts.\"blog_post_id\", blogposts.\"author_id\", blogposts.\"int_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"blog_post_id\" = ?" - >>> _select @BlogPost <> _where [ [field| uuid_list |] ]- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"uuid_list\" = ?"+ >>> _select @BlogPost <> _where [ [field| int_list |] ]+ "SELECT blogposts.\"blog_post_id\", blogposts.\"author_id\", blogposts.\"int_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"int_list\" = ?" @since 0.0.1.0 -}@@ -397,10 +426,10 @@ __Examples__ >>> _selectWhere @BlogPost [ [field| author_id |] ]- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"author_id\" = ?"+ "SELECT blogposts.\"blog_post_id\", blogposts.\"author_id\", blogposts.\"int_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"author_id\" = ?" >>> _selectWhere @BlogPost [ [field| author_id |], [field| title |]]- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"author_id\" = ? AND \"title\" = ?"+ "SELECT blogposts.\"blog_post_id\", blogposts.\"author_id\", blogposts.\"int_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"author_id\" = ? AND \"title\" = ?" @since 0.0.1.0 -}@@ -411,7 +440,7 @@ r >>> _selectWhereNotNull @BlogPost [ [field| author_id |] ]- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"author_id\" IS NOT NULL"+ "SELECT blogposts.\"blog_post_id\", blogposts.\"author_id\", blogposts.\"int_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"author_id\" IS NOT NULL" @since 0.0.1.0 -}@@ -421,7 +450,7 @@ {-| Produce a SELECT statement where the provided fields are checked for being null. >>> _selectWhereNull @BlogPost [ [field| author_id |] ]- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"author_id\" IS NULL"+ "SELECT blogposts.\"blog_post_id\", blogposts.\"author_id\", blogposts.\"int_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"author_id\" IS NULL" @since 0.0.1.0 -}@@ -431,7 +460,7 @@ {-| Produce a SELECT statement where the given field is checked aginst the provided array of values . >>> _selectWhereIn @BlogPost [field| title |] [ "Unnamed", "Mordred's Song" ]- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"title\" IN ('Unnamed', 'Mordred''s Song')"+ "SELECT blogposts.\"blog_post_id\", blogposts.\"author_id\", blogposts.\"int_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"title\" IN ('Unnamed', 'Mordred''s Song')" @since 0.0.2.0 -}@@ -443,7 +472,7 @@ __Examples__ >>> _joinSelect @BlogPost @Author- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\", authors.\"author_id\", authors.\"name\", authors.\"created_at\" FROM \"blogposts\" INNER JOIN \"authors\" USING(author_id)"+ "SELECT blogposts.\"blog_post_id\", blogposts.\"author_id\", blogposts.\"int_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\", authors.\"author_id\", authors.\"name\", authors.\"created_at\" FROM \"blogposts\" INNER JOIN \"authors\" USING(author_id)" @since 0.0.1.0 -}@@ -510,7 +539,7 @@ __Examples__ >>> _joinSelectOneByField @BlogPost @Author [field| author_id |] [field| name |] :: Query- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" INNER JOIN \"authors\" ON \"blogposts\".\"author_id\" = \"authors\".\"author_id\" WHERE authors.\"name\" = ?"+ "SELECT blogposts.\"blog_post_id\", blogposts.\"author_id\", blogposts.\"int_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" INNER JOIN \"authors\" ON \"blogposts\".\"author_id\" = \"authors\".\"author_id\" WHERE authors.\"name\" = ?" @since 0.0.2.0 -}@@ -544,7 +573,7 @@ __Examples__ >>> _insert @BlogPost- "INSERT INTO \"blogposts\" (\"blogpost_id\", \"author_id\", \"uuid_list\", \"title\", \"content\", \"created_at\") VALUES (?, ?, ?, ?, ?, ?)"+ "INSERT INTO \"blogposts\" (\"blog_post_id\", \"author_id\", \"int_list\", \"title\", \"content\", \"created_at\") VALUES (?, ?, ?, ?, ?, ?)" @since 0.0.1.0 -}@@ -558,14 +587,14 @@ __Examples__ - >>> _onConflictDoUpdate [[field| blogpost_id |]] [ [field| title |], [field| content |]]- " ON CONFLICT (blogpost_id) DO UPDATE SET title = EXCLUDED.title, content = EXCLUDED.content"+ >>> _onConflictDoUpdate [[field| blog_post_id |]] [ [field| title |], [field| content |]]+ " ON CONFLICT (blog_post_id) DO UPDATE SET title = EXCLUDED.title, content = EXCLUDED.content" - >>> _onConflictDoUpdate [[field| blogpost_id |], [field| author_id |]] [ [field| title |], [field| content |]]- " ON CONFLICT (blogpost_id, author_id) DO UPDATE SET title = EXCLUDED.title, content = EXCLUDED.content"+ >>> _onConflictDoUpdate [[field| blog_post_id |], [field| author_id |]] [ [field| title |], [field| content |]]+ " ON CONFLICT (blog_post_id, author_id) DO UPDATE SET title = EXCLUDED.title, content = EXCLUDED.content" - >>> _insert @BlogPost <> _onConflictDoUpdate [[field| blogpost_id |]] [ [field| title |], [field| content |]]- "INSERT INTO \"blogposts\" (\"blogpost_id\", \"author_id\", \"uuid_list\", \"title\", \"content\", \"created_at\") VALUES (?, ?, ?, ?, ?, ?) ON CONFLICT (blogpost_id) DO UPDATE SET title = EXCLUDED.title, content = EXCLUDED.content"+ >>> _insert @BlogPost <> _onConflictDoUpdate [[field| blog_post_id |]] [ [field| title |], [field| content |]]+ "INSERT INTO \"blogposts\" (\"blog_post_id\", \"author_id\", \"int_list\", \"title\", \"content\", \"created_at\") VALUES (?, ?, ?, ?, ?, ?) ON CONFLICT (blog_post_id) DO UPDATE SET title = EXCLUDED.title, content = EXCLUDED.content" @since 0.0.2.0 -}@@ -586,7 +615,7 @@ "UPDATE \"authors\" SET (\"name\", \"created_at\") = ROW(?, ?) WHERE \"author_id\" = ?" >>> _update @BlogPost- "UPDATE \"blogposts\" SET (\"author_id\", \"uuid_list\", \"title\", \"content\", \"created_at\") = ROW(?, ?, ?, ?, ?) WHERE \"blogpost_id\" = ?"+ "UPDATE \"blogposts\" SET (\"author_id\", \"int_list\", \"title\", \"content\", \"created_at\") = ROW(?, ?, ?, ?, ?) WHERE \"blog_post_id\" = ?" @since 0.0.1.0 -}@@ -655,7 +684,7 @@ __Examples__ >>> _delete @BlogPost- "DELETE FROM \"blogposts\" WHERE \"blogpost_id\" = ?"+ "DELETE FROM \"blogposts\" WHERE \"blog_post_id\" = ?" @since 0.0.1.0 -}
src/Database/PostgreSQL/Entity/Internal.hs view
@@ -53,14 +53,63 @@ import Database.PostgreSQL.Entity.Types {- $setup- >>> :set -XQuasiQuotes- >>> :set -XOverloadedLists- >>> :set -XTypeApplications- >>> import Database.PostgreSQL.Entity- >>> import Database.PostgreSQL.Entity.Types- >>> import Database.PostgreSQL.Entity.Internal.BlogPost- >>> import Database.PostgreSQL.Entity.Internal.QQ- >>> import Database.PostgreSQL.Entity.Internal.Unsafe+>>> :set -XQuasiQuotes+>>> :set -XOverloadedStrings+>>> :set -XOverloadedLists+>>> :set -XTypeApplications+>>> import Database.PostgreSQL.Entity+>>> import Database.PostgreSQL.Simple.FromRow (FromRow(..))+>>> import Database.PostgreSQL.Simple.ToRow+>>> import Database.PostgreSQL.Entity.Types+>>> import Database.PostgreSQL.Entity.Internal+>>> import Database.PostgreSQL.Entity.Internal.QQ+>>> import Database.PostgreSQL.Simple.Types (Query (..))+>>> import Data.Vector (Vector)+>>> import qualified Data.Vector as V+>>> import Data.Time (UTCTime)+>>> import GHC.Generics (Generic)+>>> :{+>>> data Author = Author+>>> { authorId :: Int+>>> , name :: Text+>>> , createdAt :: UTCTime+>>> }+>>> deriving stock (Eq, Generic, Ord, Show)+>>> deriving anyclass (FromRow, ToRow)+>>> deriving+>>> (Entity)+>>> via (GenericEntity '[PrimaryKey "author_id", TableName "authors"] Author)+>>>+>>> data BlogPost = BlogPost+>>> { blogPostId :: Int+>>> -- ^ Primary key+>>> , authorId :: Int+>>> -- ^ Foreign keys, for which we need an explicit type annotation+>>> , intList :: Vector Int+>>> , title :: Text+>>> , content :: Text+>>> , createdAt :: UTCTime+>>> }+>>> deriving stock (Eq, Generic, Ord, Show)+>>> deriving anyclass (FromRow, ToRow)+>>> deriving+>>> (Entity)+>>> via (GenericEntity '[PrimaryKey "blog_post_id", TableName "blogposts"] BlogPost)+>>>+>>> data Tags = Tags+>>> { category :: Text+>>> , labels :: [Text]+>>> }+>>>+>>> instance Entity Tags where+>>> tableName = "tags"+>>> schema = Just "public"+>>> primaryKey = [field| category |]+>>> fields =+>>> [ [field| category |]+>>> , [field| labels |]+>>> ]+>>> :} -} {-| Wrap the given text between parentheses@@ -147,7 +196,7 @@ __Examples__ >>> expandFields @BlogPost- "\"blogpost_id\", \"author_id\", \"uuid_list\", \"title\", \"content\", \"created_at\""+ "\"blog_post_id\", \"author_id\", \"int_list\", \"title\", \"content\", \"created_at\"" @since 0.0.1.0 -}@@ -159,7 +208,7 @@ __Examples__ >>> expandQualifiedFields @BlogPost- "blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\""+ "blogposts.\"blog_post_id\", blogposts.\"author_id\", blogposts.\"int_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\"" @since 0.0.1.0 -}@@ -173,7 +222,7 @@ __Examples__ >>> expandQualifiedFields' (fields @BlogPost) "legacy"- "legacy.\"blogpost_id\", legacy.\"author_id\", legacy.\"uuid_list\", legacy.\"title\", legacy.\"content\", legacy.\"created_at\""+ "legacy.\"blog_post_id\", legacy.\"author_id\", legacy.\"int_list\", legacy.\"title\", legacy.\"content\", legacy.\"created_at\"" @since 0.0.1.0 -}@@ -203,7 +252,7 @@ __Examples__ >>> qualifyFields "legacy" (fields @BlogPost)- [Field "legacy.\"blogpost_id\"" Nothing,Field "legacy.\"author_id\"" Nothing,Field "legacy.\"uuid_list\"" Nothing,Field "legacy.\"title\"" Nothing,Field "legacy.\"content\"" Nothing,Field "legacy.\"created_at\"" Nothing]+ [Field "legacy.\"blog_post_id\"" Nothing,Field "legacy.\"author_id\"" Nothing,Field "legacy.\"int_list\"" Nothing,Field "legacy.\"title\"" Nothing,Field "legacy.\"content\"" Nothing,Field "legacy.\"created_at\"" Nothing] @since 0.0.1.0 -}@@ -221,7 +270,7 @@ "\"ids\" = ?" >>> fmap placeholder $ fields @BlogPost- ["\"blogpost_id\" = ?","\"author_id\" = ?","\"uuid_list\" = ?","\"title\" = ?","\"content\" = ?","\"created_at\" = ?"]+ ["\"blog_post_id\" = ?","\"author_id\" = ?","\"int_list\" = ?","\"title\" = ?","\"content\" = ?","\"created_at\" = ?"] @since 0.0.1.0 -}@@ -293,13 +342,20 @@ fieldNames = fmap fieldName fs' process f = quoteName f <> " IS NULL" +{-| Produce an "IS (<value1>, <value2>, …, <valueN>)" clause++>>> isIn [field| colour |] [ "yellow", "blue", "magenta" ]+"\"colour\" IN ('yellow', 'blue', 'magenta')"++@since 0.0.2.0+-} isIn :: Field -> Vector Text -> Text isIn f values = process f <> " IN (" <> fold (intercalateVector ", " vals) <> ")" where vals = fmap literal values process f' = quoteName $ fieldName f' -{-| Since the 'Query' type has an 'IsString' instance, the process of converting from 'Text' to 'String' to 'Query' is+{-| Since the 'Query' type has an 'Data.String.IsString' instance, the process of converting from 'Text' to 'String' to 'Query' is factored into this function ⚠ This may be dangerous and an unregulated usage of this function may expose to you SQL injection attacks
src/Database/PostgreSQL/Entity/Internal/QQ.hs view
@@ -27,8 +27,8 @@ > instance Entity BlogPost where > tableName = "blogposts"- > primaryKey = [field| blogpost_id |]- > fields = [ [field| blogpost_id |]+ > primaryKey = [field| blog_post_id |]+ > fields = [ [field| blog_post_id |] > , [field| author_id |] > , [field| uuid_list :: uuid[] |] -- ← This is where we specify an optional PostgreSQL type annotation > , [field| title |]
test/EntitySpec.hs view
@@ -39,10 +39,12 @@ import Database.PostgreSQL.Simple (Only (Only)) import Database.PostgreSQL.Transact (DBT) +import qualified Data.Map as Map import Data.Maybe (fromJust) import qualified Data.Set as S import qualified Data.Set as Set import Data.Vector (Vector)+import qualified Data.Vector as Vector import Database.PostgreSQL.Entity.Types import Optics.Core import Test.Tasty@@ -132,7 +134,11 @@ _joinSelectWithFields @BlogPost @Author [[field| title |]] [[field| name |]] <> _where [[field| name |]] result <- liftDB (query Select q (Only ("Hansi Kürsch" :: Text)) :: MonadIO m => DBT m (Vector (Text, Text)))- U.assertEqual [("The Script for my requiem", "Hansi Kürsch"), ("Mordred's Song", "Hansi Kürsch")] result+ let actualMap = Map.fromList $ Vector.toList result+ let expectedMap = Map.fromList [("The Script for my requiem", "Hansi Kürsch"), ("Mordred's Song", "Hansi Kürsch")]+ U.assertEqual+ expectedMap+ actualMap changeAuthorName :: TestM () changeAuthorName = do
test/Utils.hs view
@@ -4,6 +4,7 @@ module Utils where import Control.Exception.Safe+import Control.Monad (void) import Control.Monad.IO.Class import Control.Monad.Reader import Data.ByteString (ByteString)