Add case-insensitive ordering

This commit is contained in:
Daniel J. Summers 2024-08-21 21:03:38 -04:00
parent 2c24e2e912
commit 27b8a83a7a
5 changed files with 81 additions and 6 deletions

View File

@ -401,10 +401,13 @@ module Query =
{ it with Name = parts[0] }, Some $" {parts[1]}"
else it, None)
|> Seq.map (fun (field, direction) ->
match dialect, field.Name.StartsWith "n:" with
| PostgreSQL, true -> $"({ { field with Name = field.Name[2..] }.Path PostgreSQL})::numeric"
| SQLite, true -> { field with Name = field.Name[2..] }.Path SQLite
| _, _ -> field.Path dialect
if field.Name.StartsWith "n:" then
let f = { field with Name = field.Name[2..] }
match dialect with PostgreSQL -> $"({f.Path PostgreSQL})::numeric" | SQLite -> f.Path SQLite
elif field.Name.StartsWith "i:" then
let p = { field with Name = field.Name[2..] }.Path dialect
match dialect with PostgreSQL -> $"LOWER({p})" | SQLite -> $"{p} COLLATE NOCASE"
else field.Path dialect
|> function path -> path + defaultArg direction "")
|> String.concat ", "
|> function it -> $" ORDER BY {it}"

View File

@ -613,6 +613,18 @@ public static class CommonCSharpTests
{
Expect.equal(Query.OrderBy([Field.Named("n:Test")], Dialect.SQLite), " ORDER BY data->>'Test'",
"Order By not constructed correctly for numeric field");
}),
TestCase("succeeds for PostgreSQL case-insensitive ordering", () =>
{
Expect.equal(Query.OrderBy([Field.Named("i:Test.Field DESC")], Dialect.PostgreSQL),
" ORDER BY LOWER(data#>>'{Test,Field}') DESC",
"Order By not constructed correctly for case-insensitive field");
}),
TestCase("succeeds for SQLite case-insensitive ordering", () =>
{
Expect.equal(Query.OrderBy([Field.Named("i:Test.Field ASC")], Dialect.SQLite),
" ORDER BY data->>'Test'->>'Field' COLLATE NOCASE ASC",
"Order By not constructed correctly for case-insensitive field");
})
])
]);

View File

@ -627,8 +627,9 @@ public static class SqliteCSharpTests
var docs = await Find.ByFieldsOrdered<JsonDocument>(SqliteDb.TableName, FieldMatch.Any,
[Field.GT("NumValue", 15)], [Field.Named("Id")]);
Expect.hasLength(docs, 2, "There should have been two documents returned");
Expect.equal(string.Join('|', docs.Select(x => x.Id)), "five|four",
"There should have been two documents returned");
"The documents were not sorted correctly");
}),
TestCase("succeeds when documents are not found", async () =>
{
@ -637,8 +638,31 @@ public static class SqliteCSharpTests
var docs = await Find.ByFieldsOrdered<JsonDocument>(SqliteDb.TableName, FieldMatch.Any,
[Field.GT("NumValue", 15)], [Field.Named("Id DESC")]);
Expect.hasLength(docs, 2, "There should have been two documents returned");
Expect.equal(string.Join('|', docs.Select(x => x.Id)), "four|five",
"There should have been two documents returned");
"The documents were not sorted correctly");
}),
TestCase("succeeds when sorting case-sensitively", async () =>
{
await using var db = await SqliteDb.BuildDb();
await LoadDocs();
var docs = await Find.ByFieldsOrdered<JsonDocument>(SqliteDb.TableName, FieldMatch.Any,
[Field.LE("NumValue", 10)], [Field.Named("Value")]);
Expect.hasLength(docs, 3, "There should have been three documents returned");
Expect.equal(string.Join('|', docs.Select(x => x.Id)), "three|one|two",
"The documents were not sorted correctly");
}),
TestCase("succeeds when sorting case-insensitively", async () =>
{
await using var db = await SqliteDb.BuildDb();
await LoadDocs();
var docs = await Find.ByFieldsOrdered<JsonDocument>(SqliteDb.TableName, FieldMatch.Any,
[Field.LE("NumValue", 10)], [Field.Named("i:Value")]);
Expect.hasLength(docs, 3, "There should have been three documents returned");
Expect.equal(string.Join('|', docs.Select(x => x.Id)), "three|two|one",
"The documents were not sorted correctly");
})
]),
TestList("FirstByFields",

View File

@ -450,6 +450,18 @@ let queryTests = testList "Query" [
" ORDER BY data->>'Test'"
"Order By not constructed correctly for numeric field"
}
test "succeeds for PostgreSQL case-insensitive ordering" {
Expect.equal
(Query.orderBy [ Field.Named "i:Test.Field DESC" ] PostgreSQL)
" ORDER BY LOWER(data#>>'{Test,Field}') DESC"
"Order By not constructed correctly for case-insensitive field"
}
test "succeeds for SQLite case-insensitive ordering" {
Expect.equal
(Query.orderBy [ Field.Named "i:Test.Field ASC" ] SQLite)
" ORDER BY data->>'Test'->>'Field' COLLATE NOCASE ASC"
"Order By not constructed correctly for case-insensitive field"
}
]
]

View File

@ -527,6 +527,7 @@ let findTests = testList "Find" [
let! docs =
Find.byFieldsOrdered<JsonDocument>
SqliteDb.TableName Any [ Field.GT "NumValue" 15 ] [ Field.Named "Id" ]
Expect.hasLength docs 2 "There should have been two documents returned"
Expect.equal
(docs |> List.map _.Id |> String.concat "|") "five|four" "The documents were not ordered correctly"
}
@ -537,9 +538,32 @@ let findTests = testList "Find" [
let! docs =
Find.byFieldsOrdered<JsonDocument>
SqliteDb.TableName Any [ Field.GT "NumValue" 15 ] [ 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" "The documents were not ordered correctly"
}
testTask "succeeds when sorting case-sensitively" {
use! db = SqliteDb.BuildDb()
do! loadDocs ()
let! docs =
Find.byFieldsOrdered<JsonDocument>
SqliteDb.TableName All [ Field.LE "NumValue" 10 ] [ Field.Named "Value" ]
Expect.hasLength docs 3 "There should have been three documents returned"
Expect.equal
(docs |> List.map _.Id |> String.concat "|") "three|one|two" "Documents not ordered correctly"
}
testTask "succeeds when sorting case-insensitively" {
use! db = SqliteDb.BuildDb()
do! loadDocs ()
let! docs =
Find.byFieldsOrdered<JsonDocument>
SqliteDb.TableName All [ Field.LE "NumValue" 10 ] [ Field.Named "i:Value" ]
Expect.hasLength docs 3 "There should have been three documents returned"
Expect.equal
(docs |> List.map _.Id |> String.concat "|") "three|two|one" "Documents not ordered correctly"
}
]
testList "firstByFields" [
testTask "succeeds when a document is found" {