LKDBHelper.m 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919
  1. //
  2. // LKDBHelper.m
  3. // upin
  4. //
  5. // Created by Fanhuan on 12-12-6.
  6. // Copyright (c) 2012年 linggan. All rights reserved.
  7. //
  8. #import "LKDBHelper.h"
  9. #define checkClassIsInvalid(modelClass)if([LKDBUtils checkStringIsEmpty:[modelClass getTableName]]){\
  10. LKLog(@"model class name %@ table name is invalid!",NSStringFromClass(modelClass));\
  11. return NO;}
  12. #define checkModelIsInvalid(model)if(model == nil){LKLog(@"model is nil");return NO;}checkClassIsInvalid(model.class)
  13. @interface LKDBHelper()
  14. @property(unsafe_unretained,nonatomic)FMDatabase* usingdb;
  15. @property(strong,nonatomic)FMDatabaseQueue* bindingQueue;
  16. @property(copy,nonatomic)NSString* dbname;
  17. @property(strong,nonatomic)NSRecursiveLock* threadLock;
  18. @property(strong,nonatomic)LKTableManager* tableManager;
  19. @end
  20. @implementation LKDBHelper
  21. #pragma mark- deprecated
  22. +(LKDBHelper *)sharedDBHelper
  23. {return [LKDBHelper getUsingLKDBHelper];}
  24. #pragma mark-
  25. -(id)initWithDBName:(NSString *)dbname
  26. {
  27. self = [super init];
  28. if (self) {
  29. self.threadLock = [[NSRecursiveLock alloc]init];
  30. [self setDBName:dbname];
  31. }
  32. return self;
  33. }
  34. - (id)init
  35. {
  36. return [self initWithDBName:@"Weqia"];
  37. }
  38. -(void)setDBName:(NSString *)fileName
  39. {
  40. if([self.dbname isEqualToString:fileName] == NO)
  41. {
  42. if([fileName hasSuffix:@".db"] == NO)
  43. {
  44. self.dbname = [NSString stringWithFormat:@"%@.db",fileName];
  45. }
  46. else
  47. {
  48. self.dbname = fileName;
  49. }
  50. [self.bindingQueue close];
  51. self.bindingQueue = [[FMDatabaseQueue alloc]initWithPath:[LKDBUtils getPathForDocuments:self.dbname inDir:@"db"]];
  52. #ifdef DEBUG
  53. //debug 模式下 打印错误日志
  54. [_bindingQueue inDatabase:^(FMDatabase *db) {
  55. db.logsErrors = YES;
  56. }];
  57. #endif
  58. self.tableManager = [[LKTableManager alloc]initWithLKDBHelper:self];
  59. }
  60. }
  61. #pragma mark- core
  62. -(void)executeDB:(void (^)(FMDatabase *db))block
  63. {
  64. [_threadLock lock];
  65. if(self.usingdb != nil)
  66. {
  67. block(self.usingdb);
  68. }
  69. else
  70. {
  71. [_bindingQueue inDatabase:^(FMDatabase *db) {
  72. self.usingdb = db;
  73. block(db);
  74. self.usingdb = nil;
  75. }];
  76. }
  77. [_threadLock unlock];
  78. }
  79. -(BOOL)executeSQL:(NSString *)sql arguments:(NSArray *)args
  80. {
  81. __block BOOL execute = NO;
  82. [self executeDB:^(FMDatabase *db) {
  83. if(args.count>0)
  84. execute = [db executeUpdate:sql withArgumentsInArray:args];
  85. else
  86. execute = [db executeUpdate:sql];
  87. }];
  88. return execute;
  89. }
  90. -(NSString *)executeScalarWithSQL:(NSString *)sql arguments:(NSArray *)args
  91. {
  92. __block NSString* scalar = nil;
  93. [self executeDB:^(FMDatabase *db) {
  94. FMResultSet* set = nil;
  95. if(args.count>0)
  96. set = [db executeQuery:sql withArgumentsInArray:args];
  97. else
  98. set = [db executeQuery:sql];
  99. if([set columnCount]>0 && [set next])
  100. {
  101. scalar = [set stringForColumnIndex:0];
  102. }
  103. [set close];
  104. }];
  105. return scalar;
  106. }
  107. //splice 'where' 拼接where语句
  108. - (NSMutableArray *)extractQuery:(NSMutableString *)query where:(NSDictionary*)where
  109. {
  110. NSMutableArray* values = nil;
  111. if([where isKindOfClass:[NSString class]] && [LKDBUtils checkStringIsEmpty:where]==NO)
  112. {
  113. [query appendFormat:@" where %@",where];
  114. }
  115. else if ([where isKindOfClass:[NSDictionary class]] && [where count] > 0)
  116. {
  117. values = [NSMutableArray arrayWithCapacity:[where count]];
  118. NSString* wherekey = [self dictionaryToSqlWhere:where andValues:values];
  119. [query appendFormat:@" where %@",wherekey];
  120. }
  121. return values;
  122. }
  123. //dic where parse
  124. -(NSString*)dictionaryToSqlWhere:(NSDictionary*)dic andValues:(NSMutableArray*)values
  125. {
  126. NSMutableString* wherekey = [NSMutableString stringWithCapacity:0];
  127. if(dic != nil && dic.count >0 )
  128. {
  129. NSArray* keys = dic.allKeys;
  130. for (int i=0; i< keys.count;i++) {
  131. NSString* key = [keys objectAtIndex:i];
  132. id va = [dic objectForKey:key];
  133. if([va isKindOfClass:[NSArray class]])
  134. {
  135. NSArray* vlist = va;
  136. if(vlist.count==0)
  137. continue;
  138. if(wherekey.length > 0)
  139. [wherekey appendString:@" and"];
  140. [wherekey appendFormat:@" %@ in(",key];
  141. for (int j=0; j<vlist.count; j++) {
  142. [wherekey appendString:@"?"];
  143. if(j== vlist.count-1)
  144. [wherekey appendString:@")"];
  145. else
  146. [wherekey appendString:@","];
  147. [values addObject:[vlist objectAtIndex:j]];
  148. }
  149. }
  150. else
  151. {
  152. if(wherekey.length > 0)
  153. [wherekey appendFormat:@" and %@=?",key];
  154. else
  155. [wherekey appendFormat:@" %@=?",key];
  156. [values addObject:va];
  157. }
  158. }
  159. }
  160. return wherekey;
  161. }
  162. //where sql statements about model primary keys
  163. -(NSMutableString*)primaryKeyWhereSQLWithModel:(NSObject*)model addPValues:(NSMutableArray*)addPValues
  164. {
  165. LKModelInfos* infos = [model.class getModelInfos];
  166. NSArray* primaryKeys = infos.primaryKeys;
  167. NSMutableString* pwhere = [NSMutableString string];
  168. if(primaryKeys.count>0)
  169. {
  170. for (int i=0; i<primaryKeys.count; i++) {
  171. NSString* pk = [primaryKeys objectAtIndex:i];
  172. if([LKDBUtils checkStringIsEmpty:pk] == NO)
  173. {
  174. LKDBProperty* property = [infos objectWithSqlColumeName:pk];
  175. id pvalue = nil;
  176. if(property && [property.type isEqualToString:LKSQLUserCalculate])
  177. {
  178. pvalue = [model userGetValueForModel:property];
  179. }
  180. else if(pk && property)
  181. {
  182. pvalue = [model modelGetValue:property];
  183. }
  184. if(pvalue)
  185. {
  186. if(pwhere.length>0)
  187. [pwhere appendString:@"and"];
  188. if(addPValues)
  189. {
  190. [pwhere appendFormat:@" %@=? ",pk];
  191. [addPValues addObject:pvalue];
  192. }
  193. else
  194. {
  195. [pwhere appendFormat:@" %@='%@' ",pk,pvalue];
  196. }
  197. }
  198. }
  199. }
  200. }
  201. return pwhere;
  202. }
  203. #pragma mark- dealloc
  204. -(void)dealloc
  205. {
  206. [self.bindingQueue close];
  207. self.usingdb = nil;
  208. self.bindingQueue = nil;
  209. self.dbname = nil;
  210. self.tableManager = nil;
  211. self.threadLock = nil;
  212. }
  213. @end
  214. @implementation LKDBHelper(DatabaseManager)
  215. -(void)dropAllTable
  216. {
  217. [self executeDB:^(FMDatabase *db) {
  218. FMResultSet* set = [db executeQuery:@"select name from sqlite_master where type='table'"];
  219. NSMutableArray* dropTables = [NSMutableArray arrayWithCapacity:0];
  220. while ([set next]) {
  221. [dropTables addObject:[set stringForColumnIndex:0]];
  222. }
  223. [set close];
  224. for (NSString* tableName in dropTables) {
  225. NSString* dropTable = [NSString stringWithFormat:@"drop table %@",tableName];
  226. [db executeUpdate:dropTable];
  227. }
  228. }];
  229. [self.tableManager clearTableInfos];
  230. }
  231. -(BOOL)dropTableWithClass:(Class)modelClass
  232. {
  233. checkClassIsInvalid(modelClass);
  234. NSString* tableName = [modelClass getTableName];
  235. NSString* dropTable = [NSString stringWithFormat:@"drop table %@",tableName];
  236. BOOL isDrop = [self executeSQL:dropTable arguments:nil];
  237. if(isDrop)
  238. [_tableManager setTableName:tableName version:0];
  239. return isDrop;
  240. }
  241. -(void)fixSqlColumesWithClass:(Class)clazz
  242. {
  243. NSString* tableName = [clazz getTableName];
  244. LKModelInfos* infos = [clazz getModelInfos];
  245. [self executeDB:^(FMDatabase *db) {
  246. NSString* select = [NSString stringWithFormat:@"select * from %@ limit 0",tableName];
  247. FMResultSet* set = [db executeQuery:select];
  248. NSString* columeText = [set.columnNameToIndexMap.allKeys componentsJoinedByString:@","];
  249. [set close];
  250. for (int i=0; i<infos.count; i++) {
  251. LKDBProperty* p = [infos objectWithIndex:i];
  252. if([p.sqlColumeName.lowercaseString isEqualToString:@"rowid"])
  253. continue;
  254. if([columeText rangeOfString:p.sqlColumeName.lowercaseString].length == 0)
  255. {
  256. if([clazz getAutoUpdateSqlColume])
  257. [clazz tableUpdateAddColumeWithName:p.sqlColumeName sqliteType:p.sqlColumeType];
  258. else
  259. [clazz removePropertyWithColumeName:p.sqlColumeName];
  260. }
  261. }
  262. }];
  263. }
  264. -(BOOL)createTableWithModelClass:(Class)modelClass
  265. {
  266. checkClassIsInvalid(modelClass);
  267. NSString* tableName = [modelClass getTableName];
  268. int oldVersion = [_tableManager versionWithName:tableName];
  269. int newVersion = [modelClass getTableVersion];
  270. if(oldVersion>0 && oldVersion != newVersion)
  271. {
  272. LKTableUpdateType userOperation = [modelClass tableUpdateForOldVersion:oldVersion newVersion:newVersion];
  273. switch (userOperation) {
  274. case LKTableUpdateTypeDeleteOld:
  275. {
  276. [self dropTableWithClass:modelClass];
  277. }
  278. break;
  279. case LKTableUpdateTypeDefault:
  280. [self fixSqlColumesWithClass:modelClass];
  281. return NO;
  282. case LKTableUpdateTypeCustom:
  283. [self fixSqlColumesWithClass:modelClass];
  284. [_tableManager setTableName:tableName version:newVersion];
  285. return YES;
  286. }
  287. }
  288. else if(oldVersion == newVersion)
  289. {
  290. __block BOOL isTableCreated = NO;
  291. [self executeDB:^(FMDatabase *db) {
  292. FMResultSet* set = [db executeQuery:@"select count(name) from sqlite_master where type='table' and name=?",tableName];
  293. [set next];
  294. if([set intForColumnIndex:0]>0)
  295. {
  296. isTableCreated = YES;
  297. }
  298. [set close];
  299. }];
  300. if(isTableCreated)
  301. {
  302. //已创建表 就跳过
  303. [self fixSqlColumesWithClass:modelClass];
  304. return YES;
  305. }
  306. }
  307. LKModelInfos* infos = [modelClass getModelInfos];
  308. NSArray* primaryKeys = infos.primaryKeys;
  309. NSMutableString* table_pars = [NSMutableString string];
  310. for (int i=0; i<infos.count; i++) {
  311. if(i > 0)
  312. [table_pars appendString:@","];
  313. LKDBProperty* property = [infos objectWithIndex:i];
  314. [modelClass columeAttributeWithProperty:property];
  315. [table_pars appendFormat:@"%@ %@",property.sqlColumeName,property.sqlColumeType];
  316. if([property.sqlColumeType isEqualToString:LKSQLText])
  317. {
  318. if(property.length>0)
  319. {
  320. [table_pars appendFormat:@"(%d)",property.length];
  321. }
  322. }
  323. if(property.isNotNull)
  324. {
  325. [table_pars appendFormat:@" %@",LKSQLNotNull];
  326. }
  327. if(property.isUnique)
  328. {
  329. [table_pars appendFormat:@" %@",LKSQLUnique];
  330. }
  331. if(property.checkValue)
  332. {
  333. [table_pars appendFormat:@" %@(%@)",LKSQLCheck,property.checkValue];
  334. }
  335. if(property.defaultValue)
  336. {
  337. [table_pars appendFormat:@" %@ %@",LKSQLDefault,property.defaultValue];
  338. }
  339. }
  340. NSMutableString* pksb = [NSMutableString string];
  341. if(primaryKeys.count>0)
  342. {
  343. pksb = [NSMutableString string];
  344. for (int i=0; i<primaryKeys.count; i++) {
  345. NSString* pk = [primaryKeys objectAtIndex:i];
  346. if(pksb.length>0)
  347. [pksb appendString:@","];
  348. [pksb appendString:pk];
  349. }
  350. if(pksb.length>0)
  351. {
  352. [pksb insertString:@",primary key(" atIndex:0];
  353. [pksb appendString:@")"];
  354. }
  355. }
  356. NSString* createTableSQL = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS %@(%@%@)",tableName,table_pars,pksb];
  357. BOOL isCreated = [self executeSQL:createTableSQL arguments:nil];
  358. if(isCreated)
  359. [_tableManager setTableName:tableName version:newVersion];
  360. return isCreated;
  361. }
  362. @end
  363. @implementation LKDBHelper(DatabaseExecute)
  364. -(id)modelValueWithProperty:(LKDBProperty *)property model:(NSObject *)model {
  365. id value = nil;
  366. if(property.isUserCalculate)
  367. {
  368. value = [model userGetValueForModel:property];
  369. }
  370. else
  371. {
  372. value = [model modelGetValue:property];
  373. }
  374. if(value == nil)
  375. {
  376. value = @"";
  377. }
  378. return value;
  379. }
  380. -(void)asyncBlock:(void(^)(void))block
  381. {
  382. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),block);
  383. }
  384. #pragma mark - row count operation
  385. -(int)rowCount:(Class)modelClass where:(id)where
  386. {
  387. return [self rowCountBase:modelClass where:where];
  388. }
  389. -(void)rowCount:(Class)modelClass where:(id)where callback:(void (^)(int))callback
  390. {
  391. [self asyncBlock:^{
  392. int result = [self rowCountBase:modelClass where:where];
  393. if(callback != nil)
  394. {
  395. callback(result);
  396. }
  397. }];
  398. }
  399. -(int)rowCountBase:(Class)modelClass where:(id)where
  400. {
  401. NSMutableString* rowCountSql = [NSMutableString stringWithFormat:@"select count(rowid) from %@",[modelClass getTableName]];
  402. NSMutableArray* valuesarray = [self extractQuery:rowCountSql where:where];
  403. int result = [[self executeScalarWithSQL:rowCountSql arguments:valuesarray] intValue];
  404. return result;
  405. }
  406. #pragma mark- search operation
  407. -(NSMutableArray *)search:(Class)modelClass where:(id)where orderBy:(NSString *)orderBy offset:(int)offset count:(int)count
  408. {
  409. return [self searchBase:modelClass where:where orderBy:orderBy offset:offset count:count];
  410. }
  411. -(id)searchSingle:(Class)modelClass where:(id)where orderBy:(NSString *)orderBy
  412. {
  413. NSMutableArray* array = [self searchBase:modelClass where:where orderBy:orderBy offset:0 count:1];
  414. if(array.count>0)
  415. return [array objectAtIndex:0];
  416. return nil;
  417. }
  418. -(void)search:(Class)modelClass where:(id)where orderBy:(NSString *)orderBy offset:(int)offset count:(int)count callback:(void (^)(NSMutableArray *))block
  419. {
  420. [self asyncBlock:^{
  421. NSMutableArray* array = [self searchBase:modelClass where:where orderBy:orderBy offset:offset count:count];
  422. if(block != nil)
  423. block(array);
  424. }];
  425. }
  426. -(NSMutableArray *)searchBase:(Class)modelClass where:(id)where orderBy:(NSString *)orderBy offset:(int)offset count:(int)count
  427. {
  428. NSMutableString* query = [NSMutableString stringWithFormat:@"select rowid,* from %@",[modelClass getTableName]];
  429. NSMutableArray * values = [self extractQuery:query where:where];
  430. [self sqlString:query AddOder:orderBy offset:offset count:count];
  431. __block NSMutableArray* results = nil;
  432. [self executeDB:^(FMDatabase *db) {
  433. FMResultSet* set = nil;
  434. if(values == nil)
  435. set = [db executeQuery:query];
  436. else
  437. set = [db executeQuery:query withArgumentsInArray:values];
  438. results = [self executeResult:set Class:modelClass];
  439. [set close];
  440. }];
  441. return results;
  442. }
  443. -(void)sqlString:(NSMutableString*)sql AddOder:(NSString*)orderby offset:(int)offset count:(int)count
  444. {
  445. if([LKDBUtils checkStringIsEmpty:orderby] == NO)
  446. {
  447. [sql appendFormat:@" order by %@",orderby];
  448. }
  449. if(count>0)
  450. {
  451. [sql appendFormat:@" limit %d offset %d",count,offset];
  452. }
  453. }
  454. - (NSMutableArray *)executeResult:(FMResultSet *)set Class:(Class)modelClass
  455. {
  456. NSMutableArray* array = [NSMutableArray arrayWithCapacity:0];
  457. LKModelInfos* infos = [modelClass getModelInfos];
  458. int columeCount = [set columnCount];
  459. while ([set next]) {
  460. NSObject* bindingModel = [[modelClass alloc]init];
  461. bindingModel.rowid = [set intForColumnIndex:0];
  462. for (int i=1; i<columeCount; i++) {
  463. NSString* sqlName = [set columnNameForIndex:i];
  464. NSString* sqlValue = [set stringForColumnIndex:i];
  465. LKDBProperty* property = [infos objectWithSqlColumeName:sqlName];
  466. if(property.propertyName && [property.type isEqualToString:LKSQLUserCalculate] ==NO)
  467. {
  468. [bindingModel modelSetValue:property value:sqlValue];
  469. }
  470. else
  471. {
  472. [bindingModel userSetValueForModel:property value:sqlValue];
  473. }
  474. }
  475. [array addObject:bindingModel];
  476. }
  477. return array;
  478. }
  479. #pragma mark- insert operation
  480. -(BOOL)insertToDB:(NSObject *)model
  481. {
  482. return [self insertBase:model];
  483. }
  484. -(void)insertToDB:(NSObject *)model callback:(void (^)(BOOL))block
  485. {
  486. [self asyncBlock:^{
  487. BOOL result = [self insertBase:model];
  488. if(block != nil)
  489. {
  490. block(result);
  491. }
  492. }];
  493. }
  494. -(BOOL)insertWhenNotExists:(NSObject *)model
  495. {
  496. if([self isExistsModel:model]==NO)
  497. {
  498. return [self insertToDB:model];
  499. }
  500. return NO;
  501. }
  502. -(void)insertWhenNotExists:(NSObject *)model callback:(void (^)(BOOL))block
  503. {
  504. [self asyncBlock:^{
  505. if(block != nil)
  506. {
  507. block([self insertWhenNotExists:model]);
  508. }
  509. else
  510. {
  511. [self insertWhenNotExists:model];
  512. }
  513. }];
  514. }
  515. -(BOOL)insertBase:(NSObject*)model{
  516. // checkModelIsInvalid(model);
  517. Class modelClass = model.class;
  518. //callback
  519. [modelClass dbWillInsert:model];
  520. //--
  521. LKModelInfos* infos = [modelClass getModelInfos];
  522. NSMutableString* insertKey = [NSMutableString stringWithCapacity:0];
  523. NSMutableString* insertValuesString = [NSMutableString stringWithCapacity:0];
  524. NSMutableArray* insertValues = [NSMutableArray arrayWithCapacity:infos.count];
  525. LKDBProperty* primaryProperty = [model singlePrimaryKeyProperty];
  526. for (int i=0; i<infos.count; i++) {
  527. LKDBProperty* property = [infos objectWithIndex:i];
  528. if([LKDBUtils checkStringIsEmpty:property.sqlColumeName])
  529. continue;
  530. if([property isEqual:primaryProperty])
  531. {
  532. if([model singlePrimaryKeyValueIsEmpty])
  533. continue;
  534. }
  535. if(insertKey.length>0)
  536. {
  537. [insertKey appendString:@","];
  538. [insertValuesString appendString:@","];
  539. }
  540. [insertKey appendString:property.sqlColumeName];
  541. [insertValuesString appendString:@"?"];
  542. id value = [self modelValueWithProperty:property model:model];
  543. [insertValues addObject:value];
  544. }
  545. //拼接insertSQL 语句 采用 replace 插入
  546. NSString* insertSQL = [NSString stringWithFormat:@"replace into %@(%@) values(%@)",[modelClass getTableName],insertKey,insertValuesString];
  547. __block BOOL execute = NO;
  548. __block int lastInsertRowId = 0;
  549. [self executeDB:^(FMDatabase *db) {
  550. execute = [db executeUpdate:insertSQL withArgumentsInArray:insertValues];
  551. lastInsertRowId= db.lastInsertRowId;
  552. }];
  553. model.rowid = lastInsertRowId;
  554. // if(execute == NO)
  555. // LKLog(@"database insert fail %@, sql:%@",NSStringFromClass(modelClass),insertSQL);
  556. //callback
  557. [modelClass dbDidInserted:model result:execute];
  558. return execute;
  559. }
  560. #pragma mark- update operation
  561. -(BOOL)updateToDB:(NSObject *)model where:(id)where
  562. {
  563. return [self updateToDBBase:model where:where];
  564. }
  565. -(void)updateToDB:(NSObject *)model where:(id)where callback:(void (^)(BOOL))block
  566. {
  567. [self asyncBlock:^{
  568. BOOL result = [self updateToDBBase:model where:where];
  569. if(block != nil)
  570. block(result);
  571. }];
  572. }
  573. -(BOOL)updateToDBBase:(NSObject *)model where:(NSDictionary*)where
  574. {
  575. checkModelIsInvalid(model);
  576. Class modelClass = model.class;
  577. //callback
  578. [modelClass dbWillUpdate:model];
  579. LKModelInfos* infos = [modelClass getModelInfos];
  580. NSMutableString* updateKey = [NSMutableString string];
  581. NSMutableArray* updateValues = [NSMutableArray arrayWithCapacity:infos.count];
  582. for (int i=0; i<infos.count; i++) {
  583. LKDBProperty* property = [infos objectWithIndex:i];
  584. if(i>0)
  585. [updateKey appendString:@","];
  586. [updateKey appendFormat:@"%@=?",property.sqlColumeName];
  587. id value = [self modelValueWithProperty:property model:model];
  588. [updateValues addObject:value];
  589. }
  590. NSMutableString* updateSQL = [NSMutableString stringWithFormat:@"update %@ set %@ where ",[modelClass getTableName],updateKey];
  591. //添加where 语句
  592. if([where isKindOfClass:[NSString class]] && [LKDBUtils checkStringIsEmpty:where]== NO)
  593. {
  594. [updateSQL appendString:where];
  595. }
  596. else if([where isKindOfClass:[NSDictionary class]] && [where count]>0)
  597. {
  598. NSMutableArray* valuearray = [NSMutableArray array];
  599. NSString* sqlwhere = [self dictionaryToSqlWhere:where andValues:valuearray];
  600. [updateSQL appendString:sqlwhere];
  601. [updateValues addObjectsFromArray:valuearray];
  602. }
  603. else if(model.rowid > 0)
  604. {
  605. [updateSQL appendFormat:@" rowid=%d",model.rowid];
  606. }
  607. else
  608. {
  609. //如果不通过 rowid 来 更新数据 那 primarykey 一定要有值
  610. NSString* pwhere = [self primaryKeyWhereSQLWithModel:model addPValues:updateValues];
  611. if(pwhere.length ==0)
  612. {
  613. LKLog(@"database update fail : %@ no find primary key!",NSStringFromClass(modelClass));
  614. return NO;
  615. }
  616. [updateSQL appendString:pwhere];
  617. }
  618. BOOL execute = [self executeSQL:updateSQL arguments:updateValues];
  619. if(execute == NO)
  620. {
  621. LKLog(@"database update fail : %@ -----> update sql: %@",NSStringFromClass(modelClass),updateSQL);
  622. }
  623. //callback
  624. [modelClass dbDidUpdated:model result:execute];
  625. return execute;
  626. }
  627. -(BOOL)updateToDB:(Class)modelClass set:(NSString *)sets where:(id)where
  628. {
  629. checkClassIsInvalid(modelClass);
  630. NSMutableString* updateSQL = [NSMutableString stringWithFormat:@"update %@ set %@ ",[modelClass getTableName],sets];
  631. NSMutableArray* updateValues = [self extractQuery:updateSQL where:where];
  632. BOOL execute = [self executeSQL:updateSQL arguments:updateValues];
  633. if(execute == NO)
  634. LKLog(@"database update fail %@ ----->sql:%@",NSStringFromClass(modelClass),updateSQL);
  635. return execute;
  636. }
  637. #pragma mark - delete operation
  638. -(BOOL)deleteToDB:(NSObject *)model
  639. {
  640. return [self deleteToDBBase:model];
  641. }
  642. -(void)deleteToDB:(NSObject *)model callback:(void (^)(BOOL))block
  643. {
  644. [self asyncBlock:^{
  645. BOOL isDeleted = [self deleteToDBBase:model];
  646. if(block != nil)
  647. block(isDeleted);
  648. }];
  649. }
  650. -(BOOL)deleteToDBBase:(NSObject *)model
  651. {
  652. checkModelIsInvalid(model);
  653. Class modelClass = model.class;
  654. //callback
  655. [modelClass dbWillDelete:model];
  656. NSMutableString* deleteSQL =[NSMutableString stringWithFormat:@"delete from %@ where ",[modelClass getTableName]];
  657. NSMutableArray* parsArray = [NSMutableArray array];
  658. if(model.rowid > 0)
  659. {
  660. [deleteSQL appendFormat:@"rowid = %d",model.rowid];
  661. }
  662. else
  663. {
  664. NSString* pwhere = [self primaryKeyWhereSQLWithModel:model addPValues:parsArray];
  665. if(pwhere.length==0)
  666. {
  667. LKLog(@"delete fail : %@ primary value is nil",NSStringFromClass(modelClass));
  668. return NO;
  669. }
  670. [deleteSQL appendString:pwhere];
  671. }
  672. if(parsArray.count==0)
  673. parsArray = nil;
  674. BOOL execute = [self executeSQL:deleteSQL arguments:parsArray];
  675. //callback
  676. [modelClass dbDidIDeleted:model result:execute];
  677. return execute;
  678. }
  679. -(BOOL)deleteWithClass:(Class)modelClass where:(id)where
  680. {
  681. return [self deleteWithClassBase:modelClass where:where];
  682. }
  683. -(void)deleteWithClass:(Class)modelClass where:(id)where callback:(void (^)(BOOL))block
  684. {
  685. [self asyncBlock:^{
  686. BOOL isDeleted = [self deleteWithClassBase:modelClass where:where];
  687. if (block != nil) {
  688. block(isDeleted);
  689. }
  690. }];
  691. }
  692. -(BOOL)deleteWithClassBase:(Class)modelClass where:(id)where
  693. {
  694. checkClassIsInvalid(modelClass);
  695. NSMutableString* deleteSQL = [NSMutableString stringWithFormat:@"delete from %@",[modelClass getTableName]];
  696. NSMutableArray* values = [self extractQuery:deleteSQL where:where];
  697. BOOL result = [self executeSQL:deleteSQL arguments:values];
  698. return result;
  699. }
  700. #pragma mark - other operation
  701. -(BOOL)isExistsModel:(NSObject *)model
  702. {
  703. checkModelIsInvalid(model);
  704. if(model.rowid>0)
  705. return YES;
  706. else
  707. {
  708. NSMutableString* pwhere = [self primaryKeyWhereSQLWithModel:model addPValues:nil];
  709. if(pwhere.length == 0)
  710. {
  711. LKLog(@"exists model fail: primary key is nil or invalid");
  712. return NO;
  713. }
  714. return [self isExistsClass:model.class where:pwhere];
  715. }
  716. }
  717. -(BOOL)isExistsClass:(Class)modelClass where:(id)where
  718. {
  719. return [self isExistsClassBase:modelClass where:where];
  720. }
  721. -(BOOL)isExistsClassBase:(Class)modelClass where:(id)where
  722. {
  723. return [self rowCount:modelClass where:where] > 0;
  724. }
  725. #pragma mark- clear operation
  726. +(void)clearTableData:(Class)modelClass
  727. {
  728. [[modelClass getUsingLKDBHelper] executeDB:^(FMDatabase *db) {
  729. NSString* delete = [NSString stringWithFormat:@"DELETE FROM %@",[modelClass getTableName]];
  730. [db executeUpdate:delete];
  731. }];
  732. }
  733. +(void)clearNoneImage:(Class)modelClass columes:(NSArray *)columes
  734. {
  735. [self clearFileWithTable:modelClass columes:columes type:1];
  736. }
  737. +(void)clearNoneData:(Class)modelClass columes:(NSArray *)columes
  738. {
  739. [self clearFileWithTable:modelClass columes:columes type:2];
  740. }
  741. #define LKTestDirFilename @"LKTestDirFilename111"
  742. +(void)clearFileWithTable:(Class)modelClass columes:(NSArray*)columes type:(int)type
  743. {
  744. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
  745. NSString* testpath = nil;
  746. switch (type) {
  747. case 1:
  748. testpath = [modelClass getDBImagePathWithName:LKTestDirFilename];
  749. break;
  750. case 2:
  751. testpath = [modelClass getDBDataPathWithName:LKTestDirFilename];
  752. break;
  753. }
  754. if([LKDBUtils checkStringIsEmpty:testpath])
  755. return ;
  756. NSString* dir = [testpath stringByReplacingOccurrencesOfString:LKTestDirFilename withString:@""];
  757. NSInteger count = columes.count;
  758. //获取该目录下所有文件名
  759. NSArray* files = [LKDBUtils getFilenamesWithDir:dir];
  760. NSString* seleteColume = [columes componentsJoinedByString:@","];
  761. NSMutableString* whereStr =[NSMutableString string];
  762. for (int i=0; i<count ; i++) {
  763. [whereStr appendFormat:@" %@ != '' ",[columes objectAtIndex:i]];
  764. if(i< count -1)
  765. {
  766. [whereStr appendString:@" or "];
  767. }
  768. }
  769. NSString* querySql = [NSString stringWithFormat:@"select %@ from %@ where %@",seleteColume,[modelClass getTableName],whereStr];
  770. __block NSArray* dbfiles;
  771. [[modelClass getUsingLKDBHelper] executeDB:^(FMDatabase *db) {
  772. NSMutableArray* tempfiles = [NSMutableArray arrayWithCapacity:6];
  773. FMResultSet* set = [db executeQuery:querySql];
  774. while ([set next]) {
  775. for (int j=0; j<count; j++) {
  776. NSString* str = [set stringForColumnIndex:j];
  777. if([LKDBUtils checkStringIsEmpty:str] ==NO)
  778. {
  779. [tempfiles addObject:str];
  780. }
  781. }
  782. }
  783. [set close];
  784. dbfiles = tempfiles;
  785. }];
  786. //遍历 当不再数据库记录中 就删除
  787. for (NSString* deletefile in files) {
  788. if([dbfiles indexOfObject:deletefile] == NSNotFound)
  789. {
  790. [LKDBUtils deleteWithFilepath:[dir stringByAppendingPathComponent:deletefile]];
  791. }
  792. }
  793. });
  794. }
  795. @end