package TemporaryDatabase;
import ModSQL.*;
import java.sql.*;

/* TemporaryDatabase/Table.java
 *
 * Copyright (c) 2003 Chris Studholme <chris.studholme@utoronto.ca>
 *
 * May be copied or modified under the terms of the GNU General Public
 * License.  See COPYING for more information.
 */

/**
 * <p>Temporary (in memory) database tables.
 *
 * @author chris.studholme@utoronto.ca
 */

class Table implements DatabaseTable {

  protected TableData data;
  protected boolean readonly;

  protected int nrows;
  protected int rowid;
  protected Object[] currentrow;

  public Table(TableData data, boolean readonly) {
    this.readonly = readonly;
    this.data = data;
    nrows = data.access();
    rowid=-1;
  }

  public void close() {
    if (data!=null) {
      data.release();
      data=null;
    }
  }
  protected void finalize() {
    close();
  }

  public DatabaseIndex openIndex(int column) {
    return null;
  }
    
  public boolean isIndexAvailable(int column) {
    return false;
  }
    
  public boolean isReadOnly() {
    return readonly;
  }
    
  public String getTableName() {
    return data.name;
  }
    
  public int getColumnCount() {
    return data.columns.size();
  }
    
  public long getTableSize() {
    return data.size()*data.columns.size();
  }
    
  public long getTableSignature() {
    return data.sig;
  }

  public long getRowCount() {
    return data.size();
  }
    
  public int findColumn(String name) {
    for (int i=0; i<data.columns.size(); ++i) {
      Column c = (Column)data.columns.get(i);
      if (name.equalsIgnoreCase(c.name))
	return i+1;
    }
    return -1;
  }
    
  public int getColumnDisplaySize(int column) throws DatabaseException {
    if (column<1 || column>data.columns.size())
      return 0;
    Column c = (Column)data.columns.get(column-1);
    if (c.type!=Types.CHAR && c.type!=Types.VARCHAR && 
	c.type!=Types.LONGVARCHAR) 
      return 0;
    if (c.maxlen>0)
      return c.maxlen;
    // compute maximum length
    return data.maxStringLength(column-1);
  }
    
  public String getColumnName(int column) {
    if (column<1 || column>data.columns.size())
      return null;
    Column c = (Column)data.columns.get(column-1);
    return c.name;
  }
    
  public String getColumnLabel(int column) {
    return getColumnName(column);
  }
    
  public int getColumnType(int column) throws DatabaseException {
    if (column<1 || column>data.columns.size())
      return Types.NULL;
    Column c = (Column)data.columns.get(column-1);
    return c.type;
  }
    
  public void addColumn(String name, int type, int maxlen)
    throws DatabaseException {
    if (readonly)
      throw new DatabaseException("table is read-only");
    if (data.size()>0)
      throw new DatabaseException("cannot add column (table has rows)");
    Column c = new Column(name,type,maxlen);
    data.columns.add(c);
    ++data.sig;
  }
    
  public boolean next() {
    while (++rowid<nrows) {
      currentrow=data.get(rowid);
      if (currentrow!=null)
	return true;
    } 
    return false;
  }
    
  public void addRow() throws DatabaseException {
    if (readonly)
      throw new DatabaseException("table is read-only");
    nrows = data.add();
    rowid=nrows-1;
    currentrow=data.get(rowid);
  }
  
  public void deleteRow() throws DatabaseException {
    if (readonly)
      throw new DatabaseException("table is read-only");
    if (rowid<0 || rowid>=nrows || currentrow==null)
      throw new DatabaseException("invalid row");
    data.remove(rowid);
  }
    
  public boolean isBeforeFirst() {
    return rowid<0;
  }
    
  public boolean isAfterLast() {
    return rowid>=nrows;
  }
    
  public void beforeFirst() {
    rowid=-1;
  }
    
  public void afterLast() {
    rowid=nrows;
  }
    
  public Object getRowId() {
    return new Integer(rowid);
  }
    
  public boolean absolute(Object id) {
    rowid = ((Number)id).intValue();
    if (rowid<0 || rowid>=nrows)
      return false;
    currentrow=data.get(rowid);
    return currentrow!=null;
  }
    
  public Object getObject(int column) throws DatabaseException {
    if (rowid<0 || rowid>=nrows || currentrow==null)
      return null;
    if (column<1 || column>currentrow.length)
      return null;
    return currentrow[column-1];
  }
    
  public void updateObject(int column, Object x) 
    throws DatabaseException {
    if (readonly)
      throw new DatabaseException("table is read-only");
    if (rowid<0 || rowid>=nrows || currentrow==null)
      throw new DatabaseException("invalid row");
    if (column<1 || column>currentrow.length)
      throw new DatabaseException("invalid column");
    // we assume x is an object of the correct type but we verify maxlen
    if (x instanceof String) {
      int maxlen = ((Column)data.columns.get(column-1)).maxlen;
      if (maxlen>0 && ((String)x).length()>maxlen) 
	x = ((String)x).substring(0,maxlen);
    }
    currentrow[column-1] = x;
    ++data.sig;
  }

  public void commitUpdates() 
    throws DatabaseException {
    // should do something here
  }
};

