FileDocCategorySizeDatePackage
SimpleTextResultSet.javaAPI DocExample51950Sat Feb 03 11:43:42 GMT 2001jdbc.SimpleText

SimpleTextResultSet.java

//----------------------------------------------------------------------------
//
// 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;
}