フリープログラミング for windows.

MinGW(gcc)でFirebirdを使ってみる(3)

今回は、InterBase APIを使用してFirebirdデータベースに問い合わせ型SQL文を実行します。

問い合わせ型SQL文の実行

入力パラメータのある問い合わせ型SQL文の実行

前回は非問い合わせ型SQL文の発行をとりあげましたが、今回は問い合わせ型SQL文について記載していきます。 入力パラメータのないものは、前回を参照していただければと思います。

入力パラメータのためのコードは非問い合わせ型SQL文の場合と同じです。 今度は問い合わせを行いますので、その結果セットを受け取れるようにします。結果セットも入力パラメータと同様に XSQLDA構造体を使用します。

まず、XSQLDA構造体をローカルで定義し、sqlnを1とにします。 次にisc_dsql_prepare()のパラメータにXSQLDA構造体を指定しています。 isc_dsql_prepare()はSQL文が何個のカラムを返すかをsqldに設定します。 次に、sqldを指定してXSQLDA構造体を確保し、sqlnに最初に取得したsqldを設定します。 確保したXSQLDA構造体を指定してisc_dsql_describe()を呼び出します。

if (isc_start_transaction(status, &hTrn, 1, &hDb, 0, NULL)) {
	cerr << "Failed to start transaction. status=" 
	     << isc_sqlcode(status) << endl;
	return 1;
}

char* sql = "SELECT * FROM sample1 WHERE ITEM1 = ?";

XSQLDA* inDa = (XSQLDA*)new char[XSQLDA_LENGTH(1)];
inDa->version = SQLDA_VERSION1;
inDa->sqln = 1;

XSQLDA paraDa;
paraDa.version = SQLDA_VERSION1;
paraDa.sqln = 1;

if (isc_dsql_allocate_statement(status, &hDb, &hStmt)) {
	cerr << "Failed to allocate statement. status=" 
	     << isc_sqlcode(status) << endl;
	return 1;
}
if (isc_dsql_prepare(status, &hTrn, &hStmt, 0, sql, 1, &paraDa)) {
	cerr << "Failed to prepare statement. status=" 
	     << isc_sqlcode(status) << endl;
	return 1;
}
if (isc_dsql_describe_bind(status, &hStmt, 1, inDa)) {
	cerr << "Failed to describe bind. status=" 
	     << isc_sqlcode(status) << endl;
	return 1;
}
if (inDa->sqld > inDa->sqln) {
	short sqld = inDa->sqld;
	delete [] inDa;
	inDa = (XSQLDA*)new char[XSQLDA_LENGTH(sqld)];
	inDa->sqln = sqld;
	inDa->version = SQLDA_VERSION1;
	if (isc_dsql_describe_bind(status, &hStmt, 1, inDa)) {
		cerr << "Failed to describe bind. status=" 
		     << isc_sqlcode(status) << endl;
		return 1;
	}
}
XSQLVAR *var;
int i;
for (i = 0, var = inDa->sqlvar; i < inDa->sqld; i++, var++) {
	switch (var->sqltype & ~1) {
	case SQL_VARYING:
		var->sqldata = (char *)new char[var->sqllen + 2];
		break;
	default:
		var->sqldata = (char *)new char[var->sqllen];
		break;
	}
	if (var->sqltype & 1) {
		var->sqlind = (short *)new short;
		*(var->sqlind) = 0;
	}
}

var = inDa->sqlvar;
*(short*)(var->sqldata) = 2;

XSQLDA* outDa = (XSQLDA*)new char[XSQLDA_LENGTH(paraDa.sqld)];
outDa->version = SQLDA_VERSION1;
outDa->sqln = paraDa.sqld;

if (isc_dsql_describe(status, &hStmt, 1, outDa)) {
	cerr << "Failed to describe. status=" 
	     << isc_sqlcode(status) << endl;
	return 1;
}

ここで、お気づきかと思いますが、入力パラメータのためのXSQLDA構造体は最初に適当に割り当てた後に、isc_dsql_describe_bind() を呼び出し、正確なsqldを指定して、XSQLDA構造体を再割り当てしisc_dsql_describe_bind()を再度呼び出しました。

出力用のXSQLDA構造体も同様にすることができます。 この場合はisc_dsql_prepare()には出力用のXSQLDA構造体を指定する必要はありません。 isc_dsql_describe()も呼び出されるとsqldを正確な値で再設定します。

(ここでは値の設定部分以外は、SQL文がわからなくても利用可能なコードとしていますが、 明示的に分かっている場合は、固定で設定できます)

値を格納するエリアを確保し、上記で確保したXSQLDA構造体に設定します。

for (i = 0, var = outDa->sqlvar; i < outDa->sqld; i++, var++) {
	switch (var->sqltype & ~1) {
	case SQL_VARYING:
		var->sqldata = (char *)new char[var->sqllen + 2];
		break;
	default:
		var->sqldata = (char *)new char[var->sqllen];
		break;
	}
	if (var->sqltype & 1) {
		var->sqlind = (short *)new short;
	}
}

isc_dsql_execute()でSQL文を実行します。

if (isc_dsql_execute(status, &hTrn, &hStmt, 1, inDa)) {
	cerr << "Failed to execute statement. status=" 
	     << isc_sqlcode(status) << endl;
	return 1;
}

結果セットを取り出すため、isc_dsql_fetch()を呼び出します。isc_dsql_fetch()は問い合わせした結果を 1件づつ上記で確保した出力用のエリアに値を格納します。返す結果がなくなった時は100を返します。 後はタイプに従って値をとりだすことができます。例では標準出力に値をプリントしています。

int w_len;
string w_str;
int w_row = 0;
long fetch_stat;
while ((fetch_stat = isc_dsql_fetch(status, &hStmt, 1, outDa)) == 0) {
	cout << "== Row Index: " << w_row++ << "============" << endl;
	for (i = 0, var = outDa->sqlvar; i < outDa->sqld; i++, var++) {
		cout << "   Column Index: " << i << endl;
		switch (var->sqltype & ~1) {
		case SQL_VARYING:
			cout << "     type: SQL_VARYING:" 
			     << var->sqltype << endl;
			if ((var->sqltype & 1) && (*(var->sqlind) == -1)) {
				cout << "   data: NULL" << endl;
			} else {
				w_len = *(short*)var->sqldata;
				w_str.assign(var->sqldata + 2, w_len);
				cout << "     data: " << w_str << endl;
			}
			break;
		case SQL_TEXT:
			cout << "     type: SQL_TEXT:" 
			     << var->sqltype << endl;
			if ((var->sqltype & 1) && (*(var->sqlind) == -1)) {
				cout << "     data: NULL" << endl;
			} else {
				w_len = var->sqllen;
				w_str.assign(var->sqldata, w_len);
				cout << "     data: " << w_str << endl;
			}
			break;
		case SQL_LONG:
			cout << "     type: SQL_LONG:" 
			     << var->sqltype << endl;
			if ((var->sqltype & 1) && (*(var->sqlind) == -1)) {
				cout << "     data: NULL" << endl;
			} else {
				cout << "     data: " 
				     << *(long*)var->sqldata << endl;
			}
			break;
		case SQL_SHORT:
			cout << "     type: SQL_SHORT:" 
			     << var->sqltype << endl;
			if ((var->sqltype & 1) && (*(var->sqlind) == -1)) {
				cout << "     data: NULL" << endl;
			} else {
				cout << "     data: " 
				     << *(short*)var->sqldata << endl;
			}
			break;
		default:
			cout << "     type: " << var->sqltype << endl;
			cout << "     data: Not implement." << endl;
			break;
		}
	}
}
if (fetch_stat != 100L) {
	cerr << "Failed to fetch. status="
	     << isc_sqlcode(status) << endl;
	return 1;
}
if (isc_commit_transaction(status, &hTrn)) {
	cerr << "Failed to commit transaction. status=" 
	     << isc_sqlcode(status) << endl;
	return 1;
}

ソースコードの例:sample4.cpp (エラーリターン時の後処理等はしていませんのでご注意願います。)

サンプルプログラムの実行

上記サンプルを実行した場合の出力結果が以下です。 ITME1が 2の行が2件あった時の出力例となります。

== Row Index: 0============
   Column Index: 0
     type: SQL_SHORT:501
     data: 2
   Column Index: 1
     type: SQL_TEXT:453
     data: val 
== Row Index: 1============
   Column Index: 0
     type: SQL_SHORT:501
     data: 2
   Column Index: 1
     type: SQL_TEXT:453
     data: val 

ソフトウエア製品

やっぱり、製品版でないとなにかと不自由な面も多いのは確かです。Windowsプログラミングするなら...

■ Visual Studio 2008

検出率、アップデート頻度、軽さ等、好評のセキュリティソフト...

■ カスペルスキー

格安レンタルサーバ

月額1000円以下で利用できるレンタルサーバです。

■ ロリポップ!
■ チカッパ!
■ さくらインターネット
■ TOK2 PROFESSIONAL
■ Bfit.jp

ネットバンク

金利の高さと、手数料の安さからネットバンクはたいへんお得です。

■ ジャパンネット銀行
■ イーバンク銀行

アフィリエイト

ブログ、ホームページを持っているなら、アフィリエイトで広告収入を得られます。

■ A8.net
■ リンクシェア
■ JANet

パソコン・周辺機器

インターネットだけのサービスやアウトレット、思わぬ掘り出し物があるので、こまめにチェックしたいものです。

メーカ直販系
□ パソコン本体
■ デルオンラインストア
■ エプソンダイレクト
■ ソニースタイル
■ Apple Store
■ 富士通直販サイト WEB MART
■ NEC「得選街」
■ レノボ・ジャパン株式会社
■ マウスコンピューター
□ 周辺機器
■ ioPLAZA
ショップ系
■ ジョーシン
■ パソコン専門店PCDEPOT WEB本店


Apple Store(Japan)
Copyright(C) 2005 freepg-lab. All rights reserved.
SEO [PR] 爆速!無料ブログ 無料ホームページ開設 無料ライブ放送