2025-04-22 21:36:41 -07:00
//
// FMDatabaseAdditions . m
// fmdb
//
// Created by August Mueller on 10 / 30 / 05.
// Copyright 2005 Flying Meat Inc . . All rights reserved .
//
# import "FMDatabase.h"
# import "FMDatabaseAdditions.h"
# import "TargetConditionals.h"
# import "sqlite3.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 : 0 x00 orDictionary : 0 x00 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 ;
}
/ *
2025-04-28 21:45:23 -07:00
get table with list of tables : result columns : type [ STRING ] , name [ STRING ] , tbl_name [ STRING ] , rootpage [ INTEGER ] , sql [ STRING ]
2025-04-22 21:36:41 -07:00
check if table exist in database ( patch from OZLB )
* /
- ( FMResultSet * ) getSchema {
2025-04-28 21:45:23 -07:00
// result columns : type [ STRING ] , name [ STRING ] , tbl_name [ STRING ] , rootpage [ INTEGER ] , sql [ STRING ]
2025-04-22 21:36:41 -07:00
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 ;
}
/ *
2025-04-28 21:45:23 -07:00
get table schema : result columns : cid [ INTEGER ] , name , type [ STRING ] , notnull [ INTEGER ] , dflt_value [ ] , pk [ INTEGER ]
2025-04-22 21:36:41 -07:00
* /
- ( FMResultSet * ) getTableSchema : ( NSString * ) tableName {
2025-04-28 21:45:23 -07:00
// result columns : cid [ INTEGER ] , name , type [ STRING ] , notnull [ INTEGER ] , dflt_value [ ] , pk [ INTEGER ]
2025-04-22 21:36:41 -07:00
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 ;
}
- ( void ) setApplicationID : ( uint32_t ) appID {
NSString * query = [ NSString stringWithFormat : @ "pragma application_id=%d" , appID ] ;
FMResultSet * rs = [ self executeQuery : query ] ;
[ rs next ] ;
[ rs close ] ;
}
# if TARGET_OS _MAC && ! TARGET_OS _IPHONE
- ( NSString * ) applicationIDString {
NSString * s = NSFileTypeForHFSTypeCode ( [ self applicationID ] ) ;
assert ( [ s length ] = = 6 ) ;
s = [ s substringWithRange : NSMakeRange ( 1 , 4 ) ] ;
return s ;
}
- ( 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
# endif
- ( uint32_t ) userVersion {
uint32_t r = 0 ;
FMResultSet * rs = [ self executeQuery : @ "pragma user_version" ] ;
if ( [ rs next ] ) {
r = ( uint32_t ) [ rs longLongIntForColumnIndex : 0 ] ;
}
[ rs close ] ;
return r ;
}
- ( void ) setUserVersion : ( uint32_t ) version {
NSString * query = [ NSString stringWithFormat : @ "pragma user_version = %d" , version ] ;
FMResultSet * rs = [ self executeQuery : query ] ;
[ rs next ] ;
[ rs close ] ;
}
# 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 ;
int rc = sqlite3_prepare _v2 ( [ self sqliteHandle ] , [ sql UTF8String ] , -1 , & pStmt , 0 ) ;
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