12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207 |
- //
- // BGDB.m
- // BGFMDB
- //
- // Created by biao on 2017/10/18.
- // Copyright © 2017年 Biao. All rights reserved.
- //
- #import "BGDB.h"
- #import "BGTool.h"
- #import "NSCache+BGCache.h"
- /**
- 默认数据库名称
- */
- #define SQLITE_NAME @"BGFMDB.db"
- #define bg_debug(param) do{\
- if(self.debug){bg_log(@"调试输出: %@",param);}\
- }while(0)
- #define MaxQueryPageNum 50
- #define CachePath(name) [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:name]
- static const void * const BGFMDBDispatchQueueSpecificKey = &BGFMDBDispatchQueueSpecificKey;
- @interface BGDB()
- /**
- 数据库队列
- */
- @property (nonatomic, strong) FMDatabaseQueue *queue;
- @property (nonatomic, strong) FMDatabase* db;
- @property (nonatomic, assign) BOOL inTransaction;
- /**
- 多线程池
- */
- @property(nonatomic,strong)NSMutableArray* _Nullable mulThreadPool;
- @property(nonatomic,strong)dispatch_queue_t mulThreadPoolQueue;
- /**
- 线程池执行状态标识
- */
- @property(nonatomic,assign)BOOL threadPoolFlag;
- /**
- 递归锁.
- */
- //@property (nonatomic, strong) NSRecursiveLock *threadLock;
- /**
- 记录注册监听数据变化的block.
- */
- @property (nonatomic,strong) NSMutableDictionary* changeBlocks;
- /**
- 存放当队列处于忙时的事务block
- */
- @property (nonatomic,strong) NSMutableArray* transactionBlocks;
- @end
- static BGDB* BGdb = nil;
- @implementation BGDB
- -(void)dealloc{
- //烧毁数据.
- [self destroy];
- }
- -(void)destroy{
- if (self.changeBlocks){
- [self.changeBlocks removeAllObjects];//清除所有注册列表.
- _changeBlocks = nil;
- }
- if (_semaphore) {
- _semaphore = 0x00;
- }
- [self closeDB];
- if (BGdb) {
- BGdb = nil;
- }
-
- }
- -(NSMutableArray *)mulThreadPool{
- if (_mulThreadPool == nil) {
- _mulThreadPool = [NSMutableArray array];
- }
- return _mulThreadPool;
- }
- -(dispatch_queue_t)mulThreadPoolQueue{
- if (_mulThreadPoolQueue == nil) {
- _mulThreadPoolQueue = dispatch_queue_create("BGFMDB.excuteThreadPool", DISPATCH_QUEUE_SERIAL);
- }
- return _mulThreadPoolQueue;
- }
- /**
- 关闭数据库.
- */
- -(void)closeDB{
- if(_disableCloseDB)return;//不关闭数据库
-
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- if(!_inTransaction && _queue) {//没有事务的情况下就关闭数据库.
- [_queue close];//关闭数据库.
- _queue = nil;
- }
- dispatch_semaphore_signal(self.semaphore);
- }
- /**
- 删除数据库文件.
- */
- +(BOOL)deleteSqlite:(NSString*)sqliteName{
- NSString* filePath = CachePath(([NSString stringWithFormat:@"%@.db",sqliteName]));
- NSFileManager * file_manager = [NSFileManager defaultManager];
- NSError* error;
- if ([file_manager fileExistsAtPath:filePath]) {
- [file_manager removeItemAtPath:filePath error:&error];
- }
- return error==nil;
- }
- -(instancetype)init{
- self = [super init];
- if (self) {
- //创建递归锁.
- //self.threadLock = [[NSRecursiveLock alloc] init];
- //创建信号量.
- self.semaphore = dispatch_semaphore_create(1);
- }
- return self;
- }
- -(FMDatabaseQueue *)queue{
- if(_queue)return _queue;
- //获得沙盒中的数据库文件名
- NSString* name;
- if(_sqliteName) {
- name = [NSString stringWithFormat:@"%@.db",_sqliteName];
- }else{
- name = SQLITE_NAME;
- }
- NSString *filename = CachePath(name);
- //HLog(@"数据库路径 = %@",filename);
- _queue = [FMDatabaseQueue databaseQueueWithPath:filename];
- return _queue;
- }
- -(NSMutableDictionary *)changeBlocks{
- if (_changeBlocks == nil) {
- @synchronized(self){
- if(_changeBlocks == nil){
- _changeBlocks = [NSMutableDictionary dictionary];
- }
- }
- }
- return _changeBlocks;
- }
- -(NSMutableArray *)transactionBlocks{
- if (_transactionBlocks == nil){
- @synchronized(self){
- if(_transactionBlocks == nil){
- _transactionBlocks = [NSMutableArray array];
- }
- }
- }
- return _transactionBlocks;
- }
- /**
- 获取单例函数.
- */
- +(_Nonnull instancetype)shareManager{
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- BGdb = [[BGDB alloc] init];
- });
- return BGdb;
- }
- /**
- 添加操作到线程池
- */
- -(void)addToThreadPool:(void (^_Nonnull)())block{
-
- if(!self.mulThreadPoolQueue || !self.mulThreadPool || !block){
- HLog(@"\n\n\n\n\n\n\n addToThreadPool error");
- NSString *errorstr = [[NSString alloc] initWithFormat:@"addToThreadPool error block:%@,mulThreadPool:%@,mulThreadPoolQueue:%@",block,self.mulThreadPool,self.mulThreadPoolQueue ];
- [cachesFileManager writeLogsWithMsg:errorstr];
- //return;
- }
-
- NSAssert(block, @"block is nil!");
-
- dispatch_async(self.mulThreadPoolQueue, ^{
- NSString* key = [NSString stringWithFormat:@"b_%@_%@",@([[NSDate new] timeIntervalSince1970]),@(random())];
- NSDictionary* dict = @{key:block};
- [self.mulThreadPool addObject:dict];
- [self excuteThreadPool];
- });
- }
- /**
- 执行线程池操作
- */
- -(void)excuteThreadPool{
- if (!_threadPoolFlag) {
- _threadPoolFlag = YES;
- do{
- if(self.mulThreadPool.count>0){
- NSDictionary* dict = self.mulThreadPool.firstObject;
- NSString* key = [dict.allKeys firstObject];
- void(^block)(void) = dict[key];
- if(block){
- block();
- }
-
- if(self.mulThreadPool.count>0){//hxd add 20240305 推测线程没保护好
- [self.mulThreadPool removeObjectAtIndex:0];//移除任务
- }
- }
- }while(self.mulThreadPool.count>0);
- _threadPoolFlag = NO;
- }
- }
- //事务操作
- -(void)inTransaction:(BOOL (^_Nonnull)())block{
- NSAssert(block, @"block is nil!");
- if([NSThread currentThread].isMainThread){//主线程直接执行
- [self executeTransation:block];
- }else{//子线程则延迟执行
- [self.transactionBlocks addObject:block];
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.2*NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- [self executeTransationBlocks];
- });
- }
- }
- /*
- 执行事务操作
- */
- -(void)executeTransation:(BOOL (^_Nonnull)())block{
- [self executeDB:^(FMDatabase * _Nonnull db) {
- _inTransaction = db.isInTransaction;
- if (!_inTransaction) {
- _inTransaction = [db beginTransaction];
- }
- BOOL isCommit = NO;
- isCommit = block();
- if (_inTransaction){
- if (isCommit) {
- [db commit];
- }else {
- [db rollback];
- }
- _inTransaction = NO;
- }
- }];
- }
- -(void)executeTransationBlocks{
- //[self.threadLock lock];
- @synchronized(self){
- if(_inTransaction || _queue){
- if(self.transactionBlocks.count) {
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.2*NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- [self executeTransationBlocks];
- });
- }
- return;
- }
- while(self.transactionBlocks.count) {
- BOOL (^block)() = [self.transactionBlocks lastObject];
- [self executeTransation:block];
- [self.transactionBlocks removeLastObject];
- }
- }
- //[self.threadLock unlock];
- }
- /**
- 为了对象层的事物操作而封装的函数.
- */
- -(void)executeDB:(void (^_Nonnull)(FMDatabase *_Nonnull db))block{
- NSAssert(block, @"block is nil!");
-
- if (_db){//为了事务操作防止死锁而设置.
- block(_db);
- return;
- }
- __weak typeof(self) weakSelf = self;
- [self.queue inDatabase:^(FMDatabase *db){
- __strong typeof(weakSelf) strongSelf = weakSelf;
- strongSelf.db = db;
- block(db);
- strongSelf.db = nil;
- }];
-
- }
- /**
- 注册数据变化监听.
- */
- -(BOOL)registerChangeWithName:(NSString* const _Nonnull)name block:(bg_changeBlock)block{
- if ([self.changeBlocks.allKeys containsObject:name]){
- NSString* reason = [NSString stringWithFormat:@"%@表注册监听重复,注册监听失败!",name];
- bg_debug(reason);
- return NO;
- }else{
- [self.changeBlocks setObject:block forKey:name];
- return YES;
- }
- }
- /**
- 移除数据变化监听.
- */
- -(BOOL)removeChangeWithName:(NSString* const _Nonnull)name{
- if ([self.changeBlocks.allKeys containsObject:name]){
- [self.changeBlocks removeObjectForKey:name];
- return YES;
- }else{
- NSString* reason = [NSString stringWithFormat:@"%@表还没有注册监听,移除监听失败!",name];
- bg_debug(reason);
- return NO;
- }
- }
- -(void)doChangeWithName:(NSString* const _Nonnull)name flag:(BOOL)flag state:(bg_changeState)state{
- if(flag && self.changeBlocks.count>0){
- //开一个子线程去执行block,防止死锁.
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0), ^{
- [self.changeBlocks enumerateKeysAndObjectsUsingBlock:^(NSString* _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop){
- NSString* tablename = [key componentsSeparatedByString:@"*"].firstObject;
- if([name isEqualToString:tablename]){
- void(^block)(bg_changeState) = obj;
- //返回主线程回调.
- dispatch_sync(dispatch_get_main_queue(), ^{
- block(state);
- });
- }
- }];
- });
- }
- }
- /**
- 数据库中是否存在表.
- */
- -(void)isExistWithTableName:(NSString* _Nonnull)name complete:(bg_complete_B)complete{
- NSAssert(name,@"表名不能为空!");
- __block BOOL result;
- [self executeDB:^(FMDatabase * _Nonnull db) {
- result = [db tableExists:name];
- }];
- bg_completeBlock(result);
- }
- /**
- 对用户暴露的
- */
- -(BOOL)bg_isExistWithTableName:( NSString* _Nonnull)name{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- NSAssert(name,@"表名不能为空!");
- __block BOOL result;
- [self executeDB:^(FMDatabase * _Nonnull db) {
- result = [db tableExists:name];
- }];
- dispatch_semaphore_signal(self.semaphore);
- return result;
- }
- /**
- 创建表(如果存在则不创建).
- */
- -(void)createTableWithTableName:(NSString* _Nonnull)name keys:(NSArray<NSString*>* _Nonnull)keys unionPrimaryKeys:(NSArray* _Nullable)unionPrimaryKeys uniqueKeys:(NSArray* _Nullable)uniqueKeys complete:(bg_complete_B)complete{
- NSAssert(name,@"表名不能为空!");
- NSAssert(keys,@"字段数组不能为空!");
- //创表
- __block BOOL result;
- [self executeDB:^(FMDatabase * _Nonnull db) {
- NSString* header = [NSString stringWithFormat:@"create table if not exists %@ (",name];
- NSMutableString* sql = [[NSMutableString alloc] init];
- [sql appendString:header];
- NSInteger uniqueKeyFlag = uniqueKeys.count;
- NSMutableArray* tempUniqueKeys = [NSMutableArray arrayWithArray:uniqueKeys];
- for(int i=0;i<keys.count;i++){
- NSString* key = [keys[i] componentsSeparatedByString:@"*"][0];
-
- if(tempUniqueKeys.count && [tempUniqueKeys containsObject:key]){
- for(NSString* uniqueKey in tempUniqueKeys){
- if([BGTool isUniqueKey:uniqueKey with:keys[i]]){
- [sql appendFormat:@"%@ unique",[BGTool keyAndType:keys[i]]];
- [tempUniqueKeys removeObject:uniqueKey];
- uniqueKeyFlag--;
- break;
- }
- }
- }else{
- if ([key isEqualToString:bg_primaryKey] && !unionPrimaryKeys.count){
- [sql appendFormat:@"%@ primary key autoincrement",[BGTool keyAndType:keys[i]]];
- }else{
- [sql appendString:[BGTool keyAndType:keys[i]]];
- }
- }
-
- if (i == (keys.count-1)) {
- if(unionPrimaryKeys.count){
- [sql appendString:@",primary key ("];
- [unionPrimaryKeys enumerateObjectsUsingBlock:^(id _Nonnull unionKey, NSUInteger idx, BOOL * _Nonnull stop) {
- if(idx == 0){
- [sql appendString:bg_sqlKey(unionKey)];
- }else{
- [sql appendFormat:@",%@",bg_sqlKey(unionKey)];
- }
- }];
- [sql appendString:@")"];
- }
- [sql appendString:@");"];
- }else{
- [sql appendString:@","];
- }
-
- }//for over
-
- if(uniqueKeys.count){
- NSAssert(!uniqueKeyFlag,@"没有找到设置的'唯一约束',请检查模型类.m文件的bg_uniqueKeys函数返回值是否正确!");
- }
-
- bg_debug(sql);
- result = [db executeUpdate:sql];
- }];
-
- bg_completeBlock(result);
- }
- -(NSInteger)getKeyMaxForTable:(NSString*)name key:(NSString*)key db:(FMDatabase*)db{
- __block NSInteger num = 0;
- [db executeStatements:[NSString stringWithFormat:@"select max(%@) from %@",key,name] withResultBlock:^int(NSDictionary *resultsDictionary){
- id dbResult = [resultsDictionary.allValues lastObject];
- if(dbResult && ![dbResult isKindOfClass:[NSNull class]]) {
- num = [dbResult integerValue];
- }
- return 0;
- }];
- return num;
- }
- /**
- 插入数据.
- */
- -(void)insertIntoTableName:(NSString* _Nonnull)name Dict:(NSDictionary* _Nonnull)dict complete:(bg_complete_B)complete{
- NSAssert(name,@"表名不能为空!");
- NSAssert(dict,@"插入值字典不能为空!");
- __block BOOL result;
- [self executeDB:^(FMDatabase * _Nonnull db) {
- NSArray* keys = dict.allKeys;
- if([keys containsObject:bg_sqlKey(bg_primaryKey)]){
- NSInteger num = [self getKeyMaxForTable:name key:bg_sqlKey(bg_primaryKey) db:db];
- [dict setValue:@(num+1) forKey:bg_sqlKey(bg_primaryKey)];
- }
- NSArray* values = dict.allValues;
- NSMutableString* SQL = [[NSMutableString alloc] init];
- [SQL appendFormat:@"insert into %@(",name];
- for(int i=0;i<keys.count;i++){
- [SQL appendFormat:@"%@",keys[i]];
- if(i == (keys.count-1)){
- [SQL appendString:@") "];
- }else{
- [SQL appendString:@","];
- }
- }
- [SQL appendString:@"values("];
- for(int i=0;i<values.count;i++){
- [SQL appendString:@"?"];
- if(i == (keys.count-1)){
- [SQL appendString:@");"];
- }else{
- [SQL appendString:@","];
- }
- }
-
- bg_debug(SQL);
- result = [db executeUpdate:SQL withArgumentsInArray:values];
- }];
- //数据监听执行函数
- [self doChangeWithName:name flag:result state:bg_insert];
- bg_completeBlock(result);
- }
- /**
- 批量插入
- */
- -(void)insertIntoTableName:(NSString* _Nonnull)name DictArray:(NSArray<NSDictionary*>* _Nonnull)dictArray complete:(bg_complete_B)complete{
- NSAssert(name,@"表名不能为空!");
- __block BOOL result;
- [self executeDB:^(FMDatabase * _Nonnull db) {
- [db beginTransaction];
- __block NSInteger counter = 0;
- [dictArray enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull dict, NSUInteger idx, BOOL * _Nonnull stop) {
- @autoreleasepool {
- NSArray* keys = dict.allKeys;
- NSArray* values = dict.allValues;
- NSMutableString* SQL = [[NSMutableString alloc] init];
- [SQL appendFormat:@"insert into %@(",name];
- for(int i=0;i<keys.count;i++){
- [SQL appendFormat:@"%@",keys[i]];
- if(i == (keys.count-1)){
- [SQL appendString:@") "];
- }else{
- [SQL appendString:@","];
- }
- }
- [SQL appendString:@"values("];
- for(int i=0;i<values.count;i++){
- [SQL appendString:@"?"];
- if(i == (keys.count-1)){
- [SQL appendString:@");"];
- }else{
- [SQL appendString:@","];
- }
- }
- bg_debug(SQL);
- BOOL flag = [db executeUpdate:SQL withArgumentsInArray:values];
- if(flag){
- counter++;
- }else{
- *stop=YES;
- }
- }
- }];
-
- if(dictArray.count == counter){
- result = YES;
- [db commit];
- }else{
- result = NO;
- [db rollback];
- }
-
- }];
- //数据监听执行函数
- [self doChangeWithName:name flag:result state:bg_insert];
- bg_completeBlock(result);
- }
- /**
- 批量更新
- over
- */
- -(void)updateSetTableName:(NSString* _Nonnull)name class:(__unsafe_unretained _Nonnull Class)cla DictArray:(NSArray<NSDictionary*>* _Nonnull)dictArray complete:(bg_complete_B)complete{
- __block BOOL result;
- [self executeDB:^(FMDatabase * _Nonnull db) {
- [db beginTransaction];
- __block NSInteger counter = 0;
- [dictArray enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull dict, NSUInteger idx, BOOL * _Nonnull stop) {
- @autoreleasepool {
- NSArray* uniqueKeys = [BGTool executeSelector:bg_uniqueKeysSelector forClass:cla];
- NSMutableDictionary* tempDict = [[NSMutableDictionary alloc] initWithDictionary:dict];
- NSMutableString* where = [NSMutableString new];
- if(uniqueKeys.count > 1){
- [where appendString:@" where"];
- [uniqueKeys enumerateObjectsUsingBlock:^(NSString* _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop){
- NSString* uniqueKey = bg_sqlKey(obj);
- id uniqueKeyVlaue = tempDict[uniqueKey];
- if(idx < (uniqueKeys.count-1)){
- [where appendFormat:@" %@=%@ or",uniqueKey,bg_sqlValue(uniqueKeyVlaue)];
- }else{
- [where appendFormat:@" %@=%@",uniqueKey,bg_sqlValue(uniqueKeyVlaue)];
- }
- [tempDict removeObjectForKey:uniqueKey];
- }];
- }else if(uniqueKeys.count == 1){
- NSString* uniqueKey = bg_sqlKey([uniqueKeys firstObject]);
- id uniqueKeyVlaue = tempDict[uniqueKey];
- [where appendFormat:@" where %@=%@",uniqueKey,bg_sqlValue(uniqueKeyVlaue)];
- [tempDict removeObjectForKey:uniqueKey];
- }else if([dict.allKeys containsObject:bg_sqlKey(bg_primaryKey)]){
- NSString* primaryKey = bg_sqlKey(bg_primaryKey);
- id primaryKeyVlaue = tempDict[primaryKey];
- [where appendFormat:@" where %@=%@",primaryKey,bg_sqlValue(primaryKeyVlaue)];
- [tempDict removeObjectForKey:primaryKey];
- }else;
-
- NSMutableArray* arguments = [NSMutableArray array];
- NSMutableString* SQL = [[NSMutableString alloc] init];
- [SQL appendFormat:@"update %@ set ",name];
- [tempDict enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
- [SQL appendFormat:@"%@=?,",key];
- [arguments addObject:obj];
- }];
- SQL = [NSMutableString stringWithString:[SQL substringToIndex:SQL.length-1]];
- if(where.length) {
- [SQL appendString:where];
- }
- bg_debug(SQL);
- BOOL flag = [db executeUpdate:SQL withArgumentsInArray:arguments];
- if(flag){
- counter++;
- }
- }
- }];
-
- if (dictArray.count == counter){
- result = YES;
- [db commit];
- }else{
- result = NO;
- [db rollback];
- }
-
- }];
- //数据监听执行函数
- [self doChangeWithName:name flag:result state:bg_update];
- bg_completeBlock(result);
- }
- /**
- 批量插入或更新.
- */
- -(void)bg_saveOrUpdateWithTableName:(NSString* _Nonnull)tablename class:(__unsafe_unretained _Nonnull Class)cla DictArray:(NSArray<NSDictionary*>* _Nonnull)dictArray complete:(bg_complete_B)complete{
- __block BOOL result;
- [self executeDB:^(FMDatabase * _Nonnull db) {
- [db beginTransaction];
- __block NSInteger counter = 0;
- [dictArray enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull dict, NSUInteger idx, BOOL * _Nonnull stop) {
- @autoreleasepool {
- NSString* bg_id = bg_sqlKey(bg_primaryKey);
- //获得"唯一约束"
- NSArray* uniqueKeys = [BGTool executeSelector:bg_uniqueKeysSelector forClass:cla];
- //获得"联合主键"
- NSArray* unionPrimaryKeys =[BGTool executeSelector:bg_unionPrimaryKeysSelector forClass:cla];
- NSMutableDictionary* tempDict = [[NSMutableDictionary alloc] initWithDictionary:dict];
- NSMutableString* where = [NSMutableString new];
- BOOL isSave = NO;//是否存储还是更新.
- if(uniqueKeys.count || unionPrimaryKeys.count){
- NSArray* tempKeys;
- NSString* orAnd;
-
- if(unionPrimaryKeys.count){
- tempKeys = unionPrimaryKeys;
- orAnd = @"and";
- }else{
- tempKeys = uniqueKeys;
- orAnd = @"or";
- }
-
- if(tempKeys.count == 1){
- NSString* tempkey = bg_sqlKey([tempKeys firstObject]);
- id tempkeyVlaue = tempDict[tempkey];
- [where appendFormat:@" where %@=%@",tempkey,bg_sqlValue(tempkeyVlaue)];
- }else{
- [where appendString:@" where"];
- [tempKeys enumerateObjectsUsingBlock:^(NSString* _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop){
- NSString* tempkey = bg_sqlKey(obj);
- id tempkeyVlaue = tempDict[tempkey];
- if(idx < (tempKeys.count-1)){
- [where appendFormat:@" %@=%@ %@",tempkey,bg_sqlValue(tempkeyVlaue),orAnd];
- }else{
- [where appendFormat:@" %@=%@",tempkey,bg_sqlValue(tempkeyVlaue)];
- }
- }];
- }
- NSString* dataCountSql = [NSString stringWithFormat:@"select count(*) from %@%@",tablename,where];
- __block NSInteger dataCount = 0;
- [db executeStatements:dataCountSql withResultBlock:^int(NSDictionary *resultsDictionary) {
- dataCount = [[resultsDictionary.allValues lastObject] integerValue];
- return 0;
- }];
- bg_debug(dataCountSql);
- if(dataCount){
- //更新操作
- [tempKeys enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
- [tempDict removeObjectForKey:bg_sqlKey(obj)];
- }];
- }else{
- //插入操作
- isSave = YES;
- }
- }else{
- if([tempDict.allKeys containsObject:bg_id]){
- //更新操作
- id primaryKeyVlaue = tempDict[bg_id];
- [where appendFormat:@" where %@=%@",bg_id,bg_sqlValue(primaryKeyVlaue)];
- }else{
- //插入操作
- isSave = YES;
- }
- }
-
- NSMutableString* SQL = [[NSMutableString alloc] init];
- NSMutableArray* arguments = [NSMutableArray array];
- if(isSave){//存储操作
- NSInteger num = [self getKeyMaxForTable:tablename key:bg_id db:db];
- [tempDict setValue:@(num+1) forKey:bg_id];
- [SQL appendFormat:@"insert into %@(",tablename];
- NSArray* keys = tempDict.allKeys;
- NSArray* values = tempDict.allValues;
- for(int i=0;i<keys.count;i++){
- [SQL appendFormat:@"%@",keys[i]];
- if(i == (keys.count-1)){
- [SQL appendString:@") "];
- }else{
- [SQL appendString:@","];
- }
- }
- [SQL appendString:@"values("];
- for(int i=0;i<values.count;i++){
- [SQL appendString:@"?"];
- if(i == (keys.count-1)){
- [SQL appendString:@");"];
- }else{
- [SQL appendString:@","];
- }
- [arguments addObject:values[i]];
- }
- }else{//更新操作
- if([tempDict.allKeys containsObject:bg_id]){
- [tempDict removeObjectForKey:bg_id];//移除主键
- }
- [tempDict removeObjectForKey:bg_sqlKey(bg_createTimeKey)];//移除创建时间
- [SQL appendFormat:@"update %@ set ",tablename];
- [tempDict enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
- [SQL appendFormat:@"%@=?,",key];
- [arguments addObject:obj];
- }];
- SQL = [NSMutableString stringWithString:[SQL substringToIndex:SQL.length-1]];
- if(where.length) {
- [SQL appendString:where];
- }
- }
-
-
- bg_debug(SQL);
- BOOL flag = [db executeUpdate:SQL withArgumentsInArray:arguments];
- if(flag){
- counter++;
- }
- }
- }];
-
- if (dictArray.count == counter){
- result = YES;
- [db commit];
- }else{
- result = NO;
- [db rollback];
- }
-
- }];
- //数据监听执行函数
- [self doChangeWithName:tablename flag:result state:bg_update];
- bg_completeBlock(result);
- }
- -(void)queryQueueWithTableName:(NSString* _Nonnull)name conditions:(NSString* _Nullable)conditions complete:(bg_complete_A)complete{
- NSAssert(name,@"表名不能为空!");
- __block NSMutableArray* arrM = nil;
- [self executeDB:^(FMDatabase * _Nonnull db){
- NSString* SQL = conditions?[NSString stringWithFormat:@"select * from %@ %@",name,conditions]:[NSString stringWithFormat:@"select * from %@",name];
- bg_debug(SQL);
- // 1.查询数据
- FMResultSet *rs = [db executeQuery:SQL];
- if (rs == nil) {
- bg_debug(@"查询错误,可能是'类变量名'发生了改变或'字段','表格'不存在!,请存储后再读取!");
- }else{
- arrM = [[NSMutableArray alloc] init];
- }
- // 2.遍历结果集
- while (rs.next) {
- NSMutableDictionary* dictM = [[NSMutableDictionary alloc] init];
- for (int i=0;i<[[[rs columnNameToIndexMap] allKeys] count];i++) {
- dictM[[rs columnNameForIndex:i]] = [rs objectForColumnIndex:i];
- }
- [arrM addObject:dictM];
- }
- //查询完后要关闭rs,不然会报@"Warning: there is at least one open result set around after performing
- [rs close];
- }];
-
- bg_completeBlock(arrM);
- }
- /**
- 直接传入条件sql语句查询
- */
- -(void)queryWithTableName:(NSString* _Nonnull)name conditions:(NSString* _Nullable)conditions complete:(bg_complete_A)complete{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- @autoreleasepool {
- [self queryQueueWithTableName:name conditions:conditions complete:complete];
- }
- dispatch_semaphore_signal(self.semaphore);
- }
- /**
- 根据条件查询字段.
- */
- -(void)queryWithTableName:(NSString* _Nonnull)name keys:(NSArray<NSString*>* _Nullable)keys where:(NSArray* _Nullable)where complete:(bg_complete_A)complete{
- NSAssert(name,@"表名不能为空!");
- NSMutableArray* arrM = [[NSMutableArray alloc] init];
- __block NSArray* arguments;
- [self executeDB:^(FMDatabase * _Nonnull db) {
- NSMutableString* SQL = [[NSMutableString alloc] init];
- [SQL appendString:@"select"];
- if ((keys!=nil)&&(keys.count>0)) {
- [SQL appendString:@" "];
- for(int i=0;i<keys.count;i++){
- [SQL appendFormat:@"%@%@",BG,keys[i]];
- if (i != (keys.count-1)) {
- [SQL appendString:@","];
- }
- }
- }else{
- [SQL appendString:@" *"];
- }
- [SQL appendFormat:@" from %@",name];
-
- if(where && (where.count>0)){
- NSArray* results = [BGTool where:where];
- [SQL appendString:results[0]];
- arguments = results[1];
- }
-
- bg_debug(SQL);
- // 1.查询数据
- FMResultSet *rs = [db executeQuery:SQL withArgumentsInArray:arguments];
- if (rs == nil) {
- bg_debug(@"查询错误,可能是'类变量名'发生了改变或'字段','表格'不存在!,请存储后再读取,或检查条件数组'字段名称'是否正确");
- }
- // 2.遍历结果集
- while (rs.next) {
- NSMutableDictionary* dictM = [[NSMutableDictionary alloc] init];
- for (int i=0;i<[[[rs columnNameToIndexMap] allKeys] count];i++) {
- dictM[[rs columnNameForIndex:i]] = [rs objectForColumnIndex:i];
- }
- [arrM addObject:dictM];
- }
- //查询完后要关闭rs,不然会报@"Warning: there is at least one open result set around after performing
- [rs close];
- }];
-
- bg_completeBlock(arrM);
- }
- /**
- 查询对象.
- */
- -(void)queryWithTableName:(NSString* _Nonnull)name where:(NSString* _Nullable)where complete:(bg_complete_A)complete{
- NSAssert(name,@"表名不能为空!");
- NSMutableArray* arrM = [[NSMutableArray alloc] init];
- [self executeDB:^(FMDatabase * _Nonnull db) {
- NSMutableString* SQL = [NSMutableString string];
- [SQL appendFormat:@"select * from %@",name];
- !where?:[SQL appendFormat:@" %@",where];
- bg_debug(SQL);
- // 1.查询数据
- FMResultSet *rs = [db executeQuery:SQL];
- if (rs == nil) {
- bg_debug(@"查询错误,'表格'不存在!,请存储后再读取!");
- }
- // 2.遍历结果集
- while (rs.next) {
- NSMutableDictionary* dictM = [[NSMutableDictionary alloc] init];
- for (int i=0;i<[[[rs columnNameToIndexMap] allKeys] count];i++) {
- dictM[[rs columnNameForIndex:i]] = [rs objectForColumnIndex:i];
- }
- [arrM addObject:dictM];
- }
- //查询完后要关闭rs,不然会报@"Warning: there is at least one open result set around after performing
- [rs close];
- }];
-
- bg_completeBlock(arrM);
- }
- /**
- 更新数据.
- */
- -(void)updateWithTableName:(NSString* _Nonnull)name valueDict:(NSDictionary* _Nonnull)valueDict where:(NSArray* _Nullable)where complete:(bg_complete_B)complete{
- NSAssert(name,@"表名不能为空!");
- NSAssert(valueDict,@"更新数据集合不能为空!");
- __block BOOL result;
- NSMutableArray* arguments = [NSMutableArray array];
- [self executeDB:^(FMDatabase * _Nonnull db) {
- NSMutableString* SQL = [[NSMutableString alloc] init];
- [SQL appendFormat:@"update %@ set ",name];
- for(int i=0;i<valueDict.allKeys.count;i++){
- [SQL appendFormat:@"%@=?",valueDict.allKeys[i]];
- [arguments addObject:valueDict[valueDict.allKeys[i]]];
- if (i != (valueDict.allKeys.count-1)) {
- [SQL appendString:@","];
- }
- }
-
- if(where && (where.count>0)){
- NSArray* results = [BGTool where:where];
- [SQL appendString:results[0]];
- [arguments addObjectsFromArray:results[1]];
- }
-
- bg_debug(SQL);
- result = [db executeUpdate:SQL withArgumentsInArray:arguments];
- }];
-
- //数据监听执行函数
- [self doChangeWithName:name flag:result state:bg_update];
- bg_completeBlock(result);
- }
- -(void)updateQueueWithTableName:(NSString* _Nonnull)name valueDict:(NSDictionary* _Nullable)valueDict conditions:(NSString* _Nonnull)conditions complete:(bg_complete_B)complete{
- NSAssert(name,@"表名不能为空!");
- __block BOOL result;
- [self executeDB:^(FMDatabase * _Nonnull db){
- NSString* SQL;
- if (!valueDict || !valueDict.count) {
- SQL = [NSString stringWithFormat:@"update %@ %@",name,conditions];
- }else{
- NSMutableString* param = [NSMutableString stringWithFormat:@"update %@ set ",name];
- for(int i=0;i<valueDict.allKeys.count;i++){
- NSString* key = valueDict.allKeys[i];
- [param appendFormat:@"%@=?",key];
- if(i != (valueDict.allKeys.count-1)) {
- [param appendString:@","];
- }
- }
- [param appendFormat:@" %@",conditions];
- SQL = param;
- }
- bg_debug(SQL);
- result = [db executeUpdate:SQL withArgumentsInArray:valueDict.allValues];
- }];
-
- //数据监听执行函数
- [self doChangeWithName:name flag:result state:bg_update];
- bg_completeBlock(result);
- }
- /**
- 直接传入条件sql语句更新.
- */
- -(void)updateWithObject:(id _Nonnull)object valueDict:(NSDictionary* _Nullable)valueDict conditions:(NSString* _Nonnull)conditions complete:(bg_complete_B)complete{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- @autoreleasepool {
- //自动判断是否有字段改变,自动刷新数据库.
- [self ifIvarChangeForObject:object ignoredKeys:[BGTool executeSelector:bg_ignoreKeysSelector forClass:[object class]]];
- NSString* tablename = [BGTool getTableNameWithObject:object];
- [self updateQueueWithTableName:tablename valueDict:valueDict conditions:conditions complete:complete];
- }
- dispatch_semaphore_signal(self.semaphore);
- }
- /**
- 直接传入条件sql语句更新对象.
- */
- -(void)updateObject:(id _Nonnull)object ignoreKeys:(NSArray* const _Nullable)ignoreKeys conditions:(NSString* _Nonnull)conditions complete:(bg_complete_B)complete{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- @autoreleasepool {
- NSString* tableName = [BGTool getTableNameWithObject:object];
- //自动判断是否有字段改变,自动刷新数据库.
- [self ifIvarChangeForObject:object ignoredKeys:ignoreKeys];
- NSDictionary* valueDict = [BGTool getDictWithObject:self ignoredKeys:ignoreKeys filtModelInfoType:bg_ModelInfoSingleUpdate];
- [self updateQueueWithTableName:tableName valueDict:valueDict conditions:conditions complete:complete];
- }
- dispatch_semaphore_signal(self.semaphore);
- }
- /**
- 根据keypath更新数据
- */
- -(void)updateWithTableName:(NSString* _Nonnull)name forKeyPathAndValues:(NSArray* _Nonnull)keyPathValues valueDict:(NSDictionary* _Nonnull)valueDict complete:(bg_complete_B)complete{
- NSString* like = [BGTool getLikeWithKeyPathAndValues:keyPathValues where:YES];
- NSMutableArray* arguments = [NSMutableArray array];
- __block BOOL result;
- [self executeDB:^(FMDatabase * _Nonnull db){
- NSMutableString* SQL = [[NSMutableString alloc] init];
- [SQL appendFormat:@"update %@ set ",name];
- for(int i=0;i<valueDict.allKeys.count;i++){
- [SQL appendFormat:@"%@=?",valueDict.allKeys[i]];
- [arguments addObject:valueDict[valueDict.allKeys[i]]];
- if (i != (valueDict.allKeys.count-1)) {
- [SQL appendString:@","];
- }
- }
- [SQL appendString:like];
- result = [db executeUpdate:SQL withArgumentsInArray:arguments];
- bg_debug(SQL);
- }];
-
- //数据监听执行函数
- [self doChangeWithName:name flag:result state:bg_update];
- bg_completeBlock(result);
- }
- /**
- 根据条件删除数据.
- */
- -(void)deleteWithTableName:(NSString* _Nonnull)name where:(NSArray* _Nonnull)where complete:(bg_complete_B)complete{
- NSAssert(name,@"表名不能为空!");
- NSAssert(where,@"条件数组错误! 不能为空");
- __block BOOL result;
- NSMutableArray* arguments = [NSMutableArray array];
- [self executeDB:^(FMDatabase * _Nonnull db) {
- NSMutableString* SQL = [[NSMutableString alloc] init];
- [SQL appendFormat:@"delete from %@",name];
-
- if(where && (where.count>0)){
- NSArray* results = [BGTool where:where];
- [SQL appendString:results[0]];
- [arguments addObjectsFromArray:results[1]];
- }
-
- bg_debug(SQL);
- result = [db executeUpdate:SQL withArgumentsInArray:arguments];
- }];
-
- //数据监听执行函数
- [self doChangeWithName:name flag:result state:bg_delete];
- bg_completeBlock(result);
- }
- -(void)deleteQueueWithTableName:(NSString* _Nonnull)name conditions:(NSString* _Nullable)conditions complete:(bg_complete_B)complete{
- NSAssert(name,@"表名不能为空!");
- __block BOOL result;
- [self executeDB:^(FMDatabase * _Nonnull db) {
- NSString* SQL = conditions?[NSString stringWithFormat:@"delete from %@ %@",name,conditions]:[NSString stringWithFormat:@"delete from %@",name];
- bg_debug(SQL);
- result = [db executeUpdate:SQL];
- }];
-
- //数据监听执行函数
- [self doChangeWithName:name flag:result state:bg_delete];
- bg_completeBlock(result);
- }
- /**
- 直接传入条件sql语句删除.
- */
- -(void)deleteWithTableName:(NSString* _Nonnull)name conditions:(NSString* _Nullable)conditions complete:(bg_complete_B)complete{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- [self deleteQueueWithTableName:name conditions:conditions complete:complete];
- dispatch_semaphore_signal(self.semaphore);
- }
- -(void)deleteQueueWithTableName:(NSString* _Nonnull)name forKeyPathAndValues:(NSArray* _Nonnull)keyPathValues complete:(bg_complete_B)complete{
- NSAssert(name,@"表名不能为空!");
- NSString* like = [BGTool getLikeWithKeyPathAndValues:keyPathValues where:YES];
- __block BOOL result;
- [self executeDB:^(FMDatabase * _Nonnull db) {
- NSMutableString* SQL = [[NSMutableString alloc] init];
- [SQL appendFormat:@"delete from %@%@",name,like];
- bg_debug(SQL);
- result = [db executeUpdate:SQL];
- }];
-
- //数据监听执行函数
- [self doChangeWithName:name flag:result state:bg_delete];
- bg_completeBlock(result);
- }
- //根据keypath删除表内容.
- -(void)deleteWithTableName:(NSString* _Nonnull)name forKeyPathAndValues:(NSArray* _Nonnull)keyPathValues complete:(bg_complete_B)complete{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- [self deleteQueueWithTableName:name forKeyPathAndValues:keyPathValues complete:complete];
- dispatch_semaphore_signal(self.semaphore);
- }
- /**
- 根据表名删除表格全部内容.
- */
- -(void)clearTable:(NSString* _Nonnull)name complete:(bg_complete_B)complete{
- NSAssert(name,@"表名不能为空!");
- __block BOOL result;
- [self executeDB:^(FMDatabase * _Nonnull db) {
- NSString* SQL = [NSString stringWithFormat:@"delete from %@",name];
- bg_debug(SQL);
- result = [db executeUpdate:SQL];
- }];
-
- //数据监听执行函数
- [self doChangeWithName:name flag:result state:bg_delete];
- bg_completeBlock(result);
- }
- /**
- 删除表.
- */
- -(void)dropTable:(NSString* _Nonnull)name complete:(bg_complete_B)complete{
- NSAssert(name,@"表名不能为空!");
- __block BOOL result;
- [self executeDB:^(FMDatabase * _Nonnull db) {
- NSString* SQL = [NSString stringWithFormat:@"drop table %@",name];
- bg_debug(SQL);
- result = [db executeUpdate:SQL];
- }];
-
- //数据监听执行函数
- [self doChangeWithName:name flag:result state:bg_drop];
- bg_completeBlock(result);
- }
- /**
- 删除表(线程安全).
- */
- -(void)dropSafeTable:(NSString* _Nonnull)name complete:(bg_complete_B)complete{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- @autoreleasepool {
- [self dropTable:name complete:complete];
- }
- dispatch_semaphore_signal(self.semaphore);
- }
- /**
- 动态添加表字段.
- */
- -(void)addTable:(NSString* _Nonnull)name key:(NSString* _Nonnull)key complete:(bg_complete_B)complete{
- NSAssert(name,@"表名不能为空!");
- __block BOOL result;
- [self executeDB:^(FMDatabase * _Nonnull db) {
- NSString* SQL = [NSString stringWithFormat:@"alter table %@ add %@;",name,[BGTool keyAndType:key]];
- bg_debug(SQL);
- result = [db executeUpdate:SQL];
- }];
- bg_completeBlock(result);
- }
- /**
- 查询该表中有多少条数据
- */
- -(NSInteger)countQueueForTable:(NSString* _Nonnull)name where:(NSArray* _Nullable)where{
- NSAssert(name,@"表名不能为空!");
- NSAssert(!(where.count%3),@"条件数组错误!");
- NSMutableString* strM = [NSMutableString string];
- !where?:[strM appendString:@" where "];
- for(int i=0;i<where.count;i+=3){
- if ([where[i+2] isKindOfClass:[NSString class]]) {
- [strM appendFormat:@"%@%@%@'%@'",BG,where[i],where[i+1],where[i+2]];
- }else{
- [strM appendFormat:@"%@%@%@%@",BG,where[i],where[i+1],where[i+2]];
- }
-
- if (i != (where.count-3)) {
- [strM appendString:@" and "];
- }
- }
- __block NSUInteger count=0;
- [self executeDB:^(FMDatabase * _Nonnull db) {
- NSString* SQL = [NSString stringWithFormat:@"select count(*) from %@%@",name,strM];
- bg_debug(SQL);
- [db executeStatements:SQL withResultBlock:^int(NSDictionary *resultsDictionary) {
- count = [[resultsDictionary.allValues lastObject] integerValue];
- return 0;
- }];
- }];
- return count;
- }
- /**
- 查询该表中有多少条数据
- */
- -(NSInteger)countForTable:(NSString* _Nonnull)name where:(NSArray* _Nullable)where{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- NSInteger count = 0;
- @autoreleasepool {
- count = [self countQueueForTable:name where:where];
- }
- dispatch_semaphore_signal(self.semaphore);
- return count;
- }
- /**
- 直接传入条件sql语句查询数据条数.
- */
- -(NSInteger)countQueueForTable:(NSString* _Nonnull)name conditions:(NSString* _Nullable)conditions{
- NSAssert(name,@"表名不能为空!");
- __block NSUInteger count=0;
- [self executeDB:^(FMDatabase * _Nonnull db) {
- NSString* SQL = conditions?[NSString stringWithFormat:@"select count(*) from %@ %@",name,conditions]:[NSString stringWithFormat:@"select count(*) from %@",name];
- bg_debug(SQL);
- [db executeStatements:SQL withResultBlock:^int(NSDictionary *resultsDictionary) {
- count = [[resultsDictionary.allValues lastObject] integerValue];
- return 0;
- }];
- }];
- return count;
- }
- /**
- 直接传入条件sql语句查询数据条数.
- */
- -(NSInteger)countForTable:(NSString* _Nonnull)name conditions:(NSString* _Nullable)conditions{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- NSInteger count = 0;
- @autoreleasepool {
- count = [self countQueueForTable:name conditions:conditions];
- }
- dispatch_semaphore_signal(self.semaphore);
- return count;
- }
- /**
- 直接调用sqliteb的原生函数计算sun,min,max,avg等.
- */
- -(double)sqliteMethodQueueForTable:(NSString* _Nonnull)name type:(bg_sqliteMethodType)methodType key:(NSString*)key where:(NSString* _Nullable)where{
- NSAssert(name,@"表名不能为空!");
- NSAssert(key,@"属性名不能为空!");
- __block double num = 0.0;
- NSString* method;
- switch (methodType) {
- case bg_min:
- method = [NSString stringWithFormat:@"min(%@%@)",BG,key];
- break;
- case bg_max:
- method = [NSString stringWithFormat:@"max(%@%@)",BG,key];
- break;
- case bg_sum:
- method = [NSString stringWithFormat:@"sum(%@%@)",BG,key];
- break;
- case bg_avg:
- method = [NSString stringWithFormat:@"avg(%@%@)",BG,key];
- break;
- default:
- NSAssert(NO,@"请传入方法类型!");
- break;
- }
- [self executeDB:^(FMDatabase * _Nonnull db){
- NSString* SQL;
- if(where){
- SQL = [NSString stringWithFormat:@"select %@ from %@ %@",method,name,where];
- }else{
- SQL = [NSString stringWithFormat:@"select %@ from %@",method,name];
- }
- bg_debug(SQL);
- [db executeStatements:SQL withResultBlock:^int(NSDictionary *resultsDictionary){
- id dbResult = [resultsDictionary.allValues lastObject];
- if(dbResult && ![dbResult isKindOfClass:[NSNull class]]) {
- num = [dbResult doubleValue];
- }
- return 0;
- }];
- }];
- return num;
- }
- /**
- 直接调用sqliteb的原生函数计算sun,min,max,avg等.
- */
- -(double)sqliteMethodForTable:(NSString* _Nonnull)name type:(bg_sqliteMethodType)methodType key:(NSString*)key where:(NSString* _Nullable)where{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- double num = 0.0;
- @autoreleasepool {
- num = [self sqliteMethodQueueForTable:name type:methodType key:key where:where];
- }
- dispatch_semaphore_signal(self.semaphore);
- return num;
- }
- /**
- keyPath查询数据条数.
- */
- -(NSInteger)countQueueForTable:(NSString* _Nonnull)name forKeyPathAndValues:(NSArray* _Nonnull)keyPathValues{
- NSString* like = [BGTool getLikeWithKeyPathAndValues:keyPathValues where:YES];
- __block NSUInteger count=0;
- [self executeDB:^(FMDatabase * _Nonnull db) {
- NSString* SQL = [NSString stringWithFormat:@"select count(*) from %@%@",name,like];
- bg_debug(SQL);
- [db executeStatements:SQL withResultBlock:^int(NSDictionary *resultsDictionary) {
- count = [[resultsDictionary.allValues lastObject] integerValue];
- return 0;
- }];
- }];
- return count;
- }
- /**
- keyPath查询数据条数.
- */
- -(NSInteger)countForTable:(NSString* _Nonnull)name forKeyPathAndValues:(NSArray* _Nonnull)keyPathValues{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- NSInteger count = 0;
- @autoreleasepool {
- count = [self countQueueForTable:name forKeyPathAndValues:keyPathValues];
- }
- dispatch_semaphore_signal(self.semaphore);
- return count;
- }
- -(void)copyA:(NSString* _Nonnull)A toB:(NSString* _Nonnull)B class:(__unsafe_unretained _Nonnull Class)cla keys:(NSArray<NSString*>* const _Nonnull)keys complete:(bg_complete_I)complete{
- //获取"唯一约束"字段名
- NSArray* uniqueKeys = [BGTool executeSelector:bg_uniqueKeysSelector forClass:cla];
- //获取“联合主键”字段名
- NSArray* unionPrimaryKeys = [BGTool executeSelector:bg_unionPrimaryKeysSelector forClass:cla];
- //建立一张临时表
- __block BOOL createFlag;
- [self createTableWithTableName:B keys:keys unionPrimaryKeys:unionPrimaryKeys uniqueKeys:uniqueKeys complete:^(BOOL isSuccess) {
- createFlag = isSuccess;
- }];
- if (!createFlag){
- bg_debug(@"数据库更新失败!");
- bg_completeBlock(bg_error);
- return;
- }
- __block bg_dealState refreshstate = bg_error;
- __block BOOL recordError = NO;
- __block BOOL recordSuccess = NO;
- __weak typeof(self) BGSelf = self;
- NSInteger count = [self countQueueForTable:A where:nil];
- for(NSInteger i=0;i<count;i+=MaxQueryPageNum){
- @autoreleasepool{//由于查询出来的数据量可能巨大,所以加入自动释放池.
- NSString* param = [NSString stringWithFormat:@"limit %@,%@",@(i),@(MaxQueryPageNum)];
- [self queryWithTableName:A where:param complete:^(NSArray * _Nullable array) {
- for(NSDictionary* oldDict in array){
- NSMutableDictionary* newDict = [NSMutableDictionary dictionary];
- for(NSString* keyAndType in keys){
- NSString* key = [keyAndType componentsSeparatedByString:@"*"][0];
- //字段名前加上 @"BG_"
- key = [NSString stringWithFormat:@"%@%@",BG,key];
- if (oldDict[key]){
- newDict[key] = oldDict[key];
- }
- }
- //将旧表的数据插入到新表
- [BGSelf insertIntoTableName:B Dict:newDict complete:^(BOOL isSuccess){
- if (isSuccess){
- if (!recordSuccess) {
- recordSuccess = YES;
- }
- }else{
- if (!recordError) {
- recordError = YES;
- }
- }
-
- }];
- }
- }];
- }
- }
-
- if (complete){
- if (recordError && recordSuccess) {
- refreshstate = bg_incomplete;
- }else if(recordError && !recordSuccess){
- refreshstate = bg_error;
- }else if (recordSuccess && !recordError){
- refreshstate = bg_complete;
- }else;
- complete(refreshstate);
- }
-
- }
- -(void)refreshQueueTable:(NSString* _Nonnull)name class:(__unsafe_unretained _Nonnull Class)cla keys:(NSArray<NSString*>* const _Nonnull)keys complete:(bg_complete_I)complete{
- NSAssert(name,@"表名不能为空!");
- NSAssert(keys,@"字段数组不能为空!");
- [self isExistWithTableName:name complete:^(BOOL isSuccess){
- if (!isSuccess){
- bg_debug(@"没有数据存在,数据库更新失败!");
- bg_completeBlock(bg_error);
- return;
- }
- }];
- NSString* BGTempTable = @"BGTempTable";
- //事务操作.
- __block int recordFailCount = 0;
- [self executeTransation:^BOOL{
- [self copyA:name toB:BGTempTable class:cla keys:keys complete:^(bg_dealState result) {
- if(result == bg_complete){
- recordFailCount++;
- }
- }];
- [self dropTable:name complete:^(BOOL isSuccess) {
- if(isSuccess)recordFailCount++;
- }];
- [self copyA:BGTempTable toB:name class:cla keys:keys complete:^(bg_dealState result) {
- if(result == bg_complete){
- recordFailCount++;
- }
- }];
- [self dropTable:BGTempTable complete:^(BOOL isSuccess) {
- if(isSuccess)recordFailCount++;
- }];
- if(recordFailCount != 4){
- bg_debug(@"发生错误,更新数据库失败!");
- }
- return recordFailCount==4;
- }];
-
- //回调结果.
- if (recordFailCount==0) {
- bg_completeBlock(bg_error);
- }else if (recordFailCount>0&&recordFailCount<4){
- bg_completeBlock(bg_incomplete);
- }else{
- bg_completeBlock(bg_complete);
- }
- }
- /**
- 刷新数据库,即将旧数据库的数据复制到新建的数据库,这是为了去掉没用的字段.
- */
- -(void)refreshTable:(NSString* _Nonnull)name class:(__unsafe_unretained _Nonnull Class)cla keys:(NSArray<NSString*>* const _Nonnull)keys complete:(bg_complete_I)complete{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- @autoreleasepool {
- [self refreshQueueTable:name class:cla keys:keys complete:complete];
- }
- dispatch_semaphore_signal(self.semaphore);
- }
- -(void)copyA:(NSString* _Nonnull)A toB:(NSString* _Nonnull)B keyDict:(NSDictionary* const _Nullable)keyDict complete:(bg_complete_I)complete{
- //获取"唯一约束"字段名
- NSArray* uniqueKeys = [BGTool executeSelector:bg_uniqueKeysSelector forClass:NSClassFromString(A)];
- //获取“联合主键”字段名
- NSArray* unionPrimaryKeys = [BGTool executeSelector:bg_unionPrimaryKeysSelector forClass:NSClassFromString(A)];
- __block NSArray* keys = [BGTool getClassIvarList:NSClassFromString(A) Object:nil onlyKey:NO];
- NSArray* newKeys = keyDict.allKeys;
- NSArray* oldKeys = keyDict.allValues;
- //建立一张临时表
- __block BOOL createFlag;
- [self createTableWithTableName:B keys:keys unionPrimaryKeys:unionPrimaryKeys uniqueKeys:uniqueKeys complete:^(BOOL isSuccess) {
- createFlag = isSuccess;
- }];
- if (!createFlag){
- bg_debug(@"数据库更新失败!");
- bg_completeBlock(bg_error);
- return;
- }
-
- __block bg_dealState refreshstate = bg_error;
- __block BOOL recordError = NO;
- __block BOOL recordSuccess = NO;
- __weak typeof(self) BGSelf = self;
- NSInteger count = [self countQueueForTable:A where:nil];
- for(NSInteger i=0;i<count;i+=MaxQueryPageNum){
- @autoreleasepool{//由于查询出来的数据量可能巨大,所以加入自动释放池.
- NSString* param = [NSString stringWithFormat:@"limit %@,%@",@(i),@(MaxQueryPageNum)];
- [self queryWithTableName:A where:param complete:^(NSArray * _Nullable array) {
- __strong typeof(BGSelf) strongSelf = BGSelf;
- for(NSDictionary* oldDict in array){
- NSMutableDictionary* newDict = [NSMutableDictionary dictionary];
- for(NSString* keyAndType in keys){
- NSString* key = [keyAndType componentsSeparatedByString:@"*"][0];
- //字段名前加上 @"BG_"
- key = [NSString stringWithFormat:@"%@%@",BG,key];
- if (oldDict[key]){
- newDict[key] = oldDict[key];
- }
- }
- for(int i=0;i<oldKeys.count;i++){
- //字段名前加上 @"BG_"
- NSString* oldkey = [NSString stringWithFormat:@"%@%@",BG,oldKeys[i]];
- NSString* newkey = [NSString stringWithFormat:@"%@%@",BG,newKeys[i]];
- if (oldDict[oldkey]){
- newDict[newkey] = oldDict[oldkey];
- }
- }
- //将旧表的数据插入到新表
- [strongSelf insertIntoTableName:B Dict:newDict complete:^(BOOL isSuccess){
-
- if (isSuccess){
- if (!recordSuccess) {
- recordSuccess = YES;
- }
- }else{
- if (!recordError) {
- recordError = YES;
- }
- }
- }];
- }
-
- }];
- }
- }
-
- if (complete){
- if (recordError && recordSuccess) {
- refreshstate = bg_incomplete;
- }else if(recordError && !recordSuccess){
- refreshstate = bg_error;
- }else if (recordSuccess && !recordError){
- refreshstate = bg_complete;
- }else;
- complete(refreshstate);
- }
-
-
- }
- -(void)refreshQueueTable:(NSString* _Nonnull)tablename class:(__unsafe_unretained _Nonnull Class)cla keys:(NSArray* const _Nonnull)keys keyDict:(NSDictionary* const _Nonnull)keyDict complete:(bg_complete_I)complete{
- NSAssert(tablename,@"表名不能为空!");
- NSAssert(keyDict,@"变量名影射集合不能为空!");
- [self isExistWithTableName:tablename complete:^(BOOL isSuccess){
- if (!isSuccess){
- bg_debug(@"没有数据存在,数据库更新失败!");
- bg_completeBlock(bg_error);
- return;
- }
- }];
-
- //事务操作.
- NSString* BGTempTable = @"BGTempTable";
- __block int recordFailCount = 0;
- [self executeTransation:^BOOL{
- [self copyA:tablename toB:BGTempTable keyDict:keyDict complete:^(bg_dealState result) {
- if(result == bg_complete){
- recordFailCount++;
- }
- }];
- [self dropTable:tablename complete:^(BOOL isSuccess) {
- if(isSuccess)recordFailCount++;
- }];
- [self copyA:BGTempTable toB:tablename class:cla keys:keys complete:^(bg_dealState result) {
- if(result == bg_complete){
- recordFailCount++;
- }
- }];
- [self dropTable:BGTempTable complete:^(BOOL isSuccess) {
- if(isSuccess)recordFailCount++;
- }];
- if (recordFailCount != 4) {
- bg_debug(@"发生错误,更新数据库失败!");
- }
- return recordFailCount==4;
- }];
-
- //回调结果.
- if(recordFailCount==0){
- bg_completeBlock(bg_error);
- }else if (recordFailCount>0&&recordFailCount<4){
- bg_completeBlock(bg_incomplete);
- }else{
- bg_completeBlock(bg_complete);
- }
-
- }
- -(void)refreshTable:(NSString* _Nonnull)name class:(__unsafe_unretained _Nonnull Class)cla keys:(NSArray* const _Nonnull)keys keyDict:(NSDictionary* const _Nonnull)keyDict complete:(bg_complete_I)complete{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- @autoreleasepool {
- [self refreshQueueTable:name class:cla keys:keys keyDict:keyDict complete:complete];
- }
- dispatch_semaphore_signal(self.semaphore);
- }
- /**
- 判断类属性是否有改变,智能刷新.
- */
- -(void)ifIvarChangeForObject:(id)object ignoredKeys:(NSArray*)ignoredkeys{
- //获取缓存的属性信息
- NSCache* cache = [NSCache bg_cache];
- NSString *tableName = [object valueForKey:bg_tableNameKey];
- tableName = tableName.length ? tableName : NSStringFromClass([object class]);
- NSString* cacheKey = [NSString stringWithFormat:@"%@_IvarChangeState",tableName];
- id IvarChangeState = [cache objectForKey:cacheKey];
- if(IvarChangeState){
- return;
- }else{
- [cache setObject:@(YES) forKey:cacheKey];
- }
-
- @autoreleasepool {
- //获取表名
- NSString* tableName = [BGTool getTableNameWithObject:object];
- NSMutableArray* newKeys = [NSMutableArray array];
- NSMutableArray* sqlKeys = [NSMutableArray array];
- [self executeDB:^(FMDatabase * _Nonnull db) {
- NSString* SQL = [NSString stringWithFormat:@"select sql from sqlite_master where tbl_name='%@' and type='table';",tableName];
- NSMutableArray* tempArrayM = [NSMutableArray array];
- //获取表格所有列名.
- [db executeStatements:SQL withResultBlock:^int(NSDictionary *resultsDictionary) {
- NSString* allName = [resultsDictionary.allValues lastObject];
- allName = [allName stringByReplacingOccurrencesOfString:@"\"" withString:@""];
- NSRange range1 = [allName rangeOfString:@"("];
- allName = [allName substringFromIndex:range1.location+1];
- NSRange range2 = [allName rangeOfString:@")"];
- allName = [allName substringToIndex:range2.location];
- NSArray* sqlNames = [allName componentsSeparatedByString:@","];
-
- for(NSString* sqlName in sqlNames){
- NSString* columnName = [[sqlName componentsSeparatedByString:@" "] firstObject];
- [tempArrayM addObject:columnName];
- }
- return 0;
- }];
- NSArray* columNames = tempArrayM.count?tempArrayM:nil;
- NSArray* keyAndtypes = [BGTool getClassIvarList:[object class] Object:object onlyKey:NO];
- for(NSString* keyAndtype in keyAndtypes){
- NSString* key = [[keyAndtype componentsSeparatedByString:@"*"] firstObject];
- if(ignoredkeys && [ignoredkeys containsObject:key])continue;
-
- key = [NSString stringWithFormat:@"%@%@",BG,key];
- if (![columNames containsObject:key]) {
- [newKeys addObject:keyAndtype];
- }
- }
-
- NSMutableArray* keys = [NSMutableArray arrayWithArray:[BGTool getClassIvarList:[object class] Object:nil onlyKey:YES]];
- if (ignoredkeys) {
- [keys removeObjectsInArray:ignoredkeys];
- }
- [columNames enumerateObjectsUsingBlock:^(NSString* _Nonnull columName, NSUInteger idx, BOOL * _Nonnull stop) {
- NSString* propertyName = [columName stringByReplacingOccurrencesOfString:BG withString:@""];
- if(![keys containsObject:propertyName]){
- [sqlKeys addObject:columName];
- }
- }];
-
- }];
-
- if((sqlKeys.count==0) && (newKeys.count>0)){
- //此处只是增加了新的列.
- for(NSString* key in newKeys){
- //添加新字段
- [self addTable:tableName key:key complete:^(BOOL isSuccess){}];
- }
- }else if(sqlKeys.count>0){
- //字段发生改变,减少或名称变化,实行刷新数据库.
- NSMutableArray* newTableKeys = [[NSMutableArray alloc] initWithArray:[BGTool getClassIvarList:[object class] Object:nil onlyKey:NO]];
- NSMutableArray* tempIgnoreKeys = [[NSMutableArray alloc] initWithArray:ignoredkeys];
- for(int i=0;i<newTableKeys.count;i++){
- NSString* key = [[newTableKeys[i] componentsSeparatedByString:@"*"] firstObject];
- if([tempIgnoreKeys containsObject:key]) {
- [newTableKeys removeObject:newTableKeys[i]];
- [tempIgnoreKeys removeObject:key];
- i--;
- }
- if(tempIgnoreKeys.count == 0){
- break;
- }
- }
- [self refreshQueueTable:tableName class:[object class] keys:newTableKeys complete:nil];
- }else;
- }
- }
- /**
- 处理插入的字典数据并返回
- */
- -(void)insertWithObject:(id)object ignoredKeys:(NSArray* const _Nullable)ignoredKeys complete:(bg_complete_B)complete{
- NSDictionary* dictM = [BGTool getDictWithObject:object ignoredKeys:ignoredKeys filtModelInfoType:bg_ModelInfoInsert];
- //自动判断是否有字段改变,自动刷新数据库.
- [self ifIvarChangeForObject:object ignoredKeys:ignoredKeys];
- NSString* tableName = [BGTool getTableNameWithObject:object];
- [self insertIntoTableName:tableName Dict:dictM complete:complete];
-
- }
- -(NSArray*)getArray:(NSArray*)array ignoredKeys:(NSArray* const _Nullable)ignoredKeys filtModelInfoType:(bg_getModelInfoType)filtModelInfoType{
- NSMutableArray* dictArray = [NSMutableArray array];
- [array enumerateObjectsUsingBlock:^(id _Nonnull object, NSUInteger idx, BOOL * _Nonnull stop) {
- NSDictionary* dict = [BGTool getDictWithObject:object ignoredKeys:ignoredKeys filtModelInfoType:filtModelInfoType];
- [dictArray addObject:dict];
- }];
- return dictArray;
- }
- /**
- 批量插入数据
- */
- -(void)insertWithObjects:(NSArray*)array ignoredKeys:(NSArray* const _Nullable)ignoredKeys complete:(bg_complete_B)complete{
- NSArray* dictArray = [self getArray:array ignoredKeys:ignoredKeys filtModelInfoType:bg_ModelInfoInsert];
- //自动判断是否有字段改变,自动刷新数据库.
- [self ifIvarChangeForObject:array.firstObject ignoredKeys:ignoredKeys];
- NSString* tableName = [BGTool getTableNameWithObject:array.firstObject];
- [self insertIntoTableName:tableName DictArray:dictArray complete:complete];
- }
- /**
- 批量更新数据.
- over
- */
- -(void)updateSetWithObjects:(NSArray*)array ignoredKeys:(NSArray* const _Nullable)ignoredKeys complete:(bg_complete_B)complete{
- NSArray* dictArray = [self getArray:array ignoredKeys:ignoredKeys filtModelInfoType:bg_ModelInfoArrayUpdate];
- NSString* tableName = [BGTool getTableNameWithObject:array.firstObject];
- [self updateSetTableName:tableName class:[array.firstObject class] DictArray:dictArray complete:complete];
- }
- /**
- 批量存储.
- */
- -(void)saveObjects:(NSArray* _Nonnull)array ignoredKeys:(NSArray* const _Nullable)ignoredKeys complete:(bg_complete_B)complete{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- @autoreleasepool {
- [BGTool ifNotExistWillCreateTableWithObject:array.firstObject ignoredKeys:ignoredKeys];
- [self insertWithObjects:array ignoredKeys:ignoredKeys complete:complete];
- }
- dispatch_semaphore_signal(self.semaphore);
- }
- /**
- 批量更新.
- over
- */
- -(void)updateObjects:(NSArray* _Nonnull)array ignoredKeys:(NSArray* const _Nullable)ignoredKeys complete:(bg_complete_B)complete{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- @autoreleasepool {
- [self updateSetWithObjects:array ignoredKeys:ignoredKeys complete:complete];
- }
- dispatch_semaphore_signal(self.semaphore);
- }
- /**
- 批量插入或更新.
- */
- -(void)bg_saveOrUpateArray:(NSArray* _Nonnull)array ignoredKeys:(NSArray* const _Nullable)ignoredKeys complete:(bg_complete_B)complete{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- @autoreleasepool {
- //判断是否建表.
- [BGTool ifNotExistWillCreateTableWithObject:array.firstObject ignoredKeys:ignoredKeys];
- //自动判断是否有字段改变,自动刷新数据库.
- [self ifIvarChangeForObject:array.firstObject ignoredKeys:ignoredKeys];
- //转换模型数据
- NSArray* dictArray = [self getArray:array ignoredKeys:ignoredKeys filtModelInfoType:bg_ModelInfoNone];
- //获取自定义表名
- NSString* tableName = [BGTool getTableNameWithObject:array.firstObject];
- [self bg_saveOrUpdateWithTableName:tableName class:[array.firstObject class] DictArray:dictArray complete:complete];
- }
- dispatch_semaphore_signal(self.semaphore);
- }
- /**
- 存储一个对象.
- */
- -(void)saveObject:(id _Nonnull)object ignoredKeys:(NSArray* const _Nullable)ignoredKeys complete:(bg_complete_B)complete{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- @autoreleasepool {
- [BGTool ifNotExistWillCreateTableWithObject:object ignoredKeys:ignoredKeys];
- [self insertWithObject:object ignoredKeys:ignoredKeys complete:complete];
- }
- dispatch_semaphore_signal(self.semaphore);
- }
- -(void)queryObjectQueueWithTableName:(NSString* _Nonnull)tablename class:(__unsafe_unretained _Nonnull Class)cla where:(NSString* _Nullable)where complete:(bg_complete_A)complete{
- //检查是否建立了跟对象相对应的数据表
- __weak typeof(self) BGSelf = self;
- [self isExistWithTableName:tablename complete:^(BOOL isExist) {
- __strong typeof(BGSelf) strongSelf = BGSelf;
- if (!isExist){//如果不存在就返回空
- bg_completeBlock(nil);
- }else{
- [strongSelf queryWithTableName:tablename where:where complete:^(NSArray * _Nullable array) {
- NSArray* resultArray = [BGTool tansformDataFromSqlDataWithTableName:tablename class:cla array:array];
- bg_completeBlock(resultArray);
- }];
- }
- }];
- }
- /**
- 查询对象.
- */
- -(void)queryObjectWithTableName:(NSString* _Nonnull)tablename class:(__unsafe_unretained _Nonnull Class)cla where:(NSString* _Nullable)where complete:(bg_complete_A)complete{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- @autoreleasepool {
- [self queryObjectQueueWithTableName:tablename class:cla where:where complete:complete];
- }
- dispatch_semaphore_signal(self.semaphore);
- }
- -(void)updateQueueWithObject:(id _Nonnull)object where:(NSArray* _Nullable)where ignoreKeys:(NSArray* const _Nullable)ignoreKeys complete:(bg_complete_B)complete{
- NSDictionary* valueDict = [BGTool getDictWithObject:object ignoredKeys:ignoreKeys filtModelInfoType:bg_ModelInfoSingleUpdate];
- NSString* tableName = [BGTool getTableNameWithObject:object];
- __block BOOL result = NO;
- [self isExistWithTableName:tableName complete:^(BOOL isExist){
- result = isExist;
- }];
-
- if (!result){
- //如果不存在就返回NO
- bg_completeBlock(NO);
- }else{
- //自动判断是否有字段改变,自动刷新数据库.
- [self ifIvarChangeForObject:object ignoredKeys:ignoreKeys];
- [self updateWithTableName:tableName valueDict:valueDict where:where complete:complete];
- }
-
- }
- /**
- 根据条件改变对象数据.
- */
- -(void)updateWithObject:(id _Nonnull)object where:(NSArray* _Nullable)where ignoreKeys:(NSArray* const _Nullable)ignoreKeys complete:(bg_complete_B)complete{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- @autoreleasepool {
- [self updateQueueWithObject:object where:where ignoreKeys:ignoreKeys complete:complete];
- }
- dispatch_semaphore_signal(self.semaphore);
- }
- -(void)updateQueueWithObject:(id _Nonnull)object forKeyPathAndValues:(NSArray* _Nonnull)keyPathValues ignoreKeys:(NSArray* const _Nullable)ignoreKeys complete:(bg_complete_B)complete{
- NSDictionary* valueDict = [BGTool getDictWithObject:object ignoredKeys:ignoreKeys filtModelInfoType:bg_ModelInfoSingleUpdate];
- NSString* tableName = [BGTool getTableNameWithObject:object];
- __weak typeof(self) BGSelf = self;
- [self isExistWithTableName:tableName complete:^(BOOL isExist){
- __strong typeof(BGSelf) strongSelf = BGSelf;
- if (!isExist){//如果不存在就返回NO
- bg_completeBlock(NO);
- }else{
- [strongSelf updateWithTableName:tableName forKeyPathAndValues:keyPathValues valueDict:valueDict complete:complete];
- }
- }];
- }
- /**
- 根据keyPath改变对象数据.
- */
- -(void)updateWithObject:(id _Nonnull)object forKeyPathAndValues:(NSArray* _Nonnull)keyPathValues ignoreKeys:(NSArray* const _Nullable)ignoreKeys complete:(bg_complete_B)complete{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- @autoreleasepool {
- //自动判断是否有字段改变,自动刷新数据库.
- [self ifIvarChangeForObject:object ignoredKeys:ignoreKeys];
- [self updateQueueWithObject:object forKeyPathAndValues:keyPathValues ignoreKeys:ignoreKeys complete:complete];
- }
- dispatch_semaphore_signal(self.semaphore);
- }
- /**
- 根据类删除此类所有表数据.
- */
- -(void)clearWithObject:(id _Nonnull)object complete:(bg_complete_B)complete{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
-
- NSString* tableName = [BGTool getTableNameWithObject:object];
- __weak typeof(self) BGSelf = self;
- [self isExistWithTableName:tableName complete:^(BOOL isExist) {
- __strong typeof(BGSelf) strongSelf = BGSelf;
- if (!isExist){//如果不存在就相当于清空,返回YES
- bg_completeBlock(YES);
- }else{
- [strongSelf clearTable:tableName complete:complete];
- }
- }];
-
- dispatch_semaphore_signal(self.semaphore);
- }
- /**
- 根据类,删除这个类的表.
- */
- -(void)dropWithTableName:(NSString* _Nonnull)tablename complete:(bg_complete_B)complete{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
-
- __weak typeof(self) BGSelf = self;
- [self isExistWithTableName:tablename complete:^(BOOL isExist){
- __strong typeof(BGSelf) strongSelf = BGSelf;
- if (!isExist){//如果不存在就返回NO
- bg_completeBlock(NO);
- }else{
- [strongSelf dropTable:tablename complete:complete];
- }
- }];
-
- dispatch_semaphore_signal(self.semaphore);
- }
- -(void)copyQueueTable:(NSString* _Nonnull)srcTable to:(NSString* _Nonnull)destTable keyDict:(NSDictionary* const _Nonnull)keydict append:(BOOL)append complete:(bg_complete_I)complete{
- NSAssert(![srcTable isEqualToString:destTable],@"不能将本表数据拷贝给自己!");
- NSArray* destKeys = keydict.allValues;
- NSArray* srcKeys = keydict.allKeys;
- [self isExistWithTableName:srcTable complete:^(BOOL isExist) {
- NSAssert(isExist,@"原表中还没有数据,复制失败!");
- }];
- __weak typeof(self) BGSelf = self;
- [self isExistWithTableName:destTable complete:^(BOOL isExist) {
- if(!isExist){
- NSAssert(NO,@"目标表不存在,复制失败!");
- }else{
- if (!append){//覆盖模式,即将原数据删掉,拷贝新的数据过来
- [BGSelf clearTable:destTable complete:nil];
- }
- }
- }];
- __block bg_dealState copystate = bg_error;
- __block BOOL recordError = NO;
- __block BOOL recordSuccess = NO;
- NSInteger srcCount = [self countQueueForTable:srcTable where:nil];
- for(NSInteger i=0;i<srcCount;i+=MaxQueryPageNum){
- @autoreleasepool{//由于查询出来的数据量可能巨大,所以加入自动释放池.
- NSString* param = [NSString stringWithFormat:@"limit %@,%@",@(i),@(MaxQueryPageNum)];
- [self queryWithTableName:srcTable where:param complete:^(NSArray * _Nullable array) {
- for(NSDictionary* srcDict in array){
- NSMutableDictionary* destDict = [NSMutableDictionary dictionary];
- for(int i=0;i<srcKeys.count;i++){
- //字段名前加上 @"BG_"
- NSString* destSqlKey = [NSString stringWithFormat:@"%@%@",BG,destKeys[i]];
- NSString* srcSqlKey = [NSString stringWithFormat:@"%@%@",BG,srcKeys[i]];
- destDict[destSqlKey] = srcDict[srcSqlKey];
- }
- [BGSelf insertIntoTableName:destTable Dict:destDict complete:^(BOOL isSuccess) {
- if (isSuccess){
- if (!recordSuccess) {
- recordSuccess = YES;
- }
- }else{
- if (!recordError) {
- recordError = YES;
- }
- }
- }];
- }
- }];
- }
- }
-
- if (complete){
- if (recordError && recordSuccess) {
- copystate = bg_incomplete;
- }else if(recordError && !recordSuccess){
- copystate = bg_error;
- }else if (recordSuccess && !recordError){
- copystate = bg_complete;
- }else;
- complete(copystate);
- }
-
- }
- /**
- 将某表的数据拷贝给另一个表
- */
- -(void)copyTable:(NSString* _Nonnull)srcTable to:(NSString* _Nonnull)destTable keyDict:(NSDictionary* const _Nonnull)keydict append:(BOOL)append complete:(bg_complete_I)complete{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- @autoreleasepool {
- [self copyQueueTable:srcTable to:destTable keyDict:keydict append:append complete:complete];
- }
- dispatch_semaphore_signal(self.semaphore);
- }
- /**
- 直接执行sql语句.
- @tablename 要操作的表名.
- @cla 要操作的类.
- */
- -(id _Nullable)bg_executeSql:(NSString* const _Nonnull)sql tablename:(NSString* _Nonnull)tablename class:(__unsafe_unretained _Nonnull Class)cla{
- NSAssert(sql,@"sql语句不能为空!");
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- __block id result;
- [self executeDB:^(FMDatabase * _Nonnull db){
- if([[sql lowercaseString] hasPrefix:@"select"]){
- // 1.查询数据
- FMResultSet *rs = [db executeQuery:sql];
- if (rs == nil) {
- bg_debug(@"查询错误,数据不存在,请存储后再读取!");
- result = nil;
- }else{
- result = [NSMutableArray array];
- }
- result = [NSMutableArray array];
- // 2.遍历结果集
- while (rs.next) {
- NSMutableDictionary* dictM = [[NSMutableDictionary alloc] init];
- for (int i=0;i<[[[rs columnNameToIndexMap] allKeys] count];i++) {
- dictM[[rs columnNameForIndex:i]] = [rs objectForColumnIndex:i];
- }
- [result addObject:dictM];
- }
- //查询完后要关闭rs,不然会报@"Warning: there is at least one open result set around after performing
- [rs close];
- //转换结果
- result = [BGTool tansformDataFromSqlDataWithTableName:tablename class:cla array:result];
- }else{
- result = @([db executeUpdate:sql]);
- }
- bg_debug(sql);
- }];
- dispatch_semaphore_signal(self.semaphore);
- return result;
- }
- #pragma mark 存储数组.
- /**
- 直接存储数组.
- */
- -(void)saveArray:(NSArray* _Nonnull)array name:(NSString*)name complete:(bg_complete_B)complete{
- NSAssert(array&&array.count,@"数组不能为空!");
- NSAssert(name,@"唯一标识名不能为空!");
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- @autoreleasepool {
- __weak typeof(self) BGSelf = self;
- [self isExistWithTableName:name complete:^(BOOL isSuccess) {
- if (!isSuccess) {
- [BGSelf createTableWithTableName:name keys:@[[NSString stringWithFormat:@"%@*i",bg_primaryKey],@"param*@\"NSString\"",@"index*i"] unionPrimaryKeys:nil uniqueKeys:nil complete:nil];
- }
- }];
- __block NSInteger sqlCount = [self countQueueForTable:name where:nil];
-
- __block NSInteger num = 0;
- [self executeTransation:^BOOL{
- for(id value in array){
- NSString* type = [NSString stringWithFormat:@"@\"%@\"",NSStringFromClass([value class])];
- id sqlValue = [BGTool getSqlValue:value type:type encode:YES];
- sqlValue = [NSString stringWithFormat:@"%@$$$%@",sqlValue,type];
- NSDictionary* dict = @{@"BG_param":sqlValue,@"BG_index":@(sqlCount++)};
- [self insertIntoTableName:name Dict:dict complete:^(BOOL isSuccess) {
- if(isSuccess) {
- num++;
- }
- }];
- }
- return YES;
- }];
- bg_completeBlock(array.count==num);
- }
- dispatch_semaphore_signal(self.semaphore);
- }
- /**
- 读取数组.
- */
- -(void)queryArrayWithName:(NSString*)name complete:(bg_complete_A)complete{
- NSAssert(name,@"唯一标识名不能为空!");
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- @autoreleasepool {
- NSString* condition = [NSString stringWithFormat:@"order by %@ asc",bg_sqlKey(bg_primaryKey)];
- [self queryQueueWithTableName:name conditions:condition complete:^(NSArray * _Nullable array) {
- NSMutableArray* resultM = nil;
- if(array&&array.count){
- resultM = [NSMutableArray array];
- for(NSDictionary* dict in array){
- NSArray* keyAndTypes = [dict[@"BG_param"] componentsSeparatedByString:@"$$$"];
- id value = [keyAndTypes firstObject];
- NSString* type = [keyAndTypes lastObject];
- value = [BGTool getSqlValue:value type:type encode:NO];
- [resultM addObject:value];
- }
- }
- bg_completeBlock(resultM);
- }];
- }
- dispatch_semaphore_signal(self.semaphore);
- }
- /**
- 读取数组某个元素.
- */
- -(id _Nullable)queryArrayWithName:(NSString* _Nonnull)name index:(NSInteger)index{
- NSAssert(name,@"唯一标识名不能为空!");
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- __block id resultValue = nil;
- @autoreleasepool {
- [self queryQueueWithTableName:name conditions:[NSString stringWithFormat:@"where BG_index=%@",@(index)] complete:^(NSArray * _Nullable array){
- if(array&&array.count){
- NSDictionary* dict = [array firstObject];
- NSArray* keyAndTypes = [dict[@"BG_param"] componentsSeparatedByString:@"$$$"];
- id value = [keyAndTypes firstObject];
- NSString* type = [keyAndTypes lastObject];
- resultValue = [BGTool getSqlValue:value type:type encode:NO];
- }
- }];
- }
- dispatch_semaphore_signal(self.semaphore);
- return resultValue;
- }
- /**
- 更新数组某个元素.
- */
- -(BOOL)updateObjectWithName:(NSString* _Nonnull)name object:(id _Nonnull)object index:(NSInteger)index{
- NSAssert(name,@"唯一标识名不能为空!");
- NSAssert(object,@"元素不能为空!");
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- __block BOOL result;
- @autoreleasepool{
- NSString* type = [NSString stringWithFormat:@"@\"%@\"",NSStringFromClass([object class])];
- id sqlValue = [BGTool getSqlValue:object type:type encode:YES];
- sqlValue = [NSString stringWithFormat:@"%@$$$%@",sqlValue,type];
- NSDictionary* dict = @{@"BG_param":sqlValue};
- [self updateWithTableName:name valueDict:dict where:@[@"index",@"=",@(index)] complete:^(BOOL isSuccess) {
- result = isSuccess;
- }];
- }
- dispatch_semaphore_signal(self.semaphore);
- return result;
- }
- /**
- 删除数组某个元素.
- */
- -(BOOL)deleteObjectWithName:(NSString* _Nonnull)name index:(NSInteger)index{
- NSAssert(name,@"唯一标识名不能为空!");
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- __block NSInteger flag = 0;
- @autoreleasepool {
- [self executeTransation:^BOOL{
- [self deleteQueueWithTableName:name conditions:[NSString stringWithFormat:@"where BG_index=%@",@(index)] complete:^(BOOL isSuccess) {
- if(isSuccess) {
- flag++;
- }
- }];
- if(flag){
- [self updateQueueWithTableName:name valueDict:nil conditions:[NSString stringWithFormat:@"set BG_index=BG_index-1 where BG_index>%@",@(index)] complete:^(BOOL isSuccess) {
- if(isSuccess) {
- flag++;
- }
- }];
- }
- return flag==2;
- }];
- }
- dispatch_semaphore_signal(self.semaphore);
- return flag==2;
- }
- #pragma mark 存储字典.
- /**
- 直接存储字典.
- */
- -(void)saveDictionary:(NSDictionary* _Nonnull)dictionary complete:(bg_complete_B)complete{
- NSAssert(dictionary||dictionary.allKeys.count,@"字典不能为空!");
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- @autoreleasepool {
- __weak typeof(self) BGSelf = self;
- NSString* const tableName = @"BG_Dictionary";
- [self isExistWithTableName:tableName complete:^(BOOL isSuccess) {
- if (!isSuccess) {
- [BGSelf createTableWithTableName:tableName keys:@[[NSString stringWithFormat:@"%@*i",bg_primaryKey],@"key*@\"NSString\"",@"value*@\"NSString\""] unionPrimaryKeys:nil uniqueKeys:@[@"key"] complete:nil];
- }
- }];
- __block NSInteger num = 0;
- [self executeTransation:^BOOL{
- [dictionary enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull value, BOOL * _Nonnull stop){
- NSString* type = [NSString stringWithFormat:@"@\"%@\"",NSStringFromClass([value class])];
- id sqlValue = [BGTool getSqlValue:value type:type encode:YES];
- sqlValue = [NSString stringWithFormat:@"%@$$$%@",sqlValue,type];
- NSDictionary* dict = @{@"BG_key":key,@"BG_value":sqlValue};
- [self insertIntoTableName:tableName Dict:dict complete:^(BOOL isSuccess) {
- if(isSuccess) {
- num++;
- }
- }];
- }];
- return YES;
- }];
- bg_completeBlock(dictionary.allKeys.count==num);
- }
- dispatch_semaphore_signal(self.semaphore);
- }
- /**
- 添加字典元素.
- */
- -(BOOL)bg_setValue:(id _Nonnull)value forKey:(NSString* const _Nonnull)key{
- NSAssert(key,@"key不能为空!");
- NSAssert(value,@"value不能为空!");
- NSDictionary* dict = @{key:value};
- __block BOOL result;
- [self saveDictionary:dict complete:^(BOOL isSuccess) {
- result = isSuccess;
- }];
- return result;
- }
- /**
- 更新字典元素.
- */
- -(BOOL)bg_updateValue:(id _Nonnull)value forKey:(NSString* const _Nonnull)key{
- NSAssert(key,@"key不能为空!");
- NSAssert(value,@"value不能为空!");
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- __block BOOL result;
- @autoreleasepool{
- NSString* type = [NSString stringWithFormat:@"@\"%@\"",NSStringFromClass([value class])];
- id sqlvalue = [BGTool getSqlValue:value type:type encode:YES];
- sqlvalue = [NSString stringWithFormat:@"%@$$$%@",sqlvalue,type];
- NSDictionary* dict = @{@"BG_value":sqlvalue};
- NSString* const tableName = @"BG_Dictionary";
- [self updateWithTableName:tableName valueDict:dict where:@[@"key",@"=",key] complete:^(BOOL isSuccess) {
- result = isSuccess;
- }];
- }
- dispatch_semaphore_signal(self.semaphore);
- return result;
- }
- /**
- 遍历字典元素.
- */
- -(void)bg_enumerateKeysAndObjectsUsingBlock:(void (^ _Nonnull)(NSString* _Nonnull key, id _Nonnull value,BOOL *stop))block{
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- @autoreleasepool{
- NSString* const tableName = @"BG_Dictionary";
- NSString* condition = [NSString stringWithFormat:@"order by %@ asc",bg_sqlKey(bg_primaryKey)];
- [self queryQueueWithTableName:tableName conditions:condition complete:^(NSArray * _Nullable array) {
- BOOL stopFlag = NO;
- for(NSDictionary* dict in array){
- NSArray* keyAndTypes = [dict[@"BG_value"] componentsSeparatedByString:@"$$$"];
- NSString* key = dict[@"BG_key"];
- id value = [keyAndTypes firstObject];
- NSString* type = [keyAndTypes lastObject];
- value = [BGTool getSqlValue:value type:type encode:NO];
- !block?:block(key,value,&stopFlag);
- if(stopFlag){
- break;
- }
- }
- }];
- }
- dispatch_semaphore_signal(self.semaphore);
- }
- /**
- 获取字典元素.
- */
- -(id _Nullable)bg_valueForKey:(NSString* const _Nonnull)key{
- NSAssert(key,@"key不能为空!");
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- __block id resultValue = nil;
- @autoreleasepool {
- NSString* const tableName = @"BG_Dictionary";
- [self queryQueueWithTableName:tableName conditions:[NSString stringWithFormat:@"where BG_key='%@'",key] complete:^(NSArray * _Nullable array){
- if(array&&array.count){
- NSDictionary* dict = [array firstObject];
- NSArray* keyAndTypes = [dict[@"BG_value"] componentsSeparatedByString:@"$$$"];
- id value = [keyAndTypes firstObject];
- NSString* type = [keyAndTypes lastObject];
- resultValue = [BGTool getSqlValue:value type:type encode:NO];
- }
- }];
- }
- dispatch_semaphore_signal(self.semaphore);
- return resultValue;
- }
- /**
- 删除字典元素.
- */
- -(BOOL)bg_deleteValueForKey:(NSString* const _Nonnull)key{
- NSAssert(key,@"key不能为空!");
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
- __block BOOL result;
- @autoreleasepool {
- NSString* const tableName = @"BG_Dictionary";
- [self deleteQueueWithTableName:tableName conditions:[NSString stringWithFormat:@"where BG_key='%@'",key] complete:^(BOOL isSuccess) {
- result = isSuccess;
- }];
- }
- dispatch_semaphore_signal(self.semaphore);
- return result;
- }
- @end
|