この節では、データベース接続の開始、終了、および切り替え方について解説します。
以下のSQL文を使用して、データベースへ接続します。
EXEC SQL CONNECT TOtarget
[ASconnection-name
] [USERuser-name
];
target
は以下の方法で指定されます。
dbname
[@hostname
][:port
]
tcp:postgresql://hostname
[:port
][/dbname
][?options
]
unix:postgresql://hostname
[:port
][/dbname
][?options
]
DEFAULT
接続対象をリテラル(つまり、変数を参照しない形)で指定し、その値を引用符でくくらなかった場合、大文字小文字の区別に関して通常のSQLの規則が適用されます。
また、この場合、必要に応じて個々のパラメータを二重引用符で別々にくくることもできます。
実際には、おそらく(単一引用符でくくられた)文字列リテラルもしくは変数の参照を使用した方がエラーをより防止することができます。
DEFAULT
接続対象は、デフォルトデータベース、デフォルトのユーザ名で接続を初期化します。
この場合は、ユーザ名と接続名を分けて指定することができません。
ユーザ名を指定するには、別の方法もあります。
username
username
/password
username
IDENTIFIED BY password
username
USING password
これまで同様、username
とpassword
は、SQL識別子、SQL文字列リテラル、文字型変数への参照を取ることができます。
接続対象にoptions
を含めるのなら、
指定をアンパサンド(keyword
=value
&
)で区切って構成します。
許されるキーワードは、libpqが認識するものと同じです(33.1.2を参照してください)。
keyword
やvalue
の前の空白は無視されますが、中や後の空白は無視されません。
value
の中に&
を書く方法はないことに注意してください。
1つのプログラム内で複数の接続を処理する場合には、connection-name
を使用します。
プログラムで1つしか接続を使わない場合は省略して構いません。
最も最近に開かれた接続が現在の接続になり、SQL文を実行しようとする時にデフォルトでこの接続が使用されます(本章の後で説明します)。
信用できないユーザが安全なスキーマ使用パターンを採用していないデータベースにアクセスできる場合、各セッションをsearch_path
から一般のユーザが書き込み可能なスキーマを取り除くことから始めます。
例えば、options=-c search_path=
を
に追加したり、接続後にoptions
EXEC SQL SELECT pg_catalog.set_config('search_path', '', false);
を発行したりします。
この配慮はECPGに特有のものではありません。任意のSQLコマンドを実行するインタフェースすべてに当てはまります。
以下にCONNECT
文について、数例を示します。
EXEC SQL CONNECT TO mydb@sql.mydomain.com; EXEC SQL CONNECT TO unix:postgresql://sql.mydomain.com/mydb AS myconnection USER john; EXEC SQL BEGIN DECLARE SECTION; const char *target = "mydb@sql.mydomain.com"; const char *user = "john"; const char *passwd = "secret"; EXEC SQL END DECLARE SECTION; ... EXEC SQL CONNECT TO :target USER :user USING :passwd; /* もしくは EXEC SQL CONNECT TO :target USER :user/:passwd; */
最後の形式では、文字変数参照として上を参照する変数を使用しています。 後の節で、接頭辞にコロンを持つ場合のSQL文内でのC変数の使用方法について説明します。
接続対象の書式は標準SQLでは規定されていないことに注意してください。 そのため、移植可能なアプリケーションを開発したいのであれば、上の例の最後の方法を基にして、接続対象文字列をどこかにカプセル化してください。
前節で示したSQL文は現在の接続、つまり、最も最近に開いた接続上で実行されます。 複数の接続を管理する必要があるアプリケーションでは、これを処理する2つの方法があります。
1つ目の選択肢は、各SQL文で明示的に接続を選択することです。 以下に例を示します。
EXEC SQL AT connection-name
SELECT ...;
アプリケーションが複数の接続を不特定な順番で使用する必要がある場合、この選択肢は特に適しています。
アプリケーションの実行に複数スレッドを使用する場合、スレッド間で接続を同時に共有できません。 接続へのアクセスを(ミューテクスを使用して)明示的に制御するか、または各スレッド用の接続を使用するかを行わなければなりません。
2番目の選択肢は、現在の接続を切り替えるSQL文を実行することです。 以下のSQL文です。
EXEC SQL SET CONNECTION connection-name
;
多くのSQL文を同一接続に対して使用する場合、この選択肢は特に便利です。
以下に複数のデータベースコネクションを管理しているプログラムの例を示します。
#include <stdio.h> EXEC SQL BEGIN DECLARE SECTION; char dbname[1024]; EXEC SQL END DECLARE SECTION; int main() { EXEC SQL CONNECT TO testdb1 AS con1 USER testuser; EXEC SQL SELECT pg_catalog.set_config('search_path', '', false); EXEC SQL COMMIT; EXEC SQL CONNECT TO testdb2 AS con2 USER testuser; EXEC SQL SELECT pg_catalog.set_config('search_path', '', false); EXEC SQL COMMIT; EXEC SQL CONNECT TO testdb3 AS con3 USER testuser; EXEC SQL SELECT pg_catalog.set_config('search_path', '', false); EXEC SQL COMMIT; /* この問い合わせは最後に開いたデータベース"testdb3"で実行される。 */ EXEC SQL SELECT current_database() INTO :dbname; printf("current=%s (should be testdb3)\n", dbname); /* "testdb2"で問い合わせを実行するには"AT"を使う */ EXEC SQL AT con2 SELECT current_database() INTO :dbname; printf("current=%s (should be testdb2)\n", dbname); /* 現在の接続を"testdb1"に切り替える。 */ EXEC SQL SET CONNECTION con1; EXEC SQL SELECT current_database() INTO :dbname; printf("current=%s (should be testdb1)\n", dbname); EXEC SQL DISCONNECT ALL; return 0; }
この例は、次のような出力を生成します。
current=testdb3 (should be testdb3) current=testdb2 (should be testdb2) current=testdb1 (should be testdb1)
接続を閉じるには以下のSQL文を使用します。
EXEC SQL DISCONNECT [connection
];
connection
は以下の方法で指定されます。
connection-name
DEFAULT
CURRENT
ALL
接続名の指定がなければ、現在の接続が閉じられます。
アプリケーションでは、過去に開いたすべての接続を明示的に閉じることを推奨します。