Added a new addition which can be used for reading and writing on disk databases to in memory databases.

This commit is contained in:
ccgus 2013-02-05 11:12:43 -08:00
parent 5a463d036d
commit bbca6425f3
4 changed files with 126 additions and 0 deletions

View File

@ -3,6 +3,9 @@ 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.
2013.02.05
Added an "extra" folder which contains additional things which might be useful for programmers, but which I don't think should be part of the standard classes. At this time- there's only a single category in there which will load and save an on disk database to an in memory database. Thanks to Peter Carr who provided these additions!
2013.01.31
Lazy init of columnNameToIndexMap in FMResultSet, and you are now able to use it before asking for any rows first. Thanks to Daniel Dickison for the patch!

View File

@ -35,5 +35,6 @@ Geoffrey Foster
Robert Ryan
Samuel Chen
Daniel Dickison
Peter Carr
Aaaaannnd, Gus Mueller (that's me!)

View File

@ -0,0 +1,26 @@
//
// FMDatabase+InMemoryOnDiskIO.h
// FMDB
//
// Created by Peter Carr on 6/12/12.
//
// I find there is a massive performance hit using an "on-disk" representation when
// constantly reading from or writing to the DB. If your machine has sufficient memory, you
// should get a significant performance boost using an "in-memory" representation. The FMDB
// warpper does not contain methods to load an "on-disk" representation into memory and
// similarly save an "in-memory" representation to disk. However, SQLite3 has built-in
// support for this functionality via its "Backup" API. Here, we extend the FMBD wrapper
// to include this functionality.
//
// http://www.sqlite.org/backup.html
#import "FMDatabase.h"
@interface FMDatabase (InMemoryOnDiskIO)
// Loads an on-disk representation into memory.
- (BOOL)readFromFile:(NSString*)filePath;
// Saves an in-memory representation to disk
- (BOOL)writeToFile:(NSString *)filePath;
@end

View File

@ -0,0 +1,96 @@
#import "FMDatabase+InMemoryOnDiskIO.h"
// http://www.sqlite.org/backup.html
static
int loadOrSaveDb(sqlite3 *pInMemory, const char *zFilename, int isSave)
{
int rc; /* Function return code */
sqlite3 *pFile; /* Database connection opened on zFilename */
sqlite3_backup *pBackup; /* Backup object used to copy data */
sqlite3 *pTo; /* Database to copy to (pFile or pInMemory) */
sqlite3 *pFrom; /* Database to copy from (pFile or pInMemory) */
/* Open the database file identified by zFilename. Exit early if this fails
** for any reason. */
rc = sqlite3_open(zFilename, &pFile);
if( rc==SQLITE_OK ){
/* If this is a 'load' operation (isSave==0), then data is copied
** from the database file just opened to database pInMemory.
** Otherwise, if this is a 'save' operation (isSave==1), then data
** is copied from pInMemory to pFile. Set the variables pFrom and
** pTo accordingly. */
pFrom = (isSave ? pInMemory : pFile);
pTo = (isSave ? pFile : pInMemory);
/* Set up the backup procedure to copy from the "main" database of
** connection pFile to the main database of connection pInMemory.
** If something goes wrong, pBackup will be set to NULL and an error
** code and message left in connection pTo.
**
** If the backup object is successfully created, call backup_step()
** to copy data from pFile to pInMemory. Then call backup_finish()
** to release resources associated with the pBackup object. If an
** error occurred, then an error code and message will be left in
** connection pTo. If no error occurred, then the error code belonging
** to pTo is set to SQLITE_OK.
*/
pBackup = sqlite3_backup_init(pTo, "main", pFrom, "main");
if( pBackup ){
(void)sqlite3_backup_step(pBackup, -1);
(void)sqlite3_backup_finish(pBackup);
}
rc = sqlite3_errcode(pTo);
}
/* Close the database connection opened on database file zFilename
** and return the result of this function. */
(void)sqlite3_close(pFile);
return rc;
}
@implementation FMDatabase (InMemoryOnDiskIO)
- (BOOL)readFromFile:(NSString*)filePath
{
// only attempt to load an on-disk representation for an in-memory database
if ( self->_databasePath != nil )
{
NSLog(@"Database is not an in-memory representation." );
return NO;
}
// and only if the database is open
if ( self->_db == nil )
{
NSLog(@"Invalid database connection." );
return NO;
}
return ( SQLITE_OK == loadOrSaveDb( self->_db, [filePath fileSystemRepresentation], false ) );
}
- (BOOL)writeToFile:(NSString *)filePath
{
// only attempt to save an on-disk representation for an in-memory database
if ( self->_databasePath != nil )
{
NSLog(@"Database is not an in-memory representation." );
return NO;
}
// and only if the database is open
if ( self->_db == nil )
{
NSLog(@"Invalid database connection." );
return NO;
}
// save the in-memory representation
return ( SQLITE_OK == loadOrSaveDb( self->_db, [filePath fileSystemRepresentation], true ) );
}
@end