Hatena::Groupiphone-dev

haoyayoi Dev Style このページをアンテナに追加 RSSフィード

2009-05-05

FMDatabaseの最小限度の流れ

| 15:05 | FMDatabaseの最小限度の流れ - haoyayoi Dev Style を含むブックマーク はてなブックマーク - FMDatabaseの最小限度の流れ - haoyayoi Dev Style FMDatabaseの最小限度の流れ - haoyayoi Dev Style のブックマークコメント

何度もEXC_BAD_ACCESS続きだったんですが、ようやく確立したので。

読み込み

	FMDatabase *db = [FMDatabase databaseWithPath:dbPath];
	if([db open]){
		NSLog(@"Error :: Cannot open DB");
		return;
	}
	[db beginTransaction];
        FMResultSet *res = [db executeQuery:@"SELECT * FROM ....", etc...];
        //any load from res
        [res close];
        [db close];

書込み

	FMDatabase *db = [FMDatabase databaseWithPath:dbPath];
	if([db open]){
		NSLog(@"Error :: Cannot open DB");
		return;
	}
	[db beginTransaction];
        [db executeUpdate:@"INSERT INTO *  ....", etc...];
        [res commit];
        [res close];
        [db close];

流れ

まずは、databaseWithPathでDBパスを指定してインスタンスの生成。その後、openにて確認を行い、beganTransactionにてトランザクションの開始。executeUpdateを用いた場合はcommitを忘れずに行う。これらが一個でも抜けたらEXC_BAD_ACCESSとなる具合です。その後、FMResultおよびFMDatabaseのcloseを実行。

ヘッダを見ても、正直何がどういったメソッドなのか分かりにくいため実装を読まざる得ない感じです。もうちょっと冗長気味なメソッド名にしてくれてもよさそうなものですが。

FMDataBaseのメソッドメモ

| 09:31 | FMDataBaseのメソッドメモ - haoyayoi Dev Style を含むブックマーク はてなブックマーク - FMDataBaseのメソッドメモ - haoyayoi Dev Style FMDataBaseのメソッドメモ - haoyayoi Dev Style のブックマークコメント

FMDataBaseを使っていて、発生するエラーの山がどうにも防げない。根本的な問題として、FMDataBaseのメソッドおよび使い方がリポジトリのあるwikiに書かれていないのも一因。

とりあえず少しづつ書いていくことにする。バージョンアップでまた差異がでてしまうかもしれないけど、それはそのとき。

+ (id)databaseWithPath:(NSString*)aPath

指定したDBパスでのFMDataBaseのインスタンスを返す。autoreleaseがかかってる。

- (id)initWithPath:(NSString*)aPath

指定したDBパスでのFMDataBaseのインスタンスを返す。

+ (NSString*) sqliteLibVersion

sqliteのバージョンを返す。

- (NSString *) databasePath

DBのパスを返す。

- (sqlite3*) sqliteHandle

sqlite3のハンドラを返す。

- (BOOL) open

DBが開いているかどうか返す。

- (void) close

DBを閉じる。ビジーであったり、sqlite3で閉じることに失敗した場合は何もしない。

- (void) clearCachedStatements

キャッシュされていたステートメントをすべてクリア。

- (FMStatement*) cachedStatementForQuery:(NSString*)query

指定のクエリのステートメントを返す。

- (void) setCachedStatement:(FMStatement*)statement forQuery:(NSString*)query

ステートメントを指定のクエリで保存する。

- (BOOL) rekey:(NSString*)key

- (BOOL) setKey:(NSString*)key

- (BOOL) goodConnection

接続を確認する。確認はtableのsqlite_master内のnameを選択する形で行う。

- (void) compainAboutInUse

DBが使用中であるかしらべる。エラーの場合はNSAssert1で通知。

- (NSString*) lastErrorMessage

SQliteの最新のエラーメッセージを返す。

- (BOOL) hadError

エラーを起こしていないか判定する。

- (int) lastErrorCode

SQLiteの最新のエラーコードを取得する。

- (sqlite_int64) lastInsertRowId

挿入した最新の行を取得。DB使用中の場合はエラー。

- (void) bindObject:(id)obj toColumn:(int)idx inStatement:(sqlite3_stmt*)pStmt;

- (id) executeQuery:(NSString *)sql arguments:(va_list)args

クエリを実行する。実行結果をFMResultで返す。

- (id) executeQuery:(NSString*)sql, ...

クエリを実行する。(id) executeQuery:(NSString *)sql arguments:(va_list)argsのラッパー

- (BOOL) executeUpdate:(NSString*)sql arguments:(va_list)args

クエリを実行する。実行結果を真偽値で返す。

- (BOOL) executeUpdate:(NSString*)sql, ...

クエリを実行する。(BOOL) executeUpdate:(NSString*)sql arguments:(va_list)argsのラッパー

- (BOOL) rollback

ロールバックする。

- (BOOL) commit

トランザクションをコミットする。

- (BOOL) beginDeferredTransaction

トランザクションを開始する。最初にDBにアクセスした時点でロックする。トランザクションとロックが同時ではない。

- (BOOL) beginTransaction

トランザクションを開始する。同時にロックもかける。

- (BOOL)logsErrors

ログエラーの設定を返す。

- (void)setLogsErrors:(BOOL)flag

ログエラーを設定する

- (BOOL)crashOnErrors

エラー時のクラッシュ設定を返す。

- (void)setCrashOnErrors:(BOOL)flag

エラー時のクラッシュ指定を設定する。

- (BOOL)inUse

使用中かどうかの設定を返す。

- (void) setInUse:(BOOL)b

使用中にする。

- (BOOL)inTransaction

トランザクション判定を返す。

- (void)setInTransaction:(BOOL)flag

トランザクション中にする。

- (BOOL)traceExecution

実行クエリをログに書き出す設定を返す。

- (void)setTraceExecution:(BOOL)flag

実行クエリをログに書き出す指定を行う。YESの場合、executeQueryなどで実行されたクエリがNSLogで書き出されるようになる。

2009-05-03

FMDatabaseを使ったSQLite クエリにおけるFormatter文字

| 10:26 | FMDatabaseを使ったSQLite クエリにおけるFormatter文字 - haoyayoi Dev Style を含むブックマーク はてなブックマーク - FMDatabaseを使ったSQLite クエリにおけるFormatter文字 - haoyayoi Dev Style FMDatabaseを使ったSQLite クエリにおけるFormatter文字 - haoyayoi Dev Style のブックマークコメント

FMDatabaseを使ってqueryを延々と書いてて少々はまったのでメモ。

わりとSQLiteをプロジェクト内にもちこむ方法と、そこからDocumentsへのコピーあたりまでは資料充実してるわけですが、そこから先になると割と書いてる人いなくて、とりあえず勝手に皆挫折したものだと思う事にしました。

queryに用いるformatter

NSStringには幾つかformatとして用いる文字列があるわけですが、このformat用文字をqueryに用いると想定外なエスケープがなされて泣きめをみます。'test'が\'test\'になったりして。

ここらへんをクリアしているアプリは何かないものかと思い、twitterクライアントあたりでsqliteを使っていて、かつオープンソースであるものを探した結果、twitter fonがありました。

TwitterFon - github

ソースを読んだ結果、対処方法は分かりました。

 [[FMDatabase databaseWithPath:dbPath] executeUpdate:@"REPLACE INTO users VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)"];

最初は何かが文字化けして?(はてな)になってるのかなと思ったんですが、文字通り?(はてな)がformatterになっています。FMDatabase内部では、このquery処理のためにGCCのビルトイン関数を用いているようで、この辺りの処理についてはそもそもSDKドキュメントに含まれるはずもない、という様子。なおNSStringで?をFormatterにあてがっても、代入されずに?として処理されます。

SQLiteのformatter

SQlite3.0のAPIドキュメントを見てみたところ、?がSQLiteの代入子にあたる、ということで。他の言語では文字連結でクエリを作ってたものだから、存在そのものを初めて知りました。

2009-05-02

SQLiteの仕込みのために

| 17:07 | SQLiteの仕込みのために - haoyayoi Dev Style を含むブックマーク はてなブックマーク - SQLiteの仕込みのために - haoyayoi Dev Style SQLiteの仕込みのために - haoyayoi Dev Style のブックマークコメント

ちょっとしたデータならplistもいいわけですが、それなりの量になるようであればsqliteのほうが多分早いです。

sqliteを使うために必要なコーディングを行っていたのですが、わりと必要な下準備がある事にきがつき、それならある程度をテンプレみたいな具合でクラス化したほうが良いだろうと思い、書いてみました。依存もへったくれもないので気軽に使えると思います。

SqliteInitialize

Resourcesの中に該当DBファイルをいれておき、あとはcopyDBを使うくらい。copyDBで失敗した場合はNOが帰ってきます。