WIP on PG Query.whereByFIelds
This commit is contained in:
		
							parent
							
								
									433302d995
								
							
						
					
					
						commit
						e96c449324
					
				@ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user