gt:                 if (!nodes[0].dataType.isNumberType()) {
context: /* Copyright (c) 2001-2009, The HSQL Development Group
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions are met:
   *
   * Redistributions of source code must retain the above copyright notice, this
   * list of conditions and the following disclaimer.
   *
   * Redistributions in binary form must reproduce the above copyright notice,
   * this list of conditions and the following disclaimer in the documentation
   * and/or other materials provided with the distribution.
   *
   * Neither the name of the HSQL Development Group nor the names of its
   * contributors may be used to endorse or promote products derived from this
   * software without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
   * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   */
  
  
  package org.hsqldb_voltpatches;
  
  import org.hsqldb_voltpatches.ParserDQL.CompileContext;
  import org.hsqldb_voltpatches.lib.IntValueHashMap;
  import org.hsqldb_voltpatches.store.ValuePool;
  import org.hsqldb_voltpatches.types.BinaryData;
  import org.hsqldb_voltpatches.types.BinaryType;
  import org.hsqldb_voltpatches.types.BlobData;
  import org.hsqldb_voltpatches.types.CharacterType;
  import org.hsqldb_voltpatches.types.DTIType;
  import org.hsqldb_voltpatches.types.DateTimeType;
  import org.hsqldb_voltpatches.types.NumberType;
  import org.hsqldb_voltpatches.types.Type;
  
  // A VoltDB extension to allow use of X'..' as numeric literals
  import java.math.BigInteger;
  // End VoltDB extension
  /**
   * Implementation of SQL standard function calls
   *
   * @author Fred Toussi (fredt@users dot sourceforge.net)
   * @version 1.9.0
   * @since 1.9.0
   */
  public class FunctionSQL extends Expression {
  
      private final static int   FUNC_POSITION_CHAR                    = 1;     // numeric
      private final static int   FUNC_POSITION_BINARY                  = 2;
      private final static int   FUNC_OCCURENCES_REGEX                 = 3;
      private final static int   FUNC_POSITION_REGEX                   = 4;
      protected final static int FUNC_EXTRACT                          = 5;
      protected final static int FUNC_BIT_LENGTH                       = 6;
      protected final static int FUNC_CHAR_LENGTH                      = 7;
      protected final static int FUNC_OCTET_LENGTH                     = 8;
      private final static int   FUNC_CARDINALITY                      = 9;
      private final static int   FUNC_ABS                              = 10;
      private final static int   FUNC_MOD                              = 11;
      protected final static int FUNC_LN                               = 12;
      private final static int   FUNC_EXP                              = 13;
      private final static int   FUNC_POWER                            = 14;
      private final static int   FUNC_SQRT                             = 15;
      private final static int   FUNC_FLOOR                            = 16;
      private final static int   FUNC_CEILING                          = 17;
      private final static int   FUNC_WIDTH_BUCKET                     = 20;
      protected final static int FUNC_SUBSTRING_CHAR                   = 21;    // string
      private final static int   FUNC_SUBSTRING_REG_EXPR               = 22;
      private final static int   FUNC_SUBSTRING_REGEX                  = 23;
      protected final static int FUNC_FOLD_LOWER                       = 24;
      protected final static int FUNC_FOLD_UPPER                       = 25;
      private final static int   FUNC_TRANSCODING                      = 26;
      private final static int   FUNC_TRANSLITERATION                  = 27;
      private final static int   FUNC_REGEX_TRANSLITERATION            = 28;
      protected final static int FUNC_TRIM_CHAR                        = 29;
      final static int           FUNC_OVERLAY_CHAR                     = 30;
      private final static int   FUNC_CHAR_NORMALIZE                   = 31;
      private final static int   FUNC_SUBSTRING_BINARY                 = 32;
      private final static int   FUNC_TRIM_BINARY                      = 33;
      private final static int   FUNC_OVERLAY_BINARY                   = 40;
      protected final static int FUNC_CURRENT_DATE                     = 41;    // datetime
      protected final static int FUNC_CURRENT_TIME                     = 42;
      protected final static int FUNC_CURRENT_TIMESTAMP                = 43;
      protected final static int FUNC_LOCALTIME                        = 44;
      private final static int   FUNC_LOCALTIMESTAMP                   = 50;
      private final static int   FUNC_CURRENT_CATALOG                  = 51;    // general
      private final static int   FUNC_CURRENT_DEFAULT_TRANSFORM_GROUP  = 52;
      private final static int   FUNC_CURRENT_PATH                     = 53;
      private final static int   FUNC_CURRENT_ROLE                     = 54;
      private final static int   FUNC_CURRENT_SCHEMA                   = 55;
      private final static int   FUNC_CURRENT_TRANSFORM_GROUP_FOR_TYPE = 56;
      private final static int   FUNC_CURRENT_USER                     = 57;
      private final static int   FUNC_SESSION_USER                     = 58;
      private final static int   FUNC_SYSTEM_USER                      = 59;
      protected final static int FUNC_USER                             = 60;
      private final static int   FUNC_VALUE                            = 61;
  
      //
      static final short[] noParamList              = new short[]{};
      static final short[] emptyParamList           = new short[] {
          Tokens.OPENBRACKET, Tokens.CLOSEBRACKET
      };
      static final short[] optionalNoParamList      = new short[] {
          Tokens.X_OPTION, 2, Tokens.OPENBRACKET, Tokens.CLOSEBRACKET
      };
      static final short[] singleParamList          = new short[] {
          Tokens.OPENBRACKET, Tokens.QUESTION, Tokens.CLOSEBRACKET
      };
      static final short[] optionalIntegerParamList = new short[] {
          Tokens.X_OPTION, 3, Tokens.OPENBRACKET, Tokens.X_POS_INTEGER,
          Tokens.CLOSEBRACKET
      };
      static final short[] doubleParamList = new short[] {
          Tokens.OPENBRACKET, Tokens.QUESTION, Tokens.COMMA, Tokens.QUESTION,
          Tokens.CLOSEBRACKET
      };
      static final short[] tripleParamList = new short[] {
          Tokens.OPENBRACKET, Tokens.QUESTION, Tokens.COMMA, Tokens.QUESTION,
          Tokens.COMMA, Tokens.QUESTION, Tokens.CLOSEBRACKET
      };
      static final short[] quadParamList = new short[] {
          Tokens.OPENBRACKET, Tokens.QUESTION, Tokens.COMMA, Tokens.QUESTION,
          Tokens.COMMA, Tokens.QUESTION, Tokens.COMMA, Tokens.QUESTION,
          Tokens.CLOSEBRACKET
      };
  
      //
      static IntValueHashMap valueFuncMap   = new IntValueHashMap();
      static IntValueHashMap regularFuncMap = new IntValueHashMap();
  
      static {
          regularFuncMap.put(Tokens.T_POSITION, FUNC_POSITION_CHAR);
          /*
          regularFuncMap.put(Token.T_OCCURENCES_REGEX, FUNC_OCCURENCES_REGEX);
          */
          regularFuncMap.put(Tokens.T_POSITION_REGEX, FUNC_POSITION_REGEX);
          regularFuncMap.put(Tokens.T_EXTRACT, FUNC_EXTRACT);
          regularFuncMap.put(Tokens.T_BIT_LENGTH, FUNC_BIT_LENGTH);
          regularFuncMap.put(Tokens.T_CHAR_LENGTH, FUNC_CHAR_LENGTH);
          regularFuncMap.put(Tokens.T_CHARACTER_LENGTH, FUNC_CHAR_LENGTH);
          regularFuncMap.put(Tokens.T_OCTET_LENGTH, FUNC_OCTET_LENGTH);
          /*
          regularFuncMap.put(Token.T_CARDINALITY, FUNC_CARDINALITY);
          */
          regularFuncMap.put(Tokens.T_ABS, FUNC_ABS);
          regularFuncMap.put(Tokens.T_MOD, FUNC_MOD);
          regularFuncMap.put(Tokens.T_LN, FUNC_LN);
          regularFuncMap.put(Tokens.T_EXP, FUNC_EXP);
          regularFuncMap.put(Tokens.T_POWER, FUNC_POWER);
          regularFuncMap.put(Tokens.T_SQRT, FUNC_SQRT);
          regularFuncMap.put(Tokens.T_FLOOR, FUNC_FLOOR);
          regularFuncMap.put(Tokens.T_CEILING, FUNC_CEILING);
          regularFuncMap.put(Tokens.T_CEIL, FUNC_CEILING);
          regularFuncMap.put(Tokens.T_WIDTH_BUCKET, FUNC_WIDTH_BUCKET);
          regularFuncMap.put(Tokens.T_SUBSTRING, FUNC_SUBSTRING_CHAR);
          /*
          regularFuncMap.put(Token.T_SUBSTRING_REG_EXPR,
                             FUNC_SUBSTRING_REG_EXPR);
          */
          regularFuncMap.put(Tokens.T_SUBSTRING_REGEX, FUNC_SUBSTRING_REGEX);
          regularFuncMap.put(Tokens.T_LOWER, FUNC_FOLD_LOWER);
          regularFuncMap.put(Tokens.T_UPPER, FUNC_FOLD_UPPER);
          /*
          regularFuncMap.put(Token.T_TRANSCODING, FUNC_TRANSCODING);
          regularFuncMap.put(Token.T_TRANSLITERATION, FUNC_TRANSLITERATION);
          regularFuncMap.put(Token.T_TRASLATION,
                             FUNC_REGEX_TRANSLITERATION);
          */
          regularFuncMap.put(Tokens.T_TRIM, FUNC_TRIM_CHAR);
          regularFuncMap.put(Tokens.T_OVERLAY, FUNC_OVERLAY_CHAR);
          /*
          regularFuncMap.put(Token.T_NORMALIZE, FUNC_CHAR_NORMALIZE);
          */
          regularFuncMap.put(Tokens.T_TRIM, FUNC_TRIM_BINARY);
      }
  
      static {
          valueFuncMap.put(Tokens.T_CURRENT_DATE, FUNC_CURRENT_DATE);
          valueFuncMap.put(Tokens.T_CURRENT_TIME, FUNC_CURRENT_TIME);
          valueFuncMap.put(Tokens.T_CURRENT_TIMESTAMP, FUNC_CURRENT_TIMESTAMP);
          valueFuncMap.put(Tokens.T_LOCALTIME, FUNC_LOCALTIME);
          valueFuncMap.put(Tokens.T_LOCALTIMESTAMP, FUNC_LOCALTIMESTAMP);
          valueFuncMap.put(Tokens.T_CURRENT_CATALOG, FUNC_CURRENT_CATALOG);
          /*
          valueFuncMap.put(Token.T_CURRENT_DEFAULT_TRANSFORM_GROUP,
                  FUNC_CURRENT_DEFAULT_TRANSFORM_GROUP);
          */
          valueFuncMap.put(Tokens.T_CURRENT_PATH, FUNC_CURRENT_PATH);
          valueFuncMap.put(Tokens.T_CURRENT_ROLE, FUNC_CURRENT_ROLE);
          valueFuncMap.put(Tokens.T_CURRENT_SCHEMA, FUNC_CURRENT_SCHEMA);
          /*
          valueFuncMap.put(Token.T_CURRENT_TRANSFORM_GROUP_FOR_TYPE,
                  FUNC_CURRENT_TRANSFORM_GROUP_FOR_TYPE);
          */
          valueFuncMap.put(Tokens.T_CURRENT_USER, FUNC_CURRENT_USER);
          valueFuncMap.put(Tokens.T_SESSION_USER, FUNC_SESSION_USER);
          valueFuncMap.put(Tokens.T_SYSTEM_USER, FUNC_SYSTEM_USER);
          valueFuncMap.put(Tokens.T_USER, FUNC_USER);
          valueFuncMap.put(Tokens.T_VALUE, FUNC_VALUE);
      }
  
      //
      int     funcType;
      String  name;
      short[] parseList;
      short[] parseListAlt;
      boolean isValueFunction;
      // A VoltDB extension to control SQL functions,
      // their types and whether they are implemented in VoltDB.
      protected int parameterArg = -1;
      protected String voltDisabled;
      private static String DISABLED_IN_FUNCTIONSQL_CONSTRUCTOR = "SQL Function";
      // End of VoltDB extension
  
      public static FunctionSQL newSQLFunction(String token,
              CompileContext context) {
  
          int id = regularFuncMap.get(token, -1);
  
          if (id == -1) {
              id = valueFuncMap.get(token, -1);
          }
  
          if (id == -1) {
              return null;
          }
  
          FunctionSQL function = new FunctionSQL(id);
  
          if (id == FUNC_VALUE) {
              if (context.currentDomain == null) {
                  return null;
              }
  
              function.dataType = context.currentDomain;
          }
  
          return function;
      }
  
      public static boolean isFunction(String token) {
          return isRegularFunction(token) || isValueFunction(token);
      }
  
      public static boolean isRegularFunction(String token) {
          return regularFuncMap.containsKey(token);
      }
  
      public static boolean isValueFunction(String token) {
          return valueFuncMap.containsKey(token);
      }
  
      protected FunctionSQL() {
  
          super(OpTypes.SQL_FUNCTION);
  
          nodes = Expression.emptyExpressionArray;
      }
  
      protected FunctionSQL(int id) {
  
          this();
  
          this.funcType = id;
  
          switch (id) {
  
              case FUNC_POSITION_CHAR :
              case FUNC_POSITION_BINARY :
                  name      = Tokens.T_POSITION;
                  parseList = new short[] {
                      Tokens.OPENBRACKET, Tokens.QUESTION, Tokens.IN,
                      Tokens.QUESTION, Tokens.X_OPTION, 5, Tokens.USING,
                      Tokens.X_KEYSET, 2, Tokens.CHARACTERS, Tokens.OCTETS,
                      Tokens.CLOSEBRACKET
                  };
                  break;
  
              case FUNC_OCCURENCES_REGEX :
              case FUNC_POSITION_REGEX :
                  // A VoltDB extension to customize the SQL function set support
                  voltDisabled = DISABLED_IN_FUNCTIONSQL_CONSTRUCTOR;
                  // End of VoltDB extension
                  break;
  
              case FUNC_EXTRACT :
                  name      = Tokens.T_EXTRACT;
                  parseList = new short[] {
                      // A VoltDB extension to support more selectors
                      Tokens.OPENBRACKET, Tokens.X_KEYSET, 18, Tokens.YEAR,
                      /* disable 1 line ...
                      Tokens.OPENBRACKET, Tokens.X_KEYSET, 16, Tokens.YEAR,
                      ... disabled 1 line */
                      // End of VoltDB extension
                      Tokens.MONTH, Tokens.DAY, Tokens.HOUR, Tokens.MINUTE,
                      Tokens.SECOND, Tokens.DAY_OF_WEEK, Tokens.WEEK_OF_YEAR,
                      Tokens.QUARTER, Tokens.DAY_OF_YEAR, Tokens.DAY_OF_MONTH,
                      Tokens.DAY_NAME, Tokens.MONTH_NAME,
                      Tokens.SECONDS_MIDNIGHT, Tokens.TIMEZONE_HOUR,
                      // A VoltDB extension to support WEEK, WEEKDAY
                      Tokens.WEEKDAY, Tokens.WEEK,
                      // End of VoltDB extension
                      Tokens.TIMEZONE_MINUTE, Tokens.FROM, Tokens.QUESTION,
                      Tokens.CLOSEBRACKET
                  };
                  break;
  
              case FUNC_CHAR_LENGTH :
                  name      = Tokens.T_CHAR_LENGTH;
                  parseList = new short[] {
                      Tokens.OPENBRACKET, Tokens.QUESTION, Tokens.X_OPTION, 5,
                      Tokens.USING, Tokens.X_KEYSET, 2, Tokens.CHARACTERS,
                      Tokens.OCTETS, Tokens.CLOSEBRACKET
                  };
                  break;
  
              case FUNC_BIT_LENGTH :
                  name      = Tokens.T_BIT_LENGTH;
                  parseList = singleParamList;
                  // A VoltDB extension to customize the SQL function set support
                  voltDisabled = DISABLED_IN_FUNCTIONSQL_CONSTRUCTOR;
                  // End of VoltDB extension
                  break;
  
              case FUNC_OCTET_LENGTH :
                  name      = Tokens.T_OCTET_LENGTH;
                  parseList = singleParamList;
                  break;
  
              case FUNC_CARDINALITY :
                  parseList = singleParamList;
                  // A VoltDB extension to customize the SQL function set support
                  voltDisabled = DISABLED_IN_FUNCTIONSQL_CONSTRUCTOR;
                  // End of VoltDB extension
                  break;
  
              case FUNC_ABS :
                  name      = Tokens.T_ABS;
                  parseList = singleParamList;
                  break;
  
              case FUNC_MOD :
                  name      = Tokens.T_MOD;
                  parseList = singleParamList;
                  // A VoltDB extension to customize the SQL function set support
                  voltDisabled = DISABLED_IN_FUNCTIONSQL_CONSTRUCTOR;
                  // End of VoltDB extension
                  break;
  
              case FUNC_LN :
                  name      = Tokens.T_LN;
                  parseList = singleParamList;
                  // A VoltDB extension to customize the SQL function set support
                  voltDisabled = DISABLED_IN_FUNCTIONSQL_CONSTRUCTOR;
                  // End of VoltDB extension
                  break;
  
              case FUNC_EXP :
                  name      = Tokens.T_EXP;
                  parseList = singleParamList;
                  break;
  
              case FUNC_POWER :
                  name      = Tokens.T_POWER;
                  parseList = doubleParamList;
                  break;
  
              case FUNC_SQRT :
                  name      = Tokens.T_SQRT;
                  parseList = singleParamList;
                  break;
  
              case FUNC_FLOOR :
                  name      = Tokens.T_FLOOR;
                  parseList = singleParamList;
                  break;
  
              case FUNC_CEILING :
                  name      = Tokens.T_CEILING;
                  parseList = singleParamList;
                  break;
  
              case FUNC_WIDTH_BUCKET :
                  name      = Tokens.T_WIDTH_BUCKET;
                  parseList = quadParamList;
                  // A VoltDB extension to customize the SQL function set support
                  voltDisabled = DISABLED_IN_FUNCTIONSQL_CONSTRUCTOR;
                  // End of VoltDB extension
                  break;
  
              // A VoltDB extension to customize the SQL function set support
              case FUNC_SUBSTRING_BINARY :
                  voltDisabled = DISABLED_IN_FUNCTIONSQL_CONSTRUCTOR;
                  // $FALL-THROUGH$
              case FUNC_SUBSTRING_CHAR :
              /* disable 2 lines ...
              case FUNC_SUBSTRING_CHAR :
              case FUNC_SUBSTRING_BINARY :
              ... disabled 2 lines */
              // End of VoltDB extension
                  name      = Tokens.T_SUBSTRING;
                  parseList = new short[] {
                      Tokens.OPENBRACKET, Tokens.QUESTION, Tokens.FROM,
                      Tokens.QUESTION, Tokens.X_OPTION, 2, Tokens.FOR,
                      Tokens.QUESTION, Tokens.X_OPTION, 5, Tokens.USING,
                      Tokens.X_KEYSET, 2, Tokens.CHARACTERS, Tokens.OCTETS,
                      Tokens.CLOSEBRACKET
                  };
                  parseListAlt = new short[] {
                      Tokens.OPENBRACKET, Tokens.QUESTION, Tokens.COMMA,
                      // A VoltDB extension to make the third parameter optional
                      /* disable 1 line ...
                      Tokens.QUESTION, Tokens.COMMA, Tokens.QUESTION,
                      ... disabled 1 line */
                      Tokens.QUESTION, Tokens.X_OPTION, 2, Tokens.COMMA, Tokens.QUESTION,
                      // End of VoltDB extension
                      Tokens.CLOSEBRACKET
                  };
                  break;
  
              /*
              case FUNCTION_SUBSTRING_REG_EXPR :
                  break;
              case FUNCTION_SUBSTRING_REGEX :
                  break;
              */
              case FUNC_FOLD_LOWER :
                  name      = Tokens.T_LOWER;
                  parseList = singleParamList;
                  break;
  
              case FUNC_FOLD_UPPER :
                  name      = Tokens.T_UPPER;
                  parseList = singleParamList;
                  break;
  
              /*
              case FUNCTION_TRANSCODING :
                  break;
              case FUNCTION_TRANSLITERATION :
                  break;
              case FUNCTION_REGEX_TRANSLITERATION :
                  break;
               */
              case FUNC_TRIM_CHAR :
              case FUNC_TRIM_BINARY :
                  name      = Tokens.T_TRIM;
                  parseList = new short[] {
                      Tokens.OPENBRACKET, Tokens.X_OPTION, 11,    //
                      Tokens.X_OPTION, 5,                         //
                      Tokens.X_KEYSET, 3, Tokens.LEADING, Tokens.TRAILING,
                      Tokens.BOTH,                                //
                      Tokens.X_OPTION, 1, Tokens.QUESTION,        //
                      Tokens.FROM, Tokens.QUESTION, Tokens.CLOSEBRACKET
                  };
                  break;
  
              /*
              case FUNCTION_CHAR_NORMALIZE :
                  break;
              */
              // A VoltDB extension to customize the SQL function set support
              case FUNC_OVERLAY_BINARY :
                  voltDisabled = DISABLED_IN_FUNCTIONSQL_CONSTRUCTOR;
                  // $FALL-THROUGH$
              case FUNC_OVERLAY_CHAR :
              /* disable 2 lines ...
              case FUNC_OVERLAY_CHAR :
              case FUNC_OVERLAY_BINARY :
              ... disabled 2 lines */
              // End of VoltDB extension
                  name      = Tokens.T_OVERLAY;
                  parseList = new short[] {
                      Tokens.OPENBRACKET, Tokens.QUESTION, Tokens.PLACING,
                      Tokens.QUESTION, Tokens.FROM, Tokens.QUESTION,
                      Tokens.X_OPTION, 2, Tokens.FOR, Tokens.QUESTION,
                      Tokens.X_OPTION, 2, Tokens.USING, Tokens.CHARACTERS,
                      Tokens.CLOSEBRACKET
                  };
                  break;
  
              case FUNC_CURRENT_CATALOG :
                  name            = Tokens.T_CURRENT_CATALOG;
                  parseList       = noParamList;
                  isValueFunction = true;
                  // A VoltDB extension to customize the SQL function set support
                  voltDisabled = DISABLED_IN_FUNCTIONSQL_CONSTRUCTOR;
                  // End of VoltDB extension
                  break;
  
              /*
              case FUNC_CURRENT_DEFAULT_TRANSFORM_GROUP :
                  break;
              case FUNC_CURRENT_PATH :
                  break;
              */
              case FUNC_CURRENT_ROLE :
                  name            = Tokens.T_CURRENT_ROLE;
                  parseList       = noParamList;
                  isValueFunction = true;
                  // A VoltDB extension to customize the SQL function set support
                  voltDisabled = DISABLED_IN_FUNCTIONSQL_CONSTRUCTOR;
                  // End of VoltDB extension
                  break;
  
              case FUNC_CURRENT_SCHEMA :
                  name            = Tokens.T_CURRENT_SCHEMA;
                  parseList       = noParamList;
                  isValueFunction = true;
                  // A VoltDB extension to customize the SQL function set support
                  voltDisabled = DISABLED_IN_FUNCTIONSQL_CONSTRUCTOR;
                  // End of VoltDB extension
                  break;
  
              /*
              case FUNC_CURRENT_TRANSFORM_GROUP_FOR_TYPE :
                  break;
              */
              case FUNC_CURRENT_USER :
                  name            = Tokens.T_CURRENT_USER;
                  parseList       = noParamList;
                  isValueFunction = true;
                  // A VoltDB extension to customize the SQL function set support
                  voltDisabled = DISABLED_IN_FUNCTIONSQL_CONSTRUCTOR;
                  // End of VoltDB extension
                  break;
  
              case FUNC_SESSION_USER :
                  name            = Tokens.T_SESSION_USER;
                  parseList       = noParamList;
                  isValueFunction = true;
                  // A VoltDB extension to customize the SQL function set support
                  voltDisabled = DISABLED_IN_FUNCTIONSQL_CONSTRUCTOR;
                  // End of VoltDB extension
                  break;
  
              case FUNC_SYSTEM_USER :
                  name            = Tokens.T_SYSTEM_USER;
                  parseList       = noParamList;
                  isValueFunction = true;
                  // A VoltDB extension to customize the SQL function set support
                  voltDisabled = DISABLED_IN_FUNCTIONSQL_CONSTRUCTOR;
                  // End of VoltDB extension
                  break;
  
              case FUNC_USER :
                  name            = Tokens.T_USER;
                  parseList       = optionalNoParamList;
                  isValueFunction = true;
                  // A VoltDB extension to customize the SQL function set support
                  voltDisabled = DISABLED_IN_FUNCTIONSQL_CONSTRUCTOR;
                  // End of VoltDB extension
                  break;
  
              case FUNC_VALUE :
                  name            = Tokens.T_VALUE;
                  parseList       = noParamList;
                  isValueFunction = false;
                  // A VoltDB extension to customize the SQL function set support
                  voltDisabled = DISABLED_IN_FUNCTIONSQL_CONSTRUCTOR;
                  // End of VoltDB extension
                  break;
  
              case FUNC_CURRENT_DATE :
                  name            = Tokens.T_CURRENT_DATE;
                  parseList       = noParamList;
                  isValueFunction = true;
                  // A VoltDB extension to customize the SQL function set support
                  voltDisabled = DISABLED_IN_FUNCTIONSQL_CONSTRUCTOR;
                  // End of VoltDB extension
                  break;
  
              case FUNC_CURRENT_TIME :
                  name            = Tokens.T_CURRENT_TIME;
                  parseList       = optionalIntegerParamList;
                  isValueFunction = true;
                  // A VoltDB extension to customize the SQL function set support
                  voltDisabled = DISABLED_IN_FUNCTIONSQL_CONSTRUCTOR;
                  // End of VoltDB extension
                  break;
  
              case FUNC_CURRENT_TIMESTAMP :
                  name            = Tokens.T_CURRENT_TIMESTAMP;
                  parseList       = optionalIntegerParamList;
                  isValueFunction = true;
                  break;
  
              case FUNC_LOCALTIME :
                  name            = Tokens.T_LOCALTIME;
                  parseList       = optionalIntegerParamList;
                  isValueFunction = true;
                  // A VoltDB extension to customize the SQL function set support
                  voltDisabled = DISABLED_IN_FUNCTIONSQL_CONSTRUCTOR;
                  // End of VoltDB extension
                  break;
  
              case FUNC_LOCALTIMESTAMP :
                  name            = Tokens.T_LOCALTIMESTAMP;
                  parseList       = optionalIntegerParamList;
                  isValueFunction = true;
                  // A VoltDB extension to customize the SQL function set support
                  voltDisabled = DISABLED_IN_FUNCTIONSQL_CONSTRUCTOR;
                  // End of VoltDB extension
                  break;
  
              default :
                  throw Error.runtimeError(ErrorCode.U_S0500, "FunctionSQL");
          }
      }
  
      public void setArguments(Expression[] newNodes) {
          this.nodes = newNodes;
      }
  
      public Expression getFunctionExpression() {
          return this;
      }
  
      /**
       * Evaluates and returns this Function in the context of the session.<p>
       */
      public Object getValue(Session session) {
  
          Object[] data = new Object[nodes.length];
  
          for (int i = 0; i < nodes.length; i++) {
              Expression e = nodes[i];
  
              if (e != null) {
                  data[i] = e.getValue(session, e.dataType);
              }
          }
  
          return getValue(session, data);
      }
  
      Object getValue(Session session, Object[] data) {
  
          switch (funcType) {
  
              case FUNC_POSITION_CHAR : {
                  if (data[0] == null || data[1] == null) {
                      return null;
                  }
  
                  long result =
                      ((CharacterType) nodes[1].dataType).position(
                          session, data[1], data[0], nodes[0].dataType, 0) + 1;
  
                  if (nodes[2] != null
                          && ((Number) nodes[2].valueData).intValue()
                             == Tokens.OCTETS) {
                      result *= 2;
                  }
  
                  return ValuePool.getLong(result);
              }
              case FUNC_POSITION_BINARY : {
                  if (data[0] == null || data[1] == null) {
                      return null;
                  }
  
                  long result =
                      ((BinaryType) nodes[1].dataType).position(
                          session, (BlobData) data[1], (BlobData) data[0],
                          nodes[0].dataType, 0) + 1;
  
                  if (nodes[2] != null
                          && ((Number) nodes[2].valueData).intValue()
                             == Tokens.OCTETS) {
                      result *= 2;
                  }
  
                  return ValuePool.getLong(result);
              }
              /*
              case FUNC_OCCURENCES_REGEX :
              case FUNC_POSITION_REGEX :
              */
              case FUNC_EXTRACT : {
                  if (data[1] == null) {
                      return null;
                  }
  
                  int part = ((Number) nodes[0].valueData).intValue();
  
                  part = DTIType.getFieldNameTypeForToken(part);
  
                  switch (part) {
  
                      case Types.SQL_INTERVAL_SECOND : {
                          return ((DTIType) nodes[1].dataType).getSecondPart(
                              data[1]);
                      }
                      case DTIType.MONTH_NAME :
                      case DTIType.DAY_NAME : {
                          return ((DateTimeType) nodes[1].dataType)
                              .getPartString(session, data[1], part);
                      }
                      default : {
                          int value =
                              ((DTIType) nodes[1].dataType).getPart(session,
                                  data[1], part);
  
                          return ValuePool.getInt(value);
                      }
                  }
              }
              case FUNC_CHAR_LENGTH : {
                  if (data[0] == null) {
                      return null;
                  }
  
                  long result = ((CharacterType) nodes[0].dataType).size(session,
                      data[0]);
  
                  return ValuePool.getLong(result);
              }
              case FUNC_BIT_LENGTH : {
                  if (data[0] == null) {
                      return null;
                  }
  
                  long result;
  
                  if (nodes[0].dataType.isBinaryType()) {
                      result = ((BlobData) data[0]).bitLength(session);
                  } else {
                      result =
                          16 * ((CharacterType) nodes[0].dataType).size(session,
                              data[0]);
                  }
  
                  return ValuePool.getLong(result);
              }
              case FUNC_OCTET_LENGTH : {
                  if (data[0] == null) {
                      return null;
                  }
  
                  long result;
  
                  if (nodes[0].dataType.isBinaryType()) {
                      result = ((BlobData) data[0]).length(session);
                  } else {
                      result =
                          2 * ((CharacterType) nodes[0].dataType).size(session,
                              data[0]);
                  }
  
                  return ValuePool.getLong(result);
              }
              /*
              case FUNC_CARDINALITY :
              */
              case FUNC_ABS : {
                  if (data[0] == null) {
                      return null;
                  }
  
                  return dataType.absolute(data[0]);
              }
              case FUNC_MOD : {
                  if (data[0] == null || data[1] == null) {
                      return null;
                  }
  
                  // non-integral arguments are accepted with conversion
  
                  /** @todo - check if widening has an effect */
                  Object value =
                      ((NumberType) nodes[0].dataType).divide(nodes[0],
                          nodes[1]);
  
                  value = ((NumberType) nodes[0].dataType).subtract(nodes[0],
                          value, nodes[1].dataType);
  
                  // result type is the same as argList[1]
                  return ((NumberType) dataType).convertToTypeLimits(session,
                          value);
              }
              case FUNC_LN : {
                  if (data[0] == null) {
                      return null;
                  }
  
                  double d = ((Number) data[0]).doubleValue();
  
                  if (d <= 0) {
                      throw Error.error(ErrorCode.X_2201E);
                  }
  
                  d = Math.log(d);
  
                  return ValuePool.getDouble(Double.doubleToLongBits(d));
              }
              case FUNC_EXP : {
                  if (data[0] == null) {
                      return null;
                  }
  
                  double val = Math.exp(((Number) data[0]).doubleValue());
                  // A VoltDB extension to tweak compliance with standard sql error handling
                  if (Double.isNaN(val) || Double.isInfinite(val)) {
                      throw Error.error(ErrorCode.X_2201F);
                  }
                  // End of VoltDB extension
  
                  return ValuePool.getDouble(Double.doubleToLongBits(val));
              }
              case FUNC_POWER : {
                  if (data[0] == null || data[1] == null) {
                      return null;
                  }
  
                  double base     = ((Number) data[0]).doubleValue();
                  double exponent = ((Number) data[1]).doubleValue();
                  double val;
  
                  // A VoltDB extension to tweak compliance with standard sql error handling
                  //VOLTDB's HSQL_BACKEND doesn't object to negative exponents -- why should it?
                  /* disable 3 lines ...
                  if (exponent < 0) {
                      throw Error.error(ErrorCode.X_2201F);
                  }
                  ... disabled 2 lines */
                  // End of VoltDB extension
  
                  if (base == 0) {
                      if (exponent < 0) {
                          throw Error.error(ErrorCode.X_2201F);
                      } else if (exponent == 0) {
                          val = 1;
                      } else {
                          val = 0;
                      }
                  } else {
                      val = Math.pow(base, exponent);
                      // A VoltDB extension to tweak compliance with standard sql error handling
                      if (Double.isNaN(val) || Double.isInfinite(val)) {
                          throw Error.error(ErrorCode.X_2201F);
                      }
                      // End of VoltDB extension
                  }
  
                  return ValuePool.getDouble(Double.doubleToLongBits(val));
              }
              case FUNC_SQRT : {
                  if (data[0] == null) {
                      return null;
                  }
  
                  double val = Math.sqrt(((Number) data[0]).doubleValue());
                  // A VoltDB extension to tweak compliance with standard sql error handling
                  if (Double.isNaN(val) || Double.isInfinite(val)) {
                      throw Error.error(ErrorCode.X_2201F);
                  }
                  // End of VoltDB extension
  
                  return ValuePool.getDouble(Double.doubleToLongBits(val));
              }
              case FUNC_FLOOR : {
                  if (data[0] == null) {
                      return null;
                  }
  
                  return ((NumberType) dataType).floor(data[0]);
              }
              case FUNC_CEILING : {
                  if (data[0] == null) {
                      return null;
                  }
  
                  return ((NumberType) dataType).ceiling(data[0]);
              }
              case FUNC_WIDTH_BUCKET : {
                  return null;
              }
              case FUNC_SUBSTRING_CHAR : {
                  if (data[0] == null || data[1] == null) {
                      return null;
                  }
  
                  Object value;
  
                  value = Type.SQL_BIGINT.convertToType(session, data[1],
                                                        nodes[1].dataType);
  
                  long offset = ((Number) value).longValue() - 1;
                  long length = 0;
  
                  // A VoltDB extension to make the third parameter optional and ignored vs. broken and disabled
                  /* disable 1 line ...
                  if (nodes[2] != null) {
                  ... disabled 1 line */
                  if (nodes.length > 2 && nodes[2] != null) {
                  // End of VoltDB extension
                      if (data[2] == null) {
                          return null;
                      }
  
                      value = Type.SQL_BIGINT.convertToType(session, data[2],
                                                            nodes[2].dataType);
                      length = ((Number) value).longValue();
                  }
  
                  // A VoltDB extension to make the fourth parameter optional and ignored vs. broken and disabled
                  /* disable 9 lines ...
                  if (nodes[3] != null
                          && ((Number) nodes[2].valueData).intValue()
                             == Tokens.OCTETS) {
  
                      // not clear what the rules on USING OCTECTS are with UTF
                  }
  
                  return ((CharacterType) dataType).substring(session, data[0],
                          offset, length, nodes[2] != null, false);
                  ... disabled 9 lines */
  
                  return ((CharacterType) dataType).substring(session, data[0],
                          offset, length, (nodes.length > 2 && nodes[2] != null), false);
                  // End of VoltDB extension
              }
              /*
              case FUNCTION_SUBSTRING_REG_EXPR :
                  break;
              case FUNCTION_SUBSTRING_REGEX :
                  break;
              */
              case FUNC_FOLD_LOWER :
                  if (data[0] == null) {
                      return null;
                  }
  
                  return ((CharacterType) dataType).lower(session, data[0]);
  
              case FUNC_FOLD_UPPER :
                  if (data[0] == null) {
                      return null;
                  }
  
                  return ((CharacterType) dataType).upper(session, data[0]);
  
              /*
              case FUNCTION_TRANSCODING :
                  break;
              case FUNCTION_TRANSLITERATION :
                  break;
              case FUNCTION_REGEX_TRANSLITERATION :
                  break;
               */
              case FUNC_TRIM_CHAR : {
                  if (data[1] == null || data[2] == null) {
                      return null;
                  }
  
                  boolean leading  = false;
                  boolean trailing = false;
  
                  switch (((Number) nodes[0].valueData).intValue()) {
  
                      case Tokens.BOTH :
                          leading = trailing = true;
                          break;
  
                      case Tokens.LEADING :
                          leading = true;
                          break;
  
                      case Tokens.TRAILING :
                          trailing = true;
                          break;
  
                      default :
                          throw Error.runtimeError(ErrorCode.U_S0500,
                                                   "FunctionSQL");
                  }
  
                  String string = (String) data[1];
  
                  if (string.length() != 1) {
                      throw Error.error(ErrorCode.X_22027);
                  }
  
                  int character = string.charAt(0);
  
                  return ((CharacterType) dataType).trim(session, data[2],
                                                         character, leading,
                                                         trailing);
              }
              case FUNC_OVERLAY_CHAR : {
                  if (data[0] == null || data[1] == null || data[2] == null) {
                      return null;
                  }
  
                  Object value;
  
                  value = Type.SQL_BIGINT.convertToType(session, data[2],
                                                        nodes[2].dataType);
  
                  long offset = ((Number) value).longValue() - 1;
                  long length = 0;
  
                  if (nodes[3] != null) {
                      if (data[3] == null) {
                          return null;
                      }
  
                      value = Type.SQL_BIGINT.convertToType(session, data[3],
                                                            nodes[3].dataType);
                      length = ((Number) value).longValue();
                  }
  
                  return ((CharacterType) dataType).overlay(null, data[0],
                          data[1], offset, length, nodes[3] != null);
              }
              /*
              case FUNCTION_CHAR_NORMALIZE :
                  break;
              */
              case FUNC_SUBSTRING_BINARY : {
                  if (data[0] == null || data[1] == null) {
                      return null;
                  }
  
                  Object value;
  
                  value = Type.SQL_BIGINT.convertToType(session, data[1],
                                                        nodes[1].dataType);
  
                  long offset = ((Number) value).longValue() - 1;
                  long length = 0;
  
                  if (nodes[2] != null) {
                      if (data[2] == null) {
                          return null;
                      }
  
                      value = Type.SQL_BIGINT.convertToType(session, data[2],
                                                            nodes[2].dataType);
                      length = ((Number) value).intValue();
                  }
  
                  return ((BinaryType) dataType).substring(session,
                          (BlobData) data[0], offset, length, nodes[2] != null);
              }
              case FUNC_TRIM_BINARY : {
                  if (data[1] == null || data[2] == null) {
                      return null;
                  }
  
                  boolean leading  = false;
                  boolean trailing = false;
                  int     spec     = ((Number) nodes[0].valueData).intValue();
  
                  switch (spec) {
  
                      case Tokens.BOTH :
                          leading = trailing = true;
                          break;
  
                      case Tokens.LEADING :
                          leading = true;
                          break;
  
                      case Tokens.TRAILING :
                          trailing = true;
                          break;
  
                      default :
                          throw Error.runtimeError(ErrorCode.U_S0500,
                                                   "FunctionSQL");
                  }
  
                  BlobData string = (BlobData) data[1];
  
                  if (string.length(session) != 1) {
                      throw Error.error(ErrorCode.X_22027);
                  }
  
                  byte[] bytes = string.getBytes();
  
                  return ((BinaryType) dataType).trim(session,
                                                      (BlobData) data[3],
                                                      bytes[0], leading,
                                                      trailing);
              }
              case FUNC_OVERLAY_BINARY : {
                  if (data[0] == null || data[1] == null || data[2] == null) {
                      return null;
                  }
  
                  Object value;
  
                  value = Type.SQL_BIGINT.convertToType(session, data[2],
                                                        nodes[2].dataType);
  
                  long offset = ((Number) value).longValue() - 1;
                  long length = 0;
  
                  if (nodes[3] != null) {
                      if (data[3] == null) {
                          return null;
                      }
  
                      value = Type.SQL_BIGINT.convertToType(session, data[3],
                                                            nodes[3].dataType);
                      length = ((Number) value).longValue();
                  }
  
                  return ((BinaryType) dataType).overlay(session,
                                                         (BlobData) data[0],
                                                         (BlobData) data[1],
                                                         offset, length,
                                                         nodes[3] != null);
              }
              case FUNC_CURRENT_CATALOG :
                  return session.database.getCatalogName().name;
  
              /*
              case FUNC_CURRENT_DEFAULT_TRANSFORM_GROUP :
              case FUNC_CURRENT_PATH :
              */
              case FUNC_CURRENT_ROLE :
                  return null;
  
              case FUNC_CURRENT_SCHEMA :
                  return session.currentSchema.name;
  
              /*
              case FUNC_CURRENT_TRANSFORM_GROUP_FOR_TYPE :
              */
              case FUNC_CURRENT_USER :
                  return session.getGrantee().getNameString();
  
              case FUNC_SESSION_USER :
                  return session.getGrantee().getNameString();
  
              case FUNC_SYSTEM_USER :
                  return session.getGrantee().getNameString();
  
              case FUNC_USER :
                  return session.getGrantee().getNameString();
  
              case FUNC_VALUE :
                  return session.sessionData.currentValue;
  
              case FUNC_CURRENT_DATE :
                  return session.getCurrentDate();
  
              case FUNC_CURRENT_TIME :
                  return dataType.convertToTypeLimits(
                      session, session.getCurrentTime(true));
  
              case FUNC_CURRENT_TIMESTAMP :
                  return dataType.convertToTypeLimits(
                      session, session.getCurrentTimestamp(true));
  
              case FUNC_LOCALTIME :
                  return dataType.convertToTypeLimits(
                      session, session.getCurrentTime(false));
  
              case FUNC_LOCALTIMESTAMP :
                  return dataType.convertToTypeLimits(
                      session, session.getCurrentTimestamp(false));
  
              default :
                  throw Error.runtimeError(ErrorCode.U_S0500, "FunctionSQL");
          }
      }
  
      public void resolveTypes(Session session, Expression parent) {
  
          for (int i = 0; i < nodes.length; i++) {
              if (nodes[i] != null) {
                  nodes[i].resolveTypes(session, this);
              }
          }
  
          switch (funcType) {
  
              case FUNC_POSITION_CHAR :
              case FUNC_POSITION_BINARY : {
                  if (nodes[0].dataType == null) {
                      if (nodes[1].dataType == null) {
                          throw Error.error(ErrorCode.X_42567);
                      }
  
                      if (nodes[1].dataType.typeCode == Types.SQL_CLOB
                              || nodes[1].dataType.isBinaryType()) {
                          nodes[0].dataType = nodes[1].dataType;
                      } else {
                          nodes[0].dataType = Type.SQL_VARCHAR_DEFAULT;
                      }
                  }
  
                  if (nodes[1].dataType == null) {
                      if (nodes[0].dataType.typeCode == Types.SQL_CLOB
                              || nodes[0].dataType.isBinaryType()) {
                          nodes[1].dataType = nodes[0].dataType;
                      } else {
                          nodes[1].dataType = Type.SQL_VARCHAR_DEFAULT;
                      }
                  }
  
                  if (nodes[0].dataType.isCharacterType()
                          && nodes[1].dataType.isCharacterType()) {
                      funcType = FUNC_POSITION_CHAR;
                  } else if (nodes[0].dataType.isBinaryType()
                             && nodes[1].dataType.isBinaryType()) {
                      if (nodes[0].dataType.isBitType()
                              || nodes[1].dataType.isBitType()) {
                          throw Error.error(ErrorCode.X_42565);
                      }
  
                      funcType = FUNC_POSITION_BINARY;
                  } else {
                      throw Error.error(ErrorCode.X_42565);
                  }
  
                  dataType = Type.SQL_BIGINT;
  
                  break;
              }
              /*
              case FUNC_OCCURENCES_REGEX :
              case FUNC_POSITION_REGEX :
              */
              case FUNC_EXTRACT : {
                  if (nodes[1].dataType == null) {
                      throw Error.error(ErrorCode.X_42567);
                  }
  
                  if (!nodes[1].dataType.isDateTimeType()
                          && !nodes[1].dataType.isIntervalType()) {
                      throw Error.error(ErrorCode.X_42565);
                  }
  
                  int     part = ((Number) nodes[0].valueData).intValue();
                  DTIType type = (DTIType) nodes[1].dataType;
  
                  part     = DTIType.getFieldNameTypeForToken(part);
                  dataType = type.getExtractType(part);
  
                  break;
              }
              case FUNC_BIT_LENGTH : {
                  if (nodes[0].dataType == null) {
                      nodes[0].dataType = Type.SQL_BIT_VARYING_MAX_LENGTH;
                  }
  
                  if (!nodes[0].dataType.isCharacterType()
                          && !nodes[0].dataType.isBinaryType()) {
                      throw Error.error(ErrorCode.X_42565);
                  }
  
                  dataType = Type.SQL_BIGINT;
  
                  break;
              }
              case FUNC_CHAR_LENGTH :
                  if (!nodes[0].dataType.isCharacterType()) {
                      throw Error.error(ErrorCode.X_42565);
                  }
  
              // $FALL-THROUGH$
              case FUNC_OCTET_LENGTH : {
                  if (nodes[0].dataType == null) {
                      nodes[0].dataType = Type.SQL_VARCHAR_DEFAULT;
                  }
  
                  if (!nodes[0].dataType.isCharacterType()
                          && !nodes[0].dataType.isBinaryType()) {
                      throw Error.error(ErrorCode.X_42565);
                  }
  
                  dataType = Type.SQL_BIGINT;
  
                  break;
              }
              case FUNC_CARDINALITY : {
                  dataType = Type.SQL_BIGINT;
  
                  break;
              }
              case FUNC_MOD : {
                  if (nodes[0].dataType == null) {
                      nodes[1].dataType = nodes[0].dataType;
                  }
  
                  if (nodes[1].dataType == null) {
                      nodes[0].dataType = nodes[1].dataType;
                  }
  
                  if (nodes[0].dataType == null) {
                      throw Error.error(ErrorCode.X_42567);
                  }
  
                  if (!nodes[0].dataType.isNumberType()
                          || !nodes[1].dataType.isNumberType()) {
                      throw Error.error(ErrorCode.X_42565);
                  }
  
                  nodes[0].dataType =
                      ((NumberType) nodes[0].dataType).getIntegralType();
                  nodes[1].dataType =
                      ((NumberType) nodes[1].dataType).getIntegralType();
                  dataType = nodes[1].dataType;
                  // A VoltDB extension to customize the SQL function set support
                  parameterArg = 1;
                  // End of VoltDB extension
  
                  break;
              }
              case FUNC_POWER : {
                  if (nodes[0].dataType == null) {
                      // A VoltDB extension to customize the SQL function set support
                      // VoltDB swapped out this odd propagation of nulls.
                      // VoltDB simply gives missing types the benefit of the doubt.
                      nodes[0].dataType = Type.SQL_DOUBLE;
                      // For VoltDB, the retest for null below is now redundant.
                      /* disable 1 line ...
                      nodes[1].dataType = nodes[0].dataType;
                      ... disabled 1 line */
                      // End of VoltDB extension
                  }
  
                  if (nodes[1].dataType == null) {
                      // VoltDB swapped out this odd propagation of nulls.
                      // ORIGINAL HSQL CODE: nodes[0].dataType = nodes[1].dataType;
                      // VoltDB simply gives missing types the benefit of the doubt.
                      nodes[1].dataType = Type.SQL_DOUBLE;
                      // A VoltDB extension to customize the SQL function set support
                      // VoltDB swapped out this odd propagation of nulls.
                      /* disable 1 line ...
                      nodes[0].dataType = nodes[1].dataType;
                      ... disabled 1 line */
                      // End of VoltDB extension
                  }
  
                  if (nodes[0].dataType == null) {
                      throw Error.error(ErrorCode.X_42567);
                  }
  
                  if (!nodes[0].dataType.isNumberType()
                          || !nodes[1].dataType.isNumberType()) {
                      throw Error.error(ErrorCode.X_42565);
                  }
  
                  nodes[0].dataType = Type.SQL_DOUBLE;
                  nodes[1].dataType = Type.SQL_DOUBLE;
                  dataType          = Type.SQL_DOUBLE;
  
                  break;
              }
              case FUNC_LN :
              case FUNC_EXP :
              case FUNC_SQRT : {
                  if (nodes[0].dataType == null) {
                      nodes[0].dataType = Type.SQL_DOUBLE;
                  }
  
                  if (!nodes[0].dataType.isNumberType()) {
                      throw Error.error(ErrorCode.X_42565);
                  }
  
                  nodes[0].dataType = Type.SQL_DOUBLE;
                  dataType          = Type.SQL_DOUBLE;
  
                  break;
              }
              case FUNC_ABS :
                  if (nodes[0].dataType != null
                          && nodes[0].dataType.isIntervalType()) {
                      dataType = nodes[0].dataType;
                      // A VoltDB extension to customize the SQL function set support
                      parameterArg = 0;
                      // End of VoltDB extension
  
                      break;
                  }
  
              // $FALL-THROUGH$
              case FUNC_FLOOR :
              case FUNC_CEILING : {
                  if (nodes[0].dataType == null) {
                      nodes[0].dataType = Type.SQL_DOUBLE;
                  }
  
  