Thread: ResultSetMetaData.getTableName() == null

ResultSetMetaData.getTableName() == null

From
Alex Stienstra
Date:
Hi,

GetTableName() always returns null. Can someone tell me if this is
considered to be a problem and if so when it will be fixed.

Best regards,

Alex Stienstra.

Re: ResultSetMetaData.getTableName() == null

From
Philip Yarra
Date:
Hi Alex,

Alex Stienstra wrote:
> GetTableName() always returns null. Can someone tell me if this is
> considered to be a problem and if so when it will be fixed.

Are you sure it's really null? According to the javadoc for
ResultSetMetaData, getTableName() may return "" - see
http://java.sun.com/j2se/1.4.2/docs/api/java/sql/ResultSetMetaData.html#getTableName(int).

I did a quick test app, and the driver version I'm using
(postgresql-8.1-404.jdbc3.jar) returns "". If you get different, tell me
which driver version you're using and I'll try that.

I don't know why it returns "" - perhaps someone else can answer that.
Mind you, Oracle 10g does the same. Sybase ASE 12.5 is the only DB I
have access to where I get a non-empty table name.

Regards, Philip.

--
Philip Yarra
Senior Software Engineer, Utiba Pty Ltd
philip@utiba.com

Re: ResultSetMetaData.getTableName() == null

From
Oliver Jowett
Date:
Philip Yarra wrote:

> I don't know why it returns "" - perhaps someone else can answer that.
> Mind you, Oracle 10g does the same. Sybase ASE 12.5 is the only DB I
> have access to where I get a non-empty table name.

There was a long discussion about this some time ago, see
http://archives.postgresql.org/pgsql-jdbc/2004-08/msg00023.php or
thereabouts which is when we started agreeing on things :)

Essentially I think it boiled down to "getTableName() should return the
table alias name", and since we don't have that available we return "".
There's a postgresql-specific interface to get at the underlying table
name (in the cases where that info is available).

-O

Re: ResultSetMetaData.getTableName() == null

From
Philip Yarra
Date:
Oliver Jowett wrote:
> Essentially I think it boiled down to "getTableName() should return the
> table alias name", and since we don't have that available we return "".
> There's a postgresql-specific interface to get at the underlying table
> name (in the cases where that info is available).

Hmmm... maybe I'm missing something, but the attached test case doesn't
use any aliases, and it returns "" (at least it does for me). Is this
expected behaviour? If there's a postgresql-specific way to get it,
couldn't this method implement the same way of getting it?

BTW: not a big deal for me, I can't see that I'd ever want to use that
method. I'm just curious...

Regards, Philip.

--
Philip Yarra
Senior Software Engineer, Utiba Pty Ltd
philip@utiba.com
driver = org.postgresql.Driver
url = jdbc:postgresql://your_host:5432/your_db
user = you
pass = your_password
import java.sql.*;
import java.util.*;
import java.io.*;
import java.text.SimpleDateFormat;

class rsmd
{
    static Connection conn = null;
    static Properties prop = null;

    public static void main(String [] args)
    {
        try
        {
            if(args.length > 0) prop = loadProp(args[0]);
            else usage();
            String url = prop.getProperty("url");
            String user = prop.getProperty("user");
            String pass = prop.getProperty("pass");
            String driver = prop.getProperty("driver");
            Class.forName(driver);
            conn = DriverManager.getConnection(url,user,pass);
            conn.setAutoCommit(true);
            createTable();
            insertData();
            executeSelect();
            conn.commit();
            dropTable();
            conn.commit();
            conn.close();
            log("all done");
        }

        catch(Exception ex)
        {
            log(ex);
            System.exit(1);
        }
    }

    static void executeSelect()
    {
        PreparedStatement stmt = null;
        try{
        stmt = conn.prepareStatement("SELECT * FROM tempextest");
        ResultSet rs = stmt.executeQuery();
        ResultSetMetaData rsmd = rs.getMetaData();
        String table = rsmd.getTableName(1);
        if(table == null) log("null table name");
        if("".equals(table)) log("empty table name");
        log("table name [" + table + "]");
        } catch (SQLException sqlex) {
            log(sqlex);
            closeStatement(stmt);
        }
    }

    static void createTable()
    {
        log("Creating table tempextest");
        PreparedStatement stmt = null;
        try {
            stmt = conn.prepareStatement("CREATE TABLE tempextest(id INT PRIMARY KEY)");
            stmt.executeUpdate();
        } catch (SQLException sqlex) {
            log(sqlex);
            log("error creating table tempextest, can't proceed");
            closeStatement(stmt);
            System.exit(1);

        }
        log("Table tempextest created");
    }

    static void insertData()
    {
        log("Inserting data into table tempextest");
        PreparedStatement stmt = null;
        try {
            stmt = conn.prepareStatement("INSERT INTO tempextest(id) VALUES (42)");
            stmt.executeUpdate();
        } catch (SQLException sqlex) {
            log(sqlex);
            log("error inserting data into table tempextest, can't proceed");
            closeStatement(stmt);
            System.exit(1);

        }
        log("Table tempextest created");
    }

    static void dropTable()
    {
        log("Dropping table tempextest");
        PreparedStatement stmt = null;
        try {
            stmt = conn.prepareStatement("DROP TABLE tempextest");
            stmt.executeUpdate();
        } catch (SQLException sqlex) {
            log(sqlex);
            closeStatement(stmt);
        }
        log("Table tempextest dropped");
    }

    static Properties loadProp(String fileName)
    {
        try{
        Properties prop = new Properties();
        FileInputStream fis = new FileInputStream(fileName);
        prop.load(fis);
        return prop;
        } catch (Exception ex) {
            log("exception loading properties: " + ex);
            usage();
        }
        return null;
    }

    static void usage()
    {
        System.err.println("Usage: java rsmd propfile");
        System.exit(1);
    }

    static void log(String msg)
    {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S");
        System.out.println(sdf.format(new java.util.Date()) + ":" + msg);
    }

    static void log(Exception ex)
    {
        log(ex.toString());
        ex.printStackTrace();
    }

    static void log(Object o)
    {
        log(o.toString());
    }

    static void closeStatement(Statement st)
    {
        try{
            st.close();
        }catch(SQLException sqlex) {
            log(sqlex);
        }
    }


}

Re: ResultSetMetaData.getTableName() == null

From
Oliver Jowett
Date:
Philip Yarra wrote:
> Oliver Jowett wrote:
>
>> Essentially I think it boiled down to "getTableName() should return
>> the table alias name", and since we don't have that available we
>> return "". There's a postgresql-specific interface to get at the
>> underlying table name (in the cases where that info is available).
>
>
> Hmmm... maybe I'm missing something, but the attached test case doesn't
> use any aliases, and it returns "" (at least it does for me). Is this
> expected behaviour? If there's a postgresql-specific way to get it,
> couldn't this method implement the same way of getting it?

We don't know whether aliases have been used or not so we can't do this.

-O

Re: ResultSetMetaData.getTableName() == null

From
Philip Yarra
Date:
Oliver Jowett wrote:
> We don't know whether aliases have been used or not so we can't do this.

Just had a look at the source for getTableName:

public String getTableName(int column) throws SQLException
{
         return "";
}

I can cast rsmd to PGResultSetMetaData and call getBaseTableName, and it
does what I expect - in my example, gets the table name... so is there
some reason why getTableName couldn't be re-written as:

public String getTableName(int column) throws SQLException
{
    return getBaseTableName(column);
}

Sorry if this is re-hashing old ground - I read the thread you mentioned
before, but that seemed to be more about getting column names where
they're aliased in the query using an AS clause. I'm assuming there's a
lot of background that led to the implementation we have currently...
any hints gratefully accepted.

Regards, Philip.

--
Philip Yarra
Senior Software Engineer, Utiba Pty Ltd
philip@utiba.com

Re: ResultSetMetaData.getTableName() == null

From
Oliver Jowett
Date:
Philip Yarra wrote:

> so is there
> some reason why getTableName couldn't be re-written as:
>
> public String getTableName(int column) throws SQLException
> {
>     return getBaseTableName(column);
> }
>

We came to the conclusion in the original discussion that getTableName()
should return the aliased name of the table in the query, or the actual
table name if not aliased.

getBaseTableName() always returns the real underlying table name, even
if it was actually aliased to something else in the query. This reflects
the information that the server gives us (see the RowDescription message
in
http://www.postgresql.org/docs/8.1/static/protocol-message-formats.html
-- getBaseTableName() returns a name based on the table object ID in
that message)

So your suggested implementation would return incorrect information
whenever there were aliases involved.

We have no way of telling if aliasing has been done or not based on the
data returned by the server, so we can't even do it only when no aliases
are used.

-O

Re: ResultSetMetaData.getTableName() == null

From
Philip Yarra
Date:
Oliver Jowett wrote:
> Philip Yarra wrote:
> So your suggested implementation would return incorrect information
> whenever there were aliases involved.

Thanks, I understand now. So the decision was to return nothing, rather
than something that's potentially wrong?

> We have no way of telling if aliasing has been done or not based on the
> data returned by the server, so we can't even do it only when no aliases
> are used.

Looks like Sybase came to the same question and decided that returning
the base table name was ok:

$ java -cp .:/home/philip/bin/jconn3.jar rsmd sybase3.prop
2006-09-22T15:50:39.206:QUERY: SELECT * FROM tempextest
2006-09-22T15:50:39.210:table name [tempextest]
2006-09-22T15:50:39.212:QUERY: SELECT * FROM tempextest tablealias
2006-09-22T15:50:39.215:table name [tempextest]

Oracle seems to have a very similar implementation to PostgreSQL:

$ java -cp .:/home/philip/bin/ojdbc14.jar rsmd oracle.prop
2006-09-22T15:53:59.882:QUERY: SELECT * FROM tempextest
2006-09-22T15:53:59.986:empty table name
2006-09-22T15:53:59.987:table name []
2006-09-22T15:53:59.989:QUERY: SELECT * FROM tempextest tablealias
2006-09-22T15:54:00.3:empty table name
2006-09-22T15:54:00.4:table name []

How about allowing the user to set a connection property so that the
(possibly-wrong-but-more-useful) call through to getbaseTablename is
done, so that *some* info comes back, with default of existing
behaviour? Or has that also been discussed and dismissed previously? :-)

Regards, Philip.

--
Philip Yarra
Senior Software Engineer, Utiba Pty Ltd
philip@utiba.com

Re: ResultSetMetaData.getTableName() == null

From
Alex Stienstra
Date:
MySQL returns the tablename if possible otherwise the alias. I find
this an acceptable solution. Having at least a name one could query the
meta system in other to determine whether it is a table name or not.

I am working on automatically generated web interface on the basis of a
single SQL query. This is why I need to know the columns and tables
involved in the query: http://www.melstra.nl/test/Form1.php

Best regards,

Alex Stienstra.

Re: ResultSetMetaData.getTableName() == null

From
Markus Schaber
Date:
Hi, Alex,

Alex Stienstra wrote:
> MySQL returns the tablename if possible otherwise the alias. I find this
> an acceptable solution. Having at least a name one could query the meta
> system in other to determine whether it is a table name or not.

The problem is that PostgreSQL does not pass any information about
aliases down to the client.

So we have two possibilities to implement this feature: Hack up the
server to provide that additional info, or implement a fully-fledged SQL
parser in the client and get the alias names ourselves.

Both seems not worth it currently.

HTH,
Markus
--
Markus Schaber | Logical Tracking&Tracing International AG
Dipl. Inf.     | Software Development GIS

Fight against software patents in Europe! www.ffii.org
www.nosoftwarepatents.org

Re: ResultSetMetaData.getTableName() == null

From
Dave Cramer
Date:
On 22-Sep-06, at 9:23 AM, Markus Schaber wrote:

> Hi, Alex,
>
> Alex Stienstra wrote:
>> MySQL returns the tablename if possible otherwise the alias. I
>> find this
>> an acceptable solution. Having at least a name one could query the
>> meta
>> system in other to determine whether it is a table name or not.
>
> The problem is that PostgreSQL does not pass any information about
> aliases down to the client.
>
> So we have two possibilities to implement this feature: Hack up the
> server to provide that additional info, or implement a fully-
> fledged SQL
> parser in the client and get the alias names ourselves.
Certainly parsing the SQL is expensive, however I would like to see
the server extend the protocol to give us this information.

Dave
>
> Both seems not worth it currently.
>
> HTH,
> Markus
> --
> Markus Schaber | Logical Tracking&Tracing International AG
> Dipl. Inf.     | Software Development GIS
>
> Fight against software patents in Europe! www.ffii.org
> www.nosoftwarepatents.org
>
> ---------------------------(end of
> broadcast)---------------------------
> TIP 1: if posting/reading through Usenet, please send an appropriate
>        subscribe-nomail command to majordomo@postgresql.org so that
> your
>        message can get through to the mailing list cleanly
>


Re: ResultSetMetaData.getTableName() == null

From
"Alex Stienstra"
Date:
Hi Markus,

I'am surprised that PostgreSQL doesn't pass the table informatie to the
client. Susprised, since for example the library PHP (pg_field_table) is
using, does pass on this information. I'am quite sure that this library
function is based on the same API as the JDBC implementation is.

I agree with you that PostgreSQL server should supply this information
and implementing a full-flegded SQL parser is no option. Specially,
because PostgreSQL already parses the statement and therefore knows the
tables and columns that are involved in the query.

It is a pitty that this (for me) vital information is not made
available.

Best regards,

Alex.

-----Original Message-----
From: pgsql-jdbc-owner@postgresql.org
[mailto:pgsql-jdbc-owner@postgresql.org] On Behalf Of Markus Schaber
Sent: vrijdag 22 september 2006 15:24
To: pgsql-jdbc@postgresql.org
Subject: Re: [JDBC] ResultSetMetaData.getTableName() == null


Hi, Alex,

Alex Stienstra wrote:
> MySQL returns the tablename if possible otherwise the alias. I find
> this an acceptable solution. Having at least a name one could query
> the meta system in other to determine whether it is a table name or
> not.

The problem is that PostgreSQL does not pass any information about
aliases down to the client.

So we have two possibilities to implement this feature: Hack up the
server to provide that additional info, or implement a fully-fledged SQL
parser in the client and get the alias names ourselves.

Both seems not worth it currently.

HTH,
Markus
--
Markus Schaber | Logical Tracking&Tracing International AG
Dipl. Inf.     | Software Development GIS

Fight against software patents in Europe! www.ffii.org
www.nosoftwarepatents.org

---------------------------(end of broadcast)---------------------------
TIP 1: if posting/reading through Usenet, please send an appropriate
       subscribe-nomail command to majordomo@postgresql.org so that your
       message can get through to the mailing list cleanly


Re: ResultSetMetaData.getTableName() == null

From
Markus Schaber
Date:
Hi, Alex,

Alex Stienstra wrote:

> I'am surprised that PostgreSQL doesn't pass the table informatie to the
> client. Susprised, since for example the library PHP (pg_field_table) is
> using, does pass on this information. I'am quite sure that this library
> function is based on the same API as the JDBC implementation is.

AFAICS, it does pass _table_ information, but not alias information. Are
you shure the PHP library does show you alias information? Is it using
V2 or V3 protocol under the hoods?


Thanks,
Markus
--
Markus Schaber | Logical Tracking&Tracing International AG
Dipl. Inf.     | Software Development GIS

Fight against software patents in Europe! www.ffii.org
www.nosoftwarepatents.org