我已经开发了一款企业iPad应用程序有一段时间了。自从近两年前开始应用程序开发,我就需要从源代码编译自己的SQLite版本,因为默认的SQLite库(sqlite3.dylib)没有默认启用FTS。
好的,自那时以来一切都很顺利。我一直在使用GCC作为项目编译器。
问题是现在我正在尝试将整个项目转换为使用ARC。为此,我需要使用苹果的LLVM编译器。
就这样。当我改变编译器(从GCC 4.2到LLVM 3.1或4.0,而不进行ARC转换,也不改变其他任何东西),我的应用程序构建良好,一切正常运行,除了我的FTS查询完全不起作用,即使最简单的查询也不行。它们始终运行并返回没有结果(虽然带有SQLITE_OK代码)。
我被困在这里。我已经在WWDC'12上与苹果工程师交谈过,但我们找不到任何解决方案。
我保证这不太可能是一个格式错误的查询或类似的问题,因为该应用程序在GCC下工作正常。此外,我能够在SQLite终端版本(或使用其他应用程序,如Base)上运行查询。
我之前使用的是旧版本的SQLite,但我已更新到最新版本(3.7.13)。一切都没有改变。我还注意到,现在(我不知道从什么时候开始),mac自带的sqlite支持FTS(!),我能够删除我的版本并使用Apple的版本。问题是,我遇到了完全相同的行为。
我一直在寻找解决方案,但找不到。我发现一些与armv6和编译器优化相关的错误(可以通过使用-mno-thumb标志进行修复),但这不是我的情况。我还注意到,当我使用Clang分析我的自定义sqlite文件时,它指出了许多“潜在错误”。
我持有这种不怀疑的观点,并且(仍然)不相信这是LLVM或SQLite的错误。在将其视为错误之前,我更喜欢检查所有可能性。也许我忘记配置某些东西或需要向编译器添加一些标志。
我很感激任何帮助。再次强调,这个bug仅出现在使用LLVM编译的项目中(即使使用默认的sqlite)。如果我在终端版本的sqlite3上运行相同的查询,一切都正常。
更新:
这段代码有效。它创建一个新的数据库,使用fts创建一个新的虚拟表,插入一些项,然后执行选择操作。稍后我将尝试更复杂的查询,但目前看来,我的应用程序问题可能是我代码中预期的一个bug。
好的,自那时以来一切都很顺利。我一直在使用GCC作为项目编译器。
问题是现在我正在尝试将整个项目转换为使用ARC。为此,我需要使用苹果的LLVM编译器。
就这样。当我改变编译器(从GCC 4.2到LLVM 3.1或4.0,而不进行ARC转换,也不改变其他任何东西),我的应用程序构建良好,一切正常运行,除了我的FTS查询完全不起作用,即使最简单的查询也不行。它们始终运行并返回没有结果(虽然带有SQLITE_OK代码)。
我被困在这里。我已经在WWDC'12上与苹果工程师交谈过,但我们找不到任何解决方案。
我保证这不太可能是一个格式错误的查询或类似的问题,因为该应用程序在GCC下工作正常。此外,我能够在SQLite终端版本(或使用其他应用程序,如Base)上运行查询。
我之前使用的是旧版本的SQLite,但我已更新到最新版本(3.7.13)。一切都没有改变。我还注意到,现在(我不知道从什么时候开始),mac自带的sqlite支持FTS(!),我能够删除我的版本并使用Apple的版本。问题是,我遇到了完全相同的行为。
我一直在寻找解决方案,但找不到。我发现一些与armv6和编译器优化相关的错误(可以通过使用-mno-thumb标志进行修复),但这不是我的情况。我还注意到,当我使用Clang分析我的自定义sqlite文件时,它指出了许多“潜在错误”。
我持有这种不怀疑的观点,并且(仍然)不相信这是LLVM或SQLite的错误。在将其视为错误之前,我更喜欢检查所有可能性。也许我忘记配置某些东西或需要向编译器添加一些标志。
我很感激任何帮助。再次强调,这个bug仅出现在使用LLVM编译的项目中(即使使用默认的sqlite)。如果我在终端版本的sqlite3上运行相同的查询,一切都正常。
更新:
这段代码有效。它创建一个新的数据库,使用fts创建一个新的虚拟表,插入一些项,然后执行选择操作。稍后我将尝试更复杂的查询,但目前看来,我的应用程序问题可能是我代码中预期的一个bug。
NSArray *dirPaths = dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [dirPaths objectAtIndex:0];
sqlite3 *database;
// Build the path to the database file
NSString *databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: @"test.db"]];
NSFileManager *filemgr = [NSFileManager defaultManager];
NSError *error = nil;
[filemgr removeItemAtPath:databasePath error:&error];
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
char *errMsg;
const char *sql_stmt = "CREATE VIRTUAL TABLE IF NOT EXISTS pages USING fts3(title, body);";
if (sqlite3_exec(database, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK)
{
NSLog(@"Failed to create table");
} else {
sql_stmt = "INSERT INTO pages(docid, title, body) VALUES(53, 'Home Page', 'SQLite is a software...');";
if (sqlite3_exec(database, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK)
{
NSLog(@"Failed to insert");
}
sql_stmt = "INSERT INTO pages(title, body) VALUES('Download', 'All SQLite source code...');";
if (sqlite3_exec(database, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK)
{
NSLog(@"Failed to insert");
}
}
sqlite3_stmt *statement;
const char *query_stmt = "select * from pages where body match 'soft*';";
if (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
NSLog(@"%@ - %@", [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)],
[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)]);
} else {
NSLog(@"no results");
}
sqlite3_finalize(statement);
}
sqlite3_close(database);
} else {
NSLog(@"Failed to open/create database");
}