2015年1月8日木曜日

PostgreSQLはStatement.RETURN_GENERATED_KEYSで全カラムの値が返される

PostgresSQLは、Statement生成時に、Statement.RETURN_GENERATED_KEYSを指定するとStatement#getGeneratedKeysでそのテーブルの全カラムの情報が取得される。

これは、Statement.RETURN_GENERATED_KEYSでStatementを生成すると、実行されるINSERT文に「RETURNING *」が付加されるため。

ID、NAME、BIRTHDAYの3つのカラムを持つテーブルにINSERT処理を行っています。
INSERT対象のカラムはNAMEのみで、ID列は自動採番カラム(SERIAL)となっています。
PreparedStatement statement = connection.prepareStatement("insert into USER_INFO (name) VALUES (?)",
        Statement.RETURN_GENERATED_KEYS);
statement.setString(1, "なまえ");

statement.executeUpdate();
ResultSet generatedKeys = statement.getGeneratedKeys();
if (generatedKeys.next()) {
    System.out.println(MessageFormat.format("カラム数 = [{0}]",
            statement.getMetaData().getColumnCount()));
    System.out.println("generatedKeys.getDate(3) = " + generatedKeys.getDate(3));
}
connection.commit();

実行結果

実行すると、GeneratedKeysで取得したResultSetのカラム数は3となっていることがわかります。
また、INSERT時に列挙していないカラムのデータもとれているのがわかります。
カラム数 = [3]
generatedKeys.getDate(3) = null

実際に実行されたSQL文

ログを見てみると、実行されたINSERT文にRETURNING *が付加されているのがわかります。
これが理由で、getGeneratedKeysが全カラムの情報を戻して来ています。
2015-01-08 12:48:11 JST LOG:  duration: 0.000 ms  parse : insert into USER_INFO (name) VALUES ($1) RETURNING *
2015-01-08 12:48:11 JST LOG:  duration: 0.000 ms  bind : insert into USER_INFO (name) VALUES ($1) RETURNING *
2015-01-08 12:48:11 JST DETAIL:  parameters: $1 = 'なまえ'
2015-01-08 12:48:11 JST LOG:  duration: 1.000 ms  execute : insert into USER_INFO (name) VALUES ($1) RETURNING *
2015-01-08 12:48:11 JST DETAIL:  parameters: $1 = 'なまえ'
2015-01-08 12:48:11 JST LOG:  duration: 0.000 ms  parse : insert into USER_INFO (name) VALUES ($1) RETURNING *

カラムインデックスやカラム名指定の場合は?

Statement生成時に自動生成カラムのインデックスや名前を指定した場合は、指定したカラムの情報のみ取得することが出来ます。
例えば、ID列のみを指定した場合実行されるSQL文は以下のようになります。
2015-01-08 12:55:28 JST LOG:  duration: 34.000 ms  parse : insert into USER_INFO (name) VALUES ($1) RETURNING "id"
2015-01-08 12:55:28 JST LOG:  duration: 0.000 ms  bind : insert into USER_INFO (name) VALUES ($1) RETURNING "id"
2015-01-08 12:55:28 JST DETAIL:  parameters: $1 = 'なまえ'
2015-01-08 12:55:28 JST LOG:  duration: 0.000 ms  execute : insert into USER_INFO (name) VALUES ($1) RETURNING "id"
2015-01-08 12:55:28 JST DETAIL:  parameters: $1 = 'なまえ'
2015-01-08 12:55:28 JST LOG:  duration: 0.000 ms  parse : insert into USER_INFO (name) VALUES ($1) RETURNING "id"