Version 4 #6
@ -98,6 +98,15 @@ type Field = {
|
||||
{ this with Qualifier = Some alias }
|
||||
|
||||
|
||||
/// How fields should be matched
|
||||
[<Struct>]
|
||||
type FieldMatch =
|
||||
/// Any field matches (OR)
|
||||
| Any
|
||||
/// All fields match (AND)
|
||||
| All
|
||||
|
||||
|
||||
/// The required document serialization implementation
|
||||
type IDocumentSerializer =
|
||||
|
||||
|
@ -109,24 +109,46 @@ module Parameters =
|
||||
[<RequireQualifiedAccess>]
|
||||
module Query =
|
||||
|
||||
/// Create a WHERE clause fragment to implement a comparison on fields in a JSON document
|
||||
[<CompiledName "WhereByFields">]
|
||||
let whereByFields fields howMatched =
|
||||
let mutable idx = 0
|
||||
let nameField () =
|
||||
let name = $"field{idx}"
|
||||
idx <- idx + 1
|
||||
name
|
||||
fields
|
||||
|> List.map (fun it ->
|
||||
let fieldName = it.Qualifier |> Option.map (fun q -> $"{q}.data") |> Option.defaultValue "data"
|
||||
let jsonPath =
|
||||
if it.Name.Contains '.' then "#>>'{" + String.concat "," (it.Name.Split '.') + "}'"
|
||||
else $"->>'{it.Name}'"
|
||||
let column = fieldName + jsonPath
|
||||
match it.Op with
|
||||
| EX | NEX -> $"{column} {it.Op}"
|
||||
| BT ->
|
||||
let p = defaultArg it.ParameterName (nameField ())
|
||||
let names = $"{p}min AND {p}max"
|
||||
let values = it.Value :?> obj list
|
||||
match values[0] with
|
||||
| :? int8 | :? uint8 | :? int16 | :? uint16 | :? int | :? uint32 | :? int64 | :? uint64
|
||||
| :? decimal | :? single | :? double -> $"({column})::numeric {it.Op} {names}"
|
||||
| _ -> $"{column} {it.Op} {names}"
|
||||
| _ ->
|
||||
let p = defaultArg it.ParameterName (nameField ())
|
||||
$"{column} {it.Op} {p}")
|
||||
|> 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">]
|
||||
//[<Obsolete "Use whereByFields / WhereByFields instead">]
|
||||
let whereByField field paramName =
|
||||
match field.Op with
|
||||
| EX | NEX -> $"data->>'{field.Name}' {field.Op}"
|
||||
| BT ->
|
||||
let names = $"{paramName}min AND {paramName}max"
|
||||
let values = field.Value :?> obj list
|
||||
match values[0] with
|
||||
| :? int8 | :? uint8 | :? int16 | :? uint16 | :? int | :? uint32 | :? int64 | :? uint64
|
||||
| :? decimal | :? single | :? double -> $"(data->>'{field.Name}')::numeric {field.Op} {names}"
|
||||
| _ -> $"data->>'{field.Name}' {field.Op} {names}"
|
||||
| _ -> $"data->>'{field.Name}' {field.Op} %s{paramName}"
|
||||
whereByFields [ { field with ParameterName = Some paramName } ] Any
|
||||
|
||||
/// Create a WHERE clause fragment to implement an ID-based query
|
||||
[<CompiledName "WhereById">]
|
||||
let whereById paramName =
|
||||
whereByField (Field.EQ (Configuration.idField ()) 0) paramName
|
||||
whereByFields [ { Field.EQ (Configuration.idField ()) 0 with ParameterName = Some paramName } ] Any
|
||||
|
||||
/// Table and index definition queries
|
||||
module Definition =
|
||||
|
@ -115,9 +115,9 @@ let all =
|
||||
Expect.equal "@name" field.ParameterName.Value "The parameter name is incorrect"
|
||||
}
|
||||
test "WithQualifier succeeds" {
|
||||
let field = (Field.EQ "Bill" "Matt").WithParameterName "@joe"
|
||||
let field = (Field.EQ "Bill" "Matt").WithQualifier "joe"
|
||||
Expect.isSome field.Qualifier "The table qualifier should have been filled"
|
||||
Expect.equal "@joe" field.Qualifier.Value "The table qualifier is incorrect"
|
||||
Expect.equal "joe" field.Qualifier.Value "The table qualifier is incorrect"
|
||||
}
|
||||
]
|
||||
testList "Query" [
|
||||
|
Loading…
Reference in New Issue
Block a user