@@ -2,7 +2,6 @@ module Test.Postgres.Schema where
3import Prelude
3import Prelude
5−import Data.Array as Array
6import Data.Date (canonicalDate)
5import Data.Date (canonicalDate)
7import Data.DateTime (DateTime(..))
6import Data.DateTime (DateTime(..))
8import Data.Enum (toEnum)
7import Data.Enum (toEnum)
@@ -17,8 +16,8 @@ import Foreign (Foreign, unsafeToForeign)
17import JS.BigInt (BigInt)
16import JS.BigInt (BigInt)
18import JS.BigInt as BigInt
17import JS.BigInt as BigInt
19import Prim.Boolean (True)
18import Prim.Boolean (True)
20−import Test.Spec (Spec, around, describe, it)
19+import Test.Spec (Spec, describe, it)
21−import Test.Spec.Assertions (shouldEqual, shouldSatisfy)
20+import Test.Spec.Assertions (shouldEqual)
22import Type.Proxy (Proxy(..))
21import Type.Proxy (Proxy(..))
23import Yoga.Postgres as PG
22import Yoga.Postgres as PG
24import Yoga.Postgres.Schema
23import Yoga.Postgres.Schema
@@ -781,15 +780,30 @@ spec = do
781 it "builds nested parentheses" do
780 it "builds nested parentheses" do
782 (typedNestedParens # toSQL) `shouldEqual` "SELECT * FROM users WHERE (age > $a OR age < $b) AND name = $name"
781 (typedNestedParens # toSQL) `shouldEqual` "SELECT * FROM users WHERE (age > $a OR age < $b) AND name = $name"
783+resetUsers :: PG.Connection -> Aff Unit
785+ _ <- PG.executeSimple (PG.SQL "DELETE FROM users") conn
786+ _ <- PG.executeSimple (PG.SQL "ALTER SEQUENCE users_id_seq RESTART WITH 1") conn
787+ _ <- PG.execute (PG.SQL "INSERT INTO users (name, email, age) VALUES ($1, $2, $3)")
788+ [ PG.toPGValue "Alice", PG.toPGValue "alice@example.com", PG.toPGValue 22 ]
790+ _ <- PG.execute (PG.SQL "INSERT INTO users (name, email, age) VALUES ($1, $2, $3)")
791+ [ PG.toPGValue "Bob", PG.toPGValue "bob@example.com", PG.toPGValue 30 ]
784integrationSpec :: PG.Connection -> Spec Unit
795integrationSpec :: PG.Connection -> Spec Unit
785integrationSpec conn = do
796integrationSpec conn = do
786 describe "Builder query execution" do
797 describe "Builder query execution" do
787 it "selectAll returns all rows" do
798 it "selectAll returns all rows" do
788− rows <- from usersTable # selectAll # runQuery conn {}
800+ rows <- from usersTable # select @"name, email, age"
789− Array.length rows `shouldEqual` 2
803+ rows `shouldEqual`
790− let names = map _.name rows
804+ [ { name: "Alice", email: "alice@example.com", age: Just 22 }
791− names `shouldSatisfy` Array.elem "Alice"
805+ , { name: "Bob", email: "bob@example.com", age: Just 30 }
792− names `shouldSatisfy` Array.elem "Bob"
806+ ]
794 it "select with columns returns projected rows" do
808 it "select with columns returns projected rows" do
795 rows <- from usersTable
809 rows <- from usersTable
@@ -801,6 +815,7 @@ integrationSpec conn = do
801 it "select with alias" do
815 it "select with alias" do
802 rows <- from usersTable
816 rows <- from usersTable
803 # select @"name, email AS e"
817 # select @"name, email AS e"
804 # runQuery conn {}
819 # runQuery conn {}
805 rows `shouldEqual`
820 rows `shouldEqual`
806 [ { name: "Alice", e: "alice@example.com" }
821 [ { name: "Alice", e: "alice@example.com" }
@@ -836,42 +851,40 @@ integrationSpec conn = do
836 # select @"title, tags, view_count"
851 # select @"title, tags, view_count"
837 # where_ @"title = $title"
852 # where_ @"title = $title"
838 # runQuery conn { title: "Launch" }
853 # runQuery conn { title: "Launch" }
839− Array.length rows `shouldEqual` 1
854+ rows `shouldEqual` [ { title: "Launch", tags: [ "release", "v1" ], view_count: BigInt.fromInt 42 } ]
840− (map _.title rows) `shouldEqual` [ "Launch" ]
842 it "inserts with returningAll" do
856 it "inserts with returningAll" do
843 rows <- from eventsTable
857 rows <- from eventsTable
844 # insert { title: "Minimal", metadata: Jsonb (unsafeToForeign {}), tags: ([] :: Array String), created_at: testDateTime, view_count: BigInt.fromInt 0 }
858 # insert { title: "Minimal", metadata: Jsonb (unsafeToForeign {}), tags: ([] :: Array String), created_at: testDateTime, view_count: BigInt.fromInt 0 }
845− # returning @"id, title"
859+ # returning @"title"
846 # runQuery conn {}
860 # runQuery conn {}
847− Array.length rows `shouldEqual` 1
861+ rows `shouldEqual` [ { title: "Minimal" } ]
848− (map _.title rows) `shouldEqual` [ "Minimal" ]
850 it "WHERE with JSONB @> operator" do
863 it "WHERE with JSONB @> operator" do
851 rows <- from eventsTable
864 rows <- from eventsTable
852 # select @"title"
865 # select @"title"
853 # where_ @"metadata @> $metadata"
866 # where_ @"metadata @> $metadata"
854 # runQuery conn { metadata: Jsonb (unsafeToForeign { key: "value" }) }
867 # runQuery conn { metadata: Jsonb (unsafeToForeign { key: "value" }) }
855− Array.length rows `shouldEqual` 1
868+ rows `shouldEqual` [ { title: "Launch" } ]
856− (map _.title rows) `shouldEqual` [ "Launch" ]
858 it "WHERE with = ANY() array param" do
870 it "WHERE with = ANY() array param" do
859 rows <- from usersTable
871 rows <- from usersTable
860 # select @"name"
872 # select @"name"
861 # where_ @"id = ANY($id)"
873 # where_ @"id = ANY($id)"
862 # runQuery conn { id: [ 1, 2 ] }
875 # runQuery conn { id: [ 1, 2 ] }
863− Array.length rows `shouldSatisfy` (_ >= 1)
876+ rows `shouldEqual` [ { name: "Alice" }, { name: "Bob" } ]
865 it "complex where with multiple params" do
878 it "complex where with multiple params" do
866 rows <- from usersTable
879 rows <- from usersTable
867− # selectAll
880+ # select @"name, age"
868 # where_ @"name = $name AND age > $age"
881 # where_ @"name = $name AND age > $age"
869 # runQuery conn { name: "Bob", age: 20 }
882 # runQuery conn { name: "Bob", age: 20 }
870− Array.length rows `shouldEqual` 1
883+ rows `shouldEqual` [ { name: "Bob", age: Just 30 } ]
871− (map _.age rows) `shouldEqual` [ Just 30 ]
873 describe "Builder insert execution" do
885 describe "Builder insert execution" do
874 it "inserts a row and returns count" do
886 it "inserts a row and returns count" do
875 count <- from usersTable
888 count <- from usersTable
876 # insert { name: "Charlie", email: "charlie@example.com", age: Just 28 }
889 # insert { name: "Charlie", email: "charlie@example.com", age: Just 28 }
877 # runExecute conn {}
890 # runExecute conn {}
@@ -880,19 +893,18 @@ integrationSpec conn = do
880 # select @"name"
893 # select @"name"
881 # where_ @"name = $name"
894 # where_ @"name = $name"
882 # runQuery conn { name: "Charlie" }
895 # runQuery conn { name: "Charlie" }
883− Array.length rows `shouldEqual` 1
896+ rows `shouldEqual` [ { name: "Charlie" } ]
885 it "inserts with RETURNING" do
898 it "inserts with RETURNING" do
886 rows <- from usersTable
899 rows <- from usersTable
887 # insert { name: "Diana", email: "diana@example.com" }
900 # insert { name: "Diana", email: "diana@example.com" }
888− # returning @"id, name, email"
901+ # returning @"name, email"
889 # runQuery conn {}
902 # runQuery conn {}
890− Array.length rows `shouldEqual` 1
891− (map _.name rows) `shouldEqual` [ "Diana" ]
892− (map _.email rows) `shouldEqual` [ "diana@example.com" ]
903+ rows `shouldEqual` [ { name: "Diana", email: "diana@example.com" } ]
894 describe "Builder update execution" do
905 describe "Builder update execution" do
895 it "updates a row" do
906 it "updates a row" do
896 count <- from usersTable
908 count <- from usersTable
897 # set { email: "alice-updated@example.com" }
909 # set { email: "alice-updated@example.com" }
898 # where_ @"name = $name"
910 # where_ @"name = $name"
@@ -902,9 +914,7 @@ integrationSpec conn = do
902 # select @"email"
914 # select @"email"
903 # where_ @"name = $name"
915 # where_ @"name = $name"
904 # runQueryOne conn { name: "Alice" }
916 # runQueryOne conn { name: "Alice" }
906− Just r -> r.email `shouldEqual` "alice-updated@example.com"
917+ result `shouldEqual` Just { email: "alice-updated@example.com" }
907− Nothing -> shouldEqual "found" "nothing"
909 it "updates with RETURNING" do
919 it "updates with RETURNING" do
910 rows <- from usersTable
920 rows <- from usersTable
@@ -912,11 +922,11 @@ integrationSpec conn = do
912 # where_ @"name = $name"
922 # where_ @"name = $name"
913 # returning @"name, age"
923 # returning @"name, age"
914 # runQuery conn { name: "Bob" }
924 # runQuery conn { name: "Bob" }
915− Array.length rows `shouldEqual` 1
925+ rows `shouldEqual` [ { name: "Bob", age: Just 99 } ]
916− (map _.age rows) `shouldEqual` [ Just 99 ]
918 describe "Builder upsert execution" do
927 describe "Builder upsert execution" do
919 it "ON CONFLICT DO NOTHING skips duplicate" do
928 it "ON CONFLICT DO NOTHING skips duplicate" do
920 count <- from usersTable
930 count <- from usersTable
921 # insert { name: "Duplicate", email: "bob@example.com" }
931 # insert { name: "Duplicate", email: "bob@example.com" }
922 # onConflictDoNothing @"email"
932 # onConflictDoNothing @"email"
@@ -929,26 +939,24 @@ integrationSpec conn = do
929 # onConflict @"email" @"DO UPDATE SET name = EXCLUDED.name, age = EXCLUDED.age"
939 # onConflict @"email" @"DO UPDATE SET name = EXCLUDED.name, age = EXCLUDED.age"
930 # returning @"name, age"
940 # returning @"name, age"
931 # runQuery conn {}
941 # runQuery conn {}
932− Array.length rows `shouldEqual` 1
942+ rows `shouldEqual` [ { name: "Updated", age: Just 40 } ]
933− (map _.name rows) `shouldEqual` [ "Updated" ]
934− (map _.age rows) `shouldEqual` [ Just 40 ]
936 describe "Builder order by / limit / offset execution" do
944 describe "Builder order by / limit / offset execution" do
937 it "ORDER BY sorts results" do
945 it "ORDER BY sorts results" do
938 rows <- from usersTable
947 rows <- from usersTable
939 # select @"name"
948 # select @"name"
940 # orderBy @"name ASC"
949 # orderBy @"name ASC"
941 # runQuery conn {}
950 # runQuery conn {}
942− let names = map _.name rows
951+ rows `shouldEqual` [ { name: "Alice" }, { name: "Bob" } ]
943− names `shouldEqual` (Array.sort names)
945 it "LIMIT restricts row count" do
953 it "LIMIT restricts row count" do
946 rows <- from usersTable
954 rows <- from usersTable
947− # selectAll
955+ # select @"name"
948 # orderBy @"name"
956 # orderBy @"name"
949 # limit @"1"
957 # limit @"1"
950 # runQuery conn {}
958 # runQuery conn {}
951− Array.length rows `shouldEqual` 1
959+ rows `shouldEqual` [ { name: "Alice" } ]
953 it "OFFSET skips rows" do
961 it "OFFSET skips rows" do
954 rows <- from usersTable
962 rows <- from usersTable
@@ -957,16 +965,11 @@ integrationSpec conn = do
957 # limit @"1"
965 # limit @"1"
958 # offset @"1"
966 # offset @"1"
959 # runQuery conn {}
967 # runQuery conn {}
960− Array.length rows `shouldEqual` 1
968+ rows `shouldEqual` [ { name: "Bob" } ]
961− allRows <- from usersTable
963− # orderBy @"name ASC"
965− let allNames = map _.name allRows
966− (map _.name rows) `shouldEqual` (Array.take 1 (Array.drop 1 allNames))
968 describe "Builder delete execution" do
970 describe "Builder delete execution" do
969 it "deletes with RETURNING" do
971 it "deletes with RETURNING" do
970 _ <- from usersTable
973 _ <- from usersTable
971 # insert { name: "ToDelete", email: "delete@example.com", age: Just 50 }
974 # insert { name: "ToDelete", email: "delete@example.com", age: Just 50 }
972 # runExecute conn {}
975 # runExecute conn {}
@@ -975,24 +978,25 @@ integrationSpec conn = do
975 # where_ @"name = $name"
978 # where_ @"name = $name"
976 # returning @"name, email"
979 # returning @"name, email"
977 # runQuery conn { name: "ToDelete" }
980 # runQuery conn { name: "ToDelete" }
978− Array.length rows `shouldEqual` 1
979− (map _.name rows) `shouldEqual` [ "ToDelete" ]
981+ rows `shouldEqual` [ { name: "ToDelete", email: "delete@example.com" } ]
980− -- Verify actually deleted
981 result <- from usersTable
982 result <- from usersTable
982− # selectAll
983+ # select @"name"
983 # where_ @"name = $name"
984 # where_ @"name = $name"
984 # runQueryOne conn { name: "ToDelete" }
985 # runQueryOne conn { name: "ToDelete" }
985 result `shouldEqual` Nothing
986 result `shouldEqual` Nothing
987 describe "Builder JOIN execution" do
988 describe "Builder JOIN execution" do
988 it "INNER JOIN returns matching rows" do
989 it "INNER JOIN returns matching rows" do
989 rows <- from usersTable
991 rows <- from usersTable
990 # innerJoin @"users.id = posts.user_id" postsTable
992 # innerJoin @"users.id = posts.user_id" postsTable
991 # select @"users.name, posts.title"
993 # select @"users.name, posts.title"
994+ # orderBy @"users.name"
992 # runQuery conn {}
995 # runQuery conn {}
993− Array.length rows `shouldEqual` 2
996+ rows `shouldEqual`
994− (map _.name rows) `shouldSatisfy` Array.elem "Alice"
997+ [ { name: "Alice", title: "Alice's Post" }
995− (map _.title rows) `shouldSatisfy` Array.elem "Alice's Post"
998+ , { name: "Bob", title: "Bob's Post" }
997 it "INNER JOIN with WHERE filters correctly" do
1001 it "INNER JOIN with WHERE filters correctly" do
998 rows <- from usersTable
1002 rows <- from usersTable
@@ -1000,18 +1004,18 @@ integrationSpec conn = do
1000 # select @"users.name, posts.title"
1004 # select @"users.name, posts.title"
1001 # where_ @"users.age > $age"
1005 # where_ @"users.age > $age"
1002 # runQuery conn { age: 25 }
1006 # runQuery conn { age: 25 }
1003− Array.length rows `shouldEqual` 1
1007+ rows `shouldEqual` [ { name: "Bob", title: "Bob's Post" } ]
1004− (map _.name rows) `shouldEqual` [ "Bob" ]
1005− (map _.title rows) `shouldEqual` [ "Bob's Post" ]
1007 it "INNER JOIN with aliases" do
1009 it "INNER JOIN with aliases" do
1008 rows <- from usersTable
1010 rows <- from usersTable
1009 # innerJoin @"users.id = posts.user_id" postsTable
1011 # innerJoin @"users.id = posts.user_id" postsTable
1010 # select @"users.name AS author, posts.title AS post_title"
1012 # select @"users.name AS author, posts.title AS post_title"
1013+ # orderBy @"users.name"
1011 # runQuery conn {}
1014 # runQuery conn {}
1012− Array.length rows `shouldEqual` 2
1015+ rows `shouldEqual`
1013− (map _.author rows) `shouldSatisfy` Array.elem "Alice"
1016+ [ { author: "Alice", post_title: "Alice's Post" }
1014− (map _.post_title rows) `shouldSatisfy` Array.elem "Bob's Post"
1017+ , { author: "Bob", post_title: "Bob's Post" }
1016 it "INNER JOIN with ORDER BY and LIMIT" do
1020 it "INNER JOIN with ORDER BY and LIMIT" do
1017 rows <- from usersTable
1021 rows <- from usersTable
@@ -1020,8 +1024,7 @@ integrationSpec conn = do
1020 # orderBy @"users.name ASC"
1024 # orderBy @"users.name ASC"
1021 # limit @"1"
1025 # limit @"1"
1022 # runQuery conn {}
1026 # runQuery conn {}
1023− Array.length rows `shouldEqual` 1
1024− (map _.name rows) `shouldEqual` [ "Alice" ]
1027+ rows `shouldEqual` [ { name: "Alice", title: "Alice's Post" } ]
1026 it "LEFT JOIN includes unmatched rows" do
1029 it "LEFT JOIN includes unmatched rows" do
1027 _ <- PG.execute (PG.SQL "INSERT INTO users (name, email, age) VALUES ($1, $2, $3)")
1030 _ <- PG.execute (PG.SQL "INSERT INTO users (name, email, age) VALUES ($1, $2, $3)")
@@ -1032,11 +1035,11 @@ integrationSpec conn = do
1032 # select @"users.name, posts.title"
1035 # select @"users.name, posts.title"
1033 # orderBy @"users.name ASC"
1036 # orderBy @"users.name ASC"
1034 # runQuery conn {}
1037 # runQuery conn {}
1035− Array.length rows `shouldSatisfy` (_ >= 3)
1038+ rows `shouldEqual`
1036− let noPostRow = Array.find (\r -> r.name == "NoPost") rows
1039+ [ { name: "Alice", title: Just "Alice's Post" }
1037− case noPostRow of
1040+ , { name: "Bob", title: Just "Bob's Post" }
1038− Just r -> r.title `shouldEqual` Nothing
1041+ , { name: "NoPost", title: Nothing }
1039− Nothing -> shouldEqual "found" "nothing"
1042+ ]
1040 _ <- PG.execute (PG.SQL "DELETE FROM users WHERE name = $1")
1043 _ <- PG.execute (PG.SQL "DELETE FROM users WHERE name = $1")
1041 [ PG.toPGValue "NoPost" ]
1044 [ PG.toPGValue "NoPost" ]
@@ -1048,23 +1051,22 @@ integrationSpec conn = do
1048 # select @"users.name, posts.title"
1051 # select @"users.name, posts.title"
1049 # where_ @"users.name = $name"
1052 # where_ @"users.name = $name"
1050 # runQueryOne conn { name: "Alice" }
1053 # runQueryOne conn { name: "Alice" }
1052− Just r -> r.title `shouldEqual` "Alice's Post"
1054+ result `shouldEqual` Just { name: "Alice", title: "Alice's Post" }
1053− Nothing -> shouldEqual "found" "nothing"
1055 describe "Parameterized LIMIT/OFFSET execution" do
1056 describe "Parameterized LIMIT/OFFSET execution" do
1056 it "parameterized LIMIT restricts rows" do
1057 it "parameterized LIMIT restricts rows" do
1057 rows <- from usersTable # select @"name" # orderBy @"name"
1059 rows <- from usersTable # select @"name" # orderBy @"name"
1058 # limit @"$n"
1060 # limit @"$n"
1059 # runQuery conn { n: 1 }
1061 # runQuery conn { n: 1 }
1060− Array.length rows `shouldEqual` 1
1062+ rows `shouldEqual` [ { name: "Alice" } ]
1062 it "parameterized OFFSET skips rows" do
1064 it "parameterized OFFSET skips rows" do
1063 rows <- from usersTable # select @"name" # orderBy @"name"
1065 rows <- from usersTable # select @"name" # orderBy @"name"
1064 # limit @"$n"
1066 # limit @"$n"
1065 # offset @"$off"
1067 # offset @"$off"
1066 # runQuery conn { n: 1, off: 1 }
1068 # runQuery conn { n: 1, off: 1 }
1067− Array.length rows `shouldEqual` 1
1069+ rows `shouldEqual` [ { name: "Bob" } ]
1069 it "parameterized LIMIT with WHERE" do
1071 it "parameterized LIMIT with WHERE" do
1070 rows <- from usersTable # select @"name"
1072 rows <- from usersTable # select @"name"
@@ -1072,62 +1074,69 @@ integrationSpec conn = do
1072 # orderBy @"name"
1074 # orderBy @"name"
1073 # limit @"$n"
1075 # limit @"$n"
1074 # runQuery conn { age: 0, n: 1 }
1076 # runQuery conn { age: 0, n: 1 }
1075− Array.length rows `shouldEqual` 1
1077+ rows `shouldEqual` [ { name: "Alice" } ]
1077 describe "UNION / INTERSECT / EXCEPT execution" do
1079 describe "UNION / INTERSECT / EXCEPT execution" do
1078 it "UNION deduplicates" do
1080 it "UNION deduplicates" do
1080 (from usersTable # select @"name")
1083 (from usersTable # select @"name")
1081− `union` (from usersTable # select @"name")
1084+ # union (from usersTable # select @"name")
1082 # runQuery conn {}
1086 # runQuery conn {}
1083− Array.length rows `shouldEqual` 2
1087+ rows `shouldEqual` [ { name: "Alice" }, { name: "Bob" } ]
1085 it "UNION ALL keeps duplicates" do
1089 it "UNION ALL keeps duplicates" do
1087 (from usersTable # select @"name")
1091 (from usersTable # select @"name")
1088− `unionAll` (from usersTable # select @"name")
1092+ # unionAll (from usersTable # select @"name")
1089 # runQuery conn {}
1094 # runQuery conn {}
1090− Array.length rows `shouldEqual` 4
1095+ rows `shouldEqual`
1096+ [ { name: "Alice" }
1097+ , { name: "Alice" }
1092 it "UNION with params from both sides" do
1102 it "UNION with params from both sides" do
1094 (from usersTable # select @"name" # where_ @"age > $a")
1104 (from usersTable # select @"name" # where_ @"age > $a")
1095 `union` (from usersTable # select @"name" # where_ @"age < $b")
1105 `union` (from usersTable # select @"name" # where_ @"age < $b")
1096 # runQuery conn { a: 100, b: 0 }
1106 # runQuery conn { a: 100, b: 0 }
1097− Array.length rows `shouldEqual` 0
1107+ rows `shouldEqual` []
1099 it "INTERSECT returns common rows" do
1109 it "INTERSECT returns common rows" do
1101 (from usersTable # select @"name")
1111 (from usersTable # select @"name")
1102− `intersect` (from usersTable # select @"name")
1112+ # intersect (from usersTable # select @"name")
1103 # runQuery conn {}
1114 # runQuery conn {}
1104− Array.length rows `shouldEqual` 2
1115+ rows `shouldEqual` [ { name: "Alice" }, { name: "Bob" } ]
1106 it "EXCEPT removes matching rows" do
1117 it "EXCEPT removes matching rows" do
1108 (from usersTable # select @"name")
1119 (from usersTable # select @"name")
1109 `except_` (from usersTable # select @"name" # where_ @"name = $name")
1120 `except_` (from usersTable # select @"name" # where_ @"name = $name")
1110 # runQuery conn { name: "Alice" }
1121 # runQuery conn { name: "Alice" }
1111− Array.length rows `shouldEqual` 1
1122+ rows `shouldEqual` [ { name: "Bob" } ]
1112− (map _.name rows) `shouldEqual` [ "Bob" ]
1114 it "UNION with ORDER BY and LIMIT" do
1124 it "UNION with ORDER BY and LIMIT" do
1116− from usersTable # select @"name"
1126+ (from usersTable # select @"name")
1117− # union (from usersTable # select @"name")
1127+ `union` (from usersTable # select @"name")
1118 # orderBy @"name"
1128 # orderBy @"name"
1119 # limit @"1"
1129 # limit @"1"
1120 # runQuery conn {}
1130 # runQuery conn {}
1121− Array.length rows `shouldEqual` 1
1131+ rows `shouldEqual` [ { name: "Alice" } ]
1122− (map _.name rows) `shouldEqual` [ "Alice" ]
1124 describe "WHERE features execution" do
1133 describe "WHERE features execution" do
1125 it "BETWEEN filters range" do
1134 it "BETWEEN filters range" do
1126 rows <- from usersTable # select @"name"
1136 rows <- from usersTable # select @"name"
1127 # where_ @"age BETWEEN $lo AND $hi"
1137 # where_ @"age BETWEEN $lo AND $hi"
1128 # runQuery conn { lo: 20, hi: 26 }
1138 # runQuery conn { lo: 20, hi: 26 }
1129− Array.length rows `shouldEqual` 1
1139+ rows `shouldEqual` [ { name: "Alice" } ]
1130− (map _.name rows) `shouldEqual` [ "Alice" ]
1132 it "IS NULL matches null values" do
1141 it "IS NULL matches null values" do
1133 _ <- from usersTable
1142 _ <- from usersTable
@@ -1136,7 +1145,7 @@ integrationSpec conn = do
1136 rows <- from usersTable # select @"name"
1145 rows <- from usersTable # select @"name"
1137 # where_ @"age IS NULL"
1146 # where_ @"age IS NULL"
1138 # runQuery conn {}
1147 # runQuery conn {}
1139− (map _.name rows) `shouldSatisfy` Array.elem "NullAge"
1148+ rows `shouldEqual` [ { name: "NullAge" } ]
1140 _ <- PG.execute (PG.SQL "DELETE FROM users WHERE name = $1")
1149 _ <- PG.execute (PG.SQL "DELETE FROM users WHERE name = $1")
1141 [ PG.toPGValue "NullAge" ]
1150 [ PG.toPGValue "NullAge" ]
@@ -1148,8 +1157,9 @@ integrationSpec conn = do
1148 # runExecute conn {}
1157 # runExecute conn {}
1149 rows <- from usersTable # select @"name"
1158 rows <- from usersTable # select @"name"
1150 # where_ @"age IS NOT NULL"
1159 # where_ @"age IS NOT NULL"
1151 # runQuery conn {}
1161 # runQuery conn {}
1152− (map _.name rows) `shouldSatisfy` (not <<< Array.elem "NullAge2")
1162+ rows `shouldEqual` [ { name: "Alice" }, { name: "Bob" } ]
1153 _ <- PG.execute (PG.SQL "DELETE FROM users WHERE name = $1")
1163 _ <- PG.execute (PG.SQL "DELETE FROM users WHERE name = $1")
1154 [ PG.toPGValue "NullAge2" ]
1164 [ PG.toPGValue "NullAge2" ]
@@ -1159,4 +1169,4 @@ integrationSpec conn = do
1159 rows <- from usersTable # select @"name"
1169 rows <- from usersTable # select @"name"
1160 # where_ @"(age > $a OR age < $b) AND name = $name"
1170 # where_ @"(age > $a OR age < $b) AND name = $name"
1161 # runQuery conn { a: 100, b: 0, name: "Alice" }
1171 # runQuery conn { a: 100, b: 0, name: "Alice" }
1162− Array.length rows `shouldEqual` 0
1172+ rows `shouldEqual` ([] :: Array { name :: String })