All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jaxdb.jsql.function Maven / Gradle / Ivy

/* Copyright (c) 2017 JAX-DB
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * You should have received a copy of The MIT License (MIT) along with this
 * program. If not, see .
 */

package org.jaxdb.jsql;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.sql.SQLException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

import org.libj.math.BigInt;
import org.libj.math.SafeMath;
import org.libj.util.ArrayUtil;

final class function {
  // FIXME: Is this the right MathContext?
  private static final MathContext mc = new MathContext(65, RoundingMode.DOWN);

  static final class Function implements operation.Operation {
    static final class PI extends expression.Expression implements exp.DOUBLE {
      @Override
      data.Column getColumn() {
        return new data.DOUBLE();
      }

      @Override
      Number evaluate(final java.util.Set visited) {
        return Math.PI;
      }

      @Override
      void compile(final Compilation compilation, final boolean isExpression) throws IOException, SQLException {
        compilation.compiler.compilePi(compilation);
      }
    }

    static final class NOW extends expression.Expression implements exp.DATETIME {
      @Override
      data.Column getColumn() {
        return new data.DATETIME();
      }

      @Override
      LocalDateTime evaluate(final java.util.Set visited) {
        return LocalDateTime.now();
      }

      @Override
      void compile(final Compilation compilation, final boolean isExpression) throws IOException, SQLException {
        compilation.compiler.compileNow(compilation);
      }
    }
  }

  abstract static class Function1 implements operation.Operation1 {
    static final Function1 ABS = new Function1() {
      @Override
      public void compile(final type.Column a, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileAbs(a, compilation);
      }

      @Override
      public Number evaluate(final Number a) {
        if (a == null)
          return null;

        if (a instanceof Float)
          return SafeMath.abs(a.floatValue());

        if (a instanceof Double)
          return SafeMath.abs(a.doubleValue());

        if (a instanceof Byte || a instanceof Short || a instanceof Integer)
          return SafeMath.abs(a.intValue());

        if (a instanceof Long)
          return SafeMath.abs(a.longValue());

        if (a instanceof BigInt)
          return ((BigInt)a).clone().abs();

        if (a instanceof BigDecimal)
          return SafeMath.abs((BigDecimal)a);

        throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");
      }
    };

    static final Function1 SIGN = new Function1() {
      @Override
      public void compile(final type.Column a, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileSign(a, compilation);
      }

      @Override
      public Number evaluate(final Number a) {
        if (a == null)
          return null;

        if (a instanceof Float)
          return SafeMath.signum(a.floatValue());

        if (a instanceof Byte)
          return (byte)SafeMath.signum(a.floatValue());

        if (a instanceof Short)
          return (short)SafeMath.signum(a.floatValue());

        if (a instanceof Double)
          return SafeMath.signum(a.doubleValue());

        if (a instanceof Integer)
          return (int)SafeMath.signum(a.doubleValue());

        if (a instanceof Long)
          return (long)SafeMath.signum(a.doubleValue());

        if (a instanceof BigInt)
          return new BigInt(((BigInt)a).signum());

        if (a instanceof BigDecimal)
          return BigDecimal.valueOf(((BigDecimal)a).signum());

        throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");
      }
    };

    static final Function1 FLOOR = new Function1() {
      @Override
      public void compile(final type.Column a, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileFloor(a, compilation);
      }

      @Override
      public Number evaluate(final Number a) {
        if (a == null)
          return null;

        if (a instanceof Byte || a instanceof Short || a instanceof Integer || a instanceof Long || a instanceof BigInt)
          return a;

        if (a instanceof Float)
          return SafeMath.floor(a.floatValue());

        if (a instanceof Double)
          return SafeMath.floor(a.doubleValue());

        if (a instanceof BigDecimal)
          return SafeMath.floor((BigDecimal)a);

        throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");
      }
    };

    static final Function1 CEIL = new Function1() {
      @Override
      public void compile(final type.Column a, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileCeil(a, compilation);
      }

      @Override
      public Number evaluate(final Number a) {
        if (a == null)
          return null;

        if (a instanceof Byte || a instanceof Short || a instanceof Integer || a instanceof Long || a instanceof BigInt)
          return a;

        if (a instanceof Float)
          return SafeMath.ceil(a.floatValue());

        if (a instanceof Double)
          return SafeMath.ceil(a.doubleValue());

        if (a instanceof BigDecimal)
          return SafeMath.ceil((BigDecimal)a);

        throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");
      }
    };

    static final Function1 DEGREES = new Function1() {
      @Override
      public void compile(final type.Column a, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileDegrees(a, compilation);
      }

      @Override
      public Number evaluate(final Number a) {
        if (a == null)
          return null;

        // FIXME: Not sure if casting back to a's type is correct here.
        if (a instanceof Float)
          return (float)SafeMath.toDegrees(a.doubleValue());

        if (a instanceof Double)
          return Math.toDegrees(a.doubleValue());

        if (a instanceof Byte)
          return (byte)SafeMath.toDegrees(a.floatValue());

        if (a instanceof Short)
          return (short)SafeMath.toDegrees(a.shortValue());

        if (a instanceof Integer)
          return (int)SafeMath.toDegrees(a.intValue());

        if (a instanceof Long)
          return (long)SafeMath.toDegrees(a.longValue());

        if (a instanceof BigInt)
          return SafeMath.toDegrees(((BigInt)a).toBigDecimal(), mc);

        if (a instanceof BigDecimal)
          return SafeMath.toDegrees(((BigDecimal)a), mc);

        throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");
      }
    };

    static final Function1 RADIANS = new Function1() {
      @Override
      public void compile(final type.Column a, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileRadians(a, compilation);
      }

      @Override
      public Number evaluate(final Number a) {
        if (a == null)
          return null;

        // FIXME: Not sure if casting back to a's type is correct here.
        if (a instanceof Float)
          return (float)SafeMath.toRadians(a.doubleValue());

        if (a instanceof Double)
          return Math.toRadians(a.doubleValue());

        if (a instanceof Byte)
          return (byte)SafeMath.toRadians(a.floatValue());

        if (a instanceof Short)
          return (short)SafeMath.toRadians(a.shortValue());

        if (a instanceof Integer)
          return (int)SafeMath.toRadians(a.intValue());

        if (a instanceof Long)
          return (long)SafeMath.toRadians(a.longValue());

        if (a instanceof BigInt)
          return SafeMath.toRadians(((BigInt)a).toBigDecimal(), mc);

        if (a instanceof BigDecimal)
          return SafeMath.toRadians(((BigDecimal)a), mc);

        throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");
      }
    };

    static final Function1 SQRT = new Function1() {
      @Override
      public void compile(final type.Column a, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileSqrt(a, compilation);
      }

      @Override
      public Number evaluate(final Number a) {
        if (a == null)
          return null;

        // FIXME: Not sure if casting back to a's type is correct here.
        if (a instanceof Float)
          return (float)SafeMath.sqrt(a.floatValue());

        if (a instanceof Double)
          return SafeMath.sqrt(a.doubleValue());

        if (a instanceof Byte)
          return (byte)SafeMath.sqrt(a.floatValue());

        if (a instanceof Short)
          return (short)SafeMath.sqrt(a.shortValue());

        if (a instanceof Integer)
          return (int)SafeMath.sqrt(a.intValue());

        if (a instanceof Long)
          return (long)SafeMath.sqrt(a.longValue());

        if (a instanceof BigInt)
          return ((BigInt)a).sqrt();

        if (a instanceof BigDecimal)
          return SafeMath.sqrt((BigDecimal)a, mc);

        throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");
      }
    };

    static final Function1 SIN = new Function1() {
      @Override
      public void compile(final type.Column a, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileSin(a, compilation);
      }

      @Override
      public Number evaluate(final Number a) {
        if (a == null)
          return null;

        if (a instanceof Float)
          return (float)SafeMath.sin(a.floatValue());

        if (a instanceof Double)
          return SafeMath.sin(a.doubleValue());

        if (a instanceof Byte)
          return (byte)SafeMath.sin(a.byteValue());

        if (a instanceof Short)
          return (short)SafeMath.sin(a.shortValue());

        if (a instanceof Integer)
          return (int)SafeMath.sin(a.intValue());

        if (a instanceof Long)
          return (long)SafeMath.sin(a.longValue());

        if (a instanceof BigInt) // FIXME: Implement efficient alternative
          return SafeMath.sin(((BigInt)a).toBigInteger(), mc);

        if (a instanceof BigDecimal)
          return SafeMath.sin((BigDecimal)a, mc);

        throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");
      }
    };

    static final Function1 ASIN = new Function1() {
      @Override
      public void compile(final type.Column a, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileAsin(a, compilation);
      }

      @Override
      public Number evaluate(final Number a) {
        if (a == null)
          return null;

        if (a instanceof Float)
          return (float)SafeMath.asin(a.floatValue());

        if (a instanceof Double)
          return SafeMath.asin(a.doubleValue());

        if (a instanceof Byte)
          return (byte)SafeMath.asin(a.byteValue());

        if (a instanceof Short)
          return (short)SafeMath.asin(a.shortValue());

        if (a instanceof Integer)
          return (int)SafeMath.asin(a.intValue());

        if (a instanceof Long)
          return (long)SafeMath.asin(a.longValue());

        // FIXME: Need to figure out what should be the return type of these functions
        // FIXME: Probably: Highest possible precision type given input types
        if (a instanceof BigInt) // FIXME: Implement efficient alternative
          return SafeMath.asin(((BigInt)a).toBigInteger(), mc);

        if (a instanceof BigDecimal)
          return SafeMath.asin((BigDecimal)a, mc);

        throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");
      }
    };

    static final Function1 COS = new Function1() {
      @Override
      public void compile(final type.Column a, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileCos(a, compilation);
      }

      @Override
      public Number evaluate(final Number a) {
        if (a == null)
          return null;

        if (a instanceof Float)
          return (float)SafeMath.cos(a.floatValue());

        if (a instanceof Double)
          return SafeMath.cos(a.doubleValue());

        if (a instanceof Byte)
          return (byte)SafeMath.cos(a.byteValue());

        if (a instanceof Short)
          return (short)SafeMath.cos(a.shortValue());

        if (a instanceof Integer)
          return (int)SafeMath.cos(a.intValue());

        if (a instanceof Long)
          return (long)SafeMath.cos(a.longValue());

        if (a instanceof BigInt) // FIXME: Implement efficient alternative
          return SafeMath.cos(((BigInt)a).toBigInteger(), mc);

        if (a instanceof BigDecimal)
          return SafeMath.cos((BigDecimal)a, mc);

        throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");
      }
    };

    static final Function1 ACOS = new Function1() {
      @Override
      public void compile(final type.Column a, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileAcos(a, compilation);
      }

      @Override
      public Number evaluate(final Number a) {
        if (a == null)
          return null;

        if (a instanceof Float)
          return (float)SafeMath.acos(a.floatValue());

        if (a instanceof Double)
          return SafeMath.acos(a.doubleValue());

        if (a instanceof Byte)
          return (byte)SafeMath.acos(a.byteValue());

        if (a instanceof Short)
          return (short)SafeMath.acos(a.shortValue());

        if (a instanceof Integer)
          return (int)SafeMath.acos(a.intValue());

        if (a instanceof Long)
          return (long)SafeMath.acos(a.longValue());

        if (a instanceof BigInt) // FIXME: Implement efficient alternative
          return SafeMath.acos(((BigInt)a).toBigInteger(), mc);

        if (a instanceof BigDecimal)
          return SafeMath.acos((BigDecimal)a, mc);

        throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");
      }
    };

    static final Function1 TAN = new Function1() {
      @Override
      public void compile(final type.Column a, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileTan(a, compilation);
      }

      @Override
      public Number evaluate(final Number a) {
        if (a == null)
          return null;

        if (a instanceof Float)
          return (float)SafeMath.tan(a.floatValue());

        if (a instanceof Double)
          return SafeMath.tan(a.doubleValue());

        if (a instanceof Byte)
          return (byte)SafeMath.tan(a.byteValue());

        if (a instanceof Short)
          return (short)SafeMath.tan(a.shortValue());

        if (a instanceof Integer)
          return (int)SafeMath.tan(a.intValue());

        if (a instanceof Long)
          return (long)SafeMath.tan(a.longValue());

        if (a instanceof BigInt) // FIXME: Implement efficient alternative
          return SafeMath.tan(((BigInt)a).toBigInteger(), mc);

        if (a instanceof BigDecimal)
          return SafeMath.tan((BigDecimal)a, mc);

        throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");
      }
    };

    static final Function1 ATAN = new Function1() {
      @Override
      public void compile(final type.Column a, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileAtan(a, compilation);
      }

      @Override
      public Number evaluate(final Number a) {
        if (a == null)
          return null;

        if (a instanceof Float)
          return (float)SafeMath.atan(a.floatValue());

        if (a instanceof Double)
          return SafeMath.atan(a.doubleValue());

        if (a instanceof Byte)
          return (byte)SafeMath.atan(a.byteValue());

        if (a instanceof Short)
          return (short)SafeMath.atan(a.shortValue());

        if (a instanceof Integer)
          return (int)SafeMath.atan(a.intValue());

        if (a instanceof Long)
          return (long)SafeMath.atan(a.longValue());

        if (a instanceof BigInt) // FIXME: Implement efficient alternative
          return SafeMath.atan(((BigInt)a).toBigInteger(), mc);

        if (a instanceof BigDecimal)
          return SafeMath.atan((BigDecimal)a, mc);

        throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");
      }
    };

    static final Function1 EXP = new Function1() {
      @Override
      public void compile(final type.Column a, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileExp(a, compilation);
      }

      @Override
      public Number evaluate(final Number a) {
        if (a == null)
          return null;

        if (a instanceof Float)
          return (float)SafeMath.exp(a.floatValue());

        if (a instanceof Double)
          return SafeMath.exp(a.doubleValue());

        if (a instanceof Byte)
          return (byte)SafeMath.exp(a.byteValue());

        if (a instanceof Short)
          return (short)SafeMath.exp(a.shortValue());

        if (a instanceof Integer)
          return (int)SafeMath.exp(a.intValue());

        if (a instanceof Long)
          return (long)SafeMath.exp(a.longValue());

        if (a instanceof BigInt) // FIXME: Implement efficient alternative
          return SafeMath.exp(((BigInt)a).toBigInteger(), mc);

        if (a instanceof BigDecimal)
          return SafeMath.exp((BigDecimal)a, mc);

        throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");
      }
    };

    static final Function1 LN = new Function1() {
      @Override
      public void compile(final type.Column a, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileLn(a, compilation);
      }

      @Override
      public Number evaluate(final Number a) {
        if (a == null)
          return null;

        if (a instanceof Float || a instanceof Double || a instanceof Byte || a instanceof Short || a instanceof Integer || a instanceof Long)
          return SafeMath.log(a.floatValue());

        if (a instanceof BigInt) // FIXME: Implement efficient alternative
          return SafeMath.log(((BigInt)a).toBigDecimal(), mc);

        if (a instanceof BigDecimal)
          return SafeMath.log((BigDecimal)a, mc);

        throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");
      }
    };

    static final Function1 LOG2 = new Function1() {
      @Override
      public void compile(final type.Column a, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileLog2(a, compilation);
      }

      @Override
      public Number evaluate(final Number a) {
        if (a == null)
          return null;

        if (a instanceof Float || a instanceof Double || a instanceof Byte || a instanceof Short || a instanceof Integer || a instanceof Long)
          return SafeMath.log2(a.doubleValue());

        if (a instanceof BigInt)
          return SafeMath.log2(((BigInt)a).toBigDecimal(), mc);

        if (a instanceof BigDecimal)
          return SafeMath.log2((BigDecimal)a, mc);

        throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");
      }
    };

    static final Function1 LOG10 = new Function1() {
      @Override
      public void compile(final type.Column a, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileLog10(a, compilation);
      }

      @Override
      public Number evaluate(final Number a) {
        if (a == null)
          return null;

        if (a instanceof Float || a instanceof Double || a instanceof Byte || a instanceof Short || a instanceof Integer || a instanceof Long)
          return SafeMath.log10(a.doubleValue());

        if (a instanceof BigInt)
          return SafeMath.log10(((BigInt)a).toBigDecimal(), mc);

        if (a instanceof BigDecimal)
          return SafeMath.log10((BigDecimal)a, mc);

        throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");
      }
    };

    static final Function1 ROUND = new Function1() {
      @Override
      public void compile(final type.Column a, final Compilation compilation) throws IOException, SQLException {
        final Subject subject = (Subject)a;
        final data.Column column = subject.getColumn();
        if (column instanceof data.ExactNumeric)
          subject.compile(compilation, true);
        else
          compilation.compiler.compileRound(a, compilation);
      }

      @Override
      public Number evaluate(final Number a) {
        if (a == null)
          return null;

        if (a instanceof Byte || a instanceof Short || a instanceof Integer || a instanceof Long || a instanceof BigInt)
          return a;

        if (a instanceof Float)
          return SafeMath.round(a.floatValue(), RoundingMode.HALF_UP);

        if (a instanceof Double)
          return SafeMath.round(a.doubleValue(), RoundingMode.HALF_UP);

        if (a instanceof BigDecimal)
          return SafeMath.round((BigDecimal)a, 0, RoundingMode.HALF_UP);

        throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");
      }
    };
  }

  abstract static class Function2 implements operation.Operation2 {
    static final Function2 ATAN2 = new Function2() {
      @Override
      public void compile(final type.Column a, final type.Column b, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileAtan2(a, b, compilation);
      }

      @Override
      public Number evaluate(final Number a, final Number b) {
        if (a instanceof Float || a instanceof Double || a instanceof Byte || a instanceof Short || a instanceof Integer || a instanceof Long) {
          if (b instanceof Float || b instanceof Double || b instanceof Byte || b instanceof Short || b instanceof Integer || b instanceof Long)
            return SafeMath.atan2(a.doubleValue(), b.doubleValue());

          if (b instanceof BigInt) // FIXME: Implement efficient alternative
            return SafeMath.atan2(BigDecimal.valueOf(a.doubleValue()), ((BigInt)b).toBigDecimal(), mc);

          if (b instanceof BigDecimal)
            return SafeMath.atan2(BigDecimal.valueOf(a.doubleValue()), (BigDecimal)b, mc);

          throw new UnsupportedOperationException(b.getClass().getName() + " is not a supported Number type");
        }

        if (a instanceof BigInt) {
          if (b instanceof Float || b instanceof Double || b instanceof Byte || b instanceof Short || b instanceof Integer || b instanceof Long)
            return SafeMath.atan2(((BigInt)a).toBigDecimal(), BigDecimal.valueOf(b.doubleValue()), mc);

          if (b instanceof BigInt)
            return SafeMath.atan2(((BigInt)a).toBigDecimal(), ((BigInt)b).toBigDecimal(), mc);

          if (b instanceof BigDecimal)
            return SafeMath.atan2(((BigInt)a).toBigDecimal(), (BigDecimal)b, mc);

          throw new UnsupportedOperationException(b.getClass().getName() + " is not a supported Number type");
        }

        if (a instanceof BigDecimal) {
          if (b instanceof Float || b instanceof Double || b instanceof Byte || b instanceof Short || b instanceof Integer || b instanceof Long)
            return SafeMath.atan2((BigDecimal)a, BigDecimal.valueOf(b.doubleValue()), mc);

          if (b instanceof BigInt)
            return SafeMath.atan2((BigDecimal)a, ((BigInt)b).toBigDecimal(), mc);

          if (b instanceof BigDecimal)
            return SafeMath.atan2((BigDecimal)a, (BigDecimal)b, mc);

          throw new UnsupportedOperationException(b.getClass().getName() + " is not a supported Number type");
        }

        throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");
      }
    };

    static final Function2 LOG = new Function2() {
      @Override
      public void compile(final type.Column a, final type.Column b, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileLog(a, b, compilation);
      }

      @Override
      public Number evaluate(final Number a, final Number b) {
        if (a instanceof Float || a instanceof Double || a instanceof Byte || a instanceof Short || a instanceof Integer || a instanceof Long) {
          if (b instanceof Float || b instanceof Double || b instanceof Byte || b instanceof Short || b instanceof Integer || b instanceof Long)
            return SafeMath.log(a.doubleValue(), b.doubleValue());

          if (b instanceof BigInt) // FIXME: Implement efficient alternative
            return SafeMath.log(BigDecimal.valueOf(a.doubleValue()), ((BigInt)b).toBigDecimal(), mc);

          if (b instanceof BigDecimal)
            return SafeMath.log(BigDecimal.valueOf(a.doubleValue()), (BigDecimal)b, mc);

          throw new UnsupportedOperationException(b.getClass().getName() + " is not a supported Number type");
        }

        if (a instanceof BigInt) {
          if (b instanceof Float || b instanceof Double || b instanceof Byte || b instanceof Short || b instanceof Integer || b instanceof Long)
            return SafeMath.log(((BigInt)a).toBigDecimal(), BigDecimal.valueOf(b.doubleValue()), mc);

          if (b instanceof BigInt)
            return SafeMath.log(((BigInt)a).toBigDecimal(), ((BigInt)b).toBigDecimal(), mc);

          if (b instanceof BigDecimal)
            return SafeMath.log(((BigInt)a).toBigDecimal(), (BigDecimal)b, mc);

          throw new UnsupportedOperationException(b.getClass().getName() + " is not a supported Number type");
        }

        if (a instanceof BigDecimal) {
          if (b instanceof Float || b instanceof Double || b instanceof Byte || b instanceof Short || b instanceof Integer || b instanceof Long)
            return SafeMath.log((BigDecimal)a, BigDecimal.valueOf(b.doubleValue()), mc);

          if (b instanceof BigInt)
            return SafeMath.log((BigDecimal)a, ((BigInt)b).toBigDecimal(), mc);

          if (b instanceof BigDecimal)
            return SafeMath.log((BigDecimal)a, (BigDecimal)b, mc);

          throw new UnsupportedOperationException(b.getClass().getName() + " is not a supported Number type");
        }

        throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");
      }
    };

    static final Function2 MOD = new Function2() {
      @Override
      public void compile(final type.Column a, final type.Column b, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileMod(a, b, compilation);
      }

      @Override
      public Number evaluate(final Number a, final Number b) {
        if (a instanceof Float) {
          if (b instanceof Float)
            return a.floatValue() % b.floatValue();

          if (b instanceof Double)
            return a.floatValue() % b.doubleValue();

          if (b instanceof Byte)
            return a.floatValue() % b.byteValue();

          if (b instanceof Short)
            return a.floatValue() % b.shortValue();

          if (b instanceof Integer)
            return a.floatValue() % b.intValue();

          if (b instanceof Long)
            return a.floatValue() % b.longValue();

          if (b instanceof BigInt) // FIXME: Implement efficient alternative
            return new BigDecimal(a.floatValue(), mc).remainder(((BigInt)b).toBigDecimal()).floatValue();

          if (b instanceof BigDecimal)
            return BigDecimal.valueOf(a.floatValue()).remainder((BigDecimal)b).floatValue();

          throw new UnsupportedOperationException(b.getClass().getName() + " is not a supported Number type");
        }

        if (a instanceof Double) {
          if (b instanceof Float)
            return a.doubleValue() % b.floatValue();

          if (b instanceof Double)
            return a.doubleValue() % b.doubleValue();

          if (b instanceof Byte)
            return a.doubleValue() % b.byteValue();

          if (b instanceof Short)
            return a.doubleValue() % b.shortValue();

          if (b instanceof Integer)
            return a.doubleValue() % b.intValue();

          if (b instanceof Long)
            return a.doubleValue() % b.longValue();

          if (b instanceof BigInt) // FIXME: Implement efficient alternative
            return BigDecimal.valueOf(a.doubleValue()).remainder(((BigInt)b).toBigDecimal()).doubleValue();

          if (b instanceof BigDecimal)
            return BigDecimal.valueOf(a.doubleValue()).remainder((BigDecimal)b).doubleValue();

          throw new UnsupportedOperationException(b.getClass().getName() + " is not a supported Number type");
        }

        if (a instanceof Byte) {
          if (b instanceof Float)
            return(a.byteValue() % b.floatValue());

          if (b instanceof Double)
            return a.byteValue() % b.doubleValue();

          if (b instanceof Byte)
            return a.byteValue() % b.byteValue();

          if (b instanceof Short)
            return a.byteValue() % b.shortValue();

          if (b instanceof Integer)
            return a.byteValue() % b.intValue();

          if (b instanceof Long)
            return a.byteValue() % b.longValue();

          if (b instanceof BigInt)
            return BigDecimal.valueOf(a.byteValue()).remainder(((BigInt)b).toBigDecimal()).doubleValue();

          if (b instanceof BigDecimal)
            return BigDecimal.valueOf(a.byteValue()).remainder((BigDecimal)b).byteValue();

          throw new UnsupportedOperationException(b.getClass().getName() + " is not a supported Number type");
        }

        if (a instanceof Short) {
          if (b instanceof Float)
            return a.shortValue() % b.floatValue();

          if (b instanceof Double)
            return a.shortValue() % b.doubleValue();

          if (b instanceof Byte)
            return a.shortValue() % b.byteValue();

          if (b instanceof Short)
            return a.shortValue() % b.shortValue();

          if (b instanceof Integer)
            return a.shortValue() % b.intValue();

          if (b instanceof Long)
            return a.shortValue() % b.longValue();

          if (b instanceof BigInt)
            return BigDecimal.valueOf(a.shortValue()).remainder(((BigInt)b).toBigDecimal()).doubleValue();

          if (b instanceof BigDecimal)
            return BigDecimal.valueOf(a.shortValue()).remainder((BigDecimal)b).shortValue();

          throw new UnsupportedOperationException(b.getClass().getName() + " is not a supported Number type");
        }

        if (a instanceof Integer) {
          if (b instanceof Float)
            return a.intValue() % b.floatValue();

          if (b instanceof Double)
            return a.intValue() % b.doubleValue();

          if (b instanceof Byte)
            return a.intValue() % b.byteValue();

          if (b instanceof Short)
            return a.intValue() % b.shortValue();

          if (b instanceof Integer)
            return a.intValue() % b.intValue();

          if (b instanceof Long)
            return (int)(a.intValue() % b.longValue());

          if (b instanceof BigInt)
            return BigDecimal.valueOf(a.intValue()).remainder(((BigInt)b).toBigDecimal()).doubleValue();

          if (b instanceof BigDecimal)
            return BigDecimal.valueOf(a.intValue()).remainder((BigDecimal)b).intValue();

          throw new UnsupportedOperationException(b.getClass().getName() + " is not a supported Number type");
        }

        if (a instanceof Long) {
          if (b instanceof Float)
            return a.longValue() % b.floatValue();

          if (b instanceof Double)
            return a.longValue() % b.doubleValue();

          if (b instanceof Byte)
            return a.longValue() % b.byteValue();

          if (b instanceof Short)
            return a.longValue() % b.shortValue();

          if (b instanceof Integer)
            return (int)(a.longValue() % b.intValue());

          if (b instanceof Long)
            return a.longValue() % b.longValue();

          if (b instanceof BigInt)
            return BigDecimal.valueOf(a.longValue()).remainder(((BigInt)b).toBigDecimal()).doubleValue();

          if (b instanceof BigDecimal)
            return BigDecimal.valueOf(a.longValue()).remainder((BigDecimal)b).longValue();

          throw new UnsupportedOperationException(b.getClass().getName() + " is not a supported Number type");
        }

        if (a instanceof BigInt) {
          if (b instanceof Float)
            return ((BigInt)a).toBigDecimal().remainder(BigDecimal.valueOf(b.doubleValue())).floatValue();

          if (b instanceof Double)
            return ((BigInt)a).toBigDecimal().remainder(BigDecimal.valueOf(b.doubleValue())).doubleValue();

          if (b instanceof Byte)
            return ((BigInt)a).mod(new BigInt(b.byteValue())).byteValue();

          if (b instanceof Short)
            return ((BigInt)a).mod(new BigInt(b.shortValue())).shortValue();

          if (b instanceof BigInt)
            return ((BigInt)a).mod(new BigInt(b.intValue())).intValue();

          if (b instanceof Long)
            return ((BigInt)a).mod(new BigInt(b.longValue())).longValue();

          if (b instanceof BigInt)
            return ((BigInt)a).mod((BigInt)b);

          if (b instanceof BigDecimal)
            return ((BigInt)a).toBigDecimal().remainder((BigDecimal)b);

          throw new UnsupportedOperationException(b.getClass().getName() + " is not a supported Number type");
        }

        if (a instanceof BigDecimal) {
          if (b instanceof Float)
            return ((BigDecimal)a).remainder(BigDecimal.valueOf(b.floatValue()));

          if (b instanceof Double)
            return ((BigDecimal)a).remainder(BigDecimal.valueOf(b.doubleValue()));

          if (b instanceof Byte)
            return ((BigDecimal)a).remainder(BigDecimal.valueOf(b.byteValue()));

          if (b instanceof Short)
            return ((BigDecimal)a).remainder(BigDecimal.valueOf(b.shortValue()));

          if (b instanceof Integer)
            return ((BigDecimal)a).remainder(BigDecimal.valueOf(b.intValue()));

          if (b instanceof Long)
            return ((BigDecimal)a).remainder(BigDecimal.valueOf(b.longValue()));

          if (b instanceof BigInt)
            return ((BigDecimal)a).remainder(((BigInt)b).toBigDecimal());

          if (b instanceof BigDecimal)
            return ((BigDecimal)a).remainder((BigDecimal)b);

          throw new UnsupportedOperationException(b.getClass().getName() + " is not a supported Number type");
        }

        throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");
      }
    };

    static final Function2 POW = new Function2() {
      @Override
      public void compile(final type.Column a, final type.Column b, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compilePow(a, b, compilation);
      }

      @Override
      public Number evaluate(final Number a, final Number b) {
        if (a instanceof Float || a instanceof Double || a instanceof Byte || a instanceof Short || a instanceof Integer || a instanceof Long) {
          if (b instanceof Float || b instanceof Double || b instanceof Byte || b instanceof Short || b instanceof Integer || b instanceof Long)
            return SafeMath.pow(a.doubleValue(), b.doubleValue());

          if (b instanceof BigInt)
            return SafeMath.pow(BigDecimal.valueOf(a.doubleValue()), ((BigInt)b).toBigDecimal(), mc);

          if (b instanceof BigDecimal)
            return SafeMath.pow(BigDecimal.valueOf(a.doubleValue()), (BigDecimal)b, mc);

          throw new UnsupportedOperationException(b.getClass().getName() + " is not a supported Number type");
        }

        final BigDecimal bigDecimal;
        if (a instanceof BigDecimal)
          bigDecimal = (BigDecimal)a;
        else
          throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");

        if (b instanceof Float || b instanceof Double)
          return SafeMath.pow(bigDecimal, BigDecimal.valueOf(b.doubleValue()), mc);

        if (b instanceof BigDecimal)
          return SafeMath.pow(bigDecimal, (BigDecimal)b, mc);

        if (b instanceof Byte || b instanceof Short || b instanceof Integer || b instanceof Long)
          return SafeMath.pow(bigDecimal, BigDecimal.valueOf(b.longValue()), mc);

        if (b instanceof BigInt)
          return SafeMath.pow(bigDecimal, ((BigInt)b).toBigDecimal(), mc);

        throw new UnsupportedOperationException(b.getClass().getName() + " is not a supported Number type");
      }
    };

    static final Function2 ROUND = new Function2() {
      @Override
      public void compile(final type.Column a, final type.Column b, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileRound(a, b, compilation);
      }

      @Override
      public Number evaluate(final Number a, final Number b) {
        if (a instanceof Byte || a instanceof Short || a instanceof Integer || a instanceof Long || a instanceof BigInt)
          return a;

        if (a instanceof Float)
          return SafeMath.round(a.floatValue(), b.intValue());

        if (a instanceof Double)
          return SafeMath.round(a.doubleValue(), b.intValue());

        if (a instanceof BigDecimal)
          return SafeMath.round((BigDecimal)a, b.intValue());

        throw new UnsupportedOperationException(a.getClass().getName() + " is not a supported Number type");
      }
    };
  }

  abstract static class NumericOperator2 implements operation.Operation2 {
    static final Addition ADD = new Addition() {
      @Override
      public void compile(final type.Column a, final type.Column b, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileAdd(a, b, compilation);
      }

      @Override
      float evaluate(final float a, final float b) {
        return a + b;
      }

      @Override
      double evaluate(final double a, final double b) {
        return a + b;
      }

      @Override
      Number evaluate(final byte a, final byte b) {
        return a + b;
      }

      @Override
      Number evaluate(final short a, final short b) {
        return a + b;
      }

      @Override
      Number evaluate(final int a, final int b) {
        return a + b;
      }

      @Override
      Number evaluate(final long a, final long b) {
        return a + b;
      }

      @Override
      Number evaluate(final BigInt a, final BigInt b) {
        return a.clone().add(b);
      }

      @Override
      Number evaluate(final BigDecimal a, final BigDecimal b) {
        return a.add(b);
      }

      @Override
      LocalDate evaluate(final LocalDate a, final Interval b) {
        return b.addTo(a);
      }

      @Override
      LocalDateTime evaluate(final LocalDateTime a, final Interval b) {
        return b.addTo(a);
      }

      @Override
      LocalTime evaluate(final LocalTime a, final Interval b) {
        return b.addTo(a);
      }
    };

    static final Addition SUB = new Addition() {
      @Override
      public void compile(final type.Column a, final type.Column b, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileSub(a, b, compilation);
      }

      @Override
      float evaluate(final float a, final float b) {
        return a - b;
      }

      @Override
      double evaluate(final double a, final double b) {
        return a - b;
      }

      @Override
      Number evaluate(final byte a, final byte b) {
        return a - b;
      }

      @Override
      Number evaluate(final short a, final short b) {
        return a - b;
      }

      @Override
      Number evaluate(final int a, final int b) {
        return a - b;
      }

      @Override
      Number evaluate(final long a, final long b) {
        return a - b;
      }

      @Override
      Number evaluate(final BigInt a, final BigInt b) {
        return a.clone().sub(b);
      }

      @Override
      Number evaluate(final BigDecimal a, final BigDecimal b) {
        return a.subtract(b);
      }

      @Override
      LocalDate evaluate(final LocalDate a, final Interval b) {
        return b.subtractFrom(a);
      }

      @Override
      LocalDateTime evaluate(final LocalDateTime a, final Interval b) {
        return b.subtractFrom(a);
      }

      @Override
      LocalTime evaluate(final LocalTime a, final Interval b) {
        return b.subtractFrom(a);
      }
    };

    static final Arithmetic MUL = new Arithmetic() {
      @Override
      public void compile(final type.Column a, final type.Column b, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileMul(a, b, compilation);
      }

      @Override
      float evaluate(final float a, final float b) {
        return a * b;
      }

      @Override
      double evaluate(final double a, final double b) {
        return a * b;
      }

      @Override
      Number evaluate(final byte a, final byte b) {
        return a * b;
      }

      @Override
      Number evaluate(final short a, final short b) {
        return a * b;
      }

      @Override
      Number evaluate(final int a, final int b) {
        return a * b;
      }

      @Override
      Number evaluate(final long a, final long b) {
        return a * b;
      }

      @Override
      Number evaluate(final BigInt a, final BigInt b) {
        return a.clone().mul(b);
      }

      @Override
      Number evaluate(final BigDecimal a, final BigDecimal b) {
        return a.multiply(b);
      }
    };

    static final Arithmetic DIV = new Arithmetic() {
      @Override
      public void compile(final type.Column a, final type.Column b, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileDiv(a, b, compilation);
      }

      @Override
      float evaluate(final float a, final float b) {
        return a / b;
      }

      @Override
      double evaluate(final double a, final double b) {
        return a / b;
      }

      @Override
      Number evaluate(final byte a, final byte b) {
        return a / b;
      }

      @Override
      Number evaluate(final short a, final short b) {
        return a / b;
      }

      @Override
      Number evaluate(final int a, final int b) {
        return a / b;
      }

      @Override
      Number evaluate(final long a, final long b) {
        return a / b;
      }

      @Override
      Number evaluate(final BigInt a, final BigInt b) {
        return a.clone().div(b);
      }

      @Override
      Number evaluate(final BigDecimal a, final BigDecimal b) {
        return a.divide(b, RoundingMode.HALF_UP);
      }
    };
  }

  abstract static class Arithmetic extends NumericOperator2 {
    @Override
    public Number evaluate(final Number a, final Number b) {
      if (a == null || b == null)
        return null;

      if (a instanceof Float) {
        if (b instanceof Float || b instanceof Byte || b instanceof Short || b instanceof Integer)
          return evaluate(a.floatValue(), b.floatValue());

        if (b instanceof Double || b instanceof Long)
          return evaluate(a.doubleValue(), b.doubleValue());

        final BigDecimal bigDecimal;
        if (b instanceof BigDecimal)
          bigDecimal = (BigDecimal)b;
        else if (b instanceof BigInt)
          bigDecimal = ((BigInt)b).toBigDecimal();
        else
          throw new UnsupportedOperationException("Unsupported Number type: " + b.getClass().getName());

        return evaluate(BigDecimal.valueOf(a.floatValue()), bigDecimal);
      }

      if (a instanceof Double) {
        if (b instanceof Float || b instanceof Double || b instanceof Byte || b instanceof Short || b instanceof Integer || b instanceof Long)
          return evaluate(a.doubleValue(), b.doubleValue());

        final BigDecimal bigDecimal;
        if (b instanceof BigDecimal)
          bigDecimal = (BigDecimal)b;
        else if (b instanceof BigInt)
          bigDecimal = ((BigInt)b).toBigDecimal();
        else
          throw new UnsupportedOperationException("Unsupported Number type: " + b.getClass().getName());

        return evaluate(BigDecimal.valueOf(a.doubleValue()), bigDecimal);
      }

      if (a instanceof Byte) {
        if (b instanceof Float)
          return evaluate(a.floatValue(), b.floatValue());

        if (b instanceof Double)
          return evaluate(a.doubleValue(), b.doubleValue());

        if (b instanceof Byte)
          return evaluate(a.byteValue(), b.byteValue());

        if (b instanceof Short)
          return evaluate(a.shortValue(), b.shortValue());

        if (b instanceof Integer)
          return evaluate(a.intValue(), b.intValue());

        if (b instanceof Long)
          return evaluate(a.longValue(), b.longValue());

        if (b instanceof BigInt)
          return evaluate(new BigInt(a.longValue()), (BigInt)b);

        if (b instanceof BigDecimal)
          return evaluate(BigDecimal.valueOf(a.doubleValue()), (BigDecimal)b);

        throw new UnsupportedOperationException("Unsupported Number type: " + b.getClass().getName());
      }

      if (a instanceof Short) {
        if (b instanceof Float)
          return evaluate(a.floatValue(), b.floatValue());

        if (b instanceof Double)
          return evaluate(a.doubleValue(), b.doubleValue());

        if (b instanceof Byte || b instanceof Short)
          return evaluate(a.shortValue(), b.shortValue());

        if (b instanceof Integer)
          return evaluate(a.intValue(), b.intValue());

        if (b instanceof Long)
          return evaluate(a.longValue(), b.longValue());

        if (b instanceof BigInt)
          return evaluate(new BigInt(a.longValue()), (BigInt)b);

        if (b instanceof BigDecimal)
          return evaluate(BigDecimal.valueOf(a.doubleValue()), (BigDecimal)b);

        throw new UnsupportedOperationException("Unsupported Number type: " + b.getClass().getName());
      }

      if (a instanceof Integer) {
        if (b instanceof Float || b instanceof Double)
          return evaluate(a.doubleValue(), b.doubleValue());

        if (b instanceof Byte || b instanceof Short || b instanceof Integer)
          return evaluate(a.intValue(), b.intValue());

        if (b instanceof Long)
          return evaluate(a.longValue(), b.longValue());

        if (b instanceof BigInt)
          return evaluate(new BigInt(a.longValue()), (BigInt)b);

        if (b instanceof BigDecimal)
          return evaluate(BigDecimal.valueOf(a.doubleValue()), (BigDecimal)b);

        throw new UnsupportedOperationException("Unsupported Number type: " + b.getClass().getName());
      }

      if (a instanceof Long) {
        if (b instanceof Float || b instanceof Double)
          return evaluate(a.doubleValue(), b.doubleValue());

        if (b instanceof Byte || b instanceof Short || b instanceof Integer || b instanceof Long)
          return evaluate(a.longValue(), b.longValue());

        if (b instanceof BigInt)
          return evaluate(new BigInt(a.longValue()), (BigInt)b);

        if (b instanceof BigDecimal)
          return evaluate(BigDecimal.valueOf(a.doubleValue()), (BigDecimal)b);

        throw new UnsupportedOperationException("Unsupported Number type: " + b.getClass().getName());
      }

      if (a instanceof BigInt) {
        if (b instanceof BigInt)
          return evaluate((BigInt)a, (BigInt)b);

        if (b instanceof BigDecimal)
          return evaluate(((BigInt)a).toBigDecimal(), (BigDecimal)b);

        if (b instanceof Float || b instanceof Double)
          return evaluate(a, BigDecimal.valueOf(b.doubleValue()));

        if (b instanceof Byte || b instanceof Short || b instanceof Integer || b instanceof Long)
          return evaluate((BigInt)a, new BigInt(b.longValue()));

        throw new UnsupportedOperationException("Unsupported Number type: " + b.getClass().getName());
      }

      if (a instanceof BigDecimal) {
        if (b instanceof BigInt)
          return evaluate((BigDecimal)a, ((BigInt)b).toBigDecimal());

        if (b instanceof BigDecimal)
          return evaluate((BigDecimal)a, (BigDecimal)b);

        if (b instanceof Float || b instanceof Double)
          return evaluate((BigDecimal)a, BigDecimal.valueOf(b.doubleValue()));

        if (b instanceof Byte || b instanceof Short || b instanceof Integer || b instanceof Long)
          return evaluate((BigDecimal)a, BigDecimal.valueOf(b.longValue()));

        throw new UnsupportedOperationException("Unsupported Number type: " + b.getClass().getName());
      }

      throw new UnsupportedOperationException("Unsupported Number type: " + b.getClass().getName());
    }

    abstract float evaluate(float a, float b);
    abstract double evaluate(double a, double b);
    abstract Number evaluate(byte a, byte b);
    abstract Number evaluate(short a, short b);
    abstract Number evaluate(int a, int b);
    abstract Number evaluate(long a, long b);
    abstract Number evaluate(BigInt a, BigInt b);
    abstract Number evaluate(BigDecimal a, BigDecimal b);
  }

  abstract static class Addition extends Arithmetic {
    abstract LocalDate evaluate(LocalDate a, Interval b);
    abstract LocalDateTime evaluate(LocalDateTime a, Interval b);
    abstract LocalTime evaluate(LocalTime a, Interval b);
  }

  static final class Varchar {
    static final StringN CONCAT = new StringN() {
      @Override
      String evaluate(final String ... strings) {
        return ArrayUtil.toString(strings, ' ');
      }
    };

    static final String1 LOWER_CASE = new String1() {
      @Override
      public void compile(final type.Column a, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileLower(a, compilation);
      }

      @Override
      public String evaluate(final String a) {
        return a == null ? null : a.toLowerCase();
      }
    };

    static final String1 UPPER_CASE = new String1() {
      @Override
      public void compile(final type.Column a, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileUpper(a, compilation);
      }

      @Override
      public String evaluate(final String a) {
        return a == null ? null : a.toUpperCase();
      }
    };

    static final operation.Operation1 LENGTH = new operation.Operation1() {
      @Override
      public void compile(final type.Column a, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileLength(a, compilation);
      }

      @Override
      public Integer evaluate(final String a) {
        return a == null ? null : a.length();
      }
    };

    static final operation.Operation3 SUBSTRING = new operation.Operation3() {
      @Override
      public void compile(final type.Column a, final type.Column from, final type.Column to, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileSubstring(a, from, to, compilation);
      }

      @Override
      public String evaluate(final String a, final Integer b, final Integer c) {
        return a == null ? null : a.substring(b != null ? b - 1 : 0, c != null ? c - 1 : a.length());
      }
    };
  }

  abstract static class String1 implements operation.Operation1 {
  }

  abstract static class String2 implements operation.Operation2 {
  }

  abstract static class StringN implements operation.Operation {
    abstract String evaluate(String ... strings);
  }

  abstract static class Set implements operation.Operation {
    abstract void compile(type.Column a, boolean distinct, Compilation compilation) throws IOException, SQLException;

    static final Set SUM = new Set() {
      @Override
      public void compile(final type.Column a, final boolean distinct, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileSum(a, distinct, compilation);
      }
    };
    // FIXME: Remove all these string operators, and put them into the Compiler class
    static final Set AVG = new Set() {
      @Override
      public void compile(final type.Column a, final boolean distinct, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileAvg(a, distinct, compilation);
      }
    };
    static final Set MAX = new Set() {
      @Override
      public void compile(final type.Column a, final boolean distinct, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileMax(a, distinct, compilation);
      }
    };
    static final Set MIN = new Set() {
      @Override
      public void compile(final type.Column a, final boolean distinct, final Compilation compilation) throws IOException, SQLException {
        compilation.compiler.compileMin(a, distinct, compilation);
      }
    };
  }

  private function() {
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy