package ModSQL;
import java.sql.*;
 
/* $Id: Operator_Negate.java,v 1.9 2003/07/09 06:54:49 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>SQL operator "-".
 *
 * @author chris.studholme@utoronto.ca
 */
final class Operator_Negate extends Operator {

  /**
   * Default constructor.
   */
  public Operator_Negate() {
  }

  /**
   * Constructor with parameter.
   *
   * @param parameter first (and only) parameter
   * @throws SQLException if there is an error with the parameter
   */
  public Operator_Negate(Function parameter) throws SQLException {
    addParameter(parameter);
  }
  
  /**
   * <p>Prepare the function for use.  
   *
   * @throws SQLException if the parameter is invalid
   */
  public void optimize() throws SQLException {
    super.optimize();
    if (parameters.length!=1) 
      throw new SQLException("'-' operator requires exactly one parameter");
    switch (parameters[0].getSQLType()) {
    case Types.NULL:
    case Types.TINYINT:
    case Types.SMALLINT:
    case Types.INTEGER:
    case Types.BIGINT:
    case Types.REAL:
    case Types.FLOAT:
    case Types.DOUBLE:
      break;
    default:
      throw new SQLException("invalid parameter type in '-' operator");
    }
    evaluateConstantParameters();
  }

  /**
   * Returns "#NEGATE".
   *
   * @return name of function 
   */
  public String functionName() {
    return "#NEGATE";
  }


  /****************  result meta-data  ****************/
  

  /**
   * Returns the type of the parameter.
   *
   * @return SQL type of data to be returned
   * @throws SQLException if a database-access error occurs.
   */
  public int getSQLType() throws SQLException {
    return parameters[0].getSQLType();
  }

  /**
   * Returns -1 as this operator will never return a String object.
   *
   * @return maximum size of String returned or -1 if unknown
   */
  public int getMaxResultSize() {
    return -1;
  }


  /****************  evaluation methods  ****************/


  /**
   * Evaluate parameter and negate.
   *
   * @param aggregate passed to parameter
   * @return result object
   * @throws SQLException if a database-access error occurs
   * @throws EndOfTable if thrown by a parameter
   */
  public Object evaluate(boolean aggregate) throws SQLException, EndOfTable {
    Number value;
    if (parameter_constant[0])
      value = (Number)parameter_value[0];
    else
      value = (Number)parameters[0].evaluate(aggregate);
    if (value==null)
      return null;
    return NumberMath.negate(value);
  }

  /**
   * Evaluate parameter and negate.
   *
   * @param match_op how the value should be matched
   * @param match_value desired value
   * @return result object
   * @throws SQLException if a database-access error occurs
   * @throws EndOfTable if thrown by a parameter
   */
  public Object evaluate(int match_op, Object match_value)
    throws SQLException, EndOfTable {
    Number value;
    if (parameter_constant[0])
      value = (Number)parameter_value[0];
    else if (match_value==null)
      value = (Number)parameters[0].evaluate(match_op,null);
    else {
      int mf;
      Number mv = match_value==null ? null : 
	NumberMath.negate((Number)match_value);
      switch (match_op) {
      case MATCH_GT:  
      case MATCH_GTE:
      case MATCH_LT:
      case MATCH_LTE:
	mf = match_op^6;
	break;
      case MATCH_NE:
      case MATCH_EQU:
      default:
	mf = match_op;
      }
      value = (Number)parameters[0].evaluate(mf,mv);
    }
    if (value==null)
      return null;
    return NumberMath.negate(value);
  }
};
