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