mirror of
https://github.com/postgres/postgres.git
synced 2025-05-11 05:41:32 +03:00
Modified Files: jdbc/org/postgresql/Driver.java.in jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java jdbc/org/postgresql/jdbc1/Jdbc1Connection.java jdbc/org/postgresql/jdbc1/Jdbc1ResultSet.java jdbc/org/postgresql/jdbc2/Jdbc2Connection.java jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java Added Files: jdbc/org/postgresql/jdbc1/AbstractJdbc1DatabaseMetaData.java jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSetMetaData.java jdbc/org/postgresql/jdbc1/Jdbc1DatabaseMetaData.java jdbc/org/postgresql/jdbc1/Jdbc1ResultSetMetaData.java jdbc/org/postgresql/jdbc2/AbstractJdbc2DatabaseMetaData.java jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSetMetaData.java jdbc/org/postgresql/jdbc2/Jdbc2DatabaseMetaData.java jdbc/org/postgresql/jdbc2/Jdbc2ResultSetMetaData.java Removed Files: jdbc/org/postgresql/jdbc1/DatabaseMetaData.java jdbc/org/postgresql/jdbc1/ResultSetMetaData.java jdbc/org/postgresql/jdbc2/DatabaseMetaData.java jdbc/org/postgresql/jdbc2/ResultSetMetaData.java
554 lines
15 KiB
Java
554 lines
15 KiB
Java
package org.postgresql.jdbc2;
|
|
|
|
|
|
import java.lang.*;
|
|
import java.sql.*;
|
|
import java.util.*;
|
|
import org.postgresql.*;
|
|
import org.postgresql.util.*;
|
|
|
|
public abstract class AbstractJdbc2ResultSetMetaData extends org.postgresql.jdbc1.AbstractJdbc1ResultSetMetaData
|
|
{
|
|
|
|
/*
|
|
* 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 AbstractJdbc2ResultSetMetaData(Vector rows, Field[] fields)
|
|
{
|
|
super(rows, 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 java.sql.ResultSetMetaData.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];
|
|
}
|
|
|
|
// ** 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 <code>ResultSet.getObject</code>
|
|
* is called to retrieve a value from the column.
|
|
*
|
|
* <code>ResultSet.getObject</code> 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
|
|
* <code>ResultSet.getObject</code> 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
|
|
{
|
|
/*
|
|
The following data type mapping came from ../Field.java.
|
|
|
|
"int2",
|
|
"int4","oid",
|
|
"int8",
|
|
"cash","money",
|
|
"numeric",
|
|
"float4",
|
|
"float8",
|
|
"bpchar","char","char2","char4","char8","char16",
|
|
"varchar","text","name","filename",
|
|
"bool",
|
|
"date",
|
|
"time",
|
|
"abstime","timestamp"
|
|
|
|
Types.SMALLINT,
|
|
Types.INTEGER,Types.INTEGER,
|
|
Types.BIGINT,
|
|
Types.DOUBLE,Types.DOUBLE,
|
|
Types.NUMERIC,
|
|
Types.REAL,
|
|
Types.DOUBLE,
|
|
Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,
|
|
Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,
|
|
Types.BIT,
|
|
Types.DATE,
|
|
Types.TIME,
|
|
Types.TIMESTAMP,Types.TIMESTAMP
|
|
*/
|
|
|
|
Field field = getField(column);
|
|
int sql_type = field.getSQLType();
|
|
|
|
switch (sql_type)
|
|
{
|
|
case Types.BIT:
|
|
return("java.lang.Boolean");
|
|
case Types.SMALLINT:
|
|
return("java.lang.Short");
|
|
case Types.INTEGER:
|
|
return("java.lang.Integer");
|
|
case Types.BIGINT:
|
|
return("java.lang.Long");
|
|
case Types.NUMERIC:
|
|
return("java.math.BigDecimal");
|
|
case Types.REAL:
|
|
return("java.lang.Float");
|
|
case Types.DOUBLE:
|
|
return("java.lang.Double");
|
|
case Types.CHAR:
|
|
case Types.VARCHAR:
|
|
return("java.lang.String");
|
|
case Types.DATE:
|
|
return("java.sql.Date");
|
|
case Types.TIME:
|
|
return("java.sql.Time");
|
|
case Types.TIMESTAMP:
|
|
return("java.sql.Timestamp");
|
|
case Types.BINARY:
|
|
case Types.VARBINARY:
|
|
return("[B");
|
|
case Types.ARRAY:
|
|
return("java.sql.Array");
|
|
default:
|
|
String type = field.getPGType();
|
|
if ("unknown".equals(type))
|
|
{
|
|
return("java.lang.String");
|
|
}
|
|
return("java.lang.Object");
|
|
}
|
|
}
|
|
}
|
|
|