This commit is contained in:
asuchkov
2017-10-19 19:30:22 +03:00
parent 1e9ddbf3a9
commit b6b5acd823
32 changed files with 1766 additions and 764 deletions

View File

@@ -2,6 +2,7 @@
#import "FMResultSet.h"
#import "FMDatabasePool.h"
NS_ASSUME_NONNULL_BEGIN
#if ! __has_feature(objc_arc)
#define FMDBAutorelease(__v) ([__v autorelease]);
@@ -70,26 +71,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
#pragma clang diagnostic ignored "-Wobjc-interface-ivars"
@interface FMDatabase : NSObject {
void* _db;
NSString* _databasePath;
BOOL _logsErrors;
BOOL _crashOnErrors;
BOOL _traceExecution;
BOOL _checkedOut;
BOOL _shouldCacheStatements;
BOOL _isExecutingStatement;
BOOL _inTransaction;
NSTimeInterval _maxBusyRetryTimeInterval;
NSTimeInterval _startBusyRetryTime;
NSMutableDictionary *_cachedStatements;
NSMutableSet *_openResultSets;
NSMutableSet *_openFunctions;
NSDateFormatter *_dateFormat;
}
@interface FMDatabase : NSObject
///-----------------
/// @name Properties
@@ -113,7 +95,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
/** Dictionary of cached statements */
@property (atomic, retain) NSMutableDictionary *cachedStatements;
@property (atomic, retain, nullable) NSMutableDictionary *cachedStatements;
///---------------------
/// @name Initialization
@@ -145,7 +127,34 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
*/
+ (instancetype)databaseWithPath:(NSString*)inPath;
+ (instancetype)databaseWithPath:(NSString * _Nullable)inPath;
/** Create a `FMDatabase` object.
An `FMDatabase` is created with a path to a SQLite database file. This path can be one of these three:
1. A file system URL. The file does not have to exist on disk. If it does not exist, it is created for you.
2. `nil`. An in-memory database is created. This database will be destroyed with the `FMDatabase` connection is closed.
For example, to create/open a database in your Mac OS X `tmp` folder:
FMDatabase *db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
Or, in iOS, you might open a database in the app's `Documents` directory:
NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *dbPath = [docsPath stringByAppendingPathComponent:@"test.db"];
FMDatabase *db = [FMDatabase databaseWithPath:dbPath];
(For more information on temporary and in-memory databases, read the sqlite documentation on the subject: [http://www.sqlite.org/inmemorydb.html](http://www.sqlite.org/inmemorydb.html))
@param url The local file URL (not remote URL) of database file
@return `FMDatabase` object if successful; `nil` if failure.
*/
+ (instancetype)databaseWithURL:(NSURL * _Nullable)url;
/** Initialize a `FMDatabase` object.
@@ -167,14 +176,40 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
(For more information on temporary and in-memory databases, read the sqlite documentation on the subject: [http://www.sqlite.org/inmemorydb.html](http://www.sqlite.org/inmemorydb.html))
@param inPath Path of database file
@param path Path of database file.
@return `FMDatabase` object if successful; `nil` if failure.
*/
- (instancetype)initWithPath:(NSString*)inPath;
- (instancetype)initWithPath:(NSString * _Nullable)path;
/** Initialize a `FMDatabase` object.
An `FMDatabase` is created with a local file URL to a SQLite database file. This path can be one of these three:
1. A file system URL. The file does not have to exist on disk. If it does not exist, it is created for you.
2. `nil`. An in-memory database is created. This database will be destroyed with the `FMDatabase` connection is closed.
For example, to create/open a database in your Mac OS X `tmp` folder:
FMDatabase *db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
Or, in iOS, you might open a database in the app's `Documents` directory:
NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *dbPath = [docsPath stringByAppendingPathComponent:@"test.db"];
FMDatabase *db = [FMDatabase databaseWithPath:dbPath];
(For more information on temporary and in-memory databases, read the sqlite documentation on the subject: [http://www.sqlite.org/inmemorydb.html](http://www.sqlite.org/inmemorydb.html))
@param url The file `NSURL` of database file.
@return `FMDatabase` object if successful; `nil` if failure.
*/
- (instancetype)initWithURL:(NSURL * _Nullable)url;
///-----------------------------------
/// @name Opening and closing database
@@ -243,7 +278,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
@see close
*/
- (BOOL)openWithFlags:(int)flags vfs:(NSString *)vfsName;
- (BOOL)openWithFlags:(int)flags vfs:(NSString * _Nullable)vfsName;
/** Closing a database connection
@@ -266,7 +301,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
@return `YES` if everything succeeds, `NO` on failure.
*/
- (BOOL)goodConnection;
@property (nonatomic, readonly) BOOL goodConnection;
///----------------------
@@ -293,7 +328,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
@see [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html)
*/
- (BOOL)executeUpdate:(NSString*)sql withErrorAndBindings:(NSError**)outErr, ...;
- (BOOL)executeUpdate:(NSString*)sql withErrorAndBindings:(NSError * _Nullable *)outErr, ...;
/** Execute single update statement
@@ -302,7 +337,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
@warning **Deprecated**: Please use `<executeUpdate:withErrorAndBindings>` instead.
*/
- (BOOL)update:(NSString*)sql withErrorAndBindings:(NSError**)outErr, ... __attribute__ ((deprecated));
- (BOOL)update:(NSString*)sql withErrorAndBindings:(NSError * _Nullable*)outErr, ... __deprecated_msg("Use executeUpdate:withErrorAndBindings: instead");;
/** Execute single update statement
@@ -323,7 +358,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
@note This technique supports the use of `?` placeholders in the SQL, automatically binding any supplied value parameters to those placeholders. This approach is more robust than techniques that entail using `stringWithFormat` to manually build SQL statements, which can be problematic if the values happened to include any characters that needed to be quoted.
@note If you want to use this from Swift, please note that you must include `FMDatabaseVariadic.swift` in your project. Without that, you cannot use this method directly, and instead have to use methods such as `<executeUpdate:withArgumentsInArray:>`.
@note You cannot use this method from Swift due to incompatibilities between Swift and Objective-C variadic implementations. Consider using `<executeUpdate:values:>` instead.
*/
- (BOOL)executeUpdate:(NSString*)sql, ...;
@@ -384,9 +419,9 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
This is similar to `<executeUpdate:withArgumentsInArray:>`, except that this also accepts a pointer to a `NSError` pointer, so that errors can be returned.
In Swift 2, this throws errors, as if it were defined as follows:
In Swift, this throws errors, as if it were defined as follows:
`func executeUpdate(sql: String!, values: [AnyObject]!) throws -> Bool`
`func executeUpdate(sql: String, values: [Any]?) throws -> Bool`
@param sql The SQL to be performed, with optional `?` placeholders.
@@ -402,7 +437,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
*/
- (BOOL)executeUpdate:(NSString*)sql values:(NSArray *)values error:(NSError * __autoreleasing *)error;
- (BOOL)executeUpdate:(NSString*)sql values:(NSArray * _Nullable)values error:(NSError * _Nullable __autoreleasing *)error;
/** Execute single update statement
@@ -476,7 +511,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
*/
- (BOOL)executeStatements:(NSString *)sql withResultBlock:(FMDBExecuteStatementsCallbackBlock)block;
- (BOOL)executeStatements:(NSString *)sql withResultBlock:(__attribute__((noescape)) FMDBExecuteStatementsCallbackBlock _Nullable)block;
/** Last insert rowid
@@ -490,7 +525,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
*/
- (int64_t)lastInsertRowId;
@property (nonatomic, readonly) int64_t lastInsertRowId;
/** The number of rows changed by prior SQL statement.
@@ -502,7 +537,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
*/
- (int)changes;
@property (nonatomic, readonly) int changes;
///-------------------------
@@ -527,10 +562,10 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
@see [`FMResultSet next`](<[FMResultSet next]>)
@see [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html)
@note If you want to use this from Swift, please note that you must include `FMDatabaseVariadic.swift` in your project. Without that, you cannot use this method directly, and instead have to use methods such as `<executeQuery:withArgumentsInArray:>`.
@note You cannot use this method from Swift due to incompatibilities between Swift and Objective-C variadic implementations. Consider using `<executeQuery:values:>` instead.
*/
- (FMResultSet *)executeQuery:(NSString*)sql, ...;
- (FMResultSet * _Nullable)executeQuery:(NSString*)sql, ...;
/** Execute select statement
@@ -560,7 +595,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
*/
- (FMResultSet *)executeQueryWithFormat:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
- (FMResultSet * _Nullable)executeQueryWithFormat:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
/** Execute select statement
@@ -579,7 +614,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
@see [`FMResultSet next`](<[FMResultSet next]>)
*/
- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments;
- (FMResultSet * _Nullable)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments;
/** Execute select statement
@@ -589,9 +624,9 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
This is similar to `<executeQuery:withArgumentsInArray:>`, except that this also accepts a pointer to a `NSError` pointer, so that errors can be returned.
In Swift 2, this throws errors, as if it were defined as follows:
In Swift, this throws errors, as if it were defined as follows:
`func executeQuery(sql: String!, values: [AnyObject]!) throws -> FMResultSet!`
`func executeQuery(sql: String, values: [Any]?) throws -> FMResultSet!`
@param sql The SELECT statement to be performed, with optional `?` placeholders.
@@ -608,7 +643,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
*/
- (FMResultSet *)executeQuery:(NSString *)sql values:(NSArray *)values error:(NSError * __autoreleasing *)error;
- (FMResultSet * _Nullable)executeQuery:(NSString *)sql values:(NSArray * _Nullable)values error:(NSError * _Nullable __autoreleasing *)error;
/** Execute select statement
@@ -626,11 +661,11 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
@see [`FMResultSet next`](<[FMResultSet next]>)
*/
- (FMResultSet *)executeQuery:(NSString *)sql withParameterDictionary:(NSDictionary *)arguments;
- (FMResultSet * _Nullable)executeQuery:(NSString *)sql withParameterDictionary:(NSDictionary * _Nullable)arguments;
// Documentation forthcoming.
- (FMResultSet *)executeQuery:(NSString*)sql withVAList: (va_list)args;
- (FMResultSet * _Nullable)executeQuery:(NSString *)sql withVAList:(va_list)args;
///-------------------
/// @name Transactions
@@ -643,7 +678,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
@see commit
@see rollback
@see beginDeferredTransaction
@see inTransaction
@see isInTransaction
*/
- (BOOL)beginTransaction;
@@ -655,7 +690,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
@see commit
@see rollback
@see beginTransaction
@see inTransaction
@see isInTransaction
*/
- (BOOL)beginDeferredTransaction;
@@ -669,7 +704,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
@see beginTransaction
@see beginDeferredTransaction
@see rollback
@see inTransaction
@see isInTransaction
*/
- (BOOL)commit;
@@ -683,22 +718,22 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
@see beginTransaction
@see beginDeferredTransaction
@see commit
@see inTransaction
@see isInTransaction
*/
- (BOOL)rollback;
/** Identify whether currently in a transaction or not
@return `YES` if currently within transaction; `NO` if not.
@see beginTransaction
@see beginDeferredTransaction
@see commit
@see rollback
*/
- (BOOL)inTransaction;
@property (nonatomic, readonly) BOOL isInTransaction;
- (BOOL)inTransaction __deprecated_msg("Use isInTransaction property instead");
///----------------------------------------
@@ -718,22 +753,22 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
@return `YES` if there are open result sets; `NO` if not.
*/
- (BOOL)hasOpenResultSets;
@property (nonatomic, readonly) BOOL hasOpenResultSets;
/** Return whether should cache statements or not
/** Whether should cache statements or not
*/
@property (nonatomic) BOOL shouldCacheStatements;
/** Interupt pending database operation
This method causes any pending database operation to abort and return at its earliest opportunity
@return `YES` on success; `NO` on failure. If failed, you can call `<lastError>`, `<lastErrorCode>`, or `<lastErrorMessage>` for diagnostic information regarding the failure.
@return `YES` if should cache statements; `NO` if not.
*/
- (BOOL)shouldCacheStatements;
/** Set whether should cache statements or not
@param value `YES` if should cache statements; `NO` if not.
*/
- (void)setShouldCacheStatements:(BOOL)value;
- (BOOL)interrupt;
///-------------------------
/// @name Encryption methods
@@ -797,12 +832,14 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
///------------------------------
/** The path of the database file
@return path of database.
*/
- (NSString *)databasePath;
@property (nonatomic, readonly, nullable) NSString *databasePath;
/** The file URL of the database file.
*/
@property (nonatomic, readonly, nullable) NSURL *databaseURL;
/** The underlying SQLite handle
@@ -810,7 +847,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
*/
- (void*)sqliteHandle;
@property (nonatomic, readonly) void *sqliteHandle;
///-----------------------------
@@ -834,17 +871,33 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
/** Last error code
Returns the numeric result code or extended result code for the most recent failed SQLite API call associated with a database connection. If a prior API call failed but the most recent API call succeeded, this return value is undefined.
@return Integer value of the last error code.
@see [sqlite3_errcode()](http://sqlite.org/c3ref/errcode.html)
@see lastErrorMessage
@see lastError
*/
- (int)lastErrorCode;
/** Last extended error code
Returns the numeric extended result code for the most recent failed SQLite API call associated with a database connection. If a prior API call failed but the most recent API call succeeded, this return value is undefined.
@return Integer value of the last extended error code.
@see [sqlite3_errcode()](http://sqlite.org/c3ref/errcode.html)
@see [2. Primary Result Codes versus Extended Result Codes](http://sqlite.org/rescode.html#primary_result_codes_versus_extended_result_codes)
@see [5. Extended Result Code List](http://sqlite.org/rescode.html#extrc)
@see lastErrorMessage
@see lastError
*/
- (int)lastExtendedErrorCode;
/** Had error
@return `YES` if there was an error, `NO` if no error.
@@ -866,12 +919,11 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
*/
- (NSError*)lastError;
- (NSError *)lastError;
// description forthcoming
- (void)setMaxBusyRetryTimeInterval:(NSTimeInterval)timeoutInSeconds;
- (NSTimeInterval)maxBusyRetryTimeInterval;
@property (nonatomic) NSTimeInterval maxBusyRetryTimeInterval;
///------------------
@@ -890,7 +942,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
@see rollbackToSavePointWithName:error:
*/
- (BOOL)startSavePointWithName:(NSString*)name error:(NSError**)outErr;
- (BOOL)startSavePointWithName:(NSString*)name error:(NSError * _Nullable *)outErr;
/** Release save point
@@ -905,7 +957,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
*/
- (BOOL)releaseSavePointWithName:(NSString*)name error:(NSError**)outErr;
- (BOOL)releaseSavePointWithName:(NSString*)name error:(NSError * _Nullable *)outErr;
/** Roll back to save point
@@ -919,7 +971,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
*/
- (BOOL)rollbackToSavePointWithName:(NSString*)name error:(NSError**)outErr;
- (BOOL)rollbackToSavePointWithName:(NSString*)name error:(NSError * _Nullable *)outErr;
/** Start save point
@@ -933,7 +985,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
*/
- (NSError*)inSavePoint:(void (^)(BOOL *rollback))block;
- (NSError * _Nullable)inSavePoint:(__attribute__((noescape)) void (^)(BOOL *rollback))block;
///----------------------------
/// @name SQLite library status
@@ -971,48 +1023,193 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
For example:
[queue inDatabase:^(FMDatabase *adb) {
[adb executeUpdate:@"create table ftest (foo text)"];
[adb executeUpdate:@"insert into ftest values ('hello')"];
[adb executeUpdate:@"insert into ftest values ('hi')"];
[adb executeUpdate:@"insert into ftest values ('not h!')"];
[adb executeUpdate:@"insert into ftest values ('definitely not h!')"];
[adb makeFunctionNamed:@"StringStartsWithH" maximumArguments:1 withBlock:^(sqlite3_context *context, int aargc, sqlite3_value **aargv) {
if (sqlite3_value_type(aargv[0]) == SQLITE_TEXT) {
@autoreleasepool {
const char *c = (const char *)sqlite3_value_text(aargv[0]);
NSString *s = [NSString stringWithUTF8String:c];
sqlite3_result_int(context, [s hasPrefix:@"h"]);
}
}
else {
NSLog(@"Unknown formart for StringStartsWithH (%d) %s:%d", sqlite3_value_type(aargv[0]), __FUNCTION__, __LINE__);
sqlite3_result_null(context);
}
}];
int rowCount = 0;
FMResultSet *ars = [adb executeQuery:@"select * from ftest where StringStartsWithH(foo)"];
while ([ars next]) {
rowCount++;
NSLog(@"Does %@ start with 'h'?", [rs stringForColumnIndex:0]);
[db makeFunctionNamed:@"RemoveDiacritics" arguments:1 block:^(void *context, int argc, void **argv) {
SqliteValueType type = [self.db valueType:argv[0]];
if (type == SqliteValueTypeNull) {
[self.db resultNullInContext:context];
return;
}
FMDBQuickCheck(rowCount == 2);
if (type != SqliteValueTypeText) {
[self.db resultError:@"Expected text" context:context];
return;
}
NSString *string = [self.db valueString:argv[0]];
NSString *result = [string stringByFoldingWithOptions:NSDiacriticInsensitiveSearch locale:nil];
[self.db resultString:result context:context];
}];
@param name Name of function
FMResultSet *rs = [db executeQuery:@"SELECT * FROM employees WHERE RemoveDiacritics(first_name) LIKE 'jose'"];
NSAssert(rs, @"Error %@", [db lastErrorMessage]);
@param name Name of function.
@param count Maximum number of parameters
@param arguments Maximum number of parameters.
@param block The block of code for the function
@param block The block of code for the function.
@see [sqlite3_create_function()](http://sqlite.org/c3ref/create_function.html)
*/
- (void)makeFunctionNamed:(NSString*)name maximumArguments:(int)count withBlock:(void (^)(void *context, int argc, void **argv))block;
- (void)makeFunctionNamed:(NSString *)name arguments:(int)arguments block:(void (^)(void *context, int argc, void * _Nonnull * _Nonnull argv))block;
- (void)makeFunctionNamed:(NSString *)name maximumArguments:(int)count withBlock:(void (^)(void *context, int argc, void * _Nonnull * _Nonnull argv))block __deprecated_msg("Use makeFunctionNamed:arguments:block:");
typedef NS_ENUM(int, SqliteValueType) {
SqliteValueTypeInteger = 1,
SqliteValueTypeFloat = 2,
SqliteValueTypeText = 3,
SqliteValueTypeBlob = 4,
SqliteValueTypeNull = 5
};
- (SqliteValueType)valueType:(void *)argv;
/**
Get integer value of parameter in custom function.
@param value The argument whose value to return.
@return The integer value.
@see makeFunctionNamed:arguments:block:
*/
- (int)valueInt:(void *)value;
/**
Get long value of parameter in custom function.
@param value The argument whose value to return.
@return The long value.
@see makeFunctionNamed:arguments:block:
*/
- (long long)valueLong:(void *)value;
/**
Get double value of parameter in custom function.
@param value The argument whose value to return.
@return The double value.
@see makeFunctionNamed:arguments:block:
*/
- (double)valueDouble:(void *)value;
/**
Get `NSData` value of parameter in custom function.
@param value The argument whose value to return.
@return The data object.
@see makeFunctionNamed:arguments:block:
*/
- (NSData * _Nullable)valueData:(void *)value;
/**
Get string value of parameter in custom function.
@param value The argument whose value to return.
@return The string value.
@see makeFunctionNamed:arguments:block:
*/
- (NSString * _Nullable)valueString:(void *)value;
/**
Return null value from custom function.
@param context The context to which the null value will be returned.
@see makeFunctionNamed:arguments:block:
*/
- (void)resultNullInContext:(void *)context NS_SWIFT_NAME(resultNull(context:));
/**
Return integer value from custom function.
@param value The integer value to be returned.
@param context The context to which the value will be returned.
@see makeFunctionNamed:arguments:block:
*/
- (void)resultInt:(int) value context:(void *)context;
/**
Return long value from custom function.
@param value The long value to be returned.
@param context The context to which the value will be returned.
@see makeFunctionNamed:arguments:block:
*/
- (void)resultLong:(long long)value context:(void *)context;
/**
Return double value from custom function.
@param value The double value to be returned.
@param context The context to which the value will be returned.
@see makeFunctionNamed:arguments:block:
*/
- (void)resultDouble:(double)value context:(void *)context;
/**
Return `NSData` object from custom function.
@param data The `NSData` object to be returned.
@param context The context to which the value will be returned.
@see makeFunctionNamed:arguments:block:
*/
- (void)resultData:(NSData *)data context:(void *)context;
/**
Return string value from custom function.
@param value The string value to be returned.
@param context The context to which the value will be returned.
@see makeFunctionNamed:arguments:block:
*/
- (void)resultString:(NSString *)value context:(void *)context;
/**
Return error string from custom function.
@param error The error string to be returned.
@param context The context to which the error will be returned.
@see makeFunctionNamed:arguments:block:
*/
- (void)resultError:(NSString *)error context:(void *)context;
/**
Return error code from custom function.
@param errorCode The integer error code to be returned.
@param context The context to which the error will be returned.
@see makeFunctionNamed:arguments:block:
*/
- (void)resultErrorCode:(int)errorCode context:(void *)context;
/**
Report memory error in custom function.
@param context The context to which the error will be returned.
@see makeFunctionNamed:arguments:block:
*/
- (void)resultErrorNoMemoryInContext:(void *)context NS_SWIFT_NAME(resultErrorNoMemory(context:));
/**
Report that string or BLOB is too long to represent in custom function.
@param context The context to which the error will be returned.
@see makeFunctionNamed:arguments:block:
*/
- (void)resultErrorTooBigInContext:(void *)context NS_SWIFT_NAME(resultErrorTooBig(context:));
///---------------------
/// @name Date formatter
@@ -1083,7 +1280,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
@see storeableDateFormat:
*/
- (NSDate *)dateFromString:(NSString *)s;
- (NSDate * _Nullable)dateFromString:(NSString *)s;
/** Convert the supplied NSDate to NSString, using the current database formatter.
@@ -1160,3 +1357,4 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
#pragma clang diagnostic pop
NS_ASSUME_NONNULL_END

View File

@@ -8,38 +8,61 @@
#import <sqlite3.h>
#endif
@interface FMDatabase ()
@interface FMDatabase () {
void* _db;
BOOL _isExecutingStatement;
NSTimeInterval _startBusyRetryTime;
NSMutableSet *_openResultSets;
NSMutableSet *_openFunctions;
NSDateFormatter *_dateFormat;
}
- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args;
- (BOOL)executeUpdate:(NSString*)sql error:(NSError**)outErr withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args;
NS_ASSUME_NONNULL_BEGIN
- (FMResultSet * _Nullable)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray * _Nullable)arrayArgs orDictionary:(NSDictionary * _Nullable)dictionaryArgs orVAList:(va_list)args;
- (BOOL)executeUpdate:(NSString *)sql error:(NSError * _Nullable *)outErr withArgumentsInArray:(NSArray * _Nullable)arrayArgs orDictionary:(NSDictionary * _Nullable)dictionaryArgs orVAList:(va_list)args;
NS_ASSUME_NONNULL_END
@end
@implementation FMDatabase
@synthesize cachedStatements=_cachedStatements;
@synthesize logsErrors=_logsErrors;
@synthesize crashOnErrors=_crashOnErrors;
@synthesize checkedOut=_checkedOut;
@synthesize traceExecution=_traceExecution;
// Because these two properties have all of their accessor methods implemented,
// we have to synthesize them to get the corresponding ivars. The rest of the
// properties have their ivars synthesized automatically for us.
@synthesize shouldCacheStatements = _shouldCacheStatements;
@synthesize maxBusyRetryTimeInterval = _maxBusyRetryTimeInterval;
#pragma mark FMDatabase instantiation and deallocation
+ (instancetype)databaseWithPath:(NSString*)aPath {
+ (instancetype)databaseWithPath:(NSString *)aPath {
return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath]);
}
+ (instancetype)databaseWithURL:(NSURL *)url {
return FMDBReturnAutoreleased([[self alloc] initWithURL:url]);
}
- (instancetype)init {
return [self initWithPath:nil];
}
- (instancetype)initWithPath:(NSString*)aPath {
- (instancetype)initWithURL:(NSURL *)url {
return [self initWithPath:url.path];
}
- (instancetype)initWithPath:(NSString *)path {
assert(sqlite3_threadsafe()); // whoa there big boy- gotta make sure sqlite it happy with what we're going to do.
self = [super init];
if (self) {
_databasePath = [aPath copy];
_databasePath = [path copy];
_openResultSets = [[NSMutableSet alloc] init];
_db = nil;
_logsErrors = YES;
@@ -50,10 +73,12 @@
return self;
}
#if ! __has_feature(objc_arc)
- (void)finalize {
[self close];
[super finalize];
}
#endif
- (void)dealloc {
[self close];
@@ -68,12 +93,12 @@
#endif
}
- (NSString *)databasePath {
return _databasePath;
- (NSURL *)databaseURL {
return _databasePath ? [NSURL fileURLWithPath:_databasePath] : nil;
}
+ (NSString*)FMDBUserVersion {
return @"2.6.2";
return @"2.7.2";
}
// returns 0x0240 for version 2.4. This makes it super easy to do things like:
@@ -321,7 +346,9 @@ static int FMDBDatabaseBusyHandler(void *f, int count) {
- (void)clearCachedStatements {
for (NSMutableSet *statements in [_cachedStatements objectEnumerator]) {
[statements makeObjectsPerformSelector:@selector(close)];
for (FMStatement *statement in [statements allObjects]) {
[statement close];
}
}
[_cachedStatements removeAllObjects];
@@ -485,7 +512,7 @@ static int FMDBDatabaseBusyHandler(void *f, int count) {
#pragma mark Error routines
- (NSString*)lastErrorMessage {
- (NSString *)lastErrorMessage {
return [NSString stringWithUTF8String:sqlite3_errmsg(_db)];
}
@@ -499,7 +526,11 @@ static int FMDBDatabaseBusyHandler(void *f, int count) {
return sqlite3_errcode(_db);
}
- (NSError*)errorWithMessage:(NSString*)message {
- (int)lastExtendedErrorCode {
return sqlite3_extended_errcode(_db);
}
- (NSError*)errorWithMessage:(NSString *)message {
NSDictionary* errorMessage = [NSDictionary dictionaryWithObject:message forKey:NSLocalizedDescriptionKey];
return [NSError errorWithDomain:@"FMDatabase" code:sqlite3_errcode(_db) userInfo:errorMessage];
@@ -1075,6 +1106,12 @@ static int FMDBDatabaseBusyHandler(void *f, int count) {
if (SQLITE_DONE == rc) {
// all is well, let's return.
}
else if (SQLITE_INTERRUPT == rc) {
if (_logsErrors) {
NSLog(@"Error calling sqlite3_step. Query was interrupted (%d: %s) SQLITE_INTERRUPT", rc, sqlite3_errmsg(_db));
NSLog(@"DB Query: %@", sql);
}
}
else if (rc == SQLITE_ROW) {
NSString *message = [NSString stringWithFormat:@"A executeUpdate is being called with a query string '%@'", sql];
if (_logsErrors) {
@@ -1259,7 +1296,7 @@ int FMDBExecuteBulkSQLCallback(void *theBlockAsVoid, int columns, char **values,
BOOL b = [self executeUpdate:@"rollback transaction"];
if (b) {
_inTransaction = NO;
_isInTransaction = NO;
}
return b;
@@ -1269,7 +1306,7 @@ int FMDBExecuteBulkSQLCallback(void *theBlockAsVoid, int columns, char **values,
BOOL b = [self executeUpdate:@"commit transaction"];
if (b) {
_inTransaction = NO;
_isInTransaction = NO;
}
return b;
@@ -1279,7 +1316,7 @@ int FMDBExecuteBulkSQLCallback(void *theBlockAsVoid, int columns, char **values,
BOOL b = [self executeUpdate:@"begin deferred transaction"];
if (b) {
_inTransaction = YES;
_isInTransaction = YES;
}
return b;
@@ -1289,14 +1326,23 @@ int FMDBExecuteBulkSQLCallback(void *theBlockAsVoid, int columns, char **values,
BOOL b = [self executeUpdate:@"begin exclusive transaction"];
if (b) {
_inTransaction = YES;
_isInTransaction = YES;
}
return b;
}
- (BOOL)inTransaction {
return _inTransaction;
return _isInTransaction;
}
- (BOOL)interrupt
{
if (_db) {
sqlite3_interrupt([self sqliteHandle]);
return YES;
}
return NO;
}
static NSString *FMDBEscapeSavePointName(NSString *savepointName) {
@@ -1407,12 +1453,19 @@ void FMDBBlockSQLiteCallBackFunction(sqlite3_context *context, int argc, sqlite3
void (^block)(sqlite3_context *context, int argc, sqlite3_value **argv) = (__bridge id)sqlite3_user_data(context);
#endif
if (block) {
block(context, argc, argv);
@autoreleasepool {
block(context, argc, argv);
}
}
}
// deprecated because "arguments" parameter is not maximum argument count, but actual argument count.
- (void)makeFunctionNamed:(NSString*)name maximumArguments:(int)count withBlock:(void (^)(void *context, int argc, void **argv))block {
- (void)makeFunctionNamed:(NSString *)name maximumArguments:(int)arguments withBlock:(void (^)(void *context, int argc, void **argv))block {
[self makeFunctionNamed:name arguments:arguments block:block];
}
- (void)makeFunctionNamed:(NSString *)name arguments:(int)arguments block:(void (^)(void *context, int argc, void **argv))block {
if (!_openFunctions) {
_openFunctions = [NSMutableSet new];
@@ -1424,26 +1477,91 @@ void FMDBBlockSQLiteCallBackFunction(sqlite3_context *context, int argc, sqlite3
/* I tried adding custom functions to release the block when the connection is destroyed- but they seemed to never be called, so we use _openFunctions to store the values instead. */
#if ! __has_feature(objc_arc)
sqlite3_create_function([self sqliteHandle], [name UTF8String], count, SQLITE_UTF8, (void*)b, &FMDBBlockSQLiteCallBackFunction, 0x00, 0x00);
sqlite3_create_function([self sqliteHandle], [name UTF8String], arguments, SQLITE_UTF8, (void*)b, &FMDBBlockSQLiteCallBackFunction, 0x00, 0x00);
#else
sqlite3_create_function([self sqliteHandle], [name UTF8String], count, SQLITE_UTF8, (__bridge void*)b, &FMDBBlockSQLiteCallBackFunction, 0x00, 0x00);
sqlite3_create_function([self sqliteHandle], [name UTF8String], arguments, SQLITE_UTF8, (__bridge void*)b, &FMDBBlockSQLiteCallBackFunction, 0x00, 0x00);
#endif
}
- (SqliteValueType)valueType:(void *)value {
return sqlite3_value_type(value);
}
- (int)valueInt:(void *)value {
return sqlite3_value_int(value);
}
- (long long)valueLong:(void *)value {
return sqlite3_value_int64(value);
}
- (double)valueDouble:(void *)value {
return sqlite3_value_double(value);
}
- (NSData *)valueData:(void *)value {
const void *bytes = sqlite3_value_blob(value);
int length = sqlite3_value_bytes(value);
return bytes ? [NSData dataWithBytes:bytes length:length] : nil;
}
- (NSString *)valueString:(void *)value {
const char *cString = (const char *)sqlite3_value_text(value);
return cString ? [NSString stringWithUTF8String:cString] : nil;
}
- (void)resultNullInContext:(void *)context {
sqlite3_result_null(context);
}
- (void)resultInt:(int) value context:(void *)context {
sqlite3_result_int(context, value);
}
- (void)resultLong:(long long)value context:(void *)context {
sqlite3_result_int64(context, value);
}
- (void)resultDouble:(double)value context:(void *)context {
sqlite3_result_double(context, value);
}
- (void)resultData:(NSData *)data context:(void *)context {
sqlite3_result_blob(context, data.bytes, (int)data.length, SQLITE_TRANSIENT);
}
- (void)resultString:(NSString *)value context:(void *)context {
sqlite3_result_text(context, [value UTF8String], -1, SQLITE_TRANSIENT);
}
- (void)resultError:(NSString *)error context:(void *)context {
sqlite3_result_error(context, [error UTF8String], -1);
}
- (void)resultErrorCode:(int)errorCode context:(void *)context {
sqlite3_result_error_code(context, errorCode);
}
- (void)resultErrorNoMemoryInContext:(void *)context {
sqlite3_result_error_nomem(context);
}
- (void)resultErrorTooBigInContext:(void *)context {
sqlite3_result_error_toobig(context);
}
@end
@implementation FMStatement
@synthesize statement=_statement;
@synthesize query=_query;
@synthesize useCount=_useCount;
@synthesize inUse=_inUse;
#if ! __has_feature(objc_arc)
- (void)finalize {
[self close];
[super finalize];
}
#endif
- (void)dealloc {
[self close];
@@ -1474,6 +1592,5 @@ void FMDBBlockSQLiteCallBackFunction(sqlite3_context *context, int argc, sqlite3
return [NSString stringWithFormat:@"%@ %ld hit(s) for query %@", [super description], _useCount, _query];
}
@end

View File

@@ -9,6 +9,7 @@
#import <Foundation/Foundation.h>
#import "FMDatabase.h"
NS_ASSUME_NONNULL_BEGIN
/** Category of additions for `<FMDatabase>` class.
@@ -30,7 +31,7 @@
@return `int` value.
@note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
@note This is not available from Swift.
*/
- (int)intForQuery:(NSString*)query, ...;
@@ -42,7 +43,7 @@
@return `long` value.
@note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
@note This is not available from Swift.
*/
- (long)longForQuery:(NSString*)query, ...;
@@ -54,7 +55,7 @@
@return `BOOL` value.
@note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
@note This is not available from Swift.
*/
- (BOOL)boolForQuery:(NSString*)query, ...;
@@ -66,7 +67,7 @@
@return `double` value.
@note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
@note This is not available from Swift.
*/
- (double)doubleForQuery:(NSString*)query, ...;
@@ -78,10 +79,10 @@
@return `NSString` value.
@note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
@note This is not available from Swift.
*/
- (NSString*)stringForQuery:(NSString*)query, ...;
- (NSString * _Nullable)stringForQuery:(NSString*)query, ...;
/** Return `NSData` value for query
@@ -90,10 +91,10 @@
@return `NSData` value.
@note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
@note This is not available from Swift.
*/
- (NSData*)dataForQuery:(NSString*)query, ...;
- (NSData * _Nullable)dataForQuery:(NSString*)query, ...;
/** Return `NSDate` value for query
@@ -102,10 +103,10 @@
@return `NSDate` value.
@note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
@note This is not available from Swift.
*/
- (NSDate*)dateForQuery:(NSString*)query, ...;
- (NSDate * _Nullable)dateForQuery:(NSString*)query, ...;
// Notice that there's no dataNoCopyForQuery:.
@@ -141,7 +142,7 @@
@see [SQLite File Format](http://www.sqlite.org/fileformat.html)
*/
- (FMResultSet*)getSchema;
- (FMResultSet *)getSchema;
/** The schema of the database.
@@ -191,7 +192,7 @@
@warning Deprecated - use `<columnExists:inTableWithName:>` instead.
*/
- (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __attribute__ ((deprecated));
- (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __deprecated_msg("Use columnExists:inTableWithName: instead");
/** Validate SQL statement
@@ -206,7 +207,7 @@
*/
- (BOOL)validateSQL:(NSString*)sql error:(NSError**)error;
- (BOOL)validateSQL:(NSString*)sql error:(NSError * _Nullable *)error;
///-----------------------------------
@@ -220,36 +221,16 @@
@see setApplicationID:
*/
- (uint32_t)applicationID;
/** Set the application ID
@param appID The `uint32_t` numeric value of the application ID.
@see applicationID
*/
- (void)setApplicationID:(uint32_t)appID;
@property (nonatomic) uint32_t applicationID;
#if TARGET_OS_MAC && !TARGET_OS_IPHONE
/** Retrieve application ID string
@return The `NSString` value of the application ID.
/** Retrieve application ID string
@see setApplicationIDString:
*/
- (NSString*)applicationIDString;
/** Set the application ID string
@param string The `NSString` value of the application ID.
@see applicationIDString
*/
- (void)setApplicationIDString:(NSString*)string;
@property (nonatomic, retain) NSString *applicationIDString;
#endif
@@ -259,20 +240,11 @@
/** Retrieve user version
@return The `uint32_t` numeric value of the user version.
@see setUserVersion:
*/
- (uint32_t)userVersion;
/** Set the user-version
@param version The `uint32_t` numeric value of the user version.
@see userVersion
*/
- (void)setUserVersion:(uint32_t)version;
@property (nonatomic) uint32_t userVersion;
@end
NS_ASSUME_NONNULL_END

View File

@@ -17,7 +17,7 @@
#endif
@interface FMDatabase (PrivateStuff)
- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args;
- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray * _Nullable)arrayArgs orDictionary:(NSDictionary * _Nullable)dictionaryArgs orVAList:(va_list)args;
@end
@implementation FMDatabase (FMDatabaseAdditions)
@@ -34,7 +34,7 @@ type ret = [resultSet sel:0]; \
return ret;
- (NSString*)stringForQuery:(NSString*)query, ... {
- (NSString *)stringForQuery:(NSString*)query, ... {
RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSString *, stringForColumnIndex);
}
@@ -222,12 +222,11 @@ return ret;
#pragma clang diagnostic pop
- (BOOL)validateSQL:(NSString*)sql error:(NSError**)error {
sqlite3_stmt *pStmt = NULL;
BOOL validationSucceeded = YES;
int rc = sqlite3_prepare_v2(_db, [sql UTF8String], -1, &pStmt, 0);
int rc = sqlite3_prepare_v2([self sqliteHandle], [sql UTF8String], -1, &pStmt, 0);
if (rc != SQLITE_OK) {
validationSucceeded = NO;
if (error) {

140
ios/Pods/FMDB/src/fmdb/FMDatabasePool.h generated Normal file → Executable file
View File

@@ -8,6 +8,8 @@
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@class FMDatabase;
/** Pool of `<FMDatabase>` objects.
@@ -28,27 +30,15 @@
in the main.m file.
*/
@interface FMDatabasePool : NSObject {
NSString *_path;
dispatch_queue_t _lockQueue;
NSMutableArray *_databaseInPool;
NSMutableArray *_databaseOutPool;
__unsafe_unretained id _delegate;
NSUInteger _maximumNumberOfDatabasesToCreate;
int _openFlags;
}
@interface FMDatabasePool : NSObject
/** Database path */
@property (atomic, retain) NSString *path;
@property (atomic, copy, nullable) NSString *path;
/** Delegate object */
@property (atomic, assign) id delegate;
@property (atomic, assign, nullable) id delegate;
/** Maximum number of databases to create */
@@ -58,73 +48,140 @@
@property (atomic, readonly) int openFlags;
/** Custom virtual file system name */
@property (atomic, copy, nullable) NSString *vfsName;
///---------------------
/// @name Initialization
///---------------------
/** Create pool using path.
@param aPath The file path of the database.
@return The `FMDatabasePool` object. `nil` on error.
*/
+ (instancetype)databasePoolWithPath:(NSString*)aPath;
+ (instancetype)databasePoolWithPath:(NSString * _Nullable)aPath;
/** Create pool using file URL.
@param url The file `NSURL` of the database.
@return The `FMDatabasePool` object. `nil` on error.
*/
+ (instancetype)databasePoolWithURL:(NSURL * _Nullable)url;
/** Create pool using path and specified flags
@param aPath The file path of the database.
@param openFlags Flags passed to the openWithFlags method of the database
@param openFlags Flags passed to the openWithFlags method of the database.
@return The `FMDatabasePool` object. `nil` on error.
*/
+ (instancetype)databasePoolWithPath:(NSString*)aPath flags:(int)openFlags;
+ (instancetype)databasePoolWithPath:(NSString * _Nullable)aPath flags:(int)openFlags;
/** Create pool using file URL and specified flags
@param url The file `NSURL` of the database.
@param openFlags Flags passed to the openWithFlags method of the database.
@return The `FMDatabasePool` object. `nil` on error.
*/
+ (instancetype)databasePoolWithURL:(NSURL * _Nullable)url flags:(int)openFlags;
/** Create pool using path.
@param aPath The file path of the database.
@return The `FMDatabasePool` object. `nil` on error.
*/
- (instancetype)initWithPath:(NSString*)aPath;
- (instancetype)initWithPath:(NSString * _Nullable)aPath;
/** Create pool using file URL.
@param url The file `NSURL of the database.
@return The `FMDatabasePool` object. `nil` on error.
*/
- (instancetype)initWithURL:(NSURL * _Nullable)url;
/** Create pool using path and specified flags.
@param aPath The file path of the database.
@param openFlags Flags passed to the openWithFlags method of the database
@return The `FMDatabasePool` object. `nil` on error.
*/
- (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags;
- (instancetype)initWithPath:(NSString * _Nullable)aPath flags:(int)openFlags;
/** Create pool using file URL and specified flags.
@param url The file `NSURL` of the database.
@param openFlags Flags passed to the openWithFlags method of the database
@return The `FMDatabasePool` object. `nil` on error.
*/
- (instancetype)initWithURL:(NSURL * _Nullable)url flags:(int)openFlags;
/** Create pool using path and specified flags.
@param aPath The file path of the database.
@param openFlags Flags passed to the openWithFlags method of the database
@param vfsName The name of a custom virtual file system
@return The `FMDatabasePool` object. `nil` on error.
*/
- (instancetype)initWithPath:(NSString * _Nullable)aPath flags:(int)openFlags vfs:(NSString * _Nullable)vfsName;
/** Create pool using file URL and specified flags.
@param url The file `NSURL` of the database.
@param openFlags Flags passed to the openWithFlags method of the database
@param vfsName The name of a custom virtual file system
@return The `FMDatabasePool` object. `nil` on error.
*/
- (instancetype)initWithURL:(NSURL * _Nullable)url flags:(int)openFlags vfs:(NSString * _Nullable)vfsName;
/** Returns the Class of 'FMDatabase' subclass, that will be used to instantiate database object.
Subclasses can override this method to return specified Class of 'FMDatabase' subclass.
@return The Class of 'FMDatabase' subclass, that will be used to instantiate database object.
*/
+ (Class)databaseClass;
///------------------------------------------------
/// @name Keeping track of checked in/out databases
///------------------------------------------------
/** Number of checked-in databases in pool
@returns Number of databases
*/
- (NSUInteger)countOfCheckedInDatabases;
@property (nonatomic, readonly) NSUInteger countOfCheckedInDatabases;
/** Number of checked-out databases in pool
@returns Number of databases
*/
- (NSUInteger)countOfCheckedOutDatabases;
@property (nonatomic, readonly) NSUInteger countOfCheckedOutDatabases;
/** Total number of databases in pool
@returns Number of databases
*/
- (NSUInteger)countOfOpenDatabases;
@property (nonatomic, readonly) NSUInteger countOfOpenDatabases;
/** Release all databases in pool */
@@ -139,21 +196,21 @@
@param block The code to be run on the `FMDatabasePool` pool.
*/
- (void)inDatabase:(void (^)(FMDatabase *db))block;
- (void)inDatabase:(__attribute__((noescape)) void (^)(FMDatabase *db))block;
/** Synchronously perform database operations in pool using transaction.
@param block The code to be run on the `FMDatabasePool` pool.
*/
- (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
- (void)inTransaction:(__attribute__((noescape)) void (^)(FMDatabase *db, BOOL *rollback))block;
/** Synchronously perform database operations in pool using deferred transaction.
@param block The code to be run on the `FMDatabasePool` pool.
*/
- (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
- (void)inDeferredTransaction:(__attribute__((noescape)) void (^)(FMDatabase *db, BOOL *rollback))block;
/** Synchronously perform database operations in pool using save point.
@@ -164,7 +221,7 @@
@warning You can not nest these, since calling it will pull another database out of the pool and you'll get a deadlock. If you need to nest, use `<[FMDatabase startSavePointWithName:error:]>` instead.
*/
- (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block;
- (NSError * _Nullable)inSavePoint:(__attribute__((noescape)) void (^)(FMDatabase *db, BOOL *rollback))block;
@end
@@ -198,3 +255,4 @@
@end
NS_ASSUME_NONNULL_END

49
ios/Pods/FMDB/src/fmdb/FMDatabasePool.m generated Normal file → Executable file
View File

@@ -15,7 +15,12 @@
#import "FMDatabasePool.h"
#import "FMDatabase.h"
@interface FMDatabasePool()
@interface FMDatabasePool () {
dispatch_queue_t _lockQueue;
NSMutableArray *_databaseInPool;
NSMutableArray *_databaseOutPool;
}
- (void)pushDatabaseBackInPool:(FMDatabase*)db;
- (FMDatabase*)db;
@@ -30,15 +35,27 @@
@synthesize openFlags=_openFlags;
+ (instancetype)databasePoolWithPath:(NSString*)aPath {
+ (instancetype)databasePoolWithPath:(NSString *)aPath {
return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath]);
}
+ (instancetype)databasePoolWithPath:(NSString*)aPath flags:(int)openFlags {
+ (instancetype)databasePoolWithURL:(NSURL *)url {
return FMDBReturnAutoreleased([[self alloc] initWithPath:url.path]);
}
+ (instancetype)databasePoolWithPath:(NSString *)aPath flags:(int)openFlags {
return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath flags:openFlags]);
}
- (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags {
+ (instancetype)databasePoolWithURL:(NSURL *)url flags:(int)openFlags {
return FMDBReturnAutoreleased([[self alloc] initWithPath:url.path flags:openFlags]);
}
- (instancetype)initWithURL:(NSURL *)url flags:(int)openFlags vfs:(NSString *)vfsName {
return [self initWithPath:url.path flags:openFlags vfs:vfsName];
}
- (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags vfs:(NSString *)vfsName {
self = [super init];
@@ -48,21 +65,36 @@
_databaseInPool = FMDBReturnRetained([NSMutableArray array]);
_databaseOutPool = FMDBReturnRetained([NSMutableArray array]);
_openFlags = openFlags;
_vfsName = [vfsName copy];
}
return self;
}
- (instancetype)initWithPath:(NSString*)aPath
{
- (instancetype)initWithPath:(NSString *)aPath flags:(int)openFlags {
return [self initWithPath:aPath flags:openFlags vfs:nil];
}
- (instancetype)initWithURL:(NSURL *)url flags:(int)openFlags {
return [self initWithPath:url.path flags:openFlags vfs:nil];
}
- (instancetype)initWithPath:(NSString*)aPath {
// default flags for sqlite3_open
return [self initWithPath:aPath flags:SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE];
}
- (instancetype)initWithURL:(NSURL *)url {
return [self initWithPath:url.path];
}
- (instancetype)init {
return [self initWithPath:nil];
}
+ (Class)databaseClass {
return [FMDatabase class];
}
- (void)dealloc {
@@ -70,6 +102,7 @@
FMDBRelease(_path);
FMDBRelease(_databaseInPool);
FMDBRelease(_databaseOutPool);
FMDBRelease(_vfsName);
if (_lockQueue) {
FMDBDispatchQueueRelease(_lockQueue);
@@ -128,13 +161,13 @@
}
}
db = [FMDatabase databaseWithPath:self->_path];
db = [[[self class] databaseClass] databaseWithPath:self->_path];
shouldNotifyDelegate = YES;
}
//This ensures that the db is opened before returning
#if SQLITE_VERSION_NUMBER >= 3005000
BOOL success = [db openWithFlags:self->_openFlags];
BOOL success = [db openWithFlags:self->_openFlags vfs:self->_vfsName];
#else
BOOL success = [db open];
#endif

95
ios/Pods/FMDB/src/fmdb/FMDatabaseQueue.h generated Normal file → Executable file
View File

@@ -8,6 +8,8 @@
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@class FMDatabase;
/** To perform queries and updates on multiple threads, you'll want to use `FMDatabaseQueue`.
@@ -60,21 +62,19 @@
*/
@interface FMDatabaseQueue : NSObject {
NSString *_path;
dispatch_queue_t _queue;
FMDatabase *_db;
int _openFlags;
}
@interface FMDatabaseQueue : NSObject
/** Path of database */
@property (atomic, retain) NSString *path;
@property (atomic, retain, nullable) NSString *path;
/** Open flags */
@property (atomic, readonly) int openFlags;
/** Custom virtual file system name */
@property (atomic, copy, nullable) NSString *vfsName;
///----------------------------------------------------
/// @name Initialization, opening, and closing of queue
///----------------------------------------------------
@@ -86,35 +86,72 @@
@return The `FMDatabaseQueue` object. `nil` on error.
*/
+ (instancetype)databaseQueueWithPath:(NSString*)aPath;
+ (instancetype)databaseQueueWithPath:(NSString * _Nullable)aPath;
/** Create queue using file URL.
@param url The file `NSURL` of the database.
@return The `FMDatabaseQueue` object. `nil` on error.
*/
+ (instancetype)databaseQueueWithURL:(NSURL * _Nullable)url;
/** Create queue using path and specified flags.
@param aPath The file path of the database.
@param openFlags Flags passed to the openWithFlags method of the database
@param openFlags Flags passed to the openWithFlags method of the database.
@return The `FMDatabaseQueue` object. `nil` on error.
*/
+ (instancetype)databaseQueueWithPath:(NSString*)aPath flags:(int)openFlags;
+ (instancetype)databaseQueueWithPath:(NSString * _Nullable)aPath flags:(int)openFlags;
/** Create queue using file URL and specified flags.
@param url The file `NSURL` of the database.
@param openFlags Flags passed to the openWithFlags method of the database.
@return The `FMDatabaseQueue` object. `nil` on error.
*/
+ (instancetype)databaseQueueWithURL:(NSURL * _Nullable)url flags:(int)openFlags;
/** Create queue using path.
@param aPath The file path of the database.
@return The `FMDatabaseQueue` object. `nil` on error.
*/
- (instancetype)initWithPath:(NSString*)aPath;
- (instancetype)initWithPath:(NSString * _Nullable)aPath;
/** Create queue using file URL.
@param url The file `NSURL of the database.
@return The `FMDatabaseQueue` object. `nil` on error.
*/
- (instancetype)initWithURL:(NSURL * _Nullable)url;
/** Create queue using path and specified flags.
@param aPath The file path of the database.
@param openFlags Flags passed to the openWithFlags method of the database
@param openFlags Flags passed to the openWithFlags method of the database.
@return The `FMDatabaseQueue` object. `nil` on error.
*/
- (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags;
- (instancetype)initWithPath:(NSString * _Nullable)aPath flags:(int)openFlags;
/** Create queue using file URL and specified flags.
@param url The file path of the database.
@param openFlags Flags passed to the openWithFlags method of the database.
@return The `FMDatabaseQueue` object. `nil` on error.
*/
- (instancetype)initWithURL:(NSURL * _Nullable)url flags:(int)openFlags;
/** Create queue using path and specified flags.
@@ -125,7 +162,18 @@
@return The `FMDatabaseQueue` object. `nil` on error.
*/
- (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags vfs:(NSString *)vfsName;
- (instancetype)initWithPath:(NSString * _Nullable)aPath flags:(int)openFlags vfs:(NSString * _Nullable)vfsName;
/** Create queue using file URL and specified flags.
@param url The file `NSURL of the database.
@param openFlags Flags passed to the openWithFlags method of the database
@param vfsName The name of a custom virtual file system
@return The `FMDatabaseQueue` object. `nil` on error.
*/
- (instancetype)initWithURL:(NSURL * _Nullable)url flags:(int)openFlags vfs:(NSString * _Nullable)vfsName;
/** Returns the Class of 'FMDatabase' subclass, that will be used to instantiate database object.
@@ -140,6 +188,10 @@
- (void)close;
/** Interupt pending database operation. */
- (void)interrupt;
///-----------------------------------------------
/// @name Dispatching database operations to queue
///-----------------------------------------------
@@ -149,21 +201,21 @@
@param block The code to be run on the queue of `FMDatabaseQueue`
*/
- (void)inDatabase:(void (^)(FMDatabase *db))block;
- (void)inDatabase:(__attribute__((noescape)) void (^)(FMDatabase *db))block;
/** Synchronously perform database operations on queue, using transactions.
@param block The code to be run on the queue of `FMDatabaseQueue`
*/
- (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
- (void)inTransaction:(__attribute__((noescape)) void (^)(FMDatabase *db, BOOL *rollback))block;
/** Synchronously perform database operations on queue, using deferred transactions.
@param block The code to be run on the queue of `FMDatabaseQueue`
*/
- (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
- (void)inDeferredTransaction:(__attribute__((noescape)) void (^)(FMDatabase *db, BOOL *rollback))block;
///-----------------------------------------------
/// @name Dispatching database operations to queue
@@ -176,7 +228,8 @@
// NOTE: you can not nest these, since calling it will pull another database out of the pool and you'll get a deadlock.
// If you need to nest, use FMDatabase's startSavePointWithName:error: instead.
- (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block;
- (NSError * _Nullable)inSavePoint:(__attribute__((noescape)) void (^)(FMDatabase *db, BOOL *rollback))block;
@end
NS_ASSUME_NONNULL_END

57
ios/Pods/FMDB/src/fmdb/FMDatabaseQueue.m generated Normal file → Executable file
View File

@@ -29,14 +29,16 @@
* the queue's dispatch queue, which should not happen and causes a deadlock.
*/
static const void * const kDispatchQueueSpecificKey = &kDispatchQueueSpecificKey;
@interface FMDatabaseQueue () {
dispatch_queue_t _queue;
FMDatabase *_db;
}
@end
@implementation FMDatabaseQueue
@synthesize path = _path;
@synthesize openFlags = _openFlags;
+ (instancetype)databaseQueueWithPath:(NSString*)aPath {
+ (instancetype)databaseQueueWithPath:(NSString *)aPath {
FMDatabaseQueue *q = [[self alloc] initWithPath:aPath];
FMDBAutorelease(q);
@@ -44,8 +46,11 @@ static const void * const kDispatchQueueSpecificKey = &kDispatchQueueSpecificKey
return q;
}
+ (instancetype)databaseQueueWithPath:(NSString*)aPath flags:(int)openFlags {
+ (instancetype)databaseQueueWithURL:(NSURL *)url {
return [self databaseQueueWithPath:url.path];
}
+ (instancetype)databaseQueueWithPath:(NSString *)aPath flags:(int)openFlags {
FMDatabaseQueue *q = [[self alloc] initWithPath:aPath flags:openFlags];
FMDBAutorelease(q);
@@ -53,12 +58,19 @@ static const void * const kDispatchQueueSpecificKey = &kDispatchQueueSpecificKey
return q;
}
+ (instancetype)databaseQueueWithURL:(NSURL *)url flags:(int)openFlags {
return [self databaseQueueWithPath:url.path flags:openFlags];
}
+ (Class)databaseClass {
return [FMDatabase class];
}
- (instancetype)initWithURL:(NSURL *)url flags:(int)openFlags vfs:(NSString *)vfsName {
return [self initWithPath:url.path flags:openFlags vfs:vfsName];
}
- (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags vfs:(NSString *)vfsName {
self = [super init];
if (self != nil) {
@@ -82,17 +94,25 @@ static const void * const kDispatchQueueSpecificKey = &kDispatchQueueSpecificKey
_queue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL);
dispatch_queue_set_specific(_queue, kDispatchQueueSpecificKey, (__bridge void *)self, NULL);
_openFlags = openFlags;
_vfsName = [vfsName copy];
}
return self;
}
- (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags {
- (instancetype)initWithPath:(NSString *)aPath flags:(int)openFlags {
return [self initWithPath:aPath flags:openFlags vfs:nil];
}
- (instancetype)initWithPath:(NSString*)aPath {
- (instancetype)initWithURL:(NSURL *)url flags:(int)openFlags {
return [self initWithPath:url.path flags:openFlags vfs:nil];
}
- (instancetype)initWithURL:(NSURL *)url {
return [self initWithPath:url.path];
}
- (instancetype)initWithPath:(NSString *)aPath {
// default flags for sqlite3_open
return [self initWithPath:aPath flags:SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE vfs:nil];
}
@@ -103,9 +123,9 @@ static const void * const kDispatchQueueSpecificKey = &kDispatchQueueSpecificKey
- (void)dealloc {
FMDBRelease(_db);
FMDBRelease(_path);
FMDBRelease(_vfsName);
if (_queue) {
FMDBDispatchQueueRelease(_queue);
@@ -126,12 +146,16 @@ static const void * const kDispatchQueueSpecificKey = &kDispatchQueueSpecificKey
FMDBRelease(self);
}
- (void)interrupt {
[[self database] interrupt];
}
- (FMDatabase*)database {
if (!_db) {
_db = FMDBReturnRetained([FMDatabase databaseWithPath:_path]);
_db = FMDBReturnRetained([[[self class] databaseClass] databaseWithPath:_path]);
#if SQLITE_VERSION_NUMBER >= 3005000
BOOL success = [_db openWithFlags:_openFlags];
BOOL success = [_db openWithFlags:_openFlags vfs:_vfsName];
#else
BOOL success = [_db open];
#endif
@@ -147,10 +171,12 @@ static const void * const kDispatchQueueSpecificKey = &kDispatchQueueSpecificKey
}
- (void)inDatabase:(void (^)(FMDatabase *db))block {
#ifndef NDEBUG
/* Get the currently executing queue (which should probably be nil, but in theory could be another DB queue
* and then check it against self to make sure we're not about to deadlock. */
FMDatabaseQueue *currentSyncQueue = (__bridge id)dispatch_get_specific(kDispatchQueueSpecificKey);
assert(currentSyncQueue != self && "inDatabase: was called reentrantly on the same queue, which would lead to a deadlock");
#endif
FMDBRetain(self);
@@ -175,7 +201,6 @@ static const void * const kDispatchQueueSpecificKey = &kDispatchQueueSpecificKey
FMDBRelease(self);
}
- (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block {
FMDBRetain(self);
dispatch_sync(_queue, ^() {

View File

@@ -1,5 +1,7 @@
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
#ifndef __has_feature // Optional.
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
#endif
@@ -22,13 +24,9 @@
- `<FMDatabase>`
*/
@interface FMResultSet : NSObject {
FMDatabase *_parentDB;
FMStatement *_statement;
NSString *_query;
NSMutableDictionary *_columnNameToIndexMap;
}
@interface FMResultSet : NSObject
@property (nonatomic, retain, nullable) FMDatabase *parentDB;
///-----------------
/// @name Properties
@@ -36,7 +34,7 @@
/** Executed query */
@property (atomic, retain) NSString *query;
@property (atomic, retain, nullable) NSString *query;
/** `NSMutableDictionary` mapping column names to numeric index */
@@ -44,7 +42,7 @@
/** `FMStatement` used by result set. */
@property (atomic, retain) FMStatement *statement;
@property (atomic, retain, nullable) FMStatement *statement;
///------------------------------------
/// @name Creating and closing database
@@ -65,8 +63,6 @@
- (void)close;
- (void)setParentDB:(FMDatabase *)newDb;
///---------------------------------------
/// @name Iterating through the result set
///---------------------------------------
@@ -93,7 +89,7 @@
@see hasAnotherRow
*/
- (BOOL)nextWithError:(NSError **)outErr;
- (BOOL)nextWithError:(NSError * _Nullable *)outErr;
/** Did the last call to `<next>` succeed in retrieving another row?
@@ -115,7 +111,7 @@
@return Integer value of the number of columns.
*/
- (int)columnCount;
@property (nonatomic, readonly) int columnCount;
/** Column index for column name
@@ -133,7 +129,7 @@
@return columnName `NSString` value of the name of the column.
*/
- (NSString*)columnNameForIndex:(int)columnIdx;
- (NSString * _Nullable)columnNameForIndex:(int)columnIdx;
/** Result set integer value for column.
@@ -249,39 +245,39 @@
@param columnName `NSString` value of the name of the column.
@return `NSString` value of the result set's column.
@return String value of the result set's column.
*/
- (NSString*)stringForColumn:(NSString*)columnName;
- (NSString * _Nullable)stringForColumn:(NSString*)columnName;
/** Result set `NSString` value for column.
@param columnIdx Zero-based index for column.
@return `NSString` value of the result set's column.
@return String value of the result set's column.
*/
- (NSString*)stringForColumnIndex:(int)columnIdx;
- (NSString * _Nullable)stringForColumnIndex:(int)columnIdx;
/** Result set `NSDate` value for column.
@param columnName `NSString` value of the name of the column.
@return `NSDate` value of the result set's column.
@return Date value of the result set's column.
*/
- (NSDate*)dateForColumn:(NSString*)columnName;
- (NSDate * _Nullable)dateForColumn:(NSString*)columnName;
/** Result set `NSDate` value for column.
@param columnIdx Zero-based index for column.
@return `NSDate` value of the result set's column.
@return Date value of the result set's column.
*/
- (NSDate*)dateForColumnIndex:(int)columnIdx;
- (NSDate * _Nullable)dateForColumnIndex:(int)columnIdx;
/** Result set `NSData` value for column.
@@ -289,20 +285,20 @@
@param columnName `NSString` value of the name of the column.
@return `NSData` value of the result set's column.
@return Data value of the result set's column.
*/
- (NSData*)dataForColumn:(NSString*)columnName;
- (NSData * _Nullable)dataForColumn:(NSString*)columnName;
/** Result set `NSData` value for column.
@param columnIdx Zero-based index for column.
@return `NSData` value of the result set's column.
@return Data value of the result set's column.
*/
- (NSData*)dataForColumnIndex:(int)columnIdx;
- (NSData * _Nullable)dataForColumnIndex:(int)columnIdx;
/** Result set `(const unsigned char *)` value for column.
@@ -311,7 +307,9 @@
@return `(const unsigned char *)` value of the result set's column.
*/
- (const unsigned char *)UTF8StringForColumnName:(NSString*)columnName;
- (const unsigned char * _Nullable)UTF8StringForColumn:(NSString*)columnName;
- (const unsigned char * _Nullable)UTF8StringForColumnName:(NSString*)columnName __deprecated_msg("Use UTF8StringForColumn instead");
/** Result set `(const unsigned char *)` value for column.
@@ -320,18 +318,20 @@
@return `(const unsigned char *)` value of the result set's column.
*/
- (const unsigned char *)UTF8StringForColumnIndex:(int)columnIdx;
- (const unsigned char * _Nullable)UTF8StringForColumnIndex:(int)columnIdx;
/** Result set object for column.
@param columnName `NSString` value of the name of the column.
@param columnName Name of the column.
@return Either `NSNumber`, `NSString`, `NSData`, or `NSNull`. If the column was `NULL`, this returns `[NSNull null]` object.
@see objectForKeyedSubscript:
*/
- (id)objectForColumnName:(NSString*)columnName;
- (id _Nullable)objectForColumn:(NSString*)columnName;
- (id _Nullable)objectForColumnName:(NSString*)columnName __deprecated_msg("Use objectForColumn instead");
/** Result set object for column.
@@ -342,7 +342,7 @@
@see objectAtIndexedSubscript:
*/
- (id)objectForColumnIndex:(int)columnIdx;
- (id _Nullable)objectForColumnIndex:(int)columnIdx;
/** Result set object for column.
@@ -363,7 +363,7 @@
@return Either `NSNumber`, `NSString`, `NSData`, or `NSNull`. If the column was `NULL`, this returns `[NSNull null]` object.
*/
- (id)objectForKeyedSubscript:(NSString *)columnName;
- (id _Nullable)objectForKeyedSubscript:(NSString *)columnName;
/** Result set object for column.
@@ -384,13 +384,13 @@
@return Either `NSNumber`, `NSString`, `NSData`, or `NSNull`. If the column was `NULL`, this returns `[NSNull null]` object.
*/
- (id)objectAtIndexedSubscript:(int)columnIdx;
- (id _Nullable)objectAtIndexedSubscript:(int)columnIdx;
/** Result set `NSData` value for column.
@param columnName `NSString` value of the name of the column.
@return `NSData` value of the result set's column.
@return Data value of the result set's column.
@warning If you are going to use this data after you iterate over the next row, or after you close the
result set, make sure to make a copy of the data first (or just use `<dataForColumn:>`/`<dataForColumnIndex:>`)
@@ -398,13 +398,13 @@ If you don't, you're going to be in a world of hurt when you try and use the dat
*/
- (NSData*)dataNoCopyForColumn:(NSString*)columnName NS_RETURNS_NOT_RETAINED;
- (NSData * _Nullable)dataNoCopyForColumn:(NSString *)columnName NS_RETURNS_NOT_RETAINED;
/** Result set `NSData` value for column.
@param columnIdx Zero-based index for column.
@return `NSData` value of the result set's column.
@return Data value of the result set's column.
@warning If you are going to use this data after you iterate over the next row, or after you close the
result set, make sure to make a copy of the data first (or just use `<dataForColumn:>`/`<dataForColumnIndex:>`)
@@ -412,7 +412,7 @@ If you don't, you're going to be in a world of hurt when you try and use the dat
*/
- (NSData*)dataNoCopyForColumnIndex:(int)columnIdx NS_RETURNS_NOT_RETAINED;
- (NSData * _Nullable)dataNoCopyForColumnIndex:(int)columnIdx NS_RETURNS_NOT_RETAINED;
/** Is the column `NULL`?
@@ -435,12 +435,10 @@ If you don't, you're going to be in a world of hurt when you try and use the dat
/** Returns a dictionary of the row results mapped to case sensitive keys of the column names.
@returns `NSDictionary` of the row results.
@warning The keys to the dictionary are case sensitive of the column names.
*/
- (NSDictionary*)resultDictionary;
@property (nonatomic, readonly, nullable) NSDictionary *resultDictionary;
/** Returns a dictionary of the row results
@@ -449,7 +447,7 @@ If you don't, you're going to be in a world of hurt when you try and use the dat
@warning **Deprecated**: Please use `<resultDictionary>` instead. Also, beware that `<resultDictionary>` is case sensitive!
*/
- (NSDictionary*)resultDict __attribute__ ((deprecated));
- (NSDictionary * _Nullable)resultDict __deprecated_msg("Use resultDictionary instead");
///-----------------------------
/// @name Key value coding magic
@@ -466,3 +464,4 @@ If you don't, you're going to be in a world of hurt when you try and use the dat
@end
NS_ASSUME_NONNULL_END

View File

@@ -12,10 +12,12 @@
- (void)resultSetDidClose:(FMResultSet *)resultSet;
@end
@interface FMResultSet () {
NSMutableDictionary *_columnNameToIndexMap;
}
@end
@implementation FMResultSet
@synthesize query=_query;
@synthesize statement=_statement;
+ (instancetype)resultSetWithStatement:(FMStatement *)statement usingParentDatabase:(FMDatabase*)aDB {
@@ -30,10 +32,12 @@
return FMDBReturnAutoreleased(rs);
}
#if ! __has_feature(objc_arc)
- (void)finalize {
[self close];
[super finalize];
}
#endif
- (void)dealloc {
[self close];
@@ -98,7 +102,7 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-implementations"
- (NSDictionary*)resultDict {
- (NSDictionary *)resultDict {
NSUInteger num_cols = (NSUInteger)sqlite3_data_count([_statement statement]);
@@ -217,7 +221,7 @@
NSNumber *n = [[self columnNameToIndexMap] objectForKey:columnName];
if (n) {
if (n != nil) {
return [n intValue];
}
@@ -226,8 +230,6 @@
return -1;
}
- (int)intForColumn:(NSString*)columnName {
return [self intForColumnIndex:[self columnIndexForName:columnName]];
}
@@ -276,9 +278,9 @@
return sqlite3_column_double([_statement statement], columnIdx);
}
- (NSString*)stringForColumnIndex:(int)columnIdx {
- (NSString *)stringForColumnIndex:(int)columnIdx {
if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0) || columnIdx >= sqlite3_column_count([_statement statement])) {
return nil;
}
@@ -302,7 +304,7 @@
- (NSDate*)dateForColumnIndex:(int)columnIdx {
if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0) || columnIdx >= sqlite3_column_count([_statement statement])) {
return nil;
}
@@ -316,7 +318,7 @@
- (NSData*)dataForColumnIndex:(int)columnIdx {
if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0) || columnIdx >= sqlite3_column_count([_statement statement])) {
return nil;
}
@@ -337,7 +339,7 @@
- (NSData*)dataNoCopyForColumnIndex:(int)columnIdx {
if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0) || columnIdx >= sqlite3_column_count([_statement statement])) {
return nil;
}
@@ -360,18 +362,26 @@
- (const unsigned char *)UTF8StringForColumnIndex:(int)columnIdx {
if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0) || columnIdx >= sqlite3_column_count([_statement statement])) {
return nil;
}
return sqlite3_column_text([_statement statement], columnIdx);
}
- (const unsigned char *)UTF8StringForColumnName:(NSString*)columnName {
- (const unsigned char *)UTF8StringForColumn:(NSString*)columnName {
return [self UTF8StringForColumnIndex:[self columnIndexForName:columnName]];
}
- (const unsigned char *)UTF8StringForColumnName:(NSString*)columnName {
return [self UTF8StringForColumn:columnName];
}
- (id)objectForColumnIndex:(int)columnIdx {
if (columnIdx < 0 || columnIdx >= sqlite3_column_count([_statement statement])) {
return nil;
}
int columnType = sqlite3_column_type([_statement statement], columnIdx);
id returnValue = nil;
@@ -398,6 +408,10 @@
}
- (id)objectForColumnName:(NSString*)columnName {
return [self objectForColumn:columnName];
}
- (id)objectForColumn:(NSString*)columnName {
return [self objectForColumnIndex:[self columnIndexForName:columnName]];
}
@@ -406,16 +420,12 @@
return [NSString stringWithUTF8String: sqlite3_column_name([_statement statement], columnIdx)];
}
- (void)setParentDB:(FMDatabase *)newDb {
_parentDB = newDb;
}
- (id)objectAtIndexedSubscript:(int)columnIdx {
return [self objectForColumnIndex:columnIdx];
}
- (id)objectForKeyedSubscript:(NSString *)columnName {
return [self objectForColumnName:columnName];
return [self objectForColumn:columnName];
}