第二次添加行时获取数据库锁定错误

时间:2016-07-22 19:46:04

标签: ios objective-c iphone sqlite

我收到错误数据库锁定。 在第一次尝试它添加行但在此之后我得到错误 的 database locked 即可。

我正在尝试制作网页保护程序,所以在应用程序加载时第一次添加行但是当我再次尝试保存任何不保存的网页时,我将错误数据库锁定。

保存一个网页后,即使删除也不会发生。

#import "DBManager.h"
static DBManager *sharedInstance = nil;
static sqlite3 *database = nil;
static sqlite3_stmt *statement = nil;

 @implementation DBManager

 +(DBManager*)getSharedInstance{
if (!sharedInstance) {
    sharedInstance = [[super allocWithZone:NULL]init];
    [sharedInstance createDB];
}
return sharedInstance;
}

-(BOOL)createDB{
NSString *docsDir;
NSArray *dirPaths;
// Get the documents directory
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = dirPaths[0];
// Build the path to the database file
databasePath = [[NSString alloc] initWithString:[docsDir stringByAppendingPathComponent: @"browser.db"]];

BOOL isSuccess = YES;
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: databasePath ] == NO)
{
    const char *dbpath = [databasePath UTF8String];
    if (sqlite3_open(dbpath, &database) == SQLITE_OK)
    {
        char *errMsg;
        NSLog(@"insod");
        const char *sql_stmt ="create table if not exists list(sno int primary key,name varchar(50),category varchar(30),path varchar(500),fav int)";
        if (sqlite3_exec(database, sql_stmt, NULL, NULL, &errMsg)
            != SQLITE_OK)
        {
            isSuccess = NO;
            NSLog(@"Failed to create table");
        }
        sqlite3_close(database);
        return  isSuccess;
    }
    else {
        isSuccess = NO;
        NSLog(@"Failed to open/create database");
    }
}else{
    NSLog(@"File Exist");
}
return isSuccess;
 }

 -(BOOL) Delete:(NSString *) name{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK){
    NSString *query = [NSString stringWithFormat:@"delete from list where name like '%@'",name];
    const char *stmt = [query UTF8String];
    sqlite3_prepare_v2(database, stmt,-1, &statement, NULL);
    if (sqlite3_step(statement) == SQLITE_DONE){
        sqlite3_finalize(statement);
        return YES;
    }else {
         NSLog(@"error: %s",sqlite3_errmsg(database));
        sqlite3_finalize(statement);
        return NO;
    }

}else{
    sqlite3_close(database);
    return NO;
}

 }

-(NSDictionary *) CatList:(NSString *) cat{
const char *dbpath = [databasePath UTF8String];
NSDictionary *dict;
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{

    NSString *querySQL =[NSString stringWithFormat:@"select name,path from list where category like '%@'",cat];
    const char *query_stmt = [querySQL UTF8String];

    if (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK)
    {
       // NSLog(@"inside list");

        NSMutableArray *arr1 = [[NSMutableArray alloc] init];
        NSMutableArray *arr2 = [[NSMutableArray alloc] init];
        //            NSMutableArray *arr3 = [[NSMutableArray alloc] init];
        while(sqlite3_step(statement) == SQLITE_ROW)
        {

            NSString *name = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
            [arr1 addObject:name];
            //NSLog(@"%@",name);
            NSString *category = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)];
            [arr2 addObject:category];
            //                //NSLog(@"%@",dept);
            //                NSString *path = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 3)];
            //                [arr3 addObject:path];
        }
        sqlite3_finalize(statement);
        dict = @{@"name":arr1,@"path":arr2};
        //NSLog(@"%@",dict);
    }else{
        NSLog(@"error: %s",sqlite3_errmsg(database));
    }
    sqlite3_close(database);
}
return dict;
 }

 - (BOOL) saveData:(NSString*)name category:(NSString*)category path:(NSString*)path{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{

    NSString *highest = @"select max(sno) from list";
    const char *Query = [highest UTF8String];

    if (sqlite3_prepare_v2(database, Query, -1, &statement, NULL) == SQLITE_OK){
        if (sqlite3_step(statement) == SQLITE_ROW){
            int sno = sqlite3_column_int(statement, 0);
            NSString *insertSQL = [NSString stringWithFormat:@"insert into list values(\"%d\",\"%@\",\"%@\", \"%@\",\"%d\")",sno+1,name, category, path,0];
            const char *insert_stmt = [insertSQL UTF8String];
            sqlite3_prepare_v2(database, insert_stmt,-1, &statement, NULL);
            if (sqlite3_step(statement) == SQLITE_DONE){
                sqlite3_finalize(statement);
                return YES;
            }else {
                sqlite3_finalize(statement);
                return NO;
            }

        }else{
            NSString *insertSQL = [NSString stringWithFormat:@"insert into list values(\"%d\",\"%@\",\"%@\", \"%@\",\"%d\")",1,name, category, path,0];
            const char *insert_stmt = [insertSQL UTF8String];
            sqlite3_prepare_v2(database, insert_stmt,-1, &statement, NULL);
            if (sqlite3_step(statement) == SQLITE_DONE){
                sqlite3_finalize(statement);
                return YES;
            }else {
                sqlite3_finalize(statement);
                return NO;
            }
        }
    }
    sqlite3_close(database);
}
return NO;
 }

 -(BOOL) Fav:(NSString *) name{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK){
    NSString *query = [NSString stringWithFormat:@"update list set fav = 1 where name like '%@'",name];
    const char *stmt = [query UTF8String];
    sqlite3_prepare_v2(database, stmt,-1, &statement, NULL);
    if (sqlite3_step(statement) == SQLITE_DONE){
        sqlite3_finalize(statement);
        return YES;
    }else {
        sqlite3_finalize(statement);
        return NO;
    }
}else{

    return NO;
}
 }

 -(NSArray *) GetListFav{
const char *dbpath = [databasePath UTF8String];
NSArray *dict;
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{

    NSString *querySQL = @"select name from list where fav = 1";
    const char *query_stmt = [querySQL UTF8String];

    if (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK)
    {
        NSMutableArray *arr1 = [[NSMutableArray alloc] init];
        while(sqlite3_step(statement) == SQLITE_ROW)
        {
            NSString *name = [[NSString alloc] initWithUTF8String:              (const char *) sqlite3_column_text(statement, 0)];
            [arr1 addObject:name];
        }
        sqlite3_finalize(statement);
        dict = arr1;
    }else{
        NSLog(@"error: %s",sqlite3_errmsg(database));
    }
    sqlite3_close(database);
}
return dict;
 }

 -(BOOL) removeFav:(NSString *) name{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK){
    NSString *query = [NSString stringWithFormat:@"update list set fav = 0 where name like '%@'",name];
    const char *stmt = [query UTF8String];
    sqlite3_prepare_v2(database, stmt,-1, &statement, NULL);
    if (sqlite3_step(statement) == SQLITE_DONE){
        sqlite3_finalize(statement);
        return YES;
    }else {
        sqlite3_finalize(statement);
        return NO;
    }

}else{
    return NO;
}
}

 -(NSArray *) GetList{
const char *dbpath = [databasePath UTF8String];
NSArray *dict;
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{

    NSString *querySQL = @"select name from list";
    const char *query_stmt = [querySQL UTF8String];

    if (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK)
    {
        //NSLog(@"inside list");

        NSMutableArray *arr1 = [[NSMutableArray alloc] init];
        while(sqlite3_step(statement) == SQLITE_ROW)
        {
            NSString *name = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
            [arr1 addObject:name];
        }
        sqlite3_finalize(statement);
        dict = arr1;
    }else{
        NSLog(@"error: %s",sqlite3_errmsg(database));
    }
    sqlite3_close(database);
}
return dict;
  }

 @end

2 个答案:

答案 0 :(得分:0)

您一次只能访问一次sqllite。如果您有多个线程,则可以在这种情况下运行。例如:

因此,一旦使用以下内容,请务必尝试关闭数据库:

sqlite3_close(database);

答案 1 :(得分:0)

在尝试再次sqlite3_open之前,您需要确保每个sqlite3_closesqlite3_open保持平衡:

  1. 您的saveData方法有相当多的return语句会阻止数据库调用sqlite3_close。确保方法之外的所有路径都正确关闭数据库。最后,这意味着您将尝试打开数据库,尽管它已经打开。

    或者,更好的是,只需打开数据库一次并保持打开状态,从而消除数据库的重复打开和关闭。

  2. 您的DeleteFavremoveFav方法也未关闭数据库。

  3. 一些不相关的观察结果:

    1. 您应该谨慎使用stringWithFormat使用字符串参数构建SQL。如果要搜索的字符串中包含撇号,则代码将失败。使用?占位符,然后使用sqlite3_bind_text将值绑定到这些占位符。

    2. 如果您将sno列设为AUTOINCREMENT,则无法执行此操作"在插入新行之前获取最大值"逻辑。因此,CREATE语句可能如下所示:

      create table if not exists list (
          sno integer primary key autoincrement, 
          name text, 
          category text, 
          path text, 
          fav integer)
      

      然后,您可以从sno语句中省略INSERT,并自动为其分配唯一标识符。