<commit_before>//
//  QueryParameterType.swift
//  MySQL
//
//  Created by <NAME> on 12/28/15.
//  Copyright © 2015 <NAME>. All rights reserved.
//

import SQLFormatter

public protocol QueryParameter {
    func queryParameter(option: QueryParameterOption) throws -> QueryParameterType
    var omitOnQueryParameter: Bool { get }
}

public extension QueryParameter {
    var omitOnQueryParameter: Bool {
        return false
    }
}

public protocol QueryParameterDictionaryType: QueryParameter {
    func queryParameter() throws -> QueryDictionary
}

public extension QueryParameterDictionaryType {
    func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {
        return try queryParameter().queryParameter(option: option)
    }
}

public protocol QueryParameterOptionType {
}


public struct QueryParameterNull: QueryParameter, ExpressibleByNilLiteral {
    
    public init() {
        
    }
    public init(nilLiteral: ()) {
        
    }
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( "NULL" )
    }
}

public struct QueryDictionary: QueryParameter {
    let dict: [String: QueryParameter?]
    public init(_ dict: [String: QueryParameter?]) {
        self.dict = dict
    }
    public func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {
        var keyVals: [String] = []
        for (k, v) in dict {
            if v == nil || v?.omitOnQueryParameter == false {
                keyVals.append("\(SQLString.escapeId(string: k)) = \(try QueryOptional(v).queryParameter(option: option).escaped())")
            }
        }
        return QueryParameterWrap( keyVals.joined(separator:  ", ") )
    }
}

//extension Dictionary: where Value: QueryParameter, Key: StringLiteralConvertible { }
// not yet supported
// extension Array:QueryParameter where Element: QueryParameter { }


protocol QueryArrayType: QueryParameter {
    
}

public struct QueryArray: QueryParameter, QueryArrayType {
    let arr: [QueryParameter?]
    public init(_ arr: [QueryParameter?]) {
        self.arr = arr
    }
    public init(_ arr: [QueryParameter]) {
        self.arr = arr.map { Optional($0) }
    }
    public func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {
        return QueryParameterWrap( try arr.filter({ val in
            if let valid = val {
                return valid.omitOnQueryParameter == false
            }
            return true
        }).map({
            if let val = $0 as? QueryArrayType {
                return "(" + (try val.queryParameter(option: option).escaped()) + ")"
            }
            return try QueryOptional($0).queryParameter(option: option).escaped()
        }).joined(separator: ", ") )
    }
}



extension Optional: QueryParameter {
    
    public func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {
        guard let value = self else {
            return QueryParameterNull().queryParameter(option: option)
        }
        guard let val = value as? QueryParameter else {
            throw QueryFormatError.castError(actual: "\(value.self)", expected: "QueryParameter", key: "")
        }
        return try val.queryParameter(option: option)
    }
    public var omitOnQueryParameter: Bool {
        guard let value = self else {
            return false
        }
        guard let val = value as? QueryParameter else {
            return false
        }
        return val.omitOnQueryParameter
    }
}


struct QueryOptional: QueryParameter {
    let val: QueryParameter?
    init(_ val: QueryParameter?) {
        self.val = val
    }
    func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {
        guard let val = self.val else {
            return QueryParameterNull().queryParameter(option: option)
        }
        return try val.queryParameter(option: option)
    }
    var omitOnQueryParameter: Bool {
        return val?.omitOnQueryParameter ?? false
    }
}

struct QueryParameterWrap: QueryParameterType {
    let val: String
    init(_ val: String) {
        self.val = val
    }
    func escaped() -> String {
        return val
    }
}

extension String: QueryParameterType {
    public func escaped() -> String {
        return SQLString.escape(string: self)
    }
}

extension String: QueryParameter {
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( SQLString.escape(string: self) )
    }
}

extension Int: QueryParameter {
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( String(self) )
    }
}

extension Int64: QueryParameter {
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( String(self) )
    }
}

extension UInt: QueryParameter {
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( String(self) )
    }
}

extension UInt64: QueryParameter {
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( String(self) )
    }
}

extension Int32: QueryParameter {
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( String(self) )
    }
}

extension UInt32: QueryParameter {
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( String(self) )
    }
}

extension Double: QueryParameter {
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( String(self) )
    }
}

extension Float: QueryParameter {
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( String(self) )<commit_msg>Add QueryParameter conformance for additional integer types<commit_after>//
//  QueryParameterType.swift
//  MySQL
//
//  Created by <NAME> on 12/28/15.
//  Copyright © 2015 <NAME>. All rights reserved.
//

import SQLFormatter

public protocol QueryParameter {
    func queryParameter(option: QueryParameterOption) throws -> QueryParameterType
    var omitOnQueryParameter: Bool { get }
}

public extension QueryParameter {
    var omitOnQueryParameter: Bool {
        return false
    }
}

public protocol QueryParameterDictionaryType: QueryParameter {
    func queryParameter() throws -> QueryDictionary
}

public extension QueryParameterDictionaryType {
    func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {
        return try queryParameter().queryParameter(option: option)
    }
}

public protocol QueryParameterOptionType {
}


public struct QueryParameterNull: QueryParameter, ExpressibleByNilLiteral {
    
    public init() {
        
    }
    public init(nilLiteral: ()) {
        
    }
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( "NULL" )
    }
}

public struct QueryDictionary: QueryParameter {
    let dict: [String: QueryParameter?]
    public init(_ dict: [String: QueryParameter?]) {
        self.dict = dict
    }
    public func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {
        var keyVals: [String] = []
        for (k, v) in dict {
            if v == nil || v?.omitOnQueryParameter == false {
                keyVals.append("\(SQLString.escapeId(string: k)) = \(try QueryOptional(v).queryParameter(option: option).escaped())")
            }
        }
        return QueryParameterWrap( keyVals.joined(separator:  ", ") )
    }
}

//extension Dictionary: where Value: QueryParameter, Key: StringLiteralConvertible { }
// not yet supported
// extension Array:QueryParameter where Element: QueryParameter { }


protocol QueryArrayType: QueryParameter {
    
}

public struct QueryArray: QueryParameter, QueryArrayType {
    let arr: [QueryParameter?]
    public init(_ arr: [QueryParameter?]) {
        self.arr = arr
    }
    public init(_ arr: [QueryParameter]) {
        self.arr = arr.map { Optional($0) }
    }
    public func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {
        return QueryParameterWrap( try arr.filter({ val in
            if let valid = val {
                return valid.omitOnQueryParameter == false
            }
            return true
        }).map({
            if let val = $0 as? QueryArrayType {
                return "(" + (try val.queryParameter(option: option).escaped()) + ")"
            }
            return try QueryOptional($0).queryParameter(option: option).escaped()
        }).joined(separator: ", ") )
    }
}



extension Optional: QueryParameter {
    
    public func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {
        guard let value = self else {
            return QueryParameterNull().queryParameter(option: option)
        }
        guard let val = value as? QueryParameter else {
            throw QueryFormatError.castError(actual: "\(value.self)", expected: "QueryParameter", key: "")
        }
        return try val.queryParameter(option: option)
    }
    public var omitOnQueryParameter: Bool {
        guard let value = self else {
            return false
        }
        guard let val = value as? QueryParameter else {
            return false
        }
        return val.omitOnQueryParameter
    }
}


struct QueryOptional: QueryParameter {
    let val: QueryParameter?
    init(_ val: QueryParameter?) {
        self.val = val
    }
    func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {
        guard let val = self.val else {
            return QueryParameterNull().queryParameter(option: option)
        }
        return try val.queryParameter(option: option)
    }
    var omitOnQueryParameter: Bool {
        return val?.omitOnQueryParameter ?? false
    }
}

struct QueryParameterWrap: QueryParameterType {
    let val: String
    init(_ val: String) {
        self.val = val
    }
    func escaped() -> String {
        return val
    }
}

extension String: QueryParameterType {
    public func escaped() -> String {
        return SQLString.escape(string: self)
    }
}

extension String: QueryParameter {
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( SQLString.escape(string: self) )
    }
}

extension Int: QueryParameter {
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( String(self) )
    }
}

extension UInt: QueryParameter {
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( String(self) )
    }
}

extension Int64: QueryParameter {
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( String(self) )
    }
}

extension Int32: QueryParameter {
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( String(self) )
    }
}

extension Int16: QueryParameter {
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( String(self) )
    }
}

extension Int8: QueryParameter {
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( String(self) )
    }
}

extension UInt64: QueryParameter {
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( String(self) )
    }
}

extension UInt32: QueryParameter {
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( String(self) )
    }
}

extension UInt16: QueryParameter {
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( String(self) )
    }
}

extension UInt8: QueryParameter {
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( String(self) )
    }
}

extension Double: QueryParameter {
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( String(self) )
    }
}

extension Float: QueryParameter {
    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
        return QueryParameterWrap( String(self) )
{'fraction_non_alphanumeric': 0.08989294710327456, 'fraction_numerical': 0.003778337531486146, 'mean_word_length': 3.006622516556291, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4610779', 'n_tokens_mistral': 3283, 'n_tokens_neox': 3204, 'n_words': 872}