“这是正确的吗?”;ResultSet.getMetaData.getTableName(col)";postgresql的';的jdbc驱动程序总是返回空字符串?

“这是正确的吗?”;ResultSet.getMetaData.getTableName(col)";postgresql的';的jdbc驱动程序总是返回空字符串?,postgresql,jdbc,metadata,tablename,Postgresql,Jdbc,Metadata,Tablename,当我使用postgresql时,我发现以下代码: Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("select * from t"); String tableName = rs.getMetaData().getTableName(1); System.out.println(tableName); 它打印一个空字符串 因此我检查了源代码,发现方法org.postgresql.jdbc2.

当我使用postgresql时,我发现以下代码:

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

String tableName = rs.getMetaData().getTableName(1);
System.out.println(tableName);
它打印一个空字符串

因此我检查了源代码,发现方法
org.postgresql.jdbc2.AbstractJdbc2ResultSetMetaData#getTableName
总是返回空字符串

源代码是:

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 "";
    }
}
您可以看到它只返回一个

我发现了关于此的讨论,请参见:

他们认为 “rs.getMetaData.getTableName(col)”应在中返回别名 查询不是基础表名。但这很难实现,所以最好让它空着

他们还提供了获取表名的方法,使用:

PGResultSetMetaData.getBaseTableName() 
样本:

ResultSet rs = stmt.executeQuery("select * from x");
// convert it to PGResultSetMetaData 
PGResultSetMetaData meta = (PGResultSetMetaData)rs.getMetaData(); 
String tableName = meta.getBaseTableName(1);
现在它可以打印正确的表名了

我不知道postgresql的实现是否正确,但返回基础表名比返回空字符串有用得多,而且大多数其他数据库都提供基础表名而不是空字符串

我在使用play2的anorm框架和postgesql:时遇到了一个问题,但在其他数据库上效果很好


您认为postgresql的jdbc驱动程序的正确实现是什么?返回空字符串、基础表名或其他内容?

我想说,返回空字符串显然是接口的错误实现,因为表名永远不会被视为空字符串

我认为他们正在努力解决的问题是,尽管他们当前的实现是错误的,但一旦他们选择了一个实现,他们就会一直坚持下去,直到他们决定打破对行为的依赖是可以接受的。因此,他们选择添加一个名称明确的方法,并提供大多数用户期望来自
getTableName
的数据,并保留
getTableName
方法的一个明显失败的实现,直到就应该返回什么达成一致意见,或者直到提交了实现一致意见的补丁

我的直觉反应是方法
getTableName
应该返回用于该表的别名。表可以与其自身连接,使用别名可以识别引用的是哪个表。查询中可能已生成表(例如取消对数组的测试),因此数据库中甚至没有表名。如果您决定“绝对总是,
getTableName
返回别名”,那么至少用户知道应该期待什么;否则,您最终会发现该方法应该返回什么并不明显

然而,即使我认为我的直觉反应是“正确的实现”,它也会引发兼容性问题。如果PostgreSQL的目标之一是提高普及率,那么希望能够以尽可能少的投资从另一个DBMS切换到PostgreSQL。因此,像“其他JDBC如何实现java.sql接口?”这样的事情变得重要起来。正如您所说,存在一个对如何实现
ResultSetMetaData
有期望的框架,而且它可能不是唯一一个对如何实现
java.sql
接口有一定期望的框架

无论他们最终选择哪种实现,都将是一种权衡,因此我可以理解为什么他们会选择“一脚踢开罐头”。一旦他们选择了他们想要做的交易,他们就会被锁定


编辑:我建议抛出一个关于未实现的异常要比默默失败要好。我希望依赖于特定实现的
getTableName
的框架无论如何不会对空字符串有太多的使用,要么出错,要么自动失败。

似乎下一个版本会改变这一点: