2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

PostgreSQLでSQL実行するECPGプログラムの簡単な例

Posted at

PostgreSQLに対して以下のDB操作・SQL実行を行うECPGの簡単なプログラム例を示します。

  • ローカルで稼働中のPostgreSQLに対して、DBユーザtestuserでデータベースtestdbに接続する。
  • (もし未作成であれば) テーブルtesttblを作成する。テーブルtesttblは、主キーであるinteger型の1カラムnumだけを持つ。
  • プログラムの引数で指定された整数値をテーブルtesttblにINSERTする。
  • テーブルtesttblの全レコードについて、numカラムでソートした結果を順番に標準出力に出力する。
  • SQL実行がエラーになった場合は、エラーの理由とSQLをエラーメッセージとして標準エラー出力に出力する。

これらを実現するECPGプログラムの簡単な例は下記です。

test.pgc
#include <stdio.h>
#include <stdlib.h>

/*
 * SQL実行でエラーが発生したら、エラー処理のための関数として
 * elog()を呼び出すようにグローバルに宣言する。
 */
static void elog(void);
EXEC SQL WHENEVER SQLERROR CALL elog();

/*
 * 現在実行中または直前に実行済のSQL文字列を保存する
 * グローバル変数sqlを宣言する。
 */
EXEC SQL BEGIN DECLARE SECTION;
char *sql;
EXEC SQL END DECLARE SECTION;

/*
 * このプログラムのメイン関数。
 * テーブルtesttblにINSERTするレコードの整数値を第1引数で指定できる。
 */
int
main(int argc, char *argv[])
{
	/*
	 * ECPGで使うローカル変数を宣言する。
	 */
	EXEC SQL BEGIN DECLARE SECTION;
	const char *target = "testdb@localhost:5432";
	const char *user = "testuser";
	int num = 0;
	int res = 0;
	EXEC SQL END DECLARE SECTION;

	/*
	 * 第1引数が指定された場合は、引数の整数値をINSERTする。
	 */
	if (argc > 1)
		num = atoi(argv[1]);

	/*
	 * ローカル内で稼働中のPostgreSQLに対して、DBユーザtestuserで
	 * データベースtestdbに接続する。
	 */
	EXEC SQL CONNECT TO :target USER :user;

	/*
	 * もし未作成であれば、テーブルtesttblを作成する。
	 */
	sql = "CREATE TABLE IF NOT EXISTS testtbl (num integer primary key)";
	EXEC SQL EXECUTE IMMEDIATE :sql;

	/*
	 * 動的SQLを使って、テーブルtesttblにレコードを1件INSERTする。
	 */
	sql = "INSERT INTO testtbl VALUES (?)";
	EXEC SQL PREPARE teststmt FROM :sql;
	EXEC SQL EXECUTE teststmt USING :num;

	/*
	 * テーブルtesttblの全レコードを表示するために、全レコードを取得する
	 * SQLに対してカーソルを定義する。
	 */
	sql = "SELECT num FROM testtbl ORDER BY num";
	EXEC SQL PREPARE teststmt FROM :sql;
	EXEC SQL DECLARE testcur CURSOR FOR teststmt;
	EXEC SQL OPEN testcur;

	/*
	 * カーソルからレコードを1件ずつ取得して標準出力する。
	 * 全レコードを取得したらwhile()ループから抜けられるように
	 * 一時的に宣言する。
	 */
	EXEC SQL WHENEVER NOT FOUND DO BREAK;
	while (1)
	{
		EXEC SQL FETCH testcur INTO :res;
		printf("%d\n", res);
	}
	EXEC SQL WHENEVER NOT FOUND CONTINUE;
	EXEC SQL CLOSE testcur;

	/*
	 * トランザクションを完了する。
	 */
	sql = "COMMIT";
	EXEC SQL EXECUTE IMMEDIATE :sql;

	/*
	 * PostgreSQLへの接続をクローズする。
	 */
	EXEC SQL DISCONNECT;

	return 0;
}

/*
 * SQL実行でエラーが発生したときに呼び出される、エラー処理のための関数。
 */
static void
elog(void)
{
	/*
	 * sqlcaからエラー理由のメッセージを取得して、標準エラー出力に出す。
	 * また、現在実行中または直前に実行済のSQLでエラーとなったものも
	 * 標準エラー出力に出す。
	 */
	fprintf(stderr, "ERROR: %s\n", sqlca.sqlerrm.sqlerrmc);
	fprintf(stderr, "STATEMENT: %s\n", sql);

	exit(1);
}

このECPGプログラムは以下のとおりコンパイルします。以下では、PostgreSQLのインストール先を/opt/pgsqlディレクトリとします。

$ ecpg test.pgc
$ gcc -o test test.c -I/opt/pgsql/include -L/opt/pgsql/lib -lecpg

プログラムの実行例は以下のとおりです。

$ ./test 1
1
$ ./test 2
1
2
$ ./test 0
0
1
2
$ ./test 0
ERROR: duplicate key value violates unique constraint "testtbl_pkey" on line 59
STATEMENT: INSERT INTO testtbl VALUES (?)
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?