Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Heed linter warnings
Note sure how to get the line length of Query back down below 500 without harming readability though.
  • Loading branch information
marmphco committed Jul 8, 2022
commit 76d34dd8ff668b58d6b5530528460dd6d2786c0e
2 changes: 1 addition & 1 deletion Documentation/Index.md
Original file line number Diff line number Diff line change
Expand Up @@ -1130,7 +1130,7 @@ let queryWithLevel =
chain.with(chain,
columns: [id, managerId, level],
recursive: true,
materializationHint: .materialize,
hint: .materialize,
as: queryWithLevel)
// WITH RECURSIVE
// "chain" ("id", "manager_id", "level") AS MATERIALIZED (
Expand Down
29 changes: 15 additions & 14 deletions Sources/SQLite/Typed/Query.swift
Original file line number Diff line number Diff line change
Expand Up @@ -498,9 +498,9 @@ extension QueryType {
query.clauses.limit = length.map { ($0, offset) }
return query
}

// MARK: WITH

/// Sets a `WITH` clause on the query.
///
/// let users = Table("users")
Expand All @@ -517,14 +517,15 @@ extension QueryType {
///
/// - recursive: Whether to evaluate the expression recursively.
///
/// - materializationHint: Provides a hint to the query planner for how the expression should be implemented.
/// - hint: Provides a hint to the query planner for how the expression should be implemented.
///
/// - subquery: A query that generates the rows for the table expression.
///
/// - Returns: A query with the given `ORDER BY` clause applied.
public func with(_ alias: Table, columns: [Expressible]? = nil, recursive: Bool = false, materializationHint: MaterializationHint? = nil, as subquery: QueryType) -> Self {
public func with(_ alias: Table, columns: [Expressible]? = nil, recursive: Bool = false,
hint: MaterializationHint? = nil, as subquery: QueryType) -> Self {
var query = self
let clause = WithClauses.Clause(alias: alias, columns: columns, materializationHint: materializationHint, query: subquery)
let clause = WithClauses.Clause(alias: alias, columns: columns, hint: hint, query: subquery)
query.clauses.with.recursive = query.clauses.with.recursive || recursive
query.clauses.with.clauses.append(clause)
return query
Expand Down Expand Up @@ -636,38 +637,38 @@ extension QueryType {
])
})
}

fileprivate var withClause: Expressible? {
guard !clauses.with.clauses.isEmpty else {
return nil
}

let innerClauses = ", ".join(clauses.with.clauses.map { (clause) in
let hintExpr: Expression<Void>?
if let hint = clause.materializationHint {
if let hint = clause.hint {
hintExpr = Expression<Void>(literal: hint.rawValue)
} else {
hintExpr = nil
}

let columnExpr: Expression<Void>?
if let columns = clause.columns {
columnExpr = "".wrap(", ".join(columns))
} else {
columnExpr = nil
}

let expressions: [Expressible?] = [
clause.alias.tableName(),
columnExpr,
Expression<Void>(literal: "AS"),
hintExpr,
"".wrap(clause.query) as Expression<Void>
]

return " ".join(expressions.compactMap { $0 })
})

return " ".join([
Expression<Void>(literal: clauses.with.recursive ? "WITH RECURSIVE" : "WITH"),
innerClauses
Expand Down Expand Up @@ -1318,12 +1319,12 @@ struct WithClauses {
struct Clause {
var alias: Table
var columns: [Expressible]?
var materializationHint: MaterializationHint?
var hint: MaterializationHint?
var query: QueryType
}
/// The `RECURSIVE` flag is applied to the entire `WITH` clause
var recursive: Bool = false

/// Each `WITH` clause may have multiple subclauses
var clauses: [Clause] = []
}
Expand All @@ -1345,7 +1346,7 @@ public struct QueryClauses {
var limit: (length: Int, offset: Int?)?

var union = [(all: Bool, table: QueryType)]()

var with = WithClauses()

fileprivate init(_ name: String, alias: String?, database: String?) {
Expand Down
12 changes: 6 additions & 6 deletions Tests/SQLiteTests/QueryIntegrationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -230,28 +230,28 @@ class QueryIntegrationTests: SQLiteTestCase {
let result = Array(try db.prepare(users.select(email).order(Expression<Int>.random()).limit(1)))
XCTAssertEqual(1, result.count)
}

func test_with_recursive() {
let nodes = Table("nodes")
let id = Expression<Int64>("id")
let parent = Expression<Int64?>("parent")
let value = Expression<Int64>("value")

try! db.run(nodes.create { builder in
builder.column(id)
builder.column(parent)
builder.column(value)
})

try! db.run(nodes.insertMany([
[id <- 0, parent <- nil, value <- 2],
[id <- 1, parent <- 0, value <- 4],
[id <- 2, parent <- 0, value <- 9],
[id <- 3, parent <- 2, value <- 8],
[id <- 4, parent <- 2, value <- 7],
[id <- 5, parent <- 4, value <- 3],
[id <- 5, parent <- 4, value <- 3]
]))

// Compute the sum of the values of node 5 and its ancestors
let ancestors = Table("ancestors")
let sum = try! db.scalar(
Expand All @@ -268,7 +268,7 @@ class QueryIntegrationTests: SQLiteTestCase {
)
)
)

XCTAssertEqual(21, sum)
}
}
Expand Down
32 changes: 16 additions & 16 deletions Tests/SQLiteTests/QueryTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class QueryTests: XCTestCase {
func test_selectDistinct_withStar_compilesSelectClause() {
assertSQL("SELECT DISTINCT * FROM \"users\"", users.select(distinct: *))
}

func test_union_compilesUnionClause() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

split:

test_union_compiles_Union_Clause
test_union_compiles_Union_All_Clause

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I split the tests in cfa6010. I kept the names in the form test_union_compilesUnionAllClause for consistency with the existing tests. Let me know if I should instead do test_union_compiles_Union_All_Clause.

assertSQL("SELECT * FROM \"users\" UNION SELECT * FROM \"posts\"", users.union(posts))
assertSQL("SELECT * FROM \"users\" UNION ALL SELECT * FROM \"posts\"", users.union(all: true, posts))
Expand Down Expand Up @@ -224,41 +224,41 @@ class QueryTests: XCTestCase {
users.join(managers, on: managers[id] == users[managerId])
)
}

func test_with_compilesWithClause() {
let temp = Table("temp")

assertSQL("WITH \"temp\" AS (SELECT * FROM \"users\") SELECT * FROM \"temp\"",
temp.with(temp, as: users))
}

func test_with_recursive_compilesWithClause() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

compiles_with_clause
compiles_with_recursive_clause

let temp = Table("temp")

assertSQL("WITH RECURSIVE \"temp\" AS (SELECT * FROM \"users\") SELECT * FROM \"temp\"",
temp.with(temp, recursive: true, as: users))

assertSQL("WITH \"temp\" AS (SELECT * FROM \"users\") SELECT * FROM \"temp\"",
temp.with(temp, recursive: false, as: users))
}

func test_with_materialization_compilesWithClause() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with_materialized
with_not_materialized

let temp = Table("temp")

assertSQL("WITH \"temp\" AS MATERIALIZED (SELECT * FROM \"users\") SELECT * FROM \"temp\"",
temp.with(temp, materializationHint: .materialized, as: users))
temp.with(temp, hint: .materialized, as: users))

assertSQL("WITH \"temp\" AS NOT MATERIALIZED (SELECT * FROM \"users\") SELECT * FROM \"temp\"",
temp.with(temp, materializationHint: .notMaterialized, as: users))
temp.with(temp, hint: .notMaterialized, as: users))
}

func test_with_columns_compilesWithClause() {
let temp = Table("temp")

assertSQL("WITH \"temp\" (\"id\", \"email\") AS (SELECT * FROM \"users\") SELECT * FROM \"temp\"",
temp.with(temp, columns: [id, email], recursive: false, materializationHint: nil, as: users))
temp.with(temp, columns: [id, email], recursive: false, hint: nil, as: users))
}

func test_with_multiple_compilesWithClause() {
let temp = Table("temp")
let second = Table("second")
Expand All @@ -267,8 +267,8 @@ class QueryTests: XCTestCase {
let query = temp
.with(temp, recursive: true, as: users)
.with(second, recursive: true, as: posts)
.with(third, materializationHint: .materialized, as:categories)
.with(third, hint: .materialized, as: categories)

assertSQL(
"""
WITH RECURSIVE \"temp\" AS (SELECT * FROM \"users\"),
Expand Down