Skip to content

Instantly share code, notes, and snippets.

@Duraiamuthan
Created April 21, 2014 15:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Duraiamuthan/11146895 to your computer and use it in GitHub Desktop.
Save Duraiamuthan/11146895 to your computer and use it in GitHub Desktop.
SQLite Objective C Data Access Layer
//DAL.h
#import <UIKit/UIKit.h>
#import <sqlite3.h>
@interface DAL : NSObject
{
sqlite3* sqLiteObj;
NSString* dataBasePath;
}
@property(strong,nonatomic)NSString *DbName;
-(NSMutableArray *)RetrieveRecordswithSql:(NSString *)sql withColumnsCount:(NSNumber *)count andColumnsDelimiter:(NSString *)colDelimiter;
-(BOOL)handleDMLQuerywithSql:(NSString *)sql;
-(void)createEditableCopyOfDatabaseIfNeeded;
-(void)RemoveDBIfExists;
@end
//DAL.m
#import "DAL.h"
@interface DAL ()
-(void)CopyDB;
-(BOOL)IsDbAvailableAt:(NSString *)directory;
-(NSString *)GetMessageForFlagLevel:(NSString *)Flag;
-(NSString *)ConstructDbpathTo;
-(NSMutableString *)Coalesce:(const char*)colVal and:(NSString *)defaultVal;
@end
@implementation DAL
@synthesize DbName;
- (id)init
{
self = [super init];
if (self) {
}
return self;
}
- (void)createEditableCopyOfDatabaseIfNeeded
{
if(![self IsDbAvailableAt:@"DocumentsDirectory"])
{
[self CopyDB];
}
}
-(NSMutableArray *)RetrieveRecordswithSql:(NSString *)sql withColumnsCount:(NSNumber *)count andColumnsDelimiter:(NSString *)colDelimiter
{
NSMutableArray * retArr=[[NSMutableArray alloc]init];
if([self IsDbAvailableAt:@"DocumentsDirectory"])
{
const char *dbpath=[dataBasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &sqLiteObj)==SQLITE_OK)
{
const char *query_stmt=[sql UTF8String];
if (sqlite3_prepare(sqLiteObj, query_stmt, -1, &statement, NULL)==SQLITE_OK)
{
while(sqlite3_step(statement)==SQLITE_ROW)
{
const char* col_temp=(const char*)sqlite3_column_text(statement, 0);
NSMutableString *record=[self Coalesce:col_temp and:@"Empty"];
for (int i=1; i<count.integerValue; i++)
{
NSString * col=[self Coalesce:(const char*)sqlite3_column_text(statement, i) and:@"Empty"];
[record appendString:colDelimiter];
[record appendString:col];
}
[retArr addObject:record];
}
sqlite3_finalize(statement);
}
else
{
[self ThrowExceptionwithMessage:[self GetMessageForFlagLevel:@"sqlite3_prepare"] andSQL:sql];
}
}
else
{
[self ThrowExceptionwithMessage:[self GetMessageForFlagLevel:@"sqlite3_open"] andSQL:sql];
}
sqlite3_close(sqLiteObj);
}
else
{
[self CopyDB];
[self ThrowExceptionwithMessage:[self GetMessageForFlagLevel:@"DBfileExistsAtPath"] andSQL:sql];
}
return retArr;
}
-(void)ThrowExceptionwithMessage:(NSString*)Message andSQL:(NSString*)sql
{
NSLog(@"Message:%@ sql:%@",Message,sql);
@throw([NSException exceptionWithName:@"Sqlite related problem" reason:Message userInfo:@{@"SQL_SCRIPT":sql}]);
}
-(BOOL)handleDMLQuerywithSql:(NSString *)sql
{
if([self IsDbAvailableAt:@"DocumentsDirectory"])
{
const char *dbpath=[dataBasePath UTF8String];
if (sqlite3_open(dbpath, &sqLiteObj)==SQLITE_OK)
{
const char *insert_stmt=[sql UTF8String];
sqlite3_stmt *statement;
if(sqlite3_prepare(sqLiteObj, insert_stmt, -1, &statement, NULL)==SQLITE_OK)
{
int resFlag=sqlite3_step(statement);
if (resFlag==SQLITE_DONE)
{
sqlite3_reset(statement);
NSLog(@"sqlite3_errmsg:%s",sqlite3_errmsg(sqLiteObj));
sqlite3_finalize(statement);
sqlite3_close(sqLiteObj);
return TRUE;
}
else
{
sqlite3_finalize(statement);
sqlite3_close(sqLiteObj);
NSString *resultFlag=[[NSString alloc]initWithFormat:@"%d",resFlag];
[self ThrowExceptionwithMessage:[self GetMessageForFlagLevel:resultFlag] andSQL:sql];
return FALSE;
}
}
else
{
sqlite3_finalize(statement);
sqlite3_close(sqLiteObj);
[self ThrowExceptionwithMessage:[self GetMessageForFlagLevel:@"sqlite3_prepare"] andSQL:sql];
return FALSE;
}
}
else
{
[self ThrowExceptionwithMessage:[self GetMessageForFlagLevel:@"sqlite3_open"] andSQL:sql];
return FALSE;
}
}
else
{
[self ThrowExceptionwithMessage:[self GetMessageForFlagLevel:@"DBfileExistsAtPath"] andSQL:sql];
return false;
}
}
-(NSMutableString *)Coalesce:(const char*)colVal and:(NSMutableString *)defaultVal;
{
return colVal==NULL?[[NSMutableString alloc]initWithString:defaultVal]:[[NSMutableString alloc]initWithUTF8String:colVal];
}
-(BOOL)IsDbAvailableAt:(NSString *)directory;
{
NSFileManager *filemgr=[NSFileManager defaultManager];
[self ConstructDbpathTo:directory];
return [filemgr fileExistsAtPath:dataBasePath];
}
-(NSString *)ConstructDbpathTo:(NSString *)directory
{
if([directory isEqual:@"DocumentsDirectory"])
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
dataBasePath = [documentsDirectory stringByAppendingPathComponent:DbName];
}
else
{
dataBasePath=[[NSBundle mainBundle] bundlePath];
dataBasePath=[dataBasePath stringByAppendingPathComponent:DbName];
}
return dataBasePath;
}
-(void)CopyDB
{
BOOL success;
NSFileManager *filemgr=[NSFileManager defaultManager];
NSError *error;
success = [filemgr copyItemAtPath:[self ConstructDbpathTo:@"MainBundle"] toPath:[self ConstructDbpathTo:@"DocumentsDirectory"] error:&error];
if (!success)
{
NSString *msg=[[NSString alloc]initWithFormat:@"Failed to create writable database file with message '%@'.", [error localizedDescription]];
NSLog(@"%@",msg);
}
}
-(void)RemoveDBIfExists
{
if([self IsDbAvailableAt:@"DocumentsDirectory"])
{
[self RemoveDB];
}
}
-(void)RemoveDB
{
NSFileManager *fileMgr=[NSFileManager defaultManager];
NSError *errRemoval;
if(![fileMgr removeItemAtPath:[self ConstructDbpathTo:@"DocumentsDirectory"] error:&errRemoval])
{
NSLog(@"RemoveDB:%@",errRemoval);
}
}
-(NSString *)GetMessageForFlagLevel:(NSString *)Flag
{
NSString *Message=[[NSString alloc]init];
if ([Flag isEqual:@"DBfileExistsAtPath"])
{
Message=@"Db file could not be opened.Please try later";
}
else if ([Flag isEqual:@"sqlite3_open"])
{
Message=@"Db file could not be opened.Please try later";
}
else if ([Flag isEqual:@"sqlite3_prepare"])
{
Message=@"sql script compilation failed";
}
else
{
NSString *res=@"sql script running failed:";
res=[res stringByAppendingString:[self Sqlite3_Flags:[Flag intValue]]];
Message=res;
}
return Message;
}
-(NSString *)Sqlite3_Flags:(int)flag
{
switch (flag) {
case SQLITE_ERROR:
return @"SQL error or missing database";
break;
case SQLITE_INTERNAL:
return @"Internal logic error in SQLite";
break;
case SQLITE_PERM:
return @"Access permission denied";
break;
case SQLITE_ABORT:
return @"Callback routine requested an abort";
break;
case SQLITE_BUSY:
return @"The database file is locked";
break;
case SQLITE_LOCKED:
return @"A table in the database is locked";
break;
case SQLITE_NOMEM:
return @"A malloc() failed";
break;
case SQLITE_READONLY:
return @"Attempt to write a readonly database";
break;
case SQLITE_INTERRUPT:
return @" Operation terminated by sqlite3_interrupt()";
break;
case SQLITE_IOERR:
return @"Some kind of disk I/O error occurred";
break;
case SQLITE_CORRUPT:
return @"The database disk image is malformed ";
break;
case SQLITE_NOTFOUND:
return @"Unknown opcode in sqlite3_file_control()";
break;
case SQLITE_FULL:
return @"Insertion failed because database is full ";
break;
case SQLITE_CANTOPEN:
return @"Unable to open the database file";
break;
case SQLITE_PROTOCOL:
return @"Database lock protocol error";
break;
case SQLITE_EMPTY:
return @"Database is empty";
break;
case SQLITE_SCHEMA:
return @"The database schema changed";
break;
case SQLITE_TOOBIG:
return @"String or BLOB exceeds size limit ";
break;
case SQLITE_CONSTRAINT:
return @"Abort due to constraint violation";
break;
case SQLITE_MISMATCH:
return @"Data type mismatch";
break;
case SQLITE_MISUSE:
return @"Library used incorrectly";
break;
case SQLITE_NOLFS:
return @"Uses OS features not supported on host ";
break;
case SQLITE_AUTH:
return @"Authorization denied";
break;
case SQLITE_FORMAT:
return @"Auxiliary database format error";
break;
case SQLITE_RANGE:
return @"2nd parameter to sqlite3_bind out of range";
break;
case SQLITE_NOTADB:
return @"File opened that is not a database file";
break;
case 27://SQLITE_NOTICE
return @"Notifications from sqlite3_log()";
break;
case 28://SQLITE_WARNING
return @"Warnings from sqlite3_log()";
break;
case SQLITE_ROW:
return @" sqlite3_step() has another row ready ";
break;
case SQLITE_DONE:
return @"sqlite3_step() has finished executing";
break;
default:
return [[NSString alloc]initWithFormat:@"%d",flag];
break;
}
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment