RC4 changes (#7)

- Add `In` and `InArray` comparisons
- Replace `Op` with `Comparison` (internal API, but was public)
- Spell out comparisons in `Field` constructor functions

Reviewed-on: #7
This commit was merged in pull request #7.
This commit is contained in:
2024-09-17 02:33:57 +00:00
parent 3bc662c984
commit 168bf0cd14
19 changed files with 883 additions and 569 deletions

View File

@@ -83,14 +83,14 @@ let parametersTests = testList "Parameters" [
}
testList "addFieldParams" [
test "succeeds when a parameter is added" {
let paramList = addFieldParams [ Field.EQ "it" "242" ] []
let paramList = addFieldParams [ Field.Where "it" (Equal "242") ] []
Expect.hasLength paramList 1 "There should have been a parameter added"
let name, value = Seq.head paramList
Expect.equal name "@field0" "Field parameter name not correct"
Expect.equal value (Sql.string "242") "Parameter value not correct"
}
test "succeeds when multiple independent parameters are added" {
let paramList = addFieldParams [ Field.EQ "me" "you"; Field.GT "us" "them" ] [ idParam 14 ]
let paramList = addFieldParams [ Field.Equal "me" "you"; Field.Greater "us" "them" ] [ idParam 14 ]
Expect.hasLength paramList 3 "There should have been 2 parameters added"
let p = Array.ofSeq paramList
Expect.equal (fst p[0]) "@id" "First field parameter name not correct"
@@ -101,11 +101,11 @@ let parametersTests = testList "Parameters" [
Expect.equal (snd p[2]) (Sql.string "them") "Third parameter value not correct"
}
test "succeeds when a parameter is not added" {
let paramList = addFieldParams [ Field.EX "tacos" ] []
let paramList = addFieldParams [ Field.Exists "tacos" ] []
Expect.isEmpty paramList "There should not have been any parameters added"
}
test "succeeds when two parameters are added for one field" {
let paramList = addFieldParams [ { Field.BT "that" "eh" "zed" with ParameterName = Some "@test" } ] []
let paramList = addFieldParams [ { Field.Between "that" "eh" "zed" with ParameterName = Some "@test" } ] []
Expect.hasLength paramList 2 "There should have been 2 parameters added"
let name, value = Seq.head paramList
Expect.equal name "@testmin" "Minimum field name not correct"
@@ -135,48 +135,66 @@ let parametersTests = testList "Parameters" [
/// Unit tests for the Query module of the PostgreSQL library
let queryTests = testList "Query" [
testList "whereByFields" [
test "succeeds for a single field when a logical operator is passed" {
test "succeeds for a single field when a logical comparison is passed" {
Expect.equal
(Query.whereByFields Any [ { Field.GT "theField" "0" with ParameterName = Some "@test" } ])
(Query.whereByFields Any [ { Field.Greater "theField" "0" with ParameterName = Some "@test" } ])
"data->>'theField' > @test"
"WHERE clause not correct"
}
test "succeeds for a single field when an existence operator is passed" {
test "succeeds for a single field when an existence comparison is passed" {
Expect.equal
(Query.whereByFields Any [ Field.NEX "thatField" ])
(Query.whereByFields Any [ Field.NotExists "thatField" ])
"data->>'thatField' IS NULL"
"WHERE clause not correct"
}
test "succeeds for a single field when a between operator is passed with numeric values" {
test "succeeds for a single field when a between comparison is passed with numeric values" {
Expect.equal
(Query.whereByFields All [ { Field.BT "aField" 50 99 with ParameterName = Some "@range" } ])
(Query.whereByFields All [ { Field.Between "aField" 50 99 with ParameterName = Some "@range" } ])
"(data->>'aField')::numeric BETWEEN @rangemin AND @rangemax"
"WHERE clause not correct"
}
test "succeeds for a single field when a between operator is passed with non-numeric values" {
test "succeeds for a single field when a between comparison is passed with non-numeric values" {
Expect.equal
(Query.whereByFields Any [ { Field.BT "field0" "a" "b" with ParameterName = Some "@alpha" } ])
(Query.whereByFields Any [ { Field.Between "field0" "a" "b" with ParameterName = Some "@alpha" } ])
"data->>'field0' BETWEEN @alphamin AND @alphamax"
"WHERE clause not correct"
}
test "succeeds for all multiple fields with logical operators" {
test "succeeds for all multiple fields with logical comparisons" {
Expect.equal
(Query.whereByFields All [ Field.EQ "theFirst" "1"; Field.EQ "numberTwo" "2" ])
(Query.whereByFields All [ Field.Equal "theFirst" "1"; Field.Equal "numberTwo" "2" ])
"data->>'theFirst' = @field0 AND data->>'numberTwo' = @field1"
"WHERE clause not correct"
}
test "succeeds for any multiple fields with an existence operator" {
test "succeeds for any multiple fields with an existence comparisons" {
Expect.equal
(Query.whereByFields Any [ Field.NEX "thatField"; Field.GE "thisField" 18 ])
(Query.whereByFields Any [ Field.NotExists "thatField"; Field.GreaterOrEqual "thisField" 18 ])
"data->>'thatField' IS NULL OR (data->>'thisField')::numeric >= @field0"
"WHERE clause not correct"
}
test "succeeds for all multiple fields with between operators" {
test "succeeds for all multiple fields with between comparisons" {
Expect.equal
(Query.whereByFields All [ Field.BT "aField" 50 99; Field.BT "anotherField" "a" "b" ])
(Query.whereByFields All [ Field.Between "aField" 50 99; Field.Between "anotherField" "a" "b" ])
"(data->>'aField')::numeric BETWEEN @field0min AND @field0max AND data->>'anotherField' BETWEEN @field1min AND @field1max"
"WHERE clause not correct"
}
test "succeeds for a field with an In comparison with alphanumeric values" {
Expect.equal
(Query.whereByFields All [ Field.In "this" [ "a"; "b"; "c" ] ])
"data->>'this' IN (@field0_0, @field0_1, @field0_2)"
"WHERE clause not correct"
}
test "succeeds for a field with an In comparison with numeric values" {
Expect.equal
(Query.whereByFields All [ Field.In "this" [ 7; 14; 21 ] ])
"(data->>'this')::numeric IN (@field0_0, @field0_1, @field0_2)"
"WHERE clause not correct"
}
test "succeeds for a field with an InArray comparison" {
Expect.equal
(Query.whereByFields All [ Field.InArray "theField" "the_table" [ "q", "r" ] ])
"data->'theField' ?| @field0"
"WHERE clause not correct"
}
]
testList "whereById" [
test "succeeds for numeric ID" {
@@ -234,7 +252,7 @@ let queryTests = testList "Query" [
}
test "byFields succeeds" {
Expect.equal
(Query.byFields "unit" Any [ Field.GT "That" 14 ])
(Query.byFields "unit" Any [ Field.Greater "That" 14 ])
"unit WHERE (data->>'That')::numeric > @field0"
"By-Field query not correct"
}
@@ -532,14 +550,15 @@ let countTests = testList "Count" [
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! theCount = Count.byFields PostgresDb.TableName Any [ Field.BT "NumValue" 15 20; Field.EQ "NumValue" 0 ]
let! theCount =
Count.byFields PostgresDb.TableName Any [ Field.Between "NumValue" 15 20; Field.Equal "NumValue" 0 ]
Expect.equal theCount 3 "There should have been 3 matching documents"
}
testTask "succeeds when items are not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! theCount = Count.byFields PostgresDb.TableName All [ Field.EX "Sub"; Field.GT "NumValue" 100 ]
let! theCount = Count.byFields PostgresDb.TableName All [ Field.Exists "Sub"; Field.Greater "NumValue" 100 ]
Expect.equal theCount 0 "There should have been no matching documents"
}
]
@@ -582,14 +601,14 @@ let existsTests = testList "Exists" [
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! exists = Exists.byFields PostgresDb.TableName Any [ Field.EX "Sub"; Field.EX "Boo" ]
let! exists = Exists.byFields PostgresDb.TableName Any [ Field.Exists "Sub"; Field.Exists "Boo" ]
Expect.isTrue exists "There should have been existing documents"
}
testTask "succeeds when documents do not exist" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! exists = Exists.byFields PostgresDb.TableName All [ Field.EQ "NumValue" "six"; Field.EX "Nope" ]
let! exists = Exists.byFields PostgresDb.TableName All [ Field.Equal "NumValue" "six"; Field.Exists "Nope" ]
Expect.isFalse exists "There should not have been existing documents"
}
]
@@ -707,8 +726,16 @@ let findTests = testList "Find" [
do! loadDocs ()
let! docs =
Find.byFields<JsonDocument> PostgresDb.TableName All [ Field.EQ "Value" "purple"; Field.EX "Sub" ]
Expect.equal (List.length docs) 1 "There should have been one document returned"
Find.byFields<JsonDocument>
PostgresDb.TableName All [ Field.In "Value" [ "purple"; "blue" ]; Field.Exists "Sub" ]
Expect.hasLength docs 1 "There should have been one document returned"
}
testTask "succeeds when documents are found using IN with numeric field" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! docs = Find.byFields<JsonDocument> PostgresDb.TableName All [ Field.In "NumValue" [ 2; 4; 6; 8 ] ]
Expect.hasLength docs 1 "There should have been one document returned"
}
testTask "succeeds when documents are not found" {
use db = PostgresDb.BuildDb()
@@ -716,7 +743,27 @@ let findTests = testList "Find" [
let! docs =
Find.byFields<JsonDocument>
PostgresDb.TableName All [ Field.EQ "Value" "mauve"; Field.NE "NumValue" 40 ]
PostgresDb.TableName All [ Field.Equal "Value" "mauve"; Field.NotEqual "NumValue" 40 ]
Expect.isEmpty docs "There should have been no documents returned"
}
testTask "succeeds for InArray when matching documents exist" {
use db = PostgresDb.BuildDb()
do! Definition.ensureTable PostgresDb.TableName
for doc in ArrayDocument.TestDocuments do do! insert PostgresDb.TableName doc
let! docs =
Find.byFields<ArrayDocument>
PostgresDb.TableName All [ Field.InArray "Values" PostgresDb.TableName [ "c" ] ]
Expect.hasLength docs 2 "There should have been two documents returned"
}
testTask "succeeds for InArray when no matching documents exist" {
use db = PostgresDb.BuildDb()
do! Definition.ensureTable PostgresDb.TableName
for doc in ArrayDocument.TestDocuments do do! insert PostgresDb.TableName doc
let! docs =
Find.byFields<ArrayDocument>
PostgresDb.TableName All [ Field.InArray "Values" PostgresDb.TableName [ "j" ] ]
Expect.isEmpty docs "There should have been no documents returned"
}
]
@@ -727,7 +774,7 @@ let findTests = testList "Find" [
let! docs =
Find.byFieldsOrdered<JsonDocument>
PostgresDb.TableName All [ Field.EQ "Value" "purple" ] [ Field.Named "Id" ]
PostgresDb.TableName All [ Field.Equal "Value" "purple" ] [ Field.Named "Id" ]
Expect.hasLength docs 2 "There should have been two documents returned"
Expect.equal
(docs |> List.map _.Id |> String.concat "|") "five|four" "Documents not ordered correctly"
@@ -738,7 +785,7 @@ let findTests = testList "Find" [
let! docs =
Find.byFieldsOrdered<JsonDocument>
PostgresDb.TableName All [ Field.EQ "Value" "purple" ] [ Field.Named "Id DESC" ]
PostgresDb.TableName All [ Field.Equal "Value" "purple" ] [ Field.Named "Id DESC" ]
Expect.hasLength docs 2 "There should have been two documents returned"
Expect.equal
(docs |> List.map _.Id |> String.concat "|") "four|five" "Documents not ordered correctly"
@@ -831,7 +878,7 @@ let findTests = testList "Find" [
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc = Find.firstByFields<JsonDocument> PostgresDb.TableName Any [ Field.EQ "Value" "another" ]
let! doc = Find.firstByFields<JsonDocument> PostgresDb.TableName Any [ Field.Equal "Value" "another" ]
Expect.isSome doc "There should have been a document returned"
Expect.equal doc.Value.Id "two" "The incorrect document was returned"
}
@@ -839,7 +886,7 @@ let findTests = testList "Find" [
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc = Find.firstByFields<JsonDocument> PostgresDb.TableName Any [ Field.EQ "Value" "purple" ]
let! doc = Find.firstByFields<JsonDocument> PostgresDb.TableName Any [ Field.Equal "Value" "purple" ]
Expect.isSome doc "There should have been a document returned"
Expect.contains [ "five"; "four" ] doc.Value.Id "An incorrect document was returned"
}
@@ -847,7 +894,7 @@ let findTests = testList "Find" [
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc = Find.firstByFields<JsonDocument> PostgresDb.TableName Any [ Field.EQ "Value" "absent" ]
let! doc = Find.firstByFields<JsonDocument> PostgresDb.TableName Any [ Field.Equal "Value" "absent" ]
Expect.isNone doc "There should not have been a document returned"
}
]
@@ -858,7 +905,7 @@ let findTests = testList "Find" [
let! doc =
Find.firstByFieldsOrdered<JsonDocument>
PostgresDb.TableName Any [ Field.EQ "Value" "purple" ] [ Field.Named "Id" ]
PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] [ Field.Named "Id" ]
Expect.isSome doc "There should have been a document returned"
Expect.equal "five" doc.Value.Id "An incorrect document was returned"
}
@@ -868,7 +915,7 @@ let findTests = testList "Find" [
let! doc =
Find.firstByFieldsOrdered<JsonDocument>
PostgresDb.TableName Any [ Field.EQ "Value" "purple" ] [ Field.Named "Id DESC" ]
PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] [ Field.Named "Id DESC" ]
Expect.isSome doc "There should have been a document returned"
Expect.equal "four" doc.Value.Id "An incorrect document was returned"
}
@@ -1045,8 +1092,8 @@ let patchTests = testList "Patch" [
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! Patch.byFields PostgresDb.TableName Any [ Field.EQ "Value" "purple" ] {| NumValue = 77 |}
let! after = Count.byFields PostgresDb.TableName Any [ Field.EQ "NumValue" 77 ]
do! Patch.byFields PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] {| NumValue = 77 |}
let! after = Count.byFields PostgresDb.TableName Any [ Field.Equal "NumValue" 77 ]
Expect.equal after 2 "There should have been 2 documents returned"
}
testTask "succeeds when no document is updated" {
@@ -1056,7 +1103,7 @@ let patchTests = testList "Patch" [
Expect.equal before 0 "There should have been no documents returned"
// This not raising an exception is the test
do! Patch.byFields PostgresDb.TableName Any [ Field.EQ "Value" "burgundy" ] {| Foo = "green" |}
do! Patch.byFields PostgresDb.TableName Any [ Field.Equal "Value" "burgundy" ] {| Foo = "green" |}
}
]
testList "byContains" [
@@ -1107,9 +1154,9 @@ let removeFieldsTests = testList "RemoveFields" [
do! loadDocs ()
do! RemoveFields.byId PostgresDb.TableName "two" [ "Sub"; "Value" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NEX "Sub" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ]
Expect.equal noSubs 4 "There should now be 4 documents without Sub fields"
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NEX "Value" ]
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ]
Expect.equal noValue 1 "There should be 1 document without Value fields"
}
testTask "succeeds when a single field is removed" {
@@ -1117,9 +1164,9 @@ let removeFieldsTests = testList "RemoveFields" [
do! loadDocs ()
do! RemoveFields.byId PostgresDb.TableName "two" [ "Sub" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NEX "Sub" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ]
Expect.equal noSubs 4 "There should now be 4 documents without Sub fields"
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NEX "Value" ]
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ]
Expect.equal noValue 0 "There should be no documents without Value fields"
}
testTask "succeeds when a field is not removed" {
@@ -1141,20 +1188,20 @@ let removeFieldsTests = testList "RemoveFields" [
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! RemoveFields.byFields PostgresDb.TableName Any [ Field.EQ "NumValue" "17" ] [ "Sub"; "Value" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NEX "Sub" ]
do! RemoveFields.byFields PostgresDb.TableName Any [ Field.Equal "NumValue" 17 ] [ "Sub"; "Value" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ]
Expect.equal noSubs 4 "There should now be 4 documents without Sub fields"
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NEX "Value" ]
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ]
Expect.equal noValue 1 "There should be 1 document without Value fields"
}
testTask "succeeds when a single field is removed" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! RemoveFields.byFields PostgresDb.TableName Any [ Field.EQ "NumValue" "17" ] [ "Sub" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NEX "Sub" ]
do! RemoveFields.byFields PostgresDb.TableName Any [ Field.Equal "NumValue" 17 ] [ "Sub" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ]
Expect.equal noSubs 4 "There should now be 4 documents without Sub fields"
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NEX "Value" ]
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ]
Expect.equal noValue 0 "There should be no documents without Value fields"
}
testTask "succeeds when a field is not removed" {
@@ -1162,13 +1209,13 @@ let removeFieldsTests = testList "RemoveFields" [
do! loadDocs ()
// This not raising an exception is the test
do! RemoveFields.byFields PostgresDb.TableName Any [ Field.EQ "NumValue" "17" ] [ "Nothing" ]
do! RemoveFields.byFields PostgresDb.TableName Any [ Field.Equal "NumValue" 17 ] [ "Nothing" ]
}
testTask "succeeds when no document is matched" {
use db = PostgresDb.BuildDb()
// This not raising an exception is the test
do! RemoveFields.byFields PostgresDb.TableName Any [ Field.NE "Abracadabra" "apple" ] [ "Value" ]
do! RemoveFields.byFields PostgresDb.TableName Any [ Field.NotEqual "Abracadabra" "apple" ] [ "Value" ]
}
]
testList "byContains" [
@@ -1177,9 +1224,9 @@ let removeFieldsTests = testList "RemoveFields" [
do! loadDocs ()
do! RemoveFields.byContains PostgresDb.TableName {| NumValue = 17 |} [ "Sub"; "Value" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NEX "Sub" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ]
Expect.equal noSubs 4 "There should now be 4 documents without Sub fields"
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NEX "Value" ]
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ]
Expect.equal noValue 1 "There should be 1 document without Value fields"
}
testTask "succeeds when a single field is removed" {
@@ -1187,9 +1234,9 @@ let removeFieldsTests = testList "RemoveFields" [
do! loadDocs ()
do! RemoveFields.byContains PostgresDb.TableName {| NumValue = 17 |} [ "Sub" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NEX "Sub" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ]
Expect.equal noSubs 4 "There should now be 4 documents without Sub fields"
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NEX "Value" ]
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ]
Expect.equal noValue 0 "There should be no documents without Value fields"
}
testTask "succeeds when a field is not removed" {
@@ -1212,9 +1259,9 @@ let removeFieldsTests = testList "RemoveFields" [
do! loadDocs ()
do! RemoveFields.byJsonPath PostgresDb.TableName "$.NumValue ? (@ == 17)" [ "Sub"; "Value" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NEX "Sub" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ]
Expect.equal noSubs 4 "There should now be 4 documents without Sub fields"
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NEX "Value" ]
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ]
Expect.equal noValue 1 "There should be 1 document without Value fields"
}
testTask "succeeds when a single field is removed" {
@@ -1222,9 +1269,9 @@ let removeFieldsTests = testList "RemoveFields" [
do! loadDocs ()
do! RemoveFields.byJsonPath PostgresDb.TableName "$.NumValue ? (@ == 17)" [ "Sub" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NEX "Sub" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ]
Expect.equal noSubs 4 "There should now be 4 documents without Sub fields"
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NEX "Value" ]
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ]
Expect.equal noValue 0 "There should be no documents without Value fields"
}
testTask "succeeds when a field is not removed" {
@@ -1268,7 +1315,7 @@ let deleteTests = testList "Delete" [
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! Delete.byFields PostgresDb.TableName Any [ Field.EQ "Value" "purple" ]
do! Delete.byFields PostgresDb.TableName Any [ Field.Equal "Value" "purple" ]
let! remaining = Count.all PostgresDb.TableName
Expect.equal remaining 3 "There should have been 3 documents remaining"
}
@@ -1276,7 +1323,7 @@ let deleteTests = testList "Delete" [
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! Delete.byFields PostgresDb.TableName Any [ Field.EQ "Value" "crimson" ]
do! Delete.byFields PostgresDb.TableName Any [ Field.Equal "Value" "crimson" ]
let! remaining = Count.all PostgresDb.TableName
Expect.equal remaining 5 "There should have been 5 documents remaining"
}