StatementArguments

public struct StatementArguments: CustomStringConvertible, Equatable,
    ExpressibleByArrayLiteral, ExpressibleByDictionaryLiteral

StatementArguments provide values to argument placeholders in raw SQL queries.

Placeholders can take several forms (see https://www.sqlite.org/lang_expr.html#varparam for more information):

  • ?NNN (e.g. ?2): the NNN-th argument (starts at 1)
  • ?: the N-th argument, where N is one greater than the largest argument number already assigned
  • :AAAA (e.g. :name): named argument

  • $AAAA (e.g. $name): named argument

Positional Arguments

To fill question marks placeholders, feed StatementArguments with an array:

db.execute(
    sql: "INSERT ... (?, ?)",
    arguments: StatementArguments(["Arthur", 41]))

// Array literals are automatically converted:
db.execute(
    sql: "INSERT ... (?, ?)",
    arguments: ["Arthur", 41])

Named Arguments

To fill named arguments, feed StatementArguments with a dictionary:

db.execute(
    sql: "INSERT ... (:name, :score)",
    arguments: StatementArguments(["name": "Arthur", "score": 41]))

// Dictionary literals are automatically converted:
db.execute(
    sql: "INSERT ... (:name, :score)",
    arguments: ["name": "Arthur", "score": 41])

Concatenating Arguments

Several arguments can be concatenated and mixed with the append(contentsOf:) method and the +, &+, += operators:

var arguments: StatementArguments = ["Arthur"]
arguments += [41]
db.execute(sql: "INSERT ... (?, ?)", arguments: arguments)

+ and += operators consider that overriding named arguments is a programmer error:

var arguments: StatementArguments = ["name": "Arthur"]
arguments += ["name": "Barbara"]
// fatal error: already defined statement argument: name

&+ and append(contentsOf:) allow overriding named arguments:

var arguments: StatementArguments = ["name": "Arthur"]
arguments = arguments &+ ["name": "Barbara"]
print(arguments)
// Prints ["name": "Barbara"]

Mixed Arguments

It is possible to mix named and positional arguments. Yet this is usually confusing, and it is best to avoid this practice:

let sql = "SELECT ?2 AS two, :foo AS foo, ?1 AS one, :foo AS foo2, :bar AS bar"
var arguments: StatementArguments = [1, 2, "bar"] + ["foo": "foo"]
let row = try Row.fetchOne(db, sql: sql, arguments: arguments)!
print(row)
// Prints [two:2 foo:"foo" one:1 foo2:"foo" bar:"bar"]

Mixed arguments exist as a support for requests like the following:

let players = try Player
    .filter(sql: "team = :team", arguments: ["team": "Blue"])
    .filter(sql: "score > ?", arguments: [1000])
    .fetchAll(db)
  • Creates statement arguments from a sequence of optional values.

    let values: [DatabaseValueConvertible?] = ["foo", 1, nil]
    db.execute(sql: "INSERT ... (?,?,?)", arguments: StatementArguments(values))
    

    Declaration

    Swift

    public init<Sequence>(_ sequence: Sequence) where Sequence : Sequence, Sequence.Element == DatabaseValueConvertible?

    Parameters

    sequence

    A sequence of DatabaseValueConvertible values.

    Return Value

    A StatementArguments.

  • Creates statement arguments from a sequence of optional values.

    let values: [String] = ["foo", "bar"]
    db.execute(sql: "INSERT ... (?,?)", arguments: StatementArguments(values))
    

    Declaration

    Swift

    public init<Sequence>(_ sequence: Sequence) where Sequence : Sequence, Sequence.Element : DatabaseValueConvertible

    Parameters

    sequence

    A sequence of DatabaseValueConvertible values.

    Return Value

    A StatementArguments.

  • Creates statement arguments from any array. The result is nil unless all array elements adopt DatabaseValueConvertible.

    Declaration

    Swift

    public init?(_ array: [Any])

    Parameters

    array

    An array

    Return Value

    A StatementArguments.

  • Creates statement arguments from a sequence of (key, value) dictionary, such as a dictionary.

    let values: [String: DatabaseValueConvertible?] = ["firstName": nil, "lastName": "Miller"]
    db.execute(sql: "INSERT ... (:firstName, :lastName)", arguments: StatementArguments(values))
    

    Declaration

    Swift

    public init(_ dictionary: [String : DatabaseValueConvertible?])

    Parameters

    sequence

    A sequence of (key, value) pairs

    Return Value

    A StatementArguments.

  • Creates statement arguments from a sequence of (key, value) pairs, such as a dictionary.

    let values: [String: DatabaseValueConvertible?] = ["firstName": nil, "lastName": "Miller"]
    db.execute(sql: "INSERT ... (:firstName, :lastName)", arguments: StatementArguments(values))
    

    Declaration

    Swift

    public init<Sequence>(_ sequence: Sequence)
        where Sequence: Swift.Sequence, Sequence.Element == (String, DatabaseValueConvertible?)

    Parameters

    sequence

    A sequence of (key, value) pairs

    Return Value

    A StatementArguments.

  • Creates statement arguments from [AnyHashable: Any].

    The result is nil unless all dictionary keys are strings, and values adopt DatabaseValueConvertible.

    Declaration

    Swift

    public init?(_ dictionary: [AnyHashable : Any])

    Parameters

    dictionary

    A dictionary.

    Return Value

    A StatementArguments.

  • Extends statement arguments with other arguments.

    Positional arguments (provided as arrays) are concatenated:

    var arguments: StatementArguments = [1]
    arguments.append(contentsOf: [2, 3])
    print(arguments)
    // Prints [1, 2, 3]
    

    Named arguments (provided as dictionaries) are updated:

    var arguments: StatementArguments = ["foo": 1]
    arguments.append(contentsOf: ["bar": 2])
    print(arguments)
    // Prints ["foo": 1, "bar": 2]
    

    Arguments that were replaced, if any, are returned:

    var arguments: StatementArguments = ["foo": 1, "bar": 2]
    let replacedValues = arguments.append(contentsOf: ["foo": 3])
    print(arguments)
    // Prints ["foo": 3, "bar": 2]
    print(replacedValues)
    // Prints ["foo": 1]
    

    You can mix named and positional arguments (see documentation of the StatementArguments type for more information about mixed arguments):

    var arguments: StatementArguments = ["foo": 1]
    arguments.append(contentsOf: [2, 3])
    print(arguments)
    // Prints ["foo": 1, 2, 3]
    

    Declaration

    Swift

    public mutating func append(contentsOf arguments: StatementArguments) -> [String : DatabaseValue]
  • Creates a new StatementArguments by extending the left-hand size arguments with the right-hand side arguments.

    Positional arguments (provided as arrays) are concatenated:

    let arguments: StatementArguments = [1] + [2, 3]
    print(arguments)
    // Prints [1, 2, 3]
    

    Named arguments (provided as dictionaries) are updated:

    let arguments: StatementArguments = ["foo": 1] + ["bar": 2]
    print(arguments)
    // Prints ["foo": 1, "bar": 2]
    

    You can mix named and positional arguments (see documentation of the StatementArguments type for more information about mixed arguments):

    let arguments: StatementArguments = ["foo": 1] + [2, 3]
    print(arguments)
    // Prints ["foo": 1, 2, 3]
    

    If the arguments on the right-hand side has named parameters that are already defined on the left, a fatal error is raised:

    let arguments: StatementArguments = ["foo": 1] + ["foo": 2]
    // fatal error: already defined statement argument: foo
    

    This fatal error can be avoided with the &+ operator, or the append(contentsOf:) method.

    Declaration

    Swift

    public static func + (lhs: StatementArguments, rhs: StatementArguments) -> StatementArguments
  • Creates a new StatementArguments by extending the left-hand size arguments with the right-hand side arguments.

    Positional arguments (provided as arrays) are concatenated:

    let arguments: StatementArguments = [1] &+ [2, 3]
    print(arguments)
    // Prints [1, 2, 3]
    

    Named arguments (provided as dictionaries) are updated:

    let arguments: StatementArguments = ["foo": 1] &+ ["bar": 2]
    print(arguments)
    // Prints ["foo": 1, "bar": 2]
    

    You can mix named and positional arguments (see documentation of the StatementArguments type for more information about mixed arguments):

    let arguments: StatementArguments = ["foo": 1] &+ [2, 3]
    print(arguments)
    // Prints ["foo": 1, 2, 3]
    

    If a named arguments is defined in both arguments, the right-hand side wins:

    let arguments: StatementArguments = ["foo": 1] &+ ["foo": 2]
    print(arguments)
    // Prints ["foo": 2]
    

    Declaration

    Swift

    public static func &+ (lhs: StatementArguments, rhs: StatementArguments) -> StatementArguments
  • Extends the left-hand size arguments with the right-hand side arguments.

    Positional arguments (provided as arrays) are concatenated:

    var arguments: StatementArguments = [1]
    arguments += [2, 3]
    print(arguments)
    // Prints [1, 2, 3]
    

    Named arguments (provided as dictionaries) are updated:

    var arguments: StatementArguments = ["foo": 1]
    arguments += ["bar": 2]
    print(arguments)
    // Prints ["foo": 1, "bar": 2]
    

    You can mix named and positional arguments (see documentation of the StatementArguments type for more information about mixed arguments):

    var arguments: StatementArguments = ["foo": 1]
    arguments.append(contentsOf: [2, 3])
    print(arguments)
    // Prints ["foo": 1, 2, 3]
    

    If the arguments on the right-hand side has named parameters that are already defined on the left, a fatal error is raised:

    var arguments: StatementArguments = ["foo": 1]
    arguments += ["foo": 2]
    // fatal error: already defined statement argument: foo
    

    This fatal error can be avoided with the &+ operator, or the append(contentsOf:) method.

    Declaration

    Swift

    public static func += (lhs: inout StatementArguments, rhs: StatementArguments)
  • Returns a StatementArguments from an array literal:

    let arguments: StatementArguments = ["Arthur", 41]
    try db.execute(
        sql: "INSERT INTO player (name, score) VALUES (?, ?)"
        arguments: arguments)
    

    Declaration

    Swift

    public init(arrayLiteral elements: DatabaseValueConvertible?...)
  • Returns a StatementArguments from a dictionary literal:

    let arguments: StatementArguments = ["name": "Arthur", "score": 41]
    try db.execute(
        sql: "INSERT INTO player (name, score) VALUES (:name, :score)"
        arguments: arguments)
    

    Declaration

    Swift

    public init(dictionaryLiteral elements: (String, DatabaseValueConvertible?)...)