私はしばらくの間エンタープライズiPadアプリを開発してきました。アプリの開発はほぼ2年前に開始されたため、デフォルトのSQLiteライブラリ(sqlite3.dylib)ではデフォルトでFTSが有効になっていないため、ソースから独自のバージョンのSQLiteをコンパイルする必要がありました。
それ以来、すべてが正常に機能していました。私は常にGCCをプロジェクトコンパイラとして使用してきました。
問題は、プロジェクト全体をARCを使用するように変換しようとしているということです。そのためには、AppleのLLVMコンパイラを使用する必要があります。
それでおしまい。コンパイラを変更すると(GCC4.2からLLVM3.1または4.0に、ARCに変換せずに、他に何も変更せずに)、アプリは正常にビルドされ、FTSクエリを除いて、すべてが正常に実行されます。最も単純なもの。それらは実行され、常に結果なしで返されます(ただし、SQLITE_OKコードを使用します)。
私はここで立ち往生しています。私はすでにWWDC'12でAppleのエンジニアと話をしましたが、解決策が見つかりませんでした。
アプリはGCCで正常に動作しているため、不正な形式のクエリなどである可能性は低いと保証します。また、ターミナルバージョンのSQLiteで(またはBaseなどの他のアプリを使用して)クエリを実行することもできます
古いバージョンのSQLiteも使用していましたが、最新バージョン(3.7.13)に更新しました。すべてが同じままです。また、Macに付属のsqliteがFTS(!!!)をサポートし、自分のバージョンを削除してAppleのバージョンを使用できるようになったことに気づきました(いつからかはわかりません)。問題は、私はまったく同じ振る舞いをしているということです。
解決策を探していましたが、見つかりませんでした。armv6とコンパイラの最適化(-mno-thumbフラグを使用して修正できます)に関連するバグをいくつか見つけましたが、私の場合はそうではありません。また、Clangを使用してカスタムsqliteファイルを分析すると、多くの「潜在的なエラー」が指摘されていることに気付きました。
私はこの懐疑的な見方をしていませんが、それがLLVMまたはSQLiteのバグであるとは(まだ)信じていません。バグに対処する前に、可能な限りすべてをチェックすることを好みます。何かを構成するのを忘れているか、実行していないフラグをコンパイラーに追加する必要があるかもしれません。
助けていただければ幸いです。繰り返しになりますが、このバグはLLVMでコンパイルされたプロジェクトでのみ発生します(デフォルトのsqliteを使用している場合でも)。sqlite3のターミナルバージョンで同じクエリを実行すると、すべてうまくいきます。
アップデート:
このコードは機能します。新しいデータベース、ftsを使用した新しい仮想テーブルを作成し、いくつかの項目を挿入してから、選択を実行します。後でもっと複雑なクエリを試しますが、今のところ、アプリの問題は、予想どおり、コードのバグである可能性があります。
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");
}