@@ -2,11 +2,15 @@ module Test.Postgres.Schema where
22
33import Prelude
44
5+import Data.Array as Array
56import Data.Date (canonicalDate)
67import Data.DateTime (DateTime(..))
78import Data.Enum (toEnum)
89import Data.Maybe (Maybe(..), fromJust)
10+import Data.Newtype (un)
11+import Data.String as String
912import Data.Time (Time(..))
13+import Data.UUID as UUID
1014import Partial.Unsafe (unsafePartial)
1115
1216import Type.Function (type (#))
@@ -735,7 +739,7 @@ articlesDDL :: String
735739articlesDDL = createTableDDL @ArticlesTable
736740
737741typedFTSWhere
738− :: Q _ _ _ _
742+ :: Q _ _ (q :: String) _
739743typedFTSWhere = from articlesTable # selectAll # where_ @"body_vector @@ to_tsquery($q)"
740744
741745-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
@@ -1343,3 +1347,74 @@ integrationSpec conn = do
13431347 # orderBy @"name"
13441348 # runQuery conn { age: 10, minCount: 0 }
13451349 rows `shouldEqual` [ { name: "Alice" }, { name: "Bob" } ]
1350+
1351+ describe "UUID + DefaultExpr execution" do
1352+ it "creates sessions table from DDL" do
1353+ _ <- PG.executeSimple (PG.SQL "DELETE FROM sessions") conn
1354+ pure unit
1355+
1356+ it "inserts with server-generated UUID and timestamp" do
1357+ _ <- PG.executeSimple (PG.SQL "DELETE FROM sessions") conn
1358+ count <- from sessionsTable
1359+ # insert { user_id: 1, token: "sess-abc" }
1360+ # runExecute conn {}
1361+ count `shouldEqual` 1
1362+
1363+ it "selects back UUID column" do
1364+ rows <- from sessionsTable
1365+ # select @"id, token"
1366+ # where_ @"token = $token"
1367+ # runQuery conn { token: "sess-abc" }
1368+ let len = Array.length rows
1369+ len `shouldEqual` 1
1370+ do
1371+ let row = unsafePartial fromJust (Array.head rows)
1372+ let uuidStr = UUID.toString (un PGUUID row.id)
1373+ String.length uuidStr `shouldEqual` 36
1374+ row.token `shouldEqual` "sess-abc"
1375+
1376+ describe "PGDate + PGTime execution" do
1377+ it "inserts and round-trips date and time" do
1378+ _ <- PG.executeSimple (PG.SQL "DELETE FROM schedule") conn
1379+ _ <- PG.executeSimple (PG.SQL "ALTER SEQUENCE schedule_id_seq RESTART WITH 1") conn
1380+ _ <- PG.execute
1381+ (PG.SQL "INSERT INTO schedule (event_date, start_time, title) VALUES ($1::date, $2::time, $3)")
1382+ [ PG.toPGValue "2025-06-15", PG.toPGValue "14:30:00", PG.toPGValue "Meeting" ]
1383+ conn
1384+ rows <- from scheduleTable
1385+ # select @"title"
1386+ # where_ @"title = $title"
1387+ # runQuery conn { title: "Meeting" }
1388+ rows `shouldEqual` [ { title: "Meeting" } ]
1389+
1390+ describe "Point execution" do
1391+ it "inserts and selects point values" do
1392+ _ <- PG.executeSimple (PG.SQL "DELETE FROM locations") conn
1393+ _ <- PG.executeSimple (PG.SQL "ALTER SEQUENCE locations_id_seq RESTART WITH 1") conn
1394+ _ <- PG.execute
1395+ (PG.SQL "INSERT INTO locations (name, coords) VALUES ($1, point($2, $3))")
1396+ [ PG.toPGValue "HQ", PG.toPGValue 40.7, PG.toPGValue (-74.0) ]
1397+ conn
1398+ rows <- from locationsTable
1399+ # select @"name"
1400+ # where_ @"name = $name"
1401+ # runQuery conn { name: "HQ" }
1402+ rows `shouldEqual` [ { name: "HQ" } ]
1403+
1404+ describe "TSVector + TSQuery execution" do
1405+ it "inserts and queries with full-text search" do
1406+ _ <- PG.executeSimple (PG.SQL "DELETE FROM articles") conn
1407+ _ <- PG.executeSimple (PG.SQL "ALTER SEQUENCE articles_id_seq RESTART WITH 1") conn
1408+ _ <- PG.execute
1409+ (PG.SQL "INSERT INTO articles (title, body_vector) VALUES ($1, to_tsvector($2))")
1410+ [ PG.toPGValue "PureScript Rocks", PG.toPGValue "purescript is a strongly typed functional language" ]
1411+ conn
1412+ _ <- PG.execute
1413+ (PG.SQL "INSERT INTO articles (title, body_vector) VALUES ($1, to_tsvector($2))")
1414+ [ PG.toPGValue "Haskell Guide", PG.toPGValue "haskell is a lazy functional language" ]
1415+ conn
1416+ rows <- from articlesTable
1417+ # select @"title"
1418+ # where_ @"body_vector @@ to_tsquery($q)"
1419+ # runQuery conn { q: "purescript" }
1420+ rows `shouldEqual` [ { title: "PureScript Rocks" } ]