RC4 changes #7
@ -19,6 +19,10 @@ type Op =
|
||||
| NE
|
||||
/// Between (BETWEEN)
|
||||
| BT
|
||||
/// In (IN)
|
||||
| IN
|
||||
// Array Contains/Exists (PostgreSQL: |? SQLite: EXISTS / json_each / IN)
|
||||
//| AEX
|
||||
/// Exists (IS NOT NULL)
|
||||
| EX
|
||||
/// Does Not Exist (IS NULL)
|
||||
@ -33,6 +37,7 @@ type Op =
|
||||
| LE -> "<="
|
||||
| NE -> "<>"
|
||||
| BT -> "BETWEEN"
|
||||
| IN -> "IN"
|
||||
| EX -> "IS NOT NULL"
|
||||
| NEX -> "IS NULL"
|
||||
|
||||
@ -89,6 +94,10 @@ type Field = {
|
||||
static member BT name (min: obj) (max: obj) =
|
||||
{ Name = name; Op = BT; Value = [ min; max ]; ParameterName = None; Qualifier = None }
|
||||
|
||||
/// Create an IN field criterion
|
||||
static member IN name (values: obj seq) =
|
||||
{ Name = name; Op = IN; Value = values; ParameterName = None; Qualifier = None }
|
||||
|
||||
/// Create an exists (IS NOT NULL) field criterion
|
||||
static member EX name =
|
||||
{ Name = name; Op = EX; Value = obj (); ParameterName = None; Qualifier = None }
|
||||
|
@ -96,6 +96,13 @@ module Parameters =
|
||||
parameterFor (List.head values) (fun v -> Sql.parameter (NpgsqlParameter($"{p}min", v))))
|
||||
yield ($"{p}max",
|
||||
parameterFor (List.last values) (fun v -> Sql.parameter (NpgsqlParameter($"{p}max", v))))
|
||||
| IN ->
|
||||
let p = name.Derive it.ParameterName
|
||||
yield!
|
||||
it.Value :?> obj seq
|
||||
|> Seq.mapi (fun idx v ->
|
||||
let paramName = $"{p}_{idx}"
|
||||
paramName, Sql.parameter (NpgsqlParameter(paramName, v)))
|
||||
| _ ->
|
||||
let p = name.Derive it.ParameterName
|
||||
yield (p, parameterFor it.Value (fun v -> Sql.parameter (NpgsqlParameter(p, v)))) })
|
||||
@ -138,6 +145,10 @@ module Query =
|
||||
let param, value =
|
||||
match it.Op with
|
||||
| BT -> $"{p}min AND {p}max", (it.Value :?> obj list)[0]
|
||||
| IN ->
|
||||
let values = it.Value :?> obj seq
|
||||
let paramNames = values |> Seq.mapi (fun idx _ -> $"{p}_{idx}") |> String.concat ", "
|
||||
$"({paramNames})", defaultArg (Seq.tryHead values) (obj ())
|
||||
| _ -> p, it.Value
|
||||
if isNumeric value then
|
||||
$"({it.Path PostgreSQL})::numeric {it.Op} {param}"
|
||||
|
@ -42,6 +42,10 @@ module Query =
|
||||
| BT ->
|
||||
let p = name.Derive it.ParameterName
|
||||
$"{it.Path SQLite} {it.Op} {p}min AND {p}max"
|
||||
| IN ->
|
||||
let p = name.Derive it.ParameterName
|
||||
let paramNames = it.Value :?> obj seq |> Seq.mapi (fun idx _ -> $"{p}_{idx}") |> String.concat ", "
|
||||
$"{it.Path SQLite} {it.Op} ({paramNames})"
|
||||
| _ -> $"{it.Path SQLite} {it.Op} {name.Derive it.ParameterName}")
|
||||
|> String.concat $" {howMatched} "
|
||||
|
||||
@ -110,6 +114,9 @@ module Parameters =
|
||||
let values = it.Value :?> obj list
|
||||
yield SqliteParameter($"{p}min", List.head values)
|
||||
yield SqliteParameter($"{p}max", List.last values)
|
||||
| IN ->
|
||||
let p = name.Derive it.ParameterName
|
||||
yield! it.Value :?> obj seq |> Seq.mapi (fun idx v -> SqliteParameter($"{p}_{idx}", v))
|
||||
| _ -> yield SqliteParameter(name.Derive it.ParameterName, it.Value) })
|
||||
|> Seq.collect id
|
||||
|> Seq.append parameters
|
||||
|
@ -177,6 +177,18 @@ let queryTests = testList "Query" [
|
||||
"(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 operator 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 operator 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"
|
||||
}
|
||||
]
|
||||
testList "whereById" [
|
||||
test "succeeds for numeric ID" {
|
||||
|
@ -51,6 +51,12 @@ let queryTests = testList "Query" [
|
||||
"data->>'aField' BETWEEN @field0min AND @field0max AND data->>'anotherField' BETWEEN @field1min AND @field1max"
|
||||
"WHERE clause not correct"
|
||||
}
|
||||
test "succeeds for a field with an IN operator" {
|
||||
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 "whereById succeeds" {
|
||||
Expect.equal (Query.whereById "@id") "data->>'Id' = @id" "WHERE clause not correct"
|
||||
|
Loading…
Reference in New Issue
Block a user