+ * This returns the Fastpath API for the current connection.
+ * functions on the postgresql backend itself.
+ * ...
+ * backend.
+ * This returns the LargeObject API for the current connection.
+ * functions on the postgresql backend itself.
+ * ...
+ * LargeObjectManager lo = ((postgresql.Connection)myconn).getLargeObjectAPI();
+ * postgresql's more unique data types.
+ * is returned.
+ * object. Custom objects can have their own methods.
+ obj = (PGobject)(Class.forName(name==null?"postgresql.util.PGobject":name).newInstance());
+ * more unique data types.
+ * ...
+ * ...
+ // This array contains the types that are supported as standard.
+ // the full class name of the handling class.
import java.util.*;
/**
- * @version 1.0 15-APR-1997
- *
* This class provides information about the database as a whole.
*
- * Many of the methods here return lists of information in ResultSets. You
+ *
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
+ *
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
* 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
+ *
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.
{
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;
}
/**
- * 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.
+ *
+ *
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.
+ *
+ *
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");
}
/**
* 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
+ *
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.
*
* 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
+ *
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.
*
* 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
+ *
If an SQL identifier is a table name, column name, etc. then
* we do not support it.
*
* @return the quoting string
* 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
+ *
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
+ *
+ *
For SQL Keywords, I took the list provided at
+ * http://web.dementia.org/~shadow/sql/sql3bnf.sep93.txt
* which is for SQL3, not SQL-92, but it is close enough for
* this purpose.
*
* 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
+ *
From the file src/backend/parser/scan.l, an identifier is
* {letter}{letter_or_digit} which makes it just those listed
* above.
*
/**
* Is column aliasing supported?
*
- * If so, the SQL AS clause can be used to provide names for
+ *
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.
*
* select count(C) as C_COUNT from T group by C;
*
+ *
* should return a column named as C_COUNT instead of count(C)
*
* @return true if so
/**
* Are expressions in "ORCER BY" lists supported?
*
- * e.g. select * from t order by a + b;
+ *
e.g. select * from t order by a + b;
*
* @return true if so
* @exception SQLException if a database access error occurs
* 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
+ *
This changed from false to true in v6.2 of the driver, as this
* support was added to the backend.
*
* @return true if so
* 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
*
- * In Appendix C. From this description, we seem to support the
+ *
In Appendix C. From this description, we seem to support the
* ODBC minimal (Level 0) grammar.
*
* @return true if so
* 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
+ *
"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)..."
* Does a data definition statement within a transaction force
* the transaction to commit? I think this means something like:
*
* CREATE TABLE T (A INT);
* INSERT INTO T (A) VALUES (2);
* BEGIN;
* CREATE TABLE X (A INT);
* SELECT A FROM T INTO X;
* COMMIT;
*
* does the CREATE TABLE call cause a commit? The answer is no.
*
}
/**
- * 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
/**
* Get a description of stored procedures available in a catalog
*
- * Only procedure descriptions matching the schema and procedure
+ *
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
+ *
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
+ *
+ *
*
* @param catalog - a catalog name; "" retrieves those without a
* catalog; null means drop catalog name from criteria
* @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
return new ResultSet(connection, f, v, "OK", 1);
}
+ /**
+ * Get a description of a catalog's stored procedure parameters
+ * and result columns.
+ *
+ *
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.
+ *
+ *
Each row in the ResultSet is a parameter description or column
+ * description with the following fields:
+ *
PROCEDURE_CAT String => procedure catalog (may be null)
+ *
PROCEDURE_SCHEM String => procedure schema (may be null)
+ *
PROCEDURE_NAME String => procedure name
+ *
COLUMN_NAME String => column/parameter name
+ *
COLUMN_TYPE Short => kind of column/parameter:
+ *
- procedureColumnUnknown - nobody knows
+ *
procedureColumnIn - IN parameter
+ *
procedureColumnInOut - INOUT parameter
+ *
procedureColumnOut - OUT parameter
+ *
procedureColumnReturn - procedure return value
+ *
procedureColumnResult - result column in ResultSet
+ *
+ *
DATA_TYPE short => SQL type from java.sql.Types
+ *
TYPE_NAME String => SQL type name
+ *
PRECISION int => precision
+ *
LENGTH int => length in bytes of data
+ *
SCALE short => scale
+ *
RADIX short => radix
+ *
NULLABLE short => can it contain NULL?
+ *
- procedureNoNulls - does not allow NULL values
+ *
procedureNullable - allows NULL values
+ *
procedureNullableUnknown - nullability unknown
+ *
REMARKS String => comment describing parameter/column
+ *
+ * @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.
+ *
+ *
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.
+ *
+ *
Each table description has the following columns:
+ *
+ *
TABLE_CAT String => table catalog (may be null)
+ *
TABLE_SCHEM String => table schema (may be null)
+ *
TABLE_NAME String => table name
+ *
TABLE_TYPE String => table type. Typical types are "TABLE",
+ * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", "LOCAL
+ * TEMPORARY", "ALIAS", "SYNONYM".
+ *
REMARKS String => explanatory comment on the table
+ *
+ *
+ *
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
+ if(notFirst)
+ sql.append(" or ");
+ for(int j=0;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.
*/
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);
}
/**
* @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);
}
/**
*/
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
+ tuple[0] = getTableTypes[i][0].getBytes();
+ v.addElement(tuple);
+ }
+ return new ResultSet(connection,f,v,"OK",1);
}
/**
*/
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);
}
/**
*/
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);
}
/**
* @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);
}
/**
* 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);
}
}
+
* The Java SQL framework allows for multiple database drivers. Each
* driver should supply a class that implements the Driver interface
*
- * The DriverManager will try to load as many drivers as it can find and then
- * for any given connection request, it will ask each driver in turn to try
- * to connect to the target URL.
+ *
The DriverManager will try to load as many drivers as it can find and
+ * then for any given connection request, it will ask each driver in turn
+ * to try to connect to the target URL.
*
- * It is strongly recommended that each Driver class should be small and
+ *
It is strongly recommended that each Driver class should be small and
* standalone so that the Driver class can be loaded and queried without
* bringing in vast quantities of supporting code.
*
- * When a Driver class is loaded, it should create an instance of itself and
- * register it with the DriverManager. This means that a user can load and
- * register a driver by doing Class.forName("foo.bah.Driver")
+ *
When a Driver class is loaded, it should create an instance of itself
+ * and register it with the DriverManager. This means that a user can load
+ * and register a driver by doing Class.forName("foo.bah.Driver")
*
* @see postgresql.Connection
* @see java.sql.Driver
* when the JDBC driverManager is asked to connect to a given URL,
* it passes the URL to each loaded driver in turn.
*
- * The driver should raise an SQLException if it is the right driver
+ *
The driver should raise an SQLException if it is the right driver
* to connect to the given URL, but has trouble connecting to the
* database.
*
- * The java.util.Properties argument can be used to pass arbitrary
+ *
The java.util.Properties argument can be used to pass arbitrary
* string tag/value pairs as connection arguments. Normally, at least
* "user" and "password" properties should be included in the
* properties.
*
- * Our protocol takes the form:
+ * Our protocol takes the forms:
- * jdbc:postgresql://host:port/database
+ * jdbc:postgresql://host:port/database?param1=val1&...
*
*
* @param url the URL of the database to connect to
* The getPropertyInfo method is intended to allow a generic GUI
* tool to discover what properties it should prompt a human for
* in order to get enough information to connect to a database.
- * Note that depending on the values the human has supplied so
+ *
+ *
Note that depending on the values the human has supplied so
* far, additional values may become necessary, so it may be necessary
* to iterate through several calls to getPropertyInfo
*
* tests, otherwise it is required to return false. JDBC compliance
* requires full support for the JDBC API and full support for SQL 92
* Entry Level.
+ *
+ *
For PostgreSQL, this is not yet possible, as we are not SQL92
+ * compliant (yet).
*/
public boolean jdbcCompliant()
{
* @param url JDBC URL to parse
* @param defaults Default properties
* @return Properties with elements added from the url
- * @throws SQLException
+ * @exception SQLException
*/
Properties parseURL(String url,Properties defaults) throws SQLException
{
}
/**
- * Returns the hostname portion of the URL
+ * @return the hostname portion of the URL
*/
public String host()
{
}
/**
- * Returns the port number portion of the URL
- * or -1 if no port was specified
+ * @return the port number portion of the URL or -1 if no port was specified
*/
public int port()
{
}
/**
- * Returns the database name of the URL
+ * @return the database name of the URL
*/
public String database()
{
}
/**
- * Returns any property
+ * @return the value of any property specified in the URL or properties
+ * passed to connect(), or null if not found.
*/
public String property(String name)
{
import postgresql.*;
/**
- * postgresql.Field is a class used to describe fields in a PostgreSQL ResultSet
- *
- * @version 1.0 15-APR-1997
+ * postgresql.Field is a class used to describe fields in a PostgreSQL
+ * ResultSet
*/
public class Field
{
String type_name = null;// The sql type name
/**
- * Construct a field based on the information fed to it.
+ * Construct a field based on the information fed to it.
*
* @param conn the connection this field came from
* @param name the name of the field
this.length = length;
}
+ /**
+ * @return the oid of this Field's data type
+ */
+ public int getOID()
+ {
+ return oid;
+ }
+
/**
* the ResultSet and ResultMetaData both need to handle the SQL
* type, which is gained from another query. Note that we cannot
*/
public int getSQLType() throws SQLException
{
- if (sql_type == -1)
- {
- ResultSet result = (postgresql.ResultSet)conn.ExecSQL("select typname from pg_type where oid = " + oid);
- if (result.getColumnCount() != 1 || result.getTupleCount() != 1)
- throw new SQLException("Unexpected return from query for type");
- result.next();
- type_name = result.getString(1);
- if (type_name.equals("int2"))
- sql_type = Types.SMALLINT;
- else if (type_name.equals("int4"))
- sql_type = Types.INTEGER;
- else if (type_name.equals("int8"))
- sql_type = Types.BIGINT;
- else if (type_name.equals("cash"))
- sql_type = Types.DECIMAL;
- else if (type_name.equals("money"))
- sql_type = Types.DECIMAL;
- else if (type_name.equals("float4"))
- sql_type = Types.REAL;
- else if (type_name.equals("float8"))
- sql_type = Types.DOUBLE;
- else if (type_name.equals("bpchar"))
- sql_type = Types.CHAR;
- else if (type_name.equals("varchar"))
- sql_type = Types.VARCHAR;
- else if (type_name.equals("bool"))
- sql_type = Types.BIT;
- else if (type_name.equals("date"))
- sql_type = Types.DATE;
- else if (type_name.equals("time"))
- sql_type = Types.TIME;
- else if (type_name.equals("abstime"))
- sql_type = Types.TIMESTAMP;
- else if (type_name.equals("timestamp"))
- sql_type = Types.TIMESTAMP;
- else
- sql_type = Types.OTHER;
- }
+ if(sql_type == -1) {
+ ResultSet result = (postgresql.ResultSet)conn.ExecSQL("select typname from pg_type where oid = " + oid);
+ if (result.getColumnCount() != 1 || result.getTupleCount() != 1)
+ throw new SQLException("Unexpected return from query for type");
+ result.next();
+ sql_type = getSQLType(result.getString(1));
+ result.close();
+ }
+ return sql_type;
+ }
+
+ /**
+ * This returns the SQL type. It is called by the Field and DatabaseMetaData classes
+ * @param type_name PostgreSQL type name
+ * @return java.sql.Types value for oid
+ */
+ public static int getSQLType(String type_name)
+ {
+ int sql_type = Types.OTHER; // default value
+ for(int i=0;i
+ if(type_name.equals(types[i]))
+ sql_type=typei[i];
return sql_type;
}
+ /**
+ * This table holds the postgresql names for the types supported.
+ * Any types that map to Types.OTHER (eg POINT) don't go into this table.
+ * They default automatically to Types.OTHER
+ *
+ * Note: This must be in the same order as below.
+ *
+ * Tip: keep these grouped together by the Types. value
+ */
+ private static final String types[] = {
+ "int2",
+ "int4","oid",
+ "int8",
+ "cash","money",
+ "float4",
+ "float8",
+ "bpchar","char","char2","char4","char8","char16",
+ "varchar","text","name","filename",
+ "bool",
+ "date",
+ "time",
+ "abstime","timestamp"
+ };
+
+ /**
+ * This table holds the JDBC type for each entry above.
+ *
+ * Note: This must be in the same order as above
+ *
+ * Tip: keep these grouped together by the Types. value
+ */
+ private static final int typei[] = {
+ Types.SMALLINT,
+ Types.INTEGER,Types.INTEGER,
+ Types.BIGINT,
+ Types.DECIMAL,Types.DECIMAL,
+ 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
+ };
+
/**
* We also need to get the type name as returned by the back end.
* This is held in type_name AFTER a call to getSQLType. Since
Send(buf);
}
+ /**
+ * Sends an integer to the back end in reverse order.
+ *
+ * This is required when the backend uses the routines in the
+ * src/backend/libpq/pqcomprim.c module.
+ *
+ * @param val the integer to be sent
+ * @param siz the length of the integer in bytes (size of structure)
+ * @exception IOException if an I/O error occurs
+ */
+ public void SendIntegerReverse(int val, int siz) throws IOException
+ {
+ byte[] buf = new byte[siz];
+ int p=0;
+ while (siz-- > 0)
+ {
+ buf[p++] = (byte)(val & 0xff);
+ val >>= 8;
+ }
+ Send(buf);
+ }
+
/**
* Send an array of bytes to the backend
*
}
}
+ /**
+ * This flushes any pending output to the backend. It is used primarily
+ * by the Fastpath code.
+ * @exception SQLException if an I/O error occurs
+ */
+ public void flush() throws SQLException
+ {
+ try {
+ pg_output.flush();
+ } catch (IOException e) {
+ throw new SQLException("Error flushing output: " + e.toString());
+ }
+ }
+
/**
* Closes the connection
*
import java.sql.*;
import java.text.*;
import java.util.*;
+import postgresql.largeobject.*;
+import postgresql.util.*;
/**
- * @version 6.3 15-APR-1997
- *
* A SQL Statement is pre-compiled and stored in a PreparedStatement object.
* This object can then be used to efficiently execute this statement multiple
* times.
*
- * Note: The setXXX methods for setting IN parameter values must
+ * <p><B>Note: The setXXX methods for setting IN parameter values must
* specify types that are compatible with the defined SQL type of the input
* parameter. For instance, if the IN parameter has SQL type Integer, then
* setInt should be used.
*
- * If arbitrary parameter type conversions are required, then the setObject
+ *
If arbitrary parameter type conversions are required, then the setObject
* method should be used with a target SQL type.
*
* @see ResultSet
Connection connection;
/**
- * Constructor for the PreparedStatement class. Split the SQL statement
- * into segments - separated by the arguments. When we rebuild the
- * thing with the arguments, we can substitute the args and join the
- * whole thing together.
+ * Constructor for the PreparedStatement class.
+ * Split the SQL statement into segments - separated by the arguments.
+ * When we rebuild the thing with the arguments, we can substitute the
+ * args and join the whole thing together.
*
* @param conn the instanatiating connection
* @param sql the SQL statement with ? for IN markers
/**
* Set a parameter to SQL NULL
*
- * Note: You must specify the parameters SQL type (although
+ * <p><B>Note: You must specify the parameters SQL type (although
* PostgreSQL ignores it)
*
* @param parameterIndex the first parameter is 1, etc...
*/
public void setString(int parameterIndex, String x) throws SQLException
{
- StringBuffer b = new StringBuffer();
- int i;
-
- b.append('\'');
- for (i = 0 ; i < x.length() ; ++i)
- {
- char c = x.charAt(i);
- if (c == '\\' || c == '\'')
- b.append((char)'\\');
- b.append(c);
- }
- b.append('\'');
- set(parameterIndex, b.toString());
+ // if the passed string is null, then set this column to null
+ if(x==null)
+ set(parameterIndex,"null");
+ else {
+ StringBuffer b = new StringBuffer();
+ int i;
+
+ b.append('\'');
+ for (i = 0 ; i < x.length() ; ++i)
+ {
+ char c = x.charAt(i);
+ if (c == '\\' || c == '\'')
+ b.append((char)'\\');
+ b.append(c);
+ }
+ b.append('\'');
+ set(parameterIndex, b.toString());
+ }
}
- /**
- * Set a parameter to a Java array of bytes. The driver converts this
- * to a SQL VARBINARY or LONGVARBINARY (depending on the argument's
- * size relative to the driver's limits on VARBINARYs) when it sends
- * it to the database.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setBytes(int parameterIndex, byte x[]) throws SQLException
- {
- throw new SQLException("Binary Data not supported");
- }
+ /**
+ * Set a parameter to a Java array of bytes. The driver converts this
+ * to a SQL VARBINARY or LONGVARBINARY (depending on the argument's
+ * size relative to the driver's limits on VARBINARYs) when it sends
+ * it to the database.
+ *
+ *
With postgresql, this creates a large object, and stores the
+ * objects oid in this column.
+ *
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ * @exception SQLException if a database access error occurs
+ */
+ public void setBytes(int parameterIndex, byte x[]) throws SQLException
+ {
+ LargeObjectManager lom = connection.getLargeObjectAPI();
+ int oid = lom.create();
+ LargeObject lob = lom.open(oid);
+ lob.write(x);
+ lob.close();
+ setInt(parameterIndex,oid);
+ }
/**
* Set a parameter to a java.sql.Date value. The driver converts this
*/
public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
{
- SimpleDateFormat df = new SimpleDateFormat(connection.europeanDates?"''dd-MM-yyyy''":"''MM-dd-yyyy''");
-
- set(parameterIndex, df.format(x));
+ SimpleDateFormat df = new SimpleDateFormat("''"+connection.getDateStyle()+"''");
+
+ // Ideally the following should work:
+ //
+ // set(parameterIndex, df.format(x));
+ //
+ // however, SimpleDateFormat seems to format a date to the previous
+ // day. So a fix (for now) is to add a day before formatting.
+ // This needs more people to confirm this is really happening, or
+ // possibly for us to implement our own formatting code.
+ //
+ // I've tested this with the Linux jdk1.1.3 and the Win95 JRE1.1.5
+ //
+ set(parameterIndex, df.format(new java.util.Date(x.getTime()+DAY)));
}
+
+ // This equates to 1 day
+ private static final int DAY = 86400000;
/**
* Set a parameter to a java.sql.Time value. The driver converts
* this to a SQL TIME value when it sends it to the database.
*
- * @param parameterIndex the first parameter is 1...
+ * @param parameterIndex the first parameter is 1...));
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
* end-of-file. The JDBC driver will do any necessary conversion from
* ASCII to the database char format.
*
- * Note: This stream object can either be a standard Java
+ * <P><B>Note: This stream object can either be a standard Java
* stream object or your own subclass that implements the standard
* interface.
*
* end-of-file. The JDBC driver will do any necessary conversion from
* UNICODE to the database char format.
*
- * Note: This stream object can either be a standard Java
+ * <P><B>Note: This stream object can either be a standard Java
* stream object or your own subclass that implements the standard
* interface.
*
* JDBC will read the data from the stream as needed, until it reaches
* end-of-file.
*
- * Note: This stream object can either be a standard Java
+ * <P><B>Note: This stream object can either be a standard Java
* stream object or your own subclass that implements the standard
* interface.
*
* Set the value of a parameter using an object; use the java.lang
* equivalent objects for integral values.
*
- * The given Java object will be converted to the targetSqlType before
+ *
The given Java object will be converted to the targetSqlType before
* being sent to the database.
*
- * note that this method may be used to pass database-specific
+ *
note that this method may be used to pass database-specific
* abstract data types. This is done by using a Driver-specific
* Java type and using a targetSqlType of java.sql.Types.OTHER
*
case Types.TIMESTAMP:
setTimestamp(parameterIndex, (Timestamp)x);
case Types.OTHER:
- setString(parameterIndex, ((PG_Object)x).value);
+ setString(parameterIndex, ((PGobject)x).getValue());
default:
throw new SQLException("Unknown Types value");
}
setTimestamp(parameterIndex, (Timestamp)x);
else if (x instanceof Boolean)
setBoolean(parameterIndex, ((Boolean)x).booleanValue());
- else if (x instanceof PG_Object)
- setString(parameterIndex, ((PG_Object)x).value);
+ else if (x instanceof PGobject)
+ setString(parameterIndex, ((PGobject)x).getValue());
else
throw new SQLException("Unknown object type");
}
import java.text.*;
import java.util.*;
import java.sql.*;
-import postgresql.*;
+import postgresql.largeobject.*;
+import postgresql.util.*;
/**
* A ResultSet provides access to a table of data generated by executing a
* Statement. The table rows are retrieved in sequence. Within a row its
* column values can be accessed in any order.
*
- * A ResultSet maintains a cursor pointing to its current row of data.
+ *
A ResultSet maintains a cursor pointing to its current row of data.
* Initially the cursor is positioned before the first row. The 'next'
* method moves the cursor to the next row.
*
- * The getXXX methods retrieve column values for the current row. You can
+ *
The getXXX methods retrieve column values for the current row. You can
* retrieve values either using the index number of the column, or by using
* the name of the column. In general using the column index will be more
* efficient. Columns are numbered from 1.
*
- * For maximum portability, ResultSet columns within each row should be read
+ *
For maximum portability, ResultSet columns within each row should be read
* in left-to-right order and each column should be read only once.
*
- * For the getXXX methods, the JDBC driver attempts to convert the underlying
- * data to the specified Java type and returns a suitable Java value. See the
- * JDBC specification for allowable mappings from SQL types to Java types with
- * the ResultSet getXXX methods.
+ *
For the getXXX methods, the JDBC driver attempts to convert the
+ * underlying data to the specified Java type and returns a suitable Java
+ * value. See the JDBC specification for allowable mappings from SQL types
+ * to Java types with the ResultSet getXXX methods.
*
- * Column names used as input to getXXX methods are case insenstive. When
+ *
Column names used as input to getXXX methods are case insenstive. When
* performing a getXXX using a column name, if several columns have the same
* name, then the value of the first matching column will be returned. The
* column name option is designed to be used when column names are used in the
* the programmer to guarentee that they actually refer to the intended
* columns.
*
- * A ResultSet is automatically closed by the Statement that generated it
+ *
A ResultSet is automatically closed by the Statement that generated it
* when that Statement is closed, re-executed, or is used to retrieve the
* next result from a sequence of multiple results.
*
- * The number, types and properties of a ResultSet's columns are provided by
+ *
The number, types and properties of a ResultSet's columns are provided by
* the ResultSetMetaData object returned by the getMetaData method.
*
* @see ResultSetMetaData
* the first call to next makes the first row the current row;
* the second call makes the second row the current row, etc.
*
- * If an input stream from the previous row is open, it is
+ *
If an input stream from the previous row is open, it is
* implicitly closed. The ResultSet's warning chain is cleared
* when a new row is read
*
* when it is automatically closed. The close method provides this
* immediate release.
*
- * Note: A ResultSet is automatically closed by the Statement
+ * <p><B>Note: A ResultSet is automatically closed by the Statement
* the Statement that generated it when that Statement is closed,
* re-executed, or is used to retrieve the next result from a sequence
* of multiple results. A ResultSet is also automatically closed
*/
public String getString(int columnIndex) throws SQLException
{
- byte[] bytes = getBytes(columnIndex);
-
- if (bytes == null)
+ //byte[] bytes = getBytes(columnIndex);
+ //
+ //if (bytes == null)
+ //return null;
+ //return new String(bytes);
+ if (columnIndex < 1 || columnIndex > fields.length)
+ throw new SQLException("Column Index out of range");
+ wasNullFlag = (this_row[columnIndex - 1] == null);
+ if(wasNullFlag)
return null;
- return new String(bytes);
+ return new String(this_row[columnIndex - 1]);
}
/**
}
/**
- * Get the value of a column in the current row as a Java byte array
- * The bytes represent the raw values returned by the driver.
+ * Get the value of a column in the current row as a Java byte array.
+ *
+ *
In normal use, the bytes represent the raw values returned by the
+ * backend. However, if the column is an OID, then it is assumed to
+ * refer to a Large Object, and that object is returned as a byte array.
+ *
+ *
Be warned If the large object is huge, then you may run out
+ * of memory.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @return the column value; if the value is SQL NULL, the result
if (columnIndex < 1 || columnIndex > fields.length)
throw new SQLException("Column Index out of range");
wasNullFlag = (this_row[columnIndex - 1] == null);
+
+ // Handle OID's as BLOBS
+ if(!wasNullFlag)
+ if( fields[columnIndex - 1].getOID() == 26) {
+ LargeObjectManager lom = connection.getLargeObjectAPI();
+ LargeObject lob = lom.open(getInt(columnIndex));
+ byte buf[] = lob.read(lob.size());
+ lob.close();
+ return buf;
+ }
+
return this_row[columnIndex - 1];
}
public java.sql.Date getDate(int columnIndex) throws SQLException
{
String s = getString(columnIndex);
- SimpleDateFormat df = new SimpleDateFormat(connection.europeanDates?"dd-MM-yyyy":"MM-dd-yyyy");
+ SimpleDateFormat df = new SimpleDateFormat(connection.getDateStyle());
try {
return new java.sql.Date(df.parse(s).getTime());
} catch (ParseException e) {
* The JDBC driver will do any necessary conversion from the
* database format into ASCII.
*
- * Note: All the data in the returned stream must be read
+ * <p><B>Note: All the data in the returned stream must be read
* prior to getting the value of any other column. The next call
* to a get method implicitly closes the stream. Also, a stream
* may return 0 for available() whether there is data available
* or not.
*
- * We implement an ASCII stream as a Binary stream - we should really
+ *
We implement an ASCII stream as a Binary stream - we should really
* do the data conversion, but I cannot be bothered to implement this
* right now.
*
*
* @param columnIndex the first column is 1, the second is 2...
* @return a Java InputStream that delivers the database column value
- * as a stream of two byte Unicode characters. If the value is
- * SQL NULL, then the result is null
+ * as a stream of bytes. If the value is SQL NULL, then the result
+ * is null
* @exception SQLException if a database access error occurs
* @see getAsciiStream
* @see getUnicodeStream
* returned. Subsequent ResultSet warnings will be chained
* to this SQLWarning.
*
- * The warning chain is automatically cleared each time a new
+ *
The warning chain is automatically cleared each time a new
* row is read.
*
- * Note: This warning chain only covers warnings caused by
+ * <p><B>Note: This warning chain only covers warnings caused by
* ResultSet methods. Any warnings caused by statement methods
* (such as reading OUT parameters) will be chained on the
* Statement object.
/**
* Get the name of the SQL cursor used by this ResultSet
*
- * In SQL, a result table is retrieved though a cursor that is
+ *
In SQL, a result table is retrieved though a cursor that is
* named. The current row of a result can be updated or deleted
* using a positioned update/delete statement that references
* the cursor name.
*
- * JDBC supports this SQL feature by providing the name of the
+ *
JDBC supports this SQL feature by providing the name of the
* SQL cursor used by a ResultSet. The current row of a ResulSet
* is also the current row of this SQL cursor.
*
- * Note: If positioned update is not supported, a SQLException
+ * <p><B>Note: If positioned update is not supported, a SQLException
* is thrown.
*
* @return the ResultSet's SQL cursor name.
/**
* Get the value of a column in the current row as a Java object
*
- * This method will return the value of the given column as a
+ *
This method will return the value of the given column as a
* Java object. The type of the Java object will be the default
* Java Object type corresponding to the column's SQL type, following
* the mapping specified in the JDBC specification.
*
- * This method may also be used to read database specific abstract
+ *
This method may also be used to read database specific abstract
* data types.
*
* @param columnIndex the first column is 1, the second is 2...
case Types.TIMESTAMP:
return getTimestamp(columnIndex);
default:
- return new PG_Object(field.getTypeName(), getString(columnIndex));
+ return connection.getObject(field.getTypeName(), getString(columnIndex));
}
}
/**
* Get the value of a column in the current row as a Java object
*
- * This method will return the value of the given column as a
+ *
This method will return the value of the given column as a
* Java object. The type of the Java object will be the default
* Java Object type corresponding to the column's SQL type, following
* the mapping specified in the JDBC specification.
*
- * This method may also be used to read database specific abstract
+ *
This method may also be used to read database specific abstract
* data types.
*
* @param columnName is the SQL name of the column
* particular, we need to know the number of rows and the
* number of columns. Rows are also known as Tuples
*
- * getTupleCount returns the number of rows
- *
* @return the number of rows
*/
public int getTupleCount()
import postgresql.*;
/**
- * @version 1.0 15-APR-1997
- *
* A ResultSetMetaData object can be used to find out about the types and
* properties of the columns in a ResultSet
*
import java.sql.*;
/**
- * @version 1.0 15-APR-1997
- *
* A Statement object is used for executing a static SQL statement and
* obtaining the results produced by it.
*
- * Only one ResultSet per Statement can be open at any point in time.
+ *
Only one ResultSet per Statement can be open at any point in time.
* Therefore, if the reading of one ResultSet is interleaved with the
* reading of another, each must have been generated by different
* Statements. All statement execute methods implicitly close a
Connection connection; // The connection who created us
ResultSet result = null; // The current results
SQLWarning warnings = null; // The warnings chain.
- int maxrows = 0; // maximum no. of rows; 0 = unlimited
int timeout = 0; // The timeout for a query (not used)
boolean escapeProcessing = true;// escape processing flag
* for this to happen when it is automatically closed. The
* close method provides this immediate release.
*
- * Note: A Statement is automatically closed when it is
+ * <p><B>Note: A Statement is automatically closed when it is
* garbage collected. When a Statement is closed, its current
* ResultSet, if one exists, is also closed.
*
*/
public int getMaxRows() throws SQLException
{
- return maxrows;
+ return connection.maxrows;
}
/**
*/
public void setMaxRows(int max) throws SQLException
{
- maxrows = max;
+ connection.maxrows = max;
}
/**
* chain. Subsequent Statement warnings will be chained to this
* SQLWarning.
*
- * The Warning chain is automatically cleared each time a statement
+ *
The Warning chain is automatically cleared each time a statement
* is (re)executed.
*
- * Note: If you are processing a ResultSet then any warnings
+ * <p><B>Note: If you are processing a ResultSet then any warnings
* associated with ResultSet reads will be chained on the ResultSet
* object.
*
* doesn't support positioned update/delete, this method is a
* no-op.
*
- * Note: By definition, positioned update/delete execution
+ * <p><B>Note: By definition, positioned update/delete execution
* must be done by a different Statement than the one which
* generated the ResultSet being used for positioning. Also, cursor
* names must be unique within a Connection.
*
- * We throw an additional constriction. There can only be one
+ *
We throw an additional constriction. There can only be one
* cursor active at any one time.
*
* @param name the new cursor name