-
-
Notifications
You must be signed in to change notification settings - Fork 58
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for UNION queries (#133)
- Loading branch information
1 parent
bfcaa63
commit d2027b4
Showing
3 changed files
with
132 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
public final class SQLUnionBuilder: SQLQueryBuilder { | ||
public var query: SQLExpression { self.union } | ||
|
||
public var union: SQLUnion | ||
public var database: SQLDatabase | ||
|
||
public init(on database: SQLDatabase, initialQuery: SQLSelect) { | ||
self.union = .init(initialQuery: initialQuery) | ||
self.database = database | ||
} | ||
|
||
public func union(distinct query: SQLSelect) -> Self { | ||
self.union.add(query, all: false) | ||
return self | ||
} | ||
|
||
public func union(all query: SQLSelect) -> Self { | ||
self.union.add(query, all: true) | ||
return self | ||
} | ||
} | ||
|
||
extension SQLDatabase { | ||
public func union(_ predicate: (SQLSelectBuilder) -> SQLSelectBuilder) -> SQLUnionBuilder { | ||
return SQLUnionBuilder(on: self, initialQuery: predicate(.init(on: self)).select) | ||
} | ||
} | ||
|
||
extension SQLUnionBuilder { | ||
public func union(distinct predicate: (SQLSelectBuilder) -> SQLSelectBuilder) -> Self { | ||
return self.union(distinct: predicate(.init(on: self.database)).select) | ||
} | ||
|
||
/// Alias the `distinct` variant so it acts as the "default". | ||
public func union(_ predicate: (SQLSelectBuilder) -> SQLSelectBuilder) -> Self { | ||
return self.union(distinct: predicate) | ||
} | ||
|
||
public func union(all predicate: (SQLSelectBuilder) -> SQLSelectBuilder) -> Self { | ||
return self.union(all: predicate(.init(on: self.database)).select) | ||
} | ||
} | ||
|
||
extension SQLSelectBuilder { | ||
public func union(distinct predicate: (SQLSelectBuilder) -> SQLSelectBuilder) -> SQLUnionBuilder { | ||
return SQLUnionBuilder(on: self.database, initialQuery: self.select) | ||
.union(distinct: predicate(.init(on: self.database)).select) | ||
} | ||
|
||
/// Alias the `distinct` variant so it acts as the "default". | ||
public func union(_ predicate: (SQLSelectBuilder) -> SQLSelectBuilder) -> SQLUnionBuilder { | ||
return SQLUnionBuilder(on: self.database, initialQuery: self.select) | ||
.union(distinct: predicate(.init(on: self.database)).select) | ||
} | ||
|
||
public func union(all predicate: (SQLSelectBuilder) -> SQLSelectBuilder) -> SQLUnionBuilder { | ||
return SQLUnionBuilder(on: self.database, initialQuery: self.select) | ||
.union(all: predicate(.init(on: self.database)).select) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
public struct SQLUnion: SQLExpression { | ||
public var initialQuery: SQLSelect | ||
public var unions: [(SQLUnionJoiner, SQLSelect)] | ||
|
||
public init(initialQuery: SQLSelect, unions: [(SQLUnionJoiner, SQLSelect)] = []) { | ||
self.initialQuery = initialQuery | ||
self.unions = unions | ||
} | ||
|
||
public mutating func add(_ query: SQLSelect, all: Bool) { | ||
self.unions.append((.init(all: all), query)) | ||
} | ||
|
||
public func serialize(to serializer: inout SQLSerializer) { | ||
assert(!self.unions.isEmpty, "Serializing a union with only one query is invalid.") | ||
SQLGroupExpression(self.initialQuery).serialize(to: &serializer) | ||
self.unions | ||
.forEach { (joiner, select) in | ||
joiner.serialize(to: &serializer) | ||
SQLGroupExpression(select).serialize(to: &serializer) | ||
} | ||
} | ||
} | ||
|
||
public struct SQLUnionJoiner: SQLExpression { | ||
public var all: Bool | ||
|
||
public init(all: Bool) { | ||
self.all = all | ||
} | ||
|
||
public func serialize(to serializer: inout SQLSerializer) { | ||
serializer.write(" UNION\(self.all ? " ALL" : "") ") | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters