All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.foundationdb.sql.jdbc.jdbc2.AbstractJdbc2ResultSetMetaData Maven / Gradle / Ivy

There is a newer version: 2.1-0-jdbc41
Show newest version
/*-------------------------------------------------------------------------
*
* Copyright (c) 2004-2011, PostgreSQL Global Development Group
*
*
*-------------------------------------------------------------------------
*/
package com.foundationdb.sql.jdbc.jdbc2;

import java.sql.*;

import com.foundationdb.sql.jdbc.PGResultSetMetaData;
import com.foundationdb.sql.jdbc.core.*;
import com.foundationdb.sql.jdbc.util.GT;
import com.foundationdb.sql.jdbc.util.PSQLException;
import com.foundationdb.sql.jdbc.util.PSQLState;

public abstract class AbstractJdbc2ResultSetMetaData implements PGResultSetMetaData
{
    protected final BaseConnection connection;
    protected final Field[] fields;

    private boolean fieldInfoFetched;

    /*
     * Initialise for a result with a tuple set and
     * a field descriptor set
     *
     * @param fields the array of field descriptors
     */
    public AbstractJdbc2ResultSetMetaData(BaseConnection connection, Field[] fields)
    {
        this.connection = connection;
        this.fields = fields;
        fieldInfoFetched = false;
    }

    /*
     * Whats the number of columns in the ResultSet?
     *
     * @return the number
     * @exception SQLException if a database access error occurs
     */
    public int getColumnCount() throws SQLException
    {
        return fields.length;
    }

    /*
     * Is the column automatically numbered (and thus read-only)
     * I believe that PostgreSQL does not support this feature.
     *
     * @param column the first column is 1, the second is 2...
     * @return true if so
     * @exception SQLException if a database access error occurs
     */
    public boolean isAutoIncrement(int column) throws SQLException
    {
        fetchFieldMetaData();
        Field field = getField(column);
        return field.getAutoIncrement();
    }

    /*
     * Does a column's case matter? ASSUMPTION: Any field that is
     * not obviously case insensitive is assumed to be case sensitive
     *
     * @param column the first column is 1, the second is 2...
     * @return true if so
     * @exception SQLException if a database access error occurs
     */
    public boolean isCaseSensitive(int column) throws SQLException
    {
        Field field = getField(column);
        return connection.getTypeInfo().isCaseSensitive(field.getOID());
    }

    /*
     * Can the column be used in a WHERE clause?  Basically for
     * this, I split the functions into two types: recognised
     * types (which are always useable), and OTHER types (which
     * may or may not be useable). The OTHER types, for now, I
     * will assume they are useable.  We should really query the
     * catalog to see if they are useable.
     *
     * @param column the first column is 1, the second is 2...
     * @return true if they can be used in a WHERE clause
     * @exception SQLException if a database access error occurs
     */
    public boolean isSearchable(int column) throws SQLException
    {
        return true;
    }

    /*
     * Is the column a cash value? 6.1 introduced the cash/money
     * type, which haven't been incorporated as of 970414, so I
     * just check the type name for both 'cash' and 'money'
     *
     * @param column the first column is 1, the second is 2...
     * @return true if its a cash column
     * @exception SQLException if a database access error occurs
     */
    public boolean isCurrency(int column) throws SQLException
    {
        String type_name = getPGType(column);

        return type_name != null && (type_name.equals("cash") || type_name.equals("money"));
    }

    /*
     * Indicates the nullability of values in the designated column.
     *
     * @param column the first column is 1, the second is 2...
     * @return one of the columnNullable values
     * @exception SQLException if a database access error occurs
     */
    public int isNullable(int column) throws SQLException
    {
        fetchFieldMetaData();
        Field field = getField(column);
        return field.getNullable();
    }

    /*
     * Is the column a signed number? In PostgreSQL, all numbers
     * are signed, so this is trivial. However, strings are not
     * signed (duh!)
     *
     * @param column the first column is 1, the second is 2...
     * @return true if so
     * @exception SQLException if a database access error occurs
     */
    public boolean isSigned(int column) throws SQLException
    {
        Field field = getField(column);
        return connection.getTypeInfo().isSigned(field.getOID());
    }

    /*
     * What is the column's normal maximum width in characters?
     *
     * @param column the first column is 1, the second is 2, etc.
     * @return the maximum width
     * @exception SQLException if a database access error occurs
     */
    public int getColumnDisplaySize(int column) throws SQLException
    {
        Field field = getField(column);
        return connection.getTypeInfo().getDisplaySize(field.getOID(), field.getMod());
    }

    /*
     * Gets the designated column's suggested title for use in printouts and
     * displays. The suggested title is usually specified by the SQL AS
     * clause. If a SQL AS is not specified, the value returned from
     * getColumnLabel will be the same as the value returned by the
     * getColumnName method.
     *
     * @param column the first column is 1, the second is 2, etc.
     * @return the column label
     * @exception SQLException if a database access error occurs
     */
    public String getColumnLabel(int column) throws SQLException
    {
        Field field = getField(column);
        return field.getColumnLabel();
    }

    /*
     * Get the designated column's name.
     *
     * @param column the first column is 1, the second is 2, etc.
     * @return the column name
     * @exception SQLException if a database access error occurs
     */
    public String getColumnName(int column) throws SQLException
    {
        fetchFieldMetaData();
        Field field = getField(column);
        return field.getColumnName();
    }

    /*
     * Get the designated column's table's schema.
     *
     * @param column the first column is 1, the second is 2...
     * @return the Schema Name
     * @exception SQLException if a database access error occurs
     */
    public String getSchemaName(int column) throws SQLException
    {
        fetchFieldMetaData();
        Field field = getField(column);
        return field.getSchemaName();
    }

    private void fetchFieldMetaData() throws SQLException {
        if (fieldInfoFetched)
            return;

        fieldInfoFetched = true;

        StringBuffer sql = new StringBuffer();
        
        if (((AbstractJdbc2Connection)connection).isFoundationDBServer()) {
            sql.append("SELECT t.table_id, c.ordinal_position, c.column_name, c.table_name, c.table_schema, c.is_nullable = 'NO', c.is_identity = 'YES'");
            sql.append(" FROM information_schema.tables t INNER JOIN information_schema.columns c USING (table_schema, table_name)");
            sql.append(" WHERE (t.table_id, c.ordinal_position) IN (");
            boolean hasSourceInfo = false;
            for (int i=0; i fields.length)
            throw new PSQLException(GT.tr("The column index is out of range: {0}, number of columns: {1}.", new Object[]{new Integer(columnIndex), new Integer(fields.length)}), PSQLState.INVALID_PARAMETER_VALUE );
        return fields[columnIndex - 1];
    }

    protected String getPGType(int columnIndex) throws SQLException
    {
        return connection.getTypeInfo().getPGType(getField(columnIndex).getOID());
    }

    protected int getSQLType(int columnIndex) throws SQLException
    {
        return connection.getTypeInfo().getSQLType(getField(columnIndex).getOID());
    }


    // ** JDBC 2 Extensions **

    // This can hook into our PG_Object mechanism
    /**
     * Returns the fully-qualified name of the Java class whose instances
     * are manufactured if the method ResultSet.getObject
     * is called to retrieve a value from the column.
     *
     * ResultSet.getObject may return a subclass of the class
     * returned by this method.
     *
     * @param column the first column is 1, the second is 2, ...
     * @return the fully-qualified name of the class in the Java programming
     *     language that would be used by the method
     *     ResultSet.getObject to retrieve the value in the specified
     *     column. This is the class name used for custom mapping.
     * @exception SQLException if a database access error occurs
     */
    public String getColumnClassName(int column) throws SQLException
    {
        Field field = getField(column);
        String result = connection.getTypeInfo().getJavaClass(field.getOID());

        if (result != null)
            return result;

        int sqlType = getSQLType(column);
        switch(sqlType) {
            case Types.ARRAY:
                return ("java.sql.Array");
            default:
                String type = getPGType(column);
                if ("unknown".equals(type)) {
                    return ("java.lang.String");
                }
                return ("java.lang.Object");
        }
    }
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy