Files
UUVPN/iOS-SwiftUI-Code/GRDB.swift-6.29.3/Tests/GRDBTests/MutablePersistableRecordPersistenceConflictPolicyTests.swift

333 lines
11 KiB
Swift

import XCTest
import GRDB
private struct DefaultPolicy: MutablePersistableRecord {
var id: Int64?
static let databaseTableName = "records"
func encode(to container: inout PersistenceContainer) {
container["id"] = id
}
mutating func didInsert(_ inserted: InsertionSuccess) {
id = inserted.rowID
}
}
private struct MixedPolicy: MutablePersistableRecord {
var id: Int64?
static let databaseTableName = "records"
static let persistenceConflictPolicy = PersistenceConflictPolicy(insert: .fail, update: .rollback)
func encode(to container: inout PersistenceContainer) {
container["id"] = id
}
mutating func didInsert(_ inserted: InsertionSuccess) {
id = inserted.rowID
}
}
private struct ReplacePolicy: MutablePersistableRecord {
var id: Int64?
var email: String
static let databaseTableName = "records"
static let persistenceConflictPolicy = PersistenceConflictPolicy(insert: .replace, update: .replace)
func encode(to container: inout PersistenceContainer) {
container["id"] = id
container["email"] = email
}
mutating func didInsert(_ inserted: InsertionSuccess) {
id = inserted.rowID
}
}
private struct IgnorePolicy: MutablePersistableRecord {
var id: Int64?
static let databaseTableName = "records"
static let persistenceConflictPolicy = PersistenceConflictPolicy(insert: .ignore, update: .ignore)
func encode(to container: inout PersistenceContainer) {
container["id"] = id
}
mutating func didInsert(_ inserted: InsertionSuccess) {
id = inserted.rowID
}
}
private struct FailPolicy: MutablePersistableRecord {
var id: Int64?
static let databaseTableName = "records"
static let persistenceConflictPolicy = PersistenceConflictPolicy(insert: .fail, update: .fail)
func encode(to container: inout PersistenceContainer) {
container["id"] = id
}
mutating func didInsert(_ inserted: InsertionSuccess) {
id = inserted.rowID
}
}
private struct AbortPolicy: MutablePersistableRecord {
var id: Int64?
static let databaseTableName = "records"
static let persistenceConflictPolicy = PersistenceConflictPolicy(insert: .abort, update: .abort)
func encode(to container: inout PersistenceContainer) {
container["id"] = id
}
mutating func didInsert(_ inserted: InsertionSuccess) {
id = inserted.rowID
}
}
private struct RollbackPolicy: MutablePersistableRecord {
var id: Int64?
static let databaseTableName = "records"
static let persistenceConflictPolicy = PersistenceConflictPolicy(insert: .rollback, update: .rollback)
func encode(to container: inout PersistenceContainer) {
container["id"] = id
}
mutating func didInsert(_ inserted: InsertionSuccess) {
id = inserted.rowID
}
}
class MutablePersistableRecordPersistenceConflictPolicyTests: GRDBTestCase {
func testPolicyDefaultArguments() {
let policy = PersistenceConflictPolicy()
XCTAssertEqual(policy.conflictResolutionForInsert, .abort)
XCTAssertEqual(policy.conflictResolutionForUpdate, .abort)
}
func testDefaultPolicy() throws {
let dbQueue = try makeDatabaseQueue()
try dbQueue.inDatabase { db in
try db.create(table: "records") { t in
t.primaryKey("id", .integer)
}
// Insert
var record = DefaultPolicy(id: nil)
try record.insert(db)
XCTAssertTrue(self.lastSQLQuery!.hasPrefix("INSERT INTO \"records\""))
XCTAssertEqual(record.id, 1)
// Update
record = DefaultPolicy(id: 1)
try record.update(db)
XCTAssertTrue(self.lastSQLQuery!.hasPrefix("UPDATE \"records\""))
}
}
func testPolicyOverride() throws {
let dbQueue = try makeDatabaseQueue()
try dbQueue.inDatabase { db in
try db.create(table: "records") { t in
t.primaryKey("id", .integer)
}
// Insert
var record = DefaultPolicy(id: nil)
try record.insert(db, onConflict: .ignore)
XCTAssertTrue(self.lastSQLQuery!.hasPrefix("INSERT OR IGNORE INTO \"records\""))
// Update
record = DefaultPolicy(id: 1)
try record.update(db, onConflict: .ignore)
XCTAssertTrue(self.lastSQLQuery!.hasPrefix("UPDATE OR IGNORE \"records\""))
}
}
func testMixedPolicy() throws {
let dbQueue = try makeDatabaseQueue()
try dbQueue.inDatabase { db in
try db.create(table: "records") { t in
t.primaryKey("id", .integer)
}
// Insert
var record = MixedPolicy(id: nil)
try record.insert(db)
XCTAssertTrue(self.lastSQLQuery!.hasPrefix("INSERT OR FAIL INTO \"records\""))
XCTAssertEqual(record.id, 1)
// Update
record = MixedPolicy(id: 1)
try record.update(db)
XCTAssertTrue(self.lastSQLQuery!.hasPrefix("UPDATE OR ROLLBACK \"records\""))
}
}
func testReplacePolicy() throws {
class Observer : TransactionObserver {
var transactionEvents: [DatabaseEvent] = []
var events: [DatabaseEvent] = []
func observes(eventsOfKind eventKind: DatabaseEventKind) -> Bool { true }
func databaseDidChange(with event: DatabaseEvent) {
transactionEvents.append(event.copy())
}
func databaseDidCommit(_ db: Database) {
events = transactionEvents
transactionEvents = []
}
func databaseDidRollback(_ db: Database) {
events = []
transactionEvents = []
}
}
let dbQueue = try makeDatabaseQueue()
let observer = Observer()
dbQueue.add(transactionObserver: observer)
try dbQueue.writeWithoutTransaction { db in
try db.create(table: "records") { t in
t.primaryKey("id", .integer)
t.column("email", .text).unique()
}
// Insert
var record = ReplacePolicy(id: nil, email: "arthur@example.com")
try record.insert(db)
XCTAssertTrue(self.lastSQLQuery!.hasPrefix("INSERT OR REPLACE INTO \"records\""))
XCTAssertEqual(record.id, 1)
XCTAssertEqual(observer.events.count, 1)
XCTAssertEqual(observer.events[0].kind, .insert)
XCTAssertEqual(observer.events[0].rowID, 1)
// Insert
record = ReplacePolicy(id: nil, email: "arthur@example.com")
try record.insert(db)
XCTAssertTrue(self.lastSQLQuery!.hasPrefix("INSERT OR REPLACE INTO \"records\""))
XCTAssertEqual(record.id, 2)
XCTAssertTrue(try ReplacePolicy.fetchCount(db) == 1)
XCTAssertEqual(observer.events.count, 1)
XCTAssertEqual(observer.events[0].kind, .insert)
XCTAssertEqual(observer.events[0].rowID, 2)
// Update
record = ReplacePolicy(id: 2, email: "arthur@example.com")
try record.update(db)
XCTAssertTrue(self.lastSQLQuery!.hasPrefix("UPDATE OR REPLACE \"records\""))
XCTAssertEqual(observer.events.count, 1)
XCTAssertEqual(observer.events[0].kind, .update)
XCTAssertEqual(observer.events[0].rowID, 2)
// Update which replaces
record = ReplacePolicy(id: 3, email: "barbara@example.com")
try record.insert(db)
XCTAssertTrue(try ReplacePolicy.fetchCount(db) == 2)
XCTAssertEqual(observer.events.count, 1)
XCTAssertEqual(observer.events[0].kind, .insert)
XCTAssertEqual(observer.events[0].rowID, 3)
record.email = "arthur@example.com"
try record.update(db)
XCTAssertTrue(try ReplacePolicy.fetchCount(db) == 1)
XCTAssertEqual(try Int64.fetchOne(db, sql: "SELECT id FROM records")!, 3)
XCTAssertEqual(observer.events.count, 1)
XCTAssertEqual(observer.events[0].kind, .update)
XCTAssertEqual(observer.events[0].rowID, 3)
}
}
func testIgnorePolicy() throws {
let dbQueue = try makeDatabaseQueue()
try dbQueue.inDatabase { db in
try db.create(table: "records") { t in
t.primaryKey("id", .integer)
}
// Insert
var record = IgnorePolicy(id: nil)
try record.insert(db)
XCTAssertTrue(self.lastSQLQuery!.hasPrefix("INSERT OR IGNORE INTO \"records\""))
XCTAssertEqual(record.id, 1)
// Update
record = IgnorePolicy(id: 1)
try record.update(db)
XCTAssertTrue(self.lastSQLQuery!.hasPrefix("UPDATE OR IGNORE \"records\""))
}
}
func testFailPolicy() throws {
let dbQueue = try makeDatabaseQueue()
try dbQueue.inDatabase { db in
try db.create(table: "records") { t in
t.primaryKey("id", .integer)
}
// Insert
var record = FailPolicy(id: nil)
try record.insert(db)
XCTAssertTrue(self.lastSQLQuery!.hasPrefix("INSERT OR FAIL INTO \"records\""))
XCTAssertEqual(record.id, 1)
// Update
record = FailPolicy(id: 1)
try record.update(db)
XCTAssertTrue(self.lastSQLQuery!.hasPrefix("UPDATE OR FAIL \"records\""))
}
}
func testAbortPolicy() throws {
let dbQueue = try makeDatabaseQueue()
try dbQueue.inDatabase { db in
try db.create(table: "records") { t in
t.primaryKey("id", .integer)
}
// Insert
var record = AbortPolicy(id: nil)
try record.insert(db)
XCTAssertTrue(self.lastSQLQuery!.hasPrefix("INSERT INTO \"records\""))
XCTAssertEqual(record.id, 1)
// Update
record = AbortPolicy(id: 1)
try record.update(db)
XCTAssertTrue(self.lastSQLQuery!.hasPrefix("UPDATE \"records\""))
}
}
func testRollbackPolicy() throws {
let dbQueue = try makeDatabaseQueue()
try dbQueue.inDatabase { db in
try db.create(table: "records") { t in
t.primaryKey("id", .integer)
}
// Insert
var record = RollbackPolicy(id: nil)
try record.insert(db)
XCTAssertTrue(self.lastSQLQuery!.hasPrefix("INSERT OR ROLLBACK INTO \"records\""))
XCTAssertEqual(record.id, 1)
// Update
record = RollbackPolicy(id: 1)
try record.update(db)
XCTAssertTrue(self.lastSQLQuery!.hasPrefix("UPDATE OR ROLLBACK \"records\""))
}
}
}