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

/* $Id: Drop.java,v 1.7 2003/09/24 19:59:34 cvs Exp $
 *
 * 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>Drop will parse a DROP sql statement.  Currently, DROP TABLE and
 * DROP INDEX are supported.
 *
 * @author chris.studholme@utoronto.ca
 */
final class Drop implements Query {

  /** Index to drop indexes this table. */
  String indexed_table=null;
  /** Index to drop indexes this column. */
  String indexed_column=null;

  /** Name of table to drop. */
  String tablename=null;

  /** Table manager used to open tables. */
  protected transient DatabaseManager tablemanager;

  /**
   * Contructor to parse query.
   *
   * @param tokenizer StreamTokenizer that SQL tokens should be read from
   * @param manager manager to use when looking up tables
   * @throws SQLException if an error occurs
   * @throws IOException if there is a problem reading the query
   */
  protected Drop(StreamTokenizer tokenizer, DatabaseManager manager) 
    throws SQLException, IOException {
    tablemanager = manager;
    ParseDrop(tokenizer);
  }

  /**
   * Close query and free resources in use.
   */
  public void close() {
  }

  /**
   * Returns human-readable string version of query (with surrounding 
   * brackets).
   *
   * @return String representation of query
   */
  public String toString() {
    return toString(true);
  }

  /**
   * Returns human-readable string version of query.
   *
   * @param with_brackets true to include surrounding brackets
   * @return String representation of query
   */
  public String toString(boolean with_brackets) {
    StringBuffer result = new StringBuffer();
    if (with_brackets) result.append('(');
    result.append("DROP");
    if (tablename!=null) {
      result.append(" TABLE ");
      result.append(tablename);
    }
    else if (indexed_table!=null && indexed_column!=null) {
      result.append(" INDEX ");
      result.append(indexed_table+"."+indexed_column);
    }
    else {
      result.append(" [UNKNOWN]");
    }
    if (with_brackets) result.append(')');
    return result.toString();
  }

  /**
   * Parse drop query of the form:<br>
   *   <blockquote><code>
   *   DROP INDEX tablename.column;<br>
   *   DROP TABLE tablename;
   *   </code></blockquote>
   *
   * @param tokenizer StreamTokenizer that SQL tokens should be read from
   * @throws SQLException if an error occurs
   * @throws IOException if there is a problem reading the query
   */   
  private void ParseDrop(StreamTokenizer tokenizer)
    throws SQLException, IOException {
    
    if ((tokenizer.ttype!=StreamTokenizer.TT_WORD)||
	(!tokenizer.sval.equals("drop")))
      throw new SQLException("'DROP' expected");
    tokenizer.nextToken();

    // subfunctions
    if (tokenizer.ttype!=StreamTokenizer.TT_WORD) 
      throw new SQLException("invalid DROP expression at or before "+
			     tokenizer);

    if (tokenizer.sval.equals("table")) {
      tokenizer.nextToken();
      ParseDropTable(tokenizer);
    }
    else if (tokenizer.sval.equals("index")) {
      tokenizer.nextToken();
      ParseDropIndex(tokenizer);
    }
    else {
      throw new SQLException("DROP expression not supported at or before "+
			     tokenizer);
    }
  }

  /**
   * Parse drop table query of the form:<br>
   *   <blockquote><code>
   *   DROP TABLE tablename;
   *   </code></blockquote>
   *
   * @param tokenizer StreamTokenizer that SQL tokens should be read from
   * @throws SQLException if an error occurs
   * @throws IOException if there is a problem reading the query
   */   
  private void ParseDropTable(StreamTokenizer tokenizer) 
    throws SQLException, IOException {
    // table name
    tablename=null;
    if (tokenizer.ttype==StreamTokenizer.TT_WORD) {
      tablename=tokenizer.sval;
      tokenizer.nextToken();
    }
    else
      throw new SQLException("table name expected at or before "+tokenizer);
  }

  /**
   * Parse drop index query of the form:<br>
   *   <blockquote><code>
   *   DROP INDEX tablename.column;<br>
   *   </code></blockquote>
   *
   * @param tokenizer StreamTokenizer that SQL tokens should be read from
   * @throws SQLException if an error occurs
   * @throws IOException if there is a problem reading the query
   */   
  private void ParseDropIndex(StreamTokenizer tokenizer) 
    throws SQLException, IOException {
    indexed_table=null;
    indexed_column=null;

    // table name
    if (tokenizer.ttype!=StreamTokenizer.TT_WORD)
      throw new SQLException("table name expected at or before "+tokenizer);
    indexed_table=tokenizer.sval;
    tokenizer.nextToken();

    if (tokenizer.ttype!='.')
      throw new SQLException("'.' expected at or before "+tokenizer);
    
    // column name
    if (tokenizer.ttype!=StreamTokenizer.TT_WORD)
      throw new SQLException("table name expected at or before "+tokenizer);
    indexed_column=tokenizer.sval;
    tokenizer.nextToken();
  }

  /**
   * Optimize query.
   *
   * @throws SQLException if an error occurs
   */
  public void optimize() throws SQLException {
  }

  /**
   * Execute the query.
   *
   * @return 1 if successful
   * @throws SQLException if an error occurs
   */
  public int execute() throws SQLException {
    if (tablename!=null) {
      tablemanager.dropTable(tablename);
    }

    else if (indexed_table!=null && indexed_column!=null) {
      //tablemanager.dropIndex(indexed_table,indexed_column);
      throw new SQLException("not implemented");
    }

    else
      throw new SQLException("cannot execute DROP statement");

    return 1;
  }

};
