Skip to content

Commit ea521df

Browse files
committed
WIP 2
Signed-off-by: Stephen Celis <[email protected]>
1 parent d446df4 commit ea521df

File tree

3 files changed

+85
-28
lines changed

3 files changed

+85
-28
lines changed

Source/Typed/Query.swift

Lines changed: 79 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
public protocol QueryType : Expressible {
22

3-
static var identifier: String { get }
4-
53
var clauses: QueryClauses { get set }
64

75
init(_ name: String, database: String?)
86

97
}
108

11-
extension QueryType {
9+
public protocol SchemaType : QueryType {
10+
11+
static var identifier: String { get }
12+
13+
}
14+
15+
extension SchemaType {
1216

1317
/// Builds a copy of the query with the `SELECT` clause applied.
1418
///
@@ -22,8 +26,8 @@ extension QueryType {
2226
/// - Parameter all: A list of expressions to select.
2327
///
2428
/// - Returns: A query with the given `SELECT` clause applied.
25-
public func select(all: Expressible...) -> Self {
26-
return select(false, all)
29+
public func select(column: Expressible, _ more: Expressible...) -> Self {
30+
return select(false, [column] + more)
2731
}
2832

2933
/// Builds a copy of the query with the `SELECT DISTINCT` clause applied.
@@ -37,8 +41,8 @@ extension QueryType {
3741
/// - Parameter columns: A list of expressions to select.
3842
///
3943
/// - Returns: A query with the given `SELECT DISTINCT` clause applied.
40-
public func select(distinct columns: Expressible...) -> Self {
41-
return select(true, columns)
44+
public func select(distinct column: Expressible, _ more: Expressible...) -> Self {
45+
return select(true, [column] + more)
4246
}
4347

4448
/// Builds a copy of the query with the `SELECT` clause applied.
@@ -79,7 +83,7 @@ extension QueryType {
7983
/// users.select(*)
8084
/// // SELECT * FROM "users"
8185
///
82-
/// - Parameter all: A list of expressions to select.
86+
/// - Parameter star: A star literal.
8387
///
8488
/// - Returns: A query with the given `SELECT *` clause applied.
8589
public func select(star: Star) -> Self {
@@ -93,15 +97,61 @@ extension QueryType {
9397
/// users.select(distinct: *)
9498
/// // SELECT DISTINCT * FROM "users"
9599
///
96-
/// - Parameter all: A list of expressions to select.
100+
/// - Parameter star: A star literal.
97101
///
98102
/// - Returns: A query with the given `SELECT DISTINCT *` clause applied.
99103
public func select(distinct star: Star) -> Self {
100104
return select(distinct: star(nil, nil))
101105
}
102106

103-
private func select(distinct: Bool, _ columns: [Expressible]) -> Self {
104-
var query = self
107+
/// Builds a scalar copy of the query with the `SELECT` clause applied.
108+
///
109+
/// let users = Query("users")
110+
/// let id = Expression<Int64>("id")
111+
///
112+
/// users.select(id)
113+
/// // SELECT "id" FROM "users"
114+
///
115+
/// - Parameter all: A list of expressions to select.
116+
///
117+
/// - Returns: A query with the given `SELECT` clause applied.
118+
public func select<V : Value>(column: Expression<V>) -> ScalarQuery<V> {
119+
return select(false, [column])
120+
}
121+
public func select<V : Value>(column: Expression<V?>) -> ScalarQuery<V?> {
122+
return select(false, [column])
123+
}
124+
125+
/// Builds a scalar copy of the query with the `SELECT DISTINCT` clause
126+
/// applied.
127+
///
128+
/// let users = Query("users")
129+
/// let email = Expression<String>("email")
130+
///
131+
/// users.select(distinct: email)
132+
/// // SELECT DISTINCT "email" FROM "users"
133+
///
134+
/// - Parameter column: A list of expressions to select.
135+
///
136+
/// - Returns: A query with the given `SELECT DISTINCT` clause applied.
137+
public func select<V : Value>(distinct column: Expression<V>) -> ScalarQuery<V> {
138+
return select(true, [column])
139+
}
140+
public func select<V : Value>(distinct column: Expression<V?>) -> ScalarQuery<V?> {
141+
return select(true, [column])
142+
}
143+
144+
public var count: ScalarQuery<Int> {
145+
return select(SQLite.count(*))
146+
}
147+
148+
}
149+
150+
extension QueryType {
151+
152+
private func select<Q : QueryType>(distinct: Bool, _ columns: [Expressible]) -> Q {
153+
var query = Q.init(clauses.from.name, database: clauses.from.database)
154+
query.clauses = clauses
105155
query.clauses.select = (distinct, columns)
106156
return query
107157
}
@@ -565,16 +615,6 @@ extension QueryType {
565615
]).expression)
566616
}
567617

568-
// MARK: - Aggregate Functions
569-
570-
public var count: Select<Int> {
571-
return Select(select(SQLite.count(*)).expression)
572-
}
573-
574-
public func scalar<T : ExpressionType>(scalar: T) -> Select<T.UnderlyingType> {
575-
return Select(select(scalar).expression)
576-
}
577-
578618
// MARK: - Array
579619

580620
public var first: Select<Row?> {
@@ -683,7 +723,7 @@ extension QueryType {
683723

684724
/// Queries a collection of chainable helper functions and expressions to build
685725
/// executable SQL statements.
686-
public struct Table : QueryType {
726+
public struct Table : SchemaType {
687727

688728
public static let identifier = "TABLE"
689729

@@ -695,7 +735,7 @@ public struct Table : QueryType {
695735

696736
}
697737

698-
public struct View : QueryType {
738+
public struct View : SchemaType {
699739

700740
public static let identifier = "VIEW"
701741

@@ -707,7 +747,7 @@ public struct View : QueryType {
707747

708748
}
709749

710-
public struct VirtualTable : QueryType {
750+
public struct VirtualTable : SchemaType {
711751

712752
public static let identifier = "VIRTUAL TABLE"
713753

@@ -719,6 +759,16 @@ public struct VirtualTable : QueryType {
719759

720760
}
721761

762+
public struct ScalarQuery<V> : QueryType {
763+
764+
public var clauses: QueryClauses
765+
766+
public init(_ name: String, database: String? = nil) {
767+
clauses = QueryClauses(name, database: database)
768+
}
769+
770+
}
771+
722772
// TODO: decide: simplify the below with a boxed type instead
723773

724774
public struct Select<T> : ExpressionType {
@@ -775,6 +825,7 @@ extension Connection {
775825
public func prepare(query: QueryType) throws -> AnySequence<Row> {
776826
let expression = query.expression
777827
let statement = try prepare(expression.template, expression.bindings)
828+
print(expression.template, expression.bindings)
778829

779830
let columnNames: [String: Int] = try {
780831
var (columnNames, idx) = ([String: Int](), 0)
@@ -795,7 +846,9 @@ extension Connection {
795846
}
796847

797848
if column == "*" {
798-
let queries = [query.select(*)] as [QueryType] + query.clauses.join.map { $0.query }
849+
var select = query
850+
select.clauses.select = (false, [Expression<Void>(literal: "*") as Expressible])
851+
let queries = [select] + query.clauses.join.map { $0.query }
799852
if !namespace.isEmpty {
800853
for q in queries {
801854
if q.tableName().expression.template == namespace {
@@ -821,7 +874,7 @@ extension Connection {
821874
}
822875
}
823876

824-
public func scalar<V : Value>(query: Select<V>) throws -> V {
877+
public func scalar<V : Value>(query: ScalarQuery<V>) throws -> V {
825878
let expression = query.expression
826879
return value(try scalar(expression.template, expression.bindings))
827880
}

Source/Typed/Schema.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
// THE SOFTWARE.
2323
//
2424

25-
extension QueryType {
25+
extension SchemaType {
2626

2727
// MARK: - DROP TABLE / VIEW / VIRTUAL TABLE
2828

Tests/QueryTests.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ class QueryTests : XCTestCase {
202202
}
203203

204204
func test_scalar_returnsScalarExpression() {
205-
AssertSQL("SELECT count(\"intOptional\") FROM \"users\"", users.scalar(intOptional.count))
205+
AssertSQL("SELECT count(\"intOptional\") FROM \"users\"", users.select(intOptional.count))
206206
}
207207

208208
func test_first_returnsSelectExpressionWithLimit() {
@@ -261,6 +261,10 @@ class QueryIntegrationTests : SQLiteTestCase {
261261
// MARK: -
262262

263263
func test_select() {
264+
let stmt = try! db.prepare("SELECT * FROM \"users\"", [])
265+
for row in stmt {
266+
267+
}
264268
for row in try! db.prepare(users) {
265269
print(row)
266270
}

0 commit comments

Comments
 (0)