Просмотр исходного кода

Abstracted database parser logic and added framework for Realm parser.

Tim Oliver лет назад: 10
Родитель
Сommit
12a1900d75

+ 13 - 1
Classes/GlobalStateExplorers/DatabaseBrowser/FLEXDatabaseManager.h

@@ -13,10 +13,22 @@
 
 #import <Foundation/Foundation.h>
 
+@protocol FLEXDatabaseManagerParser <NSObject>
+
+- (instancetype)initWithPath:(NSString*)path;
+
+- (BOOL)open;
+- (NSArray *)queryAllTables;
+- (NSArray *)queryAllColumnsWithTableName:(NSString *)tableName;
+- (NSArray *)queryAllDataWithTableName:(NSString *)tableName;
+
+@end
+
 @interface FLEXDatabaseManager : NSObject
 
+@property (nonatomic, readonly) NSString *path;
 
-- (instancetype)initWithPath:(NSString*)aPath;
+- (instancetype)initWithPath:(NSString*)path;
 
 - (BOOL)open;
 - (NSArray *)queryAllTables;

+ 21 - 151
Classes/GlobalStateExplorers/DatabaseBrowser/FLEXDatabaseManager.m

@@ -6,190 +6,60 @@
 //  Copyright © 2015年 Peng Tao. All rights reserved.
 //
 
-
-
+#import <Foundation/Foundation.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
 {
     self = [super init];
     
     if (self) {
         _databasePath = [aPath copy];
+        _parser = [self parserForFileAtPath:aPath];
     }
     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
 {
-    return [self executeQuery:QUERY_TABLENAMES_SQL];
+    return [_parser queryAllTables];
 }
 
 - (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
 {
-    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

+ 14 - 0
Classes/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDatabaseParser.h

@@ -0,0 +1,14 @@
+//
+//  FLEXRealmDatabaseManager.h
+//  FLEX
+//
+//  Created by Tim Oliver on 28/01/2016.
+//  Copyright © 2016 Realm. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "FLEXDatabaseManager.h"
+
+@interface FLEXRealmDatabaseParser : NSObject <FLEXDatabaseManagerParser>
+
+@end

+ 75 - 0
Classes/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDatabaseParser.m

@@ -0,0 +1,75 @@
+//
+//  FLEXRealmDatabaseManager.m
+//  FLEX
+//
+//  Created by Tim Oliver on 28/01/2016.
+//  Copyright © 2016 Realm. All rights reserved.
+//
+
+#import "FLEXRealmDatabaseParser.h"
+
+//#if __has_include("<Realm/Realm.h>")
+
+#import <Realm/Realm.h>
+
+@interface FLEXRealmDatabaseParser ()
+
+@property (nonatomic, copy) NSString *path;
+@property (nonatomic, strong) RLMRealm *realm;
+
+@end
+
+@implementation FLEXRealmDatabaseParser
+
+- (instancetype)initWithPath:(NSString*)aPath
+{
+    self = [super init];
+    
+    if (self) {
+        _path = aPath;
+    }
+    return self;
+}
+
+- (BOOL)open
+{
+    RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
+    configuration.dynamic = YES;
+    configuration.path = self.path;
+    
+    NSError *error = nil;
+    self.realm = [RLMRealm realmWithConfiguration:configuration error:&error];
+    
+    return (error == nil);
+}
+
+- (NSArray *)queryAllTables
+{
+    NSMutableArray *allTables = [NSMutableArray array];
+    RLMSchema *schema = self.realm.schema;
+    
+    for (RLMObjectSchema *objectSchema in schema.objectSchema) {
+        if (objectSchema.className == nil) {
+            continue;
+        }
+        
+        NSDictionary *dictionary = @{@"name":objectSchema.className};
+        [allTables addObject:dictionary];
+    }
+    
+    return allTables;
+}
+
+- (NSArray *)queryAllColumnsWithTableName:(NSString *)tableName
+{
+    return nil;
+}
+
+- (NSArray *)queryAllDataWithTableName:(NSString *)tableName
+{
+    return nil;
+}
+
+@end
+
+//#endif

+ 19 - 0
Classes/GlobalStateExplorers/DatabaseBrowser/FLEXSQLiteDatabaseParser.h

@@ -0,0 +1,19 @@
+//
+//  PTDatabaseManager.h
+//  Derived from:
+//
+//  FMDatabase.h
+//  FMDB( https://github.com/ccgus/fmdb )
+//
+//  Created by Peng Tao on 15/11/23.
+//
+//  Licensed to Flying Meat Inc. under one or more contributor license agreements.
+//  See the LICENSE file distributed with this work for the terms under
+//  which Flying Meat Inc. licenses this file to you.
+
+#import <Foundation/Foundation.h>
+#import "FLEXDatabaseManager.h"
+
+@interface FLEXSQLiteDatabaseParser : NSObject <FLEXDatabaseManagerParser>
+
+@end

+ 192 - 0
Classes/GlobalStateExplorers/DatabaseBrowser/FLEXSQLiteDatabaseParser.m

@@ -0,0 +1,192 @@
+//
+//  PTDatabaseManager.m
+//  PTDatabaseReader
+//
+//  Created by Peng Tao on 15/11/23.
+//  Copyright © 2015年 Peng Tao. All rights reserved.
+//
+
+
+
+#import "FLEXSQLiteDatabaseParser.h"
+#import <sqlite3.h>
+
+
+static NSString *const QUERY_TABLENAMES_SQL = @"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name";
+
+@implementation FLEXSQLiteDatabaseParser
+{
+    sqlite3* _db;
+    NSString* _databasePath;
+}
+
+- (instancetype)initWithPath:(NSString*)aPath
+{
+    self = [super init];
+    
+    if (self) {
+        _databasePath = [aPath copy];
+    }
+    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;
+}
+
+
+- (NSArray *)queryAllTables
+{
+    return [self executeQuery:QUERY_TABLENAMES_SQL];
+}
+
+- (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;
+}
+
+- (NSArray *)queryAllDataWithTableName:(NSString *)tableName
+{
+    NSString *sql = [NSString stringWithFormat:@"SELECT * FROM %@",tableName];
+    return [self executeQuery:sql];
+}
+
+#pragma mark -
+#pragma mark - Private
+
+- (NSArray *)executeQuery:(NSString *)sql
+{
+    [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;
+    
+    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)];
+    }
+    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];
+    }
+    
+    return returnValue;
+}
+
+- (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

+ 1 - 1
Classes/GlobalStateExplorers/FLEXFileBrowserTableViewController.m

@@ -217,7 +217,7 @@
                 drillInViewController = [[FLEXWebViewController alloc] initWithText:prettyString];
             } else if ([FLEXWebViewController supportsPathExtension:pathExtension]) {
                 drillInViewController = [[FLEXWebViewController alloc] initWithURL:[NSURL fileURLWithPath:fullPath]];
-            } else if ([[subpath pathExtension] isEqualToString:@"db"]) {
+            } else if ([@[@"db", @"sqlite3", @"realm"] containsObject:[subpath pathExtension]]) {
               drillInViewController = [[FLEXTableListViewController alloc] initWithPath:fullPath];
             }
             else {