最近作一款app,使用到了Sqlite3数据库,ios上的sqlite都是可移植的c语言代码,可是使用起来不像java或者php那么方便,打算尝试一下realm,可是因为项目代码要求支持SQL,所以只能使用SQLite3了。
php
封装后的功能以下功能
java
增删改查ios
支持批量插入,删除,修改sql
支持事务(须要手动开启关闭,begin,commit,rollback)数据库
支持获取表信息,表结构,表字段,支持获取受影响的函数,支持检索数据库是否存在数组
支持自行建立数据库,删除数据库app
看代码
函数
在iOS中,NSDictionary是有序的,并且经过字典取得的key值顺序和遍历出的顺序不一致,是一个很大的坑,所以咱们须要先定义一个无序的字典SparseDictionary,来防止咱们预编译时键值错位fetch
SparseDictionary.hatom
#import <Foundation/Foundation.h> @interface SparseDictionary : NSObject -(instancetype) init; +(instancetype)initWidthDictionary:(NSDictionary *) dict; -(void) addEntryDictonary:(NSDictionary *) dict; -(void) putValue:(NSObject *) value Key:(NSObject *)key; -(NSObject *) getValueOfKey:(NSObject *)key; -(NSArray *) keys; -(NSArray *) values; -(NSObject *) keyAtIndex:(NSInteger) index; -(NSObject *) valueAtIndex:(NSInteger) index; -(NSInteger) indexOfKey:(NSObject *) value; -(NSInteger) indexOfValue:(NSObject *) value; -(NSObject *) remove:(NSObject *) key; -(NSObject *) deleteAtIndex:(NSInteger ) index; -(NSInteger) size; -(void) clear; @end;
SparseDictonary.m
#import "SparseDictionary.h" @interface SparseDictionary() @property (nonatomic,strong,readonly) NSMutableArray * keysOfArray; @property (nonatomic,strong,readonly) NSMutableArray * valuesOfArray; @end @implementation SparseDictionary -(instancetype) init{ self = [super init]; if(self) { _keysOfArray = [NSMutableArray array]; _valuesOfArray = [NSMutableArray array]; } return self; } +(instancetype)initWidthDictionary:(NSDictionary *) dict { SparseDictionary * instance = [[SparseDictionary alloc] init]; if(instance) { if(dict!=nil) { for(NSObject * key in dict.allKeys) { [instance putValue:dict[key] Key:key]; } } } return instance; } -(void) addEntryDictonary:(NSDictionary *) dict { if(dict!=nil) { for(NSObject * key in dict.allKeys) { [self putValue:dict[key] Key:key]; } } } -(void) putValue:(NSObject *) value Key:(NSObject *)key { if([_keysOfArray indexOfObject:key]==NSNotFound) { [_keysOfArray addObject:key]; } if([_keysOfArray indexOfObject:key]<_valuesOfArray.count) { [_valuesOfArray removeObjectAtIndex:[_keysOfArray indexOfObject:key]]; [_valuesOfArray insertObject:value atIndex:[_keysOfArray indexOfObject:key]]; }else{ [ _valuesOfArray addObject:value]; } } -(NSObject *) getValueOfKey:(NSObject *)key{ if([_keysOfArray indexOfObject:key]==NSNotFound) { return nil; } return [_valuesOfArray objectAtIndex:[_keysOfArray indexOfObject:key]]; } -(NSArray *) keys { return [_keysOfArray copy]; } -(NSArray *) values { return [_valuesOfArray copy]; } -(NSObject *) keyAtIndex:(NSInteger) index { return _keysOfArray[index]; } -(NSObject *) valueAtIndex:(NSInteger) index{ return _valuesOfArray[index]; } -(NSInteger) indexOfKey:(NSObject *) key{ return [_keysOfArray indexOfObject:key]; } -(NSInteger) indexOfValue:(NSObject *) value { return [_valuesOfArray indexOfObject:value]; } -(NSObject *) remove:(NSObject *) key { NSObject * value = nil; if([_keysOfArray indexOfObject:key]!=NSNotFound) { NSInteger index = [_keysOfArray indexOfObject:key]; value = [self getValueOfKey:key]; [_keysOfArray removeObjectAtIndex:index]; [_valuesOfArray removeObjectAtIndex:index]; } return value; } -(NSInteger) size { return _keysOfArray.count; } -(NSObject *) deleteAtIndex:(NSInteger ) index { NSObject * key = [self keyAtIndex: index]; NSObject * value = nil; if(key!=nil) { value = [self getValueOfKey:key]; [_keysOfArray removeObjectAtIndex:index]; [_valuesOfArray removeObjectAtIndex:index]; } return value; } -(void) clear { [_keysOfArray removeAllObjects]; [_valuesOfArray removeAllObjects]; } -(NSString *) description{ NSString * desc = @"(\n"; for(int i=0;i<_keysOfArray.count;i++) { if(i<(_keysOfArray.count-1)) { desc = [desc stringByAppendingString:[NSString stringWithFormat:@"%@=%@,\n",_keysOfArray[i],_valuesOfArray[i]]]; }else{ desc = [desc stringByAppendingString:[NSString stringWithFormat:@"%@=%@\n",_keysOfArray[i],_valuesOfArray[i]]]; } } desc = [desc stringByAppendingString:@")\n"]; return desc; } -(void) dealloc { [self clear]; } @end
SqliteDatabase.h
#import <Foundation/Foundation.h> #import "SparseDictonary.h" #include <sqlite3.h> @interface SqliteDatabase : NSObject +(instancetype) shareInstance; -(BOOL)createDatabase:(NSString *) dbPath; /* * *初始化 */ -(BOOL)openDatabase:(NSString *) dbPath; /** * 打开默认数据库 */ -(BOOL)openDefaultDatabase; //开启事务 -(BOOL) beginTransaction:(NSString *) dbPath; //提交事务 -(BOOL) commitTransaction:(NSString *) dbPath; //回滚事务 -(BOOL) rollbackTransaction:(NSString *) dbPath; //开启默认数据库事务 -(BOOL) beginTransaction; //提交默认数据库事务 -(BOOL) commitTransaction; //回滚默认数据库事务 -(BOOL) rollbackTransaction; /** * @brief 执行非查询sql * * @param sql - sql语句 */ - (void)executeUpdate:(NSString *)sql fromDatabase:(NSString *) dbPath; //默认数据库 - (void)executeUpdate:(NSString *)sql; /** * @brief 执行查询sql * * @param sql - sql语句 * * @return 返回查询的数据 */ - (NSArray *)query:(NSString *) sql fromDatabase:(NSString *)dbPath; //默认数据库 - (NSArray *)query:(NSString *) sql; /** * * 关闭数据库 */ - (void)closeAllDatabase; /** * * 关闭指定的数据库 */ -(void)closeDatabase:(NSString *)dbPath; -(void) closeDefaultDatabase; /** * *检查数据表是否存在 */ -(BOOL)isExistTable:(NSString *)tableName fromDatabase:(NSString *) dbPath; //默认数据库 -(BOOL)isExistTable:(NSString *)tableName; /* * *删除数据库 * */ -(void) deleteDatabase:(NSString *) dbPath; /** * * 删除表 * */ -(void) dropTable:(NSString *) tableName fromDatabase:(NSString *)dbPath; //默认数据库 -(void) dropTable:(NSString *) tableName; /** * 判断是否Base64字符串 */ +(BOOL)isBase64String:(NSString *)src; /** * *获取表字段信息 */ -(NSArray *)fetchFieldsInfo:(NSString *) tableName fromDatabase:(NSString *)dbPath; //默认数据库 -(NSArray *)fetchFieldsInfo:(NSString *) tableName; /** * *获取表字段名称 */ -(NSArray *)fetchFieldsName:(NSString *) tableName fromDatabase:(NSString *)dbPath; //默认数据库 -(NSArray *)fetchFieldsName:(NSString *) tableName; //获取受影响的函数 -(int) fetchNumberOfAffectedRows:(NSString *)dbPath; //默认数据库 -(int) fetchNumberOfAffectedRows; /** * 数据插入 *{}----------普通字典 */ - (void)insertTable:(NSString *)tableName tableData:(NSDictionary *) dict fromDatabase:(NSString *) dbPath; //默认数据库 - (void)insertTable:(NSString *)tableName tableData:(NSDictionary *) dict; /** * 批量插入 */ - (void)insertTable:(NSString *)tableName fields:(NSArray *) fields values:(NSArray *) values fromDatabase:(NSString *) dbPath; - (void)insertTable:(NSString *)tableName fields:(NSArray *) fields values:(NSArray *) values; /****过滤特殊字符****/ +(NSString *)sqlEscape:(NSString *)source; @end
SqliteDatabase.m
#import "SqliteDatabase.h" @interface DBInfo : NSObject @property(nonatomic,strong) NSString * dbPath; @property(nonatomic,assign) sqlite3 * db; @property(nonatomic,strong) NSString * dbName; @property(nonatomic,assign) BOOL isOpened; @property(nonatomic,assign) BOOL isOpenedTransaction; -(instancetype) initWidthDBName:(NSString *) path forSQLite:(sqlite3 *) db; @end @implementation DBInfo -(instancetype) initWidthDBName:(NSString *) path forSQLite:(sqlite3 *) db { self = [super init]; if(self) { _dbPath = path; _db = db; _dbName = [path lastPathComponent]; _isOpened = NO; _isOpenedTransaction = NO; } return self; } @end @interface SqliteDatabase() -(instancetype) init; @property(nonatomic,strong) NSMutableDictionary * sqliteDBInfos; @property(nonatomic,strong) NSString * defaultDBPath; -(void) createDefaultDatabase; -(void) deleteDefaultDatabase; @end @implementation SqliteDatabase -(instancetype) init { self = [super init]; if(self!=nil) { _sqliteDBInfos = [NSMutableDictionary dictionary]; sqlite3_initialize(); [self performSelector:@selector(createDefaultDatabase) withObject:nil]; } return self; } -(void) createDefaultDatabase { NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString * dbPath = [path[0] stringByAppendingPathComponent:@"Databases"]; if(![[NSFileManager defaultManager] fileExistsAtPath:dbPath]) { NSError * error; [[NSFileManager defaultManager] createDirectoryAtPath:dbPath withIntermediateDirectories:YES attributes:nil error:&error]; } _defaultDBPath = [dbPath stringByAppendingPathComponent:@"default_local_db_storage.sqlite3"]; [self createDatabase:_defaultDBPath]; } +(instancetype) shareInstance { static SqliteDatabase * instance; static dispatch_once_t onceToken = 0; dispatch_once(&onceToken, ^(void){ instance = [[SqliteDatabase alloc] init]; }); return instance; } - (BOOL)createDatabase:(NSString *) nsFile { sqlite3 * db; const char *filename = [nsFile UTF8String]; int rc = sqlite3_open_v2(filename, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL ); if (rc != SQLITE_OK) { NSLog(@"数据库建立失败"); return NO; } if(db!=NULL) { sqlite3_close(db); } NSLog(@"数据库建立成功,位置:%@",nsFile); return YES; } -(BOOL) openDatabase:(NSString *) nsFile { sqlite3 * db; DBInfo * dbInfo = _sqliteDBInfos[[nsFile lastPathComponent]]; if(dbInfo!=nil && dbInfo.isOpened && dbInfo.db!=NULL) { sqlite3_close(dbInfo.db); dbInfo.db = NULL; NSLog(@"从新打开数据库"); } const char *filename = [nsFile UTF8String]; int rc = sqlite3_open_v2(filename, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL ); if (rc != SQLITE_OK) { if(db!=NULL) { sqlite3_close(db); } NSLog(@"数据库打开失败"); return NO; } if(dbInfo==nil) { dbInfo = [[DBInfo alloc] initWidthDBName:nsFile forSQLite:db]; }else{ dbInfo.db = db; } [_sqliteDBInfos setObject:dbInfo forKey:[nsFile lastPathComponent]]; dbInfo.isOpened = YES; return YES; } -(BOOL) openDefaultDatabase { return [self openDatabase:_defaultDBPath]; } -(BOOL) beginTransaction:(NSString *) dbPath { DBInfo * dbInfo = _sqliteDBInfos[[dbPath lastPathComponent]]; char *errorMsg; NSException *exception = nil; if(dbInfo==nil) { exception = [NSException exceptionWithName:@"NotFound" reason:@"数据库不存在" userInfo:nil]; @throw exception; } if(!dbInfo.isOpened) { //防止误操做,这里建议开始打开数据库,开启事务 [self openDatabase:dbPath]; } if(dbInfo.isOpenedTransaction) { NSLog(@"事务已经开启,无需重复开启!"); return YES; } if (sqlite3_exec(dbInfo.db, "BEGIN", NULL, NULL, &errorMsg)!=SQLITE_OK) { if (errorMsg != NULL) { sqlite3_free(errorMsg); NSString *msg = [[NSString stringWithFormat:@"error=%s\nSQL=",errorMsg] stringByAppendingString:@"Begin Transaction"]; exception = [NSException exceptionWithName:@"ExectueError" reason:msg userInfo:nil]; @throw exception; } NSLog(@"事务开启失败"); return NO; } NSLog(@"事务成功开启"); dbInfo.isOpenedTransaction = YES; return YES; } -(BOOL) beginTransaction { return [self beginTransaction:_defaultDBPath]; } -(BOOL) commitTransaction:(NSString *) dbPath { DBInfo * dbInfo = _sqliteDBInfos[[dbPath lastPathComponent]]; char *errorMsg; NSException *exception = nil; if(dbInfo==nil) { exception = [NSException exceptionWithName:@"NotFound" reason:@"数据库不存在" userInfo:nil]; @throw exception; } if(!dbInfo.isOpened) { NSLog(@"数据库未打开,没有事务"); return YES; } if(!dbInfo.isOpenedTransaction) { NSLog(@"数据库未开启事务,无需Commit"); return YES;//事务操做未开启 } if (sqlite3_exec(dbInfo.db, "COMMIT", NULL, NULL, &errorMsg)!=SQLITE_OK) { if (errorMsg != NULL) { sqlite3_free(errorMsg); NSString *msg = [[NSString stringWithFormat:@"error=%s\nSQL=",errorMsg] stringByAppendingString:@"COMMIT Transaction"]; exception = [NSException exceptionWithName:@"ExectueError" reason:msg userInfo:nil]; @throw exception; } NSLog(@"数据库Commit失败"); return NO; } NSLog(@"数据库Commit成功"); dbInfo.isOpenedTransaction = NO; return YES; } -(BOOL) commitTransaction { return [self commitTransaction:_defaultDBPath]; } -(BOOL) rollbackTransaction:(NSString *) dbPath { DBInfo * dbInfo = _sqliteDBInfos[[dbPath lastPathComponent]]; char *errorMsg; NSException *exception = nil; if(dbInfo==nil) { exception = [NSException exceptionWithName:@"NotFound" reason:@"数据库不存在" userInfo:nil]; @throw exception; } if(!dbInfo.isOpened) { NSLog(@"数据库未打开,没有事务"); return YES; } if(!dbInfo.isOpenedTransaction) { NSLog(@"数据库未开启事务,无需回滚"); return YES;//事务操做未开启 } if (sqlite3_exec(dbInfo.db, "ROLLBACK", NULL, NULL, &errorMsg)!=SQLITE_OK) { if (errorMsg != NULL) { sqlite3_free(errorMsg); NSString *msg = [[NSString stringWithFormat:@"error=%s\nSQL=",errorMsg] stringByAppendingString:@"COMMIT Transaction"]; exception = [NSException exceptionWithName:@"ExectueError" reason:msg userInfo:nil]; @throw exception; } NSLog(@"数据库事务回滚失败"); return NO; } NSLog(@"数据库事务回滚成功"); dbInfo.isOpenedTransaction = NO; return YES; } -(BOOL) rollbackTransaction { return [self rollbackTransaction:_defaultDBPath]; } /** *@brief执行非查询sql * *@param sql - sql语句 */ - (void)executeUpdate:(NSString *)sql fromDatabase:(NSString *) dbPath; { @synchronized(self) { char *errMsg; NSException *exception = nil; DBInfo * dbInfo = _sqliteDBInfos[[dbPath lastPathComponent]]; if(dbInfo==nil) { exception = [NSException exceptionWithName:@"NotFound" reason:@"数据库未开启" userInfo:nil]; @throw exception; } if(!dbInfo.isOpened) { [self openDatabase:dbPath]; } if(sqlite3_exec(dbInfo.db, [sql UTF8String],NULL,NULL,&errMsg) != SQLITE_OK) { if (errMsg != NULL) { NSString *msg = [[NSString stringWithFormat:@"error=%s\nSQL=",errMsg] stringByAppendingString:sql]; exception = [NSException exceptionWithName:@"ExectueError" reason:msg userInfo:nil]; sqlite3_free(errMsg); } } if (exception != nil) { @throw exception; }else{ NSLog(@"执行成功:%@",sql); } } } - (void)executeUpdate:(NSString *)sql { [self executeUpdate:sql fromDatabase:_defaultDBPath]; } - (void)insertTable:(NSString *)tableName tableData:(NSDictionary *) dict fromDatabase:(NSString *) dbPath { if(dict==nil || dict.count==0) { return; } @synchronized(self) { NSException *exception = nil; DBInfo * dbInfo = _sqliteDBInfos[[dbPath lastPathComponent]]; if(dbInfo==nil) { exception = [NSException exceptionWithName:@"NotFound" reason:@"数据库未开启" userInfo:nil]; @throw exception; } NSArray * columns = [self fetchFieldsName:tableName fromDatabase:dbPath]; SparseDictionary * keyValueEntry = [SparseDictionary initWidthDictionary:dict]; //防止字典排序,使用无序的SparseDictionary for (NSString *key in keyValueEntry.keys) { if([columns indexOfObject:key]==NSNotFound) { exception = [NSException exceptionWithName:@"ErrorFields" reason:[@"不存在的字段>>" stringByAppendingString:key] userInfo:nil]; @throw exception; } } if(!dbInfo.isOpened) { [self openDatabase:dbPath]; } NSString *sql = [NSString stringWithFormat: @"INSERT INTO %@( ",tableName]; NSString *values = @" values ("; for(NSString * key in keyValueEntry.keys) { if(![key isEqualToString:dict.allKeys.lastObject]) { sql = [sql stringByAppendingString:[NSString stringWithFormat:@" '%@' ,",key]]; values = [values stringByAppendingString:@" ? ,"]; }else{ sql = [sql stringByAppendingString:[NSString stringWithFormat:@" '%@' ) ",key]]; values = [values stringByAppendingString:@" ? );"]; } } sql = [NSString stringWithFormat:@"%@ %@",sql,values]; sqlite3_stmt *stmt; if (sqlite3_prepare_v2(dbInfo.db, [sql UTF8String], -1, &stmt, NULL) == SQLITE_OK) { NSArray * fieldsInfos = [self fetchFieldsInfo:tableName fromDatabase:dbPath]; [self bindToStatement:stmt values:keyValueEntry useFieldsInfo:fieldsInfos forDepth:0]; if (sqlite3_step(stmt) != SQLITE_DONE) { const char * errorMSG = sqlite3_errmsg(dbInfo.db); int errorCode = sqlite3_errcode(dbInfo.db); NSString *msg = [[NSString stringWithFormat:@"errorCode=%d,error=%s\nSQL=",errorCode,errorMSG] stringByAppendingString:sql]; exception = [NSException exceptionWithName:@"执行sql错误" reason:msg userInfo:nil]; sqlite3_free(&errorMSG); } }else{ NSLog(@"插入数据错误"); const char * errorMSG = sqlite3_errmsg(dbInfo.db); int errorCode = sqlite3_errcode(dbInfo.db); NSString *msg = [[NSString stringWithFormat:@"errorCode=%d,error=%s\nSQL=",errorCode,errorMSG] stringByAppendingString:sql]; exception = [NSException exceptionWithName:@"执行sql错误" reason:msg userInfo:nil]; sqlite3_free(&errorMSG); } if(stmt!=NULL) { sqlite3_finalize(stmt); } if(exception!=nil) { @throw exception; } } } /** * 批量插入 * * NSArray<NSString> fields 是一维数组,为了防止错误插入,这里filed不容许默认空缺 * NSArray<NSArray> values 是二维数组,而且每一维数组的长度必须相同,不然可能引发致命错误 * */ - (void)insertTable:(NSString *)tableName fields:(NSArray *) fields values:(NSArray *) values fromDatabase:(NSString *) dbPath { if(fields == nil || fields.count==0 || values==nil || values.count==0) { return; } @synchronized(self) { NSException *exception = nil; DBInfo * dbInfo = _sqliteDBInfos[[dbPath lastPathComponent]]; if(dbInfo==nil) { exception = [NSException exceptionWithName:@"NotFound" reason:@"数据库未开启" userInfo:nil]; @throw exception; } NSArray * columns = [self fetchFieldsName:tableName fromDatabase:dbPath]; for (NSString *key in fields) { if([columns indexOfObject:key]==NSNotFound) { exception = [NSException exceptionWithName:@"ErrorFields" reason:[@"不存在的字段>>" stringByAppendingString:key] userInfo:nil]; @throw exception; } } if(!dbInfo.isOpened) { [self openDatabase:dbPath]; } NSString *sql = [NSString stringWithFormat: @"INSERT INTO %@( ",tableName]; NSString * valueStr = @" values"; for (NSString *key in fields) { if(![key isEqualToString:fields.lastObject]) { sql = [sql stringByAppendingString:[NSString stringWithFormat:@" '%@' ,",key]]; }else{ sql = [sql stringByAppendingString:[NSString stringWithFormat:@" '%@' )",key]]; } } NSMutableArray * dataArrayDict = [NSMutableArray array]; SparseDictionary * keyValueSparseDict = nil; for (int i=0;i<values.count;i++) { valueStr = [valueStr stringByAppendingString:@" ("]; keyValueSparseDict = [[SparseDictionary alloc] init]; for (int j=0;j<fields.count;j++) { if(j<fields.count-1) { valueStr = [valueStr stringByAppendingString:@" ?,"]; }else{ valueStr = [valueStr stringByAppendingString:@" ? "]; } [keyValueSparseDict putValue:values[i][j] Key:fields[j]]; } valueStr = [valueStr stringByAppendingString:@")"]; if(i<values.count-1) { valueStr = [valueStr stringByAppendingString:@","]; }else{ valueStr = [valueStr stringByAppendingString:@";"]; } [dataArrayDict addObject:keyValueSparseDict]; } sql = [NSString stringWithFormat:@" %@ %@",sql,valueStr]; sqlite3_stmt *stmt; if (sqlite3_prepare_v2(dbInfo.db, [sql UTF8String], -1, &stmt, NULL) == SQLITE_OK) { NSArray * fieldsInfos = [self fetchFieldsInfo:tableName fromDatabase:dbPath]; int k = 0; for (SparseDictionary * dict in dataArrayDict) { [self bindToStatement:stmt values:dict useFieldsInfo:fieldsInfos forDepth:k]; k++; } if (sqlite3_step(stmt) != SQLITE_DONE) { NSLog(@"插入数据错误"); const char * errorMSG = sqlite3_errmsg(dbInfo.db); int errorCode = sqlite3_errcode(dbInfo.db); NSString *msg = [[NSString stringWithFormat:@"errorCode=%d,error=%s\nSQL=",errorCode,errorMSG] stringByAppendingString:sql]; exception = [NSException exceptionWithName:@"执行sql错误" reason:msg userInfo:nil]; sqlite3_free(&errorMSG); } }else{ NSLog(@"插入数据错误"); const char * errorMSG = sqlite3_errmsg(dbInfo.db); int errorCode = sqlite3_errcode(dbInfo.db); NSString *msg = [[NSString stringWithFormat:@"errorCode=%d,error=%s\nSQL=",errorCode,errorMSG] stringByAppendingString:sql]; exception = [NSException exceptionWithName:@"执行sql错误" reason:msg userInfo:nil]; sqlite3_free(&errorMSG); } if(stmt!=NULL) { sqlite3_finalize(stmt); } if(exception!=nil) { @throw exception; } } } -(NSArray *) sortKeyForSQL:(NSArray *) values fields:(NSArray *) fields { if(values==nil || fields==nil) { return fields; } NSMutableDictionary * tempSortDict = [NSMutableDictionary dictionaryWithObjects:values forKeys:fields]; return tempSortDict.allKeys;//进行字典排序,防止key=value与sql语句不对称问题 } - (void)insertTable:(NSString *)tableName fields:(NSArray *) fields values:(NSArray *) values { [self insertTable:tableName fields:fields values:values fromDatabase:_defaultDBPath]; } - (void)insertTable:(NSString *) tableName tableData:(NSDictionary *) dict { [self insertTable:tableName tableData:dict fromDatabase:_defaultDBPath]; } -(void) bindToStatement:(sqlite3_stmt *)stmt values:(SparseDictionary *) dict useFieldsInfo:(NSArray *) filedsInfo forDepth:(int)depIndex { if(filedsInfo==nil || dict==nil) { return; } NSMutableDictionary *fieldInfoDict = [NSMutableDictionary dictionary]; for (NSDictionary * fieldInfo in filedsInfo) { fieldInfoDict[fieldInfo[@"name"]] = fieldInfo; } for( int i=0;i< [dict size];i++) { NSString * key = [(NSString *)dict.keys[i] lowercaseString]; int index = (int)(i+(depIndex*[dict size]))+1; //数据库索引从1开始 NSString * fieldType = [fieldInfoDict[key][@"type"] lowercaseString]; NSLog(@"bindIndex=%d,key=%@,value=%@,type=%@",index,key,[dict getValueOfKey:key],fieldType); if([@"integer" isEqualToString:fieldType]||[@"int" isEqualToString:fieldType]||[@"biginteger" isEqualToString:fieldType] || [fieldType hasPrefix:@"int("]) { sqlite3_bind_int(stmt, index, [(NSString *)[dict getValueOfKey:key] intValue]); } else if([@"float" isEqualToString:fieldType]||[@"double" isEqualToString:fieldType]|| [@"real" isEqualToString:fieldType]|| [@"decimal" isEqualToString:fieldType]) { sqlite3_bind_double(stmt, index, [(NSString *)[dict getValueOfKey:key] floatValue]); } else if([@"blob" isEqualToString:fieldType] ) { NSData * data = (NSData *)[dict getValueOfKey:key]; sqlite3_bind_blob(stmt, index, data.bytes, (int)data.length, SQLITE_STATIC); } else if([@"varchar" isEqualToString:fieldType]||[@"text" isEqualToString:fieldType] || [fieldType hasPrefix:@"varchar("]) { NSString * nsSqlText = (NSString *)[dict getValueOfKey:key]; const char* sqlText = [nsSqlText UTF8String]; sqlite3_bind_text(stmt,index, sqlText,-1, SQLITE_STATIC); }else{ sqlite3_value *p = (__bridge sqlite3_value *)[dict getValueOfKey:key]; sqlite3_bind_value(stmt, index,p); } } } -(NSArray *)fetchFieldsName:(NSString *) tableName fromDatabase:(NSString *)dbPath { NSArray * tableFieldsInfo = [self fetchFieldsInfo:tableName fromDatabase:dbPath]; NSMutableArray * tableNameArray = [NSMutableArray array]; if(tableFieldsInfo!=nil) { [tableFieldsInfo enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if([obj isKindOfClass:[NSDictionary class]]) { [tableNameArray addObject:[obj objectForKey:@"name"]]; } }]; } return tableNameArray; } -(NSArray *)fetchFieldsName:(NSString *) tableName { return [self fetchFieldsName:tableName fromDatabase:_defaultDBPath]; } -(NSArray *)fetchFieldsInfo:(NSString *) tableName fromDatabase:(NSString *)dbPath { NSString * sql = [NSString stringWithFormat:@"PRAGMA TABLE_INFO('%@')",tableName]; NSLog(@"SQL-Lang:%@",sql); NSMutableArray *table = [NSMutableArray array]; @synchronized(self) { sqlite3_stmt *stmt; NSException *exception = nil; DBInfo * dbInfo = _sqliteDBInfos[[dbPath lastPathComponent]]; if(dbInfo==nil) { NSString * exName = [NSString stringWithFormat:@"NotFound"]; exception = [NSException exceptionWithName:exName reason:@"数据库不存在" userInfo:nil]; @throw exception; } if(!dbInfo.isOpened) { [self openDatabase:dbPath]; } if(sqlite3_prepare_v2(dbInfo.db,[sql UTF8String],-1,&stmt,nil) == SQLITE_OK) { while(sqlite3_step(stmt) == SQLITE_ROW) { @autoreleasepool { int col = sqlite3_column_count(stmt); NSMutableDictionary *row = [NSMutableDictionary dictionary]; for (int i=0; i<col; i++) { id k = [NSString stringWithCString:sqlite3_column_name(stmt,i) encoding:NSUTF8StringEncoding]; id v = [self reloadData:stmt column:i]; [row setObject:v forKey:k]; } [table addObject:row]; } } sqlite3_finalize(stmt); } else { NSString *msg = [[NSString stringWithFormat:@"error=%s\nSQL=",sqlite3_errmsg(dbInfo.db)] stringByAppendingString:sql]; exception = [NSException exceptionWithName:@"执行sql错误" reason:msg userInfo:nil]; @throw exception; } } return table; } -(NSArray *)fetchFieldsInfo:(NSString *) tableName { return [self fetchFieldsInfo:tableName fromDatabase:_defaultDBPath]; } /** *@brief执行查询sql *@param sql - sql语句 * @return 返回查询的数据 */ - (NSArray *)query:(NSString *) sql fromDatabase:(NSString *)dbPath;{ NSMutableArray *table = [NSMutableArray array]; @synchronized(self) { sqlite3_stmt *stmt; NSException *exception = nil; DBInfo * dbInfo = _sqliteDBInfos[[dbPath lastPathComponent]]; if(sql==nil || sql.length==0) { NSString * exName = [NSString stringWithFormat:@"EmptySQL"]; exception = [NSException exceptionWithName:exName reason:@"sql语句不能为null" userInfo:nil]; @throw exception; }else{ NSLog(@"SQL-Lang:%@",sql); } if(dbInfo==nil) { NSString * exName = [NSString stringWithFormat:@"NotFound"]; exception = [NSException exceptionWithName:exName reason:@"数据库不存在" userInfo:nil]; @throw exception; } if(!dbInfo.isOpened) { [self openDatabase:dbPath]; } if(sqlite3_prepare_v2(dbInfo.db,[sql UTF8String],-1,&stmt,nil) == SQLITE_OK) { while(sqlite3_step(stmt) == SQLITE_ROW) { @autoreleasepool { int col = sqlite3_column_count(stmt); NSMutableDictionary *row = [NSMutableDictionary dictionary]; for (int i=0; i<col; i++) { id k = [NSString stringWithCString:sqlite3_column_name(stmt,i) encoding:NSUTF8StringEncoding]; if([@"age" isEqualToString:k]){ } id v = [self reloadData:stmt column:i]; if(v==nil) { v = [self reloadData:stmt column:i]; } [row setObject:v forKey:k]; } [table addObject:row]; } } sqlite3_finalize(stmt); } else { NSString *msg = [[NSString stringWithFormat:@"error=%s\nSQL=",sqlite3_errmsg(dbInfo.db)] stringByAppendingString:sql]; exception = [NSException exceptionWithName:@"执行sql错误" reason:msg userInfo:nil]; @throw exception; } } return table; } - (NSArray *)query:(NSString *) sql { return [self query:sql fromDatabase:_defaultDBPath]; } /** * * 按照表类型获取数据 * */ - (id)reloadData:(sqlite3_stmt *)stmt column:(int)column { id object; switch (sqlite3_column_type(stmt,column)) { case SQLITE_INTEGER: { object = [NSNumber numberWithInt:sqlite3_column_int(stmt,column)]; if(object==nil) { object = [NSNumber numberWithInt:0]; } } break; case SQLITE_FLOAT: { object = [NSNumber numberWithDouble:sqlite3_column_double(stmt,column)]; if(object==nil) { object = [NSNumber numberWithDouble:0.0]; } } break; case SQLITE_BLOB: { object = [NSData dataWithBytes:sqlite3_column_blob(stmt,column) length:sqlite3_column_bytes(stmt,column)]; if(object==nil) { object = [NSNull null]; } } break; case SQLITE_NULL: object = [NSString stringWithFormat:@""]; break; case SQLITE_TEXT: { char * value = (char *) sqlite3_column_text(stmt,column); if(value!=NULL) { object = [NSString stringWithUTF8String:value]; } if(object==nil) { object = @""; } } break; default: sqlite3_value * val = sqlite3_column_value(stmt, column); NSObject * objValue = (__bridge_transfer id)val;//将c对象转为OC对象 object = objValue; break; } return object; } - (void)closeAllDatabase { NSArray * keys = [_sqliteDBInfos.allKeys copy]; for(int i=0;keys!=nil &&i<keys.count;i++) { [self closeDatabase:keys[i]]; } } -(void)closeDatabase:(NSString *)dbPath; { DBInfo * dbInfo = _sqliteDBInfos[[dbPath lastPathComponent]]; if(dbInfo!=nil && dbInfo.isOpened && dbInfo.db!=NULL) { sqlite3_close(dbInfo.db); dbInfo.isOpened = NO; dbInfo.isOpenedTransaction = NO; dbInfo.db = NULL; } } -(void) closeDefaultDatabase { [self closeDatabase:_defaultDBPath]; } -(void)dealloc { [self closeAllDatabase]; [_sqliteDBInfos removeAllObjects]; } /** *@brief判断表是否存在 *@param name 表名字 * @return 返回转义后的字符串 */ -(BOOL)isExistTable:(NSString *)tableName fromDatabase:(NSString *) dbPath; { char *err; NSString *sql = [NSString stringWithFormat:@"SELECT COUNT(*) FROM sqlite_master where type='table' and name='%@';",tableName]; const char *sql_stmt = [sql UTF8String]; DBInfo * dbInfo = _sqliteDBInfos[[dbPath lastPathComponent]]; if(dbInfo==nil) { return NO; } if(sqlite3_exec(dbInfo.db, sql_stmt, NULL, NULL, &err) == 1){ return YES; }else{ return NO; } } -(BOOL)isExistTable:(NSString *)tableName { return [self isExistTable:tableName fromDatabase:_defaultDBPath]; } -(void) dropTable:(NSString *) tableName fromDatabase:(NSString *)dbPath { NSString * sql = [@"DROP TABLE IF EXISTS " stringByAppendingString:tableName]; [self executeUpdate:sql fromDatabase:dbPath]; } -(void) dropTable:(NSString *) tableName { return [self dropTable:tableName fromDatabase:_defaultDBPath]; } -(void) deleteDatabase:(NSString *) dbPath{ [self closeDatabase:dbPath]; [_sqliteDBInfos removeObjectForKey:[dbPath lastPathComponent]]; if ([[NSFileManager defaultManager]removeItemAtPath:dbPath error:nil]) { NSLog( @"remove: %@", [NSString stringWithFormat:@"%@", dbPath]); } } -(void) deleteDefaultDatabase { return [self deleteDatabase:_defaultDBPath]; } +(BOOL)isBase64String:(NSString *)src { if(src==nil || src.length==0) { return NO; } if(src.length%4!=0) { return NO; } NSString *decodedString = nil; @try { NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:src options:0]; if(decodedData!=nil) { decodedString = [[NSString alloc] initWithData:decodedData encoding:NSUTF8StringEncoding]; } if(decodedString==nil) { @throw [[NSException alloc] initWithName:@"Base64DecodeException" reason:@"Base64Decode 解码失败!" userInfo:nil]; } } @catch(NSException *exception) { NSLog(@"exception=%@",exception); return NO; } return YES; } -(int) fetchNumberOfAffectedRows:(NSString *)dbPath { NSException *exception = nil; DBInfo * dbInfo = _sqliteDBInfos[[dbPath lastPathComponent]]; if(dbInfo==nil) { exception = [NSException exceptionWithName:@"NotFound" reason:@"数据库不存在" userInfo:nil]; @throw exception; } if(!dbInfo.isOpened) { [self openDatabase:dbPath]; } return sqlite3_changes(dbInfo.db); } -(int) fetchNumberOfAffectedRows { return [self fetchNumberOfAffectedRows:_defaultDBPath]; } +(NSString *)sqlEscape:(NSString *)source { if(source==nil || source.length==0) { return source; } static NSDictionary * exludeDict = @{ @"\0":@"", @"\'":@"\\'", @"\"":@"\\\"", @"\n":@" ", @"/":@"\\/", @"\t":@" ", @"\r":@" ", @"%":@"\\%", @"\b":@" ", @"_":@"\\_" }; for (NSString * key in exludeDict.allKeys) { if([source containsString:key]) { source = [source stringByReplacingOccurrencesOfString:key withString:exludeDict[key]]; } } return source; } @end