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