org.postgresql.jdbc2.AbstractJdbc2ResultSetMetaData Maven / Gradle / Ivy
/*-------------------------------------------------------------------------
*
* Copyright (c) 2004-2011, PostgreSQL Global Development Group
*
*
*-------------------------------------------------------------------------
*/
package org.postgresql.jdbc2;
import org.postgresql.PGResultSetMetaData;
import org.postgresql.core.*;
import org.postgresql.util.PSQLException;
import org.postgresql.util.PSQLState;
import java.sql.*;
import org.postgresql.util.GT;
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());
}
/*
* @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();
}
/*
* What's a 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
{
return getColumnLabel(column);
}
public String getBaseColumnName(int column) throws SQLException {
fetchFieldMetaData();
Field field = getField(column);
return field.getColumnName();
}
/*
* @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
{
return "";
}
private void fetchFieldMetaData() throws SQLException {
if (fieldInfoFetched)
return;
fieldInfoFetched = true;
StringBuffer sql = new StringBuffer();
// Not supported in FoundationDB SQL Layer
if (((AbstractJdbc2Connection)connection).isFoundationDBServer()) {
sql.append("SELECT 1 FROM information_schema.tables WHERE 1 = 0");
} else {
sql.append("SELECT c.oid, a.attnum, a.attname, c.relname, n.nspname, ");
sql.append("a.attnotnull OR (t.typtype = 'd' AND t.typnotnull), ");
sql.append("pg_catalog.pg_get_expr(d.adbin, d.adrelid) LIKE '%nextval(%' ");
sql.append("FROM pg_catalog.pg_class c ");
sql.append("JOIN pg_catalog.pg_namespace n ON (c.relnamespace = n.oid) ");
sql.append("JOIN pg_catalog.pg_attribute a ON (c.oid = a.attrelid) ");
sql.append("JOIN pg_catalog.pg_type t ON (a.atttypid = t.oid) ");
sql.append("LEFT JOIN pg_catalog.pg_attrdef d ON (d.adrelid = a.attrelid AND d.adnum = a.attnum) ");
sql.append("JOIN (");
// 7.4 servers don't support row IN operations (a,b) IN ((c,d),(e,f))
// so we've got to fake that with a JOIN here.
//
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 - 2025 Weber Informatics LLC | Privacy Policy