|
@@ -6,190 +6,60 @@
|
|
|
// Copyright © 2015年 Peng Tao. All rights reserved.
|
|
// Copyright © 2015年 Peng Tao. All rights reserved.
|
|
|
//
|
|
//
|
|
|
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
|
|
+#import <Foundation/Foundation.h>
|
|
|
#import "FLEXDatabaseManager.h"
|
|
#import "FLEXDatabaseManager.h"
|
|
|
-#import <sqlite3.h>
|
|
|
|
|
-
|
|
|
|
|
|
|
|
|
|
-static NSString *const QUERY_TABLENAMES_SQL = @"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name";
|
|
|
|
|
|
|
+#import "FLEXSQLiteDatabaseParser.h"
|
|
|
|
|
+#import "FLEXRealmDatabaseParser.h"
|
|
|
|
|
|
|
|
-
|
|
|
|
|
-@implementation FLEXDatabaseManager
|
|
|
|
|
-{
|
|
|
|
|
- sqlite3* _db;
|
|
|
|
|
- NSString* _databasePath;
|
|
|
|
|
|
|
+@implementation FLEXDatabaseManager {
|
|
|
|
|
+ NSString *_databasePath;
|
|
|
|
|
+ id<FLEXDatabaseManagerParser> _parser;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
- (instancetype)initWithPath:(NSString*)aPath
|
|
- (instancetype)initWithPath:(NSString*)aPath
|
|
|
{
|
|
{
|
|
|
self = [super init];
|
|
self = [super init];
|
|
|
|
|
|
|
|
if (self) {
|
|
if (self) {
|
|
|
_databasePath = [aPath copy];
|
|
_databasePath = [aPath copy];
|
|
|
|
|
+ _parser = [self parserForFileAtPath:aPath];
|
|
|
}
|
|
}
|
|
|
return self;
|
|
return self;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
-- (BOOL)open {
|
|
|
|
|
- if (_db) {
|
|
|
|
|
- return YES;
|
|
|
|
|
- }
|
|
|
|
|
- int err = sqlite3_open([_databasePath UTF8String], &_db);
|
|
|
|
|
- if(err != SQLITE_OK) {
|
|
|
|
|
- NSLog(@"error opening!: %d", err);
|
|
|
|
|
- return NO;
|
|
|
|
|
- }
|
|
|
|
|
- return YES;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-- (BOOL)close {
|
|
|
|
|
- if (!_db) {
|
|
|
|
|
- return YES;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- int rc;
|
|
|
|
|
- BOOL retry;
|
|
|
|
|
- BOOL triedFinalizingOpenStatements = NO;
|
|
|
|
|
-
|
|
|
|
|
- do {
|
|
|
|
|
- retry = NO;
|
|
|
|
|
- rc = sqlite3_close(_db);
|
|
|
|
|
- if (SQLITE_BUSY == rc || SQLITE_LOCKED == rc) {
|
|
|
|
|
- if (!triedFinalizingOpenStatements) {
|
|
|
|
|
- triedFinalizingOpenStatements = YES;
|
|
|
|
|
- sqlite3_stmt *pStmt;
|
|
|
|
|
- while ((pStmt = sqlite3_next_stmt(_db, nil)) !=0) {
|
|
|
|
|
- NSLog(@"Closing leaked statement");
|
|
|
|
|
- sqlite3_finalize(pStmt);
|
|
|
|
|
- retry = YES;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- else if (SQLITE_OK != rc) {
|
|
|
|
|
- NSLog(@"error closing!: %d", rc);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- while (retry);
|
|
|
|
|
-
|
|
|
|
|
- _db = nil;
|
|
|
|
|
- return YES;
|
|
|
|
|
|
|
+- (BOOL)open
|
|
|
|
|
+{
|
|
|
|
|
+ return [_parser open];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
- (NSArray *)queryAllTables
|
|
- (NSArray *)queryAllTables
|
|
|
{
|
|
{
|
|
|
- return [self executeQuery:QUERY_TABLENAMES_SQL];
|
|
|
|
|
|
|
+ return [_parser queryAllTables];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- (NSArray *)queryAllColumnsWithTableName:(NSString *)tableName
|
|
- (NSArray *)queryAllColumnsWithTableName:(NSString *)tableName
|
|
|
{
|
|
{
|
|
|
- NSString *sql = [NSString stringWithFormat:@"PRAGMA table_info('%@')",tableName];
|
|
|
|
|
- NSArray *resultArray = [self executeQuery:sql];
|
|
|
|
|
- NSMutableArray *array = [NSMutableArray array];
|
|
|
|
|
- for (NSDictionary *dict in resultArray) {
|
|
|
|
|
- [array addObject:dict[@"name"]];
|
|
|
|
|
- }
|
|
|
|
|
- return array;
|
|
|
|
|
|
|
+ return [_parser queryAllColumnsWithTableName:tableName];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- (NSArray *)queryAllDataWithTableName:(NSString *)tableName
|
|
- (NSArray *)queryAllDataWithTableName:(NSString *)tableName
|
|
|
{
|
|
{
|
|
|
- NSString *sql = [NSString stringWithFormat:@"SELECT * FROM %@",tableName];
|
|
|
|
|
- return [self executeQuery:sql];
|
|
|
|
|
|
|
+ return [_parser queryAllDataWithTableName:tableName];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-#pragma mark -
|
|
|
|
|
-#pragma mark - Private
|
|
|
|
|
-
|
|
|
|
|
-- (NSArray *)executeQuery:(NSString *)sql
|
|
|
|
|
|
|
+- (id<FLEXDatabaseManagerParser>)parserForFileAtPath:(NSString *)path
|
|
|
{
|
|
{
|
|
|
- [self open];
|
|
|
|
|
- NSMutableArray *resultArray = [NSMutableArray array];
|
|
|
|
|
- sqlite3_stmt *pstmt;
|
|
|
|
|
- if (sqlite3_prepare_v2(_db, [sql UTF8String], -1, &pstmt, 0) == SQLITE_OK) {
|
|
|
|
|
- while (sqlite3_step(pstmt) == SQLITE_ROW) {
|
|
|
|
|
- NSUInteger num_cols = (NSUInteger)sqlite3_data_count(pstmt);
|
|
|
|
|
- if (num_cols > 0) {
|
|
|
|
|
- NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:num_cols];
|
|
|
|
|
-
|
|
|
|
|
- int columnCount = sqlite3_column_count(pstmt);
|
|
|
|
|
-
|
|
|
|
|
- int columnIdx = 0;
|
|
|
|
|
- for (columnIdx = 0; columnIdx < columnCount; columnIdx++) {
|
|
|
|
|
-
|
|
|
|
|
- NSString *columnName = [NSString stringWithUTF8String:sqlite3_column_name(pstmt, columnIdx)];
|
|
|
|
|
- id objectValue = [self objectForColumnIndex:columnIdx stmt:pstmt];
|
|
|
|
|
- [dict setObject:objectValue forKey:columnName];
|
|
|
|
|
- }
|
|
|
|
|
- [resultArray addObject:dict];
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- [self close];
|
|
|
|
|
- return resultArray;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-- (id)objectForColumnIndex:(int)columnIdx stmt:(sqlite3_stmt*)stmt {
|
|
|
|
|
- int columnType = sqlite3_column_type(stmt, columnIdx);
|
|
|
|
|
-
|
|
|
|
|
- id returnValue = nil;
|
|
|
|
|
|
|
+ NSString *pathExtension = path.pathExtension;
|
|
|
|
|
|
|
|
- if (columnType == SQLITE_INTEGER) {
|
|
|
|
|
- returnValue = [NSNumber numberWithLongLong:sqlite3_column_int64(stmt, columnIdx)];
|
|
|
|
|
- }
|
|
|
|
|
- else if (columnType == SQLITE_FLOAT) {
|
|
|
|
|
- returnValue = [NSNumber numberWithDouble:sqlite3_column_double(stmt, columnIdx)];
|
|
|
|
|
|
|
+ if ([@[@"db", @"sqlite", @"sqlite3"] containsObject:pathExtension]) {
|
|
|
|
|
+ return [[FLEXSQLiteDatabaseParser alloc] initWithPath:path];
|
|
|
}
|
|
}
|
|
|
- else if (columnType == SQLITE_BLOB) {
|
|
|
|
|
- returnValue = [self dataForColumnIndex:columnIdx stmt:stmt];
|
|
|
|
|
- }
|
|
|
|
|
- else {
|
|
|
|
|
- //default to a string for everything else
|
|
|
|
|
- returnValue = [self stringForColumnIndex:columnIdx stmt:stmt];
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (returnValue == nil) {
|
|
|
|
|
- returnValue = [NSNull null];
|
|
|
|
|
|
|
+ else if ([pathExtension isEqualToString:@"realm"]) {
|
|
|
|
|
+ return [[FLEXRealmDatabaseParser alloc] initWithPath:path];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return returnValue;
|
|
|
|
|
|
|
+ return nil;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-- (NSString *)stringForColumnIndex:(int)columnIdx stmt:(sqlite3_stmt *)stmt {
|
|
|
|
|
-
|
|
|
|
|
- if (sqlite3_column_type(stmt, columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
|
|
|
|
|
- return nil;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- const char *c = (const char *)sqlite3_column_text(stmt, columnIdx);
|
|
|
|
|
-
|
|
|
|
|
- if (!c) {
|
|
|
|
|
- // null row.
|
|
|
|
|
- return nil;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return [NSString stringWithUTF8String:c];
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-- (NSData *)dataForColumnIndex:(int)columnIdx stmt:(sqlite3_stmt *)stmt{
|
|
|
|
|
-
|
|
|
|
|
- if (sqlite3_column_type(stmt, columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
|
|
|
|
|
- return nil;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- const char *dataBuffer = sqlite3_column_blob(stmt, columnIdx);
|
|
|
|
|
- int dataSize = sqlite3_column_bytes(stmt, columnIdx);
|
|
|
|
|
-
|
|
|
|
|
- if (dataBuffer == NULL) {
|
|
|
|
|
- return nil;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return [NSData dataWithBytes:(const void *)dataBuffer length:(NSUInteger)dataSize];
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-@end
|
|
|
|
|
|
|
+@end
|