Skip to content

Commit

Permalink
Merge branch 'FMResultSet_Next_Error_Handling' of git://github.com/ro…
Browse files Browse the repository at this point in the history
…sh89/fmdb into rosh89-FMResultSet_Next_Error_Handling
  • Loading branch information
ccgus committed Oct 19, 2014
2 parents 7b9b840 + 25f34a1 commit aa8fd46
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 1 deletion.
91 changes: 91 additions & 0 deletions Tests/FMResultSetTests.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//
// FMResultSetTests.m
// fmdb
//
// Created by Muralidharan,Roshan on 10/6/14.
//
//

#import "FMDBTempDBTests.h"
#import "FMDatabase.h"
#import "FMResultSet.h"

@interface FMResultSetTests : FMDBTempDBTests

@end

@implementation FMResultSetTests

+ (void)populateDatabase:(FMDatabase *)db
{
[db executeUpdate:@"create table test (a text, b text, c integer, d double, e double)"];

[db beginTransaction];
int i = 0;
while (i++ < 20) {
[db executeUpdate:@"insert into test (a, b, c, d, e) values (?, ?, ?, ?, ?)" ,
@"hi'",
[NSString stringWithFormat:@"number %d", i],
[NSNumber numberWithInt:i],
[NSDate date],
[NSNumber numberWithFloat:2.2f]];
}
[db commit];
}

- (void)testNextWithError_WithoutError
{
[self.db executeUpdate:@"CREATE TABLE testTable(key INTEGER PRIMARY KEY, value INTEGER)"];
[self.db executeUpdate:@"INSERT INTO testTable (key, value) VALUES (1, 2)"];
[self.db executeUpdate:@"INSERT INTO testTable (key, value) VALUES (2, 4)"];

FMResultSet *resultSet = [self.db executeQuery:@"SELECT * FROM testTable WHERE key=1"];
XCTAssertNotNil(resultSet);
NSError *error;
XCTAssertTrue([resultSet nextWithError:&error]);
XCTAssertNil(error);

XCTAssertFalse([resultSet nextWithError:&error]);
XCTAssertNil(error);

[resultSet close];
}

- (void)testNextWithError_WithBusyError
{
[self.db executeUpdate:@"CREATE TABLE testTable(key INTEGER PRIMARY KEY, value INTEGER)"];
[self.db executeUpdate:@"INSERT INTO testTable (key, value) VALUES (1, 2)"];
[self.db executeUpdate:@"INSERT INTO testTable (key, value) VALUES (2, 4)"];

FMResultSet *resultSet = [self.db executeQuery:@"SELECT * FROM testTable WHERE key=1"];
XCTAssertNotNil(resultSet);

FMDatabase *newDB = [FMDatabase databaseWithPath:self.databasePath];
[newDB open];

[newDB beginTransaction];
NSError *error;
XCTAssertFalse([resultSet nextWithError:&error]);
[newDB commit];


XCTAssertEqual(error.code, SQLITE_BUSY, @"SQLITE_BUSY should be the last error");
[resultSet close];
}

- (void)testNextWithError_WithMisuseError
{
[self.db executeUpdate:@"CREATE TABLE testTable(key INTEGER PRIMARY KEY, value INTEGER)"];
[self.db executeUpdate:@"INSERT INTO testTable (key, value) VALUES (1, 2)"];
[self.db executeUpdate:@"INSERT INTO testTable (key, value) VALUES (2, 4)"];

FMResultSet *resultSet = [self.db executeQuery:@"SELECT * FROM testTable WHERE key=9"];
XCTAssertNotNil(resultSet);
XCTAssertFalse([resultSet next]);
NSError *error;
XCTAssertFalse([resultSet nextWithError:&error]);

XCTAssertEqual(error.code, SQLITE_MISUSE, @"SQLITE_MISUSE should be the last error");
}

@end
4 changes: 4 additions & 0 deletions fmdb.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
3354379C19E71096005661F3 /* FMResultSetTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3354379B19E71096005661F3 /* FMResultSetTests.m */; };
621721B21892BFE30006691F /* FMDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = CCC24EBB0A13E34D00A6D3E3 /* FMDatabase.m */; };
621721B31892BFE30006691F /* FMResultSet.m in Sources */ = {isa = PBXBuildFile; fileRef = CCC24EC00A13E34D00A6D3E3 /* FMResultSet.m */; };
621721B41892BFE30006691F /* FMDatabaseQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = CC47A00E148581E9002CCDAB /* FMDatabaseQueue.m */; };
Expand Down Expand Up @@ -88,6 +89,7 @@
/* Begin PBXFileReference section */
08FB779EFE84155DC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
32A70AAB03705E1F00C91783 /* fmdb_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = fmdb_Prefix.pch; path = src/sample/fmdb_Prefix.pch; sourceTree = SOURCE_ROOT; };
3354379B19E71096005661F3 /* FMResultSetTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMResultSetTests.m; sourceTree = "<group>"; };
6290CBB5188FE836009790F8 /* libFMDB-IOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libFMDB-IOS.a"; sourceTree = BUILT_PRODUCTS_DIR; };
6290CBB6188FE836009790F8 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
6290CBC6188FE837009790F8 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
Expand Down Expand Up @@ -293,6 +295,7 @@
BF5D041A18416BB2008C5AA9 /* Tests */ = {
isa = PBXGroup;
children = (
3354379B19E71096005661F3 /* FMResultSetTests.m */,
BF940F5A18417D490001E077 /* FMDBTempDBTests.h */,
BF940F5B18417D490001E077 /* FMDBTempDBTests.m */,
BF5D042018416BB2008C5AA9 /* FMDatabaseTests.m */,
Expand Down Expand Up @@ -506,6 +509,7 @@
CCA66A3019C0CB1900EFDAC1 /* FMTokenizers.m in Sources */,
BF940F5C18417D490001E077 /* FMDBTempDBTests.m in Sources */,
BF940F5E18417DEA0001E077 /* FMDatabaseAdditionsTests.m in Sources */,
3354379C19E71096005661F3 /* FMResultSetTests.m in Sources */,
BF5D042118416BB2008C5AA9 /* FMDatabaseTests.m in Sources */,
67CB1E3019AD27D000A3CA7F /* FMDatabaseFTS3Tests.m in Sources */,
BFE55E131841C9A000CB3A63 /* FMDatabasePoolTests.m in Sources */,
Expand Down
15 changes: 14 additions & 1 deletion src/fmdb/FMResultSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@

/** Retrieve next row for result set.
You must always invoke `next` before attempting to access the values returned in a query, even if you're only expecting one.
You must always invoke `next` or `nextWithError` before attempting to access the values returned in a query, even if you're only expecting one.
@return `YES` if row successfully retrieved; `NO` if end of result set reached
Expand All @@ -83,6 +83,19 @@

- (BOOL)next;

/** Retrieve next row for result set.
You must always invoke `next` or `nextWithError` before attempting to access the values returned in a query, even if you're only expecting one.
@param outErr A 'NSError' object to receive any error object (if any).
@return 'YES' if row successfully retrieved; 'NO' if end of result set reached
@see hasAnotherRow
*/

- (BOOL)nextWithError:(NSError **)outErr;

/** Did the last call to `<next>` succeed in retrieving another row?
@return `YES` if the last call to `<next>` succeeded in retrieving another record; `NO` if not.
Expand Down
25 changes: 25 additions & 0 deletions src/fmdb/FMResultSet.m
Original file line number Diff line number Diff line change
Expand Up @@ -147,26 +147,51 @@ - (NSDictionary*)resultDictionary {


- (BOOL)next {
return [self nextWithError:nil];
}

- (BOOL)nextWithError:(NSError **)outErr {

int rc = sqlite3_step([_statement statement]);

if (SQLITE_BUSY == rc || SQLITE_LOCKED == rc) {
NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [_parentDB databasePath]);
NSLog(@"Database busy");
if (outErr) {
*outErr = [_parentDB lastError];
}
}
else if (SQLITE_DONE == rc || SQLITE_ROW == rc) {
// all is well, let's return.
}
else if (SQLITE_ERROR == rc) {
NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([_parentDB sqliteHandle]));
if (outErr) {
*outErr = [_parentDB lastError];
}
}
else if (SQLITE_MISUSE == rc) {
// uh oh.
NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([_parentDB sqliteHandle]));
if (outErr) {
if (_parentDB) {
*outErr = [_parentDB lastError];
}
else {
// If 'next' or 'nextWithError' is called after the result set is closed,
// we need to return the appropriate error.
NSDictionary* errorMessage = [NSDictionary dictionaryWithObject:@"parentDB does not exist" forKey:NSLocalizedDescriptionKey];
*outErr = [NSError errorWithDomain:@"FMDatabase" code:SQLITE_MISUSE userInfo:errorMessage];
}

}
}
else {
// wtf?
NSLog(@"Unknown error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([_parentDB sqliteHandle]));
if (outErr) {
*outErr = [_parentDB lastError];
}
}


Expand Down

0 comments on commit aa8fd46

Please sign in to comment.