- Removed
nullaryFunction
. Insteadfunction
can be called with()
. (#258)
-
Support PostgreSQL's
inet
type (which maps to the HaskellNetAddr IP
type). (#227) -
Rel8.materialize
andRel8.Tabulate.materialize
, which add a materialization/optimisation fence toSELECT
statements by binding a query to aWITH
subquery. Note that explicitly materialized common table expressions are only supported in PostgreSQL 12 an higher. (#180) (#284) -
Rel8.head
,Rel8.headExpr
,Rel8.last
,Rel8.lastExpr
for accessing the first/last elements ofListTable
s and arrays. We have also added variants forNonEmptyTable
s/non-empty arrays with the1
suffix (e.g.,head1
). (#245) -
Rel8 now has extensive support for
WITH
statements and data-modifying statements (https://www.postgresql.org/docs/current/queries-with.html#QUERIES-WITH-MODIFYING).This work offers a lot of new power to Rel8. One new possibility is "moving" rows between tables, for example to archive rows in one table into a log table:
import Rel8 archive :: Statement () archive = do deleted <- delete Delete { from = mainTable , using = pure () , deleteWhere = \foo -> fooId foo ==. lit 123 , returning = Returning id } insert Insert { into = archiveTable , rows = deleted , onConflict = DoNothing , returning = NoReturninvg }
This
Statement
will compile to a single SQL statement - essentially:WITH deleted_rows (DELETE FROM main_table WHERE id = 123 RETURNING *) INSERT INTO archive_table SELECT * FROM deleted_rows
This feature is a significant performant improvement, as it avoids an entire roundtrip.
This change has necessitated a change to how a
SELECT
statement is ran:select
now will now produce aRel8.Statement
, which you have torun
to turn it into a HasqlStatement
. Rel8 offers a variety ofrun
functions depending on how many rows need to be returned - see the various family ofrun
functions in Rel8's documentation for more. -
Rel8.loop
andRel8.loopDistinct
, which allow writingWITH .. RECURSIVE
queries. (#180) -
Added the
QualifiedName
type for named PostgreSQL objects (tables, views, functions, operators, sequences, etc.) that can optionally be qualified by a schema, including anIsString
instance. (#257) (#263) -
Added
queryFunction
forSELECT
ing from table-returning functions such asjsonb_to_recordset
. (#241) -
TypeName
record, which gives a richer representation of the components of a PostgreSQL type name (name, schema, modifiers, scalar/array). (#263) -
Rel8.length
andRel8.lengthExpr
for getting the lengthListTable
s and arrays. We have also added variants forNonEmptyTable
s/non-empty arrays with the1
suffix (e.g.,length1
). (#268) -
Added aggregators
listCat
andnonEmptyCat
for folding a collection of lists into a single list by concatenation. (#270) -
DBType
instance forFixed
that would map (e.g.)Micro
tonumeric(1000, 6)
andPico
tonumeric(1000, 12)
. (#280) -
aggregationFunction
, which allows custom aggregation functions to be used. (#283) -
Add support for ordered-set aggregation functions, including
mode
,percentile
,percentileContinuous
,hypotheticalRank
,hypotheticalDenseRank
,hypotheticalPercentRank
andhypotheticalCumeDist
. (#282) -
Added
index
,index1
,indexExpr
, andindex1Expr
functions for extracting individual elements fromListTable
s andNonEmptyTable
s. (#285) -
Rel8 now supports GHC 9.8. (#299)
-
Rel8's API regarding aggregation has changed significantly, and is now a closer match to Opaleye.
The previous aggregation API had
aggregate
transform aTable
from theAggregate
context back into theExpr
context:myQuery = aggregate do a <- each tableA return $ liftF2 (,) (sum (foo a)) (countDistinct (bar a))
This API seemed convenient, but has some significant shortcomings. The new API requires an explicit
Aggregator
be passed toaggregate
:myQuery = aggregate (liftA2 (,) (sumOn foo) (countDistinctOn bar)) do each tableA
For more details, see #235
-
TypeInformation
'sdecoder
field has changed. Instead of taking aHasql.Decoder
, it now takes aRel8.Decoder
, which itself is comprised of aHasql.Decoder
and anattoparsec
Parser
. This is necessitated by the fix for #168; we generally decode things in PostgreSQL's binary format (using aHasql.Decoder
), but for nested arrays we now get things in PostgreSQL's text format (for which we need anattoparsec
Parser
), so must have both. MostDBType
instances that usemapTypeInformation
orParseTypeInformation
, orDerivingVia
helpers likeReadShow
,JSONBEncoded
,Enum
andComposite
are unaffected by this change. (#243) -
The
schema
field fromTableSchema
has been removed and the name field changed fromString
toQualifiedName
. (#257) -
nextval
,function
andbinaryOperator
now take aQualifiedName
instead of aString
. (#262) -
function
has been changed to accept a single argument (as opposed to variadic arguments). (#258) -
TypeInformation
'stypeName
parameter fromString
toTypeName
. (#263) -
DBEnum
'senumTypeName
method fromString
toQualifiedName
. (#263) -
DBComposite
'scompositeTypeName
method fromString
toQualifiedName
. (#263) -
Changed
Upsert
by adding apredicate
field, which allows partial indexes to be specified as conflict targets. (#264) -
The window functions
lag
,lead
,firstValue
,lastValue
andnthValue
can now operate on entire rows at once as opposed to just single columns. (#281)
-
Fixed a bug with
catListTable
andcatNonEmptyTable
where invalid SQL could be produced. (#240) -
A fix for #168, which prevented using
catListTable
on arrays of arrays. To achieve this we had to coerce arrays of arrays to text internally, which unfortunately isn't completely transparent; you can oberve it if you write something likelistTable [listTable [10]] > listTable [listTable [9]]
: previously that would befalse
, but now it'strue
. Arrays of non-arrays are unaffected by this. -
Fixes #228 where it was impossible to call
nextval
with a qualified sequence name. -
Fixes #71.
-
Fixed a typo in the documentation for
/=.
. (#312) -
Fixed a bug where
fromRational
could crash with repeating fractions. (#309) -
Fixed a typo in the documentation for
min
. (#306)
- Rel8 now supports window functions. See the "Window functions" section of the
Rel8
module documentation for more details. (#182) Query
now hasMonoid
andSemigroup
instances. (#207)createOrReplaceView
has been added (to runCREATE OR REPLACE VIEW
). (#209 and #212)deriving Rel8able
now supports more polymorphism. (#215)- Support GHC 9.4 (#199)
- Insertion of
DEFAULT
values has been fixed. (#206) - Avoid some exponential SQL generation in
Rel8.Tabulate.alignWith
. (#213) nextVal
has been fixed to work with case-sensitive sequence names. (#217)
- Correct the documentation for "Supplying
Rel8able
instances" (#200) - Removed some redundant internal code (#202)
- Rel8 is now less dependant on the internal Opaleye API. (#204)
- The behavior of
greatest
/least
has been corrected, and was previously flipped. (#183)
NullTable
/HNull
have been added. This is an alternative toMaybeTable
that doesn't use a tag columns. It's less flexible (noFunctor
orApplicative
instance) and is meaningless when used with a table that has no non-nullable columns (so nestingNullTable
is redundant). But in situations where the underlyingTable
does have non-nullable columns, it can losslessly converted to and fromMaybeTable
. It is useful for embedding into a base table when you don't want to store the extra tag column in your schema. (#173)- Add
fromMaybeTable
. (#179) - Add
alignMaybeTable
. (#196)
- Optimize implementation of
AltTable
forTabulation
(#178)
- Documentation improvements for
HADT
. (#177) - Document example usage of
groupBy
. (#184) - Build with and require Opaleye >= 0.9.3.3. (#190)
- Build with
hasql
1.6. (#195)
- Rel8 now requires Opaleye >= 0.9.1. (#165)
div
andmod
have been changed to match Haskell semantics. If you need the PostgreSQLdiv()
andmod()
functions, usequot
andrem
. While this is not an API change, we feel this is a breaking change in semantics and have bumped the major version number. (#155)
divMod
andquotRem
functions have been added, matching Haskell'sPrelude
functions. (#155)avg
andmode
aggregation functions to find the mean value of an expression, or the most common row in a query, respectively. (#152)- The full
EqTable
andOrdTable
classes have been exported, allowing for instances to be manually created. (#157) - Added
like
andilike
(for theLIKE
andILIKE
operators). (#146)
- Rel8 now requires Opaleye 0.9. (#158)
- Rel8's test suite supports Hedgehog 1.1. (#160)
- The documentation for binary operations has been corrected. (#162)
-
castTable
has been added, which casts all columns selected from inQuery
according to the types of columns. This can occasionally be useful when usingmany
/some
on older PostgreSQL versions. (#137) -
Added
<:
,<=:
,>:
,>=:
,greatest
andleast
, which sort all columns in a table lexicographically. These operators are like the<.
operators which operate onExpr
s, but the<:
operate on entire tables. (#139)
- Support opaleye-0.8 (#142)
- New
$*
and$+
operators for projecting out ofListTable
andNonEmptyTable
respectively (analogous to the existing$?
forMaybeTable
). (#125)
-
Fix
UPSERT
support (and add tests), which was broken due to a typo inside Rel8 that made it impossible to constructProjection
s which are needed byUPSERT
. (#134) -
Remove
DBMin
andDBMax
instances forBool
, which are invalid as far as Postgres is concerned.and
andor
can be used to achieve the same thing. (#126) -
Fix
aggregateMaybeTable
,aggregateEitherTable
andaggregateTheseTable
, which generated invalid SQL previously. (#127)
rebind
now takes an additional argument for the "name" of the binding. (#128)
-
You can derive
Rel8able
for "vanilla" higher-kinded data types - data types that don't use theColumn
type family. For example, the following is now possible:data MyTable f = MyTable { myTableX :: f Int32 , myTableY :: f Text } deriving (Generic, Rel8able)
-
The
Projectable
andBiprojectable
type classes have been introduced. These classes model a type of functors and bifunctors (respectively) on tables, where the mapping function is only able to rearrange columns. For example, the following is now possible:x <- project myTableX <$> many ...
-
Insert
'sonConflict
field now has a new option -DoUpdate
. This maps to PostgreSQL'sON CONFLICT DO UPDATE
syntax, which provides upsert support. (#85) -
Insert
,Update
andDelete
has all been expanded to work withQuery
s. In particular:Delete
now supports aUSING
sub-queryUpdate
now supports aFROM
sub-queryInsert
can delete the result of any arbitraryQuery
(providing the types match)
-
The new
Rel8.Tabulate
module has been added, which gives aMap
-esque interface to writing and composing queries. (#70) -
The new
indexed
Query -> Query
function was added. This function augments each row in a query with it's 0-based index. (#117)
-
Insert
,Delete
andUpdate
have all changed. In particular, forInsert
users should now replacerows = xs
withrows = values xs
. (#85) -
Rename
whereExists
andwhereNotExists
topresent
andabsent
respectively. (#57) -
Simplify
evaluate
to run directly inside theQuery
monad, rendering theEvaluate
monad unnecessary. (#56) -
The
Labelable
type class has been removed as it's no longer necessary. This class was mostly internal, though was visible in some public API functions. (#76) -
EitherTable
,ListTable
,MaybeTable
,NonEmptyTable
andTheseTable
now all have an extra parameter which tracks the context of the table. If you manually specified any types before, you need to provide this parameter - usuallyExpr
will be the correct choice. (#101) -
We've done a lot of work to simplify the internals of Rel8, but some of these are breaking changes. However, most of these API changes shouldn't affect users as they are mostly types used in type inference, or affect classes where users don't need to define their own instances.
- The kind of a
Rel8able
is now(Type -> Type) -> Type
. Previously it was(X -> Type) -> Type
. Table
has a new associated type -FromExprs
. This was previously an open type family.Table
has a new associated type -Transpose
- andRecontextualise
has been renamed toTransposes
. ThisTransposes
class now operates in terms ofTranspose
.
- The kind of a
-
select
,insert
,update
anddelete
now produce HasqlStatement
s, rather than actually running the statement as IO. This allows Rel8 to be used with transaction/connection-managing monads likehasql-transaction
. (#94)
-
Fixes a bug where cartesian products of queries using
catListTable
,catNonEmptyTable
,catList
andcatNonEmpty
would incorrectly be zipped instead. (#61) -
Require Opaleye 0.7.3.0. This version has better support for lateral queries, which can improve query plans, especially in
optional
/LEFT JOIN
(#72) -
Rel8 now compiles with GHC 9. (#97)
-
exists
is now implemented in terms of the SQLEXISTS
keyword. (#69) -
alignBy
no longer requiresTable
s. (#67)
This release contains various fixes for documentation.
- Initial release.