beam
beam copied to clipboard
DEFAULT can appear in arbitrary expressions
DEFAULT should only be able to appear in the VALUES clause of an INSERT INTO statement, not in any arbitrary expresion.
I believe I've run into this recently. Put together a simple test case:
diff --git a/beam-postgres/beam-postgres.cabal b/beam-postgres/beam-postgres.cabal
index 132ade3..866cf71 100644
--- a/beam-postgres/beam-postgres.cabal
+++ b/beam-postgres/beam-postgres.cabal
@@ -74,6 +74,7 @@ test-suite beam-postgres-tests
hs-source-dirs: test
main-is: Main.hs
other-modules: Database.Beam.Postgres.Test,
+ Database.Beam.Postgres.Test.Insert,
Database.Beam.Postgres.Test.Marshal,
Database.Beam.Postgres.Test.Select,
Database.Beam.Postgres.Test.DataTypes,
diff --git a/beam-postgres/test/Database/Beam/Postgres/Test/Insert.hs b/beam-postgres/test/Database/Beam/Postgres/Test/Insert.hs
new file mode 100644
index 0000000..84e001d
--- /dev/null
+++ b/beam-postgres/test/Database/Beam/Postgres/Test/Insert.hs
@@ -0,0 +1,94 @@
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE StandaloneDeriving #-}
+
+module Database.Beam.Postgres.Test.Insert (tests) where
+
+import Data.Aeson
+import Data.ByteString (ByteString)
+import Data.Int
+import Data.Int (Int32)
+import Data.Text (Text)
+import Data.UUID (UUID, nil)
+import qualified Data.UUID.V5 as V5
+import qualified Data.Vector as V
+import Database.Beam
+import Database.Beam.Backend.SQL.BeamExtensions
+import Database.Beam.Backend.SQL.SQL92
+import Database.Beam.Migrate
+import Database.Beam.Postgres
+import Database.Beam.Postgres.Extensions.UuidOssp
+import Database.Beam.Postgres.Test
+import Database.PostgreSQL.Simple (execute_)
+import System.IO (IOMode (..), hPutStrLn, openFile)
+import Test.Tasty
+import Test.Tasty.HUnit
+
+tests :: IO ByteString -> TestTree
+tests getConn =
+ testGroup
+ "Insertion tests"
+ [ testInsertFromWithDefault getConn
+ ]
+
+data TestTableT f = TestTable
+ { ttId :: C f Int32,
+ ttFirstName :: C f Text,
+ ttLastName :: C f Text,
+ ttAge :: C f Int32
+ }
+ deriving (Generic, Beamable)
+
+deriving instance Show (TestTableT Identity)
+
+deriving instance Eq (TestTableT Identity)
+
+instance Table TestTableT where
+ data PrimaryKey TestTableT f = TestTableKey (C f Int32)
+ deriving (Generic, Beamable)
+ primaryKey = TestTableKey <$> ttId
+
+data TestTableDb entity = TestTableDb
+ { dbTestTable :: entity (TableEntity TestTableT)
+ }
+ deriving (Generic, Database Postgres)
+
+testDatabase :: DatabaseSettings be TestTableDb
+testDatabase = defaultDbSettings
+
+testInsertFromWithDefault :: IO ByteString -> TestTree
+testInsertFromWithDefault getConn =
+ testFunction getConn "insert_from_with_default" $ \conn -> do
+ execute_
+ conn
+ "CREATE TABLE test_table (\
+ \ id SERIAL,\
+ \ first_name TEXT NOT NULL,\
+ \ last_name TEXT NOT NULL,\
+ \ age INT NOT NULL\
+ \)"
+ inserted <-
+ runBeamPostgres conn $
+ runInsertReturningList $
+ insert (dbTestTable testDatabase) $
+ insertFrom $
+ pure $
+ TestTable
+ { ttId = default_,
+ ttFirstName = val_ "John",
+ ttLastName = val_ "Doe",
+ ttAge = val_ 99
+ }
+ let expected =
+ [ TestTable
+ { ttId = 1,
+ ttFirstName = "John",
+ ttLastName = "Doe",
+ ttAge = 99
+ }
+ ]
+ assertEqual "inserted value" inserted expected
+
+testFunction :: IO ByteString -> String -> (Connection -> Assertion) -> TestTree
+testFunction getConn name mkAssertion =
+ testCase name $
+ withTestPostgres name getConn mkAssertion
diff --git a/beam-postgres/test/Main.hs b/beam-postgres/test/Main.hs
index a6187ae..da3d5cd 100644
--- a/beam-postgres/test/Main.hs
+++ b/beam-postgres/test/Main.hs
@@ -3,6 +3,7 @@ module Main where
import qualified Database.Postgres.Temp as TempDb
import Test.Tasty
+import qualified Database.Beam.Postgres.Test.Insert as Insert
import qualified Database.Beam.Postgres.Test.Select as Select
import qualified Database.Beam.Postgres.Test.Marshal as Marshal
import qualified Database.Beam.Postgres.Test.DataTypes as DataType
@@ -12,7 +13,8 @@ main :: IO ()
main = defaultMain $ withDb $ \getDb ->
let getConnStr = TempDb.toConnectionString <$> getDb
in testGroup "beam-postgres tests"
- [ Marshal.tests getConnStr
+ [ Insert.tests getConnStr
+ , Marshal.tests getConnStr
, Select.tests getConnStr
, DataType.tests getConnStr
, Migrate.tests getConnStr
The generated SQL is
INSERT INTO "test_table"("id", "first_name", "last_name", "age")
SELECT DEFAULT AS "res0", 'John' AS "res1", 'Doe' AS "res2", 99 AS "res3"
RETURNING "id", "first_name", "last_name", "age"
Is there any workaround that I could use meanwhile?