Skip to content

Commit

Permalink
Fix for stephencelis#235 as discussed in stephencelis#383
Browse files Browse the repository at this point in the history
  • Loading branch information
dta256 committed Mar 31, 2016
1 parent b43a31f commit 801a830
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 1 deletion.
3 changes: 3 additions & 0 deletions SQLite/Core/Connection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,7 @@ public enum Result : ErrorType {

private static let successCodes: Set = [SQLITE_OK, SQLITE_ROW, SQLITE_DONE]

case IgnoredError
case Error(message: String, code: Int32, statement: Statement?)

init?(errorCode: Int32, connection: Connection, statement: Statement? = nil) {
Expand All @@ -679,6 +680,8 @@ extension Result : CustomStringConvertible {
guard let statement = statement else { return message }

return "\(message) (\(statement))"
case .IgnoredError:
return "INSERT OR IGNORE has failed, error code has been ignored"
}
}

Expand Down
62 changes: 61 additions & 1 deletion SQLite/Typed/Query.swift
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,29 @@ extension QueryType {
return Insert(" ".join(clauses.flatMap { $0 }).expression)
}

public func insertOrIgnore(values: Setter...) -> InsertOrIgnore {
return insertOrIgnore(values)
}

public func insertOrIgnore(values: [Setter]) -> InsertOrIgnore {
let insert = values.reduce((columns: [Expressible](), values: [Expressible]())) { insert, setter in
(insert.columns + [setter.column], insert.values + [setter.value])
}

let clauses: [Expressible?] = [
Expression<Void>(literal: "INSERT"),
Expression<Void>(literal: "OR \(OnConflict.Ignore.rawValue)"),
Expression<Void>(literal: "INTO"),
tableName(),
"".wrap(insert.columns) as Expression<Void>,
Expression<Void>(literal: "VALUES"),
"".wrap(insert.values) as Expression<Void>,
whereClause
]

return InsertOrIgnore(" ".join(clauses.flatMap { $0 }).expression)
}

/// Runs an `INSERT` statement against the query with `DEFAULT VALUES`.
public func insert() -> Insert {
return Insert(" ".join([
Expand Down Expand Up @@ -847,6 +870,18 @@ public struct Insert : ExpressionType {

}

public struct InsertOrIgnore : ExpressionType {

public var template: String
public var bindings: [Binding?]

public init(_ template: String, _ bindings: [Binding?]) {
self.template = template
self.bindings = bindings
}

}

public struct Update : ExpressionType {

public var template: String
Expand Down Expand Up @@ -965,7 +1000,32 @@ extension Connection {
let expression = query.expression
return try sync {
try self.run(expression.template, expression.bindings)
return self.lastInsertRowid!
if let rowid = self.lastInsertRowid
{
return rowid
}
else
{
throw Result.IgnoredError
}
}
}

/// Runs an `INSERT OR IGNORE` query.
///
/// - SeeAlso: `QueryType.insert(value:_:)`
/// - SeeAlso: `QueryType.insert(values:)`
/// - SeeAlso: `QueryType.insert(or:_:)`
/// - SeeAlso: `QueryType.insert()`
///
/// - Parameter query: An insert query.
///
/// - Returns: The insert’s rowid if any, nil if the insert has failed.
public func run(query: InsertOrIgnore) throws -> Int64? {
let expression = query.expression
return try sync {
try self.run(expression.template, expression.bindings)
return self.lastInsertRowid
}
}

Expand Down

0 comments on commit 801a830

Please sign in to comment.