/**********************************************************************
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
**********************************************************************/

#include <limits>
#include <float.h>
#include "nawstring.h"
#include "QRDescGenerator.h"
#include "NumericType.h"
#include "DatetimeType.h"
#include "QRLogger.h"
#include "OptRange.h"
#include "ItemLog.h"
#include "ComCextdecs.h"

double getDoubleValue(ConstValue* val, logLevel level);

/**
 * Returns the Int64 value corresponding to the type of the ConstValue val.
 * val can be of any numeric, datetime, or interval type. The returned value
 * is used in the representation of a range of values implied by the predicates
 * of a query for an exact numeric, datetime, or interval type.
 *
 * @param val ConstValue that wraps the value to be represented as an Int64.
 * @param rangeColType The type of the column or expr the range is for.
 * @param [out] truncated TRUE returned if the value returned was the result of
 *                        truncating the input value. This can happen for floating
 *                        point input, or exact numeric input that has greater
 *                        scale than rangeColType.
 * @param [out] valWasNegative TRUE returned if the input value was negative.
 *                             Adjustment of truncated values is only done for
 *                             positive values (because the truncation of a negative
 *                             value adjusts it correctly). The caller can't just
 *                             look at the returned value, because if it is 0, it
 *                             may have been truncated from a small negative (-1 < n < 0)
 *                             or a small positive (0 < n < 1) value.
 * @param level Logging level to use in event of failure.
 * @return The rangespec internal representation of the input constant value.
 */
static Int64 getInt64Value(ConstValue* val, const NAType* rangeColType,
                           NABoolean& truncated, NABoolean& valWasNegative,
                           logLevel level);

OptRangeSpec::OptRangeSpec(QRDescGenerator* descGenerator, CollHeap* heap, logLevel ll)
  : RangeSpec(heap, ll),
    descGenerator_(descGenerator),
    rangeExpr_(NULL),
    vid_(NULL_VALUE_ID),
    isIntersection_(FALSE)
{
  assertLogAndThrow(CAT_SQL_COMP_RANGE, logLevel_,
                    descGenerator, QRLogicException,
                    "OptRangeSpec constructed for null QRDescGenerator");

  if (descGenerator->isDumpMvMode())
    setDumpMvMode();
}

ValueId OptRangeSpec::getBaseCol(const ValueIdSet& vegMembers)
{
  for (ValueId id=vegMembers.init(); vegMembers.next(id); vegMembers.advance(id))
    {
      if (id.getItemExpr()->getOperatorType() == ITM_BASECOLUMN)
        return id;
    }
  
  return NULL_VALUE_ID;
}

ValueId OptRangeSpec::getBaseCol(const ValueId vegRefVid)
{
  ItemExpr* itemExpr = vegRefVid.getItemExpr(); 
  OperatorTypeEnum opType = itemExpr->getOperatorType();

  // See if the vid is for a basecol instead of a vegref.
  if (opType == ITM_BASECOLUMN)
    return vegRefVid;

  // Get the value id of the first member that is a base column.
  assertLogAndThrow1(CAT_SQL_COMP_RANGE, logLevel_,
                     opType == ITM_VEG_REFERENCE, QRDescriptorException,
                     "OptRangeSpec::getBaseCol() expected value id of a "
                     "vegref, not of op type -- %d", opType);

  ValueId baseColVid = getBaseCol(static_cast<VEGReference*>(itemExpr)
                                                ->getVEG()->getAllValues());
  assertLogAndThrow(CAT_SQL_COMP_RANGE, logLevel_,
                    baseColVid != NULL_VALUE_ID, QRDescriptorException,
                    "Vegref contains no base columns");
  return baseColVid;
}

OptRangeSpec* OptRangeSpec::createRangeSpec(QRDescGenerator* descGenerator,
                                            ItemExpr* predExpr,
                                            CollHeap* heap,
                                            NABoolean createForNormalizer)
{
  QRTRACER("createRangeSpec");
  OptRangeSpec* range = NULL;

  if (predExpr->getOperatorType() == ITM_RANGE_SPEC_FUNC)
    {
      assertLogAndThrow(CAT_SQL_COMP_RANGE, LL_ERROR,
                        !createForNormalizer, QRDescriptorException,
                        "RangeSpecRef should not be present if creating for Normalizer");
      RangeSpecRef* rangeIE = static_cast<RangeSpecRef*>(predExpr);
      range = new(heap) OptRangeSpec(*rangeIE->getRangeObject(), heap);

      // RangeSpecRefs are produced by the Normalizer. The rangespec they contain
      // may have a vegref vid as the rangecolvalueid instead of using the first
      // basecol vid as we do when a range is created in mvqr. Also, the vid may
      // be that of a joinpred, but will still be stored as the rangecolvalueid.
      // Below, we sort out these issues for the new rangespec we have created
      // using the copy ctor on the one in the RangeSpecRef.
      ValueId rcvid = range->getRangeColValueId();
      if (rcvid != NULL_VALUE_ID)
        {
          ItemExpr* ie = rcvid.getItemExpr();
          if (ie->getOperatorType() == ITM_VEG_REFERENCE)
            {
              if (descGenerator->isJoinPredId(rcvid))
                {
                  range->setRangeColValueId(NULL_VALUE_ID);
                  range->setRangeJoinPredId(rcvid);
                }
              else
                {
                  rcvid = range->getBaseCol(((VEGReference*)ie)->getVEG()->getAllValues());
                  if (rcvid != NULL_VALUE_ID)
                    range->setRangeColValueId(rcvid);
                }
            }
        }
    }
  else
    {
      if (createForNormalizer)
        {
          range = new (heap) OptNormRangeSpec(descGenerator, heap);
          (static_cast<OptNormRangeSpec*>(range))
                    ->setOriginalItemExpr(predExpr);
        }
      else
        range = new (heap) OptRangeSpec(descGenerator, heap);

      if (!range->buildRange(predExpr))
        {
          delete range;
          return NULL;
        }
    }

  range->setID(predExpr->getValueId());
  range->log();
  return range;
}

// Protected copy ctor, used by clone().
OptRangeSpec::OptRangeSpec(const OptRangeSpec& other, CollHeap* heap)
  : RangeSpec(other, heap),
    descGenerator_(other.descGenerator_),
    rangeExpr_(NULL),
    vid_(other.vid_),
    isIntersection_(other.isIntersection_)
{
  // At this point the inherited heap ptr mvqrHeap_ has been initialized
  // by the superclass ctor.
  if (other.rangeExpr_)
    rangeExpr_ = other.rangeExpr_->copyTree(mvqrHeap_);
}

QRRangePredPtr OptRangeSpec::createRangeElem()
{
  QRTRACER("createRangeElem");
  QRRangePredPtr rangePredElem = 
          new (mvqrHeap_) QRRangePred(ADD_MEMCHECK_ARGS(mvqrHeap_));
  rangePredElem->setRangeItem(genRangeItem());

  NABoolean rangeIsOnCol = (rangeJoinPredId_ != NULL_VALUE_ID ||
                            rangeColValueId_ != NULL_VALUE_ID);

  assertLogAndThrow(CAT_SQL_COMP_RANGE, logLevel_,
                    getID()>0, QRDescriptorException,
                    "No id for range element in OptRangeSpec::createRangeElem().");

  // The id of this rangespec is the value id of the original predicate on the
  // corresponding range column/expr. If other preds on the range col/expr were
  // found and had to be intersected, we need to use the value id of the itemexpr
  // that is the result of the intersection (so the right predicat will be used
  // for the rewrite).
  if (isIntersection_)
    rangePredElem->setID(getRangeItemExpr()->getValueId());
  else
    rangePredElem->setID(getID());

  const NAType* typePtr = getType();
  assertLogAndThrow(CAT_SQL_COMP_RANGE, logLevel_,
                    typePtr, QRDescriptorException,
                    "Call to getType() returned NULL in OptRangeSpec::createRangeElem().");
  const NAType& type = *typePtr;
  rangePredElem->setSqlType(type.getTypeSQLname());
  QROpInequalityPtr ineqOp;
  QROpEQPtr eqOp = NULL;
  QROpBTPtr betweenOp;
  CollIndex numSubranges = subranges_.entries();
  for (CollIndex i=0; i<numSubranges; i++)
    {
      SubrangeBase& subrange = *subranges_[i];
      if (subrange.startIsMin() || 
          (i==0 && rangeIsOnCol && subrange.isMinForType(type)))
        {
          assertLogAndThrow1(CAT_SQL_COMP_RANGE, logLevel_,
                             i==0, QRDescriptorException,
                             "Subrange other than 1st is unbounded on low side, "
                             "subrange index %d", i);
          if (subrange.endIsMax() ||
              (i==numSubranges-1 && rangeIsOnCol && subrange.isMaxForType(type)))
            {
              // Range spans all values of the type. If NULL is included as
              // well, return NULL to indicate no range restriction. If NULL is
              // not included in the range, an empty <RangePred> is used to
              // indicate IS NOT NULL.
              assertLogAndThrow(CAT_SQL_COMP_RANGE, logLevel_,
                                numSubranges==1, QRDescriptorException,
                                "Range of all values must have a single Subrange.");
              if (nullIncluded_)
                {
                  QRLogger::log(CAT_SQL_COMP_RANGE, LL_INFO,
                    "Range predicate ignored because it spans entire range + NULL.");
                  deletePtr(rangePredElem);
                  return NULL;
                }
              else
                {
                  // An IS NOT NULL predicate on a NOT NULL column is removed in
                  // the early compilation stages. If we generate the usual empty
                  // range element to represent a predicate that spans all values,
                  // it will not match this missing predicate. So we detect and
                  // remove it.
                  QRElementPtr rangeItemElem = rangePredElem->getRangeItem()
                                                            ->getReferencedElement();
                  if (rangeItemElem->getIDFirstChar() == 'C')
                    {
                      ValueId vid = rangeItemElem->getIDNum();
                      if ((static_cast<BaseColumn*>(vid.getItemExpr()))
                                              ->getNAColumn()->getNotNullNondroppable())
                        {
                          QRLogger::log(CAT_SQL_COMP_RANGE, LL_INFO,
                                        "Range predicate ignored because it spans entire "
                                        "range and has NOT NULL constraint.");
                          deletePtr(rangePredElem);
                          return NULL;
                        }
                    }
                }
                
              return rangePredElem;  // leave it empty
            }
          if (subrange.endInclusive())
            ineqOp = new (mvqrHeap_) QROpLE(ADD_MEMCHECK_ARGS(mvqrHeap_));
          else
            ineqOp = new (mvqrHeap_) QROpLS(ADD_MEMCHECK_ARGS(mvqrHeap_));
          ineqOp->setValue(subrange.getEndScalarValElem(mvqrHeap_, type));
          // If start is not min, we are here because lower bound for the type
          // was start of first subrange.
          ineqOp->setNormalized(!subrange.startIsMin());
          rangePredElem->addOperator(ineqOp);
        }
      else if (subrange.endIsMax() ||
               (i==numSubranges-1 && rangeIsOnCol
                                  && subrange.isMaxForType(type)))
        {
          assertLogAndThrow1(CAT_SQL_COMP_RANGE, logLevel_,
                             i==numSubranges-1, QRDescriptorException,
			     "Subrange other than last is unbounded on high side, "
                                 "subrange index %d",
                             i);
          if (eqOp)                   // wrap this up if one in progress
            {
              rangePredElem->addOperator(eqOp);
              eqOp = NULL;
            }
          if (subrange.startInclusive())
            ineqOp = new (mvqrHeap_) QROpGE(ADD_MEMCHECK_ARGS(mvqrHeap_));
          else
            ineqOp = new (mvqrHeap_) QROpGT(ADD_MEMCHECK_ARGS(mvqrHeap_));
          ineqOp->setValue(subrange.getStartScalarValElem(mvqrHeap_, type));
          // If end is not max, we are here because upper bound for the type
          // was end of last subrange.
          ineqOp->setNormalized(!subrange.endIsMax());
          rangePredElem->addOperator(ineqOp);
        }
      else if (subrange.isSingleValue())
        {
          // Add the value to a new OpEQ or the one we are already working on,
          // but don't finish it until we hit something besides a single-value
          // subrange.
          if (!eqOp)
            eqOp = new (mvqrHeap_) QROpEQ(ADD_MEMCHECK_ARGS(mvqrHeap_));
          eqOp->addValue(subrange.getStartScalarValElem(mvqrHeap_, type));
        }
      else
        {
          // If values have been accumulated in an OpEQ, add it before doing
          // the between op.
          if (eqOp)
            {
              rangePredElem->addOperator(eqOp);
              eqOp = NULL;
            }
          betweenOp = new (mvqrHeap_) QROpBT(ADD_MEMCHECK_ARGS(mvqrHeap_));
          betweenOp->setStartValue(subrange.getStartScalarValElem(mvqrHeap_,
                                                                  type));
          betweenOp->setStartIncluded(subrange.startInclusive());
          betweenOp->setEndValue(subrange.getEndScalarValElem(mvqrHeap_,
                                                              type));
          betweenOp->setEndIncluded(subrange.endInclusive());
          rangePredElem->addOperator(betweenOp);
        }
    }

  // If IS NULL is part of the range spec, it should come last. If an OpEQ
  // element is in progress, add it there, else create one for it. In either
  // of these cases, add it to the range pred element.
  if (eqOp)
    {
      if (nullIncluded_)
        eqOp->setNullVal(new(mvqrHeap_) QRNullVal(ADD_MEMCHECK_ARGS(mvqrHeap_)));
      rangePredElem->addOperator(eqOp);
    }
  else if (nullIncluded_)
    {
      eqOp = new (mvqrHeap_) QROpEQ(ADD_MEMCHECK_ARGS(mvqrHeap_));
      eqOp->setNullVal(new(mvqrHeap_) QRNullVal(ADD_MEMCHECK_ARGS(mvqrHeap_)));
      rangePredElem->addOperator(eqOp);
    }

  return rangePredElem;
}  // createRangeElem()

QRElementPtr OptRangeSpec::genRangeItem()
{
  QRElementPtr elem;
  if (rangeColValueId_ != NULL_VALUE_ID)
    elem = descGenerator_->genQRColumn(rangeColValueId_,
                                       rangeJoinPredId_);
  else if (rangeExpr_)
    elem = descGenerator_->genQRExpr(rangeExpr_, rangeJoinPredId_);
  else
    {
      assertLogAndThrow(CAT_SQL_COMP_RANGE, logLevel_,
                        rangeJoinPredId_ != NULL_VALUE_ID, QRDescriptorException,
                        "All range value ids are null");
      ValueId colVid = getBaseCol(rangeJoinPredId_);
      elem = descGenerator_->genQRColumn(colVid,
                                         rangeJoinPredId_);
    }
  return elem;
}

ItemExpr* OptRangeSpec::getRangeExpr() const
{
  if (rangeExpr_)
    return rangeExpr_;
  else if (rangeJoinPredId_ != NULL_VALUE_ID)
    return ((ValueId)rangeJoinPredId_).getItemExpr();
  else
    return ((ValueId)rangeColValueId_).getItemExpr();
}

// Exprs have been converted to a canonical form in which const is the 2nd operand.
// NULL is returned if there is not a constant operand, or if the other operand
// is not the one the range is being built for.
ConstValue* OptRangeSpec::getConstOperand(ItemExpr* predExpr, Lng32 constInx)
{
  QRTRACER("getConstOperand");
  ItemExpr* left = predExpr->child(0);
  ItemExpr* right = predExpr->child(constInx);

  // Bail out if we don't have a constant. If a vegref, see if the veg includes
  // a constant, and substitute that if so.
  if (right->getOperatorType() != ITM_CONSTANT)
    {
      if (right->getOperatorType() == ITM_VEG_REFERENCE)
        {
          ValueId constVid = (static_cast<VEGReference*>(right))->getVEG()->getAConstant(TRUE);
          if (constVid == NULL_VALUE_ID)
            return NULL;
          else
            right = constVid.getItemExpr();
        }
      else
        return NULL;
    }

  ValueId colVid;
  switch (left->getOperatorType())
    {
      case ITM_VEG_REFERENCE:
        if (forNormalizer())
          colVid = left->getValueId();
        else
          colVid = getBaseCol(((VEGReference*)left)->getVEG()->getAllValues());
        break;
      case ITM_BASECOLUMN:  // Should only happen for a check constraint
        colVid = left->getValueId();
        break;
      default:  // must be an expression
        colVid = NULL_VALUE_ID;
        break;
    }

  if (colVid != NULL_VALUE_ID)
    {
      // If this range is for an expression, the pred is not on it.
      if (rangeExpr_)
        return NULL;

      if (rangeColValueId_ == NULL_VALUE_ID)
        {
          rangeColValueId_ = colVid;
          EqualitySet* eqSet =
                    descGenerator_->getEqualitySet(&rangeColValueId_);
          if (eqSet)
            {
              rangeJoinPredId_ = (QRValueId)eqSet->getJoinPredId();
              setType(eqSet->getType());
            }
          else
            {
              rangeJoinPredId_ = (QRValueId)NULL_VALUE_ID;
              setType(&((ValueId)rangeColValueId_).getType());
            }
        }
      else if (rangeColValueId_ != colVid)
        return NULL;
    }
  else
    {
      // The left side of the pred is an expression. If this range is for a
      // simple column, it doesn't match.
      if (rangeColValueId_ != NULL_VALUE_ID)
        return NULL;

      if (!rangeExpr_)
        {
          // If more than one node is involved in an expression, it is a
          // residual pred instead of a range pred.
          if (descGenerator_->getExprNode(left) == NULL_CA_ID)
            return NULL;

          setRangeExpr(left);  // sets rangeExpr_, rangeExprText_
          EqualitySet* eqSet =
                    descGenerator_->getEqualitySet(&rangeExprText_);
          if (eqSet)
            {
              rangeJoinPredId_ = (QRValueId)eqSet->getJoinPredId();
              setType(eqSet->getType());
            }
          else
            {
              rangeJoinPredId_ = (QRValueId)NULL_VALUE_ID;
              setType(&rangeExpr_->getValueId().getType());
            }
        }
      else
        {
          // The ItemExpr ptrs will be different, so we compare the expression
          // text to see if they are the same. At some point this text will be
          // in a canonical form that ignores syntactic variances.
          NAString exprText;
          left->unparse(exprText, OPTIMIZER_PHASE, MVINFO_FORMAT);
          if (rangeExprText_ != exprText)
            return NULL;
        }
    }

  if (!(QRDescGenerator::typeSupported(getType())))
    return NULL;

  // If we reach this point, the predicate has been confirmed to apply to the
  // same col/expr of this range, and the right operand has been confirmed to
  // be a constant. Before returning the ConstValue, make sure it is a type we
  // currently support. Predicates involving types not yet supported will be
  // treated as residual predicates.
  if (QRDescGenerator::typeSupported(static_cast<ConstValue*>(right)->getType()))
    return static_cast<ConstValue*>(right);
  else
    return NULL;
} // getConstOperand()

void OptRangeSpec::addSubrange(ConstValue* start, ConstValue* end,
                               NABoolean startInclusive, NABoolean endInclusive)
{
  QRTRACER("addSubrange");
  const NAType* type = getType();
  assertLogAndThrow(CAT_SQL_COMP_RANGE, logLevel_,
                    type, QRDescriptorException,
                    "Call to getType() returned NULL in OptRangeSpec::addSubrange().");
                    
  NAString unparsedStart(""), unparsedEnd("");
  if (isDumpMvMode())
  {
    // Add the "official" unparsed text of the expression as a sub-element.
    if (start)
      start->unparse(unparsedStart, OPTIMIZER_PHASE, QUERY_FORMAT);
    if (end)
      end->unparse(unparsedEnd, OPTIMIZER_PHASE, QUERY_FORMAT);
  }            

  NABuiltInTypeEnum typeQual = type->getTypeQualifier();
  switch (typeQual)
    {
      case NA_NUMERIC_TYPE:
      case NA_DATETIME_TYPE:
      case NA_INTERVAL_TYPE:
      case NA_BOOLEAN_TYPE:
        //if (((const NumericType*)type)->isExact())
        if (typeQual == NA_DATETIME_TYPE ||
            typeQual == NA_INTERVAL_TYPE ||
            (typeQual == NA_NUMERIC_TYPE && 
             static_cast<const NumericType*>(type)->isExact()) ||
            (typeQual == NA_BOOLEAN_TYPE))
          {
            // Fixed-point numeric subranges are normalized to be inclusive, to
            // simplify equivalence and subsumption checks.
            Subrange<Int64>* sub = new (mvqrHeap_) Subrange<Int64>(logLevel_);
            sub->setUnparsedStart(unparsedStart);
            sub->setUnparsedEnd(unparsedEnd);
            NABoolean valTruncated;
            NABoolean valNegative;
            NABoolean startOverflowed = FALSE;
            NABoolean endOverflowed = FALSE;
            if (start)
              {
                // If the constant is truncated because it has higher scale than
                // the type of the range col/expr, the truncated value is not the
                // start of the range. 1 is added to the truncated value to get
                // the next value that is possible for the type.
                sub->start = getInt64Value(start, type, valTruncated, valNegative, logLevel_);
                if ((!startInclusive || valTruncated) &&
                    (!valTruncated || !valNegative))
                  sub->makeStartInclusive(type, startOverflowed);
              }
            else
              sub->setStartIsMin(TRUE);
            if (end)
              {
                // If the constant is truncated because it has higher scale than
                // the type of the range col/expr, the truncated value must be
                // included in the range even if the end is not inclusive (<).
                sub->end = getInt64Value(end, type, valTruncated, valNegative, logLevel_);
                if ((!endInclusive && !valTruncated) ||
                    (valTruncated && valNegative))
                  sub->makeEndInclusive(type, endOverflowed);
              }
            else
              sub->setEndIsMax(TRUE);

            // If not originally inclusive, has been adjusted above.
            // Need this in case makeXXXInclusive was not called, but leave as
            // is if made noninclusive because of positive (for start) or 
            // negative (for end) overflow.
            if (!startOverflowed)
              sub->setStartInclusive(TRUE);
            if (!endOverflowed)
              sub->setEndInclusive(TRUE);

            // Handling a constant with scale that exceeds that of the range
            // column could result in an empty (i.e., start>end) range. For example,
            // if n is a numeric(4,2), the predicate n = 12.341 will result in
            // the range 12.35..12.34, which is appropriate since the predicate
            // is guaranteed to be false by the type constraint of the column.
            if (sub->startIsMin() || sub->endIsMax() || sub->start <= sub->end)
              placeSubrange(sub);
            else
              delete sub;
          }
        else
          {
            Subrange<double>* sub = new (mvqrHeap_) Subrange<double>(logLevel_);
            sub->setUnparsedStart(unparsedStart);
            sub->setUnparsedEnd(unparsedEnd);
            if (start)
              sub->start = getDoubleValue(start, logLevel_);
            else
              sub->setStartIsMin(TRUE);
            if (end)
              sub->end = getDoubleValue(end, logLevel_);
            else
              sub->setEndIsMax(TRUE);
            sub->setStartInclusive(startInclusive);
            sub->setEndInclusive(endInclusive);
            placeSubrange(sub);
          }
        break;

      // In some cases, constant folding of char expressions produces a varchar
      // constant, so we have to take a possible length field into account.
      case NA_CHARACTER_TYPE:
        {
          Lng32 headerBytes;
          const NAType* startType = (start ? start->getType() : NULL);
          const NAType* endType = (end ? end->getType() : NULL);

          // Alignment is 2 for UCS2, 1 for single-byte char set.
          if (type->getDataAlignment() == 2)
            {
              // Unicode string.
              Subrange<RangeWString>* sub = new (mvqrHeap_) Subrange<RangeWString>(logLevel_);
              sub->setUnparsedStart(unparsedStart);
              sub->setUnparsedEnd(unparsedEnd);
              if (start)
                {
                  headerBytes = startType->getVarLenHdrSize() +
                                startType->getSQLnullHdrSize();
                  sub->start.remove(0)
                            .append((const NAWchar*)start->getConstValue() 
                                        + (headerBytes / sizeof(NAWchar)),
                                    (start->getStorageSize() - headerBytes)
                                        / sizeof(NAWchar));
                }
              else
                sub->setStartIsMin(TRUE);
              if (end)
                {
                  headerBytes = endType->getVarLenHdrSize() +
                                endType->getSQLnullHdrSize();
                  sub->end.remove(0)
                          .append((const NAWchar*)end->getConstValue()
                                        + (headerBytes / sizeof(NAWchar)),
                                   (end->getStorageSize() - headerBytes)
                                        / sizeof(NAWchar));
                }
              else
                sub->setEndIsMax(TRUE);
              sub->setStartInclusive(startInclusive);
              sub->setEndInclusive(endInclusive);
              placeSubrange(sub);
            }
          else
            {
              // Latin1 string.
              Subrange<RangeString>* sub = new (mvqrHeap_) Subrange<RangeString>(logLevel_);
              sub->setUnparsedStart(unparsedStart);
              sub->setUnparsedEnd(unparsedEnd);
              if (start)
                {
                  headerBytes = startType->getVarLenHdrSize() +
                                startType->getSQLnullHdrSize();
                  sub->start.remove(0)
                            .append((const char*)start->getConstValue() + headerBytes,
                                    start->getStorageSize() - headerBytes);
                }
              else
                sub->setStartIsMin(TRUE);
              if (end)
                {
                  headerBytes = endType->getVarLenHdrSize() +
                                endType->getSQLnullHdrSize();
                  sub->end.remove(0)
                          .append((const char*)end->getConstValue() + headerBytes,
                                  end->getStorageSize() - headerBytes);
                }
              else
                sub->setEndIsMax(TRUE);
              sub->setStartInclusive(startInclusive);
              sub->setEndInclusive(endInclusive);
              placeSubrange(sub);
            }
        }
        break;

      default:
        assertLogAndThrow1(CAT_SQL_COMP_RANGE, logLevel_,
                           FALSE, QRDescriptorException, 
                           "Unhandled data type: %d", typeQual);
        break;
    }
}  // addSubrange(ConstValue*...


ItemExpr* OptRangeSpec::getCheckConstraintPred(ItemExpr* checkConstraint)
{
  if (checkConstraint->getOperatorType() != ITM_CASE)
    {
      QRLogger::log(CAT_SQL_COMP_RANGE, logLevel_,
        "Expected ITM_CASE but found operator %d.",
        checkConstraint->getOperatorType());
      return NULL;
    }

  ItemExpr* itemExpr = checkConstraint->child(0);
  if (itemExpr->getOperatorType() != ITM_IF_THEN_ELSE)
    {
      QRLogger::log(CAT_SQL_COMP_RANGE, logLevel_,
        "Expected ITM_IF_THEN_ELSE but found operator %d.",
        itemExpr->getOperatorType());
      return NULL;
    }

  // Child of the if-then-else is either is_false, which is the parent of the
  // predicate (for most check constraints), or the predicate itself (for
  // isnotnull or the check option of a view).
  itemExpr = itemExpr->child(0);
  if (itemExpr->getOperatorType() == ITM_IS_FALSE)
    return itemExpr->child(0);
  else
    return itemExpr;
}

void OptRangeSpec::intersectCheckConstraints(QRDescGenerator* descGen,
                                             ValueId colValId)
{
  QRTRACER("intersectCheckConstraints");

  // Check and Not Null constraints.
  //
  ItemExpr* itemExpr = colValId.getItemExpr();
  if (itemExpr->getOperatorType() == ITM_VEG_REFERENCE)
    {
      // For a vegref, intersect all constraints applied to any member.
      const ValueIdSet& vidSet = static_cast<VEGReference*>(itemExpr)
                                                    ->getVEG()->getAllValues();
      for (ValueId vid=vidSet.init(); vidSet.next(vid); vidSet.advance(vid)) 
        {
          if (vid.getItemExpr()->getOperatorType() == ITM_BASECOLUMN)
            intersectCheckConstraints(descGen, vid);
        }
      return;
    }
  else if (itemExpr->getOperatorType() != ITM_BASECOLUMN)
    {
      QRLogger::log(CAT_SQL_COMP_RANGE, logLevel_,
        "Nonfatal unexpected result: range column operator type is "
        "%d instead of ITM_BASECOLUMN.", itemExpr->getOperatorType());
      return;
    }

#ifdef _DEBUG
    const NATable* tbl = colValId.getNAColumn()->getNATable();
    const CheckConstraintList& checks = tbl->getCheckConstraints();
    for (CollIndex c=0; c<checks.entries(); c++)
      {
        QRLogger::log(CAT_SQL_COMP_RANGE, LL_DEBUG,
          "Check constraint on table %s: %s",
                    tbl->getTableName().getObjectName().data(),
                    checks[c]->getConstraintText().data());
      }
#endif

  OptRangeSpec* checkRange = NULL;
  ItemExpr* checkPred;
  const ValueIdList& checkConstraints =
      (static_cast<BaseColumn*>(itemExpr))->getTableDesc()->getCheckConstraints();
  for (CollIndex i=0; i<checkConstraints.entries(); i++)
    {
      checkPred = getCheckConstraintPred(checkConstraints[i].getItemExpr());
      if (checkPred)
        {
          checkRange = new(mvqrHeap_) OptRangeSpec(descGen, mvqrHeap_);
          checkRange->setRangeColValueId(colValId);
          checkRange->setType(colValId.getType().newCopy(mvqrHeap_));
          if (checkRange->buildRange(checkPred))
            // Call the RangeSpec version of intersect; this avoids trying to
            // modify the original ItemExpr with the check constraint pred.
            RangeSpec::intersectRange(checkRange);
          delete checkRange;
        }
    }
}

// Add type-implied constraint for numeric, datetime, and interval types.
void OptRangeSpec::intersectTypeConstraint(QRDescGenerator* descGen,
                                           ValueId colValId)
{
  QRTRACER("intersectTypeConstraint");

  NABoolean isExact;
  const NAType& colType = colValId.getType();
  NABuiltInTypeEnum typeQual = colType.getTypeQualifier();

  switch (typeQual)
    {
      case NA_NUMERIC_TYPE:
        {
          const NumericType& numType = static_cast<const NumericType&>(colType);
          isExact = numType.isExact();
          if (isExact && numType.getFSDatatype() == REC_BIN64_SIGNED)
            return;  // No type restriction for 64-bit integers
        }
        break;

      case NA_DATETIME_TYPE:
      case NA_INTERVAL_TYPE:
        isExact = TRUE;
        break;

      default:
        return;      // No type constraint applied for other types
    }

  OptRangeSpec* typeRange = NULL;
  if (isExact)  // Exact numeric, datetime, interval
    {
      // Add the subrange implied by the type. If the type is largeint,
      // nothing is needed here and no type range will be created. We don't
      // need to set the type of the range specs created in this function,
      // because addSubrange (which looks at the type) is bypassed and we call
      // placeSubrange directly.
      typeRange = new(mvqrHeap_) OptRangeSpec(descGen, mvqrHeap_);
      Int64 start, end;
      SubrangeBase::getExactNumericMinMax(colType, start, end, logLevel_);
      Subrange<Int64>* numSubrange = new(mvqrHeap_) Subrange<Int64>(logLevel_);
      numSubrange->setUnparsedStart("");
      numSubrange->setUnparsedEnd("");
      numSubrange->start = start;
      numSubrange->end = end;
      numSubrange->setStartIsMin(FALSE);
      numSubrange->setEndIsMax(FALSE);
      numSubrange->setStartInclusive(TRUE);
      numSubrange->setEndInclusive(TRUE);
      typeRange->placeSubrange(numSubrange);
    }
  else  // approximate numeric
    {
      switch (colType.getFSDatatype())
        {
          case REC_IEEE_FLOAT32:
            {
              typeRange = new(mvqrHeap_) OptRangeSpec(descGen, mvqrHeap_);
              Subrange<double>* dblSubrange = new(mvqrHeap_) Subrange<double>(logLevel_);
              dblSubrange->end = static_cast<const NumericType&>(colType).getMaxValue();
              dblSubrange->setUnparsedStart("");
              dblSubrange->setUnparsedEnd("");
              dblSubrange->start = -(dblSubrange->end);
              dblSubrange->setStartIsMin(FALSE);
              dblSubrange->setEndIsMax(FALSE);
              dblSubrange->setStartInclusive(TRUE);
              dblSubrange->setEndInclusive(TRUE);
              typeRange->placeSubrange(dblSubrange);
            }
            break;

          case REC_IEEE_FLOAT64:
            // No range restriction needed.
            break;

          default:
            QRLogger::log(CAT_SQL_COMP_RANGE, logLevel_,
              "No case in intersectTypeConstraint() for "
                        "approximate numeric of type %d",
                        colType.getFSDatatype());
            break;
        }
    }

  if (typeRange)
    {
      typeRange->setNullIncluded(TRUE); // Null always part of a type range
      // Call the RangeSpec version of intersect; this avoids trying to
      // modify the original ItemExpr with the type constraint pred.
      RangeSpec::intersectRange(typeRange);
      delete typeRange;
    }
}  // intersectTypeConstraint()

void OptRangeSpec::addConstraints(QRDescGenerator* descGen)
{
  QRTRACER("addConstraints");

  ValueId colValId = getRangeColValueId();
  if (colValId == NULL_VALUE_ID)
    colValId = getRangeJoinPredId();
  if (colValId == NULL_VALUE_ID)
    return;

  // Add constraint implied by the column's type.
  intersectTypeConstraint(descGen, colValId);

  // Check constraints can be added and dropped at will, and so can be in
  // different states when the MV is created and when the query is matched.
  // Therefore we utilize check constraints only for query descriptors. This
  // may result in a NotProvided instead of a Provided match, but avoids the
  // need to invalidate all the MV descriptors using a table when one of the
  // table's check constraints is added/dropped.
  if (descGen->getDescriptorType() == ET_QueryDescriptor)
    intersectCheckConstraints(descGen, colValId);
//  else
//    assertLogAndThrow1(descGen->getDescriptorType() == ET_MVDescriptor,
//                       QRDescriptorException,
//                       "Invalid descriptor type -- %d",
//                       descGen->getDescriptorType());
}

void OptRangeSpec::addColumnsUsed(const QRDescGenerator* descGen)
{
  if (descGen != descGenerator_)
    descGenerator_->mergeDescGenerator(descGen);
}

#define AVR_STATE0 0
#define AVR_STATE1 1
#define AVR_STATE2 2

NABoolean OptRangeSpec::buildRange(ItemExpr* origPredExpr)
{
  QRTRACER("buildRange");
  ConstValue *startValue, *endValue;
  OperatorTypeEnum leftOp, rightOp;
  NABoolean isRange = TRUE;
  NABoolean reprocessAND = FALSE;

  //
  // buildRange() can be called recursively for all the items in an IN-list
  // at a point in time when we are already many levels deep in other
  // recursion (e.g. Scan::applyAssociativityAndCommutativity() ). Consequently,
  // we may not have much of our stack space available at the time, so
  // we must eliminate the recursive calls to buildRange() by keeping the
  // information needed by each "recursive" level in the heap and using
  // a "while" loop to look at each node in the tree in the same order as
  // the old recursive technique would have done.
  // The information needed by each "recursive" level is basically just
  // a pointer to what node (ItemExpr *) to look at next and a "state" value
  // that tells us where we are in the buildRange() code for the ItemExpr
  // node that we are currently working on.
  //
  ARRAY( ItemExpr * ) IEarray(mvqrHeap_, 10) ; //Initially 10 elements (no particular reason to choose 10)
  ARRAY( Int16 )      state(mvqrHeap_, 10)   ; //These ARRAYs will grow automatically as needed.)

  Int32 currIdx     = 0 ;
  IEarray.insertAt( currIdx, origPredExpr ) ; //Initialize 1st element in the ARRAYs
  state.insertAt(   currIdx, AVR_STATE0   ) ;

  while( currIdx >= 0 && isRange )
  {
    ItemExpr * predExpr = IEarray[currIdx] ;  //Get ptr to the current IE
    OperatorTypeEnum op = predExpr->getOperatorType();
    switch (op)
    {
      case ITM_AND:
        // Check for a bounded subrange, from BETWEEN predicate, etc. If not of
        // this form, the predicate was presumably too complex to convert to
        // conjunctive normal form without a combinatorial explosion of clauses,
        // and we handle it by creating separate range objects for each operand
        // of the AND, intersecting them, and then unioning the result with the
        // primary range.
        leftOp = predExpr->child(0)->getOperatorType();
        rightOp = predExpr->child(1)->getOperatorType();
        if (leftOp == ITM_LESS || leftOp == ITM_LESS_EQ)
          {
            if (rightOp == ITM_GREATER || rightOp == ITM_GREATER_EQ)
              {
                endValue = getConstOperand(predExpr->child(0));
                if (endValue)
                  {
                    startValue = getConstOperand(predExpr->child(1));
                    if (startValue)
                      addSubrange(startValue, endValue,
                                  rightOp == ITM_GREATER_EQ,
                                  leftOp == ITM_LESS_EQ);
                    else
                      isRange = FALSE;
                  }
                else
                  isRange = FALSE;
              }
            else
              reprocessAND = TRUE;
          }
        else if (leftOp == ITM_GREATER || leftOp == ITM_GREATER_EQ)
          {
            if (rightOp == ITM_LESS || rightOp == ITM_LESS_EQ)
              {
                startValue = getConstOperand(predExpr->child(0));
                if (startValue)
                  {
                    endValue = getConstOperand(predExpr->child(1));
                    if (endValue)
                      addSubrange(startValue, endValue,
                                  leftOp == ITM_GREATER_EQ,
                                  rightOp == ITM_LESS_EQ);
                    else
                      isRange = FALSE;
                  }
                else
                  isRange = FALSE;
              }
            else
              reprocessAND = TRUE;
          }
        else
          reprocessAND = TRUE;

        // AND was used in a sense other than that of a BETWEEN predicate, so
        // we must intersect the operand ranges before adding the result to the
        // overall range.
        if (reprocessAND)
          {
            OptRangeSpec *leftRange = NULL, *rightRange = NULL;
            leftRange = createRangeSpec(descGenerator_, predExpr->child(0),
                                        mvqrHeap_, forNormalizer());
            if (!leftRange)
              isRange = FALSE;
            else if (!rangeSubjectIsSet())
              setRangeSubject(leftRange);
            else if (!sameRangeSubject(leftRange))
              isRange = FALSE;

            if (isRange)
              {
                rightRange = createRangeSpec(descGenerator_, predExpr->child(1),
                                             mvqrHeap_, forNormalizer());
                if (rightRange && rightRange->sameRangeSubject(leftRange))
                  {
                    leftRange->intersectRange(rightRange);
                    // Call only the superclass part of unionRange(); we want
                    // to avoid the part that modifies the originalItemExpr_;
                    RangeSpec::unionRange(leftRange);
                  }
                else
                  isRange = FALSE;
              }
            delete leftRange;
            delete rightRange;
          }
        break;

      case ITM_OR:
        if ( state[currIdx] == AVR_STATE0 )
        {
           state.insertAt( currIdx, AVR_STATE1 ) ;
           currIdx++ ;                               //"Recurse" down to child 0
           state.insertAt(   currIdx, AVR_STATE0 ) ; // and start that child's state at 0
           IEarray.insertAt( currIdx, predExpr->child(0) ) ;
           continue ;
        }
        else if ( state[currIdx] == AVR_STATE1 )
        {
           state.insertAt( currIdx, AVR_STATE2 ) ;
           currIdx++ ;                               //"Recurse" down to child 1
           state.insertAt(   currIdx, AVR_STATE0 ) ; // and start that child's state at 0
           IEarray.insertAt( currIdx, predExpr->child(1) ) ;
           continue ;
        }
        else
           state.insertAt( currIdx, AVR_STATE0 ); // We are done processing predExpr
        break ;

      case ITM_EQUAL:
        startValue = endValue = getConstOperand(predExpr);
        if (startValue)
          addSubrange(startValue, endValue, TRUE, TRUE);
        else
          isRange = FALSE;
        break;

      case ITM_LESS:
        endValue = getConstOperand(predExpr);
        if (endValue)
          addSubrange(NULL, endValue, TRUE, FALSE);
        else
          isRange = FALSE;
        break;

      case ITM_LESS_EQ:
        endValue = getConstOperand(predExpr);
        if (endValue)
          addSubrange(NULL, endValue, TRUE, TRUE);
        else
          isRange = FALSE;
        break;

      case ITM_GREATER:
        startValue = getConstOperand(predExpr);
        if (startValue)
          addSubrange(startValue, NULL, FALSE, TRUE);
        else
          isRange = FALSE;
        break;

      case ITM_GREATER_EQ:
        startValue = getConstOperand(predExpr);
        if (startValue)
          addSubrange(startValue, NULL, TRUE, TRUE);
        else
          isRange = FALSE;
        break;

      case ITM_NOT_EQUAL:
        startValue = endValue = getConstOperand(predExpr);
        if (startValue)
          {
            addSubrange(NULL, endValue, TRUE, FALSE);
            addSubrange(startValue, NULL, FALSE, TRUE);
          }
        else
          isRange = FALSE;
        break;

      case ITM_BETWEEN:
        startValue = getConstOperand(predExpr);
        if (startValue)
          {
            endValue = getConstOperand(predExpr, 2);
            if (endValue)
              //@ZX The Between class has private member variables
              //    leftBoundryIncluded_ and rightBoundryIncluded_ that have
              //    no accessor functions. If it is in fact possible for the
              //    boundaries to be noninclusive, we will need access to
              //    these properties.
              addSubrange(startValue, endValue, TRUE, TRUE);
          }
        else
          isRange = FALSE;
        break;

      case ITM_IS_NULL:
      case ITM_IS_NOT_NULL:
        {
          ValueId colVid;
          ItemExpr* child = predExpr->child(0);
          if (child->getOperatorType() == ITM_VEG_REFERENCE)
            {
              // If this range is for an expression, the pred is not on it.
              if (rangeExpr_)
                isRange = FALSE;
              else
                {
                  VEG* veg = ((VEGReference*)child)->getVEG();
                  if (forNormalizer())
                    colVid = veg->getVEGReference()->getValueId();
                  else
                    colVid = getBaseCol(veg->getAllValues());
                  if (rangeColValueId_ == NULL_VALUE_ID)
                    {
                      rangeColValueId_ = colVid;
                      EqualitySet* eqSet =
                              descGenerator_->getEqualitySet(&rangeColValueId_);
                      if (eqSet)
                        {
                          rangeJoinPredId_ = (QRValueId)eqSet->getJoinPredId();
                          setType(eqSet->getType());
                        }
                      else
                        {
                          rangeJoinPredId_ = (QRValueId)NULL_VALUE_ID;
                          setType(&((ValueId)rangeColValueId_).getType());
                        }
                    }
                  else if (rangeColValueId_ != colVid)
                    isRange = FALSE;
                }
            }
          else
            {
              // The left side of the pred is an expression. If this range is 
              // for a simple column, it doesn't match.
              if (rangeColValueId_ != NULL_VALUE_ID)
                isRange = FALSE;
              else if (!rangeExpr_)
                {
                  setRangeExpr(child);  // sets rangeExpr_, rangeExprText_
                  EqualitySet* eqSet =
                            descGenerator_->getEqualitySet(&rangeExprText_);
                  if (eqSet)
                    {
                      rangeJoinPredId_ = (QRValueId)eqSet->getJoinPredId();
                      setType(eqSet->getType());
                    }
                  else
                    {
                      rangeJoinPredId_ = (QRValueId)NULL_VALUE_ID;
                      setType(&rangeExpr_->getValueId().getType());
                    }
                }
              else
                {
                  NAString exprText;
                  child->unparse(exprText, OPTIMIZER_PHASE, MVINFO_FORMAT);
                  if (rangeExprText_ != exprText)
                    isRange = FALSE;
                }
            }

          // Now that it has been validated as a range pred, take the appropriate
          // action depending on whether the op is IS NULL or IS NOT NULL.
          if (isRange)
            {
              if (op == ITM_IS_NULL)
                nullIncluded_ = TRUE;
              else
                {
                  assertLogAndThrow(CAT_SQL_COMP_RANGE, logLevel_, op == ITM_IS_NOT_NULL,
                                    QRLogicException,
                                    "op must be ITM_IS_NOT_NULL here");
                  addSubrange(NULL, NULL, TRUE, TRUE);
                }
            }
        }
        break;

      default:
        isRange = FALSE;
        break;
    }
    if ( state[currIdx] == AVR_STATE0 )
       currIdx-- ;  // Go back to the parent node & continue working on it.
  }

  return isRange;
} // buildRange()

// Local helper function to cast int64, which, as the widest integral type is
// used for rangespec processing, to the actual type of the column the rangespec
// applies to. numBuf is declared as Int64* to ensure proper alignment for all
// possible integral types.
static void downcastRangespecInt(Int64 val, Lng32 scale, NAType*& type,
                                 Int64* numBuf, NAMemory* heap)
{
  Lng32 precision = 0;  // Only used for non-integral exact numeric

  // For non-integer values with leading 0's, have to adjust precision to
  // equal scale. For example, the raw value 23 with a scale of 4 (.0023)
  // will initially be calculated to have precision 2 instead of 4.
  if (scale) // non-integral value
    {
      precision = (Lng32)log10(::abs((double)val)) + 1;
      if (scale > precision)
        precision = scale;
    }

  if (val <= SHRT_MAX && val >= SHRT_MIN)
    {
      *((Int16*)numBuf) = static_cast<Int16>(val);
      if (scale == 0)
        type = new(heap) SQLSmall(heap, TRUE, FALSE);
      else
        type = new(heap) SQLNumeric(heap, sizeof(Int16), precision, scale,
                                    TRUE, FALSE);
    }
  else if (val <= INT_MAX && val >= INT_MIN)
    {
      *((Int32*)numBuf) = static_cast<Int32>(val);
      if (scale == 0)
        type = new(heap) SQLInt(heap, TRUE, FALSE);
      else
        type = new(heap) SQLNumeric(heap, sizeof(Int32), precision, scale,
                                    TRUE, FALSE);
    }
  else
    {
      *numBuf = val;
      if(scale == 0)
        type = new(heap) SQLLargeInt(heap, TRUE, FALSE);
      else
        type = new(heap) SQLNumeric(heap, sizeof(Int64), precision, scale,
                                    TRUE, FALSE);
    }
}

// Instantiate a ConstValue using the actual type of the passed Int64 value.
// The actual type is indicated by the type parameter, and could be any type
// represented as an integer in a rangespec.
ConstValue* OptRangeSpec::reconstituteInt64Value(NAType* type, Int64 val) const
{
  // Use these for the textual representation of a constant value, which is
  // passed to the ConstValue ctor.
  char constValTextBuffer[50];
  NAString constValTextStr;

  NABuiltInTypeEnum typeQual = type->getTypeQualifier();
  switch (typeQual)
    {
      case NA_NUMERIC_TYPE:
        {
          sprintf(constValTextBuffer, PF64, val);
          constValTextStr = constValTextBuffer;
          NumericType* numType = static_cast<NumericType*>(type);
          assertLogAndThrow(CAT_SQL_COMP_RANGE, logLevel_, 
                            numType->isExact(),
                            QRLogicException,
                            "Expecting exact numeric type in "
                                "reconstituteInt64Value");
          Int64 numBuf;
          NAType* constType = NULL;
          downcastRangespecInt(val, numType->getScale(), constType, &numBuf, mvqrHeap_);
          return new(mvqrHeap_) ConstValue(constType, &numBuf,
                                           constType->getNominalSize(),
                                           &constValTextStr, mvqrHeap_);
        }
        break;

      case NA_DATETIME_TYPE:
        {
          DatetimeType* dtType = static_cast<DatetimeType*>(type);
          ULng32 tsFieldValues[DatetimeValue::N_DATETIME_FIELDS];
          DatetimeValue dtv("", 0);
          switch (dtType->getSubtype())
            {
              case DatetimeType::SUBTYPE_SQLDate:
                // Since Julian timestamp is calculated from noon on the base day,
                // the timestamp corresponding to a given date (without time) is
                // always x.5 days, where x+1 is the actual number of days passed.
                // We truncate the fractional part when we store it, so it has to
                // be added back here. .5 could be added, but to be safe we add a
                // full day minus a microsecond, which is then truncated to the
                // proper value.
                DatetimeValue::decodeTimestamp
                                 ((val+1) * SubrangeBase::MICROSECONDS_IN_DAY - 1,
                                  dtType->getFractionPrecision(), tsFieldValues);
                dtv.setValue(REC_DATE_YEAR, REC_DATE_DAY,
                             dtType->getFractionPrecision(), tsFieldValues);
                assertLogAndThrow(CAT_SQL_COMP_RANGE, logLevel_,
                                  dtv.isValid(), QRLogicException,
                                  "Invalid date value reconstructed from Julian timestamp");
                constValTextStr = dtv.getValueAsString(*dtType);
                return new(mvqrHeap_) ConstValue(new(mvqrHeap_)SQLDate(mvqrHeap_, FALSE),
                                                 (void*)dtv.getValue(), dtv.getValueLen(),
                                                 &constValTextStr, mvqrHeap_);
                break;

              case DatetimeType::SUBTYPE_SQLTime:
                // The fractional seconds part is represented not by a number
                // of microseconds but by the numerator of the fraction having
                // denominator equal to 10^fractionPrecision.
                tsFieldValues[DatetimeValue::FRACTION] = 
                  (ULng32)((val % 1000000) 
                          / (Int64)pow(10, 6 - dtType->getFractionPrecision()));
                val /= 1000000;
                tsFieldValues[DatetimeValue::SECOND] = (ULng32)(val % 60);
                val /= 60;
                tsFieldValues[DatetimeValue::MINUTE] = (ULng32)(val % 60);
                val /= 60;
                tsFieldValues[DatetimeValue::HOUR] = (ULng32)val;
                dtv.setValue(REC_DATE_HOUR, REC_DATE_SECOND,
                              dtType->getFractionPrecision(), tsFieldValues);
                assertLogAndThrow(CAT_SQL_COMP_RANGE, logLevel_,
                                  dtv.isValid(), QRLogicException,
                                  "Invalid time value reconstructed from Int64 value");
                constValTextStr = dtv.getValueAsString(*dtType);
                return new(mvqrHeap_)
                        ConstValue(new(mvqrHeap_)SQLTime(mvqrHeap_, FALSE,
                                                         dtType->getFractionPrecision()),
                                  (void*)dtv.getValue(), dtv.getValueLen(),
                                  &constValTextStr, mvqrHeap_);
                break;

              case DatetimeType::SUBTYPE_SQLTimestamp:
                // We represent these as a number of microseconds, so fractional
                // precision does not have to be taken into account.
                DatetimeValue::decodeTimestamp(val,
                                               dtType->getFractionPrecision(),
                                               tsFieldValues);
                dtv.setValue(REC_DATE_YEAR, REC_DATE_SECOND,
                             dtType->getFractionPrecision(), tsFieldValues);
                assertLogAndThrow(CAT_SQL_COMP_RANGE, logLevel_,
                                  dtv.isValid(), QRLogicException,
                                  "Invalid timestamp value reconstructed from Julian timestamp");
                constValTextStr = dtv.getValueAsString(*dtType);
                return new(mvqrHeap_) ConstValue(new(mvqrHeap_)
                                                   SQLTimestamp(mvqrHeap_, FALSE, 
                                                                dtType->getFractionPrecision()),
                                                 (void*)dtv.getValue(),
                                                 dtv.getValueLen(),
		                            &constValTextStr, mvqrHeap_);
                break;

              default:
                assertLogAndThrow1(CAT_SQL_COMP_RANGE, logLevel_,
                                   FALSE, QRLogicException,
                                   "Unknown datetime subtype -- %d",
                                   dtType->getSubtype());
                return NULL;
                break;
            }
        }
        break;

      case NA_INTERVAL_TYPE:
        {
          Int64 origVal = val;  // Use this later to check for precision loss.
          Int64 scaledVal;      // Compare to origVal to check precision loss.
          Int64 scaleFactor;
          IntervalType* intvlType = static_cast<IntervalType*>(type);

          // For rangespec analysis, all values are converted to months or
          // microseconds. Change it back to its normal internal representation
          // in terms of units of the end field.
          switch (intvlType->getEndField())
            {
              case REC_DATE_YEAR:
                val /= 12;
                scaledVal = val * 12;
                break;

              case REC_DATE_MONTH:
                // No conversion necessary.
                scaledVal = val;
                break;

              case REC_DATE_DAY:
                val /= (24LL * 60 * 60000000);
                scaledVal = val * (24LL * 60 * 60000000);
                break;

              case REC_DATE_HOUR:
                val /= (60LL * 60000000);
                scaledVal = val * (60LL * 60000000);
                break;

              case REC_DATE_MINUTE:
                val /= 60000000LL;
                scaledVal = val * 60000000;
                break;

              case REC_DATE_SECOND:
                scaleFactor = (Int64)pow(10, 6 - intvlType->getFractionPrecision());
                val /= scaleFactor;
                scaledVal = val * scaleFactor;
                break;

              default:
                assertLogAndThrow1(CAT_SQL_COMP_RANGE, logLevel_,
                                  FALSE, QRLogicException,
                                  "Invalid end field for interval type -- %d",
                                  intvlType->getEndField());
                break;
            }

          // Calculate the leading field precision of the interval constant, when
          // converted to units of its end field.
          UInt32 leadingPrec = 0;
          Int64 tempVal = (val >= 0 ? val : -val); // abs has no overload for Int64
          while (tempVal > 0)
            {
              leadingPrec++;
              tempVal /= 10;
            }

          // If the field is seconds, some of the digits we just counted may be
          // fractional seconds, so we subtract them from what we counted.
          if (intvlType->getEndField() == REC_DATE_SECOND)
            {
              UInt32 fracSecPrec = intvlType->getFractionPrecision();
              if (leadingPrec <= fracSecPrec) // could be < for a fraction of a
                leadingPrec = 2;              //   sec with leading zeroes
              else
                leadingPrec -= fracSecPrec;
            }

          // There are cases where we can come up with leading precision of 0,
          // and this causes a problem. Make it min 2, which is the default.
          if (leadingPrec < 2)
            leadingPrec = 2;

          // Any discrepancy in precision between the range column and the
          // constant value should have been dealt with when the value was
          // converted to months or microseconds in getInt64ValueFromInterval().
          assertLogAndThrow2(CAT_SQL_COMP_RANGE, logLevel_,
                             origVal == scaledVal, QRLogicException,
                             "Precision lost in conversion to interval type: "
                               "value in microseconds (or months) = %Ld, "
                               "interval end field = %d",
                             origVal, intvlType->getEndField());

          // IntervalValue::setValue() will cast the Int64 value to the appropriate
          // type if you pass the length of that type, but negative values seem
          // to be stored incorrectly unless they are 8 bytes (see bug 2773), so
          // we just use 8 bytes always.
          IntervalValue intvlVal(NULL, 0);
          intvlVal.setValue(val, SQL_LARGE_SIZE);
          constValTextStr = intvlVal.getValueAsString(*intvlType);

          // The interval type for the constant is derived from that of the column
          // the predicate is on, but is always a single field (the end field of
          // the column type), and has the maximum possible leading field precision
          // to prevent overflow in case the value is outside the range for the
          // column's declared type (can happen when the rangespec is created for
          // the Normalizer rather than MVQR, because type constraints are not
          // incorporated in that case). See bug 2974.
          return new(mvqrHeap_) ConstValue(new(mvqrHeap_)SQLInterval
                                                 (mvqrHeap_, FALSE,
                                                  intvlType->getEndField(),
                                                  leadingPrec,
                                                  intvlType->getEndField(),
                                                  intvlType->getFractionPrecision()),
                                      (void*)intvlVal.getValue(),
                                      intvlVal.getValueLen(),
                                      &constValTextStr, mvqrHeap_);
        }
        break;

      default:
        assertLogAndThrow1(CAT_SQL_COMP_RANGE, logLevel_, FALSE, QRLogicException,
                           "Type not handled by reconstituteInt64Value() -- %d",
                           typeQual);
        return NULL;
        break;
    }
  // make the compiler happy
  return NULL;
} // reconstituteInt64Value()

// Instantiate a ConstValue using the passed double value. 
ConstValue* OptRangeSpec::reconstituteDoubleValue(NAType* type, Float64 val) const
{
  NABuiltInTypeEnum typeQual = type->getTypeQualifier();
  if (typeQual != NA_NUMERIC_TYPE)
    {
      assertLogAndThrow1(CAT_SQL_COMP_RANGE, logLevel_, FALSE, QRLogicException,
                         "Type not handled by reconstituteDoubleValue() -- %d",
                         typeQual);
      return NULL;
    }

  // Use these for the textual representation of a constant value, which is
  // passed to the ConstValue ctor.
  char constValTextBuffer[50];
  NAString constValTextStr;

  sprintf(constValTextBuffer, "%g", val);
  constValTextStr = constValTextBuffer;
  NumericType* numType = static_cast<NumericType*>(type);
  assertLogAndThrow(CAT_SQL_COMP_RANGE, logLevel_, 
                    !numType->isExact(),
                    QRLogicException,
                    "Expecting approximate numeric type in "
                        "reconstituteDoubleValue");

  NAType* constType = new(mvqrHeap_) SQLDoublePrecision(mvqrHeap_, FALSE);
  return new(mvqrHeap_) ConstValue(constType, &val, constType->getNominalSize(),
                                   &constValTextStr, mvqrHeap_);
} // reconstituteDoubleValue()

// Generate a left-linear OR backbone of equality predicates corresponding
// to the values within the subrange.
ItemExpr* OptRangeSpec::makeSubrangeORBackbone(SubrangeBase* subrange,
                                               ItemExpr* subrangeItem) const
{
  QRTRACER("makeSubrangeOrBackbone");

  NAType* type = getType()->newCopy(mvqrHeap_);
  NAType* int64Type = new (mvqrHeap_) SQLLargeInt(mvqrHeap_, TRUE, FALSE );
  type->resetSQLnullFlag();
  type->resetSQLnullHdrSize();
  assertLogAndThrow(CAT_SQL_COMP_RANGE, logLevel_,
                    type, QRDescriptorException,
                    "Call to getType() returned NULL in "
                    "OptRangeSpec::makeSubrangeOrBackbone().");
  NABuiltInTypeEnum typeQual = type->getTypeQualifier();
  assertLogAndThrow1(CAT_SQL_COMP_RANGE, logLevel_,
                     typeQual == NA_DATETIME_TYPE ||
                       typeQual == NA_INTERVAL_TYPE ||
                       (typeQual == NA_NUMERIC_TYPE && 
                         static_cast<const NumericType*>(type)->isExact()),
                     QRDescriptorException,
                     "Invalid type for makeSubrangeOrBackbone() -- %d", typeQual);
  
  Subrange<Int64>* intSubrange = (Subrange<Int64>*)subrange;
  Int64 startVal = intSubrange->start;
  Int64 endVal = intSubrange->end;
  ItemExpr* top = NULL;  // current top of backbone; eventual return value
  ItemExpr* eqExpr;      // construct each rangeitem=value pred here...
  ConstValue* cv;        // ...using equality to this constant

  for (Int64 val=startVal; val<=endVal; val++)
    {
      cv = reconstituteInt64Value(type, val);
      eqExpr = new(mvqrHeap_) BiRelat(ITM_EQUAL, subrangeItem, cv);
      eqExpr->synthTypeAndValueId();

      if (top)
        top = new(mvqrHeap_) BiLogic(ITM_OR, top, eqExpr);
      else
        top = eqExpr;
    }

  return top;
} // makeSubrangeORBackbone

ItemExpr* OptRangeSpec::makeSubrangeItemExpr(SubrangeBase* subrange,
                                             ItemExpr* subrangeItem) const
{
  QRTRACER("makeSubrangeItemExpr");

  // ItemExpr that we will build and return, representing the subrange.
  ItemExpr* itemExpr;

  // Nodes that the start and end values of the subrange will be attached
  // to (as the 2nd child) as necessary.
  ItemExpr *parentOfStart = NULL, *parentOfEnd = NULL;

  // If the subrange is derived from an IN list or a disjunction of equality
  // predicates, return an OR backbone of ITM_EQUALs.
  if ((subrange->getSpecifiedValueCount() > 0))
    return makeSubrangeORBackbone(subrange, subrangeItem);

  // Build the tree, except for the ConstValue subtrees that will be attached
  // later, after the underlying type of the subrange is determined.
  // parentOfStart and parentOfEnd mark the nodes to attach them to.
  if (subrange->isSingleValue())
    {
      // A single-point subrange may have been the result of intersection of
      // two ranges that left it with adjustment flags adopted from the another
      // subranges. They aren't relevant when the subrange represents a single
      // value, and will distort the value used if left in place.
      subrange->setStartAdjustment(0);
      subrange->setEndAdjustment(0);
      itemExpr = parentOfStart
               = new(mvqrHeap_) BiRelat(ITM_EQUAL, subrangeItem);
    }
  else if (subrange->endIsMax())
    if (subrange->startInclusive() && subrange->getStartAdjustment() == 0)
      itemExpr = parentOfStart
               = new(mvqrHeap_) BiRelat(ITM_GREATER_EQ, subrangeItem);
    else
      itemExpr = parentOfStart
               = new(mvqrHeap_) BiRelat(ITM_GREATER, subrangeItem);
  else if (subrange->startIsMin())
    if (subrange->endInclusive() && subrange->getEndAdjustment() == 0)
      itemExpr = parentOfEnd
               = new(mvqrHeap_) BiRelat(ITM_LESS_EQ, subrangeItem);
    else
      itemExpr = parentOfEnd
               = new(mvqrHeap_) BiRelat(ITM_LESS, subrangeItem);
  else
    {
      itemExpr = new(mvqrHeap_) BiLogic(ITM_AND);
      if (subrange->startInclusive() && subrange->getStartAdjustment() == 0)
        itemExpr->child(0) = parentOfStart
                           = new(mvqrHeap_) BiRelat(ITM_GREATER_EQ, subrangeItem);
      else
        itemExpr->child(0) = parentOfStart
                           = new(mvqrHeap_) BiRelat(ITM_GREATER, subrangeItem);
      if (subrange->endInclusive() && subrange->getEndAdjustment() == 0)
        itemExpr->child(1) = parentOfEnd
                           = new(mvqrHeap_) BiRelat(ITM_LESS_EQ, subrangeItem);
      else
        itemExpr->child(1) = parentOfEnd
                           = new(mvqrHeap_) BiRelat(ITM_LESS, subrangeItem);
    }

  // Now the item expression is complete except for filling in the constants
  // at the appropriate locations, denoted by the parentOfStart and parentOfEnd
  // ItemExpr ptrs, each of which is null if not applicable (e.g., an unbounded
  // range will only use either the start or end value, not both).
  NAType* type = getType()->newCopy(mvqrHeap_);
  type->resetSQLnullFlag();
  type->resetSQLnullHdrSize();
  assertLogAndThrow(CAT_SQL_COMP_RANGE, logLevel_,
                    type, QRDescriptorException,
                    "Call to getType() returned NULL in "
                    "OptRangeSpec::makeSubrangeItemExpr().");
  NABuiltInTypeEnum typeQual = type->getTypeQualifier();
  switch (typeQual)
    {
      case NA_NUMERIC_TYPE:
      case NA_DATETIME_TYPE:
      case NA_INTERVAL_TYPE:
        if (typeQual == NA_DATETIME_TYPE ||
            typeQual == NA_INTERVAL_TYPE ||
            (typeQual == NA_NUMERIC_TYPE && 
               static_cast<const NumericType*>(type)->isExact()))
          {
            Subrange<Int64>* intSubrange = (Subrange<Int64>*)subrange;
            Int64 startVal = intSubrange->start - intSubrange->getStartAdjustment();
            Int64 endVal = intSubrange->end + intSubrange->getEndAdjustment();
            if (parentOfStart)
              parentOfStart->child(1) = reconstituteInt64Value(type, startVal);
            if (parentOfEnd)
              parentOfEnd->child(1) = reconstituteInt64Value(type, endVal);
          }
        else
          {
            Subrange<double>* dblSubrange = (Subrange<double>*)subrange;
            double startVal = dblSubrange->start;
            double endVal = dblSubrange->end;
            if (parentOfStart)
              parentOfStart->child(1) = reconstituteDoubleValue(type, startVal);
            if (parentOfEnd)
              parentOfEnd->child(1) = reconstituteDoubleValue(type, endVal);
          }
        break;

      case NA_CHARACTER_TYPE:
        {
          // Alignment is 2 for UCS2, 1 for single-byte char set.
          if (type->getDataAlignment() == 2)
            {
              // Unicode string.
              Subrange<RangeWString>* wcharSubrange =
                             (Subrange<RangeWString>*)subrange;
              if (parentOfStart)
                parentOfStart->child(1) =
                            new(mvqrHeap_) ConstValue(wcharSubrange->start);
              if (parentOfEnd)
                parentOfEnd->child(1) =
                            new(mvqrHeap_) ConstValue(wcharSubrange->end);
            }
          else
            {
              // Latin1 string.
              Subrange<RangeString>* charSubrange 
                      = (Subrange<RangeString>*)subrange;
              if (parentOfStart)
                parentOfStart->child(1) =
                            new(mvqrHeap_) ConstValue(charSubrange->start, ((CharType *)type)->getCharSet() );
              if (parentOfEnd)
                parentOfEnd->child(1) =
                            new(mvqrHeap_) ConstValue(charSubrange->end, ((CharType *)type)->getCharSet() );
            }
        }
        break;

      default:
        assertLogAndThrow1(CAT_SQL_COMP_RANGE, logLevel_, 
                           FALSE, QRDescriptorException, 
                           "Unhandled data type in "
                           "OptRangeSpec::makeSubrangeItemExpr: %d",
                           typeQual);
        break;
    }

  // This NAType object is never used in the creation of a ConstValue.
  delete type;

  return itemExpr;
}  // makeSubrangeItemExpr()

void OptRangeSpec::intersectRange(OptRangeSpec* other)
{
  assertLogAndThrow(CAT_SQL_COMP_RANGE, logLevel_,
                    sameRangeSubject(other) || !other->rangeSubjectIsSet(),
                    QRDescriptorException,
                    "Intersecting with range on a different col/expr, or range "
                    "subject is not set");

  // Call the superclass version to intersect the ranges, and mark this range
  // spec as being an intersection. The isIntersection_ flag will cause the
  // itemexpr representing the overall range to be created, so its value id
  // can be used as the id attribute of the RangePred element, instead of that
  // of the initial predicate on the range column/expr. This is critical,
  // because the predicate corresponding to that id is the one used to carry
  // out a NotProvided rewrite instruction for a range pred.
  RangeSpec::intersectRange(other);
  isIntersection_ = TRUE;
}

void OptRangeSpec::unionRange(OptRangeSpec* other)
{
  assertLogAndThrow(CAT_SQL_COMP_RANGE, logLevel_,
                    sameRangeSubject(other) || !other->rangeSubjectIsSet(),
                    QRDescriptorException,
                    "Unioning with range on a different col/expr, or range "
                    "subject is not set");

  // Call the superclass version to union the ranges.
  RangeSpec::unionRange(other);
}

// normWA is not used here. It is a parameter because the OptNormRangeSpec
// redefinition of this virtual function needs it.
ItemExpr* OptRangeSpec::getRangeItemExpr(NormWA* normWA) const
{
  QRTRACER("OptRangeSpec::getRangeItemExpr");

  // ItemExpr representing the application of the range condition to the
  // subject column or expression.
  ItemExpr* rangeItemExpr = NULL;

  // If there are no values in the range, the predicate can't be satisfied;
  // return a FALSE itemexpr.
  if (!subranges_.entries() && !nullIncluded_)
    rangeItemExpr = new(mvqrHeap_) BoolVal(ITM_RETURN_FALSE);

  // If all values are covered by the range, the underlying predicate is
  // necessarily true; return a TRUE itemexpr.
  if (coversFullRange())
    rangeItemExpr = new(mvqrHeap_) BoolVal(ITM_RETURN_TRUE);

  // coversFullrange is false but we may have a full range [-inf..+inf] except
  // for NULL values. In other words the predicate 'a > -1 OR a < 1' is converted
  // to 'a IS NOT NULL'
  if ((rangeItemExpr == NULL) && ((subranges_.entries() == 1) && 
	subranges_[0]->coversFullRange()))
    rangeItemExpr = new(mvqrHeap_) UnLogic(ITM_IS_NOT_NULL, getRangeExpr());

  if (rangeItemExpr == NULL)
  {

  // ItemExpr representing the column or expression the range applies to.
    ItemExpr* subjectItemExpr = getRangeExpr();

  // Create a left-deep OR backbone joining the conditions representing the
  // subranges of this range.
  SubrangeBase* subrange = NULL;
  for (CollIndex i=0; i < subranges_.entries(); i++)
    {
      subrange = subranges_[i];
      if (!rangeItemExpr)
        rangeItemExpr = makeSubrangeItemExpr(subrange, subjectItemExpr);
      else
        rangeItemExpr = 
            new(mvqrHeap_) BiLogic(ITM_OR, rangeItemExpr,
                                   makeSubrangeItemExpr(subrange,
                                                        subjectItemExpr));
    }

  // If the range permits the null value, OR in an isNull predicate.
  if (nullIncluded_)
    {
      ItemExpr* isNullItemExpr = new(mvqrHeap_) UnLogic(ITM_IS_NULL,
                                                        subjectItemExpr);
      if (!rangeItemExpr)
        rangeItemExpr = isNullItemExpr;
      else
        rangeItemExpr = new(mvqrHeap_) BiLogic(ITM_OR,
                                               rangeItemExpr,
                                               isNullItemExpr);
    }
  }

  rangeItemExpr->synthTypeAndValueId();
  rangeItemExpr->setRangespecItemExpr(TRUE);
  return rangeItemExpr;
} // OptRangeSpec::getRangeItemExpr()

ItemExpr* OptNormRangeSpec::getRangeItemExpr(NormWA* normWA) const
{
  QRTRACER("OptNormRangeSpec::getRangeItemExpr");

  // Call the superclass version to do the primary work of producing an
  // ItemExpr from the range specification.
  ItemExpr* rangeItemExpr = OptRangeSpec::getRangeItemExpr();

  // Copy LIKE pred info from original expr.
  OperatorTypeEnum op = rangeItemExpr->getOperatorType();
  if ((op == ITM_AND)||(op == ITM_OR))
  {
    op = rangeItemExpr->child(0)->getOperatorType();
    if ( (op == ITM_GREATER_EQ) ||(op == ITM_GREATER) ||
         (op == ITM_LESS) ||(op == ITM_LESS_EQ))
    {
      BiRelat *br = (BiRelat *) rangeItemExpr->child(0).getPtr();
      OperatorTypeEnum op1 = getOriginalItemExpr()->child(0)->getOperatorType();
      if( (op1 == ITM_GREATER_EQ) || (op1 == ITM_GREATER) ||
          (op1 == ITM_LESS) ||(op1 == ITM_LESS_EQ))
      {
        BiRelat *br1 = (BiRelat *) getOriginalItemExpr()->child(0).getPtr();
	br->setAddedForLikePred(br1->addedForLikePred());
        br->setOriginalLikeExprId(br1->originalLikeExprId());
        br->setLikeSelectivity(br1->getLikeSelectivity());  
        if(br1->isSelectivitySetUsingHint())
        {
          br->setSelectivitySetUsingHint();
          br->setSelectivityFactor(br1->getSelectivityFactor());
        }
      }
    }
    op = rangeItemExpr->child(1)->getOperatorType();
    if ( (op == ITM_GREATER_EQ) ||(op == ITM_GREATER) ||
         (op == ITM_LESS) ||(op == ITM_LESS_EQ))
    {
      BiRelat *br = (BiRelat *) rangeItemExpr->child(1).getPtr();
      OperatorTypeEnum op1 = getOriginalItemExpr()->child(1)->getOperatorType();
      if( (op1 == ITM_GREATER_EQ) || (op1 == ITM_GREATER) ||
          (op1 == ITM_LESS) ||(op1 == ITM_LESS_EQ))
      {
        BiRelat *br1 = (BiRelat *) getOriginalItemExpr()->child(1).getPtr();
	br->setAddedForLikePred(br1->addedForLikePred());
        br->setOriginalLikeExprId(br1->originalLikeExprId());
        br->setLikeSelectivity(br1->getLikeSelectivity()); 
        if(br1->isSelectivitySetUsingHint())
        {
          br->setSelectivitySetUsingHint();
          br->setSelectivityFactor(br1->getSelectivityFactor());
        }
      }
    }
  }
  else if ( (op == ITM_GREATER_EQ) ||(op == ITM_GREATER) ||
	(op == ITM_LESS) ||(op == ITM_LESS_EQ))
    {
      BiRelat *br = (BiRelat *) rangeItemExpr;
      OperatorTypeEnum op1 = getOriginalItemExpr()->getOperatorType();
      if( (op1 == ITM_GREATER_EQ) || (op1 == ITM_GREATER) ||
          (op1 == ITM_LESS) ||(op1 == ITM_LESS_EQ))
      {
        BiRelat *br1 = (BiRelat *) getOriginalItemExpr();
	br->setAddedForLikePred(br1->addedForLikePred());
        br->setOriginalLikeExprId(br1->originalLikeExprId());
        br->setLikeSelectivity(br1->getLikeSelectivity());  
        if(br1->isSelectivitySetUsingHint())
        {
          br->setSelectivitySetUsingHint();
          br->setSelectivityFactor(br1->getSelectivityFactor());
        }
      }
    }

  if(((ItemExpr *)getOriginalItemExpr())->isSelectivitySetUsingHint())
  {
    rangeItemExpr->setSelectivitySetUsingHint();
    rangeItemExpr->setSelectivityFactor(getOriginalItemExpr()->getSelectivityFactor());
  }

  // Now associate the range spec's itemexpr with the value id of the
  // original expression.
  ValueId vid = getOriginalItemExpr()->getValueId();
  vid.replaceItemExpr(rangeItemExpr);
  if (normWA)
    rangeItemExpr->normalizeNode(*normWA);
  return rangeItemExpr;
}

void OptNormRangeSpec::intersectRange(OptNormRangeSpec* other)
{
  // Build the item expression tree corresponding to the combined range.
  ItemExpr* otherItemExpr = const_cast<ItemExpr*>(other->getOriginalItemExpr());
  if (originalItemExpr_ && otherItemExpr)
    {
      originalItemExpr_ = new(mvqrHeap_) BiLogic(ITM_AND,
                                                 originalItemExpr_,
                                                 otherItemExpr);
      originalItemExpr_->synthTypeAndValueId(TRUE);
    }
  else
    {
      if (!originalItemExpr_)
      {
        QRLogger::log(CAT_SQL_COMP_RANGE, logLevel_,
          "OptNormRangeSpec::intersectRange -- originalItemExpr_ is NULL.");
      }
      if (!otherItemExpr)
      {
        QRLogger::log(CAT_SQL_COMP_RANGE, logLevel_,
          "OptNormRangeSpec::intersectRange -- other op has NULL ItemExpr.");
      }
    }

  // Now call the superclass version to intersect the ranges.
  OptRangeSpec::intersectRange(other);
}

void OptNormRangeSpec::unionRange(OptNormRangeSpec* other)
{
  // Build the item expression tree corresponding to the combined range.
  ItemExpr* otherItemExpr = const_cast<ItemExpr*>(other->getOriginalItemExpr());
  if (originalItemExpr_ && otherItemExpr)
    {
      originalItemExpr_ = new(mvqrHeap_) BiLogic(ITM_OR,
                                                 originalItemExpr_,
                                                 otherItemExpr);
      originalItemExpr_->synthTypeAndValueId(TRUE);
    }
  else
    {
      if (!originalItemExpr_)
      {
        QRLogger::log(CAT_SQL_COMP_RANGE, logLevel_,
          "OptNormRangeSpec::unionRange -- originalItemExpr_ is NULL.");
      }
      if (!otherItemExpr)
      {
        QRLogger::log(CAT_SQL_COMP_RANGE, logLevel_,
          "OptNormRangeSpec::unionRange -- other op has NULL ItemExpr.");
      }
    }

  // Now call the superclass version to union the ranges.
  OptRangeSpec::unionRange(other);
}

// Convert a date, time, or timestamp value to an integral form for use with
// range specifications.
static Int64 getInt64ValueFromDateTime(ConstValue* val,
                                       const DatetimeType* rangeColType,
                                       const DatetimeType* constType,
                                       NABoolean& truncated,
                                       logLevel level)
{
  char dateRep[11];
  Int64 i64val;
  char* valPtr = (char*)val->getConstValue() +
                        val->getType()->getSQLnullHdrSize();
  Lng32 rangeColFracSecPrec = rangeColType->getFractionPrecision();
  Lng32 constValueFracSecPrec = constType->getFractionPrecision();
  Lng32 fracSec;

  truncated = FALSE;

  switch (constType->getSubtype())
    {
      case DatetimeType::SUBTYPE_SQLDate:
        memcpy(dateRep, valPtr, 4);
        memset(dateRep+4, 0, 7);
        i64val = DatetimeType::julianTimestampValue(dateRep, 11, 0)
                      / SubrangeBase::MICROSECONDS_IN_DAY;
        break;

      case DatetimeType::SUBTYPE_SQLTime:
        i64val = *valPtr * 3600 + *(valPtr+1) * 60 + *(valPtr+2);
        i64val *= 1000000;  // in microseconds
        if (constValueFracSecPrec)
          {
            memcpy(&fracSec, valPtr+3, 4);
            i64val += fracSec * (Int64)pow(10, 6-constValueFracSecPrec);
          }
        break;

      case DatetimeType::SUBTYPE_SQLTimestamp:
        i64val = DatetimeType::julianTimestampValue(valPtr,
                                                    constValueFracSecPrec ? 11 : 7,
                                                    constValueFracSecPrec);
        break;

      default:
        assertLogAndThrow1(CAT_SQL_COMP_RANGE, level,
                           FALSE, QRDescriptorException,
                           "Invalid datetime subtype -- %d", constType->getSubtype());
    }

  // For time or timestamp (if date, both compared values will be 0), truncate
  // any extra (wrt the col type) fractional precision from the value and mark
  // it as truncated. The caller will use this to determine if the comparison
  // operator with the truncated value needs to be changed (e.g., t<time'12:00:00.4'
  // <--> t<=time'12:00:00', if t is time(0).
  if (constValueFracSecPrec > rangeColFracSecPrec)
    {
      Int64 scaleFactor = (Int64)pow(10, 6-rangeColFracSecPrec);
      Int64 unscaledI64Val = i64val;
      i64val = i64val / scaleFactor * scaleFactor;
      truncated = (i64val != unscaledI64Val);
    }

  return i64val;
}

// Return an interval value as an Int64 for use with range specifications.
// An interval value of either type (year-month or day-time) will be calculated
// in terms of the least significant field of that type, regardless of the
// actual fields used in the declaration. For example, an interval specified as
// HOUR TO MINUTE will return a value which is a number of microseconds. This
// facilitates comparing intervals of different granularity.
//
// A day-time interval that ends in seconds may specify a fractional precision
// less than the default (e.g., Interval '5.1' Second(2,2)), in which case its
// raw value is in units of a lower precision than microseconds (hundredths of
// a second in the example). We scale such values to microseconds so that
// everything is comparable. In the example above, the value used would be
// 5100000 instead of the original internal integral value of 510.
static Int64 getInt64ValueFromInterval(ConstValue* constVal,
                                       const IntervalType* colIntvlType,
                                       NABoolean& truncated,
                                       NABoolean& valWasNegative,
                                       logLevel level)
{
  const IntervalType* constIntvlType = 
          static_cast<const IntervalType*>(constVal->getType());
  Int64 i64val;
  char* val = (char*)constVal->getConstValue();
  Lng32 storageSize = constVal->getStorageSize();
  Lng32 nullHdrSize = constVal->getType()->getSQLnullHdrSize();
  val += nullHdrSize;
  storageSize -= nullHdrSize;
  switch (storageSize)
    {
      // No need to check for signed/unsigned before checking for negative;
      // interval type is always signed.
      case 2:
        {
          Int16 valx;
          memcpy(&valx, val, sizeof(Int16));
          valWasNegative = (valx < 0);
          i64val = valx;
        }
        break;
      case 4:
        {
          Lng32 valx;
          memcpy(&valx, val, sizeof(Lng32));
          valWasNegative = (valx < 0);
          i64val = valx;
        }
        break;
      case 8:
        memcpy(&i64val, val, sizeof(i64val));
        valWasNegative = (i64val < 0);
        break;
      default:
        assertLogAndThrow1(CAT_SQL_COMP_RANGE, level,
                           FALSE, QRDescriptorException,
                           "Invalid interval storage length -- %d",
                           storageSize);
        break;
    }

  // Now cast the value in terms of the least significant field for the constant's
  // interval type (months for year-month, microseconds for day-time), which may
  // have different fields than those of the column's type.
  switch (constIntvlType->getEndField())
    {
      case REC_DATE_YEAR:
        // Multiply by number of months in a year
        i64val *= 12;
        break;
      case REC_DATE_MONTH:
        // Value is already in correct units (months).
        break;
      case REC_DATE_DAY:
        // Multiply by number of microseconds in a day.
        i64val *= (24LL * 60 * 60000000);
        break;
      case REC_DATE_HOUR:
        // Multiply by number of microseconds in an hour.
        i64val *= (60LL * 60000000);
        break;
      case REC_DATE_MINUTE:
        // Multiply by number of microseconds in a minute.
        i64val *= 60000000;
        break;
      case REC_DATE_SECOND:
        // We want all intervals with seconds as the end field to be represented
        // as a number of microseconds to ensure comparability, so if the
        // fractional precision is less than the default (6), scale it to
        // microseconds.
        i64val *= (Int64)pow(10, 6 - constIntvlType->getFractionPrecision());
        break;
      default:
        assertLogAndThrow1(CAT_SQL_COMP_RANGE, level,
                           FALSE, QRDescriptorException,
                           "Invalid end field for interval -- %d",
                           constIntvlType->getEndField());
        break;
    }

  // Now discard any part of the constant value owing to extra precision in the
  // constant's type. For instance, if the column type is INTERVAL YEAR and the
  // constant is "interval'2-7'year to month", the constant is truncated to 2
  // years. We remember that this truncation occurred, as it may affect the
  // comparison operator used in the rangespec.
  Int64 scaleFactor;
  Int64 origI64Val = i64val;
  switch (colIntvlType->getEndField())
    {
      // Do integer division to scrape off any excess precision in the
      // constant value, then multipy by same to restore it as a number of
      // months (year-month interval) or microseconds (day-time).
      case REC_DATE_YEAR:
        // Divide/multiply by number of months in a year
        i64val = i64val / 12 * 12;
        break;
      case REC_DATE_MONTH:
        // No possibility of extra precision for the constant value.
        break;
      case REC_DATE_DAY:
        // Divide/multiply by number of microseconds in a day.
        i64val = i64val / (24LL * 60 * 60000000) * (24LL * 60 * 60000000);
        break;
      case REC_DATE_HOUR:
        // Divide/multiply by number of microseconds in an hour.
        i64val = i64val / (60LL * 60000000) * (60LL * 60000000);
        break;
      case REC_DATE_MINUTE:
        // Divide/multiply by number of microseconds in a minute.
        i64val = i64val / 60000000 * 60000000;
        break;
      case REC_DATE_SECOND:
        // Divide/multiply by 10 ** <unused frac secs>.
        scaleFactor = (Int64)pow(10, 6 - colIntvlType->getFractionPrecision());
        i64val = i64val / scaleFactor * scaleFactor;
        break;
      default:
        assertLogAndThrow1(CAT_SQL_COMP_RANGE, level,
                          FALSE, QRDescriptorException,
                          "Invalid end field for interval -- %d",
                          colIntvlType->getEndField());
        break;
    }

  truncated = (origI64Val != i64val);
  return i64val;
}

Int64 getInt64Value(ConstValue* val, const NAType* rangeColType, 
                    NABoolean& truncated, NABoolean& valWasNegative,
                    logLevel level)
{
  truncated = FALSE;
  valWasNegative = FALSE;

  // If the constant value is a date, time, timestamp, or interval, pass it on
  // to the correct function for handling that type.
  const NAType* constValType = val->getType();
  if (constValType->getTypeQualifier() == NA_DATETIME_TYPE)
    return getInt64ValueFromDateTime(val,
                                     static_cast<const DatetimeType*>(rangeColType),
                                     static_cast<const DatetimeType*>(constValType),
                                     truncated, level);
  else if (constValType->getTypeQualifier() == NA_INTERVAL_TYPE)
    return getInt64ValueFromInterval(val,
                                     static_cast<const IntervalType*>(rangeColType),
                                     truncated, valWasNegative, level);

  assertLogAndThrow1(CAT_SQL_COMP_RANGE, level,
                     constValType->getTypeQualifier() == NA_NUMERIC_TYPE,
                     QRDescriptorException,
                     "Unexpected date type -- %d",
                     constValType->getTypeQualifier());
  const NumericType* constValNumType = static_cast<const NumericType*>(constValType);
  Lng32 rangeColumnScale = rangeColType->getScale();
  NABoolean isExactNumeric = val->isExactNumeric();
  Lng32 constValueScale = (isExactNumeric ? constValNumType->getScale() : 0);
  char* valuePtr = (char*)val->getConstValue();
  Lng32 storageSize = val->getStorageSize();
  Lng32 nullHdrSize = constValNumType->getSQLnullHdrSize();
  valuePtr += nullHdrSize;
  storageSize -= nullHdrSize;
  
  // Scale factor for exact numeric constant values.
  Int64 scaleFactor = 1;
  if (constValueScale < rangeColumnScale)
    scaleFactor = (Int64)pow(10, rangeColumnScale - constValueScale);

  // Scale factor for approximate (floating-point) constant values.
  double dblScaleFactor = pow(10, rangeColumnScale);
  Int64 i64val = 0;
  Float64 flt64val = 0;

  if (constValNumType->isDecimal())
    {
      // Decode the decimal value from the string of digits. The digit values
      // are the lower nibble of each byte. As we go from left to right,
      // multiple the accumulated value by 10, and add the value of the next
      // digit. The value is negative if the upper nibble of the first byte is
      // 11 (0xB0 after masking off lower nibble).
      char* p = valuePtr;
      for (Lng32 i=0; i<storageSize; i++)
        (i64val *= 10) += (*p++ & 0x0F);
      if ((*valuePtr & 0xF0) == 0xB0)
        {
          i64val *= -1;
          valWasNegative = TRUE;
        }
    }
  else
    switch (storageSize)
      {
        case 1:
          {
            assertLogAndThrow1(CAT_SQL_COMP_RANGE, level,
                            isExactNumeric, QRDescriptorException,
                            "Constant value of size 1 not exact numeric, type is: %d",
                            constValNumType->getTypeQualifier());
            Int8 i8val;
            memcpy(&i8val, valuePtr, storageSize);
            if (constValNumType->isSigned())
              {
                valWasNegative = (i8val < 0);
                i64val = (Int64)(i8val * scaleFactor);
              }
            else
              i64val = (Int64)((UInt8)i8val * scaleFactor);
          }
          break;

       case 2:
         {
            assertLogAndThrow1(CAT_SQL_COMP_RANGE, level,
                            isExactNumeric, QRDescriptorException,
                            "Constant value of size 2 not exact numeric, type is: %d",
                            constValNumType->getTypeQualifier());
            Int16 i16val;
            memcpy(&i16val, valuePtr, storageSize);
            if (constValNumType->isSigned())
              {
                valWasNegative = (i16val < 0);
                i64val = (Int64)(i16val * scaleFactor);
              }
            else
              i64val = (Int64)((UInt16)i16val * scaleFactor);
          }
          break;

        case 4:
          if (isExactNumeric)
            {
              Lng32 i32val;
              memcpy(&i32val, valuePtr, storageSize);
              if (constValNumType->isSigned())
                {
                  valWasNegative = (i32val < 0);
                  i64val = (Int64)(i32val * scaleFactor);
                }
              else
                i64val = (Int64)((UInt32)i32val * scaleFactor);
            }
          else
            {
              Float32 flt32val;
              memcpy(&flt32val, valuePtr, storageSize);
              valWasNegative = (flt32val < 0);
              flt64val = flt32val * dblScaleFactor;
              if (flt64val < LLONG_MIN)
                i64val = LLONG_MIN;
              else if (flt64val > LLONG_MAX)
                i64val = LLONG_MAX;
              else
                i64val = (Int64)flt64val;
            }
          break;
        
        case 8:
          if (isExactNumeric)
            {
              memcpy(&i64val, valuePtr, storageSize);
              valWasNegative = (i64val < 0);
              i64val *= scaleFactor;
            }
          else
            {
              memcpy(&flt64val, valuePtr, storageSize);
              valWasNegative = (flt64val < 0);
              flt64val *= dblScaleFactor;
              if (flt64val < LLONG_MIN)
                i64val = LLONG_MIN;
              else if (flt64val > LLONG_MAX)
                i64val = LLONG_MAX;
              else
                i64val = (Int64)flt64val;
            }
          break;
        
        default:
          assertLogAndThrow1(CAT_SQL_COMP_RANGE, level,
                            FALSE, QRDescriptorException,
                            "Numeric constant of unexpected size: %d bytes",
                            storageSize);
          return 0;      // avoid warning
      }

  // If the constant has more digits to the right of the decimal point than the
  // range column, note it as truncated if any of the excess digits is nonzero.
  // The caller will use this to determine if the comparison operator with the
  // truncated value needs to be changed (e.g., i>4.3 <--> i>=4, if scale of i
  // is 0).
  if (isExactNumeric)
    {
      if (constValueScale > rangeColumnScale)
        {
          scaleFactor = (Int64)pow(10, constValueScale - rangeColumnScale);
          truncated = (i64val / scaleFactor * scaleFactor != i64val);
          return i64val / scaleFactor;
        }
      else
        return i64val;
    }
  else
    {
      truncated = (i64val != flt64val);
      return i64val;
    }
}

double getDoubleValue(ConstValue* val, logLevel level)
{
  // If the constant is a SystemLiteral (typically produced by the cast of
  // constant value), the value pointer and storage size will include a null
  // indicator header field that we have to take into account when accessing
  // the value. It also means the actual value field may not be aligned
  // properly, so we need to memcpy the value representation into a variable
  // of the appropriate type.
  const NAType* constValType = val->getType();
  Lng32 nullHdrSize = constValType->getSQLnullHdrSize();
  Lng32 valueStorageSize = val->getStorageSize() - nullHdrSize;
  void* valuePtr = (char*)val->getConstValue() + nullHdrSize;

  NABoolean isExactNumeric = val->isExactNumeric();
  double scaleDivisor = pow(10, isExactNumeric ? constValType->getScale() : 0);

  if (static_cast<const NumericType*>(constValType)->isDecimal())
    {
      // Decode the decimal value from the string of digits. The digit values
      // are the lower nibble of each byte. As we go from left to right,
      // multiple the accumulated value by 10, and add the value of the next
      // digit. The value is negative if the upper nibble of the first byte is
      // 11 (0xB0 after masking off lower nibble).
      char* p = (char*)valuePtr;
      Int64 i64val = 0;
      for (Lng32 i=0; i<valueStorageSize; i++)
        (i64val *= 10) += (*p++ & 0x0F);
      if ((*(char*)valuePtr & 0xF0) == 0xB0)
        i64val *= -1;
      return i64val / scaleDivisor;
    }

  switch (valueStorageSize)
    {
      case 1: // tinyint
        {
          assertLogAndThrow1(CAT_SQL_COMP_RANGE, level,
                           isExactNumeric, QRDescriptorException,
                           "const value of size 1 not exact numeric: %d",
                           constValType->getTypeQualifier());
          Int8 i8val;
          memcpy(&i8val, valuePtr, valueStorageSize);
          return i8val / scaleDivisor;
        }

      case 2: // smallint
        {
          assertLogAndThrow1(CAT_SQL_COMP_RANGE, level,
                           isExactNumeric, QRDescriptorException,
                           "const value of size 2 not exact numeric: %d",
                           constValType->getTypeQualifier());
          Int16 i16val;
          memcpy(&i16val, valuePtr, valueStorageSize);
          return i16val / scaleDivisor;
        }

      case 4: //  int
        if (isExactNumeric)
          {
            Lng32 i32val;
            memcpy(&i32val, valuePtr, valueStorageSize);
            return i32val / scaleDivisor;
          }
        else
          {
            Float32 fltval;
            memcpy(&fltval, valuePtr, valueStorageSize);
            return fltval;
          }
      
      case 8: // largeint
        if (isExactNumeric)
          {
            // possible loss of data
            Int64 i64val;
            memcpy(&i64val, valuePtr, valueStorageSize);
            return (double)(i64val / scaleDivisor);
          }
        else
          {
            Float64 dblval;
            memcpy(&dblval, valuePtr, valueStorageSize);
            return dblval;
          }
      
      default:
        assertLogAndThrow1(CAT_SQL_COMP_RANGE, level,
                           FALSE, QRDescriptorException,
                           "Numeric constant of unexpected size: %d bytes",
                           val->getStorageSize());
        return 0;      // avoid warning
    }
}

NABoolean RangeInfo::operator==(const RangeInfo& other)
{
  if (rangeSpec_->getRangeJoinPredId() != NULL_VALUE_ID)
    return rangeSpec_->getRangeJoinPredId() ==
              other.rangeSpec_->getRangeJoinPredId();
  else if (rangeSpec_->getRangeColValueId() != NULL_VALUE_ID)
    return rangeSpec_->getRangeColValueId() ==
              other.rangeSpec_->getRangeColValueId();
  else
    return rangeSpec_->getRangeExprText()==other.rangeSpec_->getRangeExprText();
}
