mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-08-31 21:41:33 +00:00
Adding fmdb.
This commit is contained in:
parent
8213b91b13
commit
c16b6dec2a
12 changed files with 4249 additions and 0 deletions
|
@ -270,6 +270,12 @@
|
|||
FF688E5316E6B8D0003B7B42 /* traverse_background@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FF688E5116E6B8D0003B7B42 /* traverse_background@2x.png */; };
|
||||
FF6A233216448E0700E15989 /* StoryPageControl.m in Sources */ = {isa = PBXBuildFile; fileRef = FF6A233116448E0700E15989 /* StoryPageControl.m */; };
|
||||
FF6A23391644957800E15989 /* StoryPageControl.xib in Resources */ = {isa = PBXBuildFile; fileRef = FF6A23361644903900E15989 /* StoryPageControl.xib */; };
|
||||
FF753CCE175858FC00344EC9 /* FMDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = FF753CC4175858FC00344EC9 /* FMDatabase.m */; };
|
||||
FF753CCF175858FC00344EC9 /* FMDatabaseAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = FF753CC6175858FC00344EC9 /* FMDatabaseAdditions.m */; };
|
||||
FF753CD0175858FC00344EC9 /* FMDatabasePool.m in Sources */ = {isa = PBXBuildFile; fileRef = FF753CC8175858FC00344EC9 /* FMDatabasePool.m */; };
|
||||
FF753CD1175858FC00344EC9 /* FMDatabaseQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = FF753CCA175858FC00344EC9 /* FMDatabaseQueue.m */; };
|
||||
FF753CD2175858FC00344EC9 /* fmdb.m in Sources */ = {isa = PBXBuildFile; fileRef = FF753CCB175858FC00344EC9 /* fmdb.m */; };
|
||||
FF753CD3175858FC00344EC9 /* FMResultSet.m in Sources */ = {isa = PBXBuildFile; fileRef = FF753CCD175858FC00344EC9 /* FMResultSet.m */; };
|
||||
FF793E1B13F1A9F700F282D2 /* ASIDataCompressor.m in Sources */ = {isa = PBXBuildFile; fileRef = FF793E1813F1A9F700F282D2 /* ASIDataCompressor.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||
FF793E1C13F1A9F700F282D2 /* ASIDataDecompressor.m in Sources */ = {isa = PBXBuildFile; fileRef = FF793E1A13F1A9F700F282D2 /* ASIDataDecompressor.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||
FF8364BB1755759A008F5C58 /* traverse_text.png in Resources */ = {isa = PBXBuildFile; fileRef = FF8364B91755759A008F5C58 /* traverse_text.png */; };
|
||||
|
@ -800,6 +806,17 @@
|
|||
FF6A233016448E0700E15989 /* StoryPageControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StoryPageControl.h; sourceTree = "<group>"; };
|
||||
FF6A233116448E0700E15989 /* StoryPageControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StoryPageControl.m; sourceTree = "<group>"; };
|
||||
FF6A23361644903900E15989 /* StoryPageControl.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = StoryPageControl.xib; path = ../Classes/StoryPageControl.xib; sourceTree = "<group>"; };
|
||||
FF753CC3175858FC00344EC9 /* FMDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMDatabase.h; sourceTree = "<group>"; };
|
||||
FF753CC4175858FC00344EC9 /* FMDatabase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMDatabase.m; sourceTree = "<group>"; };
|
||||
FF753CC5175858FC00344EC9 /* FMDatabaseAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMDatabaseAdditions.h; sourceTree = "<group>"; };
|
||||
FF753CC6175858FC00344EC9 /* FMDatabaseAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMDatabaseAdditions.m; sourceTree = "<group>"; };
|
||||
FF753CC7175858FC00344EC9 /* FMDatabasePool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMDatabasePool.h; sourceTree = "<group>"; };
|
||||
FF753CC8175858FC00344EC9 /* FMDatabasePool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMDatabasePool.m; sourceTree = "<group>"; };
|
||||
FF753CC9175858FC00344EC9 /* FMDatabaseQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMDatabaseQueue.h; sourceTree = "<group>"; };
|
||||
FF753CCA175858FC00344EC9 /* FMDatabaseQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMDatabaseQueue.m; sourceTree = "<group>"; };
|
||||
FF753CCB175858FC00344EC9 /* fmdb.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = fmdb.m; sourceTree = "<group>"; };
|
||||
FF753CCC175858FC00344EC9 /* FMResultSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMResultSet.h; sourceTree = "<group>"; };
|
||||
FF753CCD175858FC00344EC9 /* FMResultSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMResultSet.m; sourceTree = "<group>"; };
|
||||
FF793E1713F1A9F700F282D2 /* ASIDataCompressor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIDataCompressor.h; sourceTree = "<group>"; };
|
||||
FF793E1813F1A9F700F282D2 /* ASIDataCompressor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASIDataCompressor.m; sourceTree = "<group>"; };
|
||||
FF793E1913F1A9F700F282D2 /* ASIDataDecompressor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIDataDecompressor.h; sourceTree = "<group>"; };
|
||||
|
@ -1137,6 +1154,7 @@
|
|||
29B97315FDCFA39411CA2CEA /* Other Sources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FF753CC2175858FC00344EC9 /* fmdb */,
|
||||
FFDC9F9616E8064C000D8E0C /* ShareThis */,
|
||||
FF22FE5316E53ADC0046165A /* Underscore */,
|
||||
43A4BABE15C8663600F3B8D4 /* Popover */,
|
||||
|
@ -1779,6 +1797,25 @@
|
|||
path = Reachability;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
FF753CC2175858FC00344EC9 /* fmdb */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FF753CC3175858FC00344EC9 /* FMDatabase.h */,
|
||||
FF753CC4175858FC00344EC9 /* FMDatabase.m */,
|
||||
FF753CC5175858FC00344EC9 /* FMDatabaseAdditions.h */,
|
||||
FF753CC6175858FC00344EC9 /* FMDatabaseAdditions.m */,
|
||||
FF753CC7175858FC00344EC9 /* FMDatabasePool.h */,
|
||||
FF753CC8175858FC00344EC9 /* FMDatabasePool.m */,
|
||||
FF753CC9175858FC00344EC9 /* FMDatabaseQueue.h */,
|
||||
FF753CCA175858FC00344EC9 /* FMDatabaseQueue.m */,
|
||||
FF753CCB175858FC00344EC9 /* fmdb.m */,
|
||||
FF753CCC175858FC00344EC9 /* FMResultSet.h */,
|
||||
FF753CCD175858FC00344EC9 /* FMResultSet.m */,
|
||||
);
|
||||
name = fmdb;
|
||||
path = "Other Sources/fmdb";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
FF9B565E16E810900054BF68 /* Assets */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -2500,6 +2537,12 @@
|
|||
FFDCA0BC16E80877000D8E0C /* NSData+Base64.m in Sources */,
|
||||
FFECD016172B0D4200D45A62 /* SafariService.m in Sources */,
|
||||
FFECD01D172B10BD00D45A62 /* SafariActivityItem.m in Sources */,
|
||||
FF753CCE175858FC00344EC9 /* FMDatabase.m in Sources */,
|
||||
FF753CCF175858FC00344EC9 /* FMDatabaseAdditions.m in Sources */,
|
||||
FF753CD0175858FC00344EC9 /* FMDatabasePool.m in Sources */,
|
||||
FF753CD1175858FC00344EC9 /* FMDatabaseQueue.m in Sources */,
|
||||
FF753CD2175858FC00344EC9 /* fmdb.m in Sources */,
|
||||
FF753CD3175858FC00344EC9 /* FMResultSet.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
218
media/ios/Other Sources/fmdb/FMDatabase.h
Executable file
218
media/ios/Other Sources/fmdb/FMDatabase.h
Executable file
|
@ -0,0 +1,218 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
#import "sqlite3.h"
|
||||
#import "FMResultSet.h"
|
||||
#import "FMDatabasePool.h"
|
||||
|
||||
|
||||
#if ! __has_feature(objc_arc)
|
||||
#define FMDBAutorelease(__v) ([__v autorelease]);
|
||||
#define FMDBReturnAutoreleased FMDBAutorelease
|
||||
|
||||
#define FMDBRetain(__v) ([__v retain]);
|
||||
#define FMDBReturnRetained FMDBRetain
|
||||
|
||||
#define FMDBRelease(__v) ([__v release]);
|
||||
|
||||
#define FMDBDispatchQueueRelease(__v) (dispatch_release(__v));
|
||||
#else
|
||||
// -fobjc-arc
|
||||
#define FMDBAutorelease(__v)
|
||||
#define FMDBReturnAutoreleased(__v) (__v)
|
||||
|
||||
#define FMDBRetain(__v)
|
||||
#define FMDBReturnRetained(__v) (__v)
|
||||
|
||||
#define FMDBRelease(__v)
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
// Compiling for iOS
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000
|
||||
// iOS 6.0 or later
|
||||
#define FMDBDispatchQueueRelease(__v)
|
||||
#else
|
||||
// iOS 5.X or earlier
|
||||
#define FMDBDispatchQueueRelease(__v) (dispatch_release(__v));
|
||||
#endif
|
||||
#else
|
||||
// Compiling for Mac OS X
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
|
||||
// Mac OS X 10.8 or later
|
||||
#define FMDBDispatchQueueRelease(__v)
|
||||
#else
|
||||
// Mac OS X 10.7 or earlier
|
||||
#define FMDBDispatchQueueRelease(__v) (dispatch_release(__v));
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@interface FMDatabase : NSObject {
|
||||
|
||||
sqlite3* _db;
|
||||
NSString* _databasePath;
|
||||
BOOL _logsErrors;
|
||||
BOOL _crashOnErrors;
|
||||
BOOL _traceExecution;
|
||||
BOOL _checkedOut;
|
||||
BOOL _shouldCacheStatements;
|
||||
BOOL _isExecutingStatement;
|
||||
BOOL _inTransaction;
|
||||
int _busyRetryTimeout;
|
||||
|
||||
NSMutableDictionary *_cachedStatements;
|
||||
NSMutableSet *_openResultSets;
|
||||
NSMutableSet *_openFunctions;
|
||||
|
||||
NSDateFormatter *_dateFormat;
|
||||
}
|
||||
|
||||
|
||||
@property (atomic, assign) BOOL traceExecution;
|
||||
@property (atomic, assign) BOOL checkedOut;
|
||||
@property (atomic, assign) int busyRetryTimeout;
|
||||
@property (atomic, assign) BOOL crashOnErrors;
|
||||
@property (atomic, assign) BOOL logsErrors;
|
||||
@property (atomic, retain) NSMutableDictionary *cachedStatements;
|
||||
|
||||
+ (id)databaseWithPath:(NSString*)inPath;
|
||||
- (id)initWithPath:(NSString*)inPath;
|
||||
|
||||
- (BOOL)open;
|
||||
#if SQLITE_VERSION_NUMBER >= 3005000
|
||||
- (BOOL)openWithFlags:(int)flags;
|
||||
#endif
|
||||
- (BOOL)close;
|
||||
- (BOOL)goodConnection;
|
||||
- (void)clearCachedStatements;
|
||||
- (void)closeOpenResultSets;
|
||||
- (BOOL)hasOpenResultSets;
|
||||
|
||||
// encryption methods. You need to have purchased the sqlite encryption extensions for these to work.
|
||||
- (BOOL)setKey:(NSString*)key;
|
||||
- (BOOL)rekey:(NSString*)key;
|
||||
- (BOOL)setKeyWithData:(NSData *)keyData;
|
||||
- (BOOL)rekeyWithData:(NSData *)keyData;
|
||||
|
||||
- (NSString *)databasePath;
|
||||
|
||||
- (NSString*)lastErrorMessage;
|
||||
|
||||
- (int)lastErrorCode;
|
||||
- (BOOL)hadError;
|
||||
- (NSError*)lastError;
|
||||
|
||||
- (sqlite_int64)lastInsertRowId;
|
||||
|
||||
- (sqlite3*)sqliteHandle;
|
||||
|
||||
- (BOOL)update:(NSString*)sql withErrorAndBindings:(NSError**)outErr, ...;
|
||||
- (BOOL)executeUpdate:(NSString*)sql, ...;
|
||||
- (BOOL)executeUpdateWithFormat:(NSString *)format, ...;
|
||||
- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments;
|
||||
- (BOOL)executeUpdate:(NSString*)sql withParameterDictionary:(NSDictionary *)arguments;
|
||||
|
||||
- (FMResultSet *)executeQuery:(NSString*)sql, ...;
|
||||
- (FMResultSet *)executeQueryWithFormat:(NSString*)format, ...;
|
||||
- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments;
|
||||
- (FMResultSet *)executeQuery:(NSString *)sql withParameterDictionary:(NSDictionary *)arguments;
|
||||
|
||||
- (BOOL)rollback;
|
||||
- (BOOL)commit;
|
||||
- (BOOL)beginTransaction;
|
||||
- (BOOL)beginDeferredTransaction;
|
||||
- (BOOL)inTransaction;
|
||||
- (BOOL)shouldCacheStatements;
|
||||
- (void)setShouldCacheStatements:(BOOL)value;
|
||||
|
||||
#if SQLITE_VERSION_NUMBER >= 3007000
|
||||
- (BOOL)startSavePointWithName:(NSString*)name error:(NSError**)outErr;
|
||||
- (BOOL)releaseSavePointWithName:(NSString*)name error:(NSError**)outErr;
|
||||
- (BOOL)rollbackToSavePointWithName:(NSString*)name error:(NSError**)outErr;
|
||||
- (NSError*)inSavePoint:(void (^)(BOOL *rollback))block;
|
||||
#endif
|
||||
|
||||
+ (BOOL)isSQLiteThreadSafe;
|
||||
+ (NSString*)sqliteLibVersion;
|
||||
|
||||
- (int)changes;
|
||||
|
||||
- (void)makeFunctionNamed:(NSString*)name maximumArguments:(int)count withBlock:(void (^)(sqlite3_context *context, int argc, sqlite3_value **argv))block;
|
||||
|
||||
|
||||
|
||||
/** Generate an NSDateFormat that won't be broken by timezone or locale changes.
|
||||
|
||||
Use this method to generate values to set the dateFormat property.
|
||||
|
||||
@param dateFormat A valid NSDateFormatter format string.
|
||||
|
||||
Example:
|
||||
|
||||
myDB.dateFormat = [FMDatabase storeableDateFormat:@"yyyy-MM-dd HH:mm:ss"];
|
||||
|
||||
Note that NSDateFormatter is not thread-safe, so the formatter generated by this method should be assigned to only one FMDB instance and should not be used for other purposes.
|
||||
|
||||
*/
|
||||
+ (NSDateFormatter *)storeableDateFormat:(NSString *)format;
|
||||
|
||||
|
||||
/** Test whether the database has a date formatter assigned.
|
||||
|
||||
*/
|
||||
- (BOOL)hasDateFormatter;
|
||||
|
||||
|
||||
/** Set to a date formatter to use string dates with sqlite instead of the default UNIX timestamps.
|
||||
|
||||
Set to nil to use UNIX timestamps.
|
||||
|
||||
Defaults to nil.
|
||||
|
||||
Should be set using a formatter generated using FMDatabase::storeableDateFormat.
|
||||
|
||||
Note there is no direct getter for the NSDateFormatter, and you should not use the formatter you pass to FMDB for other purposes, as NSDateFormatter is not thread-safe.
|
||||
|
||||
*/
|
||||
- (void)setDateFormat:(NSDateFormatter *)format;
|
||||
|
||||
|
||||
/** Convert the supplied NSString to NSDate, using the current database formatter.
|
||||
|
||||
Returns nil if no formatter is set.
|
||||
|
||||
*/
|
||||
- (NSDate *)dateFromString:(NSString *)s;
|
||||
|
||||
/** Convert the supplied NSDate to NSString, using the current database formatter.
|
||||
|
||||
Returns nil if no formatter is set.
|
||||
|
||||
*/
|
||||
- (NSString *)stringFromDate:(NSDate *)date;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@interface FMStatement : NSObject {
|
||||
sqlite3_stmt *_statement;
|
||||
NSString *_query;
|
||||
long _useCount;
|
||||
}
|
||||
|
||||
@property (atomic, assign) long useCount;
|
||||
@property (atomic, retain) NSString *query;
|
||||
@property (atomic, assign) sqlite3_stmt *statement;
|
||||
|
||||
- (void)close;
|
||||
- (void)reset;
|
||||
|
||||
@end
|
||||
|
1227
media/ios/Other Sources/fmdb/FMDatabase.m
Executable file
1227
media/ios/Other Sources/fmdb/FMDatabase.m
Executable file
File diff suppressed because it is too large
Load diff
47
media/ios/Other Sources/fmdb/FMDatabaseAdditions.h
Executable file
47
media/ios/Other Sources/fmdb/FMDatabaseAdditions.h
Executable file
|
@ -0,0 +1,47 @@
|
|||
//
|
||||
// FMDatabaseAdditions.h
|
||||
// fmkit
|
||||
//
|
||||
// Created by August Mueller on 10/30/05.
|
||||
// Copyright 2005 Flying Meat Inc.. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
@interface FMDatabase (FMDatabaseAdditions)
|
||||
|
||||
|
||||
- (int)intForQuery:(NSString*)objs, ...;
|
||||
- (long)longForQuery:(NSString*)objs, ...;
|
||||
- (BOOL)boolForQuery:(NSString*)objs, ...;
|
||||
- (double)doubleForQuery:(NSString*)objs, ...;
|
||||
- (NSString*)stringForQuery:(NSString*)objs, ...;
|
||||
- (NSData*)dataForQuery:(NSString*)objs, ...;
|
||||
- (NSDate*)dateForQuery:(NSString*)objs, ...;
|
||||
|
||||
// Notice that there's no dataNoCopyForQuery:.
|
||||
// That would be a bad idea, because we close out the result set, and then what
|
||||
// happens to the data that we just didn't copy? Who knows, not I.
|
||||
|
||||
|
||||
- (BOOL)tableExists:(NSString*)tableName;
|
||||
- (FMResultSet*)getSchema;
|
||||
- (FMResultSet*)getTableSchema:(NSString*)tableName;
|
||||
|
||||
- (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName;
|
||||
|
||||
- (BOOL)validateSQL:(NSString*)sql error:(NSError**)error;
|
||||
|
||||
|
||||
#if SQLITE_VERSION_NUMBER >= 3007017
|
||||
- (uint32_t)applicationID;
|
||||
- (void)setApplicationID:(uint32_t)appID;
|
||||
|
||||
- (NSString*)applicationIDString;
|
||||
- (void)setApplicationIDString:(NSString*)s;
|
||||
#endif
|
||||
|
||||
|
||||
// deprecated - use columnExists:inTableWithName: instead.
|
||||
- (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __attribute__ ((deprecated));
|
||||
|
||||
@end
|
209
media/ios/Other Sources/fmdb/FMDatabaseAdditions.m
Executable file
209
media/ios/Other Sources/fmdb/FMDatabaseAdditions.m
Executable file
|
@ -0,0 +1,209 @@
|
|||
//
|
||||
// FMDatabaseAdditions.m
|
||||
// fmkit
|
||||
//
|
||||
// Created by August Mueller on 10/30/05.
|
||||
// Copyright 2005 Flying Meat Inc.. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FMDatabase.h"
|
||||
#import "FMDatabaseAdditions.h"
|
||||
|
||||
@interface FMDatabase (PrivateStuff)
|
||||
- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args;
|
||||
@end
|
||||
|
||||
@implementation FMDatabase (FMDatabaseAdditions)
|
||||
|
||||
#define RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(type, sel) \
|
||||
va_list args; \
|
||||
va_start(args, query); \
|
||||
FMResultSet *resultSet = [self executeQuery:query withArgumentsInArray:0x00 orDictionary:0x00 orVAList:args]; \
|
||||
va_end(args); \
|
||||
if (![resultSet next]) { return (type)0; } \
|
||||
type ret = [resultSet sel:0]; \
|
||||
[resultSet close]; \
|
||||
[resultSet setParentDB:nil]; \
|
||||
return ret;
|
||||
|
||||
|
||||
- (NSString*)stringForQuery:(NSString*)query, ... {
|
||||
RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSString *, stringForColumnIndex);
|
||||
}
|
||||
|
||||
- (int)intForQuery:(NSString*)query, ... {
|
||||
RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(int, intForColumnIndex);
|
||||
}
|
||||
|
||||
- (long)longForQuery:(NSString*)query, ... {
|
||||
RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(long, longForColumnIndex);
|
||||
}
|
||||
|
||||
- (BOOL)boolForQuery:(NSString*)query, ... {
|
||||
RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(BOOL, boolForColumnIndex);
|
||||
}
|
||||
|
||||
- (double)doubleForQuery:(NSString*)query, ... {
|
||||
RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(double, doubleForColumnIndex);
|
||||
}
|
||||
|
||||
- (NSData*)dataForQuery:(NSString*)query, ... {
|
||||
RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSData *, dataForColumnIndex);
|
||||
}
|
||||
|
||||
- (NSDate*)dateForQuery:(NSString*)query, ... {
|
||||
RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSDate *, dateForColumnIndex);
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)tableExists:(NSString*)tableName {
|
||||
|
||||
tableName = [tableName lowercaseString];
|
||||
|
||||
FMResultSet *rs = [self executeQuery:@"select [sql] from sqlite_master where [type] = 'table' and lower(name) = ?", tableName];
|
||||
|
||||
//if at least one next exists, table exists
|
||||
BOOL returnBool = [rs next];
|
||||
|
||||
//close and free object
|
||||
[rs close];
|
||||
|
||||
return returnBool;
|
||||
}
|
||||
|
||||
/*
|
||||
get table with list of tables: result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING]
|
||||
check if table exist in database (patch from OZLB)
|
||||
*/
|
||||
- (FMResultSet*)getSchema {
|
||||
|
||||
//result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING]
|
||||
FMResultSet *rs = [self executeQuery:@"SELECT type, name, tbl_name, rootpage, sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type != 'meta' AND name NOT LIKE 'sqlite_%' ORDER BY tbl_name, type DESC, name"];
|
||||
|
||||
return rs;
|
||||
}
|
||||
|
||||
/*
|
||||
get table schema: result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER]
|
||||
*/
|
||||
- (FMResultSet*)getTableSchema:(NSString*)tableName {
|
||||
|
||||
//result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER]
|
||||
FMResultSet *rs = [self executeQuery:[NSString stringWithFormat: @"PRAGMA table_info('%@')", tableName]];
|
||||
|
||||
return rs;
|
||||
}
|
||||
|
||||
- (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName {
|
||||
|
||||
BOOL returnBool = NO;
|
||||
|
||||
tableName = [tableName lowercaseString];
|
||||
columnName = [columnName lowercaseString];
|
||||
|
||||
FMResultSet *rs = [self getTableSchema:tableName];
|
||||
|
||||
//check if column is present in table schema
|
||||
while ([rs next]) {
|
||||
if ([[[rs stringForColumn:@"name"] lowercaseString] isEqualToString:columnName]) {
|
||||
returnBool = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//If this is not done FMDatabase instance stays out of pool
|
||||
[rs close];
|
||||
|
||||
return returnBool;
|
||||
}
|
||||
|
||||
#if SQLITE_VERSION_NUMBER >= 3007017
|
||||
- (uint32_t)applicationID {
|
||||
|
||||
uint32_t r = 0;
|
||||
|
||||
FMResultSet *rs = [self executeQuery:@"pragma application_id"];
|
||||
|
||||
if ([rs next]) {
|
||||
r = (uint32_t)[rs longLongIntForColumnIndex:0];
|
||||
}
|
||||
|
||||
[rs close];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
- (NSString*)applicationIDString {
|
||||
NSString *s = NSFileTypeForHFSTypeCode([self applicationID]);
|
||||
|
||||
assert([s length] == 6);
|
||||
|
||||
s = [s substringWithRange:NSMakeRange(1, 4)];
|
||||
|
||||
|
||||
return s;
|
||||
|
||||
}
|
||||
|
||||
- (void)setApplicationID:(uint32_t)appID {
|
||||
NSString *query = [NSString stringWithFormat:@"PRAGMA application_id=%d", appID];
|
||||
FMResultSet *rs = [self executeQuery:query];
|
||||
[rs next];
|
||||
[rs close];
|
||||
}
|
||||
|
||||
- (void)setApplicationIDString:(NSString*)s {
|
||||
|
||||
if ([s length] != 4) {
|
||||
NSLog(@"setApplicationIDString: string passed is not exactly 4 chars long. (was %ld)", [s length]);
|
||||
}
|
||||
|
||||
[self setApplicationID:NSHFSTypeCodeFromFileType([NSString stringWithFormat:@"'%@'", s])];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-implementations"
|
||||
|
||||
- (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __attribute__ ((deprecated)) {
|
||||
return [self columnExists:columnName inTableWithName:tableName];
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
- (BOOL)validateSQL:(NSString*)sql error:(NSError**)error {
|
||||
sqlite3_stmt *pStmt = NULL;
|
||||
BOOL validationSucceeded = YES;
|
||||
BOOL keepTrying = YES;
|
||||
int numberOfRetries = 0;
|
||||
|
||||
while (keepTrying == YES) {
|
||||
keepTrying = NO;
|
||||
int rc = sqlite3_prepare_v2(_db, [sql UTF8String], -1, &pStmt, 0);
|
||||
if (rc == SQLITE_BUSY || rc == SQLITE_LOCKED) {
|
||||
keepTrying = YES;
|
||||
usleep(20);
|
||||
|
||||
if (_busyRetryTimeout && (numberOfRetries++ > _busyRetryTimeout)) {
|
||||
NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [self databasePath]);
|
||||
NSLog(@"Database busy");
|
||||
}
|
||||
}
|
||||
else if (rc != SQLITE_OK) {
|
||||
validationSucceeded = NO;
|
||||
if (error) {
|
||||
*error = [NSError errorWithDomain:NSCocoaErrorDomain
|
||||
code:[self lastErrorCode]
|
||||
userInfo:[NSDictionary dictionaryWithObject:[self lastErrorMessage]
|
||||
forKey:NSLocalizedDescriptionKey]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_finalize(pStmt);
|
||||
|
||||
return validationSucceeded;
|
||||
}
|
||||
|
||||
@end
|
75
media/ios/Other Sources/fmdb/FMDatabasePool.h
Executable file
75
media/ios/Other Sources/fmdb/FMDatabasePool.h
Executable file
|
@ -0,0 +1,75 @@
|
|||
//
|
||||
// FMDatabasePool.h
|
||||
// fmdb
|
||||
//
|
||||
// Created by August Mueller on 6/22/11.
|
||||
// Copyright 2011 Flying Meat Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "sqlite3.h"
|
||||
|
||||
/*
|
||||
|
||||
***README OR SUFFER***
|
||||
Before using FMDatabasePool, please consider using FMDatabaseQueue instead.
|
||||
|
||||
If you really really really know what you're doing and FMDatabasePool is what
|
||||
you really really need (ie, you're using a read only database), OK you can use
|
||||
it. But just be careful not to deadlock!
|
||||
|
||||
For an example on deadlocking, search for:
|
||||
ONLY_USE_THE_POOL_IF_YOU_ARE_DOING_READS_OTHERWISE_YOULL_DEADLOCK_USE_FMDATABASEQUEUE_INSTEAD
|
||||
in the main.m file.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@class FMDatabase;
|
||||
|
||||
@interface FMDatabasePool : NSObject {
|
||||
NSString *_path;
|
||||
|
||||
dispatch_queue_t _lockQueue;
|
||||
|
||||
NSMutableArray *_databaseInPool;
|
||||
NSMutableArray *_databaseOutPool;
|
||||
|
||||
__unsafe_unretained id _delegate;
|
||||
|
||||
NSUInteger _maximumNumberOfDatabasesToCreate;
|
||||
}
|
||||
|
||||
@property (atomic, retain) NSString *path;
|
||||
@property (atomic, assign) id delegate;
|
||||
@property (atomic, assign) NSUInteger maximumNumberOfDatabasesToCreate;
|
||||
|
||||
+ (id)databasePoolWithPath:(NSString*)aPath;
|
||||
- (id)initWithPath:(NSString*)aPath;
|
||||
|
||||
- (NSUInteger)countOfCheckedInDatabases;
|
||||
- (NSUInteger)countOfCheckedOutDatabases;
|
||||
- (NSUInteger)countOfOpenDatabases;
|
||||
- (void)releaseAllDatabases;
|
||||
|
||||
- (void)inDatabase:(void (^)(FMDatabase *db))block;
|
||||
|
||||
- (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
|
||||
- (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
|
||||
|
||||
#if SQLITE_VERSION_NUMBER >= 3007000
|
||||
// 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;
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface NSObject (FMDatabasePoolDelegate)
|
||||
|
||||
- (BOOL)databasePool:(FMDatabasePool*)pool shouldAddDatabaseToPool:(FMDatabase*)database;
|
||||
|
||||
@end
|
||||
|
244
media/ios/Other Sources/fmdb/FMDatabasePool.m
Executable file
244
media/ios/Other Sources/fmdb/FMDatabasePool.m
Executable file
|
@ -0,0 +1,244 @@
|
|||
//
|
||||
// FMDatabasePool.m
|
||||
// fmdb
|
||||
//
|
||||
// Created by August Mueller on 6/22/11.
|
||||
// Copyright 2011 Flying Meat Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FMDatabasePool.h"
|
||||
#import "FMDatabase.h"
|
||||
|
||||
@interface FMDatabasePool()
|
||||
|
||||
- (void)pushDatabaseBackInPool:(FMDatabase*)db;
|
||||
- (FMDatabase*)db;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation FMDatabasePool
|
||||
@synthesize path=_path;
|
||||
@synthesize delegate=_delegate;
|
||||
@synthesize maximumNumberOfDatabasesToCreate=_maximumNumberOfDatabasesToCreate;
|
||||
|
||||
|
||||
+ (id)databasePoolWithPath:(NSString*)aPath {
|
||||
return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath]);
|
||||
}
|
||||
|
||||
- (id)initWithPath:(NSString*)aPath {
|
||||
|
||||
self = [super init];
|
||||
|
||||
if (self != nil) {
|
||||
_path = [aPath copy];
|
||||
_lockQueue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL);
|
||||
_databaseInPool = FMDBReturnRetained([NSMutableArray array]);
|
||||
_databaseOutPool = FMDBReturnRetained([NSMutableArray array]);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
|
||||
_delegate = 0x00;
|
||||
FMDBRelease(_path);
|
||||
FMDBRelease(_databaseInPool);
|
||||
FMDBRelease(_databaseOutPool);
|
||||
|
||||
if (_lockQueue) {
|
||||
FMDBDispatchQueueRelease(_lockQueue);
|
||||
_lockQueue = 0x00;
|
||||
}
|
||||
#if ! __has_feature(objc_arc)
|
||||
[super dealloc];
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
- (void)executeLocked:(void (^)(void))aBlock {
|
||||
dispatch_sync(_lockQueue, aBlock);
|
||||
}
|
||||
|
||||
- (void)pushDatabaseBackInPool:(FMDatabase*)db {
|
||||
|
||||
if (!db) { // db can be null if we set an upper bound on the # of databases to create.
|
||||
return;
|
||||
}
|
||||
|
||||
[self executeLocked:^() {
|
||||
|
||||
if ([_databaseInPool containsObject:db]) {
|
||||
[[NSException exceptionWithName:@"Database already in pool" reason:@"The FMDatabase being put back into the pool is already present in the pool" userInfo:nil] raise];
|
||||
}
|
||||
|
||||
[_databaseInPool addObject:db];
|
||||
[_databaseOutPool removeObject:db];
|
||||
|
||||
}];
|
||||
}
|
||||
|
||||
- (FMDatabase*)db {
|
||||
|
||||
__block FMDatabase *db;
|
||||
|
||||
[self executeLocked:^() {
|
||||
db = [_databaseInPool lastObject];
|
||||
|
||||
if (db) {
|
||||
[_databaseOutPool addObject:db];
|
||||
[_databaseInPool removeLastObject];
|
||||
}
|
||||
else {
|
||||
|
||||
if (_maximumNumberOfDatabasesToCreate) {
|
||||
NSUInteger currentCount = [_databaseOutPool count] + [_databaseInPool count];
|
||||
|
||||
if (currentCount >= _maximumNumberOfDatabasesToCreate) {
|
||||
NSLog(@"Maximum number of databases (%ld) has already been reached!", (long)currentCount);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
db = [FMDatabase databaseWithPath:_path];
|
||||
}
|
||||
|
||||
//This ensures that the db is opened before returning
|
||||
if ([db open]) {
|
||||
if ([_delegate respondsToSelector:@selector(databasePool:shouldAddDatabaseToPool:)] && ![_delegate databasePool:self shouldAddDatabaseToPool:db]) {
|
||||
[db close];
|
||||
db = 0x00;
|
||||
}
|
||||
else {
|
||||
//It should not get added in the pool twice if lastObject was found
|
||||
if (![_databaseOutPool containsObject:db]) {
|
||||
[_databaseOutPool addObject:db];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
NSLog(@"Could not open up the database at path %@", _path);
|
||||
db = 0x00;
|
||||
}
|
||||
}];
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
- (NSUInteger)countOfCheckedInDatabases {
|
||||
|
||||
__block NSUInteger count;
|
||||
|
||||
[self executeLocked:^() {
|
||||
count = [_databaseInPool count];
|
||||
}];
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
- (NSUInteger)countOfCheckedOutDatabases {
|
||||
|
||||
__block NSUInteger count;
|
||||
|
||||
[self executeLocked:^() {
|
||||
count = [_databaseOutPool count];
|
||||
}];
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
- (NSUInteger)countOfOpenDatabases {
|
||||
__block NSUInteger count;
|
||||
|
||||
[self executeLocked:^() {
|
||||
count = [_databaseOutPool count] + [_databaseInPool count];
|
||||
}];
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
- (void)releaseAllDatabases {
|
||||
[self executeLocked:^() {
|
||||
[_databaseOutPool removeAllObjects];
|
||||
[_databaseInPool removeAllObjects];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)inDatabase:(void (^)(FMDatabase *db))block {
|
||||
|
||||
FMDatabase *db = [self db];
|
||||
|
||||
block(db);
|
||||
|
||||
[self pushDatabaseBackInPool:db];
|
||||
}
|
||||
|
||||
- (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block {
|
||||
|
||||
BOOL shouldRollback = NO;
|
||||
|
||||
FMDatabase *db = [self db];
|
||||
|
||||
if (useDeferred) {
|
||||
[db beginDeferredTransaction];
|
||||
}
|
||||
else {
|
||||
[db beginTransaction];
|
||||
}
|
||||
|
||||
|
||||
block(db, &shouldRollback);
|
||||
|
||||
if (shouldRollback) {
|
||||
[db rollback];
|
||||
}
|
||||
else {
|
||||
[db commit];
|
||||
}
|
||||
|
||||
[self pushDatabaseBackInPool:db];
|
||||
}
|
||||
|
||||
- (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
|
||||
[self beginTransaction:YES withBlock:block];
|
||||
}
|
||||
|
||||
- (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
|
||||
[self beginTransaction:NO withBlock:block];
|
||||
}
|
||||
#if SQLITE_VERSION_NUMBER >= 3007000
|
||||
- (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block {
|
||||
|
||||
static unsigned long savePointIdx = 0;
|
||||
|
||||
NSString *name = [NSString stringWithFormat:@"savePoint%ld", savePointIdx++];
|
||||
|
||||
BOOL shouldRollback = NO;
|
||||
|
||||
FMDatabase *db = [self db];
|
||||
|
||||
NSError *err = 0x00;
|
||||
|
||||
if (![db startSavePointWithName:name error:&err]) {
|
||||
[self pushDatabaseBackInPool:db];
|
||||
return err;
|
||||
}
|
||||
|
||||
block(db, &shouldRollback);
|
||||
|
||||
if (shouldRollback) {
|
||||
[db rollbackToSavePointWithName:name error:&err];
|
||||
}
|
||||
else {
|
||||
[db releaseSavePointWithName:name error:&err];
|
||||
}
|
||||
|
||||
[self pushDatabaseBackInPool:db];
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
@end
|
38
media/ios/Other Sources/fmdb/FMDatabaseQueue.h
Executable file
38
media/ios/Other Sources/fmdb/FMDatabaseQueue.h
Executable file
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// FMDatabaseQueue.h
|
||||
// fmdb
|
||||
//
|
||||
// Created by August Mueller on 6/22/11.
|
||||
// Copyright 2011 Flying Meat Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "sqlite3.h"
|
||||
|
||||
@class FMDatabase;
|
||||
|
||||
@interface FMDatabaseQueue : NSObject {
|
||||
NSString *_path;
|
||||
dispatch_queue_t _queue;
|
||||
FMDatabase *_db;
|
||||
}
|
||||
|
||||
@property (atomic, retain) NSString *path;
|
||||
|
||||
+ (id)databaseQueueWithPath:(NSString*)aPath;
|
||||
- (id)initWithPath:(NSString*)aPath;
|
||||
- (void)close;
|
||||
|
||||
- (void)inDatabase:(void (^)(FMDatabase *db))block;
|
||||
|
||||
- (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
|
||||
- (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
|
||||
|
||||
#if SQLITE_VERSION_NUMBER >= 3007000
|
||||
// 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;
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
176
media/ios/Other Sources/fmdb/FMDatabaseQueue.m
Executable file
176
media/ios/Other Sources/fmdb/FMDatabaseQueue.m
Executable file
|
@ -0,0 +1,176 @@
|
|||
//
|
||||
// FMDatabaseQueue.m
|
||||
// fmdb
|
||||
//
|
||||
// Created by August Mueller on 6/22/11.
|
||||
// Copyright 2011 Flying Meat Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FMDatabaseQueue.h"
|
||||
#import "FMDatabase.h"
|
||||
|
||||
/*
|
||||
|
||||
Note: we call [self retain]; before using dispatch_sync, just incase
|
||||
FMDatabaseQueue is released on another thread and we're in the middle of doing
|
||||
something in dispatch_sync
|
||||
|
||||
*/
|
||||
|
||||
@implementation FMDatabaseQueue
|
||||
|
||||
@synthesize path = _path;
|
||||
|
||||
+ (id)databaseQueueWithPath:(NSString*)aPath {
|
||||
|
||||
FMDatabaseQueue *q = [[self alloc] initWithPath:aPath];
|
||||
|
||||
FMDBAutorelease(q);
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
- (id)initWithPath:(NSString*)aPath {
|
||||
|
||||
self = [super init];
|
||||
|
||||
if (self != nil) {
|
||||
|
||||
_db = [FMDatabase databaseWithPath:aPath];
|
||||
FMDBRetain(_db);
|
||||
|
||||
if (![_db open]) {
|
||||
NSLog(@"Could not create database queue for path %@", aPath);
|
||||
FMDBRelease(self);
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
_path = FMDBReturnRetained(aPath);
|
||||
|
||||
_queue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
|
||||
FMDBRelease(_db);
|
||||
FMDBRelease(_path);
|
||||
|
||||
if (_queue) {
|
||||
FMDBDispatchQueueRelease(_queue);
|
||||
_queue = 0x00;
|
||||
}
|
||||
#if ! __has_feature(objc_arc)
|
||||
[super dealloc];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)close {
|
||||
FMDBRetain(self);
|
||||
dispatch_sync(_queue, ^() {
|
||||
[_db close];
|
||||
FMDBRelease(_db);
|
||||
_db = 0x00;
|
||||
});
|
||||
FMDBRelease(self);
|
||||
}
|
||||
|
||||
- (FMDatabase*)database {
|
||||
if (!_db) {
|
||||
_db = FMDBReturnRetained([FMDatabase databaseWithPath:_path]);
|
||||
|
||||
if (![_db open]) {
|
||||
NSLog(@"FMDatabaseQueue could not reopen database for path %@", _path);
|
||||
FMDBRelease(_db);
|
||||
_db = 0x00;
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
return _db;
|
||||
}
|
||||
|
||||
- (void)inDatabase:(void (^)(FMDatabase *db))block {
|
||||
FMDBRetain(self);
|
||||
|
||||
dispatch_sync(_queue, ^() {
|
||||
|
||||
FMDatabase *db = [self database];
|
||||
block(db);
|
||||
|
||||
if ([db hasOpenResultSets]) {
|
||||
NSLog(@"Warning: there is at least one open result set around after performing [FMDatabaseQueue inDatabase:]");
|
||||
}
|
||||
});
|
||||
|
||||
FMDBRelease(self);
|
||||
}
|
||||
|
||||
|
||||
- (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block {
|
||||
FMDBRetain(self);
|
||||
dispatch_sync(_queue, ^() {
|
||||
|
||||
BOOL shouldRollback = NO;
|
||||
|
||||
if (useDeferred) {
|
||||
[[self database] beginDeferredTransaction];
|
||||
}
|
||||
else {
|
||||
[[self database] beginTransaction];
|
||||
}
|
||||
|
||||
block([self database], &shouldRollback);
|
||||
|
||||
if (shouldRollback) {
|
||||
[[self database] rollback];
|
||||
}
|
||||
else {
|
||||
[[self database] commit];
|
||||
}
|
||||
});
|
||||
|
||||
FMDBRelease(self);
|
||||
}
|
||||
|
||||
- (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
|
||||
[self beginTransaction:YES withBlock:block];
|
||||
}
|
||||
|
||||
- (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
|
||||
[self beginTransaction:NO withBlock:block];
|
||||
}
|
||||
|
||||
#if SQLITE_VERSION_NUMBER >= 3007000
|
||||
- (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block {
|
||||
|
||||
static unsigned long savePointIdx = 0;
|
||||
__block NSError *err = 0x00;
|
||||
FMDBRetain(self);
|
||||
dispatch_sync(_queue, ^() {
|
||||
|
||||
NSString *name = [NSString stringWithFormat:@"savePoint%ld", savePointIdx++];
|
||||
|
||||
BOOL shouldRollback = NO;
|
||||
|
||||
if ([[self database] startSavePointWithName:name error:&err]) {
|
||||
|
||||
block([self database], &shouldRollback);
|
||||
|
||||
if (shouldRollback) {
|
||||
[[self database] rollbackToSavePointWithName:name error:&err];
|
||||
}
|
||||
else {
|
||||
[[self database] releaseSavePointWithName:name error:&err];
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
FMDBRelease(self);
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
@end
|
104
media/ios/Other Sources/fmdb/FMResultSet.h
Executable file
104
media/ios/Other Sources/fmdb/FMResultSet.h
Executable file
|
@ -0,0 +1,104 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
#import "sqlite3.h"
|
||||
|
||||
#ifndef __has_feature // Optional.
|
||||
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
|
||||
#endif
|
||||
|
||||
#ifndef NS_RETURNS_NOT_RETAINED
|
||||
#if __has_feature(attribute_ns_returns_not_retained)
|
||||
#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))
|
||||
#else
|
||||
#define NS_RETURNS_NOT_RETAINED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@class FMDatabase;
|
||||
@class FMStatement;
|
||||
|
||||
@interface FMResultSet : NSObject {
|
||||
FMDatabase *_parentDB;
|
||||
FMStatement *_statement;
|
||||
|
||||
NSString *_query;
|
||||
NSMutableDictionary *_columnNameToIndexMap;
|
||||
}
|
||||
|
||||
@property (atomic, retain) NSString *query;
|
||||
@property (readonly) NSMutableDictionary *columnNameToIndexMap;
|
||||
@property (atomic, retain) FMStatement *statement;
|
||||
|
||||
+ (id)resultSetWithStatement:(FMStatement *)statement usingParentDatabase:(FMDatabase*)aDB;
|
||||
|
||||
- (void)close;
|
||||
|
||||
- (void)setParentDB:(FMDatabase *)newDb;
|
||||
|
||||
- (BOOL)next;
|
||||
- (BOOL)hasAnotherRow;
|
||||
|
||||
- (int)columnCount;
|
||||
|
||||
- (int)columnIndexForName:(NSString*)columnName;
|
||||
- (NSString*)columnNameForIndex:(int)columnIdx;
|
||||
|
||||
- (int)intForColumn:(NSString*)columnName;
|
||||
- (int)intForColumnIndex:(int)columnIdx;
|
||||
|
||||
- (long)longForColumn:(NSString*)columnName;
|
||||
- (long)longForColumnIndex:(int)columnIdx;
|
||||
|
||||
- (long long int)longLongIntForColumn:(NSString*)columnName;
|
||||
- (long long int)longLongIntForColumnIndex:(int)columnIdx;
|
||||
|
||||
- (unsigned long long int)unsignedLongLongIntForColumn:(NSString*)columnName;
|
||||
- (unsigned long long int)unsignedLongLongIntForColumnIndex:(int)columnIdx;
|
||||
|
||||
- (BOOL)boolForColumn:(NSString*)columnName;
|
||||
- (BOOL)boolForColumnIndex:(int)columnIdx;
|
||||
|
||||
- (double)doubleForColumn:(NSString*)columnName;
|
||||
- (double)doubleForColumnIndex:(int)columnIdx;
|
||||
|
||||
- (NSString*)stringForColumn:(NSString*)columnName;
|
||||
- (NSString*)stringForColumnIndex:(int)columnIdx;
|
||||
|
||||
- (NSDate*)dateForColumn:(NSString*)columnName;
|
||||
- (NSDate*)dateForColumnIndex:(int)columnIdx;
|
||||
|
||||
- (NSData*)dataForColumn:(NSString*)columnName;
|
||||
- (NSData*)dataForColumnIndex:(int)columnIdx;
|
||||
|
||||
- (const unsigned char *)UTF8StringForColumnIndex:(int)columnIdx;
|
||||
- (const unsigned char *)UTF8StringForColumnName:(NSString*)columnName;
|
||||
|
||||
// returns one of NSNumber, NSString, NSData, or NSNull
|
||||
- (id)objectForColumnName:(NSString*)columnName;
|
||||
- (id)objectForColumnIndex:(int)columnIdx;
|
||||
|
||||
- (id)objectForKeyedSubscript:(NSString *)columnName;
|
||||
- (id)objectAtIndexedSubscript:(int)columnIdx;
|
||||
|
||||
/*
|
||||
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:)
|
||||
If you don't, you're going to be in a world of hurt when you try and use the data.
|
||||
*/
|
||||
- (NSData*)dataNoCopyForColumn:(NSString*)columnName NS_RETURNS_NOT_RETAINED;
|
||||
- (NSData*)dataNoCopyForColumnIndex:(int)columnIdx NS_RETURNS_NOT_RETAINED;
|
||||
|
||||
- (BOOL)columnIndexIsNull:(int)columnIdx;
|
||||
- (BOOL)columnIsNull:(NSString*)columnName;
|
||||
|
||||
|
||||
/* Returns a dictionary of the row results mapped to case sensitive keys of the column names. */
|
||||
- (NSDictionary*)resultDictionary;
|
||||
|
||||
/* Please use resultDictionary instead. Also, beware that resultDictionary is case sensitive! */
|
||||
- (NSDictionary*)resultDict __attribute__ ((deprecated));
|
||||
|
||||
- (void)kvcMagic:(id)object;
|
||||
|
||||
|
||||
@end
|
||||
|
413
media/ios/Other Sources/fmdb/FMResultSet.m
Executable file
413
media/ios/Other Sources/fmdb/FMResultSet.m
Executable file
|
@ -0,0 +1,413 @@
|
|||
#import "FMResultSet.h"
|
||||
#import "FMDatabase.h"
|
||||
#import "unistd.h"
|
||||
|
||||
@interface FMDatabase ()
|
||||
- (void)resultSetDidClose:(FMResultSet *)resultSet;
|
||||
@end
|
||||
|
||||
|
||||
@implementation FMResultSet
|
||||
@synthesize query=_query;
|
||||
@synthesize statement=_statement;
|
||||
|
||||
+ (id)resultSetWithStatement:(FMStatement *)statement usingParentDatabase:(FMDatabase*)aDB {
|
||||
|
||||
FMResultSet *rs = [[FMResultSet alloc] init];
|
||||
|
||||
[rs setStatement:statement];
|
||||
[rs setParentDB:aDB];
|
||||
|
||||
return FMDBReturnAutoreleased(rs);
|
||||
}
|
||||
|
||||
- (void)finalize {
|
||||
[self close];
|
||||
[super finalize];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self close];
|
||||
|
||||
FMDBRelease(_query);
|
||||
_query = nil;
|
||||
|
||||
FMDBRelease(_columnNameToIndexMap);
|
||||
_columnNameToIndexMap = nil;
|
||||
|
||||
#if ! __has_feature(objc_arc)
|
||||
[super dealloc];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)close {
|
||||
[_statement reset];
|
||||
FMDBRelease(_statement);
|
||||
_statement = nil;
|
||||
|
||||
// we don't need this anymore... (i think)
|
||||
//[_parentDB setInUse:NO];
|
||||
[_parentDB resultSetDidClose:self];
|
||||
_parentDB = nil;
|
||||
}
|
||||
|
||||
- (int)columnCount {
|
||||
return sqlite3_column_count([_statement statement]);
|
||||
}
|
||||
|
||||
- (NSMutableDictionary *)columnNameToIndexMap {
|
||||
if (!_columnNameToIndexMap) {
|
||||
int columnCount = sqlite3_column_count([_statement statement]);
|
||||
_columnNameToIndexMap = [[NSMutableDictionary alloc] initWithCapacity:(NSUInteger)columnCount];
|
||||
int columnIdx = 0;
|
||||
for (columnIdx = 0; columnIdx < columnCount; columnIdx++) {
|
||||
[_columnNameToIndexMap setObject:[NSNumber numberWithInt:columnIdx]
|
||||
forKey:[[NSString stringWithUTF8String:sqlite3_column_name([_statement statement], columnIdx)] lowercaseString]];
|
||||
}
|
||||
}
|
||||
return _columnNameToIndexMap;
|
||||
}
|
||||
|
||||
- (void)kvcMagic:(id)object {
|
||||
|
||||
int columnCount = sqlite3_column_count([_statement statement]);
|
||||
|
||||
int columnIdx = 0;
|
||||
for (columnIdx = 0; columnIdx < columnCount; columnIdx++) {
|
||||
|
||||
const char *c = (const char *)sqlite3_column_text([_statement statement], columnIdx);
|
||||
|
||||
// check for a null row
|
||||
if (c) {
|
||||
NSString *s = [NSString stringWithUTF8String:c];
|
||||
|
||||
[object setValue:s forKey:[NSString stringWithUTF8String:sqlite3_column_name([_statement statement], columnIdx)]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-implementations"
|
||||
|
||||
- (NSDictionary*)resultDict {
|
||||
|
||||
NSUInteger num_cols = (NSUInteger)sqlite3_data_count([_statement statement]);
|
||||
|
||||
if (num_cols > 0) {
|
||||
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:num_cols];
|
||||
|
||||
NSEnumerator *columnNames = [[self columnNameToIndexMap] keyEnumerator];
|
||||
NSString *columnName = nil;
|
||||
while ((columnName = [columnNames nextObject])) {
|
||||
id objectValue = [self objectForColumnName:columnName];
|
||||
[dict setObject:objectValue forKey:columnName];
|
||||
}
|
||||
|
||||
return FMDBReturnAutoreleased([dict copy]);
|
||||
}
|
||||
else {
|
||||
NSLog(@"Warning: There seem to be no columns in this set.");
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
- (NSDictionary*)resultDictionary {
|
||||
|
||||
NSUInteger num_cols = (NSUInteger)sqlite3_data_count([_statement statement]);
|
||||
|
||||
if (num_cols > 0) {
|
||||
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:num_cols];
|
||||
|
||||
int columnCount = sqlite3_column_count([_statement statement]);
|
||||
|
||||
int columnIdx = 0;
|
||||
for (columnIdx = 0; columnIdx < columnCount; columnIdx++) {
|
||||
|
||||
NSString *columnName = [NSString stringWithUTF8String:sqlite3_column_name([_statement statement], columnIdx)];
|
||||
id objectValue = [self objectForColumnIndex:columnIdx];
|
||||
[dict setObject:objectValue forKey:columnName];
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
else {
|
||||
NSLog(@"Warning: There seem to be no columns in this set.");
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- (BOOL)next {
|
||||
|
||||
int rc;
|
||||
BOOL retry;
|
||||
int numberOfRetries = 0;
|
||||
do {
|
||||
retry = NO;
|
||||
|
||||
rc = sqlite3_step([_statement statement]);
|
||||
|
||||
if (SQLITE_BUSY == rc || SQLITE_LOCKED == rc) {
|
||||
// this will happen if the db is locked, like if we are doing an update or insert.
|
||||
// in that case, retry the step... and maybe wait just 10 milliseconds.
|
||||
retry = YES;
|
||||
if (SQLITE_LOCKED == rc) {
|
||||
rc = sqlite3_reset([_statement statement]);
|
||||
if (rc != SQLITE_LOCKED) {
|
||||
NSLog(@"Unexpected result from sqlite3_reset (%d) rs", rc);
|
||||
}
|
||||
}
|
||||
usleep(20);
|
||||
|
||||
if ([_parentDB busyRetryTimeout] && (numberOfRetries++ > [_parentDB busyRetryTimeout])) {
|
||||
|
||||
NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [_parentDB databasePath]);
|
||||
NSLog(@"Database busy");
|
||||
break;
|
||||
}
|
||||
}
|
||||
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]));
|
||||
break;
|
||||
}
|
||||
else if (SQLITE_MISUSE == rc) {
|
||||
// uh oh.
|
||||
NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([_parentDB sqliteHandle]));
|
||||
break;
|
||||
}
|
||||
else {
|
||||
// wtf?
|
||||
NSLog(@"Unknown error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([_parentDB sqliteHandle]));
|
||||
break;
|
||||
}
|
||||
|
||||
} while (retry);
|
||||
|
||||
|
||||
if (rc != SQLITE_ROW) {
|
||||
[self close];
|
||||
}
|
||||
|
||||
return (rc == SQLITE_ROW);
|
||||
}
|
||||
|
||||
- (BOOL)hasAnotherRow {
|
||||
return sqlite3_errcode([_parentDB sqliteHandle]) == SQLITE_ROW;
|
||||
}
|
||||
|
||||
- (int)columnIndexForName:(NSString*)columnName {
|
||||
columnName = [columnName lowercaseString];
|
||||
|
||||
NSNumber *n = [[self columnNameToIndexMap] objectForKey:columnName];
|
||||
|
||||
if (n) {
|
||||
return [n intValue];
|
||||
}
|
||||
|
||||
NSLog(@"Warning: I could not find the column named '%@'.", columnName);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (int)intForColumn:(NSString*)columnName {
|
||||
return [self intForColumnIndex:[self columnIndexForName:columnName]];
|
||||
}
|
||||
|
||||
- (int)intForColumnIndex:(int)columnIdx {
|
||||
return sqlite3_column_int([_statement statement], columnIdx);
|
||||
}
|
||||
|
||||
- (long)longForColumn:(NSString*)columnName {
|
||||
return [self longForColumnIndex:[self columnIndexForName:columnName]];
|
||||
}
|
||||
|
||||
- (long)longForColumnIndex:(int)columnIdx {
|
||||
return (long)sqlite3_column_int64([_statement statement], columnIdx);
|
||||
}
|
||||
|
||||
- (long long int)longLongIntForColumn:(NSString*)columnName {
|
||||
return [self longLongIntForColumnIndex:[self columnIndexForName:columnName]];
|
||||
}
|
||||
|
||||
- (long long int)longLongIntForColumnIndex:(int)columnIdx {
|
||||
return sqlite3_column_int64([_statement statement], columnIdx);
|
||||
}
|
||||
|
||||
- (unsigned long long int)unsignedLongLongIntForColumn:(NSString*)columnName {
|
||||
return [self unsignedLongLongIntForColumnIndex:[self columnIndexForName:columnName]];
|
||||
}
|
||||
|
||||
- (unsigned long long int)unsignedLongLongIntForColumnIndex:(int)columnIdx {
|
||||
return (unsigned long long int)[self longLongIntForColumnIndex:columnIdx];
|
||||
}
|
||||
|
||||
- (BOOL)boolForColumn:(NSString*)columnName {
|
||||
return [self boolForColumnIndex:[self columnIndexForName:columnName]];
|
||||
}
|
||||
|
||||
- (BOOL)boolForColumnIndex:(int)columnIdx {
|
||||
return ([self intForColumnIndex:columnIdx] != 0);
|
||||
}
|
||||
|
||||
- (double)doubleForColumn:(NSString*)columnName {
|
||||
return [self doubleForColumnIndex:[self columnIndexForName:columnName]];
|
||||
}
|
||||
|
||||
- (double)doubleForColumnIndex:(int)columnIdx {
|
||||
return sqlite3_column_double([_statement statement], columnIdx);
|
||||
}
|
||||
|
||||
- (NSString*)stringForColumnIndex:(int)columnIdx {
|
||||
|
||||
if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
const char *c = (const char *)sqlite3_column_text([_statement statement], columnIdx);
|
||||
|
||||
if (!c) {
|
||||
// null row.
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [NSString stringWithUTF8String:c];
|
||||
}
|
||||
|
||||
- (NSString*)stringForColumn:(NSString*)columnName {
|
||||
return [self stringForColumnIndex:[self columnIndexForName:columnName]];
|
||||
}
|
||||
|
||||
- (NSDate*)dateForColumn:(NSString*)columnName {
|
||||
return [self dateForColumnIndex:[self columnIndexForName:columnName]];
|
||||
}
|
||||
|
||||
- (NSDate*)dateForColumnIndex:(int)columnIdx {
|
||||
|
||||
if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [_parentDB hasDateFormatter] ? [_parentDB dateFromString:[self stringForColumnIndex:columnIdx]] : [NSDate dateWithTimeIntervalSince1970:[self doubleForColumnIndex:columnIdx]];
|
||||
}
|
||||
|
||||
|
||||
- (NSData*)dataForColumn:(NSString*)columnName {
|
||||
return [self dataForColumnIndex:[self columnIndexForName:columnName]];
|
||||
}
|
||||
|
||||
- (NSData*)dataForColumnIndex:(int)columnIdx {
|
||||
|
||||
if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
int dataSize = sqlite3_column_bytes([_statement statement], columnIdx);
|
||||
|
||||
NSMutableData *data = [NSMutableData dataWithLength:(NSUInteger)dataSize];
|
||||
|
||||
memcpy([data mutableBytes], sqlite3_column_blob([_statement statement], columnIdx), dataSize);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
- (NSData*)dataNoCopyForColumn:(NSString*)columnName {
|
||||
return [self dataNoCopyForColumnIndex:[self columnIndexForName:columnName]];
|
||||
}
|
||||
|
||||
- (NSData*)dataNoCopyForColumnIndex:(int)columnIdx {
|
||||
|
||||
if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
int dataSize = sqlite3_column_bytes([_statement statement], columnIdx);
|
||||
|
||||
NSData *data = [NSData dataWithBytesNoCopy:(void *)sqlite3_column_blob([_statement statement], columnIdx) length:(NSUInteger)dataSize freeWhenDone:NO];
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)columnIndexIsNull:(int)columnIdx {
|
||||
return sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL;
|
||||
}
|
||||
|
||||
- (BOOL)columnIsNull:(NSString*)columnName {
|
||||
return [self columnIndexIsNull:[self columnIndexForName:columnName]];
|
||||
}
|
||||
|
||||
- (const unsigned char *)UTF8StringForColumnIndex:(int)columnIdx {
|
||||
|
||||
if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
return sqlite3_column_text([_statement statement], columnIdx);
|
||||
}
|
||||
|
||||
- (const unsigned char *)UTF8StringForColumnName:(NSString*)columnName {
|
||||
return [self UTF8StringForColumnIndex:[self columnIndexForName:columnName]];
|
||||
}
|
||||
|
||||
- (id)objectForColumnIndex:(int)columnIdx {
|
||||
int columnType = sqlite3_column_type([_statement statement], columnIdx);
|
||||
|
||||
id returnValue = nil;
|
||||
|
||||
if (columnType == SQLITE_INTEGER) {
|
||||
returnValue = [NSNumber numberWithLongLong:[self longLongIntForColumnIndex:columnIdx]];
|
||||
}
|
||||
else if (columnType == SQLITE_FLOAT) {
|
||||
returnValue = [NSNumber numberWithDouble:[self doubleForColumnIndex:columnIdx]];
|
||||
}
|
||||
else if (columnType == SQLITE_BLOB) {
|
||||
returnValue = [self dataForColumnIndex:columnIdx];
|
||||
}
|
||||
else {
|
||||
//default to a string for everything else
|
||||
returnValue = [self stringForColumnIndex:columnIdx];
|
||||
}
|
||||
|
||||
if (returnValue == nil) {
|
||||
returnValue = [NSNull null];
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
- (id)objectForColumnName:(NSString*)columnName {
|
||||
return [self objectForColumnIndex:[self columnIndexForName:columnName]];
|
||||
}
|
||||
|
||||
// returns autoreleased NSString containing the name of the column in the result set
|
||||
- (NSString*)columnNameForIndex:(int)columnIdx {
|
||||
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];
|
||||
}
|
||||
|
||||
|
||||
@end
|
1455
media/ios/Other Sources/fmdb/fmdb.m
Executable file
1455
media/ios/Other Sources/fmdb/fmdb.m
Executable file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue