WIP on Postgres type derivation

This commit is contained in:
Daniel J. Summers 2024-08-10 15:07:59 -04:00
parent 74e5b77edb
commit e0fb793ec9
6 changed files with 18 additions and 108 deletions

View File

@ -56,8 +56,21 @@ module Parameters =
/// Create an ID parameter (name "@id", key will be treated as a string) /// Create an ID parameter (name "@id", key will be treated as a string)
[<CompiledName "Id">] [<CompiledName "Id">]
let idParam (key: 'TKey) = let idParam (key: 'TKey) =
// TODO: bind key by numeric types match box key with
"@id", Sql.string (string key) | :? int8 as it -> Sql.int8 it
| :? uint8 as it -> Sql.int8 (int8 it)
| :? int16 as it -> Sql.int16 it
| :? uint16 as it -> Sql.int16 (int16 it)
| :? int as it -> Sql.int it
| :? uint32 as it -> Sql.int (int it)
| :? int64 as it -> Sql.int64 it
| :? uint64 as it -> Sql.int64 (int64 it)
| :? decimal as it -> Sql.decimal it
| :? single as it -> Sql.double (double it)
| :? double as it -> Sql.double it
| :? string as it -> Sql.string it
| _ -> Sql.string (string key)
|> function it -> "@id", it
/// Create a parameter with a JSON value /// Create a parameter with a JSON value
[<CompiledName "Json">] [<CompiledName "Json">]
@ -135,12 +148,6 @@ module Query =
| _ -> $"{it.Path PostgreSQL} {it.Op} {name.Derive it.ParameterName}") | _ -> $"{it.Path PostgreSQL} {it.Op} {name.Derive it.ParameterName}")
|> String.concat (match howMatched with Any -> " OR " | All -> " AND ") |> String.concat (match howMatched with Any -> " OR " | All -> " AND ")
/// Create a WHERE clause fragment to implement a comparison on a field in a JSON document
[<CompiledName "WhereByField">]
[<System.Obsolete "Use WhereByFields instead; will be removed in v4">]
let whereByField field paramName =
whereByFields Any [ { field with ParameterName = Some paramName } ]
/// Create a WHERE clause fragment to implement an ID-based query /// Create a WHERE clause fragment to implement an ID-based query
[<CompiledName "WhereById">] [<CompiledName "WhereById">]
let whereById paramName = let whereById paramName =

View File

@ -45,12 +45,6 @@ module Query =
| _ -> $"{it.Path SQLite} {it.Op} {name.Derive it.ParameterName}") | _ -> $"{it.Path SQLite} {it.Op} {name.Derive it.ParameterName}")
|> String.concat (match howMatched with Any -> " OR " | All -> " AND ") |> String.concat (match howMatched with Any -> " OR " | All -> " AND ")
/// Create a WHERE clause fragment to implement a comparison on a field in a JSON document
[<CompiledName "WhereByField">]
[<System.Obsolete "Use WhereByFields instead; will be removed in v4">]
let whereByField field paramName =
whereByFields Any [ { field with ParameterName = Some paramName } ]
/// Create a WHERE clause fragment to implement an ID-based query /// Create a WHERE clause fragment to implement an ID-based query
[<CompiledName "WhereById">] [<CompiledName "WhereById">]
let whereById paramName = let whereById paramName =

View File

@ -217,31 +217,6 @@ public static class PostgresCSharpTests
"WHERE clause not correct"); "WHERE clause not correct");
}) })
]), ]),
#pragma warning disable CS0618
TestList("WhereByField",
[
TestCase("succeeds when a logical operator is passed", () =>
{
Expect.equal(Postgres.Query.WhereByField(Field.GT("theField", 0), "@test"),
"data->>'theField' > @test", "WHERE clause not correct");
}),
TestCase("succeeds when an existence operator is passed", () =>
{
Expect.equal(Postgres.Query.WhereByField(Field.NEX("thatField"), ""), "data->>'thatField' IS NULL",
"WHERE clause not correct");
}),
TestCase("succeeds when a between operator is passed with numeric values", () =>
{
Expect.equal(Postgres.Query.WhereByField(Field.BT("aField", 50, 99), "@range"),
"(data->>'aField')::numeric BETWEEN @rangemin AND @rangemax", "WHERE clause not correct");
}),
TestCase("succeeds when a between operator is passed with non-numeric values", () =>
{
Expect.equal(Postgres.Query.WhereByField(Field.BT("field0", "a", "b"), "@alpha"),
"data->>'field0' BETWEEN @alphamin AND @alphamax", "WHERE clause not correct");
})
]),
#pragma warning restore CS0618
TestCase("WhereById succeeds", () => TestCase("WhereById succeeds", () =>
{ {
Expect.equal(Postgres.Query.WhereById("@id"), "data->>'Id' = @id", "WHERE clause not correct"); Expect.equal(Postgres.Query.WhereById("@id"), "data->>'Id' = @id", "WHERE clause not correct");

View File

@ -63,26 +63,6 @@ public static class SqliteCSharpTests
"WHERE clause not correct"); "WHERE clause not correct");
}) })
]), ]),
#pragma warning disable CS0618
TestList("WhereByField",
[
TestCase("succeeds when a logical operator is passed", () =>
{
Expect.equal(Sqlite.Query.WhereByField(Field.GT("theField", 0), "@test"),
"data->>'theField' > @test", "WHERE clause not correct");
}),
TestCase("succeeds when an existence operator is passed", () =>
{
Expect.equal(Sqlite.Query.WhereByField(Field.NEX("thatField"), ""), "data->>'thatField' IS NULL",
"WHERE clause not correct");
}),
TestCase("succeeds when the between operator is passed", () =>
{
Expect.equal(Sqlite.Query.WhereByField(Field.BT("aField", 50, 99), "@range"),
"data->>'aField' BETWEEN @rangemin AND @rangemax", "WHERE clause not correct");
})
]),
#pragma warning restore CS0618
TestCase("WhereById succeeds", () => TestCase("WhereById succeeds", () =>
{ {
Expect.equal(Sqlite.Query.WhereById("@id"), "data->>'Id' = @id", "WHERE clause not correct"); Expect.equal(Sqlite.Query.WhereById("@id"), "data->>'Id' = @id", "WHERE clause not correct");

View File

@ -196,32 +196,6 @@ let unitTests =
"WHERE clause not correct" "WHERE clause not correct"
} }
] ]
testList "whereByField" [
test "succeeds when a logical operator is passed" {
Expect.equal
(Query.whereByField (Field.GT "theField" 0) "@test")
"data->>'theField' > @test"
"WHERE clause not correct"
}
test "succeeds when an existence operator is passed" {
Expect.equal
(Query.whereByField (Field.NEX "thatField") "")
"data->>'thatField' IS NULL"
"WHERE clause not correct"
}
test "succeeds when a between operator is passed with numeric values" {
Expect.equal
(Query.whereByField (Field.BT "aField" 50 99) "@range")
"(data->>'aField')::numeric BETWEEN @rangemin AND @rangemax"
"WHERE clause not correct"
}
test "succeeds when a between operator is passed with non-numeric values" {
Expect.equal
(Query.whereByField (Field.BT "field0" "a" "b") "@alpha")
"data->>'field0' BETWEEN @alphamin AND @alphamax"
"WHERE clause not correct"
}
]
test "whereById succeeds" { test "whereById succeeds" {
Expect.equal (Query.whereById "@id") "data->>'Id' = @id" "WHERE clause not correct" Expect.equal (Query.whereById "@id") "data->>'Id' = @id" "WHERE clause not correct"
} }
@ -466,7 +440,7 @@ let integrationTests =
let! theCount = Count.all PostgresDb.TableName let! theCount = Count.all PostgresDb.TableName
Expect.equal theCount 5 "There should have been 5 matching documents" Expect.equal theCount 5 "There should have been 5 matching documents"
} }
ptestList "byFields" [ testList "byFields" [
testTask "succeeds when items are found" { testTask "succeeds when items are found" {
use db = PostgresDb.BuildDb() use db = PostgresDb.BuildDb()
do! loadDocs () do! loadDocs ()
@ -531,7 +505,7 @@ let integrationTests =
Expect.isFalse exists "There should not have been an existing document" Expect.isFalse exists "There should not have been an existing document"
} }
] ]
testList "byFields" [ ftestList "byFields" [
testTask "succeeds when documents exist" { testTask "succeeds when documents exist" {
use db = PostgresDb.BuildDb() use db = PostgresDb.BuildDb()
do! loadDocs () do! loadDocs ()
@ -647,7 +621,7 @@ let integrationTests =
PostgresDb.TableName All [ Field.EQ "Value" "purple"; Field.EX "Sub" ] PostgresDb.TableName All [ Field.EQ "Value" "purple"; Field.EX "Sub" ]
Expect.equal (List.length docs) 1 "There should have been one document returned" Expect.equal (List.length docs) 1 "There should have been one document returned"
} }
ptestTask "succeeds when documents are not found" { ftestTask "succeeds when documents are not found" {
use db = PostgresDb.BuildDb() use db = PostgresDb.BuildDb()
do! loadDocs () do! loadDocs ()

View File

@ -52,26 +52,6 @@ let unitTests =
"WHERE clause not correct" "WHERE clause not correct"
} }
] ]
testList "whereByField" [
test "succeeds when a logical operator is passed" {
Expect.equal
(Query.whereByField (Field.GT "theField" 0) "@test")
"data->>'theField' > @test"
"WHERE clause not correct"
}
test "succeeds when an existence operator is passed" {
Expect.equal
(Query.whereByField (Field.NEX "thatField") "")
"data->>'thatField' IS NULL"
"WHERE clause not correct"
}
test "succeeds when the between operator is passed" {
Expect.equal
(Query.whereByField (Field.BT "aField" 50 99) "@range")
"data->>'aField' BETWEEN @rangemin AND @rangemax"
"WHERE clause not correct"
}
]
test "whereById succeeds" { test "whereById succeeds" {
Expect.equal (Query.whereById "@id") "data->>'Id' = @id" "WHERE clause not correct" Expect.equal (Query.whereById "@id") "data->>'Id' = @id" "WHERE clause not correct"
} }