beam icon indicating copy to clipboard operation
beam copied to clipboard

DEFAULT can appear in arbitrary expressions

Open tathougies opened this issue 7 years ago • 1 comments

DEFAULT should only be able to appear in the VALUES clause of an INSERT INTO statement, not in any arbitrary expresion.

tathougies avatar Mar 11 '18 19:03 tathougies

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?

rycee avatar Mar 20 '22 11:03 rycee