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 的目标之一是越来越受欢迎,那么希望能够以尽可能少的投资从另一个 DBMS 切换到 PostgreSQL。因此,诸如“其他 JDBC 是如何实现 java.sql 接口的?”之类的问题。变得相关。正如您所说,存在一个对ResultSetMetaData如何实现接口有期望的框架,而且它可能不是唯一一个对java.sql接口如何实现有一定期望的框架。

无论他们最终选择哪种实现方式都将是一个权衡,所以我明白为什么“把罐子踢下去”是他们的选择。一旦他们选择了他们想要做出的权衡,他们就会被锁定。

编辑:我建议抛出关于未实现的异常比只是默默地失败要好。我希望依赖于特定实现的框架getTableName无论如何都不会对空字符串有太多用处,并且无论是错误还是它们本身都会默默地失败。

于 2013-01-07T18:28:42.487 回答
0

似乎这将在下一个版本中改变:https ://github.com/pgjdbc/pgjdbc/pull/107

于 2013-12-27T10:37:25.620 回答