add swiftUI code
This commit is contained in:
@@ -0,0 +1,635 @@
|
||||
import XCTest
|
||||
import GRDB
|
||||
|
||||
class TruncateOptimizationTests: GRDBTestCase {
|
||||
// https://www.sqlite.org/c3ref/update_hook.html
|
||||
//
|
||||
// > In the current implementation, the update hook is not invoked [...]
|
||||
// > when rows are deleted using the truncate optimization.
|
||||
//
|
||||
// https://www.sqlite.org/lang_delete.html#truncateopt
|
||||
//
|
||||
// > When the WHERE is omitted from a DELETE statement and the table
|
||||
// > being deleted has no triggers, SQLite uses an optimization to erase
|
||||
// > the entire table content without having to visit each row of the
|
||||
// > table individually.
|
||||
//
|
||||
// We will thus test that the truncate optimization does not prevent
|
||||
// transaction observers from observing individual deletions.
|
||||
//
|
||||
// But that's not enough: preventing the truncate optimization requires GRDB
|
||||
// to fiddle with sqlite3_set_authorizer. When badly done, this can prevent
|
||||
// DROP TABLE statements from dropping tables. SQLite3 authorizers are
|
||||
// invoked during both compilation and execution of SQL statements. We will
|
||||
// thus test that DROP TABLE statements perform as expected when compilation
|
||||
// and execution are grouped, and when they are performed separately.
|
||||
|
||||
class DeletionObserver : TransactionObserver {
|
||||
private var notify: ([String: Int]) -> Void
|
||||
private var deletionEvents: [String: Int] = [:]
|
||||
|
||||
// Notifies table names with the number of deleted rows
|
||||
init(_ notify: @escaping ([String: Int]) -> Void) {
|
||||
self.notify = notify
|
||||
}
|
||||
|
||||
func observes(eventsOfKind eventKind: DatabaseEventKind) -> Bool { true }
|
||||
|
||||
func databaseDidChange(with event: DatabaseEvent) {
|
||||
if case .delete = event.kind {
|
||||
deletionEvents[event.tableName, default: 0] += 1
|
||||
}
|
||||
}
|
||||
|
||||
func databaseDidCommit(_ db: Database) {
|
||||
if !deletionEvents.isEmpty {
|
||||
notify(deletionEvents)
|
||||
}
|
||||
deletionEvents = [:]
|
||||
}
|
||||
|
||||
func databaseDidRollback(_ db: Database) {
|
||||
deletionEvents = [:]
|
||||
}
|
||||
}
|
||||
|
||||
class UniversalObserver : TransactionObserver {
|
||||
func observes(eventsOfKind eventKind: DatabaseEventKind) -> Bool { true }
|
||||
func databaseDidChange(with event: DatabaseEvent) { }
|
||||
func databaseDidCommit(_ db: Database) { }
|
||||
func databaseDidRollback(_ db: Database) { }
|
||||
}
|
||||
|
||||
func testExecuteDelete() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
|
||||
var deletionEvents: [[String: Int]] = []
|
||||
let observer = DeletionObserver { deletionEvents.append($0) }
|
||||
dbQueue.add(transactionObserver: observer, extent: .databaseLifetime)
|
||||
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
deletionEvents = []
|
||||
try db.execute(sql: "DELETE FROM t")
|
||||
XCTAssertEqual(deletionEvents.count, 1)
|
||||
XCTAssertEqual(deletionEvents[0], ["t": 2])
|
||||
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
deletionEvents = []
|
||||
try db.execute(sql: "DELETE FROM t")
|
||||
XCTAssertEqual(deletionEvents.count, 1)
|
||||
XCTAssertEqual(deletionEvents[0], ["t": 1])
|
||||
}
|
||||
}
|
||||
|
||||
func testExecuteDeleteCaseSensitivity() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
|
||||
class DeletionObserver : TransactionObserver {
|
||||
var deletionCount = 0
|
||||
|
||||
func observes(eventsOfKind eventKind: DatabaseEventKind) -> Bool {
|
||||
if case .delete(tableName: "pLaYeR") = eventKind {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func databaseDidChange(with event: DatabaseEvent) {
|
||||
if case .delete = event.kind {
|
||||
deletionCount += 1
|
||||
}
|
||||
}
|
||||
|
||||
func databaseDidCommit(_ db: Database) { }
|
||||
func databaseDidRollback(_ db: Database) { }
|
||||
}
|
||||
|
||||
let observer = DeletionObserver()
|
||||
dbQueue.add(transactionObserver: observer, extent: .databaseLifetime)
|
||||
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
observer.deletionCount = 0
|
||||
try db.execute(sql: "CREATE TABLE pLaYeR(a)")
|
||||
try db.execute(sql: "INSERT INTO pLaYeR VALUES (NULL)")
|
||||
try db.execute(sql: "INSERT INTO pLaYeR VALUES (NULL)")
|
||||
try db.execute(sql: "DELETE FROM pLaYeR")
|
||||
XCTAssertEqual(observer.deletionCount, 2)
|
||||
|
||||
observer.deletionCount = 0
|
||||
try db.execute(sql: "INSERT INTO pLaYeR VALUES (NULL)")
|
||||
try db.execute(sql: "DELETE FROM PLAYER")
|
||||
XCTAssertEqual(observer.deletionCount, 1)
|
||||
|
||||
observer.deletionCount = 0
|
||||
try db.execute(sql: "INSERT INTO pLaYeR VALUES (NULL)")
|
||||
try db.execute(sql: "DELETE FROM player")
|
||||
XCTAssertEqual(observer.deletionCount, 1)
|
||||
}
|
||||
}
|
||||
|
||||
func testExecuteDeleteWithPreparedStatement() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
|
||||
var deletionEvents: [[String: Int]] = []
|
||||
let observer = DeletionObserver { deletionEvents.append($0) }
|
||||
dbQueue.add(transactionObserver: observer, extent: .databaseLifetime)
|
||||
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
let deleteStatement = try db.makeStatement(sql: "DELETE FROM t")
|
||||
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
deletionEvents = []
|
||||
try deleteStatement.execute()
|
||||
XCTAssertEqual(deletionEvents.count, 1)
|
||||
XCTAssertEqual(deletionEvents[0], ["t": 2])
|
||||
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
deletionEvents = []
|
||||
try deleteStatement.execute()
|
||||
XCTAssertEqual(deletionEvents.count, 1)
|
||||
XCTAssertEqual(deletionEvents[0], ["t": 1])
|
||||
}
|
||||
}
|
||||
|
||||
func testExecuteDeleteWithCachedPreparedStatement() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
|
||||
var deletionEvents: [[String: Int]] = []
|
||||
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.cachedStatement(sql: "DELETE FROM t").execute()
|
||||
|
||||
// Start observing after statement has been cached: it does not
|
||||
// prevent the truncate optimization.
|
||||
let observer = DeletionObserver { deletionEvents.append($0) }
|
||||
db.add(transactionObserver: observer, extent: .databaseLifetime)
|
||||
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
deletionEvents = []
|
||||
// This must be a recompiled statement, so that the truncate
|
||||
// optimization is prevented.
|
||||
try db.cachedStatement(sql: "DELETE FROM t").execute()
|
||||
XCTAssertEqual(deletionEvents.count, 1)
|
||||
XCTAssertEqual(deletionEvents[0], ["t": 2])
|
||||
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
deletionEvents = []
|
||||
try db.cachedStatement(sql: "DELETE FROM t").execute()
|
||||
XCTAssertEqual(deletionEvents.count, 1)
|
||||
XCTAssertEqual(deletionEvents[0], ["t": 1])
|
||||
}
|
||||
}
|
||||
|
||||
func testDropTable() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try XCTAssertTrue(db.tableExists("t"))
|
||||
try db.execute(sql: "DROP TABLE t") // compile + execute
|
||||
try XCTAssertFalse(db.tableExists("t"))
|
||||
}
|
||||
}
|
||||
|
||||
func testObservedDropTable() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
dbQueue.add(transactionObserver: UniversalObserver(), extent: .databaseLifetime)
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try XCTAssertTrue(db.tableExists("t"))
|
||||
try db.execute(sql: "DROP TABLE t") // compile + execute
|
||||
try XCTAssertFalse(db.tableExists("t"))
|
||||
}
|
||||
}
|
||||
|
||||
func testDropTableWithPreparedStatement() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try XCTAssertTrue(db.tableExists("t"))
|
||||
let dropStatement = try db.makeStatement(sql: "DROP TABLE t") // compile...
|
||||
try dropStatement.execute() // ... then execute
|
||||
try XCTAssertFalse(db.tableExists("t"))
|
||||
}
|
||||
}
|
||||
|
||||
func testObservedDropTableWithPreparedStatement() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
dbQueue.add(transactionObserver: UniversalObserver(), extent: .databaseLifetime)
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try XCTAssertTrue(db.tableExists("t"))
|
||||
let dropStatement = try db.makeStatement(sql: "DROP TABLE t") // compile...
|
||||
try dropStatement.execute() // ... then execute
|
||||
try XCTAssertFalse(db.tableExists("t"))
|
||||
}
|
||||
}
|
||||
|
||||
func testDropTemporaryTable() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TEMPORARY TABLE t(a)")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try XCTAssertTrue(db.tableExists("t"))
|
||||
try db.execute(sql: "DROP TABLE t") // compile + execute
|
||||
try XCTAssertFalse(db.tableExists("t"))
|
||||
}
|
||||
}
|
||||
|
||||
func testObservedDropTemporaryTable() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
dbQueue.add(transactionObserver: UniversalObserver(), extent: .databaseLifetime)
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TEMPORARY TABLE t(a)")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try XCTAssertTrue(db.tableExists("t"))
|
||||
try db.execute(sql: "DROP TABLE t") // compile + execute
|
||||
try XCTAssertFalse(db.tableExists("t"))
|
||||
}
|
||||
}
|
||||
|
||||
func testDropTemporaryTableWithPreparedStatement() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TEMPORARY TABLE t(a)")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try XCTAssertTrue(db.tableExists("t"))
|
||||
let dropStatement = try db.makeStatement(sql: "DROP TABLE t") // compile...
|
||||
try dropStatement.execute() // ... then execute
|
||||
try XCTAssertFalse(db.tableExists("t"))
|
||||
}
|
||||
}
|
||||
|
||||
func testObservedDropTemporaryTableWithPreparedStatement() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
dbQueue.add(transactionObserver: UniversalObserver(), extent: .databaseLifetime)
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TEMPORARY TABLE t(a)")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try XCTAssertTrue(db.tableExists("t"))
|
||||
let dropStatement = try db.makeStatement(sql: "DROP TABLE t") // compile...
|
||||
try dropStatement.execute() // ... then execute
|
||||
try XCTAssertFalse(db.tableExists("t"))
|
||||
}
|
||||
}
|
||||
|
||||
func testDropVirtualTable() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE VIRTUAL TABLE t USING fts3(a)")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try XCTAssertTrue(db.tableExists("t"))
|
||||
try db.execute(sql: "DROP TABLE t") // compile + execute
|
||||
try XCTAssertFalse(db.tableExists("t"))
|
||||
}
|
||||
}
|
||||
|
||||
func testObservedDropVirtualTable() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
dbQueue.add(transactionObserver: UniversalObserver(), extent: .databaseLifetime)
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE VIRTUAL TABLE t USING fts3(a)")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try XCTAssertTrue(db.tableExists("t"))
|
||||
try db.execute(sql: "DROP TABLE t") // compile + execute
|
||||
try XCTAssertFalse(db.tableExists("t"))
|
||||
}
|
||||
}
|
||||
|
||||
func testDropVirtualTableWithPreparedStatement() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE VIRTUAL TABLE t USING fts3(a)")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try XCTAssertTrue(db.tableExists("t"))
|
||||
let dropStatement = try db.makeStatement(sql: "DROP TABLE t") // compile...
|
||||
try dropStatement.execute() // ... then execute
|
||||
try XCTAssertFalse(db.tableExists("t"))
|
||||
}
|
||||
}
|
||||
|
||||
func testObservedDropVirtualTableWithPreparedStatement() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
dbQueue.add(transactionObserver: UniversalObserver(), extent: .databaseLifetime)
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE VIRTUAL TABLE t USING fts3(a)")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try XCTAssertTrue(db.tableExists("t"))
|
||||
let dropStatement = try db.makeStatement(sql: "DROP TABLE t") // compile...
|
||||
try dropStatement.execute() // ... then execute
|
||||
try XCTAssertFalse(db.tableExists("t"))
|
||||
}
|
||||
}
|
||||
|
||||
func testDropView() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "CREATE VIEW v AS SELECT * FROM t")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try XCTAssertTrue(db.viewExists("v"))
|
||||
try db.execute(sql: "DROP VIEW v") // compile + execute
|
||||
try XCTAssertFalse(db.viewExists("v"))
|
||||
}
|
||||
}
|
||||
|
||||
func testObservedDropView() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
dbQueue.add(transactionObserver: UniversalObserver(), extent: .databaseLifetime)
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "CREATE VIEW v AS SELECT * FROM t")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try XCTAssertTrue(db.viewExists("v"))
|
||||
try db.execute(sql: "DROP VIEW v") // compile + execute
|
||||
try XCTAssertFalse(db.viewExists("v"))
|
||||
}
|
||||
}
|
||||
|
||||
func testDropViewWithPreparedStatement() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "CREATE VIEW v AS SELECT * FROM t")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try XCTAssertTrue(db.viewExists("v"))
|
||||
let dropStatement = try db.makeStatement(sql: "DROP VIEW v") // compile...
|
||||
try dropStatement.execute() // ... then execute
|
||||
try XCTAssertFalse(db.viewExists("v"))
|
||||
}
|
||||
}
|
||||
|
||||
func testObservedDropViewWithPreparedStatement() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
dbQueue.add(transactionObserver: UniversalObserver(), extent: .databaseLifetime)
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "CREATE VIEW v AS SELECT * FROM t")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try XCTAssertTrue(db.viewExists("v"))
|
||||
let dropStatement = try db.makeStatement(sql: "DROP VIEW v") // compile...
|
||||
try dropStatement.execute() // ... then execute
|
||||
try XCTAssertFalse(db.viewExists("v"))
|
||||
}
|
||||
}
|
||||
|
||||
func testDropTemporaryView() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "CREATE TEMPORARY VIEW v AS SELECT * FROM t")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try XCTAssertTrue(db.viewExists("v"))
|
||||
try db.execute(sql: "DROP VIEW v") // compile + execute
|
||||
try XCTAssertFalse(db.viewExists("v"))
|
||||
}
|
||||
}
|
||||
|
||||
func testObservedDropTemporaryView() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
dbQueue.add(transactionObserver: UniversalObserver(), extent: .databaseLifetime)
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "CREATE TEMPORARY VIEW v AS SELECT * FROM t")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try XCTAssertTrue(db.viewExists("v"))
|
||||
try db.execute(sql: "DROP VIEW v") // compile + execute
|
||||
try XCTAssertFalse(db.viewExists("v"))
|
||||
}
|
||||
}
|
||||
|
||||
func testDropTemporaryViewWithPreparedStatement() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "CREATE TEMPORARY VIEW v AS SELECT * FROM t")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try XCTAssertTrue(db.viewExists("v"))
|
||||
let dropStatement = try db.makeStatement(sql: "DROP VIEW v") // compile...
|
||||
try dropStatement.execute() // ... then execute
|
||||
try XCTAssertFalse(db.viewExists("v"))
|
||||
}
|
||||
}
|
||||
|
||||
func testObservedDropTemporaryViewWithPreparedStatement() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
dbQueue.add(transactionObserver: UniversalObserver(), extent: .databaseLifetime)
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "CREATE TEMPORARY VIEW v AS SELECT * FROM t")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (NULL)")
|
||||
try XCTAssertTrue(db.viewExists("v"))
|
||||
let dropStatement = try db.makeStatement(sql: "DROP VIEW v") // compile...
|
||||
try dropStatement.execute() // ... then execute
|
||||
try XCTAssertFalse(db.viewExists("v"))
|
||||
}
|
||||
}
|
||||
|
||||
func testDropIndex() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "CREATE INDEX i ON t(a)")
|
||||
try XCTAssertFalse(db.indexes(on: "t").isEmpty)
|
||||
try db.execute(sql: "DROP INDEX i") // compile + execute
|
||||
try XCTAssertTrue(db.indexes(on: "t").isEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
func testObservedDropIndex() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
dbQueue.add(transactionObserver: UniversalObserver(), extent: .databaseLifetime)
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "CREATE INDEX i ON t(a)")
|
||||
try XCTAssertFalse(db.indexes(on: "t").isEmpty)
|
||||
try db.execute(sql: "DROP INDEX i") // compile + execute
|
||||
try XCTAssertTrue(db.indexes(on: "t").isEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
func testDropIndexViewWithPreparedStatement() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "CREATE INDEX i ON t(a)")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (1)")
|
||||
try XCTAssertFalse(db.indexes(on: "t").isEmpty)
|
||||
let dropStatement = try db.makeStatement(sql: "DROP INDEX i") // compile...
|
||||
try dropStatement.execute() // ... then execute
|
||||
try XCTAssertTrue(db.indexes(on: "t").isEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
func testObservedDropIndexViewWithPreparedStatement() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
dbQueue.add(transactionObserver: UniversalObserver(), extent: .databaseLifetime)
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "CREATE INDEX i ON t(a)")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (1)")
|
||||
try XCTAssertFalse(db.indexes(on: "t").isEmpty)
|
||||
let dropStatement = try db.makeStatement(sql: "DROP INDEX i") // compile...
|
||||
try dropStatement.execute() // ... then execute
|
||||
try XCTAssertTrue(db.indexes(on: "t").isEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
func testDropTemporaryIndex() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TEMPORARY TABLE t(a)")
|
||||
try db.execute(sql: "CREATE INDEX i ON t(a)")
|
||||
try XCTAssertFalse(db.indexes(on: "t").isEmpty)
|
||||
try db.execute(sql: "DROP INDEX i") // compile + execute
|
||||
try XCTAssertTrue(db.indexes(on: "t").isEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
func testObservedDropTemporaryIndex() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
dbQueue.add(transactionObserver: UniversalObserver(), extent: .databaseLifetime)
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TEMPORARY TABLE t(a)")
|
||||
try db.execute(sql: "CREATE INDEX i ON t(a)")
|
||||
try XCTAssertFalse(db.indexes(on: "t").isEmpty)
|
||||
try db.execute(sql: "DROP INDEX i") // compile + execute
|
||||
try XCTAssertTrue(db.indexes(on: "t").isEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
func testDropTemporaryIndexViewWithPreparedStatement() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TEMPORARY TABLE t(a)")
|
||||
try db.execute(sql: "CREATE INDEX i ON t(a)")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (1)")
|
||||
try XCTAssertFalse(db.indexes(on: "t").isEmpty)
|
||||
let dropStatement = try db.makeStatement(sql: "DROP INDEX i") // compile...
|
||||
try dropStatement.execute() // ... then execute
|
||||
try XCTAssertTrue(db.indexes(on: "t").isEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
func testObservedDropTemporaryIndexViewWithPreparedStatement() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
dbQueue.add(transactionObserver: UniversalObserver(), extent: .databaseLifetime)
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TEMPORARY TABLE t(a)")
|
||||
try db.execute(sql: "CREATE INDEX i ON t(a)")
|
||||
try db.execute(sql: "INSERT INTO t VALUES (1)")
|
||||
try XCTAssertFalse(db.indexes(on: "t").isEmpty)
|
||||
let dropStatement = try db.makeStatement(sql: "DROP INDEX i") // compile...
|
||||
try dropStatement.execute() // ... then execute
|
||||
try XCTAssertTrue(db.indexes(on: "t").isEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
func testDropTrigger() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "CREATE TRIGGER r INSERT ON t BEGIN DELETE FROM t; END")
|
||||
try XCTAssertTrue(db.triggerExists("r"))
|
||||
try db.execute(sql: "DROP TRIGGER r") // compile + execute
|
||||
try XCTAssertFalse(db.triggerExists("r"))
|
||||
}
|
||||
}
|
||||
|
||||
func testObservedDropTrigger() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
dbQueue.add(transactionObserver: UniversalObserver(), extent: .databaseLifetime)
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "CREATE TRIGGER r INSERT ON t BEGIN DELETE FROM t; END")
|
||||
try XCTAssertTrue(db.triggerExists("r"))
|
||||
try db.execute(sql: "DROP TRIGGER r") // compile + execute
|
||||
try XCTAssertFalse(db.triggerExists("r"))
|
||||
}
|
||||
}
|
||||
|
||||
func testDropTriggerWithPreparedStatement() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "CREATE TRIGGER r INSERT ON t BEGIN DELETE FROM t; END")
|
||||
try XCTAssertTrue(db.triggerExists("r"))
|
||||
let dropStatement = try db.makeStatement(sql: "DROP TRIGGER r") // compile...
|
||||
try dropStatement.execute() // ... then execute
|
||||
try XCTAssertFalse(db.triggerExists("r"))
|
||||
}
|
||||
}
|
||||
|
||||
func testObservedDropTriggerWithPreparedStatement() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
dbQueue.add(transactionObserver: UniversalObserver(), extent: .databaseLifetime)
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "CREATE TRIGGER r INSERT ON t BEGIN DELETE FROM t; END")
|
||||
try XCTAssertTrue(db.triggerExists("r"))
|
||||
let dropStatement = try db.makeStatement(sql: "DROP TRIGGER r") // compile...
|
||||
try dropStatement.execute() // ... then execute
|
||||
try XCTAssertFalse(db.triggerExists("r"))
|
||||
}
|
||||
}
|
||||
|
||||
func testDropTemporaryTrigger() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "CREATE TEMPORARY TRIGGER r INSERT ON t BEGIN DELETE FROM t; END")
|
||||
try XCTAssertTrue(db.triggerExists("r"))
|
||||
try db.execute(sql: "DROP TRIGGER r") // compile + execute
|
||||
try XCTAssertFalse(db.triggerExists("r"))
|
||||
}
|
||||
}
|
||||
|
||||
func testObservedDropTemporaryTrigger() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
dbQueue.add(transactionObserver: UniversalObserver(), extent: .databaseLifetime)
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "CREATE TEMPORARY TRIGGER r INSERT ON t BEGIN DELETE FROM t; END")
|
||||
try XCTAssertTrue(db.triggerExists("r"))
|
||||
try db.execute(sql: "DROP TRIGGER r") // compile + execute
|
||||
try XCTAssertFalse(db.triggerExists("r"))
|
||||
}
|
||||
}
|
||||
|
||||
func testDropTemporaryTriggerWithPreparedStatement() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "CREATE TEMPORARY TRIGGER r INSERT ON t BEGIN DELETE FROM t; END")
|
||||
try XCTAssertTrue(db.triggerExists("r"))
|
||||
let dropStatement = try db.makeStatement(sql: "DROP TRIGGER r") // compile...
|
||||
try dropStatement.execute() // ... then execute
|
||||
try XCTAssertFalse(db.triggerExists("r"))
|
||||
}
|
||||
}
|
||||
|
||||
func testObservedDropTemporaryTriggerWithPreparedStatement() throws {
|
||||
let dbQueue = try makeDatabaseQueue()
|
||||
dbQueue.add(transactionObserver: UniversalObserver(), extent: .databaseLifetime)
|
||||
try dbQueue.writeWithoutTransaction { db in
|
||||
try db.execute(sql: "CREATE TABLE t(a)")
|
||||
try db.execute(sql: "CREATE TEMPORARY TRIGGER r INSERT ON t BEGIN DELETE FROM t; END")
|
||||
try XCTAssertTrue(db.triggerExists("r"))
|
||||
let dropStatement = try db.makeStatement(sql: "DROP TRIGGER r") // compile...
|
||||
try dropStatement.execute() // ... then execute
|
||||
try XCTAssertFalse(db.triggerExists("r"))
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user