1
0
mirror of https://github.com/postgres/postgres.git synced 2025-04-27 22:56:53 +03:00
postgres/src/interfaces/jdbc/org/postgresql/jdbc1/ResultSetMetaData.java
2001-11-19 23:16:46 +00:00

477 lines
13 KiB
Java

package org.postgresql.jdbc1;
// IMPORTANT NOTE: This file implements the JDBC 1 version of the driver.
// If you make any modifications to this file, you must make sure that the
// changes are also made (if relevent) to the related JDBC 2 class in the
// org.postgresql.jdbc2 package.
import java.lang.*;
import java.util.*;
import org.postgresql.*;
import org.postgresql.util.*;
// We explicitly import classes here as the original line:
//import java.sql.*;
// causes javac to get confused.
import java.sql.SQLException;
import java.sql.Types;
/*
* A ResultSetMetaData object can be used to find out about the types and
* properties of the columns in a ResultSet
*
* @see java.sql.ResultSetMetaData
*/
public class ResultSetMetaData implements java.sql.ResultSetMetaData
{
Vector rows;
Field[] fields;
/*
* Initialise for a result with a tuple set and
* a field descriptor set
*
* @param rows the Vector of rows returned by the ResultSet
* @param fields the array of field descriptors
*/
public ResultSetMetaData(Vector rows, Field[] fields)
{
this.rows = rows;
this.fields = fields;
}
/*
* 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
{
return false;
}
/*
* 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
{
int sql_type = getField(column).getSQLType();
switch (sql_type)
{
case Types.SMALLINT:
case Types.INTEGER:
case Types.FLOAT:
case Types.REAL:
case Types.DOUBLE:
case Types.DATE:
case Types.TIME:
case Types.TIMESTAMP:
return false;
default:
return true;
}
}
/*
* 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
{
int sql_type = getField(column).getSQLType();
// This switch is pointless, I know - but it is a set-up
// for further expansion.
switch (sql_type)
{
case Types.OTHER:
return true;
default:
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 = getField(column).getPGType();
return 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
{
/*
* TODO This needs a real implementation, taking into account columns
* defined with NOT NULL or PRIMARY KEY, CHECK constraints, views,
* functions etc.
*/
return columnNullableUnknown;
}
/*
* 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
{
int sql_type = getField(column).getSQLType();
switch (sql_type)
{
case Types.SMALLINT:
case Types.INTEGER:
case Types.FLOAT:
case Types.REAL:
case Types.DOUBLE:
return true;
case Types.DATE:
case Types.TIME:
case Types.TIMESTAMP:
return false; // I don't know about these?
default:
return false;
}
}
/*
* 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 f = getField(column);
String type_name = f.getPGType();
int sql_type = f.getSQLType();
int typmod = f.getMod();
// I looked at other JDBC implementations and couldn't find a consistent
// interpretation of the "display size" for numeric values, so this is our's
// FIXME: currently, only types with a SQL92 or SQL3 pendant are implemented - jens@jens.de
// fixed length data types
if (type_name.equals( "int2" ))
return 6; // -32768 to +32768 (5 digits and a sign)
if (type_name.equals( "int4" )
|| type_name.equals( "oid" ))
return 11; // -2147483648 to +2147483647
if (type_name.equals( "int8" ))
return 20; // -9223372036854775808 to +9223372036854775807
if (type_name.equals( "money" ))
return 12; // MONEY = DECIMAL(9,2)
if (type_name.equals( "float4" ))
return 11; // i checked it out ans wasn't able to produce more than 11 digits
if (type_name.equals( "float8" ))
return 20; // dito, 20
if (type_name.equals( "char" ))
return 1;
if (type_name.equals( "bool" ))
return 1;
if (type_name.equals( "date" ))
return 14; // "01/01/4713 BC" - "31/12/32767 AD"
if (type_name.equals( "time" ))
return 8; // 00:00:00-23:59:59
if (type_name.equals( "timestamp" ))
return 22; // hhmmm ... the output looks like this: 1999-08-03 22:22:08+02
// variable length fields
typmod -= 4;
if (type_name.equals( "bpchar" )
|| type_name.equals( "varchar" ))
return typmod; // VARHDRSZ=sizeof(int32)=4
if (type_name.equals( "numeric" ))
return ( (typmod >> 16) & 0xffff )
+ 1 + ( typmod & 0xffff ); // DECIMAL(p,s) = (p digits).(s digits)
// if we don't know better
return f.getLength();
}
/*
* What is the suggested column title for use in printouts and
* displays? We suggest the ColumnName!
*
* @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
{
return getColumnName(column);
}
/*
* 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
{
Field f = getField(column);
if (f != null)
return f.getName();
return "field" + column;
}
/*
* What is a column's table's schema? This relies on us knowing
* the table name....which I don't know how to do as yet. The
* JDBC specification allows us to return "" if this is not
* applicable.
*
* @param column the first column is 1, the second is 2...
* @return the Schema
* @exception SQLException if a database access error occurs
*/
public String getSchemaName(int column) throws SQLException
{
return "";
}
/*
* What is a column's number of decimal digits.
*
* @param column the first column is 1, the second is 2...
* @return the precision
* @exception SQLException if a database access error occurs
*/
public int getPrecision(int column) throws SQLException
{
int sql_type = getField(column).getSQLType();
switch (sql_type)
{
case Types.SMALLINT:
return 5;
case Types.INTEGER:
return 10;
case Types.REAL:
return 8;
case Types.FLOAT:
return 16;
case Types.DOUBLE:
return 16;
case Types.VARCHAR:
return 0;
case Types.NUMERIC:
Field f = getField(column);
if (f != null)
return ((0xFFFF0000)&f.getMod()) >> 16;
else
return 0;
default:
return 0;
}
}
/*
* What is a column's number of digits to the right of the
* decimal point?
*
* @param column the first column is 1, the second is 2...
* @return the scale
* @exception SQLException if a database access error occurs
*/
public int getScale(int column) throws SQLException
{
int sql_type = getField(column).getSQLType();
switch (sql_type)
{
case Types.SMALLINT:
return 0;
case Types.INTEGER:
return 0;
case Types.REAL:
return 8;
case Types.FLOAT:
return 16;
case Types.DOUBLE:
return 16;
case Types.VARCHAR:
return 0;
case Types.NUMERIC:
Field f = getField(column);
if (f != null)
return (((0x0000FFFF)&f.getMod()) - 4);
else
return 0;
default:
return 0;
}
}
/*
* Whats a column's table's name? How do I find this out? Both
* getSchemaName() and getCatalogName() rely on knowing the table
* Name, so we need this before we can work on them.
*
* @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 "";
}
/*
* What's a column's table's catalog name? As with getSchemaName(),
* we can say that if getTableName() returns n/a, then we can too -
* otherwise, we need to work on it.
*
* @param column the first column is 1, the second is 2...
* @return catalog name, or "" if not applicable
* @exception SQLException if a database access error occurs
*/
public String getCatalogName(int column) throws SQLException
{
return "";
}
/*
* What is a column's SQL Type? (java.sql.Type int)
*
* @param column the first column is 1, the second is 2, etc.
* @return the java.sql.Type value
* @exception SQLException if a database access error occurs
* @see org.postgresql.Field#getSQLType
* @see java.sql.Types
*/
public int getColumnType(int column) throws SQLException
{
return getField(column).getSQLType();
}
/*
* Whats is the column's data source specific type name?
*
* @param column the first column is 1, the second is 2, etc.
* @return the type name
* @exception SQLException if a database access error occurs
*/
public String getColumnTypeName(int column) throws SQLException
{
return getField(column).getPGType();
}
/*
* Is the column definitely not writable? In reality, we would
* have to check the GRANT/REVOKE stuff for this to be effective,
* and I haven't really looked into that yet, so this will get
* re-visited.
*
* @param column the first column is 1, the second is 2, etc.
* @return true if so
* @exception SQLException if a database access error occurs
*/
public boolean isReadOnly(int column) throws SQLException
{
return false;
}
/*
* Is it possible for a write on the column to succeed? Again, we
* would in reality have to check the GRANT/REVOKE stuff, which
* I haven't worked with as yet. However, if it isn't ReadOnly, then
* it is obviously writable.
*
* @param column the first column is 1, the second is 2, etc.
* @return true if so
* @exception SQLException if a database access error occurs
*/
public boolean isWritable(int column) throws SQLException
{
return !isReadOnly(column);
}
/*
* Will a write on this column definately succeed? Hmmm...this
* is a bad one, since the two preceding functions have not been
* really defined. I cannot tell is the short answer. I thus
* return isWritable() just to give us an idea.
*
* @param column the first column is 1, the second is 2, etc..
* @return true if so
* @exception SQLException if a database access error occurs
*/
public boolean isDefinitelyWritable(int column) throws SQLException
{
return false;
}
// ********************************************************
// END OF PUBLIC INTERFACE
// ********************************************************
/*
* For several routines in this package, we need to convert
* a columnIndex into a Field[] descriptor. Rather than do
* the same code several times, here it is.
*
* @param columnIndex the first column is 1, the second is 2...
* @return the Field description
* @exception SQLException if a database access error occurs
*/
private Field getField(int columnIndex) throws SQLException
{
if (columnIndex < 1 || columnIndex > fields.length)
throw new PSQLException("postgresql.res.colrange");
return fields[columnIndex - 1];
}
}