Created
April 21, 2014 15:56
-
-
Save Duraiamuthan/11146895 to your computer and use it in GitHub Desktop.
SQLite Objective C Data Access Layer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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