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
+(_:_:)Concatenate twoSQLQueryStrings and return the combined result.+=(_:_:)Append oneSQLQueryStringto another in-place.
Initializers
init(_:)Create a query string from a plain string containing raw SQL.
Instance Methods
appendInterpolation(_:)Embed an arbitarySQLExpressionin the string.appendInterpolation(bind:)Embed anEncodablevalue as a binding in the SQL query.appendInterpolation(binds:)Embed any number ofEncodablevalues as bindings in the SQL query, separating the bind placeholders with commas.appendInterpolation(ident:)Embed aStringas an identifier, as if viaSQLIdentifier.appendInterpolation(idents:joinedBy:)Embed an array ofStrings as a list of SQL identifiers, using thejoinerto separate them.appendInterpolation(literal:)Embed aStringas a literal value, as if viaSQLLiteral.string(_:).appendInterpolation(literals:joinedBy:)Embed an array ofStrings as a list of literal values, placing thejoinerbetween each pair of values.appendInterpolation(raw:)[DEPRECATED] Adds an interpolated string of raw SQL.appendInterpolation(unsafeRaw:)Adds an interpolated string of raw SQL, potentially including associated parameter bindings.serialize(to:)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
SQLAliasEncapsulates SQL’s<expression> [AS] <name>syntax, most often used to declare aliaed names for columns and tables.SQLBetweenAnSQLExpressionwhich constructs SQL of the form<operand> BETWEEN <lowerBound> AND <upperBound>.SQLColumnAn expression representing an optionally table-qualified column in an SQL table.SQLConstraintAn expression representing the combination of a constraint name and algorithm for table constraints.SQLDataTypeRepresents a value’s type in SQL.SQLDirectionDescribes an ordering direction for a given sorting key.SQLDistinctAn expression representing the subexpression of an aggregate function call which specifies whether the aggregate groups over all result rows or only distinct rows.SQLForeignKeyActionAn expression specifying a behavior for a foreign key constraint violation.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.SQLQualifiedTableAn expression representing an optionally second-level-qualified SQL table.