Structure
SQLQueryString
struct SQLQueryString
Overview
Query strings are primarily intended for use with SQLRawBuilder, providing for the inclusion of bound parameters in otherwise “raw” queries. The API also supports some of the more commonly used quoting functionality. Query strings are also SQLExpressions, allowing them to be used almost anywhere in SQLKit.
A corollary to this is that, while a given SQLQueryString can represent an entire complete “query” to execute against a database, it can also - as with any SQLExpression but particularly similarly to SQLStatement - represent any lesser fragment of SQL right down to an empty string, or anywhere in between.
Example usage:
// As an entire query:
try await database.raw("""
UPDATE \(ident: "foo")
SET \(ident: "bar")=\(bind: value)
WHERE \(ident: "baz")=\(literal: "bop")
""").run()
// As an SQL fragment (albeit in an extremely contrived fashion):
try await database.update("foo")
.set("bar", to: value)
.where("\(ident: "baz")" as SQLQueryString, .equal, "\(literal: "bop")" as SQLQueryString)
.run()
SQLQueryString’s additional interpolations (such as \(ident:), \(literal:), etc., as well as the ability to embed arbitrary expressions with \(_:)) are useful in particular for writing raw queries which are nonetheless compatible with multiple SQL dialects, such as in the following example:
let messyIdentifer = someCondition ? "abcd{}efgh" : "marmalade!!" // invalid identifiers if not escaped
try await database.raw("""
SELECT \(ident: messyIdentifier) FROM \(ident: "whatever") WHERE \(ident: "x")=\(bind: "foo")
""").all()
// This query renders differently in various dialect:
// - PostgreSQL: SELECT "abcd{}efgh" FROM "whatever" WHERE "x"=$0 ["foo"]
// - MySQL: SELECT `abcd{}efgh` FROM `whatever` WHERE `x`=? ["foo"]
// - SQLite: SELECT "abcd{}efgh" FROM "whatever" WHERE "x"=?0 ["foo"]
Bonus remarks
Even in Swift 5.10, language limitations prevent supporting literal strings everywhere
SQLExpressions are allowed, because the necessary conformance (e.g.extension SQLExpression: ExtensibleByStringLiteral where Self == SQLQueryString) is not allowed by the compiler. The maintainer of this package at the time of this writing considers this to perhaps be a blessing in disguise, given the concern that it is already “too easy” as things stand to embed raw SQL into queries without worrying about injection concerns. As she might put it, “You can already write entire raw queries without escaping any of the things you ought to be,” paying no heed to the fact that she was the one who brought up the topic in the first place.SQLQueryStringis almost identical toSQLStatement; they track content identically, operate by building up output based on progressive inputs, and often (indeed, usually) represent entire queries. At this point, the only remaining reason they haven’t been made into a single type is the confusion wouldn’t be worth it in light of the expectation, at the time of this writing, that this package will soon be receiving a major version bump, at which point far more opportunities will indeed abound.
Topics
Operators
static func + (SQLQueryString, SQLQueryString) -> SQLQueryStringConcatenate twoSQLQueryStrings and return the combined result.static func += (inout SQLQueryString, SQLQueryString)Append oneSQLQueryStringto another in-place.
Initializers
init(String)Create a query string from a plain string containing raw SQL.
Instance Methods
func appendInterpolation(_:)Embed an arbitarySQLExpressionin the string.func appendInterpolation(bind: any Encodable & Sendable)Embed anEncodablevalue as a binding in the SQL query.func appendInterpolation(binds: [any Encodable & Sendable])Embed any number ofEncodablevalues as bindings in the SQL query, separating the bind placeholders with commas.func appendInterpolation(ident: String)Embed aStringas an identifier, as if viaSQLIdentifier.func appendInterpolation(idents: [String], joinedBy: String)Embed an array ofStrings as a list of SQL identifiers, using thejoinerto separate them.func appendInterpolation(literal:)Embed aStringas a literal value, as if viaSQLLiteral.string(_:).func appendInterpolation(literals: [String], joinedBy: String)Embed an array ofStrings as a list of literal values, placing thejoinerbetween each pair of values.func appendInterpolation(raw: String)[DEPRECATED] Adds an interpolated string of raw SQL.func appendInterpolation(unsafeRaw: String)Adds an interpolated string of raw SQL, potentially including associated parameter bindings.func serialize(to: inout SQLSerializer)Invoked when a request is made to serialize the expression to raw SQL.
Default Implementations
Relationships
Conforms To
SQLExpressionSwift.ExpressibleByExtendedGraphemeClusterLiteralSwift.ExpressibleByStringInterpolationSwift.ExpressibleByStringLiteralSwift.ExpressibleByUnicodeScalarLiteralSwift.SendableSwift.SendableMetatypeSwift.StringInterpolationProtocol
See Also
Basic Expressions
struct SQLAliasEncapsulates SQL’s<expression> [AS] <name>syntax, most often used to declare aliaed names for columns and tables.struct SQLBetweenAnSQLExpressionwhich constructs SQL of the form<operand> BETWEEN <lowerBound> AND <upperBound>.struct SQLColumnAn expression representing an optionally table-qualified column in an SQL table.struct SQLConstraintAn expression representing the combination of a constraint name and algorithm for table constraints.enum SQLDataTypeRepresents a value’s type in SQL.enum SQLDirectionDescribes an ordering direction for a given sorting key.struct SQLDistinctAn expression representing the subexpression of an aggregate function call which specifies whether the aggregate groups over all result rows or only distinct rows.enum SQLForeignKeyActionAn expression specifying a behavior for a foreign key constraint violation.struct SQLNestedSubpathExpressionA “nested subpath” expression is used to descend into the “deeper” structure of a non-scalar value, such as a dictionary, array, or JSON value.struct SQLQualifiedTableAn expression representing an optionally second-level-qualified SQL table.