From aad255706725f7ebb821b3ece5697a4a793bb801 Mon Sep 17 00:00:00 2001 From: Gwynne Raskind Date: Wed, 16 Apr 2025 13:24:08 -0500 Subject: [PATCH 1/5] Rename SQLRaw to SQLUnsafeRaw, keeping the old name as a deprecated typealias. --- .../Builders/Prototypes/SQLJoinBuilder.swift | 4 ++-- Sources/SQLKit/Database/SQLDialect.swift | 4 ++-- .../SQLExpressions+Deprecated.swift | 5 +++- .../Expressions/Basics/SQLDataType.swift | 14 +++++------ .../Expressions/Basics/SQLQueryString.swift | 12 +++++----- .../Clauses/SQLColumnDefinition.swift | 2 +- .../Expressions/Queries/SQLAlterTable.swift | 6 ++--- .../Queries/SQLCreateTrigger.swift | 2 +- .../Expressions/Queries/SQLSelect.swift | 2 +- Sources/SQLKit/Expressions/SQLStatement.swift | 24 +++++++++---------- .../Expressions/Syntax/SQLIdentifier.swift | 2 +- .../SQLKit/Expressions/Syntax/SQLList.swift | 6 ++--- .../Expressions/Syntax/SQLLiteral.swift | 2 +- .../SQLKit/Expressions/Syntax/SQLRaw.swift | 12 +++++----- .../SQLBenchmark+Codable.swift | 2 +- .../SQLBenchmark+JSONPaths.swift | 2 +- 16 files changed, 52 insertions(+), 49 deletions(-) diff --git a/Sources/SQLKit/Builders/Prototypes/SQLJoinBuilder.swift b/Sources/SQLKit/Builders/Prototypes/SQLJoinBuilder.swift index fe69810e..1abbd844 100644 --- a/Sources/SQLKit/Builders/Prototypes/SQLJoinBuilder.swift +++ b/Sources/SQLKit/Builders/Prototypes/SQLJoinBuilder.swift @@ -82,8 +82,8 @@ extension SQLJoinBuilder { public func join(_ table: any SQLExpression, method: any SQLExpression = SQLJoinMethod.inner, using columns: any SQLExpression) -> Self { // TODO: Make ``SQLJoin`` aware of the `USING` syntax; this method is hacky and somewhat driver-specific. self.joins.append(SQLList([ - method, SQLRaw("JOIN"), table, SQLRaw("USING"), SQLGroupExpression(columns) - ], separator: SQLRaw(" "))) + method, SQLUnsafeRaw("JOIN"), table, SQLUnsafeRaw("USING"), SQLGroupExpression(columns) + ], separator: SQLUnsafeRaw(" "))) return self } } diff --git a/Sources/SQLKit/Database/SQLDialect.swift b/Sources/SQLKit/Database/SQLDialect.swift index 41d7b030..cca0b82e 100644 --- a/Sources/SQLKit/Database/SQLDialect.swift +++ b/Sources/SQLKit/Database/SQLDialect.swift @@ -483,7 +483,7 @@ extension SQLDialect { /// Default implementation of ``literalStringQuote-3ur0m``. @inlinable public var literalStringQuote: any SQLExpression { - SQLRaw("'") + SQLUnsafeRaw("'") } /// Default implementation of ``autoIncrementFunction-1ktxy``. @@ -495,7 +495,7 @@ extension SQLDialect { /// Default implementation of ``literalDefault-7nz7t``. @inlinable public var literalDefault: any SQLExpression { - SQLRaw("DEFAULT") + SQLUnsafeRaw("DEFAULT") } /// Default implementation of ``supportsIfExists-5dxcu``. diff --git a/Sources/SQLKit/Deprecated/SQLExpressions+Deprecated.swift b/Sources/SQLKit/Deprecated/SQLExpressions+Deprecated.swift index 6e884d74..54ca6d25 100644 --- a/Sources/SQLKit/Deprecated/SQLExpressions+Deprecated.swift +++ b/Sources/SQLKit/Deprecated/SQLExpressions+Deprecated.swift @@ -72,7 +72,10 @@ extension SQLQueryString { } } -extension SQLRaw { +@available(*, deprecated, renamed: "SQLUnsafeRaw", message: "SQLRaw has been renamed to SQLUnsafeRaw.") +public typealias SQLRaw = SQLUnsafeRaw + +extension SQLUnsafeRaw { @available(*, deprecated, message: "Binds set in an `SQLRaw` are ignored. Use `SQLBind`instead.") @inlinable public init(_ sql: String, _ binds: [any Encodable & Sendable]) { diff --git a/Sources/SQLKit/Expressions/Basics/SQLDataType.swift b/Sources/SQLKit/Expressions/Basics/SQLDataType.swift index 1f037933..16b9ec74 100644 --- a/Sources/SQLKit/Expressions/Basics/SQLDataType.swift +++ b/Sources/SQLKit/Expressions/Basics/SQLDataType.swift @@ -32,7 +32,7 @@ public enum SQLDataType: SQLExpression { /// > Note: Implemented as a static var rather than a new case for now because adding new cases to a public enum /// > is a source-breaking change. public static var timestamp: Self { - .custom(SQLRaw("TIMESTAMP")) + .custom(SQLUnsafeRaw("TIMESTAMP")) } /// Translates to the serialization of the given expression, unless overridden by dialect. @@ -48,17 +48,17 @@ public enum SQLDataType: SQLExpression { } else { switch self { case .smallint: - sql = SQLRaw("SMALLINT") + sql = SQLUnsafeRaw("SMALLINT") case .int: - sql = SQLRaw("INTEGER") + sql = SQLUnsafeRaw("INTEGER") case .bigint: - sql = SQLRaw("BIGINT") + sql = SQLUnsafeRaw("BIGINT") case .text: - sql = SQLRaw("TEXT") + sql = SQLUnsafeRaw("TEXT") case .real: - sql = SQLRaw("REAL") + sql = SQLUnsafeRaw("REAL") case .blob: - sql = SQLRaw("BLOB") + sql = SQLUnsafeRaw("BLOB") case .custom(let exp): sql = exp } diff --git a/Sources/SQLKit/Expressions/Basics/SQLQueryString.swift b/Sources/SQLKit/Expressions/Basics/SQLQueryString.swift index 1d3617e8..a93ad86b 100644 --- a/Sources/SQLKit/Expressions/Basics/SQLQueryString.swift +++ b/Sources/SQLKit/Expressions/Basics/SQLQueryString.swift @@ -62,7 +62,7 @@ public struct SQLQueryString: SQLExpression, ExpressibleByStringInterpolation, S /// Create a query string from a plain string containing raw SQL. @inlinable public init(_ string: String) { - self.fragments = [SQLRaw(string)] + self.fragments = [SQLUnsafeRaw(string)] } // See `SQLExpression.serialize(to:)`. @@ -98,7 +98,7 @@ extension SQLQueryString { // See `StringInterpolationProtocol.appendLiteral(_:)`. @inlinable public mutating func appendLiteral(_ literal: String) { - self.fragments.append(SQLRaw(literal)) + self.fragments.append(SQLUnsafeRaw(literal)) } } @@ -111,7 +111,7 @@ extension SQLQueryString { /// > a purpose-specific expression instead whenever possible. @inlinable public mutating func appendInterpolation(unsafeRaw value: String) { - self.fragments.append(SQLRaw(value)) + self.fragments.append(SQLUnsafeRaw(value)) } /// Embed an `Encodable` value as a binding in the SQL query. @@ -180,7 +180,7 @@ extension SQLQueryString { /// ``` @inlinable public mutating func appendInterpolation(literals: [String], joinedBy joiner: String) { - self.fragments.append(SQLList(literals.map { SQLLiteral.string($0) }, separator: SQLRaw(joiner))) + self.fragments.append(SQLList(literals.map { SQLLiteral.string($0) }, separator: SQLUnsafeRaw(joiner))) } /// Embed a `String` as an identifier, as if via ``SQLIdentifier``. @@ -210,7 +210,7 @@ extension SQLQueryString { /// ``` @inlinable public mutating func appendInterpolation(idents: [String], joinedBy joiner: String) { - self.fragments.append(SQLList(idents.map { SQLIdentifier($0) }, separator: SQLRaw(joiner))) + self.fragments.append(SQLList(idents.map { SQLIdentifier($0) }, separator: SQLUnsafeRaw(joiner))) } /// Embed an arbitary ``SQLExpression`` in the string. @@ -245,7 +245,7 @@ extension Sequence { /// - Returns: A single, concatenated string. @inlinable public func joined(separator: String = "") -> SQLQueryString { - self.joined(separator: SQLRaw(separator)) + self.joined(separator: SQLUnsafeRaw(separator)) } /// Returns a new ``SQLQueryString`` formed by concatenating the elements of the sequence, adding the given diff --git a/Sources/SQLKit/Expressions/Clauses/SQLColumnDefinition.swift b/Sources/SQLKit/Expressions/Clauses/SQLColumnDefinition.swift index 67f7659e..5e6807ea 100644 --- a/Sources/SQLKit/Expressions/Clauses/SQLColumnDefinition.swift +++ b/Sources/SQLKit/Expressions/Clauses/SQLColumnDefinition.swift @@ -53,7 +53,7 @@ public struct SQLColumnDefinition: SQLExpression { serializer.statement { $0.append(self.column, self.dataType) if !self.constraints.isEmpty { - $0.append(SQLList(self.constraints, separator: SQLRaw(" "))) + $0.append(SQLList(self.constraints, separator: SQLUnsafeRaw(" "))) } } } diff --git a/Sources/SQLKit/Expressions/Queries/SQLAlterTable.swift b/Sources/SQLKit/Expressions/Queries/SQLAlterTable.swift index b236ac4e..eb6bf319 100644 --- a/Sources/SQLKit/Expressions/Queries/SQLAlterTable.swift +++ b/Sources/SQLKit/Expressions/Queries/SQLAlterTable.swift @@ -60,9 +60,9 @@ public struct SQLAlterTable: SQLExpression { // Emit the query anyway so the error will propagate when the database rejects it. } - let additions = (self.addColumns + self.addTableConstraints).map { (verb: SQLRaw("ADD"), definition: $0) } - let removals = (self.dropColumns + self.dropTableConstraints).map { (verb: SQLRaw("DROP"), definition: $0) } - let modifications = self.modifyColumns.map { (verb: syntax.alterColumnDefinitionClause ?? SQLRaw("__INVALID__"), definition: $0) } + let additions = (self.addColumns + self.addTableConstraints).map { (verb: SQLUnsafeRaw("ADD"), definition: $0) } + let removals = (self.dropColumns + self.dropTableConstraints).map { (verb: SQLUnsafeRaw("DROP"), definition: $0) } + let modifications = self.modifyColumns.map { (verb: syntax.alterColumnDefinitionClause ?? SQLUnsafeRaw("__INVALID__"), definition: $0) } let alterations = additions + removals + modifications serializer.statement { diff --git a/Sources/SQLKit/Expressions/Queries/SQLCreateTrigger.swift b/Sources/SQLKit/Expressions/Queries/SQLCreateTrigger.swift index b97b2711..6ad855e3 100644 --- a/Sources/SQLKit/Expressions/Queries/SQLCreateTrigger.swift +++ b/Sources/SQLKit/Expressions/Queries/SQLCreateTrigger.swift @@ -196,7 +196,7 @@ public struct SQLCreateTrigger: SQLExpression { } if syntax.contains(.supportsBody), let body = self.body { - $0.append("BEGIN", SQLList(body, separator: SQLRaw(" ")), "END;") + $0.append("BEGIN", SQLList(body, separator: SQLUnsafeRaw(" ")), "END;") } else if let procedure = self.procedure { $0.append("EXECUTE PROCEDURE", procedure) } diff --git a/Sources/SQLKit/Expressions/Queries/SQLSelect.swift b/Sources/SQLKit/Expressions/Queries/SQLSelect.swift index 6d51d44c..6a69deaf 100644 --- a/Sources/SQLKit/Expressions/Queries/SQLSelect.swift +++ b/Sources/SQLKit/Expressions/Queries/SQLSelect.swift @@ -112,7 +112,7 @@ public struct SQLSelect: SQLExpression { $0.append("FROM", SQLList(self.tables)) } if !self.joins.isEmpty { - $0.append(SQLList(self.joins, separator: SQLRaw(" "))) + $0.append(SQLList(self.joins, separator: SQLUnsafeRaw(" "))) } if self.predicate != nil { $0.append("WHERE", self.predicate) diff --git a/Sources/SQLKit/Expressions/SQLStatement.swift b/Sources/SQLKit/Expressions/SQLStatement.swift index 9a595c62..00738878 100644 --- a/Sources/SQLKit/Expressions/SQLStatement.swift +++ b/Sources/SQLKit/Expressions/SQLStatement.swift @@ -131,7 +131,7 @@ public struct SQLStatement: SQLExpression { /// Add raw text to the statement output. @inlinable public mutating func append(_ raw: String) { - self.append(SQLRaw(raw)) + self.append(SQLUnsafeRaw(raw)) } /// Add an unserialized ``SQLExpression`` to the statement output. @@ -159,13 +159,13 @@ public struct SQLStatement: SQLExpression { /// Add two raw text strings to the statement output. @inlinable public mutating func append(_ raw1: String, _ raw2: String) { - self.parts.append(contentsOf: [SQLRaw(raw1), SQLRaw(raw2)]) + self.parts.append(contentsOf: [SQLUnsafeRaw(raw1), SQLUnsafeRaw(raw2)]) } /// Add raw text and an unserialized ``SQLExpression`` to the statement output, in that order. @inlinable public mutating func append(_ raw: String, _ part: any SQLExpression) { - self.parts.append(contentsOf: [SQLRaw(raw), part]) + self.parts.append(contentsOf: [SQLUnsafeRaw(raw), part]) } /// Add raw text and an optional unserialized ``SQLExpression`` to the statement output, in that order. @@ -175,13 +175,13 @@ public struct SQLStatement: SQLExpression { /// > compiler to infer the optionality as needed as with, for example, ``append(_:_:)-4g2tf``. @inlinable public mutating func append(_ raw: String, _ part: (any SQLExpression)?) { - self.parts.append(contentsOf: [SQLRaw(raw), part].compactMap { $0 }) + self.parts.append(contentsOf: [SQLUnsafeRaw(raw), part].compactMap { $0 }) } /// Add an optional unserialized ``SQLExpression`` and raw text to the statement output, in that order. @inlinable public mutating func append(_ part: (any SQLExpression)?, _ raw: String) { - self.parts.append(contentsOf: [part, SQLRaw(raw)].compactMap { $0 }) + self.parts.append(contentsOf: [part, SQLUnsafeRaw(raw)].compactMap { $0 }) } /// Add two optional unserialized ``SQLExpression``s to the statement output. @@ -195,43 +195,43 @@ public struct SQLStatement: SQLExpression { /// Add three raw text strings to the statement. @inlinable public mutating func append(_ p1: String, _ p2: String, _ p3: String) { - self.parts.append(contentsOf: [SQLRaw(p1), SQLRaw(p2), SQLRaw(p3)]) + self.parts.append(contentsOf: [SQLUnsafeRaw(p1), SQLUnsafeRaw(p2), SQLUnsafeRaw(p3)]) } /// Add an optional unserialized ``SQLExpression`` and two raw text strings to the statement output. @inlinable public mutating func append(_ p1: (any SQLExpression)?, _ p2: String, _ p3: String) { - self.parts.append(contentsOf: [p1, SQLRaw(p2), SQLRaw(p3)].compactMap { $0 }) + self.parts.append(contentsOf: [p1, SQLUnsafeRaw(p2), SQLUnsafeRaw(p3)].compactMap { $0 }) } /// Add raw text, an optional unserialized ``SQLExpression``, and more raw text to the statement output. @inlinable public mutating func append(_ p1: String, _ p2: (any SQLExpression)?, _ p3: String) { - self.parts.append(contentsOf: [SQLRaw(p1), p2, SQLRaw(p3)].compactMap { $0 }) + self.parts.append(contentsOf: [SQLUnsafeRaw(p1), p2, SQLUnsafeRaw(p3)].compactMap { $0 }) } /// Add two optional unserialized ``SQLExpression``s and raw text to the statement output. @inlinable public mutating func append(_ p1: (any SQLExpression)?, _ p2: (any SQLExpression)?, _ p3: String) { - self.parts.append(contentsOf: [p1, p2, SQLRaw(p3)].compactMap { $0 }) + self.parts.append(contentsOf: [p1, p2, SQLUnsafeRaw(p3)].compactMap { $0 }) } /// Add two raw texts strings and an optional unserialized ``SQLExpression`` to the statement output, in that order. @inlinable public mutating func append(_ p1: String, _ p2: String, _ p3: (any SQLExpression)?) { - self.parts.append(contentsOf: [SQLRaw(p1), SQLRaw(p2), p3].compactMap { $0 }) + self.parts.append(contentsOf: [SQLUnsafeRaw(p1), SQLUnsafeRaw(p2), p3].compactMap { $0 }) } /// Add raw text and two optional unserialized ``SQLExpression``s to the statement output. @inlinable public mutating func append(_ p1: String, _ p2: (any SQLExpression)?, _ p3: (any SQLExpression)?) { - self.parts.append(contentsOf: [SQLRaw(p1), p2, p3].compactMap { $0 }) + self.parts.append(contentsOf: [SQLUnsafeRaw(p1), p2, p3].compactMap { $0 }) } /// Add an optional unserialized ``SQLExpression``, raw text, and an optional unserialized ``SQLExpression`` to the statement output. @inlinable public mutating func append(_ p1: (any SQLExpression)?, _ p2: String, _ p3: (any SQLExpression)?) { - self.parts.append(contentsOf: [p1, SQLRaw(p2), p3].compactMap { $0 }) + self.parts.append(contentsOf: [p1, SQLUnsafeRaw(p2), p3].compactMap { $0 }) } /// Add three optional unserialized ``SQLExpression``s to the statement output. diff --git a/Sources/SQLKit/Expressions/Syntax/SQLIdentifier.swift b/Sources/SQLKit/Expressions/Syntax/SQLIdentifier.swift index a1eed59b..978604ac 100644 --- a/Sources/SQLKit/Expressions/Syntax/SQLIdentifier.swift +++ b/Sources/SQLKit/Expressions/Syntax/SQLIdentifier.swift @@ -38,7 +38,7 @@ public struct SQLIdentifier: SQLExpression, ExpressibleByStringLiteral { /// major version bump). Fortunately, in practice all knwon dialects always return their quoting characters /// as instances of ``SQLRaw``, so we check for that case and perform the appropriate quoting and/or escaping /// as needed, while falling back to quoting without escaping if the check fails. - if let rawQuote = (serializer.dialect.identifierQuote as? SQLRaw)?.sql { + if let rawQuote = (serializer.dialect.identifierQuote as? SQLUnsafeRaw)?.sql { serializer.write("\(rawQuote)\(self.string.sqlkit_replacing(rawQuote, with: "\(rawQuote)\(rawQuote)"))\(rawQuote)") } else { serializer.dialect.identifierQuote.serialize(to: &serializer) diff --git a/Sources/SQLKit/Expressions/Syntax/SQLList.swift b/Sources/SQLKit/Expressions/Syntax/SQLList.swift index a6309c36..f03e23c4 100644 --- a/Sources/SQLKit/Expressions/Syntax/SQLList.swift +++ b/Sources/SQLKit/Expressions/Syntax/SQLList.swift @@ -11,7 +11,7 @@ /// // "'a', 'b'" /// print(database.serialize(SQLList(SQLLiteral.string("a"), SQLLiteral.string("b"), separator: SQLBinaryOperator.and)).sql) /// // "'a'AND'b'" -/// print(database.serialize(SQLList(SQLLiteral.string("a"), SQLLiteral.string("b"), separator: SQLRaw(" AND ")).sql) +/// print(database.serialize(SQLList(SQLLiteral.string("a"), SQLLiteral.string("b"), separator: SQLUnsafeRaw(" AND ")).sql) /// // "'a' AND 'b'" /// ``` public struct SQLList: SQLExpression { @@ -25,9 +25,9 @@ public struct SQLList: SQLExpression { /// /// - Parameters: /// - expressions: The list of expressions. - /// - separator: A separator expression. If not given, defaults to `SQLRaw(", ")`. + /// - separator: A separator expression. If not given, defaults to `SQLUnsafeRaw(", ")`. @inlinable - public init(_ expressions: [any SQLExpression], separator: any SQLExpression = SQLRaw(", ")) { + public init(_ expressions: [any SQLExpression], separator: any SQLExpression = SQLUnsafeRaw(", ")) { self.expressions = expressions self.separator = separator } diff --git a/Sources/SQLKit/Expressions/Syntax/SQLLiteral.swift b/Sources/SQLKit/Expressions/Syntax/SQLLiteral.swift index 04574400..4228bf6c 100644 --- a/Sources/SQLKit/Expressions/Syntax/SQLLiteral.swift +++ b/Sources/SQLKit/Expressions/Syntax/SQLLiteral.swift @@ -54,7 +54,7 @@ public enum SQLLiteral: SQLExpression { case .string(let string): /// See ``SQLIdentifier/serialize(to:)`` for a discussion on why this is written the way it is. - if let rawQuote = (serializer.dialect.literalStringQuote as? SQLRaw)?.sql { + if let rawQuote = (serializer.dialect.literalStringQuote as? SQLUnsafeRaw)?.sql { serializer.write("\(rawQuote)\(string.sqlkit_replacing(rawQuote, with: "\(rawQuote)\(rawQuote)"))\(rawQuote)") } else { serializer.dialect.literalStringQuote.serialize(to: &serializer) diff --git a/Sources/SQLKit/Expressions/Syntax/SQLRaw.swift b/Sources/SQLKit/Expressions/Syntax/SQLRaw.swift index da0faa71..3f72e24b 100644 --- a/Sources/SQLKit/Expressions/Syntax/SQLRaw.swift +++ b/Sources/SQLKit/Expressions/Syntax/SQLRaw.swift @@ -1,17 +1,17 @@ /// A fundamental syntactical expression - an arbitrary string of raw SQL with no escaping or formating of any kind. /// -/// Users should almost never need to use ``SQLRaw`` directly; there is almost always a better/safer/more specific -/// expression available for any given purpose. The most common use for ``SQLRaw`` by end users is to represent SQL +/// Users should almost never need to use ``SQLUnsafeRaw`` directly; there is almost always a better/safer/more specific +/// expression available for any given purpose. The most common use for ``SQLUnsafeRaw`` by end users is to represent SQL /// keywords specific to a dialect, such as `SQLRaw("EXPLAIN VERBOSE")`. /// -/// In effect, ``SQLRaw`` is nothing but a wrapper which makes `String`s into ``SQLExpression``s, since conforming +/// In effect, ``SQLUnsafeRaw`` is nothing but a wrapper which makes `String`s into ``SQLExpression``s, since conforming /// `String` directly to the protocol would cause numerous issues with SQLKit's existing public API (yet another design -/// flaw). In the past, ``SQLRaw`` was intended to also contain bound values to be serialized with the text, but this +/// flaw). In the past, ``SQLUnsafeRaw`` was intended to also contain bound values to be serialized with the text, but this /// functionality was never implemented fully and is now entirely defunct. /// -/// > Note: Just to add further insult to injury, ``SQLRaw`` is entirely redundant in the presence of +/// > Note: Just to add further insult to injury, ``SQLUnsafeRaw`` is entirely redundant in the presence of /// > ``SQLQueryString`` and ``SQLStatement``, but is used so pervasively that it cannot reasonably be deprecated. -public struct SQLRaw: SQLExpression { +public struct SQLUnsafeRaw: SQLExpression { /// The raw SQL text serialized by this expression. public var sql: String diff --git a/Sources/SQLKitBenchmark/SQLBenchmark+Codable.swift b/Sources/SQLKitBenchmark/SQLBenchmark+Codable.swift index 252d2030..b9c6e23d 100644 --- a/Sources/SQLKitBenchmark/SQLBenchmark+Codable.swift +++ b/Sources/SQLKitBenchmark/SQLBenchmark+Codable.swift @@ -16,7 +16,7 @@ extension SQLBenchmarker { try await $0.create(table: "planets") .column("id", type: .bigint, .primaryKey) .column("name", type: .text, [.default(SQLLiteral.string("Unamed Planet")), .notNull]) - .column("is_inhabited", type: .custom(SQLRaw("boolean")), .notNull) + .column("is_inhabited", type: .custom(SQLUnsafeRaw("boolean")), .notNull) .column("galaxyID", type: .bigint, .references("galaxies", "id")) .run() diff --git a/Sources/SQLKitBenchmark/SQLBenchmark+JSONPaths.swift b/Sources/SQLKitBenchmark/SQLBenchmark+JSONPaths.swift index 2af8bd67..fcfbf569 100644 --- a/Sources/SQLKitBenchmark/SQLBenchmark+JSONPaths.swift +++ b/Sources/SQLKitBenchmark/SQLBenchmark+JSONPaths.swift @@ -9,7 +9,7 @@ extension SQLBenchmarker { .run() try await $0.create(table: "planet_metadata") .column("id", type: .bigint, .primaryKey(autoIncrement: $0.dialect.supportsAutoIncrement)) - .column("metadata", type: .custom(SQLRaw($0.dialect.name == "postgresql" ? "jsonb" : "json"))) + .column("metadata", type: .custom(SQLUnsafeRaw($0.dialect.name == "postgresql" ? "jsonb" : "json"))) .run() // insert From ce13cc04bea3ba49be668f808f83d0d165b36e04 Mon Sep 17 00:00:00 2001 From: Gwynne Raskind Date: Wed, 16 Apr 2025 17:36:07 -0500 Subject: [PATCH 2/5] Rename the SQLRaw.swift source file too --- .../Expressions/Syntax/{SQLRaw.swift => SQLUnsafeRaw.swift} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Sources/SQLKit/Expressions/Syntax/{SQLRaw.swift => SQLUnsafeRaw.swift} (100%) diff --git a/Sources/SQLKit/Expressions/Syntax/SQLRaw.swift b/Sources/SQLKit/Expressions/Syntax/SQLUnsafeRaw.swift similarity index 100% rename from Sources/SQLKit/Expressions/Syntax/SQLRaw.swift rename to Sources/SQLKit/Expressions/Syntax/SQLUnsafeRaw.swift From a68df7f07a3875fe7e8bcf0f55da9f8206f754dd Mon Sep 17 00:00:00 2001 From: Gwynne Raskind Date: Wed, 16 Apr 2025 17:56:17 -0500 Subject: [PATCH 3/5] Clean up remaining instances of SQLRaw -> SQLUnsafeRaw (mostly in comments and tests) --- Sources/SQLKit/Database/SQLDialect.swift | 10 ++-- .../SQLExpressions+Deprecated.swift | 2 +- .../SQLQueryBuilders+Deprecated.swift | 8 ++-- Sources/SQLKit/Docs.docc/SQLKit.md | 2 +- .../Expressions/Basics/SQLQueryString.swift | 2 +- .../Expressions/Clauses/SQLJoinMethod.swift | 2 +- .../SQLKit/Expressions/SQLExpression.swift | 2 +- Sources/SQLKit/Expressions/SQLStatement.swift | 6 +-- .../Syntax/SQLBinaryOperator.swift | 2 +- .../Expressions/Syntax/SQLIdentifier.swift | 2 +- .../SQLKit/Expressions/Syntax/SQLList.swift | 2 +- .../Expressions/Syntax/SQLUnsafeRaw.swift | 4 +- Tests/SQLKitTests/AsyncTests.swift | 4 +- Tests/SQLKitTests/BaseTests.swift | 46 +++++++++---------- Tests/SQLKitTests/BasicQueryTests.swift | 4 +- Tests/SQLKitTests/DeprecatedTests.swift | 2 +- .../SQLCommonTableExpressionTests.swift | 10 ++-- .../SQLCreateDropTriggerTests.swift | 8 ++-- Tests/SQLKitTests/SQLCreateTableTests.swift | 12 ++--- Tests/SQLKitTests/SQLExpressionTests.swift | 2 +- Tests/SQLKitTests/TestMocks.swift | 26 +++++------ 21 files changed, 79 insertions(+), 79 deletions(-) diff --git a/Sources/SQLKit/Database/SQLDialect.swift b/Sources/SQLKit/Database/SQLDialect.swift index cca0b82e..695e3b6c 100644 --- a/Sources/SQLKit/Database/SQLDialect.swift +++ b/Sources/SQLKit/Database/SQLDialect.swift @@ -18,7 +18,7 @@ public protocol SQLDialect: Sendable { /// No default is provided. var name: String { get } - /// An expression (usually an ``SQLRaw``) giving the character(s) used to quote SQL + /// An expression (usually an ``SQLUnsafeRaw``) giving the character(s) used to quote SQL /// identifiers, such as table and column names. /// /// The identifier quote is placed immediately preceding and following each identifier. @@ -26,7 +26,7 @@ public protocol SQLDialect: Sendable { /// No default is provided. var identifierQuote: any SQLExpression { get } - /// An expression (usually an ``SQLRaw``) giving the character(s) used to quote literal + /// An expression (usually an ``SQLUnsafeRaw``) giving the character(s) used to quote literal /// string values which appear in a query, such as enumerator names. /// /// The literal quote is placed immediately preceding and following each string literal. @@ -82,7 +82,7 @@ public protocol SQLDialect: Sendable { /// the first parameter has position `1`. This value is guaranteed to be greater than zero. func bindPlaceholder(at position: Int) -> any SQLExpression - /// A function which returns an SQL expression (usually an ``SQLRaw``) representing the given + /// A function which returns an SQL expression (usually an ``SQLUnsafeRaw``) representing the given /// literal boolean value. /// /// No default is provided. @@ -90,13 +90,13 @@ public protocol SQLDialect: Sendable { /// - Parameter value: The boolean value to represent. func literalBoolean(_ value: Bool) -> any SQLExpression - /// An expression (usually an ``SQLRaw``) giving the syntax used to express both "use this as + /// An expression (usually an ``SQLUnsafeRaw``) giving the syntax used to express both "use this as /// the default value" in a column definition and "use the default value for this column" in /// a value list. /// /// ``SQLLiteral/default`` always serializes to this expression. /// - /// Defaults to `SQLRaw("DEFAULT")`. + /// Defaults to `SQLUnsafeRaw("DEFAULT")`. var literalDefault: any SQLExpression { get } /// `true` if the dialect supports the `IF EXISTS` modifier for all types of `DROP` queries diff --git a/Sources/SQLKit/Deprecated/SQLExpressions+Deprecated.swift b/Sources/SQLKit/Deprecated/SQLExpressions+Deprecated.swift index 54ca6d25..1ce7b5e5 100644 --- a/Sources/SQLKit/Deprecated/SQLExpressions+Deprecated.swift +++ b/Sources/SQLKit/Deprecated/SQLExpressions+Deprecated.swift @@ -76,7 +76,7 @@ extension SQLQueryString { public typealias SQLRaw = SQLUnsafeRaw extension SQLUnsafeRaw { - @available(*, deprecated, message: "Binds set in an `SQLRaw` are ignored. Use `SQLBind`instead.") + @available(*, deprecated, message: "Binds set in an `SQLUnsafeRaw` are ignored. Use `SQLBind`instead.") @inlinable public init(_ sql: String, _ binds: [any Encodable & Sendable]) { self.sql = sql diff --git a/Sources/SQLKit/Deprecated/SQLQueryBuilders+Deprecated.swift b/Sources/SQLKit/Deprecated/SQLQueryBuilders+Deprecated.swift index b3ad5e5d..3aef682c 100644 --- a/Sources/SQLKit/Deprecated/SQLQueryBuilders+Deprecated.swift +++ b/Sources/SQLKit/Deprecated/SQLQueryBuilders+Deprecated.swift @@ -31,15 +31,15 @@ extension SQLCreateTriggerBuilder { @inlinable @discardableResult public func condition(_ value: String) -> Self { - self.condition(SQLRaw(value)) + self.condition(SQLUnsafeRaw(value)) } /// Specify a body for the trigger. - @available(*, deprecated, message: "Specifying SQL statements as raw strings is unsafe. Use `SQLQueryString` or `SQLRaw` explicitly.") + @available(*, deprecated, message: "Specifying SQL statements as raw strings is unsafe. Use `SQLQueryString` or `SQLUnsafeRaw` explicitly.") @inlinable @discardableResult public func body(_ statements: [String]) -> Self { - self.body(statements.map { SQLRaw($0) }) + self.body(statements.map { SQLUnsafeRaw($0) }) } } @@ -55,6 +55,6 @@ extension SQLJoinBuilder { @inlinable @discardableResult public func join(_ table: String, method: SQLJoinMethod = .inner, on expression: String) -> Self { - self.join(SQLIdentifier(table), method: method, on: SQLRaw(expression)) + self.join(SQLIdentifier(table), method: method, on: SQLUnsafeRaw(expression)) } } diff --git a/Sources/SQLKit/Docs.docc/SQLKit.md b/Sources/SQLKit/Docs.docc/SQLKit.md index 2503ad55..a7db8fea 100644 --- a/Sources/SQLKit/Docs.docc/SQLKit.md +++ b/Sources/SQLKit/Docs.docc/SQLKit.md @@ -87,7 +87,7 @@ SQLKit does _not_ provide facilities for creating or managing database connectio - ``SQLIdentifier`` - ``SQLList`` - ``SQLLiteral`` -- ``SQLRaw`` +- ``SQLUnsafeRaw`` ### Basic Expressions diff --git a/Sources/SQLKit/Expressions/Basics/SQLQueryString.swift b/Sources/SQLKit/Expressions/Basics/SQLQueryString.swift index a93ad86b..95aa8573 100644 --- a/Sources/SQLKit/Expressions/Basics/SQLQueryString.swift +++ b/Sources/SQLKit/Expressions/Basics/SQLQueryString.swift @@ -167,7 +167,7 @@ extension SQLQueryString { /// Embed an array of `String`s as a list of literal values, placing the `joiner` between each pair of values. /// /// This is equivalent to adding an ``SQLList`` whose subexpressions are all ``SQLLiteral/string(_:)``s and whose - /// separator is the `joiner` wrapped by ``SQLRaw``. + /// separator is the `joiner` wrapped by ``SQLUnsafeRaw``. /// /// Example: /// diff --git a/Sources/SQLKit/Expressions/Clauses/SQLJoinMethod.swift b/Sources/SQLKit/Expressions/Clauses/SQLJoinMethod.swift index 8358a282..0e462e35 100644 --- a/Sources/SQLKit/Expressions/Clauses/SQLJoinMethod.swift +++ b/Sources/SQLKit/Expressions/Clauses/SQLJoinMethod.swift @@ -18,7 +18,7 @@ public enum SQLJoinMethod: SQLExpression { /// An outer join not otherwise specified. /// /// Although this expression does generate `OUTER JOIN` for this case, this is not a valid join in most dialects. - /// It is therefore deprecated and should not be used. Users who need it can use `SQLRaw("OUTER JOIN")` instead. + /// It is therefore deprecated and should not be used. Users who need it can use `SQLUnsafeRaw("OUTER JOIN")` instead. /// /// > Note: Presumably, the original intention of this case was to allow expressing a `FULL JOIN` or /// > `FULL OUTER JOIN`, which is simply a combination of the effects of a left and right join. diff --git a/Sources/SQLKit/Expressions/SQLExpression.swift b/Sources/SQLKit/Expressions/SQLExpression.swift index bf91049f..beb71497 100644 --- a/Sources/SQLKit/Expressions/SQLExpression.swift +++ b/Sources/SQLKit/Expressions/SQLExpression.swift @@ -3,7 +3,7 @@ /// ``SQLExpression``s are not well-enough organized in practice to be considered a proper Abstract Syntax Tree /// representation, but they nonetheless conceptually act as AST nodes. As such, _anything_ which is executed as /// SQL by an ``SQLDatabase`` is represented by a value conforming to ``SQLExpression`` - even if that value is an -/// instance of ``SQLRaw`` containing arbitrary SQL text. +/// instance of ``SQLUnsafeRaw`` containing arbitrary SQL text. /// /// The single requirement of ``SQLExpression`` is the ``SQLExpression/serialize(to:)`` method, which must output /// the appropriate raw text, bindings, and/or subexpressions to the provided ``SQLSerializer`` when invoked. Most diff --git a/Sources/SQLKit/Expressions/SQLStatement.swift b/Sources/SQLKit/Expressions/SQLStatement.swift index 00738878..9961c12d 100644 --- a/Sources/SQLKit/Expressions/SQLStatement.swift +++ b/Sources/SQLKit/Expressions/SQLStatement.swift @@ -18,7 +18,7 @@ extension SQLSerializer { /// public func serialize(to serializer: inout SQLSerializer) { /// switch serializer.dialect.enumSyntax { /// case .inline: - /// SQLRaw("ENUM").serialize(to: &serializer) + /// SQLUnsafeRaw("ENUM").serialize(to: &serializer) /// SQLGroupExpression(self.cases).serialize(to: &serializer) /// default: /// SQLDataType.text.serialize(to: &serializer) @@ -103,9 +103,9 @@ public struct SQLStatement: SQLExpression { // See `SQLExpression.serialize(to:)`. @inlinable public func serialize(to serializer: inout SQLSerializer) { - /// Although `self.parts.interspersed(with: SQLRaw(" ")).forEach { $0.serialize(to: &serializer) }` would be a + /// Although `self.parts.interspersed(with: SQLUnsafeRaw(" ")).forEach { $0.serialize(to: &serializer) }` would be a /// more "elegant" way to write this, it results in the creation of `self.parts.count - 1` identical instances - /// of ``SQLRaw`` and requires the compiler to dynamically dispatch a call to each one's `serialize(to:)` + /// of ``SQLUnsafeRaw`` and requires the compiler to dynamically dispatch a call to each one's `serialize(to:)` /// method. While the total overhead of this behavior is unlikely to be measurable in practice unless the /// statement has a very large number of constitutent parts, saving a couple of extra lines of code with a /// "clever trick" is still not at all worth it - especially since it also requires importing the diff --git a/Sources/SQLKit/Expressions/Syntax/SQLBinaryOperator.swift b/Sources/SQLKit/Expressions/Syntax/SQLBinaryOperator.swift index f8ef65f4..dbad983a 100644 --- a/Sources/SQLKit/Expressions/Syntax/SQLBinaryOperator.swift +++ b/Sources/SQLKit/Expressions/Syntax/SQLBinaryOperator.swift @@ -89,7 +89,7 @@ public enum SQLBinaryOperator: SQLExpression { // See https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html#sqlmode_pipes_as_concat case .concatenate: - serializer.database.logger.debug("|| is not implemented, because it doesn't always work. Use `SQLFunction(\"CONCAT\", args...)` for MySQL or `SQLRaw(\"||\")` for Postgres and SQLite.") + serializer.database.logger.debug("|| is not implemented, because it doesn't always work. Use `SQLFunction(\"CONCAT\", args...)` for MySQL or `SQLUnsafeRaw(\"||\")` for Postgres and SQLite.") } } } diff --git a/Sources/SQLKit/Expressions/Syntax/SQLIdentifier.swift b/Sources/SQLKit/Expressions/Syntax/SQLIdentifier.swift index 978604ac..a26444ae 100644 --- a/Sources/SQLKit/Expressions/Syntax/SQLIdentifier.swift +++ b/Sources/SQLKit/Expressions/Syntax/SQLIdentifier.swift @@ -36,7 +36,7 @@ public struct SQLIdentifier: SQLExpression, ExpressibleByStringLiteral { /// seemed like a good idea for flexibility at the time, but in reality creates additional performance /// bottlenecks and prevents error-proof quoting, short of making ``SQLDialect`` even more confusing (or a /// major version bump). Fortunately, in practice all knwon dialects always return their quoting characters - /// as instances of ``SQLRaw``, so we check for that case and perform the appropriate quoting and/or escaping + /// as instances of ``SQLUnsafeRaw``, so we check for that case and perform the appropriate quoting and/or escaping /// as needed, while falling back to quoting without escaping if the check fails. if let rawQuote = (serializer.dialect.identifierQuote as? SQLUnsafeRaw)?.sql { serializer.write("\(rawQuote)\(self.string.sqlkit_replacing(rawQuote, with: "\(rawQuote)\(rawQuote)"))\(rawQuote)") diff --git a/Sources/SQLKit/Expressions/Syntax/SQLList.swift b/Sources/SQLKit/Expressions/Syntax/SQLList.swift index f03e23c4..5d03c34c 100644 --- a/Sources/SQLKit/Expressions/Syntax/SQLList.swift +++ b/Sources/SQLKit/Expressions/Syntax/SQLList.swift @@ -2,7 +2,7 @@ /// /// When serialized, an empty ``SQLList`` outputs nothing, a single-item ``SQLList`` outputs the serialization of /// that one expression, and all other ``SQLList``s output the entire list of subexpressions joined by an appropriate -/// number of copies of the separator subexpression. The default separator is `SQLRaw(", ")`. +/// number of copies of the separator subexpression. The default separator is `SQLUnsafeRaw(", ")`. /// /// Examples: /// diff --git a/Sources/SQLKit/Expressions/Syntax/SQLUnsafeRaw.swift b/Sources/SQLKit/Expressions/Syntax/SQLUnsafeRaw.swift index 3f72e24b..1a5729df 100644 --- a/Sources/SQLKit/Expressions/Syntax/SQLUnsafeRaw.swift +++ b/Sources/SQLKit/Expressions/Syntax/SQLUnsafeRaw.swift @@ -2,7 +2,7 @@ /// /// Users should almost never need to use ``SQLUnsafeRaw`` directly; there is almost always a better/safer/more specific /// expression available for any given purpose. The most common use for ``SQLUnsafeRaw`` by end users is to represent SQL -/// keywords specific to a dialect, such as `SQLRaw("EXPLAIN VERBOSE")`. +/// keywords specific to a dialect, such as `SQLUnsafeRaw("EXPLAIN VERBOSE")`. /// /// In effect, ``SQLUnsafeRaw`` is nothing but a wrapper which makes `String`s into ``SQLExpression``s, since conforming /// `String` directly to the protocol would cause numerous issues with SQLKit's existing public API (yet another design @@ -20,7 +20,7 @@ public struct SQLUnsafeRaw: SQLExpression { /// The original intention was that bindings set in this property be serialized along with the SQL text, but this /// functionality was never properly implemented and was never used, and is deprecated. Use ``SQLBind`` and/or /// ``SQLQueryString`` to achieve the same effect. - @available(*, deprecated, message: "Binds set in an `SQLRaw` are ignored. Use `SQLBind` instead.") + @available(*, deprecated, message: "Binds set in an `SQLUnsafeRaw` are ignored. Use `SQLBind` instead.") public var binds: [any Encodable & Sendable] = [] /// Create a new raw SQL text expression. diff --git a/Tests/SQLKitTests/AsyncTests.swift b/Tests/SQLKitTests/AsyncTests.swift index e52f92f3..f7e9e457 100644 --- a/Tests/SQLKitTests/AsyncTests.swift +++ b/Tests/SQLKitTests/AsyncTests.swift @@ -9,10 +9,10 @@ final class AsyncSQLKitTests: XCTestCase { } func testSQLDatabaseAsyncAndFutures() async throws { - try await self.db.execute(sql: SQLRaw("TEST"), { _ in XCTFail("Should not receive results") }).get() + try await self.db.execute(sql: SQLUnsafeRaw("TEST"), { _ in XCTFail("Should not receive results") }).get() XCTAssertEqual(self.db.results[0], "TEST") - try await self.db.execute(sql: SQLRaw("TEST"), { _ in XCTFail("Should not receive results") }) + try await self.db.execute(sql: SQLUnsafeRaw("TEST"), { _ in XCTFail("Should not receive results") }) XCTAssertEqual(self.db.results[1], "TEST") } diff --git a/Tests/SQLKitTests/BaseTests.swift b/Tests/SQLKitTests/BaseTests.swift index 8d58d369..0328fed4 100644 --- a/Tests/SQLKitTests/BaseTests.swift +++ b/Tests/SQLKitTests/BaseTests.swift @@ -152,8 +152,8 @@ final class SQLKitTests: XCTestCase { XCTAssertNil(db.version) XCTAssertEqual(db.dialect.name, self.db.dialect.name) XCTAssertEqual(db.queryLogLevel, self.db.queryLogLevel) - await XCTAssertNotNilAsync(try await db.execute(sql: SQLRaw("TEST"), { _ in })) - await XCTAssertNotNilAsync(try await db.execute(sql: SQLRaw("TEST"), { _ in }).get()) + await XCTAssertNotNilAsync(try await db.execute(sql: SQLUnsafeRaw("TEST"), { _ in })) + await XCTAssertNotNilAsync(try await db.execute(sql: SQLUnsafeRaw("TEST"), { _ in }).get()) } func testDatabaseDefaultAsyncImpl() async throws { @@ -163,7 +163,7 @@ final class SQLKitTests: XCTestCase { var eventLoop: any EventLoop { FakeEventLoop() } var dialect: any SQLDialect { GenericDialect() } } - await XCTAssertNotNilAsync(try await TestNoAsyncDatabase().execute(sql: SQLRaw("TEST"), { _ in })) + await XCTAssertNotNilAsync(try await TestNoAsyncDatabase().execute(sql: SQLUnsafeRaw("TEST"), { _ in })) } func testDatabaseVersion() { @@ -194,16 +194,16 @@ final class SQLKitTests: XCTestCase { func testDialectDefaultImpls() { struct TestDialect: SQLDialect { var name: String { "test" } - var identifierQuote: any SQLExpression { SQLRaw("`") } + var identifierQuote: any SQLExpression { SQLUnsafeRaw("`") } var supportsAutoIncrement: Bool { false } - var autoIncrementClause: any SQLExpression { SQLRaw("") } + var autoIncrementClause: any SQLExpression { SQLUnsafeRaw("") } func bindPlaceholder(at position: Int) -> any SQLExpression { SQLLiteral.numeric("\(position)") } - func literalBoolean(_ value: Bool) -> any SQLExpression { SQLRaw("\(value)") } + func literalBoolean(_ value: Bool) -> any SQLExpression { SQLUnsafeRaw("\(value)") } } - XCTAssertEqual((TestDialect().literalStringQuote as? SQLRaw)?.sql, "'") + XCTAssertEqual((TestDialect().literalStringQuote as? SQLUnsafeRaw)?.sql, "'") XCTAssertNil(TestDialect().autoIncrementFunction) - XCTAssertEqual((TestDialect().literalDefault as? SQLRaw)?.sql, "DEFAULT") + XCTAssertEqual((TestDialect().literalDefault as? SQLUnsafeRaw)?.sql, "DEFAULT") XCTAssert(TestDialect().supportsIfExists) XCTAssertEqual(TestDialect().enumSyntax, .unsupported) XCTAssertFalse(TestDialect().supportsDropBehavior) @@ -214,33 +214,33 @@ final class SQLKitTests: XCTestCase { XCTAssertNil(TestDialect().alterTableSyntax.alterColumnDefinitionTypeKeyword) XCTAssert(TestDialect().alterTableSyntax.allowsBatch) XCTAssertNil(TestDialect().customDataType(for: .int)) - XCTAssertEqual((TestDialect().normalizeSQLConstraint(identifier: SQLRaw("")) as? SQLRaw)?.sql, "") + XCTAssertEqual((TestDialect().normalizeSQLConstraint(identifier: SQLUnsafeRaw("")) as? SQLUnsafeRaw)?.sql, "") XCTAssertEqual(TestDialect().upsertSyntax, .unsupported) XCTAssertEqual(TestDialect().unionFeatures, [.union, .unionAll]) XCTAssertNil(TestDialect().sharedSelectLockExpression) XCTAssertNil(TestDialect().exclusiveSelectLockExpression) - XCTAssertNil(TestDialect().nestedSubpathExpression(in: SQLRaw(""), for: [""])) + XCTAssertNil(TestDialect().nestedSubpathExpression(in: SQLUnsafeRaw(""), for: [""])) } func testAdditionalStatementAPI() { var serializer = SQLSerializer(database: self.db) serializer.statement { $0.append("a") - $0.append(SQLRaw("a")) - + $0.append(SQLUnsafeRaw("a")) + $0.append("a", "b") - $0.append(SQLRaw("a"), "b") - $0.append("a", SQLRaw("b")) - $0.append(SQLRaw("a"), SQLRaw("b")) - + $0.append(SQLUnsafeRaw("a"), "b") + $0.append("a", SQLUnsafeRaw("b")) + $0.append(SQLUnsafeRaw("a"), SQLUnsafeRaw("b")) + $0.append("a", "b", "c") - $0.append(SQLRaw("a"), "b", "c") - $0.append("a", SQLRaw("b"), "c") - $0.append("a", "b", SQLRaw("c")) - $0.append(SQLRaw("a"), SQLRaw("b"), "c") - $0.append(SQLRaw("a"), "b", SQLRaw("c")) - $0.append("a", SQLRaw("b"), SQLRaw("c")) - $0.append(SQLRaw("a"), SQLRaw("b"), SQLRaw("c")) + $0.append(SQLUnsafeRaw("a"), "b", "c") + $0.append("a", SQLUnsafeRaw("b"), "c") + $0.append("a", "b", SQLUnsafeRaw("c")) + $0.append(SQLUnsafeRaw("a"), SQLUnsafeRaw("b"), "c") + $0.append(SQLUnsafeRaw("a"), "b", SQLUnsafeRaw("c")) + $0.append("a", SQLUnsafeRaw("b"), SQLUnsafeRaw("c")) + $0.append(SQLUnsafeRaw("a"), SQLUnsafeRaw("b"), SQLUnsafeRaw("c")) } XCTAssertEqual(serializer.sql, "a a a b a b a b a b a b c a b c a b c a b c a b c a b c a b c a b c") } diff --git a/Tests/SQLKitTests/BasicQueryTests.swift b/Tests/SQLKitTests/BasicQueryTests.swift index 9b4d8bfd..c540955d 100644 --- a/Tests/SQLKitTests/BasicQueryTests.swift +++ b/Tests/SQLKitTests/BasicQueryTests.swift @@ -324,7 +324,7 @@ final class BasicQueryTests: XCTestCase { .column("*") .from("planets") .where("name", .equal, "Earth") - .lockingClause(SQLRaw("LOCK IN SHARE MODE")), + .lockingClause(SQLUnsafeRaw("LOCK IN SHARE MODE")), is: "SELECT * FROM ``planets`` WHERE ``name`` = &1 LOCK IN SHARE MODE" ) } @@ -412,7 +412,7 @@ final class BasicQueryTests: XCTestCase { self.db.select().column("name").from("stars").where(SQLColumn("orion"), .equal, SQLIdentifier("please space")).select ), as: SQLIdentifier("star")), method: SQLJoinMethod.inner, - on: SQLColumn(SQLIdentifier("planet_id"), table: SQLIdentifier("moons")), SQLBinaryOperator.isNot, SQLRaw("%%%%%%") + on: SQLColumn(SQLIdentifier("planet_id"), table: SQLIdentifier("moons")), SQLBinaryOperator.isNot, SQLUnsafeRaw("%%%%%%") ) .where(SQLLiteral.null), is: "SELECT * FROM ``planets`` INNER JOIN (SELECT ``name`` FROM ``stars`` WHERE ``orion`` = ``please space``) AS ``star`` ON ``moons``.``planet_id`` IS NOT %%%%%% WHERE NULL" diff --git a/Tests/SQLKitTests/DeprecatedTests.swift b/Tests/SQLKitTests/DeprecatedTests.swift index 83fef9c3..093cd3f9 100644 --- a/Tests/SQLKitTests/DeprecatedTests.swift +++ b/Tests/SQLKitTests/DeprecatedTests.swift @@ -64,7 +64,7 @@ final class SQLDeprecatedTests: XCTestCase { @available(*, deprecated, message: "Contains tests of deprecated functionality") func testRawBinds() { - let raw = SQLRaw("SQL", ["a", "b"]) + let raw = SQLUnsafeRaw("SQL", ["a", "b"]) XCTAssertEqual(raw.sql, "SQL") XCTAssertEqual(raw.binds[0] as? String, "a") XCTAssertEqual(raw.binds[1] as? String, "b") diff --git a/Tests/SQLKitTests/SQLCommonTableExpressionTests.swift b/Tests/SQLKitTests/SQLCommonTableExpressionTests.swift index 24adcd4a..49357898 100644 --- a/Tests/SQLKitTests/SQLCommonTableExpressionTests.swift +++ b/Tests/SQLKitTests/SQLCommonTableExpressionTests.swift @@ -233,9 +233,9 @@ final class SQLCommonTableExpressionTests: XCTestCase { func testCodeCoverage() { var query = self.db.select().column(SQLColumn("b", table: "a")).select query.tableExpressionGroup = .init(tableExpressions: [ - SQLCommonTableExpression(alias: SQLIdentifier("x"), query: SQLRaw("VALUES(``1``)")), - SQLCommonTableExpression(alias: SQLIdentifier("x"), query: SQLGroupExpression(SQLRaw("VALUES(``1``)"))), - SQLGroupExpression(SQLRaw("FOO")) + SQLCommonTableExpression(alias: SQLIdentifier("x"), query: SQLUnsafeRaw("VALUES(``1``)")), + SQLCommonTableExpression(alias: SQLIdentifier("x"), query: SQLGroupExpression(SQLUnsafeRaw("VALUES(``1``)"))), + SQLGroupExpression(SQLUnsafeRaw("FOO")) ]) XCTAssertSerialization(of: self.db.raw("\(query)"), is: "WITH ``x`` AS (VALUES(``1``)), ``x`` AS (VALUES(``1``)), (FOO) SELECT ``a``.``b``") @@ -244,7 +244,7 @@ final class SQLCommonTableExpressionTests: XCTestCase { func testMoreRealisticCTEs() { // Simple sub-SELECT avoidance // Taken from https://www.postgresql.org/docs/16/queries-with.html#QUERIES-WITH-SELECT - self.db._dialect.identifierQuote = SQLRaw("\"") + self.db._dialect.identifierQuote = SQLUnsafeRaw("\"") XCTAssertSerialization( of: self.db.select() .with("regional_sales", as: SQLSubquery.select { $0 @@ -274,7 +274,7 @@ final class SQLCommonTableExpressionTests: XCTestCase { // Fibonacci series generator // Taken from https://dev.mysql.com/doc/refman/8.4/en/with.html#common-table-expressions-recursive-fibonacci-series - self.db._dialect.identifierQuote = SQLRaw("`") + self.db._dialect.identifierQuote = SQLUnsafeRaw("`") self.db._dialect.unionFeatures = [.union, .unionAll] XCTAssertSerialization( of: self.db.select() diff --git a/Tests/SQLKitTests/SQLCreateDropTriggerTests.swift b/Tests/SQLKitTests/SQLCreateDropTriggerTests.swift index c65f58ab..e3eb00a2 100644 --- a/Tests/SQLKitTests/SQLCreateDropTriggerTests.swift +++ b/Tests/SQLKitTests/SQLCreateDropTriggerTests.swift @@ -36,7 +36,7 @@ final class SQLCreateDropTriggerTests: XCTestCase { self.db._dialect.triggerSyntax = .init(create: [.supportsBody, .supportsOrder, .supportsDefiner, .requiresForEachRow]) let builder = self.db.create(trigger: "foo", table: "planet", when: .before, event: .insert) - .body(self.body.map { SQLRaw($0) }) + .body(self.body.map { SQLUnsafeRaw($0) }) .order(precedence: .precedes, otherTriggerName: "other") builder.createTrigger.definer = SQLLiteral.string("foo@bar") @@ -50,7 +50,7 @@ final class SQLCreateDropTriggerTests: XCTestCase { self.db._dialect.triggerSyntax = .init(create: [.supportsBody, .supportsCondition]) XCTAssertSerialization( of: self.db.create(trigger: "foo", table: "planet", when: .before, event: .insert) - .body(self.body.map { SQLRaw($0) }) + .body(self.body.map { SQLUnsafeRaw($0) }) .condition("\(ident: "foo") = \(ident: "bar")" as SQLQueryString), is: "CREATE TRIGGER ``foo`` BEFORE INSERT ON ``planet`` WHEN ``foo`` = ``bar`` BEGIN \(self.body.joined(separator: " ")) END;" ) @@ -104,7 +104,7 @@ final class SQLCreateDropTriggerTests: XCTestCase { func testAdditionalInitializer() { self.db._dialect.triggerSyntax = .init(create: [.supportsBody, .supportsCondition]) var query = SQLCreateTrigger(trigger: "t", table: "tab", when: .after, event: .delete) - query.body = self.body.map { SQLRaw($0) } + query.body = self.body.map { SQLUnsafeRaw($0) } XCTAssertSerialization(of: self.db.raw("\(query)"), is: "CREATE TRIGGER ``t`` AFTER DELETE ON ``tab`` BEGIN IF NEW.amount < 0 THEN SET NEW.amount = 0; END IF; END;") } @@ -125,7 +125,7 @@ final class SQLCreateDropTriggerTests: XCTestCase { ) let builder = self.db.create(trigger: "foo", table: "planet", when: .before, event: .insert) - .body(self.body.map { SQLRaw($0) }) + .body(self.body.map { SQLUnsafeRaw($0) }) .order(precedence: .precedes, otherTriggerName: "other") builder.createTrigger.definer = SQLLiteral.string("foo@bar") diff --git a/Tests/SQLKitTests/SQLCreateTableTests.swift b/Tests/SQLKitTests/SQLCreateTableTests.swift index 272e20d3..5f09c990 100644 --- a/Tests/SQLKitTests/SQLCreateTableTests.swift +++ b/Tests/SQLKitTests/SQLCreateTableTests.swift @@ -16,10 +16,10 @@ final class SQLCreateTableTests: XCTestCase { .column("id", type: .bigint, .primaryKey) .column("name", type: .text, .default("unnamed")) .column("galaxy_id", type: .bigint, .references("galaxies", "id")) - .column("diameter", type: .int, .check(SQLRaw("diameter > 0"))) + .column("diameter", type: .int, .check(SQLUnsafeRaw("diameter > 0"))) .column("important", type: .text, .notNull) .column("special", type: .text, .unique) - .column("automatic", type: .text, .generated(SQLRaw("CONCAT(name, special)"))) + .column("automatic", type: .text, .generated(SQLUnsafeRaw("CONCAT(name, special)"))) .column("collated", type: .text, .collate(name: "default")), is: """ CREATE TABLE ``planets`` (``id`` BIGINT PRIMARY KEY AWWTOEINCREMENT, ``name`` TEXT DEFAULT 'unnamed', ``galaxy_id`` BIGINT REFERENCES ``galaxies`` (``id``), ``diameter`` INTEGER CHECK (diameter > 0), ``important`` TEXT NOT NULL, ``special`` TEXT UNIQUE, ``automatic`` TEXT GENERATED ALWAYS AS (CONCAT(name, special)) STORED, ``collated`` TEXT COLLATE ``default``) @@ -76,7 +76,7 @@ final class SQLCreateTableTests: XCTestCase { is: "CREATE TABLE ``planets4`` (``id`` BIGINT PRIMARY KEY)" ) - self.db._dialect.autoIncrementFunction = SQLRaw("NEXTUNIQUE") + self.db._dialect.autoIncrementFunction = SQLUnsafeRaw("NEXTUNIQUE") XCTAssertSerialization( of: self.db.create(table: "planets5").column("id", type: .bigint, .primaryKey), @@ -102,11 +102,11 @@ final class SQLCreateTableTests: XCTestCase { is: "CREATE TABLE ``planets3`` (``diameter`` REAL DEFAULT 11.5)" ) XCTAssertSerialization( - of: self.db.create(table: "planets4").column("current", type: .custom(SQLRaw("BOOLEAN")), .default(false)), + of: self.db.create(table: "planets4").column("current", type: .custom(SQLUnsafeRaw("BOOLEAN")), .default(false)), is: "CREATE TABLE ``planets4`` (``current`` BOOLEAN DEFAULT FAALS)" ) XCTAssertSerialization( - of: self.db.create(table: "planets5").column("current", type: .custom(SQLRaw("BOOLEAN")), .default(SQLLiteral.boolean(true))), + of: self.db.create(table: "planets5").column("current", type: .custom(SQLUnsafeRaw("BOOLEAN")), .default(SQLLiteral.boolean(true))), is: "CREATE TABLE ``planets5`` (``current`` BOOLEAN DEFAULT TROO)" ) } @@ -132,7 +132,7 @@ final class SQLCreateTableTests: XCTestCase { .column("galaxy_id", type: .bigint) .primaryKey("id") .unique("name") - .check(SQLRaw("diameter > 0"), named: "non-zero-diameter") + .check(SQLUnsafeRaw("diameter > 0"), named: "non-zero-diameter") .foreignKey( ["galaxy_id", "galaxy_name"], references: "galaxies", diff --git a/Tests/SQLKitTests/SQLExpressionTests.swift b/Tests/SQLKitTests/SQLExpressionTests.swift index 6e51740d..081de6ad 100644 --- a/Tests/SQLKitTests/SQLExpressionTests.swift +++ b/Tests/SQLKitTests/SQLExpressionTests.swift @@ -212,8 +212,8 @@ final class SQLExpressionTests: XCTestCase { XCTAssertSerialization(of: self.db.raw("\(query)"), is: "ALTER TABLE ``table`` RENAME TO ``table2`` ADD ``a`` BIGINT , ADD UNIQUE (``d``) , DROP ``c`` , DROP ``e`` , __INVALID__ ``b`` BLOB") self.db._dialect.alterTableSyntax.allowsBatch = true - self.db._dialect.alterTableSyntax.alterColumnDefinitionClause = SQLRaw("MODIFY") XCTAssertSerialization(of: self.db.raw("\(query)"), is: "ALTER TABLE ``table`` RENAME TO ``table2`` ADD ``a`` BIGINT , ADD UNIQUE (``d``) , DROP ``c`` , DROP ``e`` , MODIFY ``b`` BLOB") + self.db._dialect.alterTableSyntax.alterColumnDefinitionClause = SQLUnsafeRaw("MODIFY") } func testCreateIndexQuery() { diff --git a/Tests/SQLKitTests/TestMocks.swift b/Tests/SQLKitTests/TestMocks.swift index ae9405f1..398fcd20 100644 --- a/Tests/SQLKitTests/TestMocks.swift +++ b/Tests/SQLKitTests/TestMocks.swift @@ -110,31 +110,31 @@ struct TestRow: SQLRow { struct GenericDialect: SQLDialect { var name: String { "generic" } - func bindPlaceholder(at position: Int) -> any SQLExpression { SQLRaw("&\(position)") } - func literalBoolean(_ value: Bool) -> any SQLExpression { SQLRaw(value ? "TROO" : "FAALS") } - var literalDefault: any SQLExpression = SQLRaw("DEFALLT") + func bindPlaceholder(at position: Int) -> any SQLExpression { SQLUnsafeRaw("&\(position)") } + func literalBoolean(_ value: Bool) -> any SQLExpression { SQLUnsafeRaw(value ? "TROO" : "FAALS") } + var literalDefault: any SQLExpression = SQLUnsafeRaw("DEFALLT") var supportsAutoIncrement = true var supportsIfExists = true var supportsReturning = true - var identifierQuote: any SQLExpression = SQLRaw("``") - var literalStringQuote: any SQLExpression = SQLRaw("'") + var identifierQuote: any SQLExpression = SQLUnsafeRaw("``") + var literalStringQuote: any SQLExpression = SQLUnsafeRaw("'") var enumSyntax = SQLEnumSyntax.typeName - var autoIncrementClause: any SQLExpression = SQLRaw("AWWTOEINCREMENT") + var autoIncrementClause: any SQLExpression = SQLUnsafeRaw("AWWTOEINCREMENT") var autoIncrementFunction: (any SQLExpression)? = nil var supportsDropBehavior = true var triggerSyntax = SQLTriggerSyntax(create: [], drop: []) - var alterTableSyntax = SQLAlterTableSyntax(alterColumnDefinitionClause: SQLRaw("MOODIFY"), alterColumnDefinitionTypeKeyword: nil) + var alterTableSyntax = SQLAlterTableSyntax(alterColumnDefinitionClause: SQLUnsafeRaw("MOODIFY"), alterColumnDefinitionTypeKeyword: nil) var upsertSyntax = SQLUpsertSyntax.standard var unionFeatures = SQLUnionFeatures() - var sharedSelectLockExpression: (any SQLExpression)? = SQLRaw("FOUR SHAARE") - var exclusiveSelectLockExpression: (any SQLExpression)? = SQLRaw("FOUR UPDATE") + var sharedSelectLockExpression: (any SQLExpression)? = SQLUnsafeRaw("FOUR SHAARE") + var exclusiveSelectLockExpression: (any SQLExpression)? = SQLUnsafeRaw("FOUR UPDATE") func nestedSubpathExpression(in column: any SQLExpression, for path: [String]) -> (any SQLExpression)? { precondition(!path.isEmpty) - let descender = SQLList([column] + path.dropLast().map(SQLLiteral.string(_:)), separator: SQLRaw("-»")) - return SQLGroupExpression(SQLList([descender, SQLLiteral.string(path.last!)], separator: SQLRaw("-»»"))) + let descender = SQLList([column] + path.dropLast().map(SQLLiteral.string(_:)), separator: SQLUnsafeRaw("-»")) + return SQLGroupExpression(SQLList([descender, SQLLiteral.string(path.last!)], separator: SQLUnsafeRaw("-»»"))) } func customDataType(for dataType: SQLDataType) -> (any SQLExpression)? { - dataType == .custom(SQLRaw("STANDARD")) ? SQLRaw("CUSTOM") : nil + dataType == .custom(SQLUnsafeRaw("STANDARD")) ? SQLUnsafeRaw("CUSTOM") : nil } } @@ -144,7 +144,7 @@ extension SQLKit.SQLDataType: Swift.Equatable { case (.bigint, .bigint), (.blob, .blob), (.int, .int), (.real, .real), (.smallint, .smallint), (.text, .text): return true - case (.custom(let lhs as SQLRaw), .custom(let rhs as SQLRaw)) where lhs.sql == rhs.sql: + case (.custom(let lhs as SQLUnsafeRaw), .custom(let rhs as SQLUnsafeRaw)) where lhs.sql == rhs.sql: return true default: return false From e4106836b6f0f22c776fb1e423204a0f3b2f5445 Mon Sep 17 00:00:00 2001 From: Gwynne Raskind Date: Wed, 16 Apr 2025 17:57:00 -0500 Subject: [PATCH 4/5] Rename SQLRawBuilder to SQLUnsafeRaw and SQLDatabase.raw(_:) to SQLDatabase.unsafeRaw(_:) --- README.md | 4 +- .../Implementations/SQLRawBuilder.swift | 8 +- .../Deprecated/SQLDatabase+Deprecated.swift | 8 + .../SQLQueryBuilders+Deprecated.swift | 3 + Sources/SQLKit/Docs.docc/BasicUsage.md | 4 +- Sources/SQLKit/Docs.docc/SQLKit.md | 2 +- .../Expressions/Basics/SQLQueryString.swift | 6 +- Tests/SQLKitTests/BaseTests.swift | 2 +- Tests/SQLKitTests/DeprecatedTests.swift | 11 +- .../SQLCommonTableExpressionTests.swift | 2 +- .../SQLCreateDropTriggerTests.swift | 2 +- Tests/SQLKitTests/SQLExpressionTests.swift | 272 +++++++++--------- Tests/SQLKitTests/SQLQueryStringTests.swift | 22 +- Tests/SQLKitTests/SQLUnionTests.swift | 4 +- 14 files changed, 183 insertions(+), 167 deletions(-) diff --git a/README.md b/README.md index 76c8187e..15c44a61 100644 --- a/README.md +++ b/README.md @@ -258,10 +258,10 @@ The delete builder is also an `SQLPredicateBuilder`. ## Raw -The `raw(_:)` method allows passing custom SQL query strings, with support for parameterized bindings and correctly-quoted identifiers: +The `unsafeRaw(_:)` method allows passing custom SQL query strings, with support for parameterized bindings and correctly-quoted identifiers: ```swift -let planets = try await db.raw("SELECT \(SQLLiteral.all) FROM \(ident: table) WHERE \(ident: name) = \(bind: "planet")") +let planets = try await db.unsafeRaw("SELECT \(SQLLiteral.all) FROM \(ident: table) WHERE \(ident: name) = \(bind: "planet")") .all() ``` diff --git a/Sources/SQLKit/Builders/Implementations/SQLRawBuilder.swift b/Sources/SQLKit/Builders/Implementations/SQLRawBuilder.swift index d57254d8..31d5c4df 100644 --- a/Sources/SQLKit/Builders/Implementations/SQLRawBuilder.swift +++ b/Sources/SQLKit/Builders/Implementations/SQLRawBuilder.swift @@ -1,5 +1,5 @@ /// Builds raw SQL queries. -public final class SQLRawBuilder: SQLQueryBuilder, SQLQueryFetcher { +public final class SQLUnsafeRawBuilder: SQLQueryBuilder, SQLQueryFetcher { /// Raw query being built. @usableFromInline var sql: SQLQueryString @@ -13,7 +13,7 @@ public final class SQLRawBuilder: SQLQueryBuilder, SQLQueryFetcher { self.sql } - /// Create a new ``SQLRawBuilder``. + /// Create a new ``SQLUnsafeRawBuilder``. @inlinable public init(_ sql: SQLQueryString, on database: any SQLDatabase) { self.database = database @@ -22,9 +22,9 @@ public final class SQLRawBuilder: SQLQueryBuilder, SQLQueryFetcher { } extension SQLDatabase { - /// Create a new ``SQLRawBuilder``. + /// Create a new ``SQLUnsafeRawBuilder``. @inlinable - public func raw(_ sql: SQLQueryString) -> SQLRawBuilder { + public func unsafeRaw(_ sql: SQLQueryString) -> SQLUnsafeRawBuilder { .init(sql, on: self) } } diff --git a/Sources/SQLKit/Deprecated/SQLDatabase+Deprecated.swift b/Sources/SQLKit/Deprecated/SQLDatabase+Deprecated.swift index fb0edd41..77171bad 100644 --- a/Sources/SQLKit/Deprecated/SQLDatabase+Deprecated.swift +++ b/Sources/SQLKit/Deprecated/SQLDatabase+Deprecated.swift @@ -38,3 +38,11 @@ extension SQLDatabaseReportedVersion { (otherVersion as? Self).map { !self.isOlder(than: $0) } ?? false } } + +extension SQLDatabase { + @available(*, deprecated, renamed: "unsafeRaw(_:)", message: "SQLDatabase.unsafeRaw(_:) has been renamed to SQLDatabase.unsafeRaw(_:).") + @inlinable + public func raw(_ sql: SQLQueryString) -> SQLUnsafeRawBuilder { + self.unsafeRaw(sql) + } +} diff --git a/Sources/SQLKit/Deprecated/SQLQueryBuilders+Deprecated.swift b/Sources/SQLKit/Deprecated/SQLQueryBuilders+Deprecated.swift index 3aef682c..15fec221 100644 --- a/Sources/SQLKit/Deprecated/SQLQueryBuilders+Deprecated.swift +++ b/Sources/SQLKit/Deprecated/SQLQueryBuilders+Deprecated.swift @@ -58,3 +58,6 @@ extension SQLJoinBuilder { self.join(SQLIdentifier(table), method: method, on: SQLUnsafeRaw(expression)) } } + +@available(*, deprecated, renamed: "SQLUnsafeRawBuilder", message: "SQLRawBuilder has been renamed to SQLUnsafeRawBuilder.") +public typealias SQLRawBuilder = SQLUnsafeRawBuilder diff --git a/Sources/SQLKit/Docs.docc/BasicUsage.md b/Sources/SQLKit/Docs.docc/BasicUsage.md index e7ccf19b..7a6f7cd2 100644 --- a/Sources/SQLKit/Docs.docc/BasicUsage.md +++ b/Sources/SQLKit/Docs.docc/BasicUsage.md @@ -273,10 +273,10 @@ The delete builder also conforms to ``SQLPredicateBuilder``. ### Raw -The ``SQLDatabase/raw(_:)`` method allows passing custom SQL query strings, with support for parameterized bindings and correctly-quoted identifiers: +The ``SQLDatabase/unsafeRaw(_:)`` method allows passing custom SQL query strings, with support for parameterized bindings and correctly-quoted identifiers: ```swift -let planets = try await db.raw("SELECT \(SQLLiteral.all) FROM \(ident: table) WHERE \(ident: name) = \(bind: "planet")") +let planets = try await db.unsafeRaw("SELECT \(SQLLiteral.all) FROM \(ident: table) WHERE \(ident: name) = \(bind: "planet")") .all() ``` diff --git a/Sources/SQLKit/Docs.docc/SQLKit.md b/Sources/SQLKit/Docs.docc/SQLKit.md index a7db8fea..a15833e5 100644 --- a/Sources/SQLKit/Docs.docc/SQLKit.md +++ b/Sources/SQLKit/Docs.docc/SQLKit.md @@ -69,12 +69,12 @@ SQLKit does _not_ provide facilities for creating or managing database connectio - ``SQLDropTriggerBuilder`` - ``SQLInsertBuilder`` - ``SQLPredicateGroupBuilder`` -- ``SQLRawBuilder`` - ``SQLReturningResultBuilder`` - ``SQLSecondaryPredicateGroupBuilder`` - ``SQLSelectBuilder`` - ``SQLSubqueryBuilder`` - ``SQLUnionBuilder`` +- ``SQLUnsafeRawBuilder`` - ``SQLUpdateBuilder`` ### Syntactic Expressions diff --git a/Sources/SQLKit/Expressions/Basics/SQLQueryString.swift b/Sources/SQLKit/Expressions/Basics/SQLQueryString.swift index 95aa8573..d47b0d83 100644 --- a/Sources/SQLKit/Expressions/Basics/SQLQueryString.swift +++ b/Sources/SQLKit/Expressions/Basics/SQLQueryString.swift @@ -1,6 +1,6 @@ /// An expression consisting of an array of constituent subexpressions generated by custom string interpolations. /// -/// Query strings are primarily intended for use with ``SQLRawBuilder``, providing for the inclusion of bound +/// Query strings are primarily intended for use with ``SQLUnsafeRawBuilder``, 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 ``SQLExpression``s, allowing them to be used almost anywhere in SQLKit. /// @@ -12,7 +12,7 @@ /// /// ```swift /// // As an entire query: -/// try await database.raw(""" +/// try await database.unsafeRaw(""" /// UPDATE \(ident: "foo") /// SET \(ident: "bar")=\(bind: value) /// WHERE \(ident: "baz")=\(literal: "bop") @@ -31,7 +31,7 @@ /// /// ```swift /// let messyIdentifer = someCondition ? "abcd{}efgh" : "marmalade!!" // invalid identifiers if not escaped -/// try await database.raw(""" +/// try await database.unsafeRaw(""" /// SELECT \(ident: messyIdentifier) FROM \(ident: "whatever") WHERE \(ident: "x")=\(bind: "foo") /// """).all() /// // This query renders differently in various dialect: diff --git a/Tests/SQLKitTests/BaseTests.swift b/Tests/SQLKitTests/BaseTests.swift index 0328fed4..a2ebbb37 100644 --- a/Tests/SQLKitTests/BaseTests.swift +++ b/Tests/SQLKitTests/BaseTests.swift @@ -66,7 +66,7 @@ final class SQLKitTests: XCTestCase { // MARK: Misc func testQuoting() { - XCTAssertSerialization(of: SQLRawBuilder("\(ident: "foo``bar``") \(literal: "foo'bar'")", on: self.db), is: "``foo````bar`````` 'foo''bar'''") + XCTAssertSerialization(of: SQLUnsafeRawBuilder("\(ident: "foo``bar``") \(literal: "foo'bar'")", on: self.db), is: "``foo````bar`````` 'foo''bar'''") } func testStringHandlingUtilities() { diff --git a/Tests/SQLKitTests/DeprecatedTests.swift b/Tests/SQLKitTests/DeprecatedTests.swift index 093cd3f9..558e4ed7 100644 --- a/Tests/SQLKitTests/DeprecatedTests.swift +++ b/Tests/SQLKitTests/DeprecatedTests.swift @@ -10,7 +10,7 @@ final class SQLDeprecatedTests: XCTestCase { @available(*, deprecated, message: "Contains tests of deprecated functionality") func testConcatOperator() { - XCTAssertSerialization(of: self.db.raw("\(SQLBinaryOperator.concatenate)"), is: "") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLBinaryOperator.concatenate)"), is: "") } @available(*, deprecated, message: "Contains tests of deprecated functionality") @@ -33,7 +33,7 @@ final class SQLDeprecatedTests: XCTestCase { @available(*, deprecated, message: "Contains tests of deprecated functionality") func testDataTypeType() { - XCTAssertSerialization(of: self.db.raw("\(SQLDataType.type("FOO"))"), is: "``FOO``") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLDataType.type("FOO"))"), is: "``FOO``") } @available(*, deprecated, message: "Contains tests of deprecated functionality") @@ -59,7 +59,7 @@ final class SQLDeprecatedTests: XCTestCase { @available(*, deprecated, message: "Contains tests of deprecated functionality") func testOldQueryStringInterpolations() { - XCTAssertSerialization(of: self.db.raw("\(raw: "X") \("x")"), is: "X x") + XCTAssertSerialization(of: self.db.unsafeRaw("\(raw: "X") \("x")"), is: "X x") } @available(*, deprecated, message: "Contains tests of deprecated functionality") @@ -142,4 +142,9 @@ final class SQLDeprecatedTests: XCTestCase { XCTAssert(TestVersion(stringValue: "a").isNotOlder(than: TestVersion(stringValue: "a"))) XCTAssertFalse(TestVersion(stringValue: "b").isNotOlder(than: AnotherTestVersion(stringValue: "a"))) } + + @available(*, deprecated, message: "Contains tests of deprecated functionality") + func testOldRawMethod() { + XCTAssertNotNil(self.db.raw("foo")) + } } diff --git a/Tests/SQLKitTests/SQLCommonTableExpressionTests.swift b/Tests/SQLKitTests/SQLCommonTableExpressionTests.swift index 49357898..aec90cf3 100644 --- a/Tests/SQLKitTests/SQLCommonTableExpressionTests.swift +++ b/Tests/SQLKitTests/SQLCommonTableExpressionTests.swift @@ -238,7 +238,7 @@ final class SQLCommonTableExpressionTests: XCTestCase { SQLGroupExpression(SQLUnsafeRaw("FOO")) ]) - XCTAssertSerialization(of: self.db.raw("\(query)"), is: "WITH ``x`` AS (VALUES(``1``)), ``x`` AS (VALUES(``1``)), (FOO) SELECT ``a``.``b``") + XCTAssertSerialization(of: self.db.unsafeRaw("\(query)"), is: "WITH ``x`` AS (VALUES(``1``)), ``x`` AS (VALUES(``1``)), (FOO) SELECT ``a``.``b``") } func testMoreRealisticCTEs() { diff --git a/Tests/SQLKitTests/SQLCreateDropTriggerTests.swift b/Tests/SQLKitTests/SQLCreateDropTriggerTests.swift index e3eb00a2..e8935898 100644 --- a/Tests/SQLKitTests/SQLCreateDropTriggerTests.swift +++ b/Tests/SQLKitTests/SQLCreateDropTriggerTests.swift @@ -106,7 +106,7 @@ final class SQLCreateDropTriggerTests: XCTestCase { var query = SQLCreateTrigger(trigger: "t", table: "tab", when: .after, event: .delete) query.body = self.body.map { SQLUnsafeRaw($0) } - XCTAssertSerialization(of: self.db.raw("\(query)"), is: "CREATE TRIGGER ``t`` AFTER DELETE ON ``tab`` BEGIN IF NEW.amount < 0 THEN SET NEW.amount = 0; END IF; END;") + XCTAssertSerialization(of: self.db.unsafeRaw("\(query)"), is: "CREATE TRIGGER ``t`` AFTER DELETE ON ``tab`` BEGIN IF NEW.amount < 0 THEN SET NEW.amount = 0; END IF; END;") } func testInvalidTriggerCreates() { diff --git a/Tests/SQLKitTests/SQLExpressionTests.swift b/Tests/SQLKitTests/SQLExpressionTests.swift index 081de6ad..58cd4755 100644 --- a/Tests/SQLKitTests/SQLExpressionTests.swift +++ b/Tests/SQLKitTests/SQLExpressionTests.swift @@ -9,192 +9,192 @@ final class SQLExpressionTests: XCTestCase { } func testDataTypes() { - XCTAssertSerialization(of: self.db.raw("\(SQLDataType.smallint)"), is: "SMALLINT") - XCTAssertSerialization(of: self.db.raw("\(SQLDataType.int)"), is: "INTEGER") - XCTAssertSerialization(of: self.db.raw("\(SQLDataType.bigint)"), is: "BIGINT") - XCTAssertSerialization(of: self.db.raw("\(SQLDataType.real)"), is: "REAL") - XCTAssertSerialization(of: self.db.raw("\(SQLDataType.text)"), is: "TEXT") - XCTAssertSerialization(of: self.db.raw("\(SQLDataType.blob)"), is: "BLOB") - XCTAssertSerialization(of: self.db.raw("\(SQLDataType.timestamp)"), is: "TIMESTAMP") - XCTAssertSerialization(of: self.db.raw("\(SQLDataType.custom(SQLRaw("STANDARD")))"), is: "CUSTOM") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLDataType.smallint)"), is: "SMALLINT") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLDataType.int)"), is: "INTEGER") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLDataType.bigint)"), is: "BIGINT") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLDataType.real)"), is: "REAL") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLDataType.text)"), is: "TEXT") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLDataType.blob)"), is: "BLOB") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLDataType.timestamp)"), is: "TIMESTAMP") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLDataType.custom(SQLUnsafeRaw("STANDARD")))"), is: "CUSTOM") } func testDirectionalities() { - XCTAssertSerialization(of: self.db.raw("\(SQLDirection.ascending)"), is: "ASC") - XCTAssertSerialization(of: self.db.raw("\(SQLDirection.descending)"), is: "DESC") - XCTAssertSerialization(of: self.db.raw("\(SQLDirection.null)"), is: "NULL") - XCTAssertSerialization(of: self.db.raw("\(SQLDirection.notNull)"), is: "NOT NULL") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLDirection.ascending)"), is: "ASC") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLDirection.descending)"), is: "DESC") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLDirection.null)"), is: "NULL") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLDirection.notNull)"), is: "NOT NULL") } func testDistinctExpr() { - XCTAssertSerialization(of: self.db.raw("\(SQLDistinct(Array()))"), is: "") - XCTAssertSerialization(of: self.db.raw("\(SQLDistinct.all)"), is: "DISTINCT *") - XCTAssertSerialization(of: self.db.raw("\(SQLDistinct("a", "b"))"), is: "DISTINCT ``a``, ``b``") - XCTAssertSerialization(of: self.db.raw("\(SQLDistinct(["a", "b"]))"), is: "DISTINCT ``a``, ``b``") - XCTAssertSerialization(of: self.db.raw("\(SQLDistinct(SQLIdentifier("a"), SQLIdentifier("b")))"), is: "DISTINCT ``a``, ``b``") - XCTAssertSerialization(of: self.db.raw("\(SQLDistinct([SQLIdentifier("a"), SQLIdentifier("b")]))"), is: "DISTINCT ``a``, ``b``") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLDistinct(Array()))"), is: "") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLDistinct.all)"), is: "DISTINCT *") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLDistinct("a", "b"))"), is: "DISTINCT ``a``, ``b``") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLDistinct(["a", "b"]))"), is: "DISTINCT ``a``, ``b``") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLDistinct(SQLIdentifier("a"), SQLIdentifier("b")))"), is: "DISTINCT ``a``, ``b``") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLDistinct([SQLIdentifier("a"), SQLIdentifier("b")]))"), is: "DISTINCT ``a``, ``b``") } func testForeignKeyActions() { - XCTAssertSerialization(of: self.db.raw("\(SQLForeignKeyAction.noAction)"), is: "NO ACTION") - XCTAssertSerialization(of: self.db.raw("\(SQLForeignKeyAction.restrict)"), is: "RESTRICT") - XCTAssertSerialization(of: self.db.raw("\(SQLForeignKeyAction.cascade)"), is: "CASCADE") - XCTAssertSerialization(of: self.db.raw("\(SQLForeignKeyAction.setNull)"), is: "SET NULL") - XCTAssertSerialization(of: self.db.raw("\(SQLForeignKeyAction.setDefault)"), is: "SET DEFAULT") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLForeignKeyAction.noAction)"), is: "NO ACTION") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLForeignKeyAction.restrict)"), is: "RESTRICT") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLForeignKeyAction.cascade)"), is: "CASCADE") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLForeignKeyAction.setNull)"), is: "SET NULL") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLForeignKeyAction.setDefault)"), is: "SET DEFAULT") } func testQualifiedTable() { - XCTAssertSerialization(of: self.db.raw("\(SQLQualifiedTable("a", space: "b"))"), is: "``b``.``a``") - XCTAssertSerialization(of: self.db.raw("\(SQLQualifiedTable(SQLIdentifier("a"), space: SQLIdentifier("b")))"), is: "``b``.``a``") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLQualifiedTable("a", space: "b"))"), is: "``b``.``a``") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLQualifiedTable(SQLIdentifier("a"), space: SQLIdentifier("b")))"), is: "``b``.``a``") } func testAlterColumnDefinitionType() { self.db._dialect.alterTableSyntax.alterColumnDefinitionTypeKeyword = nil - XCTAssertSerialization(of: self.db.raw("\(SQLAlterColumnDefinitionType(column: .init("a"), dataType: .int))"), is: "``a`` INTEGER") - XCTAssertSerialization(of: self.db.raw("\(SQLAlterColumnDefinitionType(column: SQLRaw("a"), dataType: SQLDataType.int))"), is: "a INTEGER") - - self.db._dialect.alterTableSyntax.alterColumnDefinitionTypeKeyword = SQLRaw("SET TYPE") - XCTAssertSerialization(of: self.db.raw("\(SQLAlterColumnDefinitionType(column: .init("a"), dataType: .int))"), is: "``a`` SET TYPE INTEGER") - XCTAssertSerialization(of: self.db.raw("\(SQLAlterColumnDefinitionType(column: SQLRaw("a"), dataType: SQLDataType.int))"), is: "a SET TYPE INTEGER") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLAlterColumnDefinitionType(column: .init("a"), dataType: .int))"), is: "``a`` INTEGER") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLAlterColumnDefinitionType(column: SQLUnsafeRaw("a"), dataType: SQLDataType.int))"), is: "a INTEGER") + + self.db._dialect.alterTableSyntax.alterColumnDefinitionTypeKeyword = SQLUnsafeRaw("SET TYPE") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLAlterColumnDefinitionType(column: .init("a"), dataType: .int))"), is: "``a`` SET TYPE INTEGER") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLAlterColumnDefinitionType(column: SQLUnsafeRaw("a"), dataType: SQLDataType.int))"), is: "a SET TYPE INTEGER") } func testColumnAssignment() { - XCTAssertSerialization(of: self.db.raw("\(SQLColumnAssignment(setting: "a", to: "b"))"), is: "``a`` = &1") - XCTAssertSerialization(of: self.db.raw("\(SQLColumnAssignment(setting: "a", to: SQLIdentifier("b")))"), is: "``a`` = ``b``") - XCTAssertSerialization(of: self.db.raw("\(SQLColumnAssignment(setting: SQLIdentifier("a"), to: "b"))"), is: "``a`` = &1") - XCTAssertSerialization(of: self.db.raw("\(SQLColumnAssignment(setting: SQLIdentifier("a"), to: SQLIdentifier("b")))"), is: "``a`` = ``b``") - XCTAssertSerialization(of: self.db.raw("\(SQLColumnAssignment(settingExcludedValueFor: "a"))"), is: "``a`` = EXCLUDED.``a``") - XCTAssertSerialization(of: self.db.raw("\(SQLColumnAssignment(settingExcludedValueFor: SQLIdentifier("a")))"), is: "``a`` = EXCLUDED.``a``") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnAssignment(setting: "a", to: "b"))"), is: "``a`` = &1") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnAssignment(setting: "a", to: SQLIdentifier("b")))"), is: "``a`` = ``b``") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnAssignment(setting: SQLIdentifier("a"), to: "b"))"), is: "``a`` = &1") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnAssignment(setting: SQLIdentifier("a"), to: SQLIdentifier("b")))"), is: "``a`` = ``b``") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnAssignment(settingExcludedValueFor: "a"))"), is: "``a`` = EXCLUDED.``a``") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnAssignment(settingExcludedValueFor: SQLIdentifier("a")))"), is: "``a`` = EXCLUDED.``a``") } func testColumnConstraintAlgorithm() { - XCTAssertSerialization(of: self.db.raw("\(SQLColumnConstraintAlgorithm.primaryKey(autoIncrement: false))"), is: "PRIMARY KEY") - XCTAssertSerialization(of: self.db.raw("\(SQLColumnConstraintAlgorithm.primaryKey(autoIncrement: true))"), is: "PRIMARY KEY AWWTOEINCREMENT") - XCTAssertSerialization(of: self.db.raw("\(SQLColumnConstraintAlgorithm.primaryKey)"), is: "PRIMARY KEY AWWTOEINCREMENT") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnConstraintAlgorithm.primaryKey(autoIncrement: false))"), is: "PRIMARY KEY") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnConstraintAlgorithm.primaryKey(autoIncrement: true))"), is: "PRIMARY KEY AWWTOEINCREMENT") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnConstraintAlgorithm.primaryKey)"), is: "PRIMARY KEY AWWTOEINCREMENT") - XCTAssertSerialization(of: self.db.raw("\(SQLColumnConstraintAlgorithm.notNull)"), is: "NOT NULL") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnConstraintAlgorithm.notNull)"), is: "NOT NULL") - XCTAssertSerialization(of: self.db.raw("\(SQLColumnConstraintAlgorithm.unique)"), is: "UNIQUE") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnConstraintAlgorithm.unique)"), is: "UNIQUE") - XCTAssertSerialization(of: self.db.raw("\(SQLColumnConstraintAlgorithm.check(SQLRaw("CHECK")))"), is: "CHECK (CHECK)") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnConstraintAlgorithm.check(SQLUnsafeRaw("CHECK")))"), is: "CHECK (CHECK)") - XCTAssertSerialization(of: self.db.raw("\(SQLColumnConstraintAlgorithm.collate(name: "ascii"))"), is: "COLLATE ``ascii``") - XCTAssertSerialization(of: self.db.raw("\(SQLColumnConstraintAlgorithm.collate(name: SQLIdentifier("ascii")))"), is: "COLLATE ``ascii``") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnConstraintAlgorithm.collate(name: "ascii"))"), is: "COLLATE ``ascii``") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnConstraintAlgorithm.collate(name: SQLIdentifier("ascii")))"), is: "COLLATE ``ascii``") - XCTAssertSerialization(of: self.db.raw("\(SQLColumnConstraintAlgorithm.default("a"))"), is: "DEFAULT 'a'") - XCTAssertSerialization(of: self.db.raw("\(SQLColumnConstraintAlgorithm.default(1))"), is: "DEFAULT 1") - XCTAssertSerialization(of: self.db.raw("\(SQLColumnConstraintAlgorithm.default(1.0))"), is: "DEFAULT 1.0") - XCTAssertSerialization(of: self.db.raw("\(SQLColumnConstraintAlgorithm.default(true))"), is: "DEFAULT TROO") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnConstraintAlgorithm.default("a"))"), is: "DEFAULT 'a'") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnConstraintAlgorithm.default(1))"), is: "DEFAULT 1") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnConstraintAlgorithm.default(1.0))"), is: "DEFAULT 1.0") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnConstraintAlgorithm.default(true))"), is: "DEFAULT TROO") - XCTAssertSerialization(of: self.db.raw("\(SQLColumnConstraintAlgorithm.references("a", "b", onDelete: .cascade, onUpdate: .cascade))"), is: "REFERENCES ``a`` (``b``) ON DELETE CASCADE ON UPDATE CASCADE") - XCTAssertSerialization(of: self.db.raw("\(SQLColumnConstraintAlgorithm.references(SQLIdentifier("a"), SQLIdentifier("b"), onDelete: SQLForeignKeyAction.cascade, onUpdate: SQLForeignKeyAction.cascade))"), is: "REFERENCES ``a`` (``b``) ON DELETE CASCADE ON UPDATE CASCADE") - XCTAssertSerialization(of: self.db.raw("\(SQLColumnConstraintAlgorithm.foreignKey(references: SQLForeignKey(table: SQLIdentifier("a"), columns: [SQLIdentifier("b")], onDelete: SQLForeignKeyAction.cascade, onUpdate: SQLForeignKeyAction.cascade)))"), is: "REFERENCES ``a`` (``b``) ON DELETE CASCADE ON UPDATE CASCADE") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnConstraintAlgorithm.references("a", "b", onDelete: .cascade, onUpdate: .cascade))"), is: "REFERENCES ``a`` (``b``) ON DELETE CASCADE ON UPDATE CASCADE") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnConstraintAlgorithm.references(SQLIdentifier("a"), SQLIdentifier("b"), onDelete: SQLForeignKeyAction.cascade, onUpdate: SQLForeignKeyAction.cascade))"), is: "REFERENCES ``a`` (``b``) ON DELETE CASCADE ON UPDATE CASCADE") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnConstraintAlgorithm.foreignKey(references: SQLForeignKey(table: SQLIdentifier("a"), columns: [SQLIdentifier("b")], onDelete: SQLForeignKeyAction.cascade, onUpdate: SQLForeignKeyAction.cascade)))"), is: "REFERENCES ``a`` (``b``) ON DELETE CASCADE ON UPDATE CASCADE") - XCTAssertSerialization(of: self.db.raw("\(SQLColumnConstraintAlgorithm.generated(SQLRaw("value")))"), is: "GENERATED ALWAYS AS (value) STORED") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnConstraintAlgorithm.generated(SQLUnsafeRaw("value")))"), is: "GENERATED ALWAYS AS (value) STORED") - XCTAssertSerialization(of: self.db.raw("\(SQLColumnConstraintAlgorithm.custom(SQLRaw("whatever")))"), is: "whatever") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumnConstraintAlgorithm.custom(SQLUnsafeRaw("whatever")))"), is: "whatever") } func testConflictResolutionStrategy() { self.db._dialect.upsertSyntax = .standard - XCTAssertSerialization(of: self.db.raw("\(SQLConflictResolutionStrategy(target: "a", action: .noAction))"), is: "ON CONFLICT (``a``) DO NOTHING") - XCTAssertSerialization(of: self.db.raw("\(SQLConflictResolutionStrategy(targets: ["a"], action: .noAction))"), is: "ON CONFLICT (``a``) DO NOTHING") - XCTAssertSerialization(of: self.db.raw("\(SQLConflictResolutionStrategy(target: SQLIdentifier("a"), action: .noAction))"), is: "ON CONFLICT (``a``) DO NOTHING") - XCTAssertSerialization(of: self.db.raw("\(SQLConflictResolutionStrategy(targets: [SQLIdentifier("a")], action: .noAction))"), is: "ON CONFLICT (``a``) DO NOTHING") - XCTAssertSerialization(of: self.db.raw("\(SQLConflictResolutionStrategy(target: "a", action: .noAction).queryModifier(for: self.db) ?? SQLRaw(""))"), is: "") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(target: "a", action: .noAction))"), is: "ON CONFLICT (``a``) DO NOTHING") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(targets: ["a"], action: .noAction))"), is: "ON CONFLICT (``a``) DO NOTHING") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(target: SQLIdentifier("a"), action: .noAction))"), is: "ON CONFLICT (``a``) DO NOTHING") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(targets: [SQLIdentifier("a")], action: .noAction))"), is: "ON CONFLICT (``a``) DO NOTHING") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(target: "a", action: .noAction).queryModifier(for: self.db) ?? SQLUnsafeRaw(""))"), is: "") XCTAssertSerialization( - of: self.db.raw("\(SQLConflictResolutionStrategy(target: "a", action: .update(assignments: [SQLColumnAssignment(setting: "a", to: "b")], predicate: SQLBinaryExpression(SQLIdentifier("a"), .equal, SQLIdentifier("b")))))"), + of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(target: "a", action: .update(assignments: [SQLColumnAssignment(setting: "a", to: "b")], predicate: SQLBinaryExpression(SQLIdentifier("a"), .equal, SQLIdentifier("b")))))"), is: "ON CONFLICT (``a``) DO UPDATE SET ``a`` = &1 WHERE ``a`` = ``b``" ) XCTAssertSerialization( - of: self.db.raw("\(SQLConflictResolutionStrategy(target: "a", action: .update(assignments: [SQLColumnAssignment(setting: "a", to: "b")], predicate: SQLBinaryExpression(SQLIdentifier("a"), .equal, SQLIdentifier("b")))).queryModifier(for: self.db) ?? SQLRaw(""))"), + of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(target: "a", action: .update(assignments: [SQLColumnAssignment(setting: "a", to: "b")], predicate: SQLBinaryExpression(SQLIdentifier("a"), .equal, SQLIdentifier("b")))).queryModifier(for: self.db) ?? SQLUnsafeRaw(""))"), is: "" ) self.db._dialect.upsertSyntax = .mysqlLike - XCTAssertSerialization(of: self.db.raw("\(SQLConflictResolutionStrategy(target: "a", action: .noAction))"), is: "") - XCTAssertSerialization(of: self.db.raw("\(SQLConflictResolutionStrategy(targets: ["a"], action: .noAction))"), is: "") - XCTAssertSerialization(of: self.db.raw("\(SQLConflictResolutionStrategy(target: SQLIdentifier("a"), action: .noAction))"), is: "") - XCTAssertSerialization(of: self.db.raw("\(SQLConflictResolutionStrategy(targets: [SQLIdentifier("a")], action: .noAction))"), is: "") - XCTAssertSerialization(of: self.db.raw("\(SQLConflictResolutionStrategy(target: "a", action: .noAction).queryModifier(for: self.db) ?? SQLRaw(""))"), is: "IGNORE") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(target: "a", action: .noAction))"), is: "") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(targets: ["a"], action: .noAction))"), is: "") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(target: SQLIdentifier("a"), action: .noAction))"), is: "") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(targets: [SQLIdentifier("a")], action: .noAction))"), is: "") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(target: "a", action: .noAction).queryModifier(for: self.db) ?? SQLUnsafeRaw(""))"), is: "IGNORE") XCTAssertSerialization( - of: self.db.raw("\(SQLConflictResolutionStrategy(target: "a", action: .update(assignments: [SQLColumnAssignment(setting: "a", to: "b")], predicate: SQLBinaryExpression(SQLIdentifier("a"), .equal, SQLIdentifier("b")))))"), + of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(target: "a", action: .update(assignments: [SQLColumnAssignment(setting: "a", to: "b")], predicate: SQLBinaryExpression(SQLIdentifier("a"), .equal, SQLIdentifier("b")))))"), is: "ON DUPLICATE KEY UPDATE ``a`` = &1" ) XCTAssertSerialization( - of: self.db.raw("\(SQLConflictResolutionStrategy(target: "a", action: .update(assignments: [SQLColumnAssignment(setting: "a", to: "b")], predicate: SQLBinaryExpression(SQLIdentifier("a"), .equal, SQLIdentifier("b")))).queryModifier(for: self.db) ?? SQLRaw(""))"), + of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(target: "a", action: .update(assignments: [SQLColumnAssignment(setting: "a", to: "b")], predicate: SQLBinaryExpression(SQLIdentifier("a"), .equal, SQLIdentifier("b")))).queryModifier(for: self.db) ?? SQLUnsafeRaw(""))"), is: "" ) self.db._dialect.upsertSyntax = .unsupported - XCTAssertSerialization(of: self.db.raw("\(SQLConflictResolutionStrategy(target: "a", action: .noAction))"), is: "") - XCTAssertSerialization(of: self.db.raw("\(SQLConflictResolutionStrategy(targets: ["a"], action: .noAction))"), is: "") - XCTAssertSerialization(of: self.db.raw("\(SQLConflictResolutionStrategy(target: SQLIdentifier("a"), action: .noAction))"), is: "") - XCTAssertSerialization(of: self.db.raw("\(SQLConflictResolutionStrategy(targets: [SQLIdentifier("a")], action: .noAction))"), is: "") - XCTAssertSerialization(of: self.db.raw("\(SQLConflictResolutionStrategy(target: "a", action: .noAction).queryModifier(for: self.db) ?? SQLRaw(""))"), is: "") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(target: "a", action: .noAction))"), is: "") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(targets: ["a"], action: .noAction))"), is: "") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(target: SQLIdentifier("a"), action: .noAction))"), is: "") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(targets: [SQLIdentifier("a")], action: .noAction))"), is: "") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(target: "a", action: .noAction).queryModifier(for: self.db) ?? SQLUnsafeRaw(""))"), is: "") XCTAssertSerialization( - of: self.db.raw("\(SQLConflictResolutionStrategy(target: "a", action: .update(assignments: [SQLColumnAssignment(setting: "a", to: "b")], predicate: SQLBinaryExpression(SQLIdentifier("a"), .equal, SQLIdentifier("b")))))"), + of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(target: "a", action: .update(assignments: [SQLColumnAssignment(setting: "a", to: "b")], predicate: SQLBinaryExpression(SQLIdentifier("a"), .equal, SQLIdentifier("b")))))"), is: "" ) XCTAssertSerialization( - of: self.db.raw("\(SQLConflictResolutionStrategy(target: "a", action: .update(assignments: [SQLColumnAssignment(setting: "a", to: "b")], predicate: SQLBinaryExpression(SQLIdentifier("a"), .equal, SQLIdentifier("b")))).queryModifier(for: self.db) ?? SQLRaw(""))"), + of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(target: "a", action: .update(assignments: [SQLColumnAssignment(setting: "a", to: "b")], predicate: SQLBinaryExpression(SQLIdentifier("a"), .equal, SQLIdentifier("b")))).queryModifier(for: self.db) ?? SQLUnsafeRaw(""))"), is: "" ) self.db._dialect.upsertSyntax = .mysqlLike var serializer1 = SQLSerializer(database: self.db) - XCTAssertSerialization(of: self.db.raw("\(SQLConflictResolutionStrategy(target: "a", action: .noAction).queryModifier(for: serializer1) ?? SQLRaw(""))"), is: "IGNORE") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(target: "a", action: .noAction).queryModifier(for: serializer1) ?? SQLUnsafeRaw(""))"), is: "IGNORE") serializer1.statement { - XCTAssertSerialization(of: self.db.raw("\(SQLConflictResolutionStrategy(target: "a", action: .noAction).queryModifier(for: $0) ?? SQLRaw(""))"), is: "IGNORE") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(target: "a", action: .noAction).queryModifier(for: $0) ?? SQLUnsafeRaw(""))"), is: "IGNORE") } self.db._dialect.upsertSyntax = .unsupported let serializer2 = SQLSerializer(database: self.db) - XCTAssertSerialization(of: self.db.raw("\(SQLConflictResolutionStrategy(target: "a", action: .noAction).queryModifier(for: serializer2) ?? SQLRaw(""))"), is: "") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(target: "a", action: .noAction).queryModifier(for: serializer2) ?? SQLUnsafeRaw(""))"), is: "") serializer1.statement { - XCTAssertSerialization(of: self.db.raw("\(SQLConflictResolutionStrategy(target: "a", action: .noAction).queryModifier(for: $0) ?? SQLRaw(""))"), is: "") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLConflictResolutionStrategy(target: "a", action: .noAction).queryModifier(for: $0) ?? SQLUnsafeRaw(""))"), is: "") } } func testEnumDataType() { self.db._dialect.enumSyntax = .inline - XCTAssertSerialization(of: self.db.raw("\(SQLDataType.enum("a", "b"))"), is: "ENUM ('a', 'b')") - XCTAssertSerialization(of: self.db.raw("\(SQLDataType.enum(["a", "b"]))"), is: "ENUM ('a', 'b')") - XCTAssertSerialization(of: self.db.raw("\(SQLDataType.enum([SQLLiteral.string("a"), SQLLiteral.string("b")]))"), is: "ENUM ('a', 'b')") - XCTAssertSerialization(of: self.db.raw("\(SQLEnumDataType(cases: ["a", "b"]))"), is: "ENUM ('a', 'b')") - XCTAssertSerialization(of: self.db.raw("\(SQLEnumDataType(cases: [SQLLiteral.string("a"), SQLLiteral.string("b")]))"), is: "ENUM ('a', 'b')") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLDataType.enum("a", "b"))"), is: "ENUM ('a', 'b')") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLDataType.enum(["a", "b"]))"), is: "ENUM ('a', 'b')") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLDataType.enum([SQLLiteral.string("a"), SQLLiteral.string("b")]))"), is: "ENUM ('a', 'b')") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLEnumDataType(cases: ["a", "b"]))"), is: "ENUM ('a', 'b')") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLEnumDataType(cases: [SQLLiteral.string("a"), SQLLiteral.string("b")]))"), is: "ENUM ('a', 'b')") self.db._dialect.enumSyntax = .typeName - XCTAssertSerialization(of: self.db.raw("\(SQLEnumDataType(cases: ["a", "b"]))"), is: "TEXT") - XCTAssertSerialization(of: self.db.raw("\(SQLEnumDataType(cases: [SQLLiteral.string("a"), SQLLiteral.string("b")]))"), is: "TEXT") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLEnumDataType(cases: ["a", "b"]))"), is: "TEXT") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLEnumDataType(cases: [SQLLiteral.string("a"), SQLLiteral.string("b")]))"), is: "TEXT") self.db._dialect.enumSyntax = .unsupported - XCTAssertSerialization(of: self.db.raw("\(SQLEnumDataType(cases: ["a", "b"]))"), is: "TEXT") - XCTAssertSerialization(of: self.db.raw("\(SQLEnumDataType(cases: [SQLLiteral.string("a"), SQLLiteral.string("b")]))"), is: "TEXT") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLEnumDataType(cases: ["a", "b"]))"), is: "TEXT") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLEnumDataType(cases: [SQLLiteral.string("a"), SQLLiteral.string("b")]))"), is: "TEXT") } func testExcludedColumn() { self.db._dialect.upsertSyntax = .standard - XCTAssertSerialization(of: self.db.raw("\(SQLExcludedColumn("a"))"), is: "EXCLUDED.``a``") - XCTAssertSerialization(of: self.db.raw("\(SQLExcludedColumn(SQLIdentifier("a")))"), is: "EXCLUDED.``a``") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLExcludedColumn("a"))"), is: "EXCLUDED.``a``") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLExcludedColumn(SQLIdentifier("a")))"), is: "EXCLUDED.``a``") self.db._dialect.upsertSyntax = .mysqlLike - XCTAssertSerialization(of: self.db.raw("\(SQLExcludedColumn("a"))"), is: "VALUES(``a``)") - XCTAssertSerialization(of: self.db.raw("\(SQLExcludedColumn(SQLIdentifier("a")))"), is: "VALUES(``a``)") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLExcludedColumn("a"))"), is: "VALUES(``a``)") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLExcludedColumn(SQLIdentifier("a")))"), is: "VALUES(``a``)") self.db._dialect.upsertSyntax = .unsupported - XCTAssertSerialization(of: self.db.raw("\(SQLExcludedColumn("a"))"), is: "") - XCTAssertSerialization(of: self.db.raw("\(SQLExcludedColumn(SQLIdentifier("a")))"), is: "") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLExcludedColumn("a"))"), is: "") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLExcludedColumn(SQLIdentifier("a")))"), is: "") } @available(*, deprecated, message: "Tests deprecated functionality") func testJoinMethod() { - XCTAssertSerialization(of: self.db.raw("\(SQLJoinMethod.inner)"), is: "INNER") - XCTAssertSerialization(of: self.db.raw("\(SQLJoinMethod.outer)"), is: "OUTER") - XCTAssertSerialization(of: self.db.raw("\(SQLJoinMethod.left)"), is: "LEFT") - XCTAssertSerialization(of: self.db.raw("\(SQLJoinMethod.right)"), is: "RIGHT") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLJoinMethod.inner)"), is: "INNER") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLJoinMethod.outer)"), is: "OUTER") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLJoinMethod.left)"), is: "LEFT") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLJoinMethod.right)"), is: "RIGHT") } func testReturningExpr() { - XCTAssertSerialization(of: self.db.raw("\(SQLReturning(SQLColumn("a")))"), is: "RETURNING ``a``") - XCTAssertSerialization(of: self.db.raw("\(SQLReturning([SQLColumn("a")]))"), is: "RETURNING ``a``") - XCTAssertSerialization(of: self.db.raw("\(SQLReturning([]))"), is: "") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLReturning(SQLColumn("a")))"), is: "RETURNING ``a``") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLReturning([SQLColumn("a")]))"), is: "RETURNING ``a``") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLReturning([]))"), is: "") } func testAlterTableQuery() { @@ -209,11 +209,11 @@ final class SQLExpressionTests: XCTestCase { self.db._dialect.alterTableSyntax.allowsBatch = false self.db._dialect.alterTableSyntax.alterColumnDefinitionClause = nil - XCTAssertSerialization(of: self.db.raw("\(query)"), is: "ALTER TABLE ``table`` RENAME TO ``table2`` ADD ``a`` BIGINT , ADD UNIQUE (``d``) , DROP ``c`` , DROP ``e`` , __INVALID__ ``b`` BLOB") + XCTAssertSerialization(of: self.db.unsafeRaw("\(query)"), is: "ALTER TABLE ``table`` RENAME TO ``table2`` ADD ``a`` BIGINT , ADD UNIQUE (``d``) , DROP ``c`` , DROP ``e`` , __INVALID__ ``b`` BLOB") self.db._dialect.alterTableSyntax.allowsBatch = true - XCTAssertSerialization(of: self.db.raw("\(query)"), is: "ALTER TABLE ``table`` RENAME TO ``table2`` ADD ``a`` BIGINT , ADD UNIQUE (``d``) , DROP ``c`` , DROP ``e`` , MODIFY ``b`` BLOB") self.db._dialect.alterTableSyntax.alterColumnDefinitionClause = SQLUnsafeRaw("MODIFY") + XCTAssertSerialization(of: self.db.unsafeRaw("\(query)"), is: "ALTER TABLE ``table`` RENAME TO ``table2`` ADD ``a`` BIGINT , ADD UNIQUE (``d``) , DROP ``c`` , DROP ``e`` , MODIFY ``b`` BLOB") } func testCreateIndexQuery() { @@ -223,55 +223,55 @@ final class SQLExpressionTests: XCTestCase { query.modifier = SQLColumnConstraintAlgorithm.unique query.columns = [SQLIdentifier("a"), SQLIdentifier("b")] query.predicate = SQLBinaryExpression(SQLIdentifier("c"), .equal, SQLIdentifier("d")) - XCTAssertSerialization(of: self.db.raw("\(query)"), is: "CREATE UNIQUE INDEX ``index`` ON ``table`` (``a``, ``b``) WHERE ``c`` = ``d``") + XCTAssertSerialization(of: self.db.unsafeRaw("\(query)"), is: "CREATE UNIQUE INDEX ``index`` ON ``table`` (``a``, ``b``) WHERE ``c`` = ``d``") } func testBinaryOperators() { - XCTAssertSerialization(of: self.db.raw("\(SQLBinaryOperator.equal)"), is: "=") - XCTAssertSerialization(of: self.db.raw("\(SQLBinaryOperator.notEqual)"), is: "<>") - XCTAssertSerialization(of: self.db.raw("\(SQLBinaryOperator.greaterThan)"), is: ">") - XCTAssertSerialization(of: self.db.raw("\(SQLBinaryOperator.lessThan)"), is: "<") - XCTAssertSerialization(of: self.db.raw("\(SQLBinaryOperator.greaterThanOrEqual)"), is: ">=") - XCTAssertSerialization(of: self.db.raw("\(SQLBinaryOperator.lessThanOrEqual)"), is: "<=") - XCTAssertSerialization(of: self.db.raw("\(SQLBinaryOperator.like)"), is: "LIKE") - XCTAssertSerialization(of: self.db.raw("\(SQLBinaryOperator.notLike)"), is: "NOT LIKE") - XCTAssertSerialization(of: self.db.raw("\(SQLBinaryOperator.in)"), is: "IN") - XCTAssertSerialization(of: self.db.raw("\(SQLBinaryOperator.notIn)"), is: "NOT IN") - XCTAssertSerialization(of: self.db.raw("\(SQLBinaryOperator.and)"), is: "AND") - XCTAssertSerialization(of: self.db.raw("\(SQLBinaryOperator.or)"), is: "OR") - XCTAssertSerialization(of: self.db.raw("\(SQLBinaryOperator.multiply)"), is: "*") - XCTAssertSerialization(of: self.db.raw("\(SQLBinaryOperator.divide)"), is: "/") - XCTAssertSerialization(of: self.db.raw("\(SQLBinaryOperator.modulo)"), is: "%") - XCTAssertSerialization(of: self.db.raw("\(SQLBinaryOperator.add)"), is: "+") - XCTAssertSerialization(of: self.db.raw("\(SQLBinaryOperator.subtract)"), is: "-") - XCTAssertSerialization(of: self.db.raw("\(SQLBinaryOperator.is)"), is: "IS") - XCTAssertSerialization(of: self.db.raw("\(SQLBinaryOperator.isNot)"), is: "IS NOT") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLBinaryOperator.equal)"), is: "=") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLBinaryOperator.notEqual)"), is: "<>") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLBinaryOperator.greaterThan)"), is: ">") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLBinaryOperator.lessThan)"), is: "<") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLBinaryOperator.greaterThanOrEqual)"), is: ">=") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLBinaryOperator.lessThanOrEqual)"), is: "<=") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLBinaryOperator.like)"), is: "LIKE") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLBinaryOperator.notLike)"), is: "NOT LIKE") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLBinaryOperator.in)"), is: "IN") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLBinaryOperator.notIn)"), is: "NOT IN") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLBinaryOperator.and)"), is: "AND") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLBinaryOperator.or)"), is: "OR") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLBinaryOperator.multiply)"), is: "*") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLBinaryOperator.divide)"), is: "/") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLBinaryOperator.modulo)"), is: "%") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLBinaryOperator.add)"), is: "+") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLBinaryOperator.subtract)"), is: "-") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLBinaryOperator.is)"), is: "IS") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLBinaryOperator.isNot)"), is: "IS NOT") } func testFunctionInitializers() { - XCTAssertSerialization(of: self.db.raw("\(SQLFunction("test", args: "a", "b"))"), is: "test(``a``, ``b``)") - XCTAssertSerialization(of: self.db.raw("\(SQLFunction("test", args: ["a", "b"]))"), is: "test(``a``, ``b``)") - XCTAssertSerialization(of: self.db.raw("\(SQLFunction("test", args: SQLIdentifier("a"), SQLIdentifier("b")))"), is: "test(``a``, ``b``)") - XCTAssertSerialization(of: self.db.raw("\(SQLFunction("test", args: [SQLIdentifier("a"), SQLIdentifier("b")]))"), is: "test(``a``, ``b``)") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLFunction("test", args: "a", "b"))"), is: "test(``a``, ``b``)") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLFunction("test", args: ["a", "b"]))"), is: "test(``a``, ``b``)") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLFunction("test", args: SQLIdentifier("a"), SQLIdentifier("b")))"), is: "test(``a``, ``b``)") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLFunction("test", args: [SQLIdentifier("a"), SQLIdentifier("b")]))"), is: "test(``a``, ``b``)") } func testCoalesceFunction() { - XCTAssertSerialization(of: self.db.raw("\(SQLFunction.coalesce(SQLIdentifier("a"), SQLIdentifier("b")))"), is: "COALESCE(``a``, ``b``)") - XCTAssertSerialization(of: self.db.raw("\(SQLFunction.coalesce([SQLIdentifier("a"), SQLIdentifier("b")]))"), is: "COALESCE(``a``, ``b``)") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLFunction.coalesce(SQLIdentifier("a"), SQLIdentifier("b")))"), is: "COALESCE(``a``, ``b``)") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLFunction.coalesce([SQLIdentifier("a"), SQLIdentifier("b")]))"), is: "COALESCE(``a``, ``b``)") } func testWeirdQuoting() { self.db._dialect.identifierQuote = SQLQueryString("_") self.db._dialect.literalStringQuote = SQLQueryString("~") - XCTAssertSerialization(of: self.db.raw("\(ident: "hello") \(literal: "there")"), is: "_hello_ ~there~") + XCTAssertSerialization(of: self.db.unsafeRaw("\(ident: "hello") \(literal: "there")"), is: "_hello_ ~there~") } func testColumns() { - XCTAssertSerialization(of: self.db.raw("\(SQLColumn("*"))"), is: "*") - XCTAssertSerialization(of: self.db.raw("\(SQLColumn(SQLIdentifier("*")))"), is: "``*``") - XCTAssertSerialization(of: self.db.raw("\(SQLColumn(SQLLiteral.all))"), is: "*") - XCTAssertSerialization(of: self.db.raw("\(SQLColumn("*", table: "foo"))"), is: "``foo``.*") - XCTAssertSerialization(of: self.db.raw("\(SQLColumn(SQLIdentifier("*"), table: SQLIdentifier("foo")))"), is: "``foo``.``*``") - XCTAssertSerialization(of: self.db.raw("\(SQLColumn(SQLLiteral.all, table: SQLIdentifier("foo")))"), is: "``foo``.*") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumn("*"))"), is: "*") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumn(SQLIdentifier("*")))"), is: "``*``") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumn(SQLLiteral.all))"), is: "*") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumn("*", table: "foo"))"), is: "``foo``.*") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumn(SQLIdentifier("*"), table: SQLIdentifier("foo")))"), is: "``foo``.``*``") + XCTAssertSerialization(of: self.db.unsafeRaw("\(SQLColumn(SQLLiteral.all, table: SQLIdentifier("foo")))"), is: "``foo``.*") } } diff --git a/Tests/SQLKitTests/SQLQueryStringTests.swift b/Tests/SQLKitTests/SQLQueryStringTests.swift index 84bdcce2..205a9fc9 100644 --- a/Tests/SQLKitTests/SQLQueryStringTests.swift +++ b/Tests/SQLKitTests/SQLQueryStringTests.swift @@ -9,17 +9,17 @@ final class SQLQueryStringTests: XCTestCase { } func testWithLiteralString() { - XCTAssertSerialization(of: self.db.raw("TEST"), is: "TEST") + XCTAssertSerialization(of: self.db.unsafeRaw("TEST"), is: "TEST") } func testRawCustomStringConvertible() { let field = "name" - XCTAssertSerialization(of: self.db.raw("SELECT \(unsafeRaw: field) FROM users"), is: "SELECT name FROM users") + XCTAssertSerialization(of: self.db.unsafeRaw("SELECT \(unsafeRaw: field) FROM users"), is: "SELECT name FROM users") } func testRawQueryStringInterpolation() { let (table, planet) = ("planets", "Earth") - let output = XCTAssertNoThrowWithResult(self.db.raw("SELECT * FROM \(ident: table) WHERE name = \(bind: planet)").advancedSerialize()) + let output = XCTAssertNoThrowWithResult(self.db.unsafeRaw("SELECT * FROM \(ident: table) WHERE name = \(bind: planet)").advancedSerialize()) XCTAssertEqual(output?.sql, "SELECT * FROM ``planets`` WHERE name = &1") XCTAssertEqual(output?.binds.first as? String, planet) @@ -29,23 +29,23 @@ final class SQLQueryStringTests: XCTestCase { let (table, planet) = ("planets", "Earth") XCTAssertSerialization( - of: self.db.raw(.init("SELECT * FROM \(table) WHERE name = \(planet)")), + of: self.db.unsafeRaw(.init("SELECT * FROM \(table) WHERE name = \(planet)")), is: "SELECT * FROM planets WHERE name = Earth" ) XCTAssertSerialization( - of: self.db.raw(.init(String("|||SELECT * FROM staticTable WHERE name = uselessUnboundValue|||".dropFirst(3).dropLast(3)))), + of: self.db.unsafeRaw(.init(String("|||SELECT * FROM staticTable WHERE name = uselessUnboundValue|||".dropFirst(3).dropLast(3)))), is: "SELECT * FROM staticTable WHERE name = uselessUnboundValue" ) } func testMakeQueryStringWithoutRawBuilder() { let queryString = SQLQueryString("query with \(ident: "identifier") and stuff") - XCTAssertSerialization(of: self.db.raw(queryString), is: "query with ``identifier`` and stuff") + XCTAssertSerialization(of: self.db.unsafeRaw(queryString), is: "query with ``identifier`` and stuff") } func testAllQueryStringInterpolationTypes() { XCTAssertSerialization( - of: self.db.raw(""" + of: self.db.unsafeRaw(""" Query string embeds: \(unsafeRaw: "plain string embed") \(bind: "single bind embed") @@ -79,7 +79,7 @@ final class SQLQueryStringTests: XCTestCase { func testAppendingQueryStringByOperatorPlus() { XCTAssertSerialization( - of: self.db.raw( + of: self.db.unsafeRaw( "INSERT INTO \(ident: "anything") " as SQLQueryString + "(\(idents: ["col1", "col2", "col3"], joinedBy: ",")) " as SQLQueryString + "VALUES (\(binds: [1, 2, 3]))" as SQLQueryString @@ -93,17 +93,17 @@ final class SQLQueryStringTests: XCTestCase { query += "(\(idents: ["col1", "col2", "col3"], joinedBy: ",")) " as SQLQueryString query += "VALUES (\(binds: [1, 2, 3]))" as SQLQueryString - XCTAssertSerialization(of: self.db.raw(query), is: "INSERT INTO ``anything`` (``col1``,``col2``,``col3``) VALUES (&1, &2, &3)") + XCTAssertSerialization(of: self.db.unsafeRaw(query), is: "INSERT INTO ``anything`` (``col1``,``col2``,``col3``) VALUES (&1, &2, &3)") } func testQueryStringArrayJoin() { XCTAssertSerialization( - of: self.db.raw( + of: self.db.unsafeRaw( "INSERT INTO \(ident: "anything") " as SQLQueryString + ((0..<5).map { "\(literal: "\($0)")" as SQLQueryString }).joined(separator: "..") ), is: "INSERT INTO ``anything`` '0'..'1'..'2'..'3'..'4'" ) - XCTAssertSerialization(of: self.db.raw(Array().joined()), is: "") + XCTAssertSerialization(of: self.db.unsafeRaw(Array().joined()), is: "") } } diff --git a/Tests/SQLKitTests/SQLUnionTests.swift b/Tests/SQLKitTests/SQLUnionTests.swift index af0b0949..f9750890 100644 --- a/Tests/SQLKitTests/SQLUnionTests.swift +++ b/Tests/SQLKitTests/SQLUnionTests.swift @@ -194,10 +194,10 @@ final class SQLUnionTests: XCTestCase { query.add(self.db.select().columns("*").select, all: false) self.db._dialect.unionFeatures = [] - XCTAssertSerialization(of: self.db.raw("\(query)"), is: "SELECT * SELECT * SELECT *") + XCTAssertSerialization(of: self.db.unsafeRaw("\(query)"), is: "SELECT * SELECT * SELECT *") self.db._dialect.unionFeatures = [.union, .unionAll] - XCTAssertSerialization(of: self.db.raw("\(query)"), is: "SELECT * UNION ALL SELECT * UNION SELECT *") + XCTAssertSerialization(of: self.db.unsafeRaw("\(query)"), is: "SELECT * UNION ALL SELECT * UNION SELECT *") } // MARK: Subquery unions From ca73531100f486760e0efa70284f2e83f9af5e3a Mon Sep 17 00:00:00 2001 From: Gwynne Raskind Date: Wed, 16 Apr 2025 18:36:31 -0500 Subject: [PATCH 5/5] Make the API breakage checker happy --- Sources/SQLKit/Deprecated/SQLDatabase+Deprecated.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/SQLKit/Deprecated/SQLDatabase+Deprecated.swift b/Sources/SQLKit/Deprecated/SQLDatabase+Deprecated.swift index 77171bad..4d9b7f1e 100644 --- a/Sources/SQLKit/Deprecated/SQLDatabase+Deprecated.swift +++ b/Sources/SQLKit/Deprecated/SQLDatabase+Deprecated.swift @@ -42,7 +42,7 @@ extension SQLDatabaseReportedVersion { extension SQLDatabase { @available(*, deprecated, renamed: "unsafeRaw(_:)", message: "SQLDatabase.unsafeRaw(_:) has been renamed to SQLDatabase.unsafeRaw(_:).") @inlinable - public func raw(_ sql: SQLQueryString) -> SQLUnsafeRawBuilder { + public func raw(_ sql: SQLQueryString) -> SQLRawBuilder { self.unsafeRaw(sql) } }