@ -13,6 +13,8 @@ import org.postgresql.util.PSQLException;
/ * *
* This class provides information about the database as a whole .
*
* $Id : DatabaseMetaData . java , v 1 . 34 2001 / 09 / 06 03 : 20 : 30 momjian Exp $
*
* < p > Many of the methods here return lists of information in ResultSets . You
* can use the normal ResultSet methods such as getString and getInt to
* retrieve the data from these ResultSets . If a given form of metadata is
@ -677,9 +679,9 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
/ * *
* Does this driver support the ANSI - 92 entry level SQL grammar ?
* All JDBC Compliant drivers must return true . We currently
* report false until ' schema ' support is added . Then this
* should be changed to return true , since we will be mostly
* All JDBC Compliant drivers must return true . We currently
* report false until ' schema ' support is added . Then this
* should be changed to return true , since we will be mostly
* compliant ( probably more compliant than many other databases )
* And since this is a requirement for all JDBC drivers we
* need to get to the point where we can return true .
@ -1893,21 +1895,19 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
* /
public java . sql . ResultSet getColumns ( String catalog , String schemaPattern , String tableNamePattern , String columnNamePattern ) throws SQLException
{
// the field descriptors for the new ResultSet
Field f [ ] = new Field [ 18 ] ;
java . sql . ResultSet r ; // ResultSet for the SQL query that we need to do
Vector v = new Vector ( ) ; // The new ResultSet tuple stuff
f [ 0 ] = new Field ( connection , "TABLE_CAT" , iVarcharOid , 32 ) ;
f [ 1 ] = new Field ( connection , "TABLE_SCHEM" , iVarcharOid , 32 ) ;
f [ 2 ] = new Field ( connection , "TABLE_NAME" , iVarcharOid , 32 ) ;
f [ 3 ] = new Field ( connection , "COLUMN_NAME" , iVarcharOid , 32 ) ;
f [ 4 ] = new Field ( connection , "DATA_TYPE" , iInt2Oid , 2 ) ;
f [ 5 ] = new Field ( connection , "TYPE_NAME" , iVarcharOid , 32 ) ;
f [ 6 ] = new Field ( connection , "COLUMN_SIZE" , iInt4Oid , 4 ) ;
f [ 7 ] = new Field ( connection , "BUFFER_LENGTH" , iVarcharOid , 32 ) ;
f [ 8 ] = new Field ( connection , "DECIMAL_DIGITS" , iInt4Oid , 4 ) ;
f [ 9 ] = new Field ( connection , "NUM_PREC_RADIX" , iInt4Oid , 4 ) ;
Field f [ ] = new Field [ 18 ] ; // The field descriptors for the new ResultSet
f [ 0 ] = new Field ( connection , "TABLE_CAT" , iVarcharOid , 32 ) ;
f [ 1 ] = new Field ( connection , "TABLE_SCHEM" , iVarcharOid , 32 ) ;
f [ 2 ] = new Field ( connection , "TABLE_NAME" , iVarcharOid , 32 ) ;
f [ 3 ] = new Field ( connection , "COLUMN_NAME" , iVarcharOid , 32 ) ;
f [ 4 ] = new Field ( connection , "DATA_TYPE" , iInt2Oid , 2 ) ;
f [ 5 ] = new Field ( connection , "TYPE_NAME" , iVarcharOid , 32 ) ;
f [ 6 ] = new Field ( connection , "COLUMN_SIZE" , iInt4Oid , 4 ) ;
f [ 7 ] = new Field ( connection , "BUFFER_LENGTH" , iVarcharOid , 32 ) ;
f [ 8 ] = new Field ( connection , "DECIMAL_DIGITS" , iInt4Oid , 4 ) ;
f [ 9 ] = new Field ( connection , "NUM_PREC_RADIX" , iInt4Oid , 4 ) ;
f [ 10 ] = new Field ( connection , "NULLABLE" , iInt4Oid , 4 ) ;
f [ 11 ] = new Field ( connection , "REMARKS" , iVarcharOid , 32 ) ;
f [ 12 ] = new Field ( connection , "COLUMN_DEF" , iVarcharOid , 32 ) ;
@ -1917,89 +1917,107 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
f [ 16 ] = new Field ( connection , "ORDINAL_POSITION" , iInt4Oid , 4 ) ;
f [ 17 ] = new Field ( connection , "IS_NULLABLE" , iVarcharOid , 32 ) ;
// Added by Stefan Andreasen <stefan@linux.kapow.dk>
// If the pattern are null then set them to %
if ( tableNamePattern = = null ) tableNamePattern = "%" ;
if ( columnNamePattern = = null ) columnNamePattern = "%" ;
// Now form the query
String query =
"select " +
( connection . haveMinimumServerVersion ( "7.2" ) ? "a.attrelid" : "a.oid" ) +
",c.relname,a.attname,a.atttypid," +
"a.attnum,a.attnotnull,a.attlen,a.atttypmod,d.adsrc from pg_class c," +
"pg_attribute a,pg_attrdef d where a.attrelid=c.oid and " +
"c.relname like '" + tableNamePattern . toLowerCase ( ) + "' and " +
"a.attname like '" + columnNamePattern . toLowerCase ( ) + "' and " +
"a.attnum>0 and c.oid=d.adrelid and d.adnum=a.attnum " +
"order by c.relname,a.attnum" ;
r = connection . ExecSQL ( query ) ;
while ( r . next ( ) ) {
byte [ ] [ ] tuple = new byte [ 18 ] [ 0 ] ;
// Fetch the description for the table (if any)
String getDescriptionStatement =
connection . haveMinimumServerVersion ( "7.2" ) ?
"select col_description(" + r . getInt ( 1 ) + "," + r . getInt ( 5 ) + ")" :
"select description from pg_description where objoid=" + r . getInt ( 1 ) ;
java . sql . ResultSet dr = connection . ExecSQL ( getDescriptionStatement ) ;
if ( ( ( org . postgresql . ResultSet ) dr ) . getTupleCount ( ) = = 1 ) {
dr . next ( ) ;
tuple [ 11 ] = dr . getBytes ( 1 ) ;
} else
tuple [ 11 ] = null ;
dr . close ( ) ;
tuple [ 0 ] = "" . getBytes ( ) ; // Catalog name
tuple [ 1 ] = "" . getBytes ( ) ; // Schema name
tuple [ 2 ] = r . getBytes ( 2 ) ; // Table name
tuple [ 3 ] = r . getBytes ( 3 ) ; // Column name
dr = connection . ExecSQL ( "select typname from pg_type where oid = " + r . getString ( 4 ) ) ;
dr . next ( ) ;
String typname = dr . getString ( 1 ) ;
dr . close ( ) ;
tuple [ 4 ] = Integer . toString ( connection . getSQLType ( typname ) ) . getBytes ( ) ; // Data type
tuple [ 5 ] = typname . getBytes ( ) ; // Type name
// Column size
// Looking at the psql source,
// I think the length of a varchar as specified when the table was created
// should be extracted from atttypmod which contains this length + sizeof(int32)
if ( typname . equals ( "bpchar" ) | | typname . equals ( "varchar" ) ) {
int atttypmod = r . getInt ( 8 ) ;
tuple [ 6 ] = Integer . toString ( atttypmod ! = - 1 ? atttypmod - VARHDRSZ : 0 ) . getBytes ( ) ;
} else
tuple [ 6 ] = r . getBytes ( 7 ) ;
tuple [ 7 ] = null ; // Buffer length
tuple [ 8 ] = "0" . getBytes ( ) ; // Decimal Digits - how to get this?
tuple [ 9 ] = "10" . getBytes ( ) ; // Num Prec Radix - assume decimal
// tuple[10] is below
// tuple[11] is above
tuple [ 12 ] = r . getBytes ( 9 ) ; // column default
tuple [ 13 ] = null ; // sql data type (unused)
tuple [ 14 ] = null ; // sql datetime sub (unused)
StringBuffer sql = new StringBuffer ( 512 ) ;
sql . append ( "select " +
( connection . haveMinimumServerVersion ( "7.2" ) ? "a.attrelid, " : "a.oid, " ) +
" c.relname, " +
" a.attname, " +
" a.atttypid, " +
" a.attnum, " +
" a.attnotnull, " +
" a.attlen, " +
" a.atttypmod, " +
" d.adsrc, " +
" t.typname, " +
" e.description " +
"from" +
" (" +
" (pg_class c inner join pg_attribute a on" +
" (" +
" a.attrelid=c.oid" ) ;
if ( ( tableNamePattern ! = null ) & & ! tableNamePattern . equals ( "%" ) ) {
sql . append ( " and c.relname like \'" + tableNamePattern + "\'" ) ;
}
tuple [ 15 ] = tuple [ 6 ] ; // char octet length
if ( ( columnNamePattern ! = null ) & & ! columnNamePattern . equals ( "%" ) ) {
sql . append ( " and a.attname like \'" + columnNamePattern + "\'" ) ;
}
tuple [ 16 ] = r . getBytes ( 5 ) ; // ordinal position
sql . append (
" and a.attnum > 0" +
" )" +
" ) inner join pg_type t on" +
" (" +
" t.oid = a.atttypid" +
" )" +
" )" +
" left outer join pg_attrdef d on" +
" (" +
" c.oid = d.adrelid" +
" and a.attnum = d.adnum" +
" )" +
" left outer join pg_description e on" +
" (" +
" e.objoid = a.attrelid" ) ;
if ( connection . haveMinimumServerVersion ( "7.2" ) ) {
sql . append (
" and e.objsubid = a.attnum" +
" and e.classoid = (select oid from pg_class where relname = \'pg_class\')" ) ;
}
String nullFlag = r . getString ( 6 ) ;
tuple [ 10 ] = Integer . toString ( nullFlag . equals ( "f" ) ? java . sql . DatabaseMetaData . columnNullable : java . sql . DatabaseMetaData . columnNoNulls ) . getBytes ( ) ; // Nullable
tuple [ 17 ] = ( nullFlag . equals ( "f" ) ? "YES" : "NO" ) . getBytes ( ) ; // is nullable
sql . append (
" ) " +
"order by" +
" c.relname, a.attnum" ) ;
System . out . println ( sql ) ;
java . sql . ResultSet r = connection . ExecSQL ( sql . toString ( ) ) ;
while ( r . next ( ) ) {
byte [ ] [ ] tuple = new byte [ 18 ] [ 0 ] ;
String nullFlag = r . getString ( 6 ) ;
String typname = r . getString ( 10 ) ;
tuple [ 0 ] = "" . getBytes ( ) ; // Catalog name
tuple [ 1 ] = "" . getBytes ( ) ; // Schema name
tuple [ 2 ] = r . getBytes ( 2 ) ; // Table name
tuple [ 3 ] = r . getBytes ( 3 ) ; // Column name
tuple [ 4 ] = Integer . toString ( connection . getSQLType ( typname ) ) . getBytes ( ) ; // Data type
tuple [ 5 ] = typname . getBytes ( ) ; // Type name
// Column size
// Looking at the psql source,
// I think the length of a varchar as specified when the table was created
// should be extracted from atttypmod which contains this length + sizeof(int32)
if ( typname . equals ( "bpchar" ) | | typname . equals ( "varchar" ) ) {
int atttypmod = r . getInt ( 8 ) ;
tuple [ 6 ] = Integer . toString ( atttypmod ! = - 1 ? atttypmod - VARHDRSZ : 0 ) . getBytes ( ) ;
} else {
tuple [ 6 ] = r . getBytes ( 7 ) ;
}
tuple [ 7 ] = null ; // Buffer length
tuple [ 8 ] = "0" . getBytes ( ) ; // Decimal Digits - how to get this?
tuple [ 9 ] = "10" . getBytes ( ) ; // Num Prec Radix - assume decimal
tuple [ 10 ] = Integer . toString ( nullFlag . equals ( "f" ) ?
java . sql . DatabaseMetaData . columnNullable :
java . sql . DatabaseMetaData . columnNoNulls ) . getBytes ( ) ; // Nullable
tuple [ 11 ] = r . getBytes ( 11 ) ; // Description (if any)
tuple [ 12 ] = r . getBytes ( 9 ) ; // Column default
tuple [ 13 ] = null ; // sql data type (unused)
tuple [ 14 ] = null ; // sql datetime sub (unused)
tuple [ 15 ] = tuple [ 6 ] ; // char octet length
tuple [ 16 ] = r . getBytes ( 5 ) ; // ordinal position
tuple [ 17 ] = ( nullFlag . equals ( "f" ) ? "YES" : "NO" ) . getBytes ( ) ; // Is nullable
v . addElement ( tuple ) ;
}
r . close ( ) ;
v . addElement ( tuple ) ;
}
r . close ( ) ;
return new ResultSet ( connection , f , v , "OK" , 1 ) ;
}
@ -2387,9 +2405,9 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
"from pg_class as c, pg_trigger as t " +
"where c.relname like '" + table + "' and c.relfilenode=t.tgrelid" ) ;
Vector tuples = new Vector ( ) ;
while ( rs . next ( ) ) {
tuples . addAll ( importLoop ( rs ) ) ;
tuples . addAll ( importLoop ( rs ) ) ;
}
rsret = new ResultSet ( connection , f , tuples , "OK" , 1 ) ;
@ -2707,7 +2725,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
" AND (i.oid = x.indexrelid) " +
" AND (i.relam = a.oid)) " +
"ORDER BY x.indisunique DESC, " +
" x.indisclustered, a.amname, i.relname" ) ;
" x.indisclustered, a.amname, i.relname" ) ;
while ( r . next ( ) ) {
// indkey is an array of column ordinals (integers). In the JDBC
// interface, this has to be separated out into a separate
@ -2722,7 +2740,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
}
for ( int i = 0 ; i < columnOrdinals . length ; i + + ) {
byte [ ] [ ] tuple = new byte [ 13 ] [ ] ;
tuple [ 0 ] = "" . getBytes ( ) ;
tuple [ 0 ] = "" . getBytes ( ) ;
tuple [ 1 ] = "" . getBytes ( ) ;
tuple [ 2 ] = r . getBytes ( 1 ) ;
tuple [ 3 ] = r . getBoolean ( 2 ) ? "f" . getBytes ( ) : "t" . getBytes ( ) ;