Skip to content

Commit

Permalink
Kitura/Swift-Kuery#13 Implemented query fetcher and updated the tests
Browse files Browse the repository at this point in the history
  • Loading branch information
irar2 committed Nov 24, 2016
1 parent c821328 commit 76ed790
Show file tree
Hide file tree
Showing 24 changed files with 954 additions and 294 deletions.
8 changes: 4 additions & 4 deletions Sources/SwiftKueryPostgreSQL/PostgreSQLConnection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -172,16 +172,16 @@ public class PostgreSQLConnection : Connection {
onCompletion(.successNoData)
}
else if status == PGRES_TUPLES_OK {
let (titles, rows) = PostgreSQLConnection.getRows(queryResult: result)
onCompletion(.rows(titles: titles, rows: rows))
let resultFetcher = PostgreSQLConnection.createReslutFetcher(queryResult: result)
onCompletion(.resultSet(ResultSet(resultFetcher)))
}
else {
onCompletion(.error(QueryError.databaseError("Query execution error:\n" + String(validatingUTF8: PQresultErrorMessage(result))! + "For query: " + query)))
}
PQclear(result)
}

private static func getRows(queryResult: OpaquePointer) -> ([String], [[Any?]]) {
private static func createReslutFetcher(queryResult: OpaquePointer) -> PostgreSQLResultFetcher {

This comment has been minimized.

Copy link
@ianpartridge

ianpartridge Nov 28, 2016

Contributor

Should be createResultFetcher

This comment has been minimized.

Copy link
@irar2

irar2 Nov 29, 2016

Author Contributor

Thanks! Fixed.

var result = [[Any?]]()
let rows = PQntuples(queryResult)
let columns = PQnfields(queryResult)
Expand All @@ -205,7 +205,7 @@ public class PostgreSQLConnection : Connection {
result.append(row)
}

return (columnNames, result)
return PostgreSQLResultFetcher(titles: columnNames, rows: result)
}

private static func convert(_ queryResult: OpaquePointer, row: Int32, column: Int32) -> Any {
Expand Down
66 changes: 66 additions & 0 deletions Sources/SwiftKueryPostgreSQL/PostgreSQLResultFetcher.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
Copyright IBM Corporation 2016

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import SwiftKuery

// MARK: PostgreSQLResultFetcher

/// An implementation of query result fetcher.
public class PostgreSQLResultFetcher : ResultFetcher {

private let titles: [String]
private let rows: [[Any?]]
private var index = -1

init(titles: [String], rows: [[Any?]]) {
self.titles = titles
self.rows = rows
}

/// Fetch the next row of the query result. This function is blocking.
///
/// - Returns: An array of values of type Any? representing the next row from the query result.
public func fetchNext() -> [Any?]? {
index += 1
if index < rows.count {
return (rows[index])
}
else {
return nil
}
}

/// Fetch the next row of the query result. This function is non-blocking.
///
/// - Parameter callback: A callback to call when the next row of the query result is ready.
public func fetchNext(callback: ([Any?]?) ->()) {
index += 1
if index < rows.count {
callback(rows[index])
}
else {
callback(nil)
}
}

/// Fetch the titles of the query result. This function is blocking.
///
/// - Returns: An array of column titles of type String.
public func fetchTitles() -> [String] {
return titles
}

}
57 changes: 36 additions & 21 deletions Tests/SwiftKueryPostgreSQLTests/CommonUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,41 +51,41 @@ func read(fileName: String) -> String {
}
}

func executeQuery(query: Query, connection: Connection, callback: @escaping (QueryResult)->()) {
func executeQuery(query: Query, connection: Connection, callback: @escaping (QueryResult, [[Any?]]?)->()) {
do {
try print("=======\(connection.descriptionOf(query: query))=======")
}
catch {}
connection.execute(query: query) { result in
printResult(result)
callback(result)
let rows = printResultAndGetRowsAsArray(result)
callback(result, rows)
}
}

func executeQueryWithParameters(query: Query, connection: Connection, parameters: Any..., callback: @escaping (QueryResult)->()) {
func executeQueryWithParameters(query: Query, connection: Connection, parameters: Any..., callback: @escaping (QueryResult, [[Any?]]?)->()) {
do {
try print("=======\(connection.descriptionOf(query: query))=======")
}
catch {}
connection.execute(query: query, parameters: parameters) { result in
printResult(result)
callback(result)
let rows = printResultAndGetRowsAsArray(result)
callback(result, rows)
}
}

func executeRawQueryWithParameters(_ raw: String, connection: Connection, parameters: Any..., callback: @escaping (QueryResult)->()) {
func executeRawQueryWithParameters(_ raw: String, connection: Connection, parameters: Any..., callback: @escaping (QueryResult, [[Any?]]?)->()) {
print("=======\(raw)=======")
connection.execute(raw, parameters: parameters) { result in
printResult(result)
callback(result)
let rows = printResultAndGetRowsAsArray(result)
callback(result, rows)
}
}

func executeRawQuery(_ raw: String, connection: Connection, callback: @escaping (QueryResult)->()) {
func executeRawQuery(_ raw: String, connection: Connection, callback: @escaping (QueryResult, [[Any?]]?)->()) {
print("=======\(raw)=======")
connection.execute(raw) { result in
printResult(result)
callback(result)
let rows = printResultAndGetRowsAsArray(result)
callback(result, rows)
}
}

Expand All @@ -95,21 +95,26 @@ func cleanUp(table: String, connection: Connection, callback: @escaping (QueryRe
}
}

func printResult(_ result: QueryResult) {
if let (titles, rows) = result.asRows {
private func printResultAndGetRowsAsArray(_ result: QueryResult) -> [[Any?]]? {
var rows: [[Any?]]? = nil
if let resultSet = result.asResultSet {
let titles = resultSet.titles
for title in titles {
print(title.padding(toLength: 11, withPad: " ", startingAt: 0), terminator: "")
}
print()
for row in rows {
for value in row {
var valueToPrint = ""
if value != nil {
valueToPrint = value as! String
rows = rowsAsArray(resultSet)
if let rows = rows {
for row in rows {
for value in row {
var valueToPrint = ""
if value != nil {
valueToPrint = value as! String
}
print(valueToPrint.padding(toLength: 11, withPad: " ", startingAt: 0), terminator: "")
}
print(valueToPrint.padding(toLength: 11, withPad: " ", startingAt: 0), terminator: "")
print()
}
print()
}
}
else if let value = result.asValue {
Expand All @@ -121,6 +126,15 @@ func printResult(_ result: QueryResult) {
else if let queryError = result.asError {
print("Error in query: ", queryError)
}
return rows
}

func getNumberOfRows(_ result: ResultSet) -> Int {
return result.rows.map{ $0 as [Any?] }.count
}

func rowsAsArray(_ result: ResultSet) -> [[Any?]] {
return result.rows.map{ $0 as [Any?] }
}

func createConnection() -> PostgreSQLConnection {
Expand All @@ -132,5 +146,6 @@ func createConnection() -> PostgreSQLConnection {
return PostgreSQLConnection(host: host, port: port, options: [.userName(username), .password(password)])
}


// Dummy class for test framework
class CommonUtils { }
39 changes: 20 additions & 19 deletions Tests/SwiftKueryPostgreSQLTests/TestAlias.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,41 +51,42 @@ class TestAlias: XCTestCase {

cleanUp(table: t.tableName, connection: connection) { result in

executeRawQuery("CREATE TABLE " + t.tableName + " (a varchar(40), b integer)", connection: connection) { result in
executeRawQuery("CREATE TABLE " + t.tableName + " (a varchar(40), b integer)", connection: connection) { result, rows in
XCTAssertEqual(result.success, true, "CREATE TABLE failed")
XCTAssertNil(result.asError, "Error in CREATE TABLE: \(result.asError!)")

let i1 = Insert(into: t, rows: [["apple", 10], ["apricot", 3], ["banana", 17], ["apple", 17], ["banana", -7], ["banana", 27]])
executeQuery(query: i1, connection: connection) { result in
executeQuery(query: i1, connection: connection) { result, rows in
XCTAssertEqual(result.success, true, "INSERT failed")
XCTAssertNil(result.asError, "Error in INSERT: \(result.asError!)")

let s1 = Select(t.a.as("\"fruit name\""), t.b.as("number"), from: t)
executeQuery(query: s1, connection: connection) { result in
executeQuery(query: s1, connection: connection) { result, rows in
XCTAssertEqual(result.success, true, "SELECT failed")
XCTAssertNotNil(result.asRows, "SELECT returned no rows")
let (titles, rows) = result.asRows!
XCTAssertEqual(rows.count, 6, "SELECT returned wrong number of rows: \(rows.count) instead of 6")
XCTAssertEqual(titles[0], "fruit name", "Wrong column name: \(titles[0]) instead of 'fruit name'")
XCTAssertEqual(titles[1], "number", "Wrong column name: \(titles[1]) instead of 'number'")
XCTAssertNotNil(result.asResultSet, "SELECT returned no rows")
XCTAssertNotNil(rows, "SELECT returned no rows")
let resultSet = result.asResultSet!
XCTAssertEqual(rows!.count, 6, "SELECT returned wrong number of rows: \(rows!.count) instead of 6")
XCTAssertEqual(resultSet.titles[1], "number", "Wrong column name: \(resultSet.titles[1]) instead of 'number'")
XCTAssertEqual(resultSet.titles[0], "fruit name", "Wrong column name: \(resultSet.titles[0]) instead of 'fruit name'")

let s2 = Select(from: t.as("new"))
executeQuery(query: s2, connection: connection) { result in
executeQuery(query: s2, connection: connection) { result, rows in
XCTAssertEqual(result.success, true, "SELECT failed")
XCTAssertNotNil(result.asRows, "SELECT returned no rows")
let (titles, rows) = result.asRows!
XCTAssertEqual(rows.count, 6, "SELECT returned wrong number of rows: \(rows.count) instead of 6")
XCTAssertEqual(titles[0], "a", "Wrong column name: \(titles[0]) instead of 'a'")
XCTAssertEqual(titles[1], "b", "Wrong column name: \(titles[1]) instead of 'b'")
XCTAssertNotNil(rows, "SELECT returned no rows")
let resultSet = result.asResultSet!
XCTAssertEqual(rows!.count, 6, "SELECT returned wrong number of rows: \(rows!.count) instead of 6")
XCTAssertEqual(resultSet.titles[0], "a", "Wrong column name: \(resultSet.titles[0]) instead of 'a'")
XCTAssertEqual(resultSet.titles[1], "b", "Wrong column name: \(resultSet.titles[1]) instead of 'b'")

let t2 = t.as("\"t 2\"")
let s3 = Select(t2.a, from: t2)
executeQuery(query: s3, connection: connection) { result in
executeQuery(query: s3, connection: connection) { result, rows in
XCTAssertEqual(result.success, true, "SELECT failed")
XCTAssertNotNil(result.asRows, "SELECT returned no rows")
let (titles, rows) = result.asRows!
XCTAssertEqual(rows.count, 6, "SELECT returned wrong number of rows: \(rows.count) instead of 6")
XCTAssertEqual(titles[0], "a", "Wrong column name: \(titles[0]) instead of 'a'")
XCTAssertNotNil(rows, "SELECT returned no rows")
let resultSet = result.asResultSet!
XCTAssertEqual(rows!.count, 6, "SELECT returned wrong number of rows: \(rows!.count) instead of 6")
XCTAssertEqual(resultSet.titles[0], "a", "Wrong column name: \(resultSet.titles[0]) instead of 'a'")
}
}
}
Expand Down
Loading

0 comments on commit 76ed790

Please sign in to comment.