激凹みから立ち直る方法

SQLiteを使ったメールソフトを作っています。

sqliteの構造体
sqlite3_stmt
の宣言は見つかるのですが
構造体の内容の定義してあるものが見つかりません。
sqlite3.h, sqlite3.c
を探したのですが見つかりませんでした。
 この構造体が見つからないと
そこに登録してある値が使えません。

それとも、
この構造体は定義されていなくて
これを当てにしないで
プログラムを組まなくてはいけないのでしょうか?
使わなくても動かせそうですか。。。

お分かりの方、よろしくお願いします。

A 回答 (5件)

sqlite3_column_ で始まっているルーチン郡は、クエリーの結果セットに関する情報を取り出すのに使います。


って書いてるけど。。
http://hp.vector.co.jp/authors/VA002803/sqlite/c …

だから、書き込みの時に使っても意味なくて、下記のように使うのでは?

sqlite3_prepare(db, "select * from blobtest;", -1, &plineInfo, NULL);
while(sqlite3_step(plineInfo) == SQLITE_ROW) {
 int N = sqlite3_column_count(plineInfo);
 printf("N=%d\n", N);
}
参考:http://blogs.wankuma.com/episteme/articles/56144 …

この回答への補足

動きました。参考にしたeatblob.cを以下のように修正したら
予定通りに動きました。
ありがとうございました。

int main(int argc, char **argv){
sqlite3 *db;
char *zErrMsg = 0;
char sqtext[256];
int rc;
sqlite3_stmt *plineInfo = 0;
char *line = NULL;
FILE * fp;
int n;
long buflen = 0, totread = 0;
char *buf = NULL, *pbuf = NULL;

rc = sqlite3_open("image.db", &db);
if( rc ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
exit(1);
}

rc = sqlite3_exec(db, "create table blobtest (des varchar(80), blen INTEGER, b blob);", callback, 0, &zErrMsg);

if( rc!=SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}

if ((fp = fopen("sample.jpg", "rb"))==NULL ) {
fprintf(stderr, "Can't open data: %s\n", "sample.jpg");
return 1;
}
while (buflen - totread - 1 < 1024)
buflen = addmem(&buf, buflen);
pbuf = buf;
totread = 0;
while ((n = fread(pbuf, sizeof(char), 1024, fp)) > 0) {
totread += n;
pbuf[n] = '\0';// This is for printing test
while (buflen - totread - 1 < 1024)
buflen = addmem(&buf, buflen);
pbuf = &buf[totread];
}
fclose(fp);

sprintf(sqtext,"insert into blobtest (des,blen,b) values ('A test file: sample.jpg', %d, ?);", totread);

rc = sqlite3_prepare(db,sqtext , -1, &plineInfo, 0);

if (rc == SQLITE_OK && plineInfo != NULL) {
printf( "SQLITE_OK\n");
sqlite3_bind_blob(plineInfo, 1, buf, totread, free);


while ((rc = sqlite3_step(plineInfo)) == SQLITE_ROW) {
}
rc = sqlite3_finalize(plineInfo);
}
printf("eatblob:%d> ", sqlite3_total_changes(db));

rc = sqlite3_prepare(db, "select * from blobtest;", -1, &plineInfo, 0);
while ((rc = sqlite3_step(plineInfo)) == SQLITE_ROW) {
for (int i = 0; i < sqlite3_column_count(plineInfo); ++i){
print_col(plineInfo, i);
}
printf("\n");
}
rc = sqlite3_finalize(plineInfo);

rc = sqlite3_exec(db, "select * from blobtest;", callback, 0, &zErrMsg);

if( rc!=SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}

sqlite3_close(db);

return 0;
}

補足日時:2008/02/20 18:55
    • good
    • 0

テーブルの定義と現在の状態が不明のためあてずっぽうになってしまいますが、



> insert into blobtest (des,blen,b) values ('A test file: sample.jpg', %d, ?);

が失敗している可能性はないですか?
desやblenがユニーク指定されているカラムだと、二回目以降はインサートに失敗してDBに対して影響を与えなかった為、sqlite3_column_countが0を返すことがあると思います。

この回答への補足

お世話になっています。

開発は、
OS Win2000
コンパイラ VC++2005 VC++6.0の二つ
sqlite3.c
を修正して、うえのコンパイラの統合環境で
動くようにしました。(sqlite2.cppと名前をつけました)
1回目で動くかどうか
デバッガで確認してみます。
 データベースを削除してから
動かせばよろしいでしょうか?

補足日時:2008/02/19 18:16
    • good
    • 0

ん~。

SQLiteを使ったプログラミングの話にシフトしてしまったので、
これからは知っている人の回答に期待、ですが、
提示されたコードだけでは、情報が少なすぎるのではないかと直感的に思います。
開発環境と、下記のコードの補足をお願いします。

・データベースの作成(オープン)
・テーブルの作成
・レコードの追加

こちらで時々ご回答されている、epistemeさんの記事が参考になるでしょうか。
http://codezine.jp/a/article/aid/1252.aspx?p=2

この回答への補足

int main(int argc, char **argv){
sqlite3 *db;
char *zErrMsg = 0;
char sqtext[256];
int rc;
sqlite3_stmt *plineInfo = 0;
char *line = NULL;
FILE * fp;
int n;
long buflen = 0, totread = 0;
char *buf = NULL, *pbuf = NULL;

rc = sqlite3_open("image.db", &db);
if( rc ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
exit(1);
}

rc = sqlite3_exec(db, "create table blobtest (des varchar(80), blen INTEGER, b blob);", callback, 0, &zErrMsg);

if( rc!=SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}

if ((fp = fopen("sample.jpg", "rb"))==NULL ) {
fprintf(stderr, "Can't open data: %s\n", "sample.jpg");
return 1;
}
while (buflen - totread - 1 < 1024)
buflen = addmem(&buf, buflen);
pbuf = buf;
totread = 0;
while ((n = fread(pbuf, sizeof(char), 1024, fp)) > 0) {
totread += n;
pbuf[n] = '\0';// This is for printing test
while (buflen - totread - 1 < 1024)
buflen = addmem(&buf, buflen);
pbuf = &buf[totread];
}
fclose(fp);

sprintf(sqtext,"insert into blobtest (des,blen,b) values ('A test file: sample.jpg', %d, ?);", totread);

rc = sqlite3_prepare(db,sqtext , -1, &plineInfo, 0);

if (rc == SQLITE_OK && plineInfo != NULL) {
printf( "SQLITE_OK\n");
sqlite3_bind_blob(plineInfo, 1, buf, totread, free);

while ((rc = sqlite3_step(plineInfo)) == SQLITE_ROW) {
for (int i = 0; i < sqlite3_column_count(plineInfo); ++i){
//ここに入らない。
print_col(plineInfo, i);
}
printf("\n");
}
rc = sqlite3_finalize(plineInfo);
}
printf("eatblob:%d> ", sqlite3_total_changes(db));

rc = sqlite3_exec(db, "select * from blobtest;", callback, 0, &zErrMsg);

if( rc!=SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}

sqlite3_close(db);

return 0;
}

補足日時:2008/02/19 18:14
    • good
    • 0
この回答へのお礼

ありがとうございます。
教えていただいたURLのサンプルと

sqlite3.c を修正して、vc++2005の統合環境で
動くようにした sqlite2.cppを組み合わせたら、
サンプルは正常に動きました。

それと、画像データは
複数回格納できます。
 また、plineInfoからの
情報は取り出せないんですが、
代わりの情報(サイズ、名前)をデータベースに登録しておくと
データベースから画像ファイルを取り出せます。
 列数は固定でもかまわないので
使えることは使えるのですが
BLOBデータの場合は面倒です。

ほかに、お気づきの点がありましたらよろしくお願いします。

お礼日時:2008/02/20 00:02

肝心の質問に答えていませんでした。



> これを当てにしないで
> プログラムを組まなくてはいけないのでしょうか?
> 使わなくても動かせそうですか。。。

はい、構造体の実フィールドは何か、ということは当てにせず、
http://www.sqlite.org/c3ref/stmt.html
に書いてあるような、アクセス関数を操作すれば動かせそうです。
(変数の中身は何かしら、更新されるはず)。
実際にやってみたことがないので、恐縮ですが。

>この構造体が見つからないとそこに登録してある値が使えません。

この構造体を引数にして、必要な情報を返すアクセス関数を
探してみると良いかもしれません。

この回答への補足

sprintf(sqtext,"insert into blobtest (des,blen,b) values ('A test file: sample.jpg', %d, ?);", totread);
rc = sqlite3_prepare(db,sqtext , -1, &plineInfo, 0);
//ここで値が入るのが当然と思うが入らないのです。
if (rc == SQLITE_OK && plineInfo != NULL) {
printf( "SQLITE_OK\n");
sqlite3_bind_blob(plineInfo, 1, buf, totread, free);
while ((rc = sqlite3_step(plineInfo)) == SQLITE_ROW) {
for (int i = 0; i < sqlite3_column_count(plineInfo); ++i){
print_col(plineInfo, i);
}
printf("\n");
}
rc = sqlite3_finalize(plineInfo);
}
としても、
sqlite3_column_count(plineInfo);
は、0を返します。
構造体の中身は変化しないのです。

補足日時:2008/02/18 19:52
    • good
    • 0

お分かりでないので恐縮ですが、ちょっとgoogleで探してみました。


sqlite3_stmtの実体は隠蔽されていて(いわゆるオブジェクト)
その実体にアクセスするために、以下のようなアクセス関数が
提供されているということではないでしょうか。
int sqlite3_prepare(sqlite3*, const char*, int, sqlite3_stmt**, const char**);
int sqlite3_prepare16(sqlite3*, const void*, int, sqlite3_stmt**, const void**);
int sqlite3_finalize(sqlite3_stmt*);
int sqlite3_reset(sqlite3_stmt*);

バグの混入を防ぐ為に、sqlite3_stmtの内部構造は、直接ユーザーは
知りえない状態にしているように思います。
(いわゆるカプセル化)
外してたらすいません。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報