packages feed

beam-duckdb 0.1.0.0 → 0.1.1.0

raw patch · 6 files changed

+72/−30 lines, 6 filesdep +scientificPVP ok

version bump matches the API change (PVP)

Dependencies added: scientific

API changes (from Hackage documentation)

+ Database.Beam.DuckDB: runBeamDuckDBDebugString :: (String -> IO ()) -> Connection -> DuckDBM a -> IO a

Files

CHANGELOG.md view
@@ -1,5 +1,10 @@ # Revision history for beam-duckdb +## 0.1.1.0 -- unreleased++* Fixed an issue with modeling boolean conditions, whereby, for example, checking if something was true was modeled as `... IS 1` (as for Sqlite), rather than `... IS TRUE` (like Postgres).+* Added a `FromBackendRow DuckDB Scientific`, `HasSqlEqualityCheck DuckDB Scientific`, and `HasSqlQuantifiedEqualityCheck DuckDB Scientific` instances, which are required to build the documentation.+ ## 0.1.0.0 -- 2026-02-26  * First version. Released on an unsuspecting world.
README.md view
@@ -10,3 +10,16 @@  `beam-duckdb` is the most recent backend for beam; do not hesitate to raise an issue if you'd like us to add support for something that isn't currently covered!++## Installation++The underlying duckdb-ffi needs to link to libduckdb. By default the installation assumes:++* The duckdb files are in `/usr/lib/duckdb`+* You're using duckdb 1.4.*++For Linux you can install a blessed version of duckdb in the correct path by cloining the duckdb-hasekll repo and running `make install` in the [duckdb-ffi cbits folder](https://github.com/Tritlo/duckdb-haskell/tree/main/duckdb-ffi/cbits).++## Example++From the project root directory, execute `cabal run ./examples/ExamScores.hs`.
beam-duckdb.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.0 name:               beam-duckdb-version:            0.1.0.0+version:            0.1.1.0 synopsis:           DuckDB backend for Beam description:        Beam driver for DuckDB, an analytics-focused open-source in-process database. license:            MIT@@ -44,6 +44,7 @@                     , duckdb-simple ^>=0.1                     , dlist >=0.8 && <1.1                     , free >=4.12 && <5.3+                    , scientific ^>=0.3                     , text >=1.0 && <2.2                     , time >=1.6 && <1.16                     , transformers >=0.3 && <0.7
src/Database/Beam/DuckDB.hs view
@@ -20,7 +20,9 @@ module Database.Beam.DuckDB   ( -- * Executing DuckDB queries     runBeamDuckDB,+    -- ** Executing DuckDB queries with debugging     runBeamDuckDBDebug,+    runBeamDuckDBDebugString,      -- * Backend datatype     DuckDB,@@ -108,6 +110,12 @@ runBeamDuckDBDebug :: (Text -> IO ()) -> Connection -> DuckDBM a -> IO a runBeamDuckDBDebug debug conn action =   runReaderT (runDuckDBM action) (debug, conn)++-- | Like 'runBeamDuckDBDebug', but accepts a 'String' argument instead of 'Text'.+--+-- This is provided for compatibility with other backends+runBeamDuckDBDebugString :: (String -> IO ()) -> Connection -> DuckDBM a -> IO a+runBeamDuckDBDebugString debug = runBeamDuckDBDebug (debug . Text.unpack)  newtype BeamDuckDBParams = BeamDuckDBParams [SomeField] 
src/Database/Beam/DuckDB/Backend.hs view
@@ -3,6 +3,7 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedRecordDot #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-}@@ -12,36 +13,37 @@  import Data.ByteString (ByteString) import Data.Data (Proxy (Proxy))-import Data.Functor (($>))+import Data.Functor (($>), (<&>)) import Data.Int (Int16, Int32, Int64, Int8)+import Data.Scientific (Scientific, scientific) import Data.Text (Text) import Data.Time (Day, LocalTime, TimeOfDay, UTCTime) import Data.UUID.Types (UUID) import Data.Word (Word16, Word32, Word64, Word8) import Database.Beam (HasQBuilder, HasSqlEqualityCheck, HasSqlInTable (..), HasSqlQuantifiedEqualityCheck)-import Database.Beam.Backend (-    BeamBackend (..),+import Database.Beam.Backend+  ( BeamBackend (..),     BeamSqlBackend,     BeamSqlBackendIsString,     BeamSqlBackendSyntax,     FromBackendRow,     SqlNull (..),     parseOneField,- )+  ) import Database.Beam.Backend.SQL (FromBackendRow (..))-import Database.Beam.DuckDB.Syntax (-    DuckDBCommandSyntax,+import Database.Beam.DuckDB.Syntax+  ( DuckDBCommandSyntax,     DuckDBExpressionSyntax (..),- )-import Database.Beam.DuckDB.Syntax.Builder (-    commas,+  )+import Database.Beam.DuckDB.Syntax.Builder+  ( commas,     emit,     parens,- )+  ) import Database.Beam.Query.SQL92 (buildSql92Query') import Database.Beam.Query.Types (HasQBuilder (..)) import Database.DuckDB.Simple (Null)-import Database.DuckDB.Simple.FromField (FromField)+import Database.DuckDB.Simple.FromField (DecimalValue (..), FromField)  data DuckDB @@ -50,26 +52,26 @@ instance BeamSqlBackend DuckDB  instance HasQBuilder DuckDB where-    buildSqlQuery = buildSql92Query' True+  buildSqlQuery = buildSql92Query' True  instance HasSqlInTable DuckDB where-    inRowValuesE Proxy e es =-        DuckDBExpressionSyntax $-            mconcat-                [ parens $ fromDuckDBExpression e-                , emit " IN "-                , parens $ emit "VALUES " <> commas (map fromDuckDBExpression es)-                ]+  inRowValuesE Proxy e es =+    DuckDBExpressionSyntax $+      mconcat+        [ parens $ fromDuckDBExpression e,+          emit " IN ",+          parens $ emit "VALUES " <> commas (map fromDuckDBExpression es)+        ]  instance BeamSqlBackendIsString DuckDB Text  instance BeamSqlBackendIsString DuckDB String  instance BeamBackend DuckDB where-    type BackendFromField DuckDB = FromField+  type BackendFromField DuckDB = FromField  instance FromBackendRow DuckDB SqlNull where-    fromBackendRow = parseOneField @DuckDB @Null $> SqlNull+  fromBackendRow = parseOneField @DuckDB @Null $> SqlNull  instance FromBackendRow DuckDB Bool @@ -113,6 +115,17 @@  instance FromBackendRow DuckDB UTCTime +instance FromBackendRow DuckDB Scientific where+  fromBackendRow =+    parseOneField @DuckDB @DecimalValue+      <&> decimalToScientific++decimalToScientific :: DecimalValue -> Scientific+decimalToScientific decimalValue =+  scientific+    decimalValue.decimalInteger+    (negate (fromIntegral decimalValue.decimalScale))+ instance HasSqlEqualityCheck DuckDB Bool  instance HasSqlEqualityCheck DuckDB Float@@ -155,6 +168,8 @@  instance HasSqlEqualityCheck DuckDB UTCTime +instance HasSqlEqualityCheck DuckDB Scientific+ instance HasSqlQuantifiedEqualityCheck DuckDB Bool  instance HasSqlQuantifiedEqualityCheck DuckDB Float@@ -196,3 +211,5 @@ instance HasSqlQuantifiedEqualityCheck DuckDB LocalTime  instance HasSqlQuantifiedEqualityCheck DuckDB UTCTime++instance HasSqlQuantifiedEqualityCheck DuckDB Scientific
src/Database/Beam/DuckDB/Syntax.hs view
@@ -399,14 +399,12 @@    isNotNullE = postFix "IS NOT NULL"   isNullE = postFix "IS NULL"--  -- SQLite doesn't handle tri-state booleans properly-  isTrueE = postFix "IS 1"-  isNotTrueE = postFix "IS NOT 1"-  isFalseE = postFix "IS 0"-  isNotFalseE = postFix "IS NOT 0"-  isUnknownE = postFix "IS NULL"-  isNotUnknownE = postFix "IS NOT NULL"+  isTrueE = postFix "IS TRUE"+  isFalseE = postFix "IS FALSE"+  isNotTrueE = postFix "IS NOT TRUE"+  isNotFalseE = postFix "IS NOT FALSE"+  isUnknownE = postFix "IS UNKNOWN"+  isNotUnknownE = postFix "IS NOT UNKNOWN"    existsE select = DuckDBExpressionSyntax (emit "EXISTS " <> parens (fromDuckDBSelect select))   uniqueE select = DuckDBExpressionSyntax (emit "UNIQUE " <> parens (fromDuckDBSelect select))