7

When I use postgresql, I found following code:

Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from t");

String tableName = rs.getMetaData().getTableName(1);
System.out.println(tableName);

It prints an empty string.

So I checked the source code, and found the method org.postgresql.jdbc2.AbstractJdbc2ResultSetMetaData#getTableName always returns an empty string.

The source code is:

public abstract class AbstractJdbc2ResultSetMetaData implements PGResultSetMetaData {

    /*
     * @param column the first column is 1, the second is 2...
     * @return column name, or "" if not applicable
     * @exception SQLException if a database access error occurs
     */
    public String getTableName(int column) throws SQLException
    {
        return "";
    }
}

You can see it just return a "".

I found a discussion about this, please see: http://archives.postgresql.org/pgsql-jdbc/2009-12/msg00100.php

They think "rs.getMetaData.getTableName(col)" should return the alias name in query not the underlying table name. But which is hard to implement, so it's better to leave it empty.

Also they gave a method to get the table name, use:

PGResultSetMetaData.getBaseTableName() 

Sample:

ResultSet rs = stmt.executeQuery("select * from x");
// convert it to PGResultSetMetaData 
PGResultSetMetaData meta = (PGResultSetMetaData)rs.getMetaData(); 
String tableName = meta.getBaseTableName(1);

Now it can print the correct table name.

I don't know the implementation of postgresql is correct, but returning the underlying table name is much more useful than an empty string, and, most of other databases provides underlying table name instead of an empty string.

I have a problem using play2's anorm framework with postgesql: Play2's anorm can't work on postgresql, but that works well on other databases.

What do you think the correct implementation of postgresql's jdbc driver? Return an empty string, underlying table name, or something else?

4

2 に答える 2

3

テーブル名が空の文字列と見なされることは決してないため、空の文字列を返すことは明らかにインターフェイスの不適切な実装であると言えます。

彼らが苦労していると私が信じている問題は、現在の実装が間違っているにもかかわらず、実装を選択すると、動作への依存関係を壊すことが許容されると判断するまで、その実装に固執することです。したがって、彼らは名前が明確なメソッドを追加し、ほとんどのユーザーが期待していたデータを提供することを選択し、何を返すかについて合意に達するまで、またはパッチが提出されるまでgetTableName、メソッドの明らかに壊れた実装を残します。getTableNameコンセンサスを実現するものです。

私の直観的な反応は、メソッドgetTableNameがそのテーブルに使用されているエイリアスを返す必要があるということです。テーブルはそれ自体と結合でき、エイリアスを使用すると、参照されているテーブルを識別できます。クエリでテーブルが生成された可能性があり (配列のネスト解除など)、データベースにテーブル名すらありません。「絶対に常にエイリアスを返す」という決定を下した場合getTableName、少なくともユーザーは何を期待すべきかを知っています。そうしないと、メソッドが何を返すべきかが明確にわからなくなります。

ただし、私の直感が「正しい実装」であると仮定しても、互換性の問題が発生します。PostgreSQL の目標の 1 つが人気を高めることである場合、できるだけ少ない投資で別の DBMS から PostgreSQL に切り替えることができることが望ましいです。したがって、「他の JDBC は java.sql インターフェースをどのように実装していますか?」関連するようになります。あなたが言うように、 がどのように実装されるべきかを期待するフレームワークが存在し、インターフェイスがResultSetMetaDataどのように実装されるかについて特定の期待を持っているのはフレームワークだけではありません。java.sql

最終的にどちらの実装を選択するかはトレードオフになるため、「途中でやめてしまう」ことが彼らの選択である理由がわかります。彼らが行いたいトレードオフを選択すると、彼らは閉じ込められます.

編集:実装されていないという例外をスローすることは、黙って失敗するよりも優れていることをお勧めします。の特定の実装に依存するフレームワークでは、getTableNameとにかく空の文字列をあま​​り使用せず、エラーまたはそれ自体がサイレントに失敗することを期待しています。

于 2013-01-07T18:28:42.487 に答える