git.iko.soy/rowtype-yoga/purescript-yoga-postgres
on main help sign in
Unify limit/offset with ParseLimitOffset typeclass: limit @"10" for literals, limit @"$n" for params
ff55060Mark
test/Schema.purs+97−87
@@ -2,7 +2,6 @@ module Test.Postgres.Schema where
2
2
3import Prelude
3import Prelude
4
4
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
782
783+resetUsers :: PG.Connection -> Aff Unit
784+resetUsers conn = do
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 ]
789+ conn
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 ]
792+ conn
793+ pure unit
794+
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
799+ resetUsers conn
788− rows <- from usersTable # selectAll # runQuery conn {}
800+ rows <- from usersTable # select @"name, email, age"
801+ # orderBy @"name"
802+ # runQuery conn {}
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+ ]
793
807
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"
818+ # orderBy @"name"
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" ]
841
855
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" ]
849
862
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" ]
857
869
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)"
874+ # orderBy @"name"
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" } ]
864
877
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 ]
872
884
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
887+ resetUsers conn
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" } ]
884
897
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" } ]
893
904
894 describe "Builder update execution" do
905 describe "Builder update execution" do
895 it "updates a row" do
906 it "updates a row" do
907+ resetUsers conn
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" }
905− case result of
906− Just r -> r.email `shouldEqual` "alice-updated@example.com"
917+ result `shouldEqual` Just { email: "alice-updated@example.com" }
907− Nothing -> shouldEqual "found" "nothing"
908
918
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 ]
917
926
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
929+ resetUsers conn
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 ]
935
943
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
946+ resetUsers conn
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)
944
952
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" } ]
952
960
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
962− # select @"name"
963− # orderBy @"name ASC"
964− # runQuery conn {}
965− let allNames = map _.name allRows
966− (map _.name rows) `shouldEqual` (Array.take 1 (Array.drop 1 allNames))
967
969
968 describe "Builder delete execution" do
970 describe "Builder delete execution" do
969 it "deletes with RETURNING" do
971 it "deletes with RETURNING" do
972+ resetUsers conn
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
986
987
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
990+ resetUsers conn
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" }
999+ ]
996
1000
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" ]
1006
1008
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" }
1018+ ]
1015
1019
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" } ]
1025
1028
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" ]
1042 conn
1045 conn
@@ -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" }
1051− case result of
1052− Just r -> r.title `shouldEqual` "Alice's Post"
1054+ result `shouldEqual` Just { name: "Alice", title: "Alice's Post" }
1053− Nothing -> shouldEqual "found" "nothing"
1054
1055
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
1058+ resetUsers conn
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" } ]
1061
1063
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" } ]
1068
1070
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" } ]
1076
1078
1077 describe "UNION / INTERSECT / EXCEPT execution" do
1079 describe "UNION / INTERSECT / EXCEPT execution" do
1078 it "UNION deduplicates" do
1080 it "UNION deduplicates" do
1081+ resetUsers conn
1079 rows <-
1082 rows <-
1080 (from usersTable # select @"name")
1083 (from usersTable # select @"name")
1081− `union` (from usersTable # select @"name")
1084+ # union (from usersTable # select @"name")
1085+ # orderBy @"name"
1082 # runQuery conn {}
1086 # runQuery conn {}
1083− Array.length rows `shouldEqual` 2
1087+ rows `shouldEqual` [ { name: "Alice" }, { name: "Bob" } ]
1084
1088
1085 it "UNION ALL keeps duplicates" do
1089 it "UNION ALL keeps duplicates" do
1086 rows <-
1090 rows <-
1087 (from usersTable # select @"name")
1091 (from usersTable # select @"name")
1088− `unionAll` (from usersTable # select @"name")
1092+ # unionAll (from usersTable # select @"name")
1093+ # orderBy @"name"
1089 # runQuery conn {}
1094 # runQuery conn {}
1090− Array.length rows `shouldEqual` 4
1095+ rows `shouldEqual`
1096+ [ { name: "Alice" }
1097+ , { name: "Alice" }
1098+ , { name: "Bob" }
1099+ , { name: "Bob" }
1100+ ]
1091
1101
1092 it "UNION with params from both sides" do
1102 it "UNION with params from both sides" do
1093 rows <-
1103 rows <-
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` []
1098
1108
1099 it "INTERSECT returns common rows" do
1109 it "INTERSECT returns common rows" do
1100 rows <-
1110 rows <-
1101 (from usersTable # select @"name")
1111 (from usersTable # select @"name")
1102− `intersect` (from usersTable # select @"name")
1112+ # intersect (from usersTable # select @"name")
1113+ # orderBy @"name"
1103 # runQuery conn {}
1114 # runQuery conn {}
1104− Array.length rows `shouldEqual` 2
1115+ rows `shouldEqual` [ { name: "Alice" }, { name: "Bob" } ]
1105
1116
1106 it "EXCEPT removes matching rows" do
1117 it "EXCEPT removes matching rows" do
1107 rows <-
1118 rows <-
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" ]
1113
1123
1114 it "UNION with ORDER BY and LIMIT" do
1124 it "UNION with ORDER BY and LIMIT" do
1115 rows <-
1125 rows <-
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" ]
1123
1132
1124 describe "WHERE features execution" do
1133 describe "WHERE features execution" do
1125 it "BETWEEN filters range" do
1134 it "BETWEEN filters range" do
1135+ resetUsers conn
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" ]
1131
1140
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" ]
1142 conn
1151 conn
@@ -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"
1160+ # orderBy @"name"
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" ]
1155 conn
1165 conn
@@ -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 })