Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ccgus/fmdb.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/Tests
diff options
context:
space:
mode:
authorRobert Ryan <robert.ryan@mindspring.com>2020-05-06 19:48:18 +0300
committerRobert Ryan <robert.ryan@mindspring.com>2020-05-06 20:09:11 +0300
commit4009be0a6f9de7cc6d6a59cf8ff820269015a828 (patch)
tree5d0b3b0a843c9c1732a709ab47560dafbc850a2b /Tests
parentdaa532443f7ef8b441a8c886c80f113ac433ca92 (diff)
Allow rebinding of values for prepared queries
Diffstat (limited to 'Tests')
-rw-r--r--Tests/FMDatabaseTests.m186
1 files changed, 185 insertions, 1 deletions
diff --git a/Tests/FMDatabaseTests.m b/Tests/FMDatabaseTests.m
index b9e1f8a..8ca2df5 100644
--- a/Tests/FMDatabaseTests.m
+++ b/Tests/FMDatabaseTests.m
@@ -1124,7 +1124,12 @@
}
- (void)testVersionNumber {
- XCTAssertEqual([FMDatabase FMDBVersion], 0x0276); // this is going to break everytime we bump it.
+ XCTAssertEqual([FMDatabase FMDBVersion], 0x0277); // this is going to break everytime we bump it.
+}
+
+- (void)testUserVersion {
+ NSComparisonResult result = [[FMDatabase FMDBUserVersion] compare:@"2.7.7" options:NSNumericSearch];
+ XCTAssertEqual(result, NSOrderedSame);
}
- (void)testVersionStringAboveRequired {
@@ -1551,4 +1556,183 @@
[manager removeItemAtURL:fileURL2 error:nil];
}
+// These three utility methods used by `testTransient`, to illustrate dangers of SQLITE_STATIC
+
+- (BOOL)utility1ForTestTransient:(FMDatabase *)db withValue:(long)value {
+ @autoreleasepool {
+ NSString *string = [[NSString alloc] initWithFormat:@"value %@", @(value)];
+ return [db executeUpdate:@"INSERT INTO foo (bar) VALUES (?)", [string dataUsingEncoding:NSUTF8StringEncoding]];
+ }
+}
+
+- (FMResultSet *)utility2ForTestTransient:(FMDatabase *)db withValue:(long)value {
+ @autoreleasepool {
+ NSString *string = [[NSString alloc] initWithFormat:@"value %@", @(value)];
+ return [db executeQuery:@"SELECT * FROM foo WHERE bar = ?", [string dataUsingEncoding:NSUTF8StringEncoding]];
+ }
+}
+
+- (BOOL)utility3ForTestTransient:(FMResultSet *)rs withValue:(long)value {
+ @autoreleasepool {
+ NSString *string = [[NSString alloc] initWithFormat:@"xxxxx %@", @(value + 1)];
+ XCTAssertEqualObjects(string, @"xxxxx 43"); // Just to ensure the above isn't optimized out
+ return [rs next];
+ }
+}
+
+- (void)testTransient {
+ NSURL *tempURL = [NSURL fileURLWithPath:NSTemporaryDirectory()];
+ NSURL *fileURL = [tempURL URLByAppendingPathComponent:[[NSUUID UUID] UUIDString]];
+ NSFileManager *manager = [NSFileManager defaultManager];
+
+ // ok, first create one database
+
+ FMDatabase *db = [FMDatabase databaseWithURL:fileURL];
+ BOOL success = [db open];
+ XCTAssert(success, @"Database not created correctly for purposes of test");
+ success = [db executeUpdate:@"CREATE TABLE IF NOT EXISTS foo (bar BLOB)"];
+ XCTAssert(success, @"Table created correctly for purposes of test");
+
+ long value = 42;
+ success = [self utility1ForTestTransient:db withValue:value];
+ XCTAssert(success, @"INSERT failed");
+
+ FMResultSet *rs = [self utility2ForTestTransient:db withValue:value];
+ XCTAssert(rs, @"Creating SELECT failed");
+
+ // the following is the key test, namely if FMDB uses SQLITE_STATIC, the following may fail, but SQLITE_TRANSIENT ensures it will succeed
+
+ success = [self utility3ForTestTransient:rs withValue:value];
+ XCTAssert(success, @"Performing SELECT failed");
+
+ // let's clean up
+
+ [rs close];
+ [db close];
+ [manager removeItemAtURL:fileURL error:nil];
+}
+
+- (void)testBindFailure {
+ NSURL *tempURL = [NSURL fileURLWithPath:NSTemporaryDirectory()];
+ NSURL *fileURL = [tempURL URLByAppendingPathComponent:[[NSUUID UUID] UUIDString]];
+ NSFileManager *manager = [NSFileManager defaultManager];
+
+ // ok, first create one database
+
+ FMDatabase *db = [FMDatabase databaseWithURL:fileURL];
+ BOOL success = [db open];
+ XCTAssert(success, @"Database not created correctly for purposes of test");
+ success = [db executeUpdate:@"CREATE TABLE IF NOT EXISTS foo (bar BLOB)"];
+ XCTAssert(success, @"Table created correctly for purposes of test");
+
+ NSUInteger limit = (NSUInteger)[db limitFor:SQLITE_LIMIT_LENGTH value:-1] + 1;
+ NSLog(@"%lu", (unsigned long)limit);
+ NSData *data = [NSMutableData dataWithLength:limit];
+ success = [db executeUpdate:@"INSERT INTO foo (bar) VALUES (?)", data];
+ XCTAssertFalse(success, @"Table created correctly for purposes of test");
+
+ // let's clean up
+
+ [db close];
+ [manager removeItemAtURL:fileURL error:nil];
+}
+
+- (void)testRebindingWithDictionary {
+ NSURL *tempURL = [NSURL fileURLWithPath:NSTemporaryDirectory()];
+ NSURL *fileURL = [tempURL URLByAppendingPathComponent:[[NSUUID UUID] UUIDString]];
+ NSFileManager *manager = [NSFileManager defaultManager];
+ [manager removeItemAtURL:fileURL error:nil];
+
+ // ok, first create one database
+
+ FMDatabase *db = [FMDatabase databaseWithURL:fileURL];
+ BOOL success = [db open];
+ XCTAssert(success, @"Database not created correctly for purposes of test");
+ success = [db executeUpdate:@"CREATE TABLE IF NOT EXISTS foo (id INTEGER PRIMARY KEY, bar TEXT)"];
+ XCTAssert(success, @"Table created correctly for purposes of test");
+
+ FMResultSet *rs = [db prepare:@"INSERT INTO foo (bar) VALUES (:bar)"];
+ XCTAssert(rs, @"INSERT statement not prepared %@", [db lastErrorMessage]);
+
+ NSString *value1 = @"foo";
+ XCTAssert([rs bindWithDictionary:@{@"bar": value1}], @"Unable to bind");
+ XCTAssert([rs step], @"Performing query failed");
+
+ NSString *value2 = @"bar";
+ XCTAssert([rs bindWithDictionary:@{@"bar": value2}], @"Unable to bind");
+ XCTAssert([rs step], @"Performing query failed");
+
+ XCTAssert([rs bindWithDictionary:@{@"bar": value2}], @"Unable to bind");
+ XCTAssert([rs step], @"Performing query failed");
+
+ [rs close];
+
+ rs = [db prepare:@"SELECT bar FROM foo WHERE bar = :bar"];
+ XCTAssert([rs bindWithDictionary:@{@"bar": value1}], @"Unable to bind");
+ XCTAssert([rs next], @"No record found");
+ XCTAssertEqualObjects([rs stringForColumnIndex:0], value1);
+ XCTAssertFalse([rs next], @"There should have been only one record");
+
+ XCTAssert([rs bindWithDictionary:@{@"bar": value2}], @"Unable to bind");
+ XCTAssert([rs next], @"No record found");
+ XCTAssertEqualObjects([rs stringForColumnIndex:0], value2);
+ XCTAssert([rs next], @"No record found");
+ XCTAssertEqualObjects([rs stringForColumnIndex:0], value2);
+ XCTAssertFalse([rs next], @"There should have been only two records");
+
+ // let's clean up
+
+ [rs close];
+ [db close];
+ [manager removeItemAtURL:fileURL error:nil];
+}
+
+- (void)testRebindingWithArray {
+ NSURL *tempURL = [NSURL fileURLWithPath:NSTemporaryDirectory()];
+ NSURL *fileURL = [tempURL URLByAppendingPathComponent:[[NSUUID UUID] UUIDString]];
+ NSFileManager *manager = [NSFileManager defaultManager];
+
+ // ok, first create one database
+
+ FMDatabase *db = [FMDatabase databaseWithURL:fileURL];
+ BOOL success = [db open];
+ XCTAssert(success, @"Database not created correctly for purposes of test");
+ success = [db executeUpdate:@"CREATE TABLE IF NOT EXISTS foo (id INTEGER PRIMARY KEY, bar TEXT)"];
+ XCTAssert(success, @"Table created correctly for purposes of test");
+
+ FMResultSet *rs = [db prepare:@"INSERT INTO foo (bar) VALUES (?)"];
+ XCTAssert(rs, @"INSERT statement not prepared %@", [db lastErrorMessage]);
+
+ NSString *value1 = @"foo";
+ XCTAssert([rs bindWithArray:@[value1]], @"Unable to bind");
+ XCTAssert([rs step], @"Performing INSERT 1 failed");
+
+ NSString *value2 = @"bar";
+ XCTAssert([rs bindWithArray:@[value2]], @"Unable to bind");
+ XCTAssert([rs step], @"Performing INSERT 2 failed");
+ XCTAssert([rs bindWithArray:@[value2]], @"Unable to bind");
+ XCTAssert([rs step], @"Performing INSERT 2 failed");
+
+ [rs close];
+
+ rs = [db prepare:@"SELECT bar FROM foo WHERE bar = ?"];
+ XCTAssert([rs bindWithArray:@[value1]], @"Unable to bind");
+ XCTAssert([rs next], @"No record found");
+ XCTAssertEqualObjects([rs stringForColumnIndex:0], value1);
+ XCTAssertFalse([rs next], @"There should have been only one record");
+
+ XCTAssert([rs bindWithArray:@[value2]], @"Unable to bind");
+ XCTAssert([rs next], @"No record found");
+ XCTAssertEqualObjects([rs stringForColumnIndex:0], value2);
+ XCTAssert([rs next], @"No record found");
+ XCTAssertEqualObjects([rs stringForColumnIndex:0], value2);
+ XCTAssertFalse([rs next], @"There should have been only two records");
+
+ // let's clean up
+
+ [rs close];
+ [db close];
+ [manager removeItemAtURL:fileURL error:nil];
+}
+
@end