Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ public final class SQLAlterTableBuilder: SQLQueryBuilder {
@inlinable
@discardableResult
public func column(_ column: String, type dataType: SQLDataType, _ constraints: [SQLColumnConstraintAlgorithm]) -> Self {
self.column(SQLIdentifier(column), type: dataType, constraints)
// Box each element explicitly: the implicit `[Concrete]` to `[any SQLExpression]` array
// conversion is a dynamic cast, which Embedded Swift forbids.
self.column(SQLIdentifier(column), type: dataType, constraints.map { $0 as any SQLExpression })
}

/// Add a new column to the table.
Expand Down Expand Up @@ -81,7 +83,7 @@ public final class SQLAlterTableBuilder: SQLQueryBuilder {
@inlinable
@discardableResult
public func modifyColumn(_ column: String, type dataType: SQLDataType, _ constraints: [SQLColumnConstraintAlgorithm]) -> Self {
self.modifyColumn(SQLIdentifier(column), type: dataType, constraints)
self.modifyColumn(SQLIdentifier(column), type: dataType, constraints.map { $0 as any SQLExpression })
}

/// Change an existing column's type and constraints.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public final class SQLConflictUpdateBuilder: SQLColumnUpdateBuilder, SQLPredicat
return self
}

// Codable model encoding (SQLQueryEncoder) is unavailable in Embedded Swift.
#if !hasFeature(Embedded)
/// Encodes the given `Encodable` value to a sequence of key-value pairs and adds an assignment
/// for each pair which uses the values each column was given in the original `INSERT` query's
/// `VALUES` list.
Expand Down Expand Up @@ -75,4 +77,5 @@ public final class SQLConflictUpdateBuilder: SQLColumnUpdateBuilder, SQLPredicat
) throws -> Self {
try encoder.encode(model).reduce(self) { $0.set(excludedValueOf: $1.0) }
}
#endif // !hasFeature(Embedded)
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public final class SQLCreateTableBuilder: SQLQueryBuilder {
@inlinable
@discardableResult
public func column(_ column: String, type dataType: SQLDataType, _ constraints: [SQLColumnConstraintAlgorithm]) -> Self {
self.column(SQLIdentifier(column), type: dataType, constraints)
self.column(SQLIdentifier(column), type: dataType, constraints.map { $0 as any SQLExpression })
}

/// Add a new column by name, type, and constraints.
Expand Down Expand Up @@ -66,7 +66,9 @@ public final class SQLCreateTableBuilder: SQLQueryBuilder {
@inlinable
@discardableResult
public func column(definitions: [SQLColumnDefinition]) -> SQLCreateTableBuilder {
self.columns.append(contentsOf: definitions)
// Box each element explicitly: the implicit `[Concrete]` to `[any SQLExpression]` array
// conversion is a dynamic cast, which Embedded Swift forbids.
self.columns.append(contentsOf: definitions.map { $0 as any SQLExpression })
return self
}

Expand Down Expand Up @@ -125,7 +127,10 @@ extension SQLCreateTableBuilder {
@inlinable
@discardableResult
public func primaryKey(_ columns: [String], named constraintName: String? = nil) -> Self {
self.primaryKey(columns.map(SQLIdentifier.init(_:)), named: constraintName.map(SQLIdentifier.init(_:)))
// Box each element to `any SQLExpression`: the implicit `[Concrete]`/`Concrete?` to
// `[any SQLExpression]`/`(any SQLExpression)?` conversions are dynamic casts, which
// Embedded Swift forbids.
self.primaryKey(columns.map { SQLIdentifier($0) as any SQLExpression }, named: constraintName.map { SQLIdentifier($0) as any SQLExpression })
}

/// Add a `PRIMARY KEY` constraint to the table.
Expand Down Expand Up @@ -162,7 +167,7 @@ extension SQLCreateTableBuilder {
@inlinable
@discardableResult
public func unique(_ columns: [String], named constraintName: String? = nil) -> Self {
self.unique(columns.map(SQLIdentifier.init(_:)), named: constraintName.map(SQLIdentifier.init(_:)))
self.unique(columns.map { SQLIdentifier($0) as any SQLExpression }, named: constraintName.map { SQLIdentifier($0) as any SQLExpression })
}

/// Add a `UNIQUE` constraint to the table.
Expand All @@ -188,7 +193,7 @@ extension SQLCreateTableBuilder {
@inlinable
@discardableResult
public func check(_ expression: any SQLExpression, named constraintName: String? = nil) -> Self {
self.check(expression, named: constraintName.map(SQLIdentifier.init(_:)))
self.check(expression, named: constraintName.map { SQLIdentifier($0) as any SQLExpression })
}

/// Add a `CHECK` constraint to the table.
Expand Down Expand Up @@ -226,10 +231,10 @@ extension SQLCreateTableBuilder {
named constraintName: String? = nil
) -> Self {
self.foreignKey(
columns.map(SQLIdentifier.init(_:)),
references: SQLIdentifier(foreignTable), foreignColumns.map(SQLIdentifier.init(_:)),
columns.map { SQLIdentifier($0) as any SQLExpression },
references: SQLIdentifier(foreignTable), foreignColumns.map { SQLIdentifier($0) as any SQLExpression },
onDelete: onDelete, onUpdate: onUpdate,
named: constraintName.map(SQLIdentifier.init(_:))
named: constraintName.map { SQLIdentifier($0) as any SQLExpression }
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public final class SQLCreateTriggerBuilder: SQLQueryBuilder {
@inlinable
@discardableResult
public func columns(_ columns: [String]) -> Self {
self.columns(columns.map(SQLIdentifier.init(_:)))
self.columns(columns.map { SQLIdentifier($0) as any SQLExpression })
}

/// Specify the columns to which the trigger applies.
Expand Down
17 changes: 10 additions & 7 deletions Sources/SQLKit/Builders/Implementations/SQLInsertBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ public final class SQLInsertBuilder: SQLQueryBuilder, SQLReturningBuilder/*, SQL
self.database = database
}

// Codable model encoding (SQLQueryEncoder) is unavailable in Embedded Swift.
#if !hasFeature(Embedded)
/// Use an `Encodable` value to generate a row to insert and add that row to the query.
///
/// Example usage:
Expand Down Expand Up @@ -216,7 +218,8 @@ public final class SQLInsertBuilder: SQLQueryBuilder, SQLReturningBuilder/*, SQL
}
return self
}

#endif // !hasFeature(Embedded)

/// Specify mutiple columns to be included in the list of columns for the query.
///
/// Overwrites any previously specified column list.
Expand All @@ -232,7 +235,7 @@ public final class SQLInsertBuilder: SQLQueryBuilder, SQLReturningBuilder/*, SQL
@inlinable
@discardableResult
public func columns(_ columns: [String]) -> Self {
self.columns(columns.map(SQLIdentifier.init(_:)))
self.columns(columns.map { SQLIdentifier($0) as any SQLExpression })
}

/// Specify mutiple columns to be included in the list of columns for the query.
Expand All @@ -258,15 +261,15 @@ public final class SQLInsertBuilder: SQLQueryBuilder, SQLReturningBuilder/*, SQL
@inlinable
@discardableResult
@_disfavoredOverload
public func values(_ values: any Encodable & Sendable...) -> Self {
public func values(_ values: any SQLBindable & Sendable...) -> Self {
self.values(values)
}

/// Add a set of values to be inserted as a single row.
@inlinable
@discardableResult
public func values(_ values: [any Encodable & Sendable]) -> Self {
self.values(values.map { SQLBind($0) })
public func values(_ values: [any SQLBindable & Sendable]) -> Self {
self.values(values.map { SQLBind($0) as any SQLExpression })
}

/// Add a set of values to be inserted as a single row.
Expand Down Expand Up @@ -334,7 +337,7 @@ public final class SQLInsertBuilder: SQLQueryBuilder, SQLReturningBuilder/*, SQL
@inlinable
@discardableResult
public func ignoringConflicts(with targetColumns: [String] = []) -> Self {
self.ignoringConflicts(with: targetColumns.map(SQLIdentifier.init(_:)))
self.ignoringConflicts(with: targetColumns.map { SQLIdentifier($0) as any SQLExpression })
}

/// Specify that constraint violations for the key over the given columns should cause the conflicting
Expand Down Expand Up @@ -365,7 +368,7 @@ public final class SQLInsertBuilder: SQLQueryBuilder, SQLReturningBuilder/*, SQL
with targetColumns: [String] = [],
`do` updatePredicate: (SQLConflictUpdateBuilder) throws -> SQLConflictUpdateBuilder
) rethrows -> Self {
try self.onConflict(with: targetColumns.map(SQLIdentifier.init(_:)), do: updatePredicate)
try self.onConflict(with: targetColumns.map { SQLIdentifier($0) as any SQLExpression }, do: updatePredicate)
}

/// Specify that constraint violations for the key over the given column should cause the conflicting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ public protocol SQLColumnUpdateBuilder: AnyObject {
}

extension SQLColumnUpdateBuilder {
// Codable model encoding (SQLQueryEncoder) is unavailable in Embedded Swift.
#if !hasFeature(Embedded)
/// Using a default-configured ``SQLQueryEncoder``, transform the provided model into a series of key/value
/// pairs and add an assignment for each pair.
///
Expand Down Expand Up @@ -66,6 +68,7 @@ extension SQLColumnUpdateBuilder {
) throws -> Self {
try encoder.encode(model).reduce(self) { $0.set(SQLColumn($1.0), to: $1.1) }
}
#endif // !hasFeature(Embedded)

/// Add an assignment setting the named column to the provided `Encodable` value.
///
Expand All @@ -76,7 +79,7 @@ extension SQLColumnUpdateBuilder {
/// - bind: The value to assign to the named column.
@inlinable
@discardableResult
public func set(_ column: String, to bind: any Encodable & Sendable) -> Self {
public func set(_ column: String, to bind: any SQLBindable & Sendable) -> Self {
self.set(SQLColumn(column), to: SQLBind(bind))
}

Expand All @@ -102,7 +105,7 @@ extension SQLColumnUpdateBuilder {
/// - bind: The value to assign to the given column.
@inlinable
@discardableResult
public func set(_ column: any SQLExpression, to bind: any Encodable & Sendable) -> Self {
public func set(_ column: any SQLExpression, to bind: any SQLBindable & Sendable) -> Self {
self.set(column, to: SQLBind(bind))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ extension SQLCommonTableExpressionBuilder {
@inlinable
@discardableResult
public func with(_ name: some StringProtocol, columns: [String], as query: some SQLExpression) -> Self {
self.with(name, columns: columns.map(SQLIdentifier.init(_:)), as: query)
self.with(name, columns: columns.map { SQLIdentifier($0) as any SQLExpression }, as: query)
}

/// Specify a subquery to include as a _recursive_ common table expression, for use elsewhere in
Expand Down Expand Up @@ -70,7 +70,7 @@ extension SQLCommonTableExpressionBuilder {
@inlinable
@discardableResult
public func with(recursive name: some StringProtocol, columns: [String], as query: some SQLExpression) -> Self {
self.with(recursive: name, columns: columns.map(SQLIdentifier.init(_:)), as: query)
self.with(recursive: name, columns: columns.map { SQLIdentifier($0) as any SQLExpression }, as: query)
}

// MARK: - String name, expression columns
Expand Down Expand Up @@ -170,7 +170,7 @@ extension SQLCommonTableExpressionBuilder {
@inlinable
@discardableResult
public func with(_ name: some SQLExpression, columns: [String], as query: some SQLExpression) -> Self {
self.with(name, columns: columns.map(SQLIdentifier.init(_:)), as: query)
self.with(name, columns: columns.map { SQLIdentifier($0) as any SQLExpression }, as: query)
}

/// Specify a subquery to include as a _recursive_ common table expression, for use elsewhere in
Expand Down Expand Up @@ -206,7 +206,7 @@ extension SQLCommonTableExpressionBuilder {
@inlinable
@discardableResult
public func with(recursive name: some SQLExpression, columns: [String], as query: some SQLExpression) -> Self {
self.with(recursive: name, columns: columns.map(SQLIdentifier.init(_:)), as: query)
self.with(recursive: name, columns: columns.map { SQLIdentifier($0) as any SQLExpression }, as: query)
}

// MARK: - Expression name, expression columns
Expand Down
24 changes: 12 additions & 12 deletions Sources/SQLKit/Builders/Prototypes/SQLPredicateBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ extension SQLPredicateBuilder {
/// SELECT * FROM "planets" WHERE "name" = $0 ["Earth"]
@inlinable
@discardableResult
public func `where`(_ lhs: String, _ op: SQLBinaryOperator, _ rhs: some Encodable & Sendable) -> Self {
public func `where`(_ lhs: String, _ op: SQLBinaryOperator, _ rhs: some SQLBindable & Sendable) -> Self {
self.where(SQLColumn(lhs), op, SQLBind(rhs))
}

Expand All @@ -36,8 +36,8 @@ extension SQLPredicateBuilder {
/// SELECT * FROM "planets" WHERE "name" IN ($0, $1) ["Earth", "Mars"]
@inlinable
@discardableResult
public func `where`(_ lhs: String, _ op: SQLBinaryOperator, _ rhs: [some Encodable & Sendable]) -> Self {
self.where(SQLColumn(lhs), op, SQLBind.group(rhs))
public func `where`(_ lhs: String, _ op: SQLBinaryOperator, _ rhs: [some SQLBindable & Sendable]) -> Self {
self.where(SQLColumn(lhs), op, SQLBind.group(rhs.map { $0 as any SQLBindable & Sendable }))
}

/// Adds a column to encodable comparison to this builder's `WHERE` clause by `AND`ing.
Expand All @@ -49,7 +49,7 @@ extension SQLPredicateBuilder {
/// SELECT * FROM "planets" WHERE "name" = $0 ["Earth"]
@inlinable
@discardableResult
public func `where`(_ lhs: SQLIdentifier, _ op: SQLBinaryOperator, _ rhs: some Encodable & Sendable) -> Self {
public func `where`(_ lhs: SQLIdentifier, _ op: SQLBinaryOperator, _ rhs: some SQLBindable & Sendable) -> Self {
self.where(SQLColumn(lhs), op, SQLBind(rhs))
}

Expand All @@ -62,8 +62,8 @@ extension SQLPredicateBuilder {
/// SELECT * FROM "planets" WHERE "name" IN ($0, $1) ["Earth", "Mars"]
@inlinable
@discardableResult
public func `where`(_ lhs: SQLIdentifier, _ op: SQLBinaryOperator, _ rhs: [some Encodable & Sendable]) -> Self {
self.where(SQLColumn(lhs), op, SQLBind.group(rhs))
public func `where`(_ lhs: SQLIdentifier, _ op: SQLBinaryOperator, _ rhs: [some SQLBindable & Sendable]) -> Self {
self.where(SQLColumn(lhs), op, SQLBind.group(rhs.map { $0 as any SQLBindable & Sendable }))
}

// MARK: - Column/column comparison
Expand Down Expand Up @@ -154,7 +154,7 @@ extension SQLPredicateBuilder {
/// SELECT * FROM "planets" WHERE "name" = $0 ["Earth"]
@inlinable
@discardableResult
public func orWhere(_ lhs: String, _ op: SQLBinaryOperator, _ rhs: some Encodable & Sendable) -> Self {
public func orWhere(_ lhs: String, _ op: SQLBinaryOperator, _ rhs: some SQLBindable & Sendable) -> Self {
self.orWhere(SQLColumn(lhs), op, SQLBind(rhs))
}

Expand All @@ -167,22 +167,22 @@ extension SQLPredicateBuilder {
/// SELECT * FROM "planets" WHERE "name" IN ($0, $1) ["Earth", "Mars"]
@inlinable
@discardableResult
public func orWhere(_ lhs: String, _ op: SQLBinaryOperator, _ rhs: [some Encodable & Sendable]) -> Self {
self.orWhere(SQLColumn(lhs), op, SQLBind.group(rhs))
public func orWhere(_ lhs: String, _ op: SQLBinaryOperator, _ rhs: [some SQLBindable & Sendable]) -> Self {
self.orWhere(SQLColumn(lhs), op, SQLBind.group(rhs.map { $0 as any SQLBindable & Sendable }))
}

/// Adds a column to encodable comparison to this builder's `WHERE` clause by `OR`ing.
@inlinable
@discardableResult
public func orWhere(_ lhs: SQLIdentifier, _ op: SQLBinaryOperator, _ rhs: some Encodable & Sendable) -> Self {
public func orWhere(_ lhs: SQLIdentifier, _ op: SQLBinaryOperator, _ rhs: some SQLBindable & Sendable) -> Self {
self.orWhere(SQLColumn(lhs), op, SQLBind(rhs))
}

/// Adds a column to encodable array comparison to this builder's `WHERE` clause by `OR`ing.
@inlinable
@discardableResult
public func orWhere(_ lhs: SQLIdentifier, _ op: SQLBinaryOperator, _ rhs: [some Encodable & Sendable]) -> Self {
self.orWhere(SQLColumn(lhs), op, SQLBind.group(rhs))
public func orWhere(_ lhs: SQLIdentifier, _ op: SQLBinaryOperator, _ rhs: [some SQLBindable & Sendable]) -> Self {
self.orWhere(SQLColumn(lhs), op, SQLBind.group(rhs.map { $0 as any SQLBindable & Sendable }))
}

// MARK: - Column/column comparison
Expand Down
13 changes: 12 additions & 1 deletion Sources/SQLKit/Builders/Prototypes/SQLQueryFetcher.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// `EventLoopFuture` is unavailable where SwiftNIO is not linked. The `async` `first()`/`all()`/
// `run(_:)` families further down are unconditional and carry the whole surface there.
// `run(_:)` families further down are unconditional and carry the whole surface there; their
// `<D: Decodable>` overloads additionally drop out in Embedded Swift, which has no Codable.
#if canImport(NIOCore)
import class NIOCore.EventLoopFuture
#endif
Expand Down Expand Up @@ -80,6 +81,7 @@ extension SQLQueryFetcher {
// MARK: - First (async)

extension SQLQueryFetcher {
#if !hasFeature(Embedded)
/// Returns the named column from the first output row, if any, decoded as a given type.
///
/// - Parameters:
Expand Down Expand Up @@ -129,6 +131,7 @@ extension SQLQueryFetcher {
public func first<D: Decodable>(decoding type: D.Type, with decoder: SQLRowDecoder) async throws -> D? {
try await self.first()?.decode(model: D.self, with: decoder)
}
#endif // !hasFeature(Embedded)

/// Returns the first output row, if any.
///
Expand All @@ -142,7 +145,11 @@ extension SQLQueryFetcher {
/// - Returns: The first output row, if any.
@inlinable
public func first() async throws -> Optional<any SQLRow> {
// `as?` to a different existential is a dynamic cast, which Embedded Swift forbids; skip the
// LIMIT-1 optimization there (correctness is unaffected; we just fetch and take the first).
#if !hasFeature(Embedded)
(self as? any SQLPartialResultBuilder)?.limit(1)
#endif
nonisolated(unsafe) var rows = [any SQLRow]()
try await self.run { if rows.isEmpty { rows.append($0) } }
return rows.first
Expand Down Expand Up @@ -218,6 +225,7 @@ extension SQLQueryFetcher {
// MARK: - All (async)

extension SQLQueryFetcher {
#if !hasFeature(Embedded)
/// Returns the named column from each output row, if any, decoded as a given type.
///
/// - Parameters:
Expand Down Expand Up @@ -267,6 +275,7 @@ extension SQLQueryFetcher {
public func all<D: Decodable>(decoding type: D.Type, with decoder: SQLRowDecoder) async throws -> [D] {
try await self.all().map { try $0.decode(model: D.self, with: decoder) }
}
#endif // !hasFeature(Embedded)

/// Returns all output rows, if any.
///
Expand Down Expand Up @@ -353,6 +362,7 @@ extension SQLQueryFetcher {
// MARK: - Run (async)

extension SQLQueryFetcher {
#if !hasFeature(Embedded)
/// Using a default-configured ``SQLRowDecoder``, call the provided handler closure with the result of decoding
/// each output row, if any, as a given type.
///
Expand Down Expand Up @@ -401,6 +411,7 @@ extension SQLQueryFetcher {
) async throws {
try await self.run { row in handler(Result { try row.decode(model: D.self, with: decoder) }) }
}
#endif // !hasFeature(Embedded)

/// Run the query specified by the builder, calling the provided handler closure with each output row, if any, as
/// it is received.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ extension SQLReturningBuilder {
/// - Returns: A ``SQLReturningResultBuilder`` which must be used to execute the query.
@inlinable
public func returning(_ columns: String...) -> SQLReturningResultBuilder<Self> {
self.returning(columns.map { SQLColumn($0 == "*" ? SQLLiteral.all : SQLIdentifier($0)) })
self.returning(columns.map { SQLColumn($0 == "*" ? SQLLiteral.all : SQLIdentifier($0)) as any SQLExpression })
}

/// Specify a list of columns to be returned as the result of the query.
Expand Down
Loading