DECLARE STATEMENT – PostgreSQL 14でコミットされた機能の先行紹介:技術者Blog
PostgreSQLインサイド

黒田 隼人

富士通株式会社
ソフトウェアプロダクト事業本部 データマネジメント事業部

はじめに

富士通のシニアディレクターであるAmit Kapilaが率いる"グローバルPostgreSQL開発チーム"は、当社のPostgreSQLに対する取り組みの一環として、コミュニティーへ継続的な貢献を行っています。私はこのチームの一員として、世界中の才能ある情熱的なコミュニティーメンバーとともに、PostgreSQLの発展に積極的に取り組んでいます。
私たちのチームは、メンバーが取り組んだ機能やパッチに焦点を当て、ブログ記事を発信しています。この記事では、PostgreSQL 14にコミットされたECPGの新規構文であるDECLARE STATEMENTの機能について紹介します。

背景

黒田
C言語による埋め込みSQLプログラムは、1989年に発表された標準SQL規格(SQL89)で仕様が規定されたデータベースへの接続方法です。この機能はOracleやMicrosoft、IBMといった数多くのベンダーが提供しているほか、PostgreSQLでもECPGとして公開されています。基本的な構文や規則は標準SQL規格により規定されていますが、その仕様にどの程度準拠するかはベンダーによって異なります。また、各ベンダーは埋め込みSQL構文を独自に追加しているため、これらの差異がデータベース製品の移行における障壁となることがあります。
今回私が提案したDECLARE STATEMENTという埋め込みSQL構文は、元々はOracleが提供していた機能です。この機能がPostgreSQLでも利用可能となることで、Oracleや他ベンダー製品からPostgreSQLへの移行が容易になるため、結果としてPostgreSQLの採用率向上につながると考えています。

DECLARE STATEMENTとは

黒田
DECLARE STATEMENTとはプリペアド文の識別子を宣言する埋め込みSQL構文です。この構文はOracleの埋め込みSQLプログラムとの互換性を向上させるために導入されますが、従来からのECPGユーザーにも利点があります。
Oracleの埋め込みSQLプログラムでカーソルを使用する場合、DECLARE CURSOR構文に指定するプリペアド文の識別子は事前に宣言されている必要があります。つまり、以下の様なサンプルプログラムはプレコンパイルに失敗します。

例1

…
EXEC SQL DECLARE cursor CURSOR FOR stmt; // stmtが事前に宣言されていないためプレコンパイルエラー
EXEC SQL PREPARE stmt FROM “SELECT …”;
…

では、Oracleではどのようにカーソルを使用するのでしょうか?解決策は複数個ありますが、そのうちの1つがDECLARE STATEMENT構文を使用することです。本構文をDECLARE CURSOR構文の前に記載しておくと、プレコンパイラーはstmtがプリペアド文の識別子であることを認識するため、プレコンパイルが成功するようになります。この解決策を基に、例1に対して修正を加えたのが以下のサンプルプログラムです。

例2

…
EXEC SQL DECLARE stmt STATEMENT; // ここでstmtがプリペアド文の識別子であることを宣言する
EXEC SQL DECLARE cursor CURSOR FOR stmt;
EXEC SQL PREPARE stmt FROM “SELECT …”;
…

PostgreSQL 13以前ではDECLARE STATEMENT構文が利用できなかったため、例2のような埋め込みSQLプログラムを使用しているユーザーはアプリケーションを改修する必要がありました。PostgreSQL 14以降では本構文が使用可能となったため、OracleユーザーがよりPotgreSQLへと移行しやすくなりました。なお、ECPGではプリペアド文の識別子を宣言する必要はなく、例1のサンプルプログラムの時点で問題なくプレコンパイルに成功します。このため基本的にはECPGの動作に変更はなく、互換性向上のための追加構文です。

また、本構文にはもう1つの使い方があります。それは「宣言された識別子に対して、データベースの接続を紐づける」というものです。接続と紐づいた識別子を用いる埋め込みSQL構文を実行する際には、実行時の接続ではなく識別子と紐づいたものが使用されるようになります。識別子と接続を紐づける際には、DECLARE STATEMENT構文の冒頭にAT句を追加して接続を指定します。例として以下の様なサンプルプログラムを考えてみましょう。

例3

EXEC SQL BEGIN DECLARE SECTION;
char dbname[128];
EXEC SQL END DECLARE SECTION;
…
EXEC SQL CONNECT TO db1 AS connection1;
EXEC SQL CONNECT TO db2 AS connection2;
EXEC SQL SET CONNECTION TO connection2; // (1)
EXEC SQL AT connection1 DECLARE stmt STATEMENT; // (2)
EXEC SQL PREPARE stmt FROM "SELECT current_database()"; // (3)
EXEC SQL EXECUTE stmt INTO :dbname; // (3)

このプログラムを実行した場合、どのデータベースに対して(3)PREPARE構文とEXECUTE構文が実行されるでしょうか?(1)SET CONNECTION構文により接続をconnection2へと設定していますが、(2)DECLARE STATEMENT構文では接続connection1を指定しています。このような場合、プリペアド文の識別子stmtはdb1の接続と紐づくため、(3)は接続connection1を用いて実行されます。

効果

黒田
この埋め込みSQL構文を使用する利点は何でしょうか?1つは冒頭にも述べた通り、データベース製品の移行が容易になることです。製品間での非互換が少ない場合、ユーザーは製品移行時にもアプリケーションを書き換える必要がなくなり、自分が提供したいサービスに対して100%の労力を割くことが可能になります。
また従来からPostgreSQLを利用していたユーザーにも、埋め込みSQL構文を書く際に接続指定の回数を減らし、ソースコードを短くできるという利点があります。DECLARE STATEMENT構文を使用せず、かつ、プログラム内で複数の接続を使い分けるようなユーザーアプリケーションを作成する場合、PREPARE構文やEXECUTE構文、さらにカーソル操作関連の埋め込みSQL構文において注意深く接続を指定する必要があります。これらはただ単純にソースコードが長くなるというだけでなく、接続の選択誤りによるアプリケーションのバグを引き起こす一因になるかもしれません。DECLARE STATEMENT構文を用いてプリペアド文の識別子と接続を紐づけた場合、以降の埋め込みSQL構文では使用する接続を固定することができるため、このようなバグを未然に防ぐことができます。

今後に向けて

黒田
現在において、ユーザーアプリケーションからデータベースに対して接続する場合、psqlODBCやPostgreSQL JDBC Driverといったドライバーを用いることが主流となっています。また、ECPG関連の議論はPostgreSQLコミュニティー内でもあまり活発ではなく、Commitfestのエントリー数も少ないのは事実です。しかしながら、過去の資産はこの世から消えてしまうことはなく、実際に富士通のお客様にはC言語およびCOBOL言語による埋め込みSQLプログラムを活用しているケースが多数あります。今まで培ってきた経験やお客様からの意見を基に、私たちはECPGをより使いやすいものへと改良していきます。
私個人としては、富士通に入社して最初に任された仕事がこうして実を結んだことに非常に安堵しています。今後はECPGはもちろんのこと、シャーディングによるスケールアウトをPostgreSQLで実現するための研究開発を行う予定です。

2021年5月14日公開

オンデマンド(動画)セミナー

    • PostgreSQLに関連するセミナー動画を公開中。いつでもセミナーをご覧いただけます。
      • 【事例解説】運送業務改革をもたらす次世代の運送業界向けDXプラットフォームの構築
      • ハイブリッドクラウドに最適なOSSベースのデータベースご紹介

本コンテンツに関するお問い合わせ

お電話でのお問い合わせ

Webでのお問い合わせ

当社はセキュリティ保護の観点からSSL技術を使用しております。

ページの先頭へ