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

@@ -37,18 +37,26 @@ module Query =
let name = ParameterName()
fields
|> Seq.map (fun it ->
match it.Op with
| EX | NEX -> $"{it.Path SQLite} {it.Op}"
| BT ->
match it.Comparison with
| Exists | NotExists -> $"{it.Path SQLite AsSql} {it.Comparison.OpSql}"
| Between _ ->
let p = name.Derive it.ParameterName
$"{it.Path SQLite} {it.Op} {p}min AND {p}max"
| _ -> $"{it.Path SQLite} {it.Op} {name.Derive it.ParameterName}")
$"{it.Path SQLite AsSql} {it.Comparison.OpSql} {p}min AND {p}max"
| In values ->
let p = name.Derive it.ParameterName
let paramNames = values |> Seq.mapi (fun idx _ -> $"{p}_{idx}") |> String.concat ", "
$"{it.Path SQLite AsSql} {it.Comparison.OpSql} ({paramNames})"
| InArray (table, values) ->
let p = name.Derive it.ParameterName
let paramNames = values |> Seq.mapi (fun idx _ -> $"{p}_{idx}") |> String.concat ", "
$"EXISTS (SELECT 1 FROM json_each({table}.data, '$.{it.Name}') WHERE value IN ({paramNames}))"
| _ -> $"{it.Path SQLite AsSql} {it.Comparison.OpSql} {name.Derive it.ParameterName}")
|> String.concat $" {howMatched} "
/// Create a WHERE clause fragment to implement an ID-based query
[<CompiledName "WhereById">]
let whereById paramName =
whereByFields Any [ { Field.EQ (Configuration.idField ()) 0 with ParameterName = Some paramName } ]
whereByFields Any [ { Field.Equal (Configuration.idField ()) 0 with ParameterName = Some paramName } ]
/// Create an UPDATE statement to patch documents
[<CompiledName "Patch">]
@@ -66,7 +74,7 @@ module Query =
let byId<'TKey> statement (docId: 'TKey) =
Query.statementWhere
statement
(whereByFields Any [ { Field.EQ (Configuration.idField ()) docId with ParameterName = Some "@id" } ])
(whereByFields Any [ { Field.Equal (Configuration.idField ()) docId with ParameterName = Some "@id" } ])
/// Create a query on JSON fields
[<CompiledName "ByFields">]
@@ -103,14 +111,16 @@ module Parameters =
fields
|> Seq.map (fun it ->
seq {
match it.Op with
| EX | NEX -> ()
| BT ->
let p = name.Derive it.ParameterName
let values = it.Value :?> obj list
yield SqliteParameter($"{p}min", List.head values)
yield SqliteParameter($"{p}max", List.last values)
| _ -> yield SqliteParameter(name.Derive it.ParameterName, it.Value) })
match it.Comparison with
| Exists | NotExists -> ()
| Between (min, max) ->
let p = name.Derive it.ParameterName
yield! [ SqliteParameter($"{p}min", min); SqliteParameter($"{p}max", max) ]
| In values | InArray (_, values) ->
let p = name.Derive it.ParameterName
yield! values |> Seq.mapi (fun idx v -> SqliteParameter($"{p}_{idx}", v))
| Equal v | Greater v | GreaterOrEqual v | Less v | LessOrEqual v | NotEqual v ->
yield SqliteParameter(name.Derive it.ParameterName, v) })
|> Seq.collect id
|> Seq.append parameters
|> Seq.toList