Browse Source

Added the ability to make custom sqlite functions from blocks.

August Mueller 14 years ago
parent
commit
5f14e7da23
3 changed files with 28 additions and 4 deletions
  1. 6 0
      CHANGES_AND_TODO_LIST.txt
  2. 3 2
      src/FMDatabase.h
  3. 19 2
      src/FMDatabase.m

+ 6 - 0
CHANGES_AND_TODO_LIST.txt

@@ -3,6 +3,12 @@ Zip, nada, zilch.  Got any ideas?
 
 
 If you would like to contribute some code- awesome!  I just ask that you make it conform to the coding conventions already set in here, and to add a couple of tests for your new code to fmdb.m.  And of course, the code should be of general use to more than just a couple of folks.  Send your patches to gus@flyingmeat.com.
 If you would like to contribute some code- awesome!  I just ask that you make it conform to the coding conventions already set in here, and to add a couple of tests for your new code to fmdb.m.  And of course, the code should be of general use to more than just a couple of folks.  Send your patches to gus@flyingmeat.com.
 
 
+2012.01.06:
+    Added a new method to FMDatabase to make custom functions out of a block:
+    - (void)makeFunctionNamed:(NSString*)name maximumArguments:(int)count withBlock:(void (^)(sqlite3_context *context, int argc, sqlite3_value **argv))block
+    
+    Check out the function "testSQLiteFunction" in main.m for an example.
+
 2011.07.14:
 2011.07.14:
     Added methods for named parameters, using keys from an NSDictionary (Thanks to Drarok Ithaqua for the patches!)
     Added methods for named parameters, using keys from an NSDictionary (Thanks to Drarok Ithaqua for the patches!)
     Changed FMDatabase's "- (BOOL)update:(NSString*)sql error:(NSError**)outErr bind:(id)bindArgs, ... " to "- (BOOL)update:(NSString*)sql withErrorAndBindings:(NSError**)outErr, ..." as the previous method didn't actually work as advertised in the way it was written.  Thanks to @jaekwon for pointing this out.
     Changed FMDatabase's "- (BOOL)update:(NSString*)sql error:(NSError**)outErr bind:(id)bindArgs, ... " to "- (BOOL)update:(NSString*)sql withErrorAndBindings:(NSError**)outErr, ..." as the previous method didn't actually work as advertised in the way it was written.  Thanks to @jaekwon for pointing this out.

+ 3 - 2
src/FMDatabase.h

@@ -46,8 +46,9 @@
     
     
     NSMutableDictionary *_cachedStatements;
     NSMutableDictionary *_cachedStatements;
 	NSMutableSet        *_openResultSets;
 	NSMutableSet        *_openResultSets;
+	NSMutableSet        *_openFunctions;
 
 
-#ifdef FMDB_USE_WEAK_POOK
+#ifdef FMDB_USE_WEAK_POOL
     __weak FMDatabasePool *_poolAccessViaMethodOnly;
     __weak FMDatabasePool *_poolAccessViaMethodOnly;
 #else
 #else
     FMDatabasePool      *_poolAccessViaMethodOnly;
     FMDatabasePool      *_poolAccessViaMethodOnly;
@@ -133,7 +134,7 @@
 - (FMDatabasePool *)pool;
 - (FMDatabasePool *)pool;
 - (void)setPool:(FMDatabasePool *)value;
 - (void)setPool:(FMDatabasePool *)value;
 
 
-
+- (void)makeFunctionNamed:(NSString*)name maximumArguments:(int)count withBlock:(void (^)(sqlite3_context *context, int argc, sqlite3_value **argv))block;
 
 
 @end
 @end
 
 

+ 19 - 2
src/FMDatabase.m

@@ -58,6 +58,7 @@ - (void)dealloc {
     FMDBRelease(_openResultSets);
     FMDBRelease(_openResultSets);
     FMDBRelease(_cachedStatements);
     FMDBRelease(_cachedStatements);
     FMDBRelease(_databasePath);
     FMDBRelease(_databasePath);
+    FMDBRelease(_openFunctions);
     
     
     [self setPool:0x00];
     [self setPool:0x00];
     
     
@@ -1141,10 +1142,26 @@ - (void)setPool:(FMDatabasePool *)value {
 #endif
 #endif
 }
 }
 
 
+void FMDBBlockSQLiteCallBackFunction(sqlite3_context *context, int argc, sqlite3_value **argv);
+void FMDBBlockSQLiteCallBackFunction(sqlite3_context *context, int argc, sqlite3_value **argv) {
+    void (^block)(sqlite3_context *context, int argc, sqlite3_value **argv) = (__bridge id)sqlite3_user_data(context);    
+    block(context, argc, argv);
+}
 
 
 
 
-
-
+- (void)makeFunctionNamed:(NSString*)name maximumArguments:(int)count withBlock:(void (^)(sqlite3_context *context, int argc, sqlite3_value **argv))block {
+    
+    if (!_openFunctions) {
+        _openFunctions = [NSMutableSet new];
+    }
+    
+    id b = FMDBReturnAutoreleased([block copy]);
+    
+    [_openFunctions addObject:b];
+    
+    /* 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. */
+    sqlite3_create_function([self sqliteHandle], [name UTF8String], count, SQLITE_UTF8, (__bridge void*)b, &FMDBBlockSQLiteCallBackFunction, 0x00, 0x00);
+}
 
 
 @end
 @end