Change Op to Comparison DU

This commit is contained in:
Daniel J. Summers 2024-09-15 17:45:52 -04:00
parent 14c80f32fe
commit b07ae3f097
5 changed files with 173 additions and 154 deletions

View File

@ -2,44 +2,45 @@
open System.Security.Cryptography
/// The types of logical operations available for JSON fields
[<Struct>]
type Op =
/// The types of comparisons available for JSON fields
type Comparison =
/// Equals (=)
| EQ
| Equals of obj
/// Greater Than (>)
| GT
| Greater of obj
/// Greater Than or Equal To (>=)
| GE
| GreaterOrEqual of obj
/// Less Than (<)
| LT
| Less of obj
/// Less Than or Equal To (<=)
| LE
| LessOrEqual of obj
/// Not Equal to (<>)
| NE
| NotEqual of obj
/// Between (BETWEEN)
| BT
| Between of obj * obj
/// In (IN)
| IN
| In of obj seq
// Array Contains/Exists (PostgreSQL: |? SQLite: EXISTS / json_each / IN)
//| AEX
| Contains of obj
/// Exists (IS NOT NULL)
| EX
| Exists
/// Does Not Exist (IS NULL)
| NEX
| NotExists
override this.ToString() =
/// Get the operator SQL for this comparison
member this.OpSql =
match this with
| EQ -> "="
| GT -> ">"
| GE -> ">="
| LT -> "<"
| LE -> "<="
| NE -> "<>"
| BT -> "BETWEEN"
| IN -> "IN"
| EX -> "IS NOT NULL"
| NEX -> "IS NULL"
| Equals _ -> "="
| Greater _ -> ">"
| GreaterOrEqual _ -> ">="
| Less _ -> "<"
| LessOrEqual _ -> "<="
| NotEqual _ -> "<>"
| Between _ -> "BETWEEN"
| In _ -> "IN"
| Contains _ -> "|?" // PostgreSQL only; SQL needs a subquery for this
| Exists -> "IS NOT NULL"
| NotExists -> "IS NULL"
/// The dialect in which a command should be rendered
@ -53,11 +54,12 @@ type Field = {
/// The name of the field
Name: string
/// The operation by which the field will be compared
Op: Op
/// The value of the field
Value: obj
Comparison: Comparison
// /// The operation by which the field will be compared
// Op: Op
//
// /// The value of the field
// Value: obj
/// The name of the parameter for this field
ParameterName: string option
@ -66,45 +68,49 @@ type Field = {
Qualifier: string option
} with
/// Create a comparison against a field
static member Where name comparison =
{ Name = name; Comparison = comparison; ParameterName = None; Qualifier = None }
/// Create an equals (=) field criterion
static member EQ name (value: obj) =
{ Name = name; Op = EQ; Value = value; ParameterName = None; Qualifier = None }
Field.Where name (Equals value)
/// Create a greater than (>) field criterion
static member GT name (value: obj) =
{ Name = name; Op = GT; Value = value; ParameterName = None; Qualifier = None }
Field.Where name (Greater value)
/// Create a greater than or equal to (>=) field criterion
static member GE name (value: obj) =
{ Name = name; Op = GE; Value = value; ParameterName = None; Qualifier = None }
Field.Where name (GreaterOrEqual value)
/// Create a less than (<) field criterion
static member LT name (value: obj) =
{ Name = name; Op = LT; Value = value; ParameterName = None; Qualifier = None }
Field.Where name (Less value)
/// Create a less than or equal to (<=) field criterion
static member LE name (value: obj) =
{ Name = name; Op = LE; Value = value; ParameterName = None; Qualifier = None }
Field.Where name (LessOrEqual value)
/// Create a not equals (<>) field criterion
static member NE name (value: obj) =
{ Name = name; Op = NE; Value = value; ParameterName = None; Qualifier = None }
Field.Where name (NotEqual value)
/// Create a BETWEEN field criterion
static member BT name (min: obj) (max: obj) =
{ Name = name; Op = BT; Value = [ min; max ]; ParameterName = None; Qualifier = None }
Field.Where name (Between(min, max))
/// Create an IN field criterion
static member IN name (values: obj seq) =
{ Name = name; Op = IN; Value = values; ParameterName = None; Qualifier = None }
Field.Where name (In values)
/// Create an exists (IS NOT NULL) field criterion
static member EX name =
{ Name = name; Op = EX; Value = obj (); ParameterName = None; Qualifier = None }
Field.Where name Exists
/// Create a not exists (IS NULL) field criterion
static member NEX name =
{ Name = name; Op = NEX; Value = obj (); ParameterName = None; Qualifier = None }
Field.Where name NotExists
/// Transform a field name (a.b.c) to a path for the given SQL dialect
static member NameToPath (name: string) dialect =
@ -118,7 +124,7 @@ type Field = {
/// Create a field with a given name, but no other properties filled (op will be EQ, value will be "")
static member Named name =
{ Name = name; Op = EQ; Value = ""; ParameterName = None; Qualifier = None }
Field.Where name (Equals "")
/// Specify the name of the parameter for this field
member this.WithParameterName name =

View File

@ -87,25 +87,23 @@ 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 ($"{p}min",
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 ->
match it.Comparison with
| Exists | NotExists -> ()
| Between (min, max) ->
let p = name.Derive it.ParameterName
yield ($"{p}min", parameterFor min (fun v -> Sql.parameter (NpgsqlParameter($"{p}min", v))))
yield ($"{p}max", parameterFor max (fun v -> Sql.parameter (NpgsqlParameter($"{p}max", v))))
| In values ->
let p = name.Derive it.ParameterName
yield!
it.Value :?> obj seq
values
|> Seq.mapi (fun idx v ->
let paramName = $"{p}_{idx}"
paramName, Sql.parameter (NpgsqlParameter(paramName, v)))
| _ ->
| Contains _ -> () // TODO
| Equals v | Greater v | GreaterOrEqual v | Less v | LessOrEqual v | NotEqual v ->
let p = name.Derive it.ParameterName
yield (p, parameterFor it.Value (fun v -> Sql.parameter (NpgsqlParameter(p, v)))) })
yield (p, parameterFor v (fun l -> Sql.parameter (NpgsqlParameter(p, l)))) })
|> Seq.collect id
|> Seq.append parameters
|> Seq.toList
@ -138,21 +136,22 @@ module Query =
| _ -> false
fields
|> Seq.map (fun it ->
match it.Op with
| EX | NEX -> $"{it.Path PostgreSQL} {it.Op}"
match it.Comparison with
| Exists | NotExists -> $"{it.Path PostgreSQL} {it.Comparison.OpSql}"
| _ ->
let p = name.Derive it.ParameterName
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
match it.Comparison with
| Between (min, _) -> $"{p}min AND {p}max", min
| In values ->
let paramNames = values |> Seq.mapi (fun idx _ -> $"{p}_{idx}") |> String.concat ", "
$"({paramNames})", defaultArg (Seq.tryHead values) (obj ())
| _ -> p, it.Value
| Contains _ -> p, "" // TODO: may need to use -> vs ->> in field SQL
| Equals v | Greater v | GreaterOrEqual v | Less v | LessOrEqual v | NotEqual v -> p, v
| _ -> p, ""
if isNumeric value then
$"({it.Path PostgreSQL})::numeric {it.Op} {param}"
else $"{it.Path PostgreSQL} {it.Op} {param}")
$"({it.Path PostgreSQL})::numeric {it.Comparison.OpSql} {param}"
else $"{it.Path PostgreSQL} {it.Comparison.OpSql} {param}")
|> String.concat $" {howMatched} "
/// Create a WHERE clause fragment to implement an ID-based query

View File

@ -37,16 +37,17 @@ 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} {it.Comparison.OpSql}"
| Between _ ->
let p = name.Derive it.ParameterName
$"{it.Path SQLite} {it.Op} {p}min AND {p}max"
| IN ->
$"{it.Path SQLite} {it.Comparison.OpSql} {p}min AND {p}max"
| In values ->
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}")
let paramNames = values |> Seq.mapi (fun idx _ -> $"{p}_{idx}") |> String.concat ", "
$"{it.Path SQLite} {it.Comparison.OpSql} ({paramNames})"
| Contains _ -> "" // TODO
| _ -> $"{it.Path SQLite} {it.Comparison.OpSql} {name.Derive it.ParameterName}")
|> String.concat $" {howMatched} "
/// Create a WHERE clause fragment to implement an ID-based query
@ -107,17 +108,17 @@ 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)
| IN ->
match it.Comparison with
| Exists | NotExists -> ()
| Between (min, max) ->
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($"{p}min", min); SqliteParameter($"{p}max", max) ]
| In values ->
let p = name.Derive it.ParameterName
yield! values |> Seq.mapi (fun idx v -> SqliteParameter($"{p}_{idx}", v))
| Contains _ -> () // TODO
| Equals 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

View File

@ -1,6 +1,5 @@
using Expecto.CSharp;
using Expecto;
using Microsoft.FSharp.Collections;
using Microsoft.FSharp.Core;
namespace BitBadger.Documents.Tests.CSharp;
@ -22,45 +21,53 @@ internal class TestSerializer : IDocumentSerializer
public static class CommonCSharpTests
{
/// <summary>
/// Unit tests for the Op enum
/// Unit tests for the OpSql property of the Comparison discriminated union
/// </summary>
private static readonly Test OpTests = TestList("Op",
private static readonly Test OpTests = TestList("Comparison.OpSql",
[
TestCase("EQ succeeds", () =>
TestCase("Equals succeeds", () =>
{
Expect.equal(Op.EQ.ToString(), "=", "The equals operator was not correct");
Expect.equal(Comparison.NewEquals("").OpSql, "=", "The Equals SQL was not correct");
}),
TestCase("GT succeeds", () =>
TestCase("Greater succeeds", () =>
{
Expect.equal(Op.GT.ToString(), ">", "The greater than operator was not correct");
Expect.equal(Comparison.NewGreater("").OpSql, ">", "The Greater SQL was not correct");
}),
TestCase("GE succeeds", () =>
TestCase("GreaterOrEqual succeeds", () =>
{
Expect.equal(Op.GE.ToString(), ">=", "The greater than or equal to operator was not correct");
Expect.equal(Comparison.NewGreaterOrEqual("").OpSql, ">=", "The GreaterOrEqual SQL was not correct");
}),
TestCase("LT succeeds", () =>
TestCase("Less succeeds", () =>
{
Expect.equal(Op.LT.ToString(), "<", "The less than operator was not correct");
Expect.equal(Comparison.NewLess("").OpSql, "<", "The Less SQL was not correct");
}),
TestCase("LE succeeds", () =>
TestCase("LessOrEqual succeeds", () =>
{
Expect.equal(Op.LE.ToString(), "<=", "The less than or equal to operator was not correct");
Expect.equal(Comparison.NewLessOrEqual("").OpSql, "<=", "The LessOrEqual SQL was not correct");
}),
TestCase("NE succeeds", () =>
TestCase("NotEqual succeeds", () =>
{
Expect.equal(Op.NE.ToString(), "<>", "The not equal to operator was not correct");
Expect.equal(Comparison.NewNotEqual("").OpSql, "<>", "The NotEqual SQL was not correct");
}),
TestCase("BT succeeds", () =>
TestCase("Between succeeds", () =>
{
Expect.equal(Op.BT.ToString(), "BETWEEN", "The \"between\" operator was not correct");
Expect.equal(Comparison.NewBetween("", "").OpSql, "BETWEEN", "The Between SQL was not correct");
}),
TestCase("EX succeeds", () =>
TestCase("In succeeds", () =>
{
Expect.equal(Op.EX.ToString(), "IS NOT NULL", "The \"exists\" operator was not correct");
Expect.equal(Comparison.NewIn([]).OpSql, "IN", "The In SQL was not correct");
}),
TestCase("NEX succeeds", () =>
TestCase("Contains succeeds", () =>
{
Expect.equal(Op.NEX.ToString(), "IS NULL", "The \"not exists\" operator was not correct");
Expect.equal(Comparison.NewContains("").OpSql, "|?", "The Contains SQL was not correct");
}),
TestCase("Exists succeeds", () =>
{
Expect.equal(Comparison.Exists.OpSql, "IS NOT NULL", "The Exists SQL was not correct");
}),
TestCase("NotExists succeeds", () =>
{
Expect.equal(Comparison.NotExists.OpSql, "IS NULL", "The NotExists SQL was not correct");
})
]);
@ -73,62 +80,62 @@ public static class CommonCSharpTests
{
var field = Field.EQ("Test", 14);
Expect.equal(field.Name, "Test", "Field name incorrect");
Expect.equal(field.Op, Op.EQ, "Operator incorrect");
Expect.equal(field.Value, 14, "Value incorrect");
Expect.equal(field.Comparison, Comparison.NewEquals(14), "Comparison incorrect");
}),
TestCase("GT succeeds", () =>
{
var field = Field.GT("Great", "night");
Expect.equal(field.Name, "Great", "Field name incorrect");
Expect.equal(field.Op, Op.GT, "Operator incorrect");
Expect.equal(field.Value, "night", "Value incorrect");
Expect.equal(field.Comparison, Comparison.NewGreater("night"), "Comparison incorrect");
}),
TestCase("GE succeeds", () =>
{
var field = Field.GE("Nice", 88L);
Expect.equal(field.Name, "Nice", "Field name incorrect");
Expect.equal(field.Op, Op.GE, "Operator incorrect");
Expect.equal(field.Value, 88L, "Value incorrect");
Expect.equal(field.Comparison, Comparison.NewGreaterOrEqual(88L), "Comparison incorrect");
}),
TestCase("LT succeeds", () =>
{
var field = Field.LT("Lesser", "seven");
Expect.equal(field.Name, "Lesser", "Field name incorrect");
Expect.equal(field.Op, Op.LT, "Operator incorrect");
Expect.equal(field.Value, "seven", "Value incorrect");
Expect.equal(field.Comparison, Comparison.NewLess("seven"), "Comparison incorrect");
}),
TestCase("LE succeeds", () =>
{
var field = Field.LE("Nobody", "KNOWS");
Expect.equal(field.Name, "Nobody", "Field name incorrect");
Expect.equal(field.Op, Op.LE, "Operator incorrect");
Expect.equal(field.Value, "KNOWS", "Value incorrect");
Expect.equal(field.Comparison, Comparison.NewLessOrEqual("KNOWS"), "Comparison incorrect");
}),
TestCase("NE succeeds", () =>
{
var field = Field.NE("Park", "here");
Expect.equal(field.Name, "Park", "Field name incorrect");
Expect.equal(field.Op, Op.NE, "Operator incorrect");
Expect.equal(field.Value, "here", "Value incorrect");
Expect.equal(field.Comparison, Comparison.NewNotEqual("here"), "Comparison incorrect");
}),
TestCase("BT succeeds", () =>
{
var field = Field.BT("Age", 18, 49);
Expect.equal(field.Name, "Age", "Field name incorrect");
Expect.equal(field.Op, Op.BT, "Operator incorrect");
Expect.equal(((FSharpList<object>)field.Value).ToArray(), [18, 49], "Value incorrect");
Expect.equal(field.Comparison, Comparison.NewBetween(18, 49), "Comparison incorrect");
}),
TestCase("IN succeeds", () =>
{
var field = Field.IN("Here", [8, 16, 32]);
Expect.equal(field.Name, "Here", "Field name incorrect");
Expect.isTrue(field.Comparison.IsIn, "Comparison incorrect");
Expect.sequenceEqual(((Comparison.In)field.Comparison).Item, [8, 16, 32], "Value incorrect");
}),
TestCase("EX succeeds", () =>
{
var field = Field.EX("Groovy");
Expect.equal(field.Name, "Groovy", "Field name incorrect");
Expect.equal(field.Op, Op.EX, "Operator incorrect");
Expect.isTrue(field.Comparison.IsExists, "Comparison incorrect");
}),
TestCase("NEX succeeds", () =>
{
var field = Field.NEX("Rad");
Expect.equal(field.Name, "Rad", "Field name incorrect");
Expect.equal(field.Op, Op.NEX, "Operator incorrect");
Expect.isTrue(field.Comparison.IsNotExists, "Comparison incorrect");
}),
TestList("NameToPath",
[

View File

@ -7,33 +7,39 @@ open Expecto
let tbl = "test_table"
/// Unit tests for the Op DU
let opTests = testList "Op" [
test "EQ succeeds" {
Expect.equal (string EQ) "=" "The equals operator was not correct"
let comparisonTests = testList "Comparison.OpSql" [
test "Equals succeeds" {
Expect.equal (Equals "").OpSql "=" "The Equals SQL was not correct"
}
test "GT succeeds" {
Expect.equal (string GT) ">" "The greater than operator was not correct"
test "Greater succeeds" {
Expect.equal (Greater "").OpSql ">" "The Greater SQL was not correct"
}
test "GE succeeds" {
Expect.equal (string GE) ">=" "The greater than or equal to operator was not correct"
test "GreaterOrEqual succeeds" {
Expect.equal (GreaterOrEqual "").OpSql ">=" "The GreaterOrEqual SQL was not correct"
}
test "LT succeeds" {
Expect.equal (string LT) "<" "The less than operator was not correct"
test "Less succeeds" {
Expect.equal (Less "").OpSql "<" "The Less SQL was not correct"
}
test "LE succeeds" {
Expect.equal (string LE) "<=" "The less than or equal to operator was not correct"
test "LessOrEqual succeeds" {
Expect.equal (LessOrEqual "").OpSql "<=" "The LessOrEqual SQL was not correct"
}
test "NE succeeds" {
Expect.equal (string NE) "<>" "The not equal to operator was not correct"
test "NotEqual succeeds" {
Expect.equal (NotEqual "").OpSql "<>" "The NotEqual SQL was not correct"
}
test "BT succeeds" {
Expect.equal (string BT) "BETWEEN" """The "between" operator was not correct"""
test "Between succeeds" {
Expect.equal (Between("", "")).OpSql "BETWEEN" "The Between SQL was not correct"
}
test "EX succeeds" {
Expect.equal (string EX) "IS NOT NULL" """The "exists" operator was not correct"""
test "In succeeds" {
Expect.equal (In []).OpSql "IN" "The In SQL was not correct"
}
test "NEX succeeds" {
Expect.equal (string NEX) "IS NULL" """The "not exists" operator was not correct"""
test "Contains succeeds" {
Expect.equal (Contains "").OpSql "|?" "The Contains SQL was not correct"
}
test "Exists succeeds" {
Expect.equal Exists.OpSql "IS NOT NULL" "The Exists SQL was not correct"
}
test "NotExists succeeds" {
Expect.equal NotExists.OpSql "IS NULL" "The NotExists SQL was not correct"
}
]
@ -42,70 +48,70 @@ let fieldTests = testList "Field" [
test "EQ succeeds" {
let field = Field.EQ "Test" 14
Expect.equal field.Name "Test" "Field name incorrect"
Expect.equal field.Op EQ "Operator incorrect"
Expect.equal field.Value 14 "Value incorrect"
Expect.equal field.Comparison (Equals 14) "Comparison incorrect"
Expect.isNone field.ParameterName "The default parameter name should be None"
Expect.isNone field.Qualifier "The default table qualifier should be None"
}
test "GT succeeds" {
let field = Field.GT "Great" "night"
Expect.equal field.Name "Great" "Field name incorrect"
Expect.equal field.Op GT "Operator incorrect"
Expect.equal field.Value "night" "Value incorrect"
Expect.equal field.Comparison (Greater "night") "Comparison incorrect"
Expect.isNone field.ParameterName "The default parameter name should be None"
Expect.isNone field.Qualifier "The default table qualifier should be None"
}
test "GE succeeds" {
let field = Field.GE "Nice" 88L
Expect.equal field.Name "Nice" "Field name incorrect"
Expect.equal field.Op GE "Operator incorrect"
Expect.equal field.Value 88L "Value incorrect"
Expect.equal field.Comparison (GreaterOrEqual 88L) "Comparison incorrect"
Expect.isNone field.ParameterName "The default parameter name should be None"
Expect.isNone field.Qualifier "The default table qualifier should be None"
}
test "LT succeeds" {
let field = Field.LT "Lesser" "seven"
Expect.equal field.Name "Lesser" "Field name incorrect"
Expect.equal field.Op LT "Operator incorrect"
Expect.equal field.Value "seven" "Value incorrect"
Expect.equal field.Comparison (Less "seven") "Comparison incorrect"
Expect.isNone field.ParameterName "The default parameter name should be None"
Expect.isNone field.Qualifier "The default table qualifier should be None"
}
test "LE succeeds" {
let field = Field.LE "Nobody" "KNOWS";
Expect.equal field.Name "Nobody" "Field name incorrect"
Expect.equal field.Op LE "Operator incorrect"
Expect.equal field.Value "KNOWS" "Value incorrect"
Expect.equal field.Comparison (LessOrEqual "KNOWS") "Comparison incorrect"
Expect.isNone field.ParameterName "The default parameter name should be None"
Expect.isNone field.Qualifier "The default table qualifier should be None"
}
test "NE succeeds" {
let field = Field.NE "Park" "here"
Expect.equal field.Name "Park" "Field name incorrect"
Expect.equal field.Op NE "Operator incorrect"
Expect.equal field.Value "here" "Value incorrect"
Expect.equal field.Comparison (NotEqual "here") "Comparison incorrect"
Expect.isNone field.ParameterName "The default parameter name should be None"
Expect.isNone field.Qualifier "The default table qualifier should be None"
}
test "BT succeeds" {
let field = Field.BT "Age" 18 49
Expect.equal field.Name "Age" "Field name incorrect"
Expect.equal field.Op BT "Operator incorrect"
Expect.sequenceEqual (field.Value :?> obj list) [ 18; 49 ] "Value incorrect"
Expect.equal field.Comparison (Between(18, 49)) "Comparison incorrect"
Expect.isNone field.ParameterName "The default parameter name should be None"
Expect.isNone field.Qualifier "The default table qualifier should be None"
}
test "IN succeeds" {
let field = Field.IN "Here" [| 8; 16; 32 |]
Expect.equal field.Name "Here" "Field name incorrect"
Expect.equal field.Comparison (In [| 8; 16; 32 |]) "Comparison incorrect"
Expect.isNone field.ParameterName "The default parameter name should be None"
Expect.isNone field.Qualifier "The default table qualifier should be None"
}
test "EX succeeds" {
let field = Field.EX "Groovy"
Expect.equal field.Name "Groovy" "Field name incorrect"
Expect.equal field.Op EX "Operator incorrect"
Expect.equal field.Comparison Exists "Comparison incorrect"
Expect.isNone field.ParameterName "The default parameter name should be None"
Expect.isNone field.Qualifier "The default table qualifier should be None"
}
test "NEX succeeds" {
let field = Field.NEX "Rad"
Expect.equal field.Name "Rad" "Field name incorrect"
Expect.equal field.Op NEX "Operator incorrect"
Expect.equal field.Comparison NotExists "Comparison incorrect"
Expect.isNone field.ParameterName "The default parameter name should be None"
Expect.isNone field.Qualifier "The default table qualifier should be None"
}
@ -467,7 +473,7 @@ let queryTests = testList "Query" [
/// Tests which do not hit the database
let all = testList "Common" [
opTests
comparisonTests
fieldTests
fieldMatchTests
parameterNameTests