private VectorExpression getBetweenExpression(List<ExprNodeDesc> childExpr,
      VectorExpressionDescriptor.Mode mode, TypeInfo returnType)
          throws HiveException {

    boolean hasDynamicValues = false;

    // We don't currently support the BETWEEN ends being columns.  They must be scalars.
    if ((childExpr.get(2) instanceof ExprNodeDynamicValueDesc) &&
        (childExpr.get(3) instanceof ExprNodeDynamicValueDesc)) {
      hasDynamicValues = true;
      if (mode == VectorExpressionDescriptor.Mode.PROJECTION) {

        // Projection mode is not applicable.
        return null;
      }
    } else if (!(childExpr.get(2) instanceof ExprNodeConstantDesc) ||
        !(childExpr.get(3) instanceof ExprNodeConstantDesc)) {
      return null;
    }

    boolean notKeywordPresent = (Boolean) ((ExprNodeConstantDesc) childExpr.get(0)).getValue();
    ExprNodeDesc colExpr = childExpr.get(1);

    // The children after not, might need a cast. Get common types for the two comparisons.
    // Casting for 'between' is handled here as a special case, because the first child is for NOT and doesn't need
    // cast
    TypeInfo commonType = FunctionRegistry.getCommonClassForComparison(childExpr.get(1).getTypeInfo(),
        childExpr.get(2).getTypeInfo());
    if (commonType == null) {

      // Can't vectorize
      return null;
    }
    commonType = FunctionRegistry.getCommonClassForComparison(commonType, childExpr.get(3).getTypeInfo());
    if (commonType == null) {

      // Can't vectorize
      return null;
    }

    List<ExprNodeDesc> castChildren = new ArrayList<>();
    boolean wereCastUdfs = false;
    Category commonTypeCategory = commonType.getCategory();
    for (ExprNodeDesc desc: childExpr.subList(1, 4)) {
      TypeInfo childTypeInfo = desc.getTypeInfo();
      Category childCategory = childTypeInfo.getCategory();

      if (childCategory != commonTypeCategory) {
        return null;
      }
      final boolean isNeedsCast;
      if (commonTypeCategory == Category.PRIMITIVE) {

        // Do not to strict TypeInfo comparisons for DECIMAL -- just compare the category.
        // Otherwise, we generate unnecessary casts.
        isNeedsCast =
            ((PrimitiveTypeInfo) commonType).getPrimitiveCategory() !=
            ((PrimitiveTypeInfo) childTypeInfo).getPrimitiveCategory();
      } else {
        isNeedsCast = !commonType.equals(desc.getTypeInfo());
      }

      if (!isNeedsCast) {
        castChildren.add(desc);
      } else {
        GenericUDF castUdf = getGenericUDFForCast(commonType);
        ExprNodeGenericFuncDesc engfd = new ExprNodeGenericFuncDesc(commonType, castUdf,
            Arrays.asList(new ExprNodeDesc[] { desc }));
        castChildren.add(engfd);
        wereCastUdfs = true;
      }
    }
    String colType = commonType.getTypeName();

    // prepare arguments for createVectorExpression
    List<ExprNodeDesc> childrenAfterNot = evaluateCastOnConstants(castChildren);

    // determine class
    Class<?> cl = null;
    if (isIntFamily(colType) && !notKeywordPresent) {
      if (mode == VectorExpressionDescriptor.Mode.PROJECTION) {
        cl = LongColumnBetween.class;
      } else {
        cl = (hasDynamicValues ?
            FilterLongColumnBetweenDynamicValue.class :
            FilterLongColumnBetween.class);
      }
    } else if (isIntFamily(colType) && notKeywordPresent) {
      if (mode == VectorExpressionDescriptor.Mode.PROJECTION) {
        cl = LongColumnNotBetween.class;
      } else {
        cl = FilterLongColumnNotBetween.class;
      }
    } else if (isFloatFamily(colType) && !notKeywordPresent) {
      if (mode == VectorExpressionDescriptor.Mode.PROJECTION) {
        cl = DoubleColumnBetween.class;
      } else {
        cl = (hasDynamicValues ?
            FilterDoubleColumnBetweenDynamicValue.class :
            FilterDoubleColumnBetween.class);
      }
    } else if (isFloatFamily(colType) && notKeywordPresent) {
      if (mode == VectorExpressionDescriptor.Mode.PROJECTION) {
        cl = DoubleColumnNotBetween.class;
      } else {
        cl = FilterDoubleColumnNotBetween.class;
      }
    } else if (colType.equals(serdeConstants.STRING_TYPE_NAME) && !notKeywordPresent) {
      if (mode == VectorExpressionDescriptor.Mode.PROJECTION) {
        cl = StringColumnBetween.class;
      } else {
        cl = (hasDynamicValues ?
            FilterStringColumnBetweenDynamicValue.class :
            FilterStringColumnBetween.class);
      }
    } else if (colType.equals(serdeConstants.STRING_TYPE_NAME) && notKeywordPresent) {
      if (mode == VectorExpressionDescriptor.Mode.PROJECTION) {
        cl = StringColumnNotBetween.class;
      } else {
        cl = FilterStringColumnNotBetween.class;
      }
    } else if (varcharTypePattern.matcher(colType).matches() && !notKeywordPresent) {
      if (mode == VectorExpressionDescriptor.Mode.PROJECTION) {
        cl = VarCharColumnBetween.class;
      } else {
        cl = (hasDynamicValues ?
            FilterVarCharColumnBetweenDynamicValue.class :
            FilterVarCharColumnBetween.class);
      }
    } else if (varcharTypePattern.matcher(colType).matches() && notKeywordPresent) {
      if (mode == VectorExpressionDescriptor.Mode.PROJECTION) {
        cl = VarCharColumnNotBetween.class;
      } else {
        cl = FilterVarCharColumnNotBetween.class;
      }
    } else if (charTypePattern.matcher(colType).matches() && !notKeywordPresent) {
      if (mode == VectorExpressionDescriptor.Mode.PROJECTION) {
        cl = CharColumnBetween.class;
      } else {
        cl =  (hasDynamicValues ?
            FilterCharColumnBetweenDynamicValue.class :
            FilterCharColumnBetween.class);
      }
    } else if (charTypePattern.matcher(colType).matches() && notKeywordPresent) {
      if (mode == VectorExpressionDescriptor.Mode.PROJECTION) {
        cl = CharColumnNotBetween.class;
      } else {
        cl = FilterCharColumnNotBetween.class;
      }
    } else if (colType.equals(serdeConstants.TIMESTAMP_TYPE_NAME) && !notKeywordPresent) {
      if (mode == VectorExpressionDescriptor.Mode.PROJECTION) {
        cl = TimestampColumnBetween.class;
      } else {
        cl = (hasDynamicValues ?
            FilterTimestampColumnBetweenDynamicValue.class :
            FilterTimestampColumnBetween.class);
      }
    } else if (colType.equals(serdeConstants.TIMESTAMP_TYPE_NAME) && notKeywordPresent) {
      if (mode == VectorExpressionDescriptor.Mode.PROJECTION) {
        cl = TimestampColumnNotBetween.class;
      } else {
        cl = FilterTimestampColumnNotBetween.class;
      }
    } else if (isDecimalFamily(colType) && !notKeywordPresent) {
      final boolean tryDecimal64 =
          checkExprNodeDescForDecimal64(colExpr) && !wereCastUdfs && !hasDynamicValues;
      if (tryDecimal64) {
        VectorExpression decimal64VecExpr =
            tryDecimal64Between(
                mode, /* isNot */ false, colExpr, childrenAfterNot,
                 returnType);
        if (decimal64VecExpr != null) {
          return decimal64VecExpr;
        }
      }
      if (mode == VectorExpressionDescriptor.Mode.PROJECTION) {
        cl = DecimalColumnBetween.class;
      } else {
        cl = (hasDynamicValues ?
            FilterDecimalColumnBetweenDynamicValue.class :
            FilterDecimalColumnBetween.class);
      }
    } else if (isDecimalFamily(colType) && notKeywordPresent) {
      final boolean tryDecimal64 =
          checkExprNodeDescForDecimal64(colExpr) && !wereCastUdfs && !hasDynamicValues;
      if (tryDecimal64) {
        VectorExpression decimal64VecExpr =
            tryDecimal64Between(
                mode, /* isNot */ true, colExpr, childrenAfterNot, returnType);
        if (decimal64VecExpr != null) {
          return decimal64VecExpr;
        }
      }
      if (mode == VectorExpressionDescriptor.Mode.PROJECTION) {
        cl = DecimalColumnNotBetween.class;
      } else {
        cl = FilterDecimalColumnNotBetween.class;
      }
    } else if (isDateFamily(colType) && !notKeywordPresent) {
      if (mode == VectorExpressionDescriptor.Mode.PROJECTION) {
        cl = LongColumnBetween.class;
      } else {
        cl =  (hasDynamicValues ?
            FilterDateColumnBetweenDynamicValue.class :
            FilterLongColumnBetween.class);
      }
    } else if (isDateFamily(colType) && notKeywordPresent) {
      if (mode == VectorExpressionDescriptor.Mode.PROJECTION) {
        cl = LongColumnNotBetween.class;
      } else {
        cl = FilterLongColumnNotBetween.class;
      }
    }
    return createVectorExpression(
        cl, childrenAfterNot, VectorExpressionDescriptor.Mode.PROJECTION, returnType, DataTypePhysicalVariation.NONE);
  }
Invoke special handling for expressions that can't be vectorized by regular
descriptor based lookup.
ql/src/java/org/apache/hadoop/hive/ql/exec/vector/VectorizationContext.java