![]() | Source code below from: Java Cookbook, Second Edition By Ian Darwin Published 14 June, 2004 Average rating
Powells
Alibris
|
//---------------------------------------------------------------------------- // // Module: SimpleTextResultSet.java // // Description: Implementation of the JDBC ResultSet interface // // Author: Karl Moss // // Copyright: (C) 1996,1997 Karl Moss. All rights reserved. // You may study, use, modify and distribute this example // for any purpose, provided that this copyright notice // appears in all copies. This example is provided WITHOUT // WARRANTY either expressed or implied. //---------------------------------------------------------------------------- package jdbc.SimpleText; //---------------------------------------------------------------------------- // 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. 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 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 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. // // Column names used as input to getXXX methods are case insensitive. // 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. // // 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 ResulSetMetaData object returned by the getMetaData // method. //---------------------------------------------------------------------------- // NOTE - this is an implementation of the JDBC API version 1.20 //--------------------------------------------------------------------------- import java.sql.*; import java.util.Hashtable; import java.io.*; public class SimpleTextResultSet extends SimpleTextObject implements ResultSet { //------------------------------------------------------------------------ // initialize //------------------------------------------------------------------------ public void initialize( SimpleTextIStatement statement, String catalog, String table, Hashtable columns, SimpleTextFilter filter) throws SQLException { // Save the owning statement object ownerStatement = statement; ownerConnection = ownerStatement.getConnection(); // Save the in-memory column definitions inMemoryColumns = columns; // Save the select WHERE filter selectFilter = filter; // If a table was given, open it now if (table != null) { openSDF(catalog, table); } } public void initialize( SimpleTextIStatement statement, Hashtable columns, Hashtable rows) throws SQLException { // Save the in-memory rows (used for catalog functions) inMemoryRows = rows; rowNum = 0; initialize(statement, null, null, columns, null); } //------------------------------------------------------------------------ // next - JDBC API // A ResultSet is initially positioned before its first row; 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 // implicitly closed. The ResultSet's warning chain is cleared // when a new row is read. // // Returns true if the new current row is valid; false if there // are no more rows //------------------------------------------------------------------------ public boolean next() throws SQLException { boolean rc = true; boolean validRow = false; // In memory result set, get the next row if (inMemoryRows != null) { rowNum++; // No more rows, return end-of-file if (rowNum > inMemoryRows.size()) { rc = false; } } else { // Not in-memory, read the next line from the file until a // valid row has been found while (!validRow) { currentLine = readLine(rafSDF); if (currentLine == null) { rc = false; break; } // We'll cheat a little bit here. We'll use the SQL // parser to break the line up, then treat it as a // comma separated list (much like a select list) String data[] = ownerConnection.parseSQL(currentLine); Hashtable dataList = new Hashtable(); ownerStatement.buildList(data, 0, "", dataList); // Now go through each data element and create a // CommonValue object. Then, put the CommonValue object // on our columnValues list SimpleTextColumn column; columnValues = new Hashtable(); String s; CommonValue value; for (int i = 1; i <= dataList.size(); i++) { column = (SimpleTextColumn) dataList.get(new Integer(i)); // Get the data item s = column.name; // Remove any quotes if (s.startsWith("'") && s.endsWith("'")) { s = s.substring(1, s.length() - 1); } // Create a CommonValue object using the string value = new CommonValue(s); // Create a CommonValue object columnValues.put(new Integer(i), value); } // Filter the row, if necessary validRow = filterRow(columnValues, selectFilter); } } return rc; } //------------------------------------------------------------------------ // close - JDBC API // In some cases, it is desirable to immediately release a // ResultSet's database and JDBC resources instead of waiting for // this to happen when it is automatically closed; the close // method provides this immediate release. // // Note: 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. A ResultSet is also automatically // closed when it is garbage collected. //------------------------------------------------------------------------ public void close() throws SQLException { try { if (rafSDF != null) { rafSDF.close(); } if (rafSBF != null) { rafSBF.close(); } } catch (Exception ex) { } } //------------------------------------------------------------------------ // wasNull - JDBC API // A column may have the value of SQL NULL; wasNull reports whether // the last column read had this special value. // Note that you must first call getXXX on a column to try to read // its value and then call wasNull() to find if the value was // the SQL NULL. // // Returns true if last column read was SQL NULL //------------------------------------------------------------------------ public boolean wasNull() throws SQLException { return lastNull; } //------------------------------------------------------------------------ // getString - JDBC API // Get the value of a column in the current row as a Java String. // // columnIndex the first column is 1, the second is 2, ... // // Returns the column value; if the value is SQL NULL the result is null //------------------------------------------------------------------------ public String getString( int columnIndex) throws SQLException { // Verify the column verify(columnIndex); String s = null; if (inMemoryRows != null) { s = (getColumn(rowNum, columnIndex)).getString(); } else { CommonValue value = getValue(columnIndex); if (value != null) { s = value.getString(); } } if (s == null) { lastNull = true; } return s; } //------------------------------------------------------------------------ // getBoolean - JDBC API // Get the value of a column in the current row as a Java boolean. // // columnIndex the first column is 1, the second is 2, ... // // Returns the column value; if the value is SQL NULL the result is false //------------------------------------------------------------------------ public boolean getBoolean( int columnIndex) throws SQLException { // We could coerce the data, but for now an exception is thrown throw DataTypeNotSupported(); } //------------------------------------------------------------------------ // getByte - JDBC API // Get the value of a column in the current row as a Java byte. // // columnIndex the first column is 1, the second is 2, ... // Returns the column value; if the value is SQL NULL the result is 0 //------------------------------------------------------------------------ public byte getByte( int columnIndex) throws SQLException { // We could coerce the data, but for now an exception is thrown throw DataTypeNotSupported(); } //------------------------------------------------------------------------ // getShort - JDBC API // Get the value of a column in the current row as a Java short. // // columnIndex the first column is 1, the second is 2, ... // // Returns the column value; if the value is SQL NULL the result is 0 //------------------------------------------------------------------------ public short getShort( int columnIndex) throws SQLException { // We could coerce the data, but for now an exception is thrown throw DataTypeNotSupported(); } //------------------------------------------------------------------------ // getInt - JDBC API // Get the value of a column in the current row as a Java int. // // columnIndex the first column is 1, the second is 2, ... // // Returns the column value; if the value is SQL NULL the result is 0 //------------------------------------------------------------------------ public int getInt( int columnIndex) throws SQLException { // Verify the column verify(columnIndex); CommonValue value; if (inMemoryRows != null) { value = getColumn(rowNum, columnIndex); } else { value = getValue(columnIndex); } // Check for a null value if (value == null) { lastNull = true; return 0; } if (value.isNull()) { lastNull = true; return 0; } return value.getInt(); } //------------------------------------------------------------------------ // getLong - JDBC API // Get the value of a column in the current row as a Java long. // // columnIndex the first column is 1, the second is 2, ... // // Returns the column value; if the value is SQL NULL the result is 0 //------------------------------------------------------------------------ public long getLong( int columnIndex) throws SQLException { // We could coerce the data, but for now an exception is thrown throw DataTypeNotSupported(); } //------------------------------------------------------------------------ // getFloat - JDBC API // Get the value of a column in the current row as a Java float. // // columnIndex the first column is 1, the second is 2, ... // // Returns the column value; if the value is SQL NULL the result is 0 //------------------------------------------------------------------------ public float getFloat( int columnIndex) throws SQLException { // We could coerce the data, but for now an exception is thrown throw DataTypeNotSupported(); } //------------------------------------------------------------------------ // getDouble - JDBC API // Get the value of a column in the current row as a Java double. // // columnIndex the first column is 1, the second is 2, ... // // Returns the column value; if the value is SQL NULL the result is 0 //------------------------------------------------------------------------ public double getDouble( int columnIndex) throws SQLException { // We could coerce the data, but for now an exception is thrown throw DataTypeNotSupported(); } //------------------------------------------------------------------------ // getBigDecimal - JDBC API // Get the value of a column in the current row as a java.math.BigDecimal // object. // // columnIndex the first column is 1, the second is 2, ... // scale the number of digits to the right of the decimal // // Returns the column value; if the value is SQL NULL the result is null //------------------------------------------------------------------------ public java.math.BigDecimal getBigDecimal( int columnIndex, int scale) throws SQLException { String s = getString(columnIndex); java.math.BigDecimal d = null; if (s != null) { java.math.BigInteger i = new java.math.BigInteger(s); d = new java.math.BigDecimal (i, scale); } return d; } //------------------------------------------------------------------------ // getBytes - JDBC API // 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. // // columnIndex the first column is 1, the second is 2, ... // // Returns the column value; if the value is SQL NULL the result is null //------------------------------------------------------------------------ public byte[] getBytes( int columnIndex) throws SQLException { // Verify the column verify(columnIndex); byte b[] = null; if (inMemoryRows != null) { b = (getColumn(rowNum, columnIndex)).getBytes(); } else { CommonValue value = getValue(columnIndex); if (value != null) { b = value.getBytes(); } } if (b == null) { lastNull = true; } return b; } //------------------------------------------------------------------------ // getDate - JDBC API // Get the value of a column in the current row as a java.sql.Date object. // // columnIndex the first column is 1, the second is 2, ... // // Returns the column value; if the value is SQL NULL the result is null //------------------------------------------------------------------------ public java.sql.Date getDate( int columnIndex) throws SQLException { // We could coerce the data, but for now an exception is thrown throw DataTypeNotSupported(); } //------------------------------------------------------------------------ // getTime - JDBC API // Get the value of a column in the current row as a java.sql.Time object. // // columnIndex the first column is 1, the second is 2, ... // // Returns the column value; if the value is SQL NULL the result is null //------------------------------------------------------------------------ public java.sql.Time getTime( int columnIndex) throws SQLException { // We could coerce the data, but for now an exception is thrown throw DataTypeNotSupported(); } //------------------------------------------------------------------------ // getTimestamp - JDBC API // Get the value of a column in the current row as a java.sql.Timestamp // object. // // columnIndex the first column is 1, the second is 2, ... // // Returns the column value; if the value is SQL NULL the result is null //------------------------------------------------------------------------ public java.sql.Timestamp getTimestamp( int columnIndex) throws SQLException { // We could coerce the data, but for now an exception is thrown throw DataTypeNotSupported(); } //------------------------------------------------------------------------ // A column value can be retrieved as a stream of ASCII characters // and then read in chunks from the stream. This method is particularly // suitable for retrieving large LONGVARCHAR values. 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 prior to getting the value of any other column. The // next call to a get method implicitly closes the stream. // // columnIndex the first column is 1, the second is 2, ... // // Returns a Java input stream that delivers the database column value // as a stream of one byte ASCII characters. If the value is SQL NULL // then the result is null. //------------------------------------------------------------------------ public java.io.InputStream getAsciiStream( int columnIndex) throws SQLException { // Binary InputStreams are the only InputStream types supported throw DataTypeNotSupported(); } //------------------------------------------------------------------------ // getUnicodeStream - JDBC API // A column value can be retrieved as a stream of Unicode characters // and then read in chunks from the stream. This method is particularly // suitable for retrieving large LONGVARCHAR values. The JDBC driver will // do any necessary conversion from the database format into Unicode. // // 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. // // columnIndex the first column is 1, the second is 2, ... // // Returns a Java input stream 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. //------------------------------------------------------------------------ public java.io.InputStream getUnicodeStream( int columnIndex) throws SQLException { // Binary InputStreams are the only InputStream types supported throw DataTypeNotSupported(); } //------------------------------------------------------------------------ // getBinaryStream - JDBC API // A column value can be retrieved as a stream of uninterpreted bytes // and then read in chunks from the stream. This method is particularly // suitable for retrieving large LONGVARBINARY values. // // 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. // // columnIndex the first column is 1, the second is 2, ... // // Returns a Java input stream that delivers the database column value // as a stream of uninterpreted bytes. If the value is SQL NULL // then the result is null. //------------------------------------------------------------------------ public java.io.InputStream getBinaryStream( int columnIndex) throws SQLException { // Verify the column verify(columnIndex); CommonValue value = null; if (inMemoryRows != null) { value = getColumn(rowNum, columnIndex); } else { value = getValue(columnIndex); } int length = -1; // Get the length, if possible if (value != null) { byte b[] = value.getBytes(); if (b != null) { length = b.length; } } SimpleTextInputStream inputStream = new SimpleTextInputStream( value, SimpleTextInputStream.STREAM_TYPE_BINARY, length); return inputStream; } //====================================================================== // Methods for accessing results by column name //====================================================================== //------------------------------------------------------------------------ // getString - JDBC API // Get the value of a column in the current row as a Java String. // // columnName is the SQL name of the column // // Returns the column value; if the value is SQL NULL the result is null //------------------------------------------------------------------------ public String getString( String columnName) throws SQLException { return getString(findColumn(columnName)); } //------------------------------------------------------------------------ // getBoolean - JDBC API // Get the value of a column in the current row as a Java boolean. // // columnName is the SQL name of the column // // Returns the column value; if the value is SQL NULL the result is false //------------------------------------------------------------------------ public boolean getBoolean( String columnName) throws SQLException { return getBoolean(findColumn(columnName)); } //------------------------------------------------------------------------ // getByte - JDBC API // Get the value of a column in the current row as a Java byte. // // columnName is the SQL name of the column // // Returns the column value; if the value is SQL NULL the result is 0 //------------------------------------------------------------------------ public byte getByte( String columnName) throws SQLException { return getByte(findColumn(columnName)); } //------------------------------------------------------------------------ // getShort - JDBC API // Get the value of a column in the current row as a Java short. // // columnName is the SQL name of the column // // Returns the column value; if the value is SQL NULL the result is 0 //------------------------------------------------------------------------ public short getShort( String columnName) throws SQLException { return getShort(findColumn(columnName)); } //------------------------------------------------------------------------ // getInt - JDBC API // Get the value of a column in the current row as a Java int. // // columnName is the SQL name of the column // // Returns the column value; if the value is SQL NULL the result is 0 //------------------------------------------------------------------------ public int getInt( String columnName) throws SQLException { return getInt(findColumn(columnName)); } //------------------------------------------------------------------------ // getLong - JDBC API // Get the value of a column in the current row as a Java long. // // columnName is the SQL name of the column // // Returns the column value; if the value is SQL NULL the result is 0 //------------------------------------------------------------------------ public long getLong( String columnName) throws SQLException { return getLong(findColumn(columnName)); } //------------------------------------------------------------------------ // getFloat - JDBC API // Get the value of a column in the current row as a Java float. // // columnName is the SQL name of the column // // Returns the column value; if the value is SQL NULL the result is 0 //------------------------------------------------------------------------ public float getFloat( String columnName) throws SQLException { return getFloat(findColumn(columnName)); } //------------------------------------------------------------------------ // getDouble - JDBC API // Get the value of a column in the current row as a Java double. // // columnName is the SQL name of the column // // Returns the column value; if the value is SQL NULL the result is 0 //------------------------------------------------------------------------ public double getDouble( String columnName) throws SQLException { return getDouble(findColumn(columnName)); } //------------------------------------------------------------------------ // getBigDecimal - JDBC API // Get the value of a column in the current row as a java.math.BigDecimal // object. // // columnName is the SQL name of the column // scale the number of digits to the right of the decimal // // Returns the column value; if the value is SQL NULL the result is null //------------------------------------------------------------------------ public java.math.BigDecimal getBigDecimal( String columnName, int scale) throws SQLException { return getBigDecimal(findColumn(columnName), scale); } //------------------------------------------------------------------------ // getBytes - JDBC API // 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. // // columnName is the SQL name of the column // // Returns the column value; if the value is SQL NULL the result is null //------------------------------------------------------------------------ public byte[] getBytes( String columnName) throws SQLException { return getBytes(findColumn(columnName)); } //------------------------------------------------------------------------ // getDate - JDBC API // Get the value of a column in the current row as a java.sql.Date object. // // columnName is the SQL name of the column // // Returns the column value; if the value is SQL NULL the result is null //------------------------------------------------------------------------ public java.sql.Date getDate( String columnName) throws SQLException { return getDate(findColumn(columnName)); } //------------------------------------------------------------------------ // getTime - JDBC API // Get the value of a column in the current row as a java.sql.Time object. // // columnName is the SQL name of the column // // Returns the column value; if the value is SQL NULL the result is null //------------------------------------------------------------------------ public java.sql.Time getTime( String columnName) throws SQLException { return getTime(findColumn(columnName)); } //------------------------------------------------------------------------ // getTimestamp - JDBC API // Get the value of a column in the current row as a java.sql.Timestamp // object. // // columnName is the SQL name of the column // Returns the column value; if the value is SQL NULL the result is null //------------------------------------------------------------------------ public java.sql.Timestamp getTimestamp( String columnName) throws SQLException { return getTimestamp(findColumn(columnName)); } //------------------------------------------------------------------------ // getAsciiStream // A column value can be retrieved as a stream of ASCII characters // and then read in chunks from the stream. This method is particularly // suitable for retrieving large LONGVARCHAR values. 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 prior to getting the value of any other column. The // next call to a get method implicitly closes the stream. // // columnName is the SQL name of the column // // Returns a Java input stream that delivers the database column value // as a stream of one byte ASCII characters. If the value is SQL NULL // then the result is null. //------------------------------------------------------------------------ public java.io.InputStream getAsciiStream( String columnName) throws SQLException { return getAsciiStream(findColumn(columnName)); } //------------------------------------------------------------------------ // getUnicodeStream - JDBC API // A column value can be retrieved as a stream of Unicode characters // and then read in chunks from the stream. This method is particularly // suitable for retrieving large LONGVARCHAR values. The JDBC driver will // do any necessary conversion from the database format into Unicode. // // 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. // // columnName is the SQL name of the column // // Returns a Java input stream 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. //------------------------------------------------------------------------ public java.io.InputStream getUnicodeStream( String columnName) throws SQLException { return getUnicodeStream(findColumn(columnName)); } //------------------------------------------------------------------------ // getBinaryStream - JDBC API // A column value can be retrieved as a stream of uninterpreted bytes // and then read in chunks from the stream. This method is particularly // suitable for retrieving large LONGVARBINARY values. // // 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. // // columnName is the SQL name of the column // // Returns a Java input stream that delivers the database column value // as a stream of uninterpreted bytes. If the value is SQL NULL // then the result is null. //------------------------------------------------------------------------ public java.io.InputStream getBinaryStream( String columnName) throws SQLException { return getBinaryStream(findColumn(columnName)); } //===================================================================== // Advanced features: //===================================================================== //------------------------------------------------------------------------ // getWarnings - JDBC API // The first warning reported by calls on this ResultSet is // returned. Subsequent ResultSet warnings will be chained to this // SQLWarning. // // The warning chain is automatically cleared each time a new // row is read. // // Note: This warning chain only covers warnings caused // by ResultSet methods. Any warning caused by statement methods // (such as reading OUT parameters) will be chained on the // Statement object. // // Returns the first SQLWarning or null //------------------------------------------------------------------------ public SQLWarning getWarnings() throws SQLException { return lastWarning; } //------------------------------------------------------------------------ // clearWarnings - JDBC API // After this call getWarnings returns null until a new warning is // reported for this ResultSet. //------------------------------------------------------------------------ public void clearWarnings() throws SQLException { setWarning(null); } //------------------------------------------------------------------------ // setWarning // Sets the given SQLWarning in the warning chain. If null, the // chain is reset //------------------------------------------------------------------------ protected void setWarning( SQLWarning warning) { if (warning == null) { lastWarning = null; } else { SQLWarning chain = lastWarning; // Find the end of the chain while (chain.getNextWarning() != null) { chain = chain.getNextWarning(); } // We're at the end of the chain. Add the new warning chain.setNextWarning(warning); } } //------------------------------------------------------------------------ // getCursorName - JDBC API // Get the name of the SQL cursor used by this ResultSet. // // In SQL, a result table is retrieved through 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 // SQL cursor used by a ResultSet. The current row of a ResultSet // is also the current row of this SQL cursor. // // Note: If positioned update is not supported a // SQLException is thrown // // Returns the ResultSet's SQL cursor name //------------------------------------------------------------------------ public String getCursorName() throws SQLException { // The SimpleText driver does not support positioned updates throw DriverNotCapable(); } //------------------------------------------------------------------------ // getMetaData - JDBC API // The number, types and properties of a ResultSet's columns // are provided by the getMetaData method. // // Returns the description of a ResultSet's columns //------------------------------------------------------------------------ public ResultSetMetaData getMetaData() throws SQLException { SimpleTextResultSetMetaData md = new SimpleTextResultSetMetaData(); md.initialize(inMemoryColumns, ownerConnection.isReadOnly()); return md; } //------------------------------------------------------------------------ // getObject - JDBC API // Get the value of a column as a Java object. // // This method will return the value of the given column as a Java // object. The type of the Java object will be default Java Object type // corresponding to the column's SQL type, following the mapping // specified in the JDBC spec. // // This method may also be used to read datatabase specific abstract // data types. // // columnIndex the first column is 1, the second is 2, ... // // Returns A java.lang.Object holding the column value. //------------------------------------------------------------------------ public Object getObject( int columnIndex) throws SQLException { // Verify the column verify(columnIndex); // Get the data type of the column int type = (getColumn(columnIndex)).type; // The CommonValue for the column CommonValue value; if (inMemoryRows != null) { value = getColumn(rowNum, columnIndex); } else { value = getValue(columnIndex); } // Check for a null value if (value == null) { lastNull = true; return null; } if (value.isNull()) { lastNull = true; return null; } Object o = null; // Return the appropriate object for the given type switch(type) { case Types.VARCHAR: o = value.getString(); break; case Types.INTEGER: o = new Integer(value.getInt()); break; case Types.VARBINARY: o = value.getBytes(); break; default: throw DataTypeNotSupported(); } return o; } //------------------------------------------------------------------------ // getObject - JDBC API // Get the value of a parameter as a Java object. // // This method will return the value of the given column as a Java // object. The type of the Java object will be default Java Object type // corresponding to the column's SQL type, following the mapping // specified in the JDBC spec. // // This method may also be used to read datatabase specific abstract // data types. // // columnName is the SQL name of the column // // Returns A java.lang.Object holding the column value. //------------------------------------------------------------------------ public Object getObject( String columnName) throws SQLException { return getObject(findColumn(columnName)); } //------------------------------------------------------------------------ // findColumn - JDBC API // Map a Resultset column name to a ResultSet column index. // // columnName the name of the column // // Returns the column index // // Note: The code implemented here comes from appendix C of the // JDBC API. //------------------------------------------------------------------------ public int findColumn( String columnName) throws SQLException { // Make a mapping cache if we don't already have one. if (md == null) { md = getMetaData(); s2c = new Hashtable(); } // Look for the mapping in our cache Integer x = (Integer) s2c.get(columnName); if (x != null) { return (x.intValue()); } // OK, we'll have to use metadata for (int i = 1; i <= md.getColumnCount(); i++) { if (md.getColumnName(i).equalsIgnoreCase(columnName)) { // Success! Add an entry to the cache s2c.put(columnName, new Integer(i)); return (i); } } throw new SQLException("Column name not found: " + columnName, "S0022"); } //------------------------------------------------------------------------ // verify // Verifies the column number given is valid, and resets the warnings // and null indicator. Returns the absolute column number. //------------------------------------------------------------------------ protected int verify( int column) throws SQLException { clearWarnings(); lastNull = false; SimpleTextColumn col = (SimpleTextColumn) inMemoryColumns.get( new Integer(column)); if (col == null) { throw new SQLException("Invalid column number: " + column); } return col.colNo; } //------------------------------------------------------------------------ // getColumn // Given a row and column number, return the CommonValue object from // the inMemoryRows //------------------------------------------------------------------------ protected CommonValue getColumn( int rowNum, int column) throws SQLException { // First, get the row Hashtable row = (Hashtable) inMemoryRows.get(new Integer(rowNum)); if (row == null) { throw new SQLException("Invalid row number: " + rowNum); } // Get the value CommonValue value = (CommonValue) row.get(new Integer(column)); if (value == null) { // Column wasn't found. Return a null value value = new CommonValue(); } return value; } private Hashtable s2c; // Maps strings to column indexes private ResultSetMetaData md; // Our metadata object //------------------------------------------------------------------------ // openSDF // Opens the simple data file //------------------------------------------------------------------------ protected void openSDF( String catalog, String table) throws SQLException { String fullName = catalog + "/" + table + SimpleTextDefine.DATA_FILE_EXT; String sbfName = catalog + "/" + table + SimpleTextDefine.BINARY_FILE_EXT; // Make sure the file exists SDF = new File(fullName); SBF = new File(sbfName); if (!SDF.exists()) { throw new SQLException("Text file does not exist: " + fullName); } try { // Create our random access object (read only) rafSDF = new RandomAccessFile(SDF, "r"); } catch (Exception ex) { throw new SQLException("Unable to access file: " +ex.getMessage()); } // Read past the first line (the column definitions). Before // we got to this point, the Statement object verified that // it is a valid file readLine(rafSDF); } //------------------------------------------------------------------------ // readLine // Given a random access file object, read the next line. Returns null // if eof //------------------------------------------------------------------------ protected String readLine( RandomAccessFile f) throws SQLException { String s = null; try { if (f.getFilePointer() >= f.length()) { return null; } s = f.readLine(); } catch (Exception ex) { throw new SQLException("Error reading file: " + ex.getMessage()); } return s; } //------------------------------------------------------------------------ // readSBF // Given an offset, read the binary file and return a byte array //------------------------------------------------------------------------ protected byte[] readSBF( int offset) throws SQLException { // Invalid offset, return null if (offset < 0) { return null; } byte b[] = null; // First time, check to make sure it exists if (rafSBF == null) { if (!SBF.exists()) { throw new SQLException("Binary file does not exist"); } } try { // First time, create random access file object if (rafSBF == null) { rafSBF = new RandomAccessFile(SBF, "r"); } // Position to the given offset rafSBF.seek(offset); // Make sure there is enough file to read an int if ((rafSBF.getFilePointer() + 4) > rafSBF.length()) { throw new SQLException("Attempt to read beyond end-of-file"); } // Read the length of the data int len = rafSBF.readInt(); // Make sure there's enough data to read if ((rafSBF.getFilePointer() + len) > rafSBF.length()) { throw new SQLException("Attempt to read beyond end-of-file"); } b = new byte[len]; rafSBF.read(b); } catch (Exception ex) { throw new SQLException("Unable to access SBF: " + ex.getMessage()); } return b; } //------------------------------------------------------------------------ // getValue // Returns a CommonValue object for the given column //------------------------------------------------------------------------ protected CommonValue getValue( int column) throws SQLException { CommonValue value; // Get the column definition (we already know it's there) SimpleTextColumn col = (SimpleTextColumn) inMemoryColumns.get( new Integer(column)); // value = (CommonValue) columnValues.get(new Integer(column)); value = (CommonValue) columnValues.get(new Integer(col.colNo)); if (value == null) { return null; } switch(col.type) { // For binary types, read the binary file case Types.VARBINARY: { byte b[] = readSBF(value.getInt()); value = new CommonValue(b); } break; } return value; } //------------------------------------------------------------------------ // filter // Given a Hashtable of column values and a select filter, determine if // the data is valid. Returns true if the row is valid. //------------------------------------------------------------------------ protected boolean filterRow( Hashtable values, SimpleTextFilter filter) throws SQLException { if (filter == null) { return true; } boolean valid = false; // Get the column number int column = filter.column.colNo; // Get the data for the column CommonValue value = (CommonValue) values.get(new Integer(column)); // If we didn't find the column, invalidate the column if (value == null) { return false; } switch(filter.column.type) { // Perform integer comparisions case Types.INTEGER: { int icol = value.getInt(); int ifilter = filter.value.getInt(); switch (filter.operator) { case SimpleTextFilter.OP_EQ: valid = (icol == ifilter); break; case SimpleTextFilter.OP_GT: valid = (icol > ifilter); break; case SimpleTextFilter.OP_LT: valid = (icol < ifilter); break; case SimpleTextFilter.OP_NE: valid = (icol != ifilter); break; } } break; // By default, compare as a string default: { String scol = value.getString(); String sfilter = filter.value.getString(); switch (filter.operator) { case SimpleTextFilter.OP_EQ: valid = (scol.equals(sfilter)); break; case SimpleTextFilter.OP_GT: valid = (scol.compareTo(sfilter) > 0); break; case SimpleTextFilter.OP_LT: valid = (scol.compareTo(sfilter) < 0); break; case SimpleTextFilter.OP_NE: valid = (!scol.equals(sfilter)); break; } } break; } return valid; } //------------------------------------------------------------------------ // getColumn // Returns the SimpleTextColumn object for the given column number. // If not found, an exception is thrown //------------------------------------------------------------------------ protected SimpleTextColumn getColumn( int col) throws SQLException { SimpleTextColumn column = (SimpleTextColumn) inMemoryColumns.get(new Integer(col)); if (column == null) { throw new SQLException("Invalid column number: " + col); } return column; } // SQLWarning chain protected SQLWarning lastWarning; // Owning statement object protected SimpleTextIStatement ownerStatement; // Owning connection object protected SimpleTextIConnection ownerConnection; // Hashtable containing a SimpleTextColumn object for each column // in the result set. Used for catalog functions as well as normal // tables protected Hashtable inMemoryColumns; // Hashtable containing another Hashtable for each row. Used for // catalog functions protected Hashtable inMemoryRows; // Current row number (for in-memory result sets) protected int rowNum; // true if the last row accessed was null protected boolean lastNull; // File objects for the simple data file and simple binary file File SDF; File SBF; RandomAccessFile rafSDF; RandomAccessFile rafSBF; // Current text line String currentLine; // Current data values (CommonValue objects) Hashtable columnValues; // SimpleTextFilter object for select WHERE clause SimpleTextFilter selectFilter; } //---------------------------------------------------------------------------- // SimpleTextFilter // Class to represent a filter for a SELECT statement (i.e. the WHERE clause). // This class is package-private //---------------------------------------------------------------------------- class SimpleTextFilter { SimpleTextColumn column; int operator; public final static int OP_EQ = 1; public final static int OP_GT = 2; public final static int OP_LT = 3; public final static int OP_NE = 4; CommonValue value; }