SQLITE Database Error 14

2019-09-03 14:49发布

问题:

I'm developing a game where there are 4 buildings and in these buildings, there are 3 stages inside. The player can play the stages one by one, from one building to another, however, when they have finished one cycle (eg. going from building 1 stage 1 to building 4 stage 3) I keep getting this error where it's an error 14 (SQLITE_CANTOPEN) whenever the player clicks on another building. It keeps happening every single time I test the app. Can anyone help me? :S

edit: sorry, here's the code I used to open the window to access the game:

NSArray *bldgLevels = [[SQLiteManager sharedManager] fetchDataFromDatabase: MAIN_DATABASE 
                                                                         withQuery: SQL_STMT_GET_BUILDING_LEVELS 
                                                                withValuesAndTypes: [NSArray arrayWithObjects: 
                                                                                     [NSString stringWithFormat: @"%d", gameStateProxy.selectedArea], @"i", nil]];

        NSLog(@"bldgLevels: %@", bldgLevels);

        NSLog(@"getting player levels");
        NSArray *playerLevels = [[SQLiteManager sharedManager] fetchDataFromDatabase: MAIN_DATABASE 
                                                                           withQuery: SQL_STMT_GET_PLAYER_UNLOCKED_LEVELS 
                                                                  withValuesAndTypes: [NSArray arrayWithObjects: 
                                                                                       [NSString stringWithFormat: @"%d", gameStateProxy.playerId], @"i", nil]];

        NSLog(@"playerLevels: %@", playerLevels);

        int i = 0;
        while (i < [bldgLevels count]) 
        {
            NSDictionary *bldgLevel = (NSDictionary *)[bldgLevels objectAtIndex: i];
            int levelId = [(NSNumber *)[bldgLevel objectForKey: @"level_id"] intValue];
            int indexOrder = [(NSNumber *)[bldgLevel objectForKey: @"index_order"] intValue];

            data = [BldgLevelData createObject];
            data.levelId = levelId;
            data.levelName = (NSString *)[bldgLevel objectForKey: @"name"];
            data.rescuedPtsRequired = [(NSNumber *)[bldgLevel objectForKey: @"rescued_required"] intValue];
            data.minPtsToComplete = [(NSNumber *)[bldgLevel objectForKey: @"min_pts"] intValue];
            data.lastPlayed = @"";
            data.dateAdded = @"";
            data.isNew = NO;
            data.isCompleted = NO;
            data.isLocked = YES;

            // Group levels together by their index order
            if (indexOrder == 1) { groupId++; }
            data.groupId = groupId;
            data.indexOrder = indexOrder;

            int j = 0;
            while (j < [playerLevels count]) 
            {
                NSDictionary *playerLevel = (NSDictionary *)[playerLevels objectAtIndex: j];
                int playerLevelId = [(NSNumber *)[playerLevel objectForKey: @"level_id"] intValue];

                if (levelId == playerLevelId)
                {
                    data.rescuedHighScore = [(NSNumber *)[playerLevel objectForKey: @"rescued_highscore"] intValue];
                    data.rescuedScore = [(NSNumber *)[playerLevel objectForKey: @"rescued_score"] intValue];
                    data.lastPlayed = (NSString *)[playerLevel objectForKey: @"lastplayed"];
                    data.dateAdded = (NSString *)[playerLevel objectForKey: @"dateadded"];
                    data.isNew = ([(NSString *)[playerLevel objectForKey: @"lastplayed"] isEqualToString: @""]);
                    data.isCompleted = ([(NSNumber *)[playerLevel objectForKey: @"completed"] intValue] == 1);
                    data.isLocked = NO;

                    break;
                }

                j++;
            }

            if (indexOrder == 1)
            {
                list = [NSMutableArray arrayWithCapacity: 1];

                groupData = [BldgLevelGroupData createObject];
                groupData.groupId = groupId;
                groupData.firstLevelId = levelId;
                groupData.timeLimit = [(NSNumber *)[bldgLevel objectForKey: @"time_limit"] intValue];
                groupData.list = list;


                // Get SOS items
                NSMutableArray *sosItems = [NSMutableArray arrayWithCapacity: 0];
                //
                NSLog(@"getting levelSOSItems");

                NSLog(@"i: %d, j: %d", i, j);
                NSLog(@"list: %@", list);
                NSLog(@"levelId: %d", levelId);

                NSArray *levelSOSItems = [[SQLiteManager sharedManager] fetchDataFromDatabase: MAIN_DATABASE 
                                                                                    withQuery: SQL_STMT_GET_LEVEL_SOS 
                                                                           withValuesAndTypes: [NSArray arrayWithObjects: 
                                                                                                [NSString stringWithFormat: @"%d", levelId], @"i", nil]];

                NSLog(@"Levelsositems: %@", levelSOSItems);

                NSLog(@"getting player sos Items");
                NSArray *playerSOSItems = [[SQLiteManager sharedManager] fetchDataFromDatabase: MAIN_DATABASE 
                                                                                     withQuery: SQL_STMT_GET_PLAYER_SOS 
                                                                            withValuesAndTypes: [NSArray arrayWithObjects: 
                                                                                                 [NSString stringWithFormat: @"%d", gameStateProxy.playerId], @"i", 
                                                                                                 nil]];

                NSLog(@"playerSoSItems: %@", playerSOSItems);

                j = 0;
                while (j < [levelSOSItems count])
                {
                    SOSItemData *sosItemData = [SOSItemData createObject];
                    sosItemData.itemId = [(NSNumber *)[(NSDictionary *)[levelSOSItems objectAtIndex: j] objectForKey: @"sos_id"] intValue];
                    sosItemData.itemName = (NSString *)[(NSDictionary *)[levelSOSItems objectAtIndex: j] objectForKey: @"name"];
                    sosItemData.desc = (NSString *)[(NSDictionary *)[levelSOSItems objectAtIndex: j] objectForKey: @"desc"];
                    sosItemData.coins = [(NSNumber *)[(NSDictionary *)[levelSOSItems objectAtIndex: j] objectForKey: @"coins_cost"] intValue];
                    sosItemData.cash = [(NSNumber *)[(NSDictionary *)[levelSOSItems objectAtIndex: j] objectForKey: @"cash_cost"] intValue];
                    sosItemData.rescuedPtsRequired = [(NSNumber *)[(NSDictionary *)[levelSOSItems objectAtIndex: j] objectForKey: @"rescued_required"] intValue];

                    int k = 0;
                    while (k < [playerSOSItems count]) 
                    {
                        if ([(NSNumber *)[(NSDictionary *)[playerSOSItems objectAtIndex: k] objectForKey: @"sos_id"] intValue] == sosItemData.itemId)
                        {
                            sosItemData.qty = [(NSNumber *)[(NSDictionary *)[playerSOSItems objectAtIndex: k] objectForKey: @"qty"] intValue];
                            break;
                        }

                        k++;
                    }

                    //NSLog(@"%@", sosItemData);
                    [sosItems addObject: sosItemData];

                    j++;
                }

                groupData.sosItems = sosItems;


                [groupsList addObject: groupData];
            }

            NSLog(@"%@", data);
            [list addObject: data];

            i++;
        }

and here's the code I used to fetch the data from the database:

-(NSArray *) fetchDataFromDatabase:(NSString *)dbPath withQuery: (NSString *)sql withValuesAndTypes: (NSArray *)params

{ /* dbPath - Name of database file sql - SQL statement. Prepared statements are allowed to be used here (refer to params params - Array containing data and its corresponding data type */

NSMutableArray *result = nil;

//make sure db is closed
NSLog(@"close database first!");
sqlite3_close(database);

NSLog(@"open database!");
int dbStatus = [self openDatabase: dbPath];
if (dbStatus == SQLITE_OK) 
{
    //int stmtStatus = sqlite3_prepare_v2(database, [sql UTF8String], -1, &stmt, NULL);
    int stmtStatus = [self prepareStatement: sql withParams: params];
    if(stmtStatus == SQLITE_OK) 
    {
        result = [NSMutableArray arrayWithCapacity: 1];

        while(sqlite3_step(stmt) == SQLITE_ROW) 
        {
            NSMutableDictionary *row = [NSMutableDictionary dictionaryWithCapacity: 1];

            int columnCount = sqlite3_column_count(stmt);
            int j = 0;

            while (j < columnCount) 
            {
                /*
                 Possible sqlite data types:
                 SQLITE_INTEGER, SQLITE_FLOAT, SQLITE_TEXT, SQLITE_BLOB, SQLITE_NULL
                 */

                if (sqlite3_column_type(stmt, j) == SQLITE_INTEGER)
                {
                    [row setObject: [NSNumber numberWithInt: sqlite3_column_int(stmt, j)] 
                            forKey: [NSString stringWithUTF8String: sqlite3_column_name(stmt, j)]];
                }
                else if (sqlite3_column_type(stmt, j) == SQLITE_FLOAT)
                {
                    [row setObject: [NSNumber numberWithDouble: sqlite3_column_double(stmt, j)] 
                            forKey: [NSString stringWithUTF8String: sqlite3_column_name(stmt, j)]];
                }
                else if (sqlite3_column_type(stmt, j) == SQLITE_TEXT)
                {
                    [row setObject: [NSString stringWithFormat: @"%s", sqlite3_column_text(stmt, j)]  
                            forKey: [NSString stringWithUTF8String: sqlite3_column_name(stmt, j)]];
                }
                else if (sqlite3_column_type(stmt, j) == SQLITE_NULL)
                {
                    [row setObject: [NSNull null]   
                            forKey: [NSString stringWithUTF8String: sqlite3_column_name(stmt, j)]];
                }

                j++;
            }

            [result addObject: row];
        }
    }
    else { NSLog(@"stmt error: %d", stmtStatus); }
}
else if (dbStatus == 14) 
{
    NSLog(@"db error: %d", dbStatus);
    NSLog(@"killing app.");
    exit(0);
}
else { NSLog(@"db error: %d", dbStatus); }

//Even though the open call failed, close the database connection to release all the memory.
sqlite3_close(database); 

return result;

}

回答1:

sorry if it is wrong..... in your code you didn't finalize statement but useed stmt variable .before close DB ,we should finalize statement if we use statement.....

comment for finalize statement
sqlite3_finalize(Stmt);