Example 5: Expression Evaluator

This custom procedure evaluates simple expressions.

package proc;
import com.compositesw.extension.*;
import java.sql.SQLException;
import java.sql.Types;
/**
 * Custom procedure to evaluate simple expressions:
 *
 * ARG1 | ARG2
 * ARG1 if it is neither null nor 0, otherwise ARG2
 *
 * ARG1 & ARG2
 * ARG1 if neither argument is null or 0, otherwise 0
 *
 * ARG1 < ARG2
 * ARG1 is less than ARG2
 *
 * ARG1 <= ARG2
 * ARG1 is less than or equal to ARG2
 *
 * ARG1 = ARG2
 * ARG1 is equal to ARG2
 *
 * ARG1 != ARG2
 * ARG1 is unequal to ARG2
 *
 * ARG1 >= ARG2
 * ARG1 is greater than or equal to ARG2
 *
 * ARG1 > ARG2
 * ARG1 is greater than ARG2
 *
 * ARG1 + ARG2
 * arithmetic sum of ARG1 and ARG2
 *
 * ARG1 - ARG2
 * arithmetic difference of ARG1 and ARG2
 *
 * ARG1 * ARG2
 * arithmetic product of ARG1 and ARG2
 *
 * ARG1 / ARG2
 * arithmetic quotient of ARG1 divided by ARG2
 *
 * ARG1 % ARG2
 * arithmetic remainder of ARG1 divided by ARG2
 */
public class ExpressionEvaluator
  implements CustomProcedure
{
  private ExecutionEnvironment qenv;
  private int result;
  public ExpressionEvaluator() { }
  /**
   * This is called once just after constructing the class. The
   * environment contains methods used to interact with the server.
   */
  public void initialize(ExecutionEnvironment qenv)
    throws SQLException
  {
    this.qenv = qenv;
  }
  /**
   * Called during introspection to get the description of the input
   * and output parameters. Should not return null.
   */
  public ParameterInfo[] getParameterInfo() {
    return new ParameterInfo[] {
      new ParameterInfo("arg1", Types.INTEGER, DIRECTION_IN),
      new ParameterInfo("operator", Types.VARCHAR, DIRECTION_IN),
      new ParameterInfo("arg2", Types.INTEGER, DIRECTION_IN),
      new ParameterInfo("result", Types.INTEGER, DIRECTION_OUT),
    };
  }
  /**
   * Called to invoke the stored procedure. Will only be called a
   * single time per instance. Can throw CustomProcedureException or
   * SQLException if there is an error during invoke.
   */
  public void invoke(Object[] inputValues)
    throws CustomProcedureException, SQLException
  {
    int arg1 =
      (inputValues[0] != null ? ((Integer)inputValues[0]).intValue() : 0);
    String op = (String)inputValues[1];
    int arg2 =
      (inputValues[2] != null ? ((Integer)inputValues[2]).intValue() : 0);
    if (op.equals("|"))
      result = (arg1 != 0) ? arg1 : arg2;
    else if (op.equals("&"))
      result = (arg1 != 0 && arg2 != 0) ? arg1 : 0;
    else if (op.equals("<"))
      result = (arg1 < arg2) ? 1 : 0;
    else if (op.equals("<="))
      result = (arg1 <= arg2) ? 1 : 0;
    else if (op.equals("="))
      result = (arg1 == arg2) ? 1 : 0;
    else if (op.equals("!="))
      result = (arg1 != arg2) ? 1 : 0;
    else if (op.equals(">="))
      result = (arg1 >= arg2) ? 1 : 0;
    else if (op.equals(">"))
      result = (arg1 > arg2) ? 1 : 0;
    else if (op.equals("+"))
      result = arg1 + arg2;
    else if (op.equals("-"))
      result = arg1 - arg2;
    else if (op.equals("*"))
      result = arg1 * arg2;
    else if (op.equals("/"))
      result = arg1 / arg2;
    else if (op.equals("%"))
      result = arg1 % arg2;
    else
      throw new CustomProcedureException("Unknown operator: " + op);
  }
  /**
   * Called to retrieve the number of rows that were inserted,
   * updated, or deleted during the execution of the procedure. A
   * return value of -1 indicates that the number of affected rows is
   * unknown. Can throw CustomProcedureException or SQLException if
   * there is an error when getting the number of affected rows.
   */
  public int getNumAffectedRows() {
    return 0;
  }
  /**
   * Called to retrieve the output values. The returned objects
   * should obey the Java to SQL typing conventions as defined in the
   * table above. Output cursors can be returned as either
   * CustomCursor or java.sql.ResultSet. Can throw
   * CustomProcedureException or SQLException if there is an error
   * when getting the output values. Should not return null.
   */
  public Object[] getOutputValues() {
    return new Object[] { new Integer(result) };
  }
  /**
   * Called when the procedure reference is no longer needed. Close
   * can be called without retrieving any of the output values (such
   * as cursors) or even invoking, so this needs to do any remaining
   * cleanup. Close can be called concurrently with any other call
   * such as "invoke" or "getOutputValues". In this case, any pending
   * methods should immediately throw a CustomProcedureException.
   */
  public void close()
    throws SQLException
  { }
  //
  // Introspection methods
  //
  /**
   * Called during introspection to get the short name of the stored
   * procedure. This name can be overridden during configuration.
   * Should not return null.
   */
  public String getName() {
    return "expr";
  }
  /**
   * Called during introspection to get the description of the stored
   * procedure. Should not return null.
   */
  public String getDescription() {
    return "Custom procedure to evaluate simple expressions";
  }
  //
  // Transaction methods
  //
  /**
   * Returns true if the custom procedure uses transactions. If this
   * method returns false then commit and rollback will not be called.
   */
  public boolean canCommit() {
    return false;
  }
/**
   * Commit any open transactions.
   */
  public void commit()
    throws SQLException
  { }
  /**
   * Rollback any open transactions.
   */
  public void rollback()
    throws SQLException
  { }
  /**
   * Returns true if the transaction can be compensated.
   */
  public boolean canCompensate() {
    return false;
  }
  /**
   * Compensate any committed transactions (if supported).
   */
  public void compensate(ExecutionEnvironment qenv)
    throws SQLException
  { }
}