Skip to content

1.5.0.0

Latest
Compare
Choose a tag to compare
@ocharles ocharles released this 02 May 07:18
· 16 commits to master since this release
4c18447

Removed

  • Removed nullaryFunction. Instead function can be called with (). (#258)

Added

  • Support PostgreSQL's inet type (which maps to the Haskell NetAddr IP type). (#227)

  • Rel8.materialize and Rel8.Tabulate.materialize, which add a materialization/optimisation fence to SELECT statements by binding a query to a WITH 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 of ListTables and arrays. We have also added variants for NonEmptyTables/non-empty arrays with the 1 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 a Rel8.Statement, which you have to run to turn it into a Hasql Statement. Rel8 offers a variety of run functions depending on how many rows need to be returned - see the various family of run functions in Rel8's documentation for more.

    #250

  • Rel8.loop and Rel8.loopDistinct, which allow writing WITH .. 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 an IsString instance. (#257) (#263)

  • Added queryFunction for SELECTing from table-returning functions such as jsonb_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 and Rel8.lengthExpr for getting the length ListTables and arrays. We have also added variants for NonEmptyTables/non-empty arrays with the 1 suffix (e.g., length1). (#268)

  • Added aggregators listCat and nonEmptyCat for folding a collection of lists into a single list by concatenation. (#270)

  • DBType instance for Fixed that would map (e.g.) Micro to numeric(1000, 6) and Pico to numeric(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 and hypotheticalCumeDist. (#282)

  • Added index, index1, indexExpr, and index1Expr functions for extracting individual elements from ListTables and NonEmptyTables. (#285)

  • Rel8 now supports GHC 9.8. (#299)

Changed

  • Rel8's API regarding aggregation has changed significantly, and is now a closer match to Opaleye.

    The previous aggregation API had aggregate transform a Table from the Aggregate context back into the Expr 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 to aggregate:

    myQuery = aggregate (liftA2 (,) (sumOn foo) (countDistinctOn bar)) do
      each tableA

    For more details, see #235

  • TypeInformation's decoder field has changed. Instead of taking a Hasql.Decoder, it now takes a Rel8.Decoder, which itself is comprised of a Hasql.Decoder and an attoparsec Parser. This is necessitated by the fix for #168; we generally decode things in PostgreSQL's binary format (using a Hasql.Decoder), but for nested arrays we now get things in PostgreSQL's text format (for which we need an attoparsec Parser), so must have both. Most DBType instances that use mapTypeInformation or ParseTypeInformation, or DerivingVia helpers like ReadShow, JSONBEncoded, Enum and Composite are unaffected by this change. (#243)

  • The schema field from TableSchema has been removed and the name field changed from String to QualifiedName. (#257)

  • nextval, function and binaryOperator now take a QualifiedName instead of a String. (#262)

  • function has been changed to accept a single argument (as opposed to variadic arguments). (#258)

  • TypeInformation's typeName parameter from String to TypeName. (#263)

  • DBEnum's enumTypeName method from String to QualifiedName. (#263)

  • DBComposite's compositeTypeName method from String to QualifiedName. (#263)

  • Changed Upsert by adding a predicate field, which allows partial indexes to be specified as conflict targets. (#264)

  • The window functions lag, lead, firstValue, lastValue and nthValue can now operate on entire rows at once as opposed to just single columns. (#281)

Fixed

  • Fixed a bug with catListTable and catNonEmptyTable 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 like listTable [listTable [10]] > listTable [listTable [9]]: previously that would be false, but now it's true. 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)