Skip to content

Commit

Permalink
Changed the FMDatabase class to "JSTDatabase" - since folks who were …
Browse files Browse the repository at this point in the history
…already using FMDatabase would get warnings at runtime.

Updated the example as well.
  • Loading branch information
August Mueller committed Oct 14, 2009
1 parent b1cd362 commit 4843fe1
Show file tree
Hide file tree
Showing 11 changed files with 259 additions and 147 deletions.
22 changes: 20 additions & 2 deletions plugins/sqlite-fmdb-jstplugin/FMDB.bridgesupport
Expand Up @@ -4,7 +4,7 @@
<depends_on path='/System/Library/Frameworks/Foundation.framework'/>
<depends_on path='/System/Library/Frameworks/AppKit.framework'/>
<depends_on path='/System/Library/Frameworks/CoreFoundation.framework'/>
<class name='FMDatabase'>
<class name='JSTDatabase'>
<method selector='beginDeferredTransaction'>
<retval type='B'/>
</method>
Expand Down Expand Up @@ -32,6 +32,9 @@
<method selector='executeUpdate:arguments:'>
<retval type='B'/>
</method>
<method selector='executeUpdate:withArgumentsInArray:'>
<retval type='B'/>
</method>
<method selector='goodConnection'>
<retval type='B'/>
</method>
Expand All @@ -52,6 +55,9 @@
<method selector='open'>
<retval type='B'/>
</method>
<method selector='openWithFlags:'>
<retval type='B'/>
</method>
<method selector='rekey:'>
<retval type='B'/>
</method>
Expand Down Expand Up @@ -86,17 +92,29 @@
<retval type='B'/>
</method>
<method variadic='true' selector='stringForQuery:'/>
<method selector='tableExists:'>
<retval type='B'/>
</method>
<method selector='traceExecution'>
<retval type='B'/>
</method>
</class>
<class name='FMResultSet'>
<class name='JSTResultSet'>
<method selector='boolForColumn:'>
<retval type='B'/>
</method>
<method selector='boolForColumnIndex:'>
<retval type='B'/>
</method>
<method selector='columnIndexIsNull:'>
<retval type='B'/>
</method>
<method selector='columnIsNull:'>
<retval type='B'/>
</method>
<method selector='hasAnotherRow'>
<retval type='B'/>
</method>
<method selector='next'>
<retval type='B'/>
</method>
Expand Down
5 changes: 4 additions & 1 deletion plugins/sqlite-fmdb-jstplugin/FMDatabase.h
Expand Up @@ -2,7 +2,7 @@
#import "sqlite3.h"
#import "FMResultSet.h"

@interface FMDatabase : NSObject
@interface JSTDatabase : NSObject
{
sqlite3* db;
NSString* databasePath;
Expand All @@ -22,6 +22,9 @@
- (id)initWithPath:(NSString*)inPath;

- (BOOL) open;
#if SQLITE_VERSION_NUMBER >= 3005000
- (BOOL) openWithFlags:(int)flags;
#endif
- (void) close;
- (BOOL) goodConnection;
- (void) clearCachedStatements;
Expand Down
48 changes: 31 additions & 17 deletions plugins/sqlite-fmdb-jstplugin/FMDatabase.m
@@ -1,10 +1,10 @@
#import "FMDatabase.h"
#import "unistd.h"

@implementation FMDatabase
@implementation JSTDatabase

+ (id)databaseWithPath:(NSString*)aPath {
return [[[FMDatabase alloc] initWithPath:aPath] autorelease];
return [[[self alloc] initWithPath:aPath] autorelease];
}

- (id)initWithPath:(NSString*)aPath {
Expand Down Expand Up @@ -43,7 +43,7 @@ - (sqlite3*) sqliteHandle {
}

- (BOOL) open {
int err = sqlite3_open( [databasePath fileSystemRepresentation], &db );
int err = sqlite3_open([databasePath fileSystemRepresentation], &db );
if(err != SQLITE_OK) {
NSLog(@"error opening!: %d", err);
return NO;
Expand All @@ -52,6 +52,18 @@ - (BOOL) open {
return YES;
}

#if SQLITE_VERSION_NUMBER >= 3005000
- (BOOL) openWithFlags:(int)flags {
int err = sqlite3_open_v2([databasePath fileSystemRepresentation], &db, flags, NULL /* Name of VFS module to use */);
if(err != SQLITE_OK) {
NSLog(@"error opening!: %d", err);
return NO;
}
return YES;
}
#endif


- (void) close {

[self clearCachedStatements];
Expand Down Expand Up @@ -148,7 +160,7 @@ - (BOOL) goodConnection {
return NO;
}

FMResultSet *rs = [self executeQuery:@"select name from sqlite_master where type='table'"];
JSTResultSet *rs = [self executeQuery:@"select name from sqlite_master where type='table'"];

if (rs) {
[rs close];
Expand All @@ -159,10 +171,10 @@ - (BOOL) goodConnection {
}

- (void) compainAboutInUse {
NSLog(@"The FMDatabase %@ is currently in use.", self);
NSLog(@"The JSTDatabase %@ is currently in use.", self);

if (crashOnErrors) {
NSAssert1(false, @"The FMDatabase %@ is currently in use.", self);
NSAssert1(false, @"The JSTDatabase %@ is currently in use.", self);
}
}

Expand All @@ -171,7 +183,9 @@ - (NSString*) lastErrorMessage {
}

- (BOOL) hadError {
return ([self lastErrorCode] != SQLITE_OK);
int lastErrCode = [self lastErrorCode];

return (lastErrCode > SQLITE_OK && lastErrCode < SQLITE_ROW);
}

- (int) lastErrorCode {
Expand Down Expand Up @@ -241,7 +255,7 @@ - (id) executeQuery:(NSString *)sql arguments:(va_list)args {

[self setInUse:YES];

FMResultSet *rs = nil;
JSTResultSet *rs = nil;

int rc = 0x00;;
sqlite3_stmt *pStmt = 0x00;;
Expand All @@ -262,7 +276,7 @@ - (id) executeQuery:(NSString *)sql arguments:(va_list)args {
if (!pStmt) {
do {
retry = NO;
rc = sqlite3_prepare(db, [sql UTF8String], -1, &pStmt, 0);
rc = sqlite3_prepare_v2(db, [sql UTF8String], -1, &pStmt, 0);

if (SQLITE_BUSY == rc) {
retry = YES;
Expand All @@ -283,9 +297,9 @@ - (id) executeQuery:(NSString *)sql arguments:(va_list)args {
NSLog(@"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]);
NSLog(@"DB Query: %@", sql);
if (crashOnErrors) {
#ifdef __BIG_ENDIAN__
asm{ trap };
#endif
//#if defined(__BIG_ENDIAN__) && !TARGET_IPHONE_SIMULATOR
// asm{ trap };
//#endif
NSAssert2(false, @"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]);
}
}
Expand Down Expand Up @@ -334,7 +348,7 @@ - (id) executeQuery:(NSString *)sql arguments:(va_list)args {
}

// the statement gets close in rs's dealloc or [rs close];
rs = [FMResultSet resultSetWithStatement:statement usingParentDatabase:self];
rs = [JSTResultSet resultSetWithStatement:statement usingParentDatabase:self];
[rs setQuery:sql];

statement.useCount = statement.useCount + 1;
Expand Down Expand Up @@ -386,7 +400,7 @@ - (BOOL) executeUpdate:(NSString*)sql arguments:(va_list)args {

do {
retry = NO;
rc = sqlite3_prepare(db, [sql UTF8String], -1, &pStmt, 0);
rc = sqlite3_prepare_v2(db, [sql UTF8String], -1, &pStmt, 0);
if (SQLITE_BUSY == rc) {
retry = YES;
usleep(20);
Expand All @@ -406,9 +420,9 @@ - (BOOL) executeUpdate:(NSString*)sql arguments:(va_list)args {
NSLog(@"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]);
NSLog(@"DB Query: %@", sql);
if (crashOnErrors) {
#ifdef __BIG_ENDIAN__
asm{ trap };
#endif
//#if defined(__BIG_ENDIAN__) && !TARGET_IPHONE_SIMULATOR
// asm{ trap };
//#endif
NSAssert2(false, @"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]);
}
}
Expand Down
8 changes: 7 additions & 1 deletion plugins/sqlite-fmdb-jstplugin/FMDatabaseAdditions.h
Expand Up @@ -7,7 +7,7 @@
//

#import <Foundation/Foundation.h>
@interface FMDatabase (FMDatabaseAdditions)
@interface JSTDatabase (JSTDatabaseAdditions)


- (int) intForQuery:(NSString*)objs, ...;
Expand All @@ -21,4 +21,10 @@
// 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.

- (id)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments;
- (BOOL) executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments;

- (BOOL) tableExists:(NSString*)tableName;
- (JSTResultSet*) getDataBaseSchema:(NSString*)tableName;

@end
98 changes: 95 additions & 3 deletions plugins/sqlite-fmdb-jstplugin/FMDatabaseAdditions.m
@@ -1,5 +1,5 @@
//
// FMDatabaseAdditions.m
// JSTDatabaseAdditions.m
// fmkit
//
// Created by August Mueller on 10/30/05.
Expand All @@ -9,12 +9,12 @@
#import "FMDatabase.h"
#import "FMDatabaseAdditions.h"

@implementation FMDatabase (FMDatabaseAdditions)
@implementation JSTDatabase (JSTDatabaseAdditions)

#define RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(type, sel) \
va_list args; \
va_start(args, query); \
FMResultSet *resultSet = [self executeQuery:query arguments:args]; \
JSTResultSet *resultSet = [self executeQuery:query arguments:args]; \
va_end(args); \
if (![resultSet next]) { return (type)0; } \
type ret = [resultSet sel:0]; \
Expand Down Expand Up @@ -48,4 +48,96 @@ - (NSData*)dataForQuery:(NSString*)query, ...; {
}


//From Phong Long:
//sometimes you want to be able generate queries programatically
//with an arbitrary number of arguments, as well as be able to bind
//them properly. this method allows you to pass in a query string with any
//number of ?, then you pass in an appropriate number of objects in an NSArray
//to executeQuery:arguments:

//this technique is being implemented as described by Matt Gallagher at
//http://cocoawithlove.com/2009/05/variable-argument-lists-in-cocoa.html

- (id)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments {

#ifdef __LP64__

NSLog(@"executeQuery:withArgumentsInArray: does not work when compiled as 64 bit");
// got a patch? send it gus@flyingmeat.com

return 0x00;

#else
id returnObject;

//also need make sure that everything in arguments is an Obj-C object
//or else argList will be the wrong size
NSUInteger argumentsCount = [arguments count];
char *argList = (char *)malloc(sizeof(id *) * argumentsCount);
[arguments getObjects:(id *)argList];

returnObject = [self executeQuery:sql arguments:argList];

free(argList);

return returnObject;
#endif
}

- (BOOL) executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments {

#ifdef __LP64__

NSLog(@"executeUpdate:withArgumentsInArray: does not work when compiled as 64 bit");
// got a patch? send it gus@flyingmeat.com

return 0x00;

#else

BOOL returnBool;

//also need make sure that everything in arguments is an Obj-C object
//or else argList will be the wrong size
NSUInteger argumentsCount = [arguments count];
char *argList = (char *)malloc(sizeof(id *) * argumentsCount);
[arguments getObjects:(id *)argList];

returnBool = [self executeUpdate:sql arguments:argList];

free(argList);

return returnBool;
#endif
}


//check if table exist in database (patch from OZLB)
- (BOOL) tableExists:(NSString*)tableName {

BOOL returnBool;
//lower case table name
tableName = [tableName lowercaseString];
//search in sqlite_master table if table exists
JSTResultSet *rs = [self executeQuery:@"select [sql] from sqlite_master where [type] = 'table' and lower(name) = ?", tableName];
//if at least one next exists, table exists
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)
- (JSTResultSet*) getDataBaseSchema:(NSString*)tableName {

//lower case table name
tableName = [tableName lowercaseString];
//result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING]
JSTResultSet *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;
}

@end

0 comments on commit 4843fe1

Please sign in to comment.