不执行任何查询SQLite

时间:2014-08-24 22:45:58

标签: ios objective-c sqlite

所以我创建了一个连接到SQLite数据库的NSObject,一切都运行良好。在我的代码中,如果查询是可执行的,则代码会经历一系列条件并执行查询。然后,无缘无故,我没有做任何事情,可执行查询停止工作。我尝试删除db文件并再次将其复制(我确保检查所有复选框),但所有发生的事情是project.pbxproj突然出现在我的所有文件中,Xcode仍然无法执行我的可执行查询。我将project.pbxproj放回到项目文件中,并在没有运气的情况下继续从项目中删除/重新复制db文件。 这是我的代码,我知道它非常好,因为我没有改变任何内容并且它正在工作:

-(void)runQuery:(const char *)query isQueryExecutable:(BOOL)queryExecutable{
    // Create a sqlite object.
    sqlite3 *sqlite3Database;

    // Set the database file path.
    NSString *databasePath = [self.documentsDirectory stringByAppendingPathComponent:self.databaseFilename];

    // Initialize the results array.
    if (self.arrResults != nil) {
        [self.arrResults removeAllObjects];
        self.arrResults = nil;
    }
    self.arrResults = [[NSMutableArray alloc] init];

    // Initialize the column names array.
    if (self.arrColumnNames != nil) {
        [self.arrColumnNames removeAllObjects];
        self.arrColumnNames = nil;
    }
    self.arrColumnNames = [[NSMutableArray alloc] init];


    // Open the database.
    BOOL openDatabaseResult = sqlite3_open([databasePath UTF8String], &sqlite3Database);
    if(openDatabaseResult == SQLITE_OK) {
        // Declare a sqlite3_stmt object in which will be stored the query after having been compiled into a SQLite statement.
        sqlite3_stmt *compiledStatement;

        // Load all data from database to memory.
        BOOL prepareStatementResult = sqlite3_prepare_v2(sqlite3Database, query, -1, &compiledStatement, NULL);
        if(prepareStatementResult == SQLITE_OK) {
            // Check if the query is non-executable.
            if (!queryExecutable){
                // In this case data must be loaded from the database.

                // Declare an array to keep the data for each fetched row.
                NSMutableArray *arrDataRow;

                // Loop through the results and add them to the results array row by row.
                while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
                    // Initialize the mutable array that will contain the data of a fetched row.
                    arrDataRow = [[NSMutableArray alloc] init];

                    // Get the total number of columns.
                    int totalColumns = sqlite3_column_count(compiledStatement);

                    // Go through all columns and fetch each column data.
                    for (int i=0; i<totalColumns; i++){
                        // Convert the column data to text (characters).
                        char *dbDataAsChars = (char *)sqlite3_column_text(compiledStatement, i);

                        // If there are contents in the currenct column (field) then add them to the current row array.
                        if (dbDataAsChars != NULL) {
                            // Convert the characters to string.
                            [arrDataRow addObject:[NSString  stringWithUTF8String:dbDataAsChars]];
                        }

                        // Keep the current column name.
                        if (self.arrColumnNames.count != totalColumns) {
                            dbDataAsChars = (char *)sqlite3_column_name(compiledStatement, i);
                            [self.arrColumnNames addObject:[NSString stringWithUTF8String:dbDataAsChars]];
                        }
                    }

                    // Store each fetched data row in the results array, but first check if there is actually data.
                    if (arrDataRow.count > 0) {
                        [self.arrResults addObject:arrDataRow];
                    }
                }
            }
            else {
                // This is the case of an executable query (insert, update, ...).

                // Execute the query.
                BOOL executeQueryResults = sqlite3_step(compiledStatement);
                if (executeQueryResults == SQLITE_DONE) {
                    // Keep the affected rows.
                    self.affectedRows = sqlite3_changes(sqlite3Database);

                    // Keep the last inserted row ID.
                    self.lastInsertedRowID = sqlite3_last_insert_rowid(sqlite3Database);
                }else if(executeQueryResults == SQLITE_BUSY){
                    NSLog(@"busy");
                }else if(executeQueryResults == SQLITE_ERROR){
                    NSLog(@"error in exec");
                }else if(executeQueryResults == SQLITE_MISUSE){
                    NSLog(@"misuse");
                }else if(executeQueryResults == SQLITE_ROW){
                    NSLog(@"row");
                }
                else {
                    // If could not execute the query show the error message on the debugger.
                    NSLog(@"DB Error: %s", sqlite3_errmsg(sqlite3Database));
                }
            }
        }
        else {
            // In the database cannot be opened then show the error message on the debugger.
            NSLog(@"%s", sqlite3_errmsg(sqlite3Database));
        }

        // Release the compiled statement from memory.
        sqlite3_finalize(compiledStatement);

    }

    // Close the database.
    sqlite3_close(sqlite3Database);
}

我创建了所有条件来检查出现了什么样的问题,结果是executeQueryResults等于SQLITE_ERROR,错误是:unkown error。 此外,我尝试记录数组,它们是空的或等于null,即使数据库不是空的开始。 此外,我在比较executeQueryResults与SQLITE_DONE / BUSY / ERROR等所有行的错误(仅在此项目中)说:语义问题:常量101与类型&#39; BOOL&#39;的表达式的比较。 (又名&#39; bool&#39;)总是假的。 在具有完全相同代码的其他项目中,不会出现此错误。

Screenshot for warning

1 个答案:

答案 0 :(得分:4)

问题是你在布尔变量中持有SQLite调用的返回值。您应该将这些变量更改为int,与sqlite3_xxx()函数调用返回的类型相同。

线索是您在修订后的问题中提供的错误消息:

  

常量101与'BOOL'(又名'bool')表达式的比较总是错误的。

为64位目标构建时,BOOL被定义为bool类型。 bool类型将采用任何非零值并将其更改为1。但是,对于非64位目标,BOOL被定义为signed char(它不会将非零值映射到1),这就是为什么你的代码工作时的原因编译针对某些目标,但不针对其他目标。

因此,当sqlite_step返回成功的SQLITE_DONE(非零值)时,对于64位目标,BOOL表示为bool,并且有意义的返回代码被替换为1(等同于SQLITE_ERROR)。随后对sqlite3_errmsg的调用变得混乱,因为实际上没有发生SQLite错误。

如果您将这些BOOL引用替换为int(无论如何应该这样做),代码应该可以正常工作。