Sfoglia il codice sorgente

Added the ability to make custom sqlite functions from blocks.

August Mueller 14 anni fa
parent
commit
5f14e7da23
3 ha cambiato i file con 28 aggiunte e 4 eliminazioni
  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.
 
+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:
     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.

+ 3 - 2
src/FMDatabase.h

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

+ 19 - 2
src/FMDatabase.m

@@ -58,6 +58,7 @@ - (void)dealloc {
     FMDBRelease(_openResultSets);
     FMDBRelease(_cachedStatements);
     FMDBRelease(_databasePath);
+    FMDBRelease(_openFunctions);
     
     [self setPool:0x00];
     
@@ -1141,10 +1142,26 @@ - (void)setPool:(FMDatabasePool *)value {
 #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