You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
203 lines
5.5 KiB
203 lines
5.5 KiB
//
|
|
// PTDatabaseManager.m
|
|
// PTDatabaseReader
|
|
//
|
|
// Created by Peng Tao on 15/11/23.
|
|
// Copyright © 2015年 Peng Tao. All rights reserved.
|
|
//
|
|
|
|
#import "FLEXSQLiteDatabaseManager.h"
|
|
#import "FLEXManager.h"
|
|
#import <sqlite3.h>
|
|
|
|
|
|
static NSString *const QUERY_TABLENAMES_SQL = @"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name";
|
|
|
|
@implementation FLEXSQLiteDatabaseManager
|
|
{
|
|
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 SQLITE_HAS_CODEC
|
|
NSString *defaultSqliteDatabasePassword = [FLEXManager sharedManager].defaultSqliteDatabasePassword;
|
|
|
|
if (defaultSqliteDatabasePassword) {
|
|
const char *key = defaultSqliteDatabasePassword.UTF8String;
|
|
|
|
sqlite3_key(_db, key, (int)strlen(key));
|
|
}
|
|
#endif
|
|
|
|
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<NSDictionary<NSString *, id> *> *)queryAllTables
|
|
{
|
|
return [self executeQuery:QUERY_TABLENAMES_SQL];
|
|
}
|
|
|
|
- (NSArray<NSString *> *)queryAllColumnsWithTableName:(NSString *)tableName
|
|
{
|
|
NSString *sql = [NSString stringWithFormat:@"PRAGMA table_info('%@')",tableName];
|
|
NSArray<NSDictionary<NSString *, id> *> *resultArray = [self executeQuery:sql];
|
|
NSMutableArray<NSString *> *array = [NSMutableArray array];
|
|
for (NSDictionary<NSString *, id> *dict in resultArray) {
|
|
NSString *columnName = (NSString *)dict[@"name"] ?: @"";
|
|
[array addObject:columnName];
|
|
}
|
|
return array;
|
|
}
|
|
|
|
- (NSArray<NSDictionary<NSString *, id> *> *)queryAllDataWithTableName:(NSString *)tableName
|
|
{
|
|
NSString *sql = [NSString stringWithFormat:@"SELECT * FROM %@",tableName];
|
|
return [self executeQuery:sql];
|
|
}
|
|
|
|
#pragma mark -
|
|
#pragma mark - Private
|
|
|
|
- (NSArray<NSDictionary<NSString *, id> *> *)executeQuery:(NSString *)sql
|
|
{
|
|
[self open];
|
|
NSMutableArray<NSDictionary<NSString *, id> *> *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<NSString *, id> *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
|