Skip to content

Commit

Permalink
Added support for the union query clause
Browse files Browse the repository at this point in the history
  • Loading branch information
stephanheilner committed Sep 7, 2017
1 parent ec7b589 commit 2efa00e
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 1 deletion.
39 changes: 38 additions & 1 deletion Sources/SQLite/Typed/Query.swift
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,27 @@ extension QueryType {
return query
}

// MARK: UNION

/// Adds a `UNION` clause to the query.
///
/// let users = Table("users")
/// let email = Expression<String>("email")
///
/// users.filter(email == "alice@example.com").union(users.filter(email == "sally@example.com"))
/// // SELECT * FROM "users" WHERE email = 'alice@example.com' UNION SELECT * FROM "users" WHERE email = 'sally@example.com'
///
/// - Parameters:
///
/// - table: A query representing the other table.
///
/// - Returns: A query with the given `UNION` clause applied.
public func union(_ table: QueryType) -> Self {
var query = self
query.clauses.union.append(table)
return query
}

// MARK: JOIN

/// Adds a `JOIN` clause to the query.
Expand Down Expand Up @@ -565,6 +586,19 @@ extension QueryType {
Expression<Void>(literal: "OFFSET \(offset)")
])
}

fileprivate var unionClause: Expressible? {
guard !clauses.union.isEmpty else {
return nil
}

return " ".join(clauses.union.map { query in
" ".join([
Expression<Void>(literal: "UNION"),
query
])
})
}

// MARK: -

Expand Down Expand Up @@ -780,7 +814,8 @@ extension QueryType {
whereClause,
groupByClause,
orderClause,
limitOffsetClause
limitOffsetClause,
unionClause
]

return " ".join(clauses.flatMap { $0 }).expression
Expand Down Expand Up @@ -1154,6 +1189,8 @@ public struct QueryClauses {
var order = [Expressible]()

var limit: (length: Int, offset: Int?)?

var union = [QueryType]()

fileprivate init(_ name: String, alias: String?, database: String?) {
self.from = (name, alias, database)
Expand Down
13 changes: 13 additions & 0 deletions Tests/SQLiteTests/QueryTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -361,5 +361,18 @@ class QueryIntegrationTests : SQLiteTestCase {
let changes = try! db.run(users.delete())
XCTAssertEqual(0, changes)
}

func test_union() throws {
let expectedIDs = [
try db.run(users.insert(email <- "alice@example.com")),
try db.run(users.insert(email <- "sally@example.com"))
]

let query1 = users.filter(email == "alice@example.com")
let query2 = users.filter(email == "sally@example.com")

let actualIDs = try db.prepare(query1.union(query2)).map { $0[id] }
XCTAssertEqual(expectedIDs, actualIDs)
}

}

0 comments on commit 2efa00e

Please sign in to comment.