summaryrefslogtreecommitdiff
path: root/src/interfaces/jdbc/postgresql/DatabaseMetaData.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/jdbc/postgresql/DatabaseMetaData.java')
-rw-r--r--src/interfaces/jdbc/postgresql/DatabaseMetaData.java452
1 files changed, 392 insertions, 60 deletions
diff --git a/src/interfaces/jdbc/postgresql/DatabaseMetaData.java b/src/interfaces/jdbc/postgresql/DatabaseMetaData.java
index b5e8a985fb2..4e3894f66b6 100644
--- a/src/interfaces/jdbc/postgresql/DatabaseMetaData.java
+++ b/src/interfaces/jdbc/postgresql/DatabaseMetaData.java
@@ -4,17 +4,14 @@ import java.sql.*;
import java.util.*;
/**
- * @version 1.0 15-APR-1997
- * @author <A HREF="mailto:[email protected]">Adrian Hall</A>
- *
* This class provides information about the database as a whole.
*
- * Many of the methods here return lists of information in ResultSets. You
+ * <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
* not available, these methods should throw a SQLException.
*
- * Some of these methods take arguments that are String patterns. These
+ * <p>Some of these methods take arguments that are String patterns. These
* arguments all have names such as fooPattern. Within a pattern String,
* "%" means match any substring of 0 or more characters, and "_" means
* match any one character. Only metadata entries matching the search
@@ -22,7 +19,7 @@ import java.util.*;
* ref, it means that argument's criteria should be dropped from the
* search.
*
- * A SQLException will be throws if a driver does not support a meta
+ * <p>A SQLException will be throws if a driver does not support a meta
* data method. In the case of methods that return a ResultSet, either
* a ResultSet (which may be empty) is returned or a SQLException is
* thrown.
@@ -33,6 +30,12 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
{
Connection connection; // The connection association
+ // These define various OID's. Hopefully they will stay constant.
+ static final int iVarcharOid = 1043; // OID for varchar
+ static final int iBoolOid = 16; // OID for bool
+ static final int iInt2Oid = 21; // OID for int2
+ static final int iInt4Oid = 23; // OID for int4
+
public DatabaseMetaData(Connection conn)
{
this.connection = conn;
@@ -152,19 +155,21 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
}
/**
- * What is the version of this database product. Note that
- * PostgreSQL 6.1 has a system catalog called pg_version -
+ * What is the version of this database product.
+ *
+ * <p>Note that PostgreSQL 6.3 has a system catalog called pg_version -
* however, select * from pg_version on any database retrieves
- * no rows. For now, we will return the version 6.1 (in the
- * hopes that we change this driver as often as we change the
- * database)
+ * no rows.
+ *
+ * <p>For now, we will return the version 6.3 (in the hope that we change
+ * this driver as often as we change the database)
*
* @return the database version
* @exception SQLException if a database access error occurs
*/
public String getDatabaseProductVersion() throws SQLException
{
- return ("6.2");
+ return ("6.3");
}
/**
@@ -240,7 +245,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
* as case sensitive and as a result store them in mixed case?
* A JDBC-Compliant driver will always return false.
*
- * Predicament - what do they mean by "SQL identifiers" - if it
+ * <p>Predicament - what do they mean by "SQL identifiers" - if it
* means the names of the tables and columns, then the answers
* given below are correct - otherwise I don't know.
*
@@ -290,7 +295,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
* case sensitive and as a result store them in mixed case? A
* JDBC compliant driver will always return true.
*
- * Predicament - what do they mean by "SQL identifiers" - if it
+ * <p>Predicament - what do they mean by "SQL identifiers" - if it
* means the names of the tables and columns, then the answers
* given below are correct - otherwise I don't know.
*
@@ -340,7 +345,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
* a space if identifier quoting isn't supported. A JDBC Compliant
* driver will always use a double quote character.
*
- * If an SQL identifier is a table name, column name, etc. then
+ * <p>If an SQL identifier is a table name, column name, etc. then
* we do not support it.
*
* @return the quoting string
@@ -355,10 +360,12 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
* Get a comma separated list of all a database's SQL keywords that
* are NOT also SQL92 keywords.
*
- * Within PostgreSQL, the keywords are found in
+ * <p>Within PostgreSQL, the keywords are found in
* src/backend/parser/keywords.c
- * For SQL Keywords, I took the list provided at
- * http://web.dementia.org/~shadow/sql/sql3bnf.sep93.txt
+ *
+ * <p>For SQL Keywords, I took the list provided at
+ * <a href="http://web.dementia.org/~shadow/sql/sql3bnf.sep93.txt">
+ * http://web.dementia.org/~shadow/sql/sql3bnf.sep93.txt</a>
* which is for SQL3, not SQL-92, but it is close enough for
* this purpose.
*
@@ -410,7 +417,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
* Get all the "extra" characters that can bew used in unquoted
* identifier names (those beyond a-zA-Z0-9 and _)
*
- * From the file src/backend/parser/scan.l, an identifier is
+ * <p>From the file src/backend/parser/scan.l, an identifier is
* {letter}{letter_or_digit} which makes it just those listed
* above.
*
@@ -449,14 +456,16 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
/**
* Is column aliasing supported?
*
- * If so, the SQL AS clause can be used to provide names for
+ * <p>If so, the SQL AS clause can be used to provide names for
* computed columns or to provide alias names for columns as
* required. A JDBC Compliant driver always returns true.
*
- * e.g.
+ * <p>e.g.
*
+ * <br><pre>
* select count(C) as C_COUNT from T group by C;
*
+ * </pre><br>
* should return a column named as C_COUNT instead of count(C)
*
* @return true if so
@@ -506,7 +515,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
/**
* Are expressions in "ORCER BY" lists supported?
*
- * e.g. select * from t order by a + b;
+ * <br>e.g. select * from t order by a + b;
*
* @return true if so
* @exception SQLException if a database access error occurs
@@ -607,7 +616,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
* Can columns be defined as non-nullable. A JDBC Compliant driver
* always returns true.
*
- * This changed from false to true in v6.2 of the driver, as this
+ * <p>This changed from false to true in v6.2 of the driver, as this
* support was added to the backend.
*
* @return true if so
@@ -622,9 +631,9 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
* Does this driver support the minimum ODBC SQL grammar. This
* grammar is defined at:
*
- * http://www.microsoft.com/msdn/sdk/platforms/doc/odbc/src/intropr.htm
+ * <p><a href="http://www.microsoft.com/msdn/sdk/platforms/doc/odbc/src/intropr.htm">http://www.microsoft.com/msdn/sdk/platforms/doc/odbc/src/intropr.htm</a>
*
- * In Appendix C. From this description, we seem to support the
+ * <p>In Appendix C. From this description, we seem to support the
* ODBC minimal (Level 0) grammar.
*
* @return true if so
@@ -1142,7 +1151,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
* What is the maximum number of columns in a table? From the
* create_table(l) manual page...
*
- * "The new class is created as a heap with no initial data. A
+ * <p>"The new class is created as a heap with no initial data. A
* class can have no more than 1600 attributes (realistically,
* this is limited by the fact that tuple sizes must be less than
* 8192 bytes)..."
@@ -1393,6 +1402,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
* Does a data definition statement within a transaction force
* the transaction to commit? I think this means something like:
*
+ * <p><pre>
* CREATE TABLE T (A INT);
* INSERT INTO T (A) VALUES (2);
* BEGIN;
@@ -1400,6 +1410,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
* CREATE TABLE X (A INT);
* SELECT A FROM T INTO X;
* COMMIT;
+ * </pre><p>
*
* does the CREATE TABLE call cause a commit? The answer is no.
*
@@ -1412,7 +1423,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
}
/**
- * Is a data definition statement within a transaction ignored?
+ * Is a data definition statement within a transaction ignored?
* It seems to be (from experiment in previous method)
*
* @return true if so
@@ -1426,22 +1437,26 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
/**
* Get a description of stored procedures available in a catalog
*
- * Only procedure descriptions matching the schema and procedure
+ * <p>Only procedure descriptions matching the schema and procedure
* name criteria are returned. They are ordered by PROCEDURE_SCHEM
* and PROCEDURE_NAME
*
- * Each procedure description has the following columns:
- * PROCEDURE_CAT String => procedure catalog (may be null)
- * PROCEDURE_SCHEM String => procedure schema (may be null)
- * PROCEDURE_NAME String => procedure name
- * Field 4 reserved (make it null)
- * Field 5 reserved (make it null)
- * Field 6 reserved (make it null)
- * REMARKS String => explanatory comment on the procedure
- * PROCEDURE_TYPE short => kind of procedure
- * * procedureResultUnknown - May return a result
- * * procedureNoResult - Does not return a result
- * * procedureReturnsResult - Returns a result
+ * <p>Each procedure description has the following columns:
+ * <ol>
+ * <li><b>PROCEDURE_CAT</b> String => procedure catalog (may be null)
+ * <li><b>PROCEDURE_SCHEM</b> String => procedure schema (may be null)
+ * <li><b>PROCEDURE_NAME</b> String => procedure name
+ * <li><b>Field 4</b> reserved (make it null)
+ * <li><b>Field 5</b> reserved (make it null)
+ * <li><b>Field 6</b> reserved (make it null)
+ * <li><b>REMARKS</b> String => explanatory comment on the procedure
+ * <li><b>PROCEDURE_TYPE</b> short => kind of procedure
+ * <ul>
+ * <li> procedureResultUnknown - May return a result
+ * <li> procedureNoResult - Does not return a result
+ * <li> procedureReturnsResult - Returns a result
+ * </ul>
+ * </ol>
*
* @param catalog - a catalog name; "" retrieves those without a
* catalog; null means drop catalog name from criteria
@@ -1451,8 +1466,6 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
* @return ResultSet - each row is a procedure description
* @exception SQLException if a database access error occurs
*/
- static final int iVarcharOid = 1043; // This is the OID for a varchar()
- static final int iInt2Oid = 21; // This is the OID for an int2
public java.sql.ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException
{
// the field descriptors for the new ResultSet
@@ -1497,17 +1510,183 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
return new ResultSet(connection, f, v, "OK", 1);
}
+ /**
+ * Get a description of a catalog's stored procedure parameters
+ * and result columns.
+ *
+ * <p>Only descriptions matching the schema, procedure and parameter
+ * name criteria are returned. They are ordered by PROCEDURE_SCHEM
+ * and PROCEDURE_NAME. Within this, the return value, if any, is
+ * first. Next are the parameter descriptions in call order. The
+ * column descriptions follow in column number order.
+ *
+ * <p>Each row in the ResultSet is a parameter description or column
+ * description with the following fields:
+ * <ol>
+ * <li><b>PROCEDURE_CAT</b> String => procedure catalog (may be null)
+ * <li><b>PROCEDURE_SCHE</b>M String => procedure schema (may be null)
+ * <li><b>PROCEDURE_NAME</b> String => procedure name
+ * <li><b>COLUMN_NAME</b> String => column/parameter name
+ * <li><b>COLUMN_TYPE</b> Short => kind of column/parameter:
+ * <ul><li>procedureColumnUnknown - nobody knows
+ * <li>procedureColumnIn - IN parameter
+ * <li>procedureColumnInOut - INOUT parameter
+ * <li>procedureColumnOut - OUT parameter
+ * <li>procedureColumnReturn - procedure return value
+ * <li>procedureColumnResult - result column in ResultSet
+ * </ul>
+ * <li><b>DATA_TYPE</b> short => SQL type from java.sql.Types
+ * <li><b>TYPE_NAME</b> String => SQL type name
+ * <li><b>PRECISION</b> int => precision
+ * <li><b>LENGTH</b> int => length in bytes of data
+ * <li><b>SCALE</b> short => scale
+ * <li><b>RADIX</b> short => radix
+ * <li><b>NULLABLE</b> short => can it contain NULL?
+ * <ul><li>procedureNoNulls - does not allow NULL values
+ * <li>procedureNullable - allows NULL values
+ * <li>procedureNullableUnknown - nullability unknown
+ * <li><b>REMARKS</b> String => comment describing parameter/column
+ * </ol>
+ * @param catalog This is ignored in postgresql, advise this is set to null
+ * @param schemaPattern This is ignored in postgresql, advise this is set to null
+ * @param procedureNamePattern a procedure name pattern
+ * @param columnNamePattern a column name pattern
+ * @return each row is a stored procedure parameter or column description
+ * @exception SQLException if a database-access error occurs
+ * @see #getSearchStringEscape
+ */
+ // Implementation note: This is required for Borland's JBuilder to work
public java.sql.ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException
{
- // XXX-Not Implemented
- return null;
+ // for now, this returns an empty result set.
+ Field f[] = new Field[13];
+ 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, new String("PROCEDURE_CAT"), iVarcharOid, 32);
+ f[1] = new Field(connection, new String("PROCEDURE_SCHEM"), iVarcharOid, 32);
+ f[2] = new Field(connection, new String("PROCEDURE_NAME"), iVarcharOid, 32);
+ f[3] = new Field(connection, new String("COLUMN_NAME"), iVarcharOid, 32);
+ f[4] = new Field(connection, new String("COLUMN_TYPE"), iInt2Oid, 2);
+ f[5] = new Field(connection, new String("DATA_TYPE"), iInt2Oid, 2);
+ f[6] = new Field(connection, new String("TYPE_NAME"), iVarcharOid, 32);
+ f[7] = new Field(connection, new String("PRECISION"), iInt4Oid, 4);
+ f[8] = new Field(connection, new String("LENGTH"), iInt4Oid, 4);
+ f[9] = new Field(connection, new String("SCALE"), iInt2Oid, 2);
+ f[10] = new Field(connection, new String("RADIX"), iInt2Oid, 2);
+ f[11] = new Field(connection, new String("NULLABLE"), iInt2Oid, 2);
+ f[12] = new Field(connection, new String("REMARKS"), iVarcharOid, 32);
+
+ return new ResultSet(connection, f, v, "OK", 1);
}
+ /**
+ * Get a description of tables available in a catalog.
+ *
+ * <p>Only table descriptions matching the catalog, schema, table
+ * name and type criteria are returned. They are ordered by
+ * TABLE_TYPE, TABLE_SCHEM and TABLE_NAME.
+ *
+ * <p>Each table description has the following columns:
+ *
+ * <ol>
+ * <li><b>TABLE_CAT</b> String => table catalog (may be null)
+ * <li><b>TABLE_SCHEM</b> String => table schema (may be null)
+ * <li><b>TABLE_NAME</b> String => table name
+ * <li><b>TABLE_TYPE</b> String => table type. Typical types are "TABLE",
+ * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", "LOCAL
+ * TEMPORARY", "ALIAS", "SYNONYM".
+ * <li><b>REMARKS</b> String => explanatory comment on the table
+ * </ol>
+ *
+ * <p>The valid values for the types parameter are:
+ * "TABLE", "INDEX", "LARGE OBJECT", "SEQUENCE", "SYSTEM TABLE" and
+ * "SYSTEM INDEX"
+ *
+ * @param catalog a catalog name; For postgresql, this is ignored, and
+ * should be set to null
+ * @param schemaPattern a schema name pattern; For postgresql, this is ignored, and
+ * should be set to null
+ * @param tableNamePattern a table name pattern. For all tables this should be "%"
+ * @param types a list of table types to include; null returns
+ * all types
+ * @return each row is a table description
+ * @exception SQLException if a database-access error occurs.
+ */
public java.sql.ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String types[]) throws SQLException
{
- return connection.createStatement().executeQuery("SELECT '' as TABLE_CAT,'' AS TABLE_SCHEM,relname AS TABLE_NAME,'TABLE' AS TABLE_TYPE,'' AS REMARKS FROM pg_class WHERE relkind = 'r' and relname !~ '^pg_' and relname !~ '^Inv' and relname ~ '"+tableNamePattern+"' ORDER BY TABLE_NAME");
+ // the field descriptors for the new ResultSet
+ Field f[] = new Field[5];
+ 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, new String("TABLE_CAT"), iVarcharOid, 32);
+ f[1] = new Field(connection, new String("TABLE_SCHEM"), iVarcharOid, 32);
+ f[2] = new Field(connection, new String("TABLE_NAME"), iVarcharOid, 32);
+ f[3] = new Field(connection, new String("TABLE_TYPE"), iVarcharOid, 32);
+ f[4] = new Field(connection, new String("REMARKS"), iVarcharOid, 32);
+
+ // Now form the query
+ StringBuffer sql = new StringBuffer("select relname,oid from pg_class where ");
+ boolean notFirst=false;
+ for(int i=0;i<types.length;i++) {
+ if(notFirst)
+ sql.append(" or ");
+ for(int j=0;j<getTableTypes.length;j++)
+ if(getTableTypes[j][0].equals(types[i])) {
+ sql.append(getTableTypes[j][1]);
+ notFirst=true;
+ }
+ }
+
+ // Now run the query
+ r = connection.ExecSQL(sql.toString());
+
+ if (r.getColumnCount() != 2)
+ throw new SQLException("Unexpected return from query for table list");
+
+ while (r.next())
+ {
+ byte[][] tuple = new byte[5][0];
+
+ String name = r.getString(1);
+ String remarks = new String("no remarks");
+
+ // Fetch the description for the table (if any)
+ ResultSet dr = connection.ExecSQL("select description from pg_description where objoid="+r.getInt(2));
+ if(dr.getTupleCount()==1) {
+ dr.next();
+ remarks=dr.getString(1);
+ }
+ dr.close();
+
+ tuple[0] = null; // Catalog name
+ tuple[1] = null; // Schema name
+ tuple[2] = name.getBytes(); // Table name
+ tuple[3] = null; // Table type
+ tuple[4] = remarks.getBytes(); // Remarks
+ v.addElement(tuple);
+ }
+ r.close();
+ return new ResultSet(connection, f, v, "OK", 1);
}
+ // This array contains the valid values for the types argument
+ // in getTables().
+ //
+ // Each supported type consists of it's name, and the sql where
+ // clause to retrieve that value.
+ //
+ // IMPORTANT: the query must be enclosed in ( )
+ private static final String getTableTypes[][] = {
+ {"TABLE", "(relkind='r' and relname !~ '^pg_' and relname !~ '^xinv')"},
+ {"INDEX", "(relkind='i' and relname !~ '^pg_' and relname !~ '^xinx')"},
+ {"LARGE OBJECT", "(relkind='r' and relname ~ '^xinv')"},
+ {"SEQUENCE", "(relkind='S' and relname !~ '^pg_')"},
+ {"SYSTEM TABLE", "(relkind='r' and relname ~ '^pg_')"},
+ {"SYSTEM INDEX", "(relkind='i' and relname ~ '^pg_')"}
+ };
+
/**
* Get the schema names available in this database. The results
* are ordered by schema name.
@@ -1522,8 +1701,15 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
*/
public java.sql.ResultSet getSchemas() throws SQLException
{
- // XXX-Not Implemented
- return null;
+ // We don't use schemas, so we simply return a single schema name "".
+ //
+ Field f[] = new Field[1];
+ Vector v = new Vector();
+ byte[][] tuple = new byte[1][0];
+ f[0] = new Field(connection,new String("TABLE_SCHEM"),iVarcharOid,32);
+ tuple[0] = "".getBytes();
+ v.addElement(tuple);
+ return new ResultSet(connection,f,v,"OK",1);
}
/**
@@ -1538,10 +1724,16 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
* @return ResultSet each row has a single String column that is a
* catalog name
*/
- // We don't use catalog names, so this returns a single catalog
public java.sql.ResultSet getCatalogs() throws SQLException
{
- return connection.createStatement().executeQuery("SELECT '' as TABLE_CAT");
+ // We don't use catalogs, so we simply return a single catalog name "".
+ Field f[] = new Field[1];
+ Vector v = new Vector();
+ byte[][] tuple = new byte[1][0];
+ f[0] = new Field(connection,new String("TABLE_CAT"),iVarcharOid,32);
+ tuple[0] = "".getBytes();
+ v.addElement(tuple);
+ return new ResultSet(connection,f,v,"OK",1);
}
/**
@@ -1560,8 +1752,15 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
*/
public java.sql.ResultSet getTableTypes() throws SQLException
{
- // XXX-Not Implemented
- return null;
+ Field f[] = new Field[1];
+ Vector v = new Vector();
+ byte[][] tuple = new byte[1][0];
+ f[0] = new Field(connection,new String("TABLE_TYPE"),iVarcharOid,32);
+ for(int i=0;i<getTableTypes.length;i++) {
+ tuple[0] = getTableTypes[i][0].getBytes();
+ v.addElement(tuple);
+ }
+ return new ResultSet(connection,f,v,"OK",1);
}
/**
@@ -1614,10 +1813,87 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
*/
public java.sql.ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException
{
- // XXX-Not Implemented
- // PM: this will be implemented, as soon as I sort out how to convert the
- // code from the other driver (private note: look at getProcedures() )
- return null;
+ // the field descriptors for the new ResultSet
+ Field f[] = new Field[18];
+ 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, new String("TABLE_CAT"), iVarcharOid, 32);
+ f[1] = new Field(connection, new String("TABLE_SCHEM"), iVarcharOid, 32);
+ f[2] = new Field(connection, new String("TABLE_NAME"), iVarcharOid, 32);
+ f[3] = new Field(connection, new String("COLUMN_NAME"), iVarcharOid, 32);
+ f[4] = new Field(connection, new String("DATA_TYPE"), iInt2Oid, 2);
+ f[5] = new Field(connection, new String("TYPE_NAME"), iVarcharOid, 32);
+ f[6] = new Field(connection, new String("COLUMN_SIZE"), iInt4Oid, 4);
+ f[7] = new Field(connection, new String("BUFFER_LENGTH"), iVarcharOid, 32);
+ f[8] = new Field(connection, new String("DECIMAL_DIGITS"), iInt4Oid, 4);
+ f[9] = new Field(connection, new String("NUM_PREC_RADIX"), iInt4Oid, 4);
+ f[10] = new Field(connection, new String("NULLABLE"), iInt4Oid, 4);
+ f[11] = new Field(connection, new String("REMARKS"), iVarcharOid, 32);
+ f[12] = new Field(connection, new String("COLUMN_DEF"), iVarcharOid, 32);
+ f[13] = new Field(connection, new String("SQL_DATA_TYPE"), iInt4Oid, 4);
+ f[14] = new Field(connection, new String("SQL_DATETIME_SUB"), iInt4Oid, 4);
+ f[15] = new Field(connection, new String("CHAR_OCTET_LENGTH"), iVarcharOid, 32);
+ f[16] = new Field(connection, new String("ORDINAL_POSITION"), iInt4Oid,4);
+ f[17] = new Field(connection, new String("IS_NULLABLE"), iVarcharOid, 32);
+
+ // Now form the query
+ r = connection.ExecSQL("select a.oid,c.relname,a.attname,a.atttypid,a.attnum,a.attnotnull,a.attlen from pg_class c, pg_attribute a where a.attrelid=c.oid and c.relname like '"+tableNamePattern+"' and a.attname like '"+columnNamePattern+"' and a.attnum>0 order by c.relname,a.attnum");
+
+ while(r.next()) {
+ byte[][] tuple = new byte[18][0];
+
+ String name = r.getString(1);
+ String remarks = new String("no remarks");
+
+ // Fetch the description for the table (if any)
+ ResultSet dr = connection.ExecSQL("select description from pg_description where objoid="+r.getInt(1));
+ if(dr.getTupleCount()==1) {
+ dr.next();
+ remarks=dr.getString(1);
+ }
+ dr.close();
+
+ tuple[0] = "".getBytes(); // Catalog name
+ tuple[1] = "".getBytes(); // Schema name
+ tuple[2] = r.getString(2).getBytes(); // Table name
+ tuple[3] = r.getString(3).getBytes(); // 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(Field.getSQLType(typname)).getBytes(); // Data type
+ tuple[5] = typname.getBytes(); // Type name
+
+ tuple[6] = r.getString(7).getBytes(); // Column size
+
+ 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] = remarks.getBytes(); // Remarks
+
+ tuple[12] = null; // 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.getString(5).getBytes(); // ordinal position
+
+ 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
+
+ v.addElement(tuple);
+ }
+ r.close();
+ return new ResultSet(connection, f, v, "OK", 1);
}
/**
@@ -1649,8 +1925,30 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
*/
public java.sql.ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) throws SQLException
{
- // XXX-Not Implemented
+ // XXX-Not Implemented as grant is broken
return null;
+ //Field f[] = new Field[8];
+ //Vector v = new Vector();
+ //
+ //f[0] = new Field(connection,new String("TABLE_CAT"),iVarcharOid,32);
+ //f[1] = new Field(connection,new String("TABLE_SCHEM"),iVarcharOid,32);
+ //f[2] = new Field(connection,new String("TABLE_NAME"),iVarcharOid,32);
+ //f[3] = new Field(connection,new String("COLUMN_NAME"),iVarcharOid,32);
+ //f[4] = new Field(connection,new String("GRANTOR"),iVarcharOid,32);
+ //f[5] = new Field(connection,new String("GRANTEE"),iVarcharOid,32);
+ //f[6] = new Field(connection,new String("PRIVILEGE"),iVarcharOid,32);
+ //f[7] = new Field(connection,new String("IS_GRANTABLE"),iVarcharOid,32);
+ //
+ //// This is taken direct from the psql source
+ //ResultSet r = connection.ExecSQL("SELECT relname, relacl FROM pg_class, pg_user WHERE ( relkind = 'r' OR relkind = 'i') and relname !~ '^pg_' and relname !~ '^xin[vx][0-9]+' and usesysid = relowner ORDER BY relname");
+ //while(r.next()) {
+ //byte[][] tuple = new byte[8][0];
+ //tuple[0] = tuple[1]= "default".getBytes();
+ //
+ //v.addElement(tuple);
+ //}
+ //
+ //return new ResultSet(connection,f,v,"OK",1);
}
/**
@@ -1722,10 +2020,24 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
* @param nullable include columns that are nullable?
* @return ResultSet each row is a column description
*/
+ // Implementation note: This is required for Borland's JBuilder to work
public java.sql.ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) throws SQLException
{
- // XXX-Not Implemented
- return null;
+ // for now, this returns an empty result set.
+ Field f[] = new Field[8];
+ 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, new String("SCOPE"), iInt2Oid, 2);
+ f[1] = new Field(connection, new String("COLUMN_NAME"), iVarcharOid, 32);
+ f[2] = new Field(connection, new String("DATA_TYPE"), iInt2Oid, 2);
+ f[3] = new Field(connection, new String("TYPE_NAME"), iVarcharOid, 32);
+ f[4] = new Field(connection, new String("COLUMN_SIZE"), iInt4Oid, 4);
+ f[5] = new Field(connection, new String("BUFFER_LENGTH"), iInt4Oid, 4);
+ f[6] = new Field(connection, new String("DECIMAL_DIGITS"), iInt2Oid, 2);
+ f[7] = new Field(connection, new String("PSEUDO_COLUMN"), iInt2Oid, 2);
+
+ return new ResultSet(connection, f, v, "OK", 1);
}
/**
@@ -2078,9 +2390,29 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
* accurate
* @return ResultSet each row is an index column description
*/
+ // Implementation note: This is required for Borland's JBuilder to work
public java.sql.ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) throws SQLException
{
- // XXX-Not Implemented
- return null;
+ // for now, this returns an empty result set.
+ Field f[] = new Field[13];
+ 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, new String("TABLE_CAT"), iVarcharOid, 32);
+ f[1] = new Field(connection, new String("TABLE_SCHEM"), iVarcharOid, 32);
+ f[2] = new Field(connection, new String("TABLE_NAME"), iVarcharOid, 32);
+ f[3] = new Field(connection, new String("NON_UNIQUE"), iBoolOid, 1);
+ f[4] = new Field(connection, new String("INDEX_QUALIFIER"), iVarcharOid, 32);
+ f[5] = new Field(connection, new String("INDEX_NAME"), iVarcharOid, 32);
+ f[6] = new Field(connection, new String("TYPE"), iInt2Oid, 2);
+ f[7] = new Field(connection, new String("ORDINAL_POSITION"), iInt2Oid, 2);
+ f[8] = new Field(connection, new String("COLUMN_NAME"), iVarcharOid, 32);
+ f[9] = new Field(connection, new String("ASC_OR_DESC"), iVarcharOid, 32);
+ f[10] = new Field(connection, new String("CARDINALITY"), iInt4Oid, 4);
+ f[11] = new Field(connection, new String("PAGES"), iInt4Oid, 4);
+ f[12] = new Field(connection, new String("FILTER_CONDITION"), iVarcharOid, 32);
+
+ return new ResultSet(connection, f, v, "OK", 1);
}
}
+