/**********************************************************************
// @@@ 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 @@@
**********************************************************************/
 /* -*-C++-*-
******************************************************************************
*
* File:         ItemExpr.C
* Description:  Item expressions (both physical and logical operators)
* Created:      5/17/94
* Language:     C++
*
*
*
*
******************************************************************************
*/

#define  SQLPARSERGLOBALS_NADEFAULTS
#include "SqlParserGlobals.h"

#include "Platform.h"
#include "Sqlcomp.h"
#include "GroupAttr.h"
#include "AllItemExpr.h"
#include "PartFunc.h"
#include "wstr.h"
#include "NLSConversion.h"
#include "Cost.h"          /* for lookups in the defaults table */
#include "Stats.h"
#include "exp_function.h" // for calling ExHDPHash::hash(data, len)
#include "ItemFuncUDF.h"
#include "CmpStatement.h"
#include "exp_datetime.h"

#include "OptRange.h"

#   include <limits.h>

#include <string.h>			// memcmp


// A constant to be used for allocating a buffer for getText()
#define TEXT_DISPLAY_LENGTH 1001

static NABoolean isQuantifiedComp(const ItemExpr *ie);

#define _strcmpi strcasecmp


// Initialize static members.
//THREAD_P OperatorTypeEnum ItemExpr::origOpTypeBeingBound_ = NO_OPERATOR_TYPE;
//THREAD_P Int32 ItemExpr::origOpTypeCounter_ = 0;

void ItemExpr::cleanupPerStatement()
{ 
  if (CURRENTSTMT)
     CURRENTSTMT->setItemExprOrigOpTypeBeingBound(NO_OPERATOR_TYPE);
}

// -----------------------------------------------------------------------
// methods for class ExprValueId
// -----------------------------------------------------------------------


// Ane ExprValueId can hold either an ItemExpr * or a ValueId.
// If it holds ValueId then the ItemExpr * is NULL.

ExprValueId::ExprValueId()
{
  exprMode_ = STANDALONE;
  exprPtr_  = NULL;
  exprId_   = NULL_VALUE_ID;
}

ExprValueId::ExprValueId(const ExprValueId &other)
{
  exprMode_ = other.exprMode_;
  exprId_   = other.exprId_;
  exprPtr_  = other.exprPtr_;

  if (exprId_ != NULL_VALUE_ID)
    exprPtr_  = NULL;
}

ExprValueId::ExprValueId(ItemExpr * exprPtr)
{
  exprMode_ = STANDALONE;
  exprPtr_  = exprPtr;
  if (exprPtr_ != NULL)
    exprId_   = exprPtr->getValueId();
  else
    exprId_   = NULL_VALUE_ID;

  if (exprId_ != NULL_VALUE_ID)
    exprPtr_  = NULL;
}

ExprValueId::ExprValueId(const ValueId & exprId)
{
  exprMode_ = STANDALONE;
  exprPtr_  = NULL;
  exprId_   = exprId;
}

ExprValueId & ExprValueId::operator= (const ExprValueId & other)
{
  CMPASSERT(exprMode_ != MEMOIZED);
  exprMode_ = other.exprMode_;
  exprPtr_ = other.exprPtr_;
  exprId_ = other.exprId_;

  if (exprId_ != NULL_VALUE_ID)
    exprPtr_  = NULL;
  return *this;
}

ExprValueId & ExprValueId::operator= (ItemExpr * other)
{
  CMPASSERT(exprMode_ != MEMOIZED);
  exprPtr_ = other;
  // update the value id as well (may be set to a NULL value id, though)
  if (exprPtr_ != NULL)
    exprId_ = exprPtr_->getValueId();
  else
    exprId_ = NULL_VALUE_ID;

  if (exprId_ != NULL_VALUE_ID)
    exprPtr_  = NULL;
  return *this;
}

ExprValueId & ExprValueId::operator= (const ValueId & other)
{
  CMPASSERT(exprMode_ != MEMOIZED);
  exprId_ = other;
  exprPtr_ = NULL;
  return *this;
}

NABoolean ExprValueId::operator== (const ExprValueId &other) const
{
  return (getPtr() == other.getPtr());       // ptrs must match
}

NABoolean ExprValueId::operator== (const ItemExpr *other) const
{
  return getPtr() == other;
}
NABoolean ExprValueId::operator== (const ValueId &other) const
{
  return (getValueId() == other);
}

ValueId ExprValueId::getValueId() const
{
  // make sure we return the value id that belongs to exprPtr_
  // (we might have initialized it with an ItemExpr * and later
  // added the value id to the ItemExpr without updating this object)
  if (exprId_ == NULL_VALUE_ID AND exprPtr_ != NULL)
    return exprPtr_->getValueId();
  else
    return exprId_;
}
void ExprValueId::convertToMemoized()
{
  // set this mode to prevent updates to it: a MEMOIZED object cannot
  // be assigned a new value
  exprMode_ = MEMOIZED;
}

void ExprValueId::convertToStandalone()
{
  exprMode_ = STANDALONE;
}

ItemExpr * ExprValueId::getPtr() const
{
  ValueId temp = exprId_;		// NSK platform needs to save this...?
  exprPtr_->checkInvalidObject(this);
  if (temp == NULL_VALUE_ID)
  {
    if (exprPtr_ == NULL || exprPtr_->getValueId() == NULL_VALUE_ID)
      return exprPtr_;
    return exprPtr_->getValueId().getItemExpr();
  }
  return exprId_.getItemExpr();
}

// -----------------------------------------------------------------------
// common member functions
// -----------------------------------------------------------------------

THREAD_P ObjectCounter (*ItemExpr::counter_)(0);

ItemExpr::ItemExpr(OperatorTypeEnum otype,
		   ItemExpr *child0,
		   ItemExpr *child1)
  : ExprNode(otype),
//  origOpType_(origOpTypeBeingBound() != NO_OPERATOR_TYPE ?
//		origOpTypeBeingBound() : otype),
    currChildNo_(0),
    clause_(NULL),
    collateClause_(NULL),
    previousHostVar_(FALSE),
    resolveIncompleteType_(FALSE),
    preCodeGenNATypeChange_(FALSE),
    selectivityFactor_(-1),
    flags_(0)
{
  child(0) = child0;
  child(1) = child1;
  replacementExpr_ = this;
  (*counter_).incrementCounter();

  origOpType_ = otype;

  CmpStatement* currStmt = CmpCommon::statement();
  if ( currStmt ) {
    OperatorTypeEnum x = currStmt->getItemExprOrigOpTypeBeingBound();

    if (x != NO_OPERATOR_TYPE)
      origOpType_ = x;
  }
}

ItemExpr::ItemExpr(const ItemExpr& s)
  : ExprNode(s)
  , valId_(s.valId_)
  , currChildNo_(s.currChildNo_)
  , collateClause_(s.collateClause_)
  , replacementExpr_(s.replacementExpr_)
  , clause_(s.clause_)
  , origOpType_(s.origOpType_)
  , previousHostVar_(s.previousHostVar_)
  , resolveIncompleteType_(s.resolveIncompleteType_)
  , previousName_(s.previousName_)
  , preCodeGenNATypeChange_(s.preCodeGenNATypeChange_)
  , selectivityFactor_(s.selectivityFactor_)
  , flags_(s.flags_)
{
  inputs_[0] = s.inputs_[0];
  inputs_[1] = s.inputs_[1];
  inputs_[2] = s.inputs_[2];
}

ItemExpr::~ItemExpr()
{
  // recursively delete all the children
  for (Lng32 i = 0; i < MAX_ITM_ARITY; i++)
    delete inputs_[i].getPtr();
  (*counter_).decrementCounter();
}

void ItemExpr::transformToRelExpr(NormWA & normWARef,
                            ExprValueId & locationOfPointerToMe,
                            ExprGroupId & introduceSemiJoinHere,
                            const ValueIdSet & externalInputs)
{
      // Do nothing
   locationOfPointerToMe = this;

}

// operator[] is used to access the children of a tree
ExprValueId & ItemExpr::operator[] (Lng32 index)
{
  CMPASSERT(index >= 0 AND index < MAX_ITM_ARITY);
  return inputs_[index];
}

const ExprValueId & ItemExpr::operator[] (Lng32 index) const
{
  CMPASSERT(index >= 0 AND index < MAX_ITM_ARITY);
  return inputs_[index];
}

NABoolean ItemExpr::operator== (const ItemExpr& other) const	// virtual meth
{
  return (getValueId() == other.getValueId());
}
void ItemExpr::deleteInstance()
{
  Int32 nc = getArity();
  for (Lng32 i = 0; i < (Lng32)nc; i++)
    inputs_[i] = NULL;
  delete this;
} // ItemExpr::deleteInstance()


void ItemExpr::setChild(Lng32 index, ExprNode * newChild)
{
  if (newChild)
    {
      CMPASSERT(newChild->castToItemExpr());
      child(index) = newChild->castToItemExpr();
    }
  else
    child(index) = (ItemExpr *)NULL;
} // ItemExpr::setChild()

void ItemExpr::allocValueId()
{
  ValueDesc *vdesc = new (CmpCommon::statementHeap()) ValueDesc(this);
  setValueId(vdesc->getValueId());
} // ItemExpr::allocValueId()

// Check whether the given ValueId is referenced in this ItemExpr.
NABoolean ItemExpr::referencesTheGivenValue(const ValueId & vid,
                                    NABoolean doNotDigInsideVegRefs ,
                                    NABoolean doNotDigInsideInstNulls) const
{
  // In really peculiar cases, a VEGRef might contain another VEGRef within
  // its VEG which recursively self-references the VEGRef. In order to prevent
  // running into an infinite loop there, we remember those VEG we've already
  // already seen by setting a flag in those VEG. If we run into that again,
  // there is no need to check the members of the VEG into it anymore since
  // those have already been or will be checked.
  //
  NABoolean retVal = FALSE;

  if (getValueId() == vid)
    return TRUE;

  ValueId exprId;
  switch (getOperatorType())
  {
    case ITM_VEG_PREDICATE:
    {
      VEG *veg = ((VEGPredicate *)this)->getVEG();
      if (veg->getVEGReference()->getValueId() == vid)
        return TRUE;
      else
      {
        // Already seen. Return FALSE. In VEGRef_x(VEG{VEGRef_x(..),y,z}),
        // the call to the inner VEGRef_x returns FALSE. However, if the
        // vid is VEGRef_x itself, when the function is called on the outer
        // VEGRef_x, it has return TRUE already. The previous "if" clause
        // ensures that. If vid is one of the other values in the VEG such
        // as y or z, ValueIdSet::referencesTheGivenValue() is going to call
        // us again on other members of the VEG. We will return TRUE with
        // the matching member; and ValueIdSet::referencesTheGivenValue()
        // is also going to return TRUE when we return TRUE on any one of
        // the members of the VEG.
        //
        if (veg->seenBefore())
          return FALSE;
        else
        {
          // Mark this VEG as already seen before going over its members,
          // so that if one of its members is a VEGRef to this VEG, we
          // don't have to traverse the VEG anymore.
          //
          veg->markAsSeenBefore();
          retVal = veg->getAllValues().referencesTheGivenValue(vid,exprId);
          veg->markAsNotSeenBefore();
        }
      }
      break;
    }
    case ITM_VEG_REFERENCE:
    {
      if (doNotDigInsideVegRefs)
        return FALSE;

      VEG *veg = ((VEGReference *)this)->getVEG();

      // Already seen. Return FALSE. In VEGRef_x(VEG{VEGRef_x(..),y,z}),
      // the call to the inner VEGRef_x returns FALSE. However, if the
      // vid is VEGRef_x itself, when the function is called on the outer
      // VEGRef_x, it has return TRUE already. The previous "if" clause
      // ensures that. If vid is one of the other values in the VEG such
      // as y or z, ValueIdSet::referencesTheGivenValue() is going to call
      // us again on other members of the VEG. We will return TRUE with
      // the matching member; and ValueIdSet::referencesTheGivenValue()
      // is also going to return TRUE when we return TRUE on any one of
      // the members of the VEG.
      //
      if (veg->seenBefore())
      {
        return FALSE;
      }
      else
      {
        // Mark this VEG as already seen before going over its members,
        // so that if one of its members is a VEGRef to this VEG, we
        // don't have to traverse the VEG anymore.
        //
        veg->markAsSeenBefore();
        retVal = veg->getAllValues().referencesTheGivenValue(vid,exprId);
        veg->markAsNotSeenBefore();
      }
      break;
    }
    case ITM_INSTANTIATE_NULL:
    {
      ValueId  nvid = getValueId();
      const ItemExpr * nie = nvid.getItemExpr();
      InstantiateNull *inst = (InstantiateNull *)nie->castToItemExpr();

      if (doNotDigInsideInstNulls)
        return FALSE;
      else
      {
        // Need to dig underneath the instantiate null to check if
        // the value we are looking for is the immediate child of
        // the instantiate null or contained in a veg reference
        // that is the child of the instantiate null.
        const ValueId & childVid = this->child(0)->getValueId();
        const ItemExpr * childExpr = childVid.getItemExpr();
        retVal =  childExpr->referencesTheGivenValue(vid);
      }
      break;
    } // end case instantiate null
    case ITM_ROWSETARRAY_SCAN:
    {
      retVal = FALSE;
      break;
    }
    default:
    {
      Lng32 nc = getArity();
      for (Lng32 i = 0; i < nc; i++)
      {
        if (child(i).getPtr())
        {
          if (child(i)->referencesTheGivenValue(vid))
          {
            retVal = TRUE;
            break;
          }
        }
      } // endfor

      // if this is a subquery, check any outer references of the subquery as
      // well as the children.
      //
      if ((NOT retVal) AND isASubquery())
      {
        // check if the given value is referenced in the required inputs of
        // the subquery
        //
        const ValueIdSet inputs = ((Subquery *)this)->getSubquery()->
                                   getGroupAttr()->getCharacteristicInputs();

        // Must not call internal function here, since we are checking on a
        // different set (inputs), not a subexpr within this node.
        //
        retVal = inputs.referencesTheGivenValue(vid,exprId);
      }
      break;
    } // default
  } // switch

  return retVal;
}




// Check whether this ItemExpr references any one value
// belonging to the given ValueidSet
NABoolean ItemExpr::referencesOneValueFrom(const ValueIdSet &vs) const
{
  for (ValueId id = vs.init(); vs.next(id); vs.advance(id))
    {
	  //check if the item expr is a non-strict constant
	  //a strict constant is somethine like cos(1)
	  //where as cos(?p) can be considered a constant
	  //in the non-strict definition since it remains
	  //constant for a given execution of a query
      if (!id.getItemExpr()->doesExprEvaluateToConstant(FALSE) )
         if (referencesTheGivenValue(id))
	    return TRUE;
    }
  return FALSE;
} // ItemExpr::referencesOneValueFrom()

// Check whether the given ValueId is contained in a VEGRef
NABoolean ItemExpr::containsTheGivenValue(const ValueId & vid) const
{
  // In really peculiar cases, a VEGRef might contain another VEGRef within
  // its VEG which recursively self-references the VEGRef. In order to prevent
  // running into an infinite loop there, we remember those VEG we've already
  // already seen by setting a flag in those VEG. If we run into that again,
  // there is no need to check the members of the VEG into it anymore since
  // those have already been or will be checked.
  //
  NABoolean retVal = FALSE;

  if (getValueId() == vid)
    return TRUE;

  switch (getOperatorType())
  {
    case ITM_VEG_PREDICATE:
    {
      VEG *veg = ((VEGPredicate *)this)->getVEG();
      if (veg->getVEGReference()->getValueId() == vid)
        return TRUE;
      else
      {
        // Already seen. Return FALSE. In VEGRef_x(VEG{VEGRef_x(..),y,z}),
        // the call to the inner VEGRef_x returns FALSE. However, if the
        // vid is VEGRef_x itself, when the function is called on the outer
        // VEGRef_x, it has return TRUE already. The previous "if" clause
        // ensures that. If vid is one of the other values in the VEG such
        // as y or z, ValueIdSet::containsTheGivenValue() is going to call
        // us again on other members of the VEG. We will return TRUE with
        // the matching member; and ValueIdSet::containsTheGivenValue()
        // is also going to return TRUE when we return TRUE on any one of
        // the members of the VEG.
        //
        if (veg->seenBefore())
          return FALSE;
        else
        {
          // Mark this VEG as already seen before going over its members,
          // so that if one of its members is a VEGRef to this VEG, we
          // don't have to traverse the VEG anymore.
          //
          veg->markAsSeenBefore();
          retVal = veg->getAllValues().containsTheGivenValue(vid);
          veg->markAsNotSeenBefore();
        }
      }
      break;
    }
    case ITM_VEG_REFERENCE:
    {
      VEG *veg = ((VEGReference *)this)->getVEG();

      // Already seen. Return FALSE. In VEGRef_x(VEG{VEGRef_x(..),y,z}),
      // the call to the inner VEGRef_x returns FALSE. However, if the
      // vid is VEGRef_x itself, when the function is called on the outer
      // VEGRef_x, it has return TRUE already. The previous "if" clause
      // ensures that. If vid is one of the other values in the VEG such
      // as y or z, ValueIdSet::containsTheGivenValue() is going to call
      // us again on other members of the VEG. We will return TRUE with
      // the matching member; and ValueIdSet::containsTheGivenValue()
      // is also going to return TRUE when we return TRUE on any one of
      // the members of the VEG.
      //
      if (veg->seenBefore())
      {
        return FALSE;
      }
      else
      {
        // Mark this VEG as already seen before going over its members,
        // so that if one of its members is a VEGRef to this VEG, we
        // don't have to traverse the VEG anymore.
        //
        veg->markAsSeenBefore();
        retVal = veg->getAllValues().containsTheGivenValue(vid);
        veg->markAsNotSeenBefore();
      }
      break;
    }
    case ITM_INSTANTIATE_NULL:
    {
      ValueId  nvid = getValueId();
      const ItemExpr * nie = nvid.getItemExpr();
      InstantiateNull *inst = (InstantiateNull *)nie->castToItemExpr();
      // Special code to handle instantiate nulls for subqueries.
      // If the instantiate null was introduced for a subquery, then the
      // "NoCheckForLeftToInnerJoin" flag was set to TRUE. If set, this
      // flag indicates that we don't need to check to see if we need to
      // transform the left join to an inner join, and thus possibly
      // remove the instantiate null, because the instantiate_null isn't
      // for a left join. If the flag is FALSE, however, it means the
      // instantiate null is for left join. In this case, we don't need
      // to execute this special code, so just break out now.
      if (NOT inst->NoCheckforLeftToInnerJoin)
      {
        break;
      }
      else
      {
        // Need to dig underneath the instantiate null to check if
        // the value we are looking for is the immediate child of
        // the instantiate null or contained in a veg reference
        // that is the child of the instantiate null.
        const ValueId & childVid = this->child(0)->getValueId();
        const ItemExpr * childExpr = childVid.getItemExpr();
        return childExpr->containsTheGivenValue(vid);

      }
    } // end case instantiate null
    default:
    {
      break;
    }
  } // switch

  return retVal;

} // ItemExpr::containsTheGivenValue()


// return the folded expression (if can be done). Return NULL otherwise
ItemExpr* ItemExpr::constFold() 
{
   ItemExpr* expr = NULL;

   try  {
      expr = copyTree(STMTHEAP);
   }

   catch (...) {
      return NULL;
   }

   expr->synthTypeAndValueId(TRUE, TRUE);

   expr = expr->simplifyBeforeConstFolding();
   //expr = simplifyBeforeConstFolding();

   if ( expr == NULL )
     expr = this;

   ValueIdList dummy; ValueId dummyId;
   ItemExpr* outExpr = NULL;
   Int32 error = dummy.evaluateExpr(dummyId, expr->getValueId(), -1,
                                    FALSE, //don't simplify expr
                                    TRUE,  // eval all consts
                                    &outExpr);

   if ( error == TRUE && outExpr ) 
       return outExpr;
   else 
       return NULL; 
}

ItemExpr* ItemExpr::simplifyBeforeConstFolding()
{
  Lng32 nc = getArity();

  if ( nc == 0 ) {
    return getConstantInVEG();
  }

  for (Int32 i = 0; i < nc; i++)
   {

      ValueId id = child(i)->getValueId();

      ItemExpr* cExpr = id.getItemExpr()->simplifyBeforeConstFolding();

      if ( cExpr )
        setChild(i, cExpr);
   }

   return this;
}

ItemExpr* ItemExpr::getConstantInVEG()
{
  switch (getOperatorType())
  {
     case ITM_VEG_REFERENCE:
      {
          const VEG * exprVEG = ((VEGReference*)this)->getVEG();
          const ValueIdSet & VEGGroup = exprVEG->getAllValues();

          ItemExpr *c = NULL;
          Lng32 cnt = 0;

          for (ValueId id = VEGGroup.init(); VEGGroup.next(id); VEGGroup.advance(id))
            {
              const ItemExpr * expr = id.getItemExpr();
              if (expr->getOperatorType() == ITM_CONSTANT)
                {
                  c = (ConstValue*)(id.getItemExpr());
                  cnt ++;
                }

            }
            return (cnt == 1) ? c : NULL;
       }

       default:
        break;
   }

   return NULL;
}

ItemExpr * ItemExpr::createMirrorPred(ItemExpr *compColPtr, 
                                      ItemExpr * compColExprPtr, 
                                      const ValueIdSet &underlyingCols)
{
   CMPASSERT(compColPtr->getOperatorType() == ITM_BASECOLUMN);
   BaseColumn *bcol = static_cast<BaseColumn *>(compColPtr);
   // use the basecolumn Veg, using the basecolumn by itself can cause issues
   // during codegen downstream
   ValueId egVid = bcol->getTableDesc()->getColumnVEGList()[bcol->getColNumber()];
   ItemExpr *compColVEGRefPtr = egVid.getItemExpr();

   switch (getOperatorType())
     {
     case ITM_VEG_PREDICATE:
       {
          ValueId refColId ;
          // XXX this should be a for loop to collect the each sub
          // expression containing each referenced column, mirror those
          // sub expressions and then final assembly of the complete
          // complete expression. The colde below works for simple expressions
          // like A=2 and B=4 when the computed col expr is POWER(A+B,2)
          // because of the veges formed.
          underlyingCols.getFirst(refColId); 
          const VEG * predVEG = ((VEGPredicate *) this)->getVEG();
          const ValueIdSet & VEGGroup = predVEG->getAllValues();
          if (VEGGroup.containsTheGivenValue(refColId) &&
              underlyingCols.entries() == 1)
            {
              ItemExpr * keyColExpr = predVEG->getVEGReference();
              ItemExpr * keyColRef = refColId.getItemExpr();

              ValueIdMap compExprRewriteMap;
              ValueId newCompExpr;
              compExprRewriteMap.addMapEntry(keyColExpr->getValueId(), keyColRef->getValueId());
              newCompExpr = compColExprPtr->mapAndRewrite(compExprRewriteMap);

              // Now try to const folding the newCompExpr by evaluating 
              // the expression. If successful, we use the computed result 
              // instead of newCompExpr. The simplification is necessary for 
              // the scan optimizer to figure out the actual number of rows 
              // returned per probe. 

              ItemExpr* foldedExpr = newCompExpr.getItemExpr()->constFold();

              ItemExpr * compPred = new(CmpCommon::statementHeap())
                                      BiRelat(ITM_EQUAL,
                                              compColVEGRefPtr,
                                              (foldedExpr==NULL) ? newCompExpr.getItemExpr() : foldedExpr);
              compPred->synthTypeAndValueId(TRUE);

              return compPred;
            }
          
          return NULL; 
          break;
       }
     case ITM_EQUAL:
     case ITM_LESS:
     case ITM_LESS_EQ:
     case ITM_LESS_OR_LE:
     case ITM_GREATER:
     case ITM_GREATER_EQ:
     case ITM_GREATER_OR_GE:
       {
          ItemExpr *keyColRef;
          ItemExpr *keyColExpr;
          ValueId refColId;
          // XXX figure out what it means when we have more than one
          // say CC expr is POWER(T.A+T.B,2)
          // If the keyPred is: T.A =2 AND T.B=4
          // we need to make sure we substitue both T.A and T.B in the power
          // expression above. 
          // The current code does the correct thing for simple veg expressions
          // with multiple cols even though it 
          // only process the first of the underlying cols, due to the veges 
          // formed. Should be a for loop instead
          // Also, at the moment have restricted the key predicate candidates
          // to mirror only to be equipreds when we have multiple columns 
          // referenced in the computedColumn expression.
          underlyingCols.getFirst(refColId); 
          NABoolean keyColOnLeft = TRUE;
          if (child(0)->referencesTheGivenValue(refColId) &&
              underlyingCols.entries() == 1)
            {
              keyColRef = child(0);
              keyColExpr = child(1);
            }
          else if (child(1)->referencesTheGivenValue(refColId) &&
                   underlyingCols.entries() == 1)
            {
              keyColRef = child(1);
              keyColExpr = child(0);
              keyColOnLeft = FALSE;
            }
          else
            { // XXX print warning for now.
#ifdef DEBUG
              fprintf(stderr, "ItemExpr::createMirrorPred(): Didn't find any references to valueId: %d\n", tempV);
#endif
              return NULL; 
            }
          // now we want to replace the reference to the key column in the compExpr with the keyColExpr

          ValueIdMap compExprRewriteMap;
          ValueId newCompExpr;
          compExprRewriteMap.addMapEntry(keyColExpr->getValueId(), keyColRef->getValueId());
          newCompExpr = compColExprPtr->mapAndRewrite(compExprRewriteMap);


          ItemExpr* foldedExpr = newCompExpr.getItemExpr()->constFold();
          ItemExpr* mirroredExpr = 
               (foldedExpr==NULL) ? newCompExpr.getItemExpr() : foldedExpr;

          ItemExpr * compPred;
          if (keyColOnLeft == TRUE)
              compPred = new(CmpCommon::statementHeap())
                BiRelat(((BiRelat *) this)->getRelaxedComparisonOpType(),
                                   compColVEGRefPtr,
                                   mirroredExpr //newCompExpr.getItemExpr()
                        );
          else
              compPred = new(CmpCommon::statementHeap())
                           BiRelat(((BiRelat *) this)->getRelaxedComparisonOpType(),
                                   mirroredExpr, //newCompExpr.getItemExpr(),
                                   compColVEGRefPtr);
          compPred->synthTypeAndValueId(TRUE);
          return compPred;
          break;
       }
     default:
       return NULL;
     }
   return NULL;
}

//Does 'this' ItemExpr evaluate to a constant?
//e.g.
//Sin(Cos(1)+1) will return TRUE.
//Sin(?p) will return FALSE.
NABoolean ItemExpr::doesExprEvaluateToConstant(NABoolean strict,
                                               NABoolean considerVEG) const
{

  NABoolean result = TRUE;
  Lng32 nc = getArity();

  //check if I am a leaf node
  if(!nc){
	//I am a leaf node
	//therefore check if I can be considered
	//a constant
	switch(getOperatorType()){

		case ITM_CONSTANT:
		case ITM_DEFAULT_SPECIFICATION:
		case ITM_PI:
		  //I am a strict constant, so return TRUE
		  return TRUE;

		case ITM_HOSTVAR:
                 {
                     HostVar* hv = (HostVar*)this;
                     if ( hv->isSystemGeneratedOutputHV() )
                        return TRUE;
                 }

		case ITM_DYN_PARAM:
		case ITM_CACHE_PARAM:
		case ITM_CURRENT_USER:
		case ITM_SESSION_USER:
		case ITM_CURRENT_TIMESTAMP:
		case ITM_UNIX_TIMESTAMP:
		case ITM_GET_TRIGGERS_STATUS:
		case ITM_UNIQUE_EXECUTE_ID:
		case ITM_CURR_TRANSID:
		  if(strict)
			//I am a non-strict constant, so return FALSE
			return FALSE;
		  //non-strict definition of constant
		  //therefore return TRUE
		  return TRUE;
    case ITM_VEG_REFERENCE:
      if(considerVEG)
      {
        const VEG * refVEG = ((VEGReference *)this)->getVEG();
        ValueId literal = NULL_VALUE_ID;

        if (strict)
        {
          literal = refVEG->getAConstant();
        }
        else{
          literal = refVEG->getAConstantHostVarOrParameter();
        }

        if (literal == NULL_VALUE_ID)
          return FALSE;

        return TRUE;
      }
      return FALSE;
		default:
		  return FALSE;
    }
  }

  //I am not a leaf node

  //check if I the random method
  //I will return different values
  //for the same parameter, so
  //I will never return a constant
  //value
  if(getOperatorType() == ITM_RANDOMNUM)
    return FALSE;

  // An aggrgate, sequence function  and instantiateNull itemExprs require state information (i.e. other rows)
  // to determine their value. Therefore they cannot be a constant. Also a rowset array scan 
  // denotes an array of values and is therefore not a constant.
  if(isAnAggregate()|| isASequenceFunction () ||
      (getOperatorType() == ITM_INSTANTIATE_NULL) || 
      (getOperatorType() == ITM_ROWSETARRAY_SCAN) ) 
  {
    return FALSE;
  }

  //I am not constant if anyone of my children
  //is not constant
  //check if all my children can be considered constants
  for (Lng32 i = 0; i < nc; i++)
  {
    result = child(i)->doesExprEvaluateToConstant(strict,considerVEG);

    //check if this child is not a constant
    if(!result){
	  //this child is not a constant, so return FALSE
      return result;
    }

  }

  //none of my children is a non-constant, so return TRUE
  return result;

}//ItemExpr::doesExprEvaluateToConstant()

NABoolean ItemExpr::referencesAHostVar() const
{
  NABoolean result = FALSE;
  Lng32 nc = getArity();

  //check if I am a leaf node
  if(!nc)
  {
    //I am a leaf node
    //therefore check if I can be considered
    //a constant
    switch(getOperatorType())
    {
      case ITM_HOSTVAR:
      case ITM_DYN_PARAM:
      case ITM_CURRENT_USER:
      case ITM_SESSION_USER:
      case ITM_CURRENT_TIMESTAMP:
      case ITM_UNIX_TIMESTAMP:
      case ITM_GET_TRIGGERS_STATUS:
      case ITM_UNIQUE_EXECUTE_ID:
      case ITM_CURR_TRANSID:
	return TRUE;

      case ITM_VEG_PREDICATE:
      {
        VEG * predVEG = ((VEGPredicate *)this)->getVEG();
        // Now, get all members of the VEG group, only if this VEG has not
        // been seen before. This is to avoid infinite looping for cases
        // where a VEG references itself
        if (predVEG->seenBefore())
          return FALSE;

        // get all members of the VEG
        const ValueIdSet & VEGGroup = predVEG->getAllValues();
        for (ValueId id = VEGGroup.init(); VEGGroup.next(id); VEGGroup.advance(id))
        {
          predVEG->markAsSeenBefore();
          NABoolean isAHostVar = id.getItemExpr()->referencesAHostVar();
          predVEG->markAsNotSeenBefore();

          if (isAHostVar)
            return TRUE;
        }
        return FALSE;
      } // end Case ITM_VEG_PREDICATE
    } // end switch
  } // end nc == 0

  for (Lng32 i = 0; i < nc; i++)
  {
    if(this->child(i)->referencesAHostVar())
      return TRUE;
  }
  return FALSE;
}

// This method returns TRUE or FALSE depending whether the optimizer
// should use stats to compute selectivity or use default selectivity
// Return TRUE if the expression is a VEG reference, base column,
// index column, column with CAST / UPPER / LOWER / UCASE / 
// LCASE / UPSHIFT / TRIM / SUBSTR (sometimes)
//
// Note that in the case of functions such as CAST and UPPER,
// the stats returned are those of the argument. For a right TRIM
// where we are trimming blanks, this is correct but for the 
// others the resulting stats will be incorrect in some way.
// For example, UPPER maps characters to upper case, so the UECs
// of the result should often be lower than the original, and
// certain intervals (namely those encompassing values that begin
// with a lower case letter) should be empty. For another
// example, CAST often is a 1-to-1 transformation so the UECs
// are right, but the order might change (e.g. when casting 
// numerics to characters; 99 < 100, but '99' > '100'). Even
// so, the statistics of the argument are still a better reflection
// of the result of the function than the default distribution,
// particularly from the standpoint of skew. So, we use them.
NABoolean ItemExpr::useStatsForPred()
{
  OperatorTypeEnum myType = getOperatorType();

  if (myType == ITM_VEG_REFERENCE OR
	  myType == ITM_BASECOLUMN OR
	  myType == ITM_VEG_PREDICATE OR
	  myType == ITM_INDEXCOLUMN OR
	  myType == ITM_VALUEIDUNION OR
	  myType == ITM_CAST OR
	  myType == ITM_INSTANTIATE_NULL OR
	  myType == ITM_UNPACKCOL OR
	  myType == ITM_UPPER OR
	  myType == ITM_LOWER OR
	  myType == ITM_TRIM OR
	  myType == ITM_CONVERT)

	return TRUE;
  else if (myType == ITM_SUBSTR)
    {
      // if the substring is known to be a prefix of the string,
      // then use the stats
      ItemExpr * startPosition = child(1);
      if (startPosition->getOperatorType() == ITM_CONSTANT)
        {
          NABoolean negate = FALSE;
          ConstValue * c = startPosition->castToConstValue(negate);
          if (c->canGetExactNumericValue() &&
               (c->getExactNumericValue() == 1))
            return TRUE;
        }
      return FALSE;  
    }
  else
	return FALSE;
}

void ItemExpr::getLeafValueIds(ValueIdSet &lv) const
{
  Int32 nc = getArity();

  // if this is a leaf node, add its value id
  // UDFunction uses the getArity() function to return the number
  // of inputs. It is really a leaf value...
  if (nc == 0 || getOperatorType() == ITM_USER_DEF_FUNCTION)
    {
      lv += getValueId();
    }
  else
    {
      // else add the leaf value ids of all the children
      for (Lng32 i = 0; i < (Lng32)nc; i++)
	{
	  child(i)->getLeafValueIds(lv);
	}
    }
}

void ItemExpr::getLeafValueIds(ValueIdList &lv) const
{
  Int32 nc = getArity();

  // if this is a leaf node, add its value id
  // UDFunction uses the getArity() function to return the number
  // of inputs. It is really a leaf value...
  if (nc == 0 || getOperatorType() == ITM_USER_DEF_FUNCTION)
    {
      lv.insert(getValueId());
    }
  else
    {
      // else add the leaf value ids of all the children
      for (Lng32 i = 0; i < (Lng32)nc; i++)
	{
	  child(i)->getLeafValueIds(lv);
	}
    }
}

void ItemExpr::getLeafValueIdsForCaseExpr(ValueIdSet &lv) 
{
  Int32 nc = getArity();

  // if this is a leaf node, add its value id
  if (nc == 0)
    {
	  if (doesExprEvaluateToConstant(FALSE))
		  lv += getValueId();
	  else
	  {
        ValueIdSet baseColSet;
	    findAll(ITM_BASECOLUMN, baseColSet, TRUE, TRUE);
        lv.addSet(baseColSet);
	  }
    }
  else
    {
      // elseadd the leaf value ids of all the children
		if (getOperatorType() == ITM_IF_THEN_ELSE)
		{
		  // for if_then_else statement ignore the first parameter which is the condition
		  child(1)->getLeafValueIdsForCaseExpr(lv);

		  // else part of Case can be a NULL pointer if it is created by Generator
		  if (child(2))
			child(2)->getLeafValueIdsForCaseExpr(lv);
		}
		else // for Case get the child, which would be IF_THEN_ELSE
		{
		  if (getOperatorType() == ITM_CASE)
			child(0)->getLeafValueIdsForCaseExpr(lv);
		  else // for all other expressions, collect the base columns
		  {
			ValueIdSet baseColSet;
			findAll(ITM_BASECOLUMN, baseColSet, TRUE, TRUE);
			lv.addSet(baseColSet);
		  }
		}
	}
}

// get leaf expression if the cardinality for this expression can be
// estimated using histograms
ItemExpr * ItemExpr::getLeafValueIfUseStats(NABoolean digIntoInstantiateNull)
{
  ItemExpr * expr = this;

  if (useStatsForPred())
  {
    if (digIntoInstantiateNull == FALSE && expr->getOperatorType() == ITM_INSTANTIATE_NULL)
      return expr;

    if(expr->getArity() > 0)
    {
      if (expr->getOperatorType() != ITM_TRIM)
            expr = expr->child(0)->getLeafValueIfUseStats(digIntoInstantiateNull);
      else
            expr = expr->child(1)->getLeafValueIfUseStats(digIntoInstantiateNull);
    }
  }

  return expr;
}
ItemExpr * ItemExpr::castToItemExpr()
{
  return this;
} // ItemExpr::castToItemExpr()

const ItemExpr * ItemExpr::castToItemExpr() const
{
  return this;
} // ItemExpr::castToItemExpr()

ConstValue * ItemExpr::castToConstValue(NABoolean & negate_it)
{
  negate_it = FALSE;
  return NULL;
}

SimpleHashValue ItemExpr::hash()
{
  // this method is just defined to have a hash method in ExprNode
  // without referencing class HashValue (which is too complicated
  // for the common code directory)
  return treeHash().getValue();
}

HashValue ItemExpr::topHash()
{

  HashValue result = 0;

  // hash on item properties???

  return result;
}

// this method is not virtual, since combining the hash values of the
// top node and its inputs should be independent of the actual node
HashValue ItemExpr::treeHash()
{
  HashValue result = topHash();
  Int32 maxc = getArity();

  for (Lng32 i = 0; i < (Lng32)maxc; i++)
    {
      // call this method recursively for the inputs
      result ^= child(i)->treeHash();
    }

  return result;
}

NABoolean ItemExpr::duplicateMatch(const ItemExpr & other) const
{
  // duplicateMatch works a little different in ItemExpr objects than it
  // does in RelExpr. In classes derived from RelExpr we strictly require
  // the duplicateMatch() method to be defined correctly. In classes
  // derived from ItemExpr this has not been done. Therefore, the
  // default method returns FALSE to be conservative (except
  // when the two expressions are the same).
  // The generic processing of duplicateMatch() for every derived class
  // is done in a separate method, genericDuplicateMatch().
  return (this == &other);
}

NABoolean ItemExpr::genericDuplicateMatch(const ItemExpr & other) const
{
  DCMPASSERT(other.castToItemExpr());

  if ((getValueId() == other.getValueId()) &&
      (getValueId() != NULL_VALUE_ID))
    return TRUE;
  if (getOperatorType() != other.getOperatorType())
    return FALSE;
  Int32 arity = getArity();
  if (arity != other.getArity())
    return FALSE;

  for (Lng32 i=0; i < (Lng32) arity; i++)
    {
      if (NOT (child(i)->duplicateMatch(*(other.child(i).getPtr()))))
	return FALSE;
    }
  return TRUE;
}

ItemExpr * ItemExpr::copyTopNode(ItemExpr *derivedNode,
				 CollHeap* )
{
  ItemExpr *result = NULL;

  if (derivedNode == NULL)
    {
      ABORT("encountered an instantiation of an ItemExpr object");
    }
  else
    result = derivedNode;

  // copy this's (the source's) original setting to result (the target)
  result->origOpType_ = origOpType_;

  result->selectivityFactor_ = selectivityFactor_;

  #ifndef NDEBUG
    CMPASSERT(!collateClause());	// else, Binder fell down on the job
  #endif				// (wrong overload of synthType() used)

  // copy/synthesize other item properties???

  return result;
}

// this method is not virtual, since combining the copies of the
// top node and its inputs should be independent of the actual node
ItemExpr * ItemExpr::copyTree(CollHeap* outHeap)
{
  ItemExpr * result = copyTopNode(NULL, outHeap);
  Int32 arity = getArity();

  for (Int32 i = 0; i < arity; i++) {
    if (child(i)) {
      result->child(i) = child(i)->copyTree(outHeap);
    }
  }

  return result;
}

NABoolean ItemExpr::containsSubquery()     // virtual method
{
  Int32 arity = getArity();

  for (Int32 i = 0; i < arity; i++)
    if (child(i) && child(i)->containsSubquery())
      return TRUE;

  return FALSE;
}

ItemExpr *ItemExpr::containsUDF()     // virtual method
{
  Int32 arity = getArity();

  for (Int32 i = 0; i < arity; i++)
    if (child(i) && child(i)->containsUDF())
      return child(i)->containsUDF();

  return 0;
}
NABoolean ItemExpr::containsIsolatedUDFunction()    // virtual method
{
  Int32 arity = getArity();

  for (Int32 i = 0; i < arity; i++)
    if (child(i) && child(i)->containsIsolatedUDFunction())
      return TRUE;

  return FALSE;
}

NABoolean ItemExpr::containsValueIdProxySibling(const ValueIdSet &siblings)
    // virtual method
{
  Int32 arity = getArity();

  for (Int32 i = 0; i < arity; i++)
    if (child(i) && child(i)->containsValueIdProxySibling(siblings))
      return TRUE;

  return FALSE;
} 

NABoolean ItemExpr::isASubquery() const   { return FALSE; }  // virtual method

NABoolean ItemExpr::isAnAggregate() const { return FALSE; }  // virtual method

NABoolean ItemExpr::isAPredicate() const  { return FALSE; }  // virtual method

NABoolean ItemExpr::isASequenceFunction() const { return FALSE; }   // virtual method

NABoolean ItemExpr::isOlapFunction() const { return FALSE; }   // virtual method


NABoolean ItemExpr::isAUserSuppliedInput() const { return FALSE; }  // virtual

ItemExpr * ItemExpr::transformMultiValuePredicate(	     // virtual method
					NABoolean /*flattenSubqueries*/,
					ChildCondition /*tfmIf*/)
{ return NULL; }

NABoolean ItemExpr::containsAnAggregate() const
{
  for (Int32 i=0; i<getArity(); i++)
  {
    if (child(i)->containsAnAggregate())
      return TRUE;
  }
  return FALSE;
}

// ----------------------------------------------------------------------
// Walk through an ItemExpr tree and gather the ValueIds of those
// expressions that behave as if they are "leaves" for the sake of
// the coverage test, e.g., expressions that have no children, or
// aggregate functions, or instantiate null. These are usually values
// that are produced in one "scope" and referenced above that "scope"
// in the dataflow tree for the query.
// ----------------------------------------------------------------------
void ItemExpr::getLeafValuesForCoverTest(ValueIdSet & leafValues, 
                                         const GroupAttributes& coveringGA,
                                         const ValueIdSet & newExternalInputs) const
{
  Lng32 nc = getArity();

  if ((nc == 0) 
    || coveringGA.isCharacteristicOutput(getValueId())
    || newExternalInputs.contains(getValueId()))
    {
      leafValues += getValueId();
    }
  else
    {
      for (Lng32 i = 0; i < nc; i++) {
	if (coveringGA.isCharacteristicOutput(child(i)->getValueId()) ||
	    newExternalInputs.contains(child(i)->getValueId()))
          leafValues += child(i)->getValueId();
        else
	  child(i)->getLeafValuesForCoverTest(leafValues, coveringGA, newExternalInputs);
      }
    }
} // ItemExpr::getLeafValuesForCoverTest()

// This is a recursive
// function that returns the leaf predicates of the tree
// whose root is the ItemExpr into the ValueIdSet&.
void ItemExpr::getLeafPredicates(ValueIdSet& leafPredicates)
{
  if (getOperatorType() != ITM_AND &&
      getOperatorType() != ITM_OR)
    leafPredicates.insert(getValueId());
  else {
    for (Lng32 i=0; i < (Lng32)getArity(); i++)
      child(i)->getLeafPredicates(leafPredicates);
  }
}// getLeafPredicates()

// -----------------------------------------------------------------------
// temp. method to collect basecolumns, used in FileScanRule
// -----------------------------------------------------------------------

template <class Result>
void ItemExpr::findAllT(OperatorTypeEnum wantedType,
		       Result& result,
		       NABoolean visitVEGMembers,
		       NABoolean visitIndexColDefs)
{
  OperatorTypeEnum myType = getOperatorType();

  if (myType == wantedType)
    result.addMember(this);

  // for VEGReferences and VEGPredicates (both having arity 0),
  // look at all the VEG members as well, if requested by the caller
  if (visitVEGMembers AND
      (myType == ITM_VEG_REFERENCE OR myType == ITM_VEG_PREDICATE))
    {
      VEG *veg;
      ValueId vegM;

      if (myType == ITM_VEG_REFERENCE)
	veg = ((VEGReference *) this)->getVEG();
      else
	veg = ((VEGPredicate *) this)->getVEG();

      if(! veg->seenBefore())
      {
	      veg->markAsSeenBefore();
	      for (ValueId x = veg->getAllValues().init();
			 veg->getAllValues().next(x);
			 veg->getAllValues().advance(x))

	      x.getItemExpr()->findAllT(wantedType,
			       result,
			       visitVEGMembers,
			       visitIndexColDefs);

	      veg->markAsNotSeenBefore();
      }
    }

  // for indexcolumns, look at the corresponding base column
  // or expression from the base table, if requested
  if (visitIndexColDefs AND myType == ITM_INDEXCOLUMN)
    {
      ((IndexColumn *) this)->getDefinition().getItemExpr()->
	findAllT(wantedType,
		result,
		visitVEGMembers,
		visitIndexColDefs);
    }

  // recurse
  Int32 nc = getArity();

  for (Lng32 i = 0; i < (Lng32)nc; i++)
    child(i)->findAllT(wantedType,
		      result,
		      visitVEGMembers,
		      visitIndexColDefs);

  if ( nc == 0 )
    switch ( myType )
      {
      case ITM_VALUEIDUNION:
	{
          // NB: ValueIdUnion objects can have more than 2 sources!
	  ValueIdUnion * tempUnion = (ValueIdUnion*) this;
          for (Lng32 i = 0; i < (Lng32)tempUnion->entries(); i++)
            {
              // guard against loops in the references
              // (can happen with common subexpressions, for example)
              if (!tempUnion->getSource(i).getItemExpr()->
                     referencesTheGivenValue(getValueId()))
                tempUnion->getSource(i).getItemExpr()->
                  findAllT(wantedType,
                           result,
                           visitVEGMembers,
                           visitIndexColDefs);
            }
	  break;
	}

      default:
	break;
      }

} // ItemExpr::findAllT, Template version

void ItemExpr::findAll(OperatorTypeEnum wantedType,
                       ValueIdSet & result,
                       NABoolean visitVEGMembers,
                       NABoolean visitIndexColDefs)
{
  findAllT(wantedType, result, visitVEGMembers, visitIndexColDefs);
}

void ItemExpr::findAll(OperatorTypeEnum wantedType,
		       ItemExprList& result,
		       NABoolean visitVEGMembers,
		       NABoolean visitIndexColDefs)
{
  // Collect all ItemExprs into a list.
  findAllT(wantedType, result, visitVEGMembers, visitIndexColDefs);
} // ItemExpr::findAll


Lng32 ItemExpr::getTreeSize(Lng32& maxDepth, NABoolean giveUpThreshold)
{
  Lng32 currentSize=1;
  Int32 nc = getArity();

  for (Lng32 i = 0; i < (Lng32)nc; i++)
  {
    Lng32 thisDepth = 0;
    currentSize += child(i)->getTreeSize(thisDepth, giveUpThreshold);

    if (giveUpThreshold > 0 && currentSize >= giveUpThreshold)
      break;

    if (thisDepth > maxDepth)
      maxDepth = thisDepth;
  }

  maxDepth++;
  return currentSize;
}

// Find all eqaulity columns in an item expression tree.
void ItemExpr::findEqualityCols(ValueIdSet& result)
{
  OperatorTypeEnum myType = getOperatorType();
  ValueId  myVid = getValueId();

  // If it is a base column or an index column, add to the list
  if (myType == ITM_BASECOLUMN || myType == ITM_INDEXCOLUMN)
    result += myVid;

  // If it belongs to VEG, add all the memebers of that VEG
  if (myType == ITM_VEG_REFERENCE || myType == ITM_VEG_PREDICATE)
  {
    VEG *veg;

    if (myType == ITM_VEG_REFERENCE)
      veg = ((VEGReference *) myVid.getItemExpr())->getVEG();
    else 
      // myType == ITM_VEG_PREDICATE
      veg = ((VEGPredicate *) myVid.getItemExpr())->getVEG();

    for (ValueId vid = veg->getAllValues().init();
         veg->getAllValues().next(vid);
         veg->getAllValues().advance(vid))
    {    
      result += vid; 
    }    
  }

  // recurse
  if (myType == ITM_EQUAL)
  {
    child(0)->findEqualityCols(result);
    child(1)->findEqualityCols(result);
  }
}

ItemExpr * ItemExpr::treeWalk(ItemTreeWalkFunc f,
                              CollHeap *outHeap,
                              enum ItemTreeWalkSeq sequence,
                              void *context)
{
  ItemExpr *transformedChildrenArr[4];
  ItemExpr **transformedChildren = transformedChildrenArr;
  Int32 arity = -1;
  NABoolean needToCopy = FALSE;
  ItemExpr *result = this;

  if (sequence == ITM_PREFIX_WALK)
    result = f(result, outHeap, context);

  arity = result->getArity();
  if (arity > 4)
    // allocated from stmt heap since it is used locally only
    // and is not deallocated below
    transformedChildren = new(CmpCommon::statementHeap()) ItemExpr *[getArity()];

  for (int i=0; i<arity; i++)
    {
      transformedChildren[i] =
        result->child(i)->treeWalk(f,
                                   outHeap,
                                   sequence,
                                   context);
      if (transformedChildren[i] != child(i))
        needToCopy = TRUE;
    }

  if (needToCopy)
    {
      // one of the children changed, since we can't
      // change an ItemExpr once we assigned a ValueId to
      // it, make a copy with new children
      result = result->copyTopNode(NULL, outHeap);
      for (int j=0; j<arity; j++)
        result->setChild(j, transformedChildren[j]);
    }

  if (sequence == ITM_POSTFIX_WALK)
    result = f(result, outHeap, context);
  
  return result;
}

ValueId ItemExpr::mapAndRewrite(ValueIdMap &map,
				NABoolean mapDownwards)
{
  ValueId result;

  // Look in the map for a match
  if (mapDownwards)
    map.mapValueIdDown(getValueId(),result);
  else
    map.mapValueIdUp(result,getValueId());

  // if this expression can be mapped directly, then return the
  // mapped value id
  if (result != getValueId())
    return result;

  return mapAndRewriteCommon(map, mapDownwards);
} // ItemExpr::mapAndRewrite

ValueId Aggregate::mapAndRewrite(ValueIdMap &map,
                                NABoolean mapDownwards)
{

  // Need to make sure we map and rewrite the distinctId as well.
  if (isDistinct())
    distinctId_ = distinctId_.getItemExpr()->mapAndRewrite(map, mapDownwards);

  return ItemExpr::mapAndRewrite(map, mapDownwards);
} // Aggregate::mapAndRewrite

ValueId ItemExpr::mapAndRewriteWithIndx(ValueIdMap &map,
					CollIndex ind)
{
  ValueId result;

  map.mapValueIdUpWithIndex(result,getValueId(), ind);

  // if this expression can be mapped directly, then return the
  // mapped value id
  if (result != getValueId())
    return result;

  return mapAndRewriteCommon(map, FALSE);
} // ItemExpr::mapAndRewriteWithIndex

// This method has the code that is common to
// mapAndRewrite() and mapAndRewriteWithIndex().
ValueId ItemExpr::mapAndRewriteCommon(ValueIdMap &map, NABoolean mapDownwards)
{
  ValueId result;

  ItemExpr *copyOfMe = NULL;
  Lng32 nc = getArity();

  // if the children of this expression changed after mapping, then
  // return the value id of a duplicate of myself with the new
  // children attached to it
  for (Lng32 i = 0; i < nc; i++)
    {
      ValueId c = child(i)->mapAndRewrite(map,mapDownwards);

      if (c != child(i)->getValueId())
	{
          // This child was mapped to a different value id
	  if (copyOfMe == NULL)
	    {
              // This was the first child to map to a different value
	      // make a copy of me and initialize its children with
	      // the same pointers that I have
	      copyOfMe = copyTopNode(NULL, CmpCommon::statementHeap());
              // copy the previous children into the new expression
	      for (Lng32 j = 0; j < nc; j++)
		copyOfMe->child(j) = child(j).getPtr();
	    }

	  copyOfMe->child(i) = c.getItemExpr();
	}
    }
  // If the expr had not child then copyOfMe is NULL

  if (copyOfMe)
    {
      // A new expression was created as the mapped value
      copyOfMe->synthTypeAndValueId();
      result = copyOfMe->getValueId();

      // Add to the map table the newly formed expression
      if (mapDownwards)
        map.addMapEntry(getValueId(),result);
      else
        map.addMapEntry(result,getValueId());
    }
  else
    // otherwise just return my value id
    result = getValueId();

  return result;
} // ItemExpr::mapAndRewriteCommon

ItemExpr * ItemExpr::foldConstants(ComDiagsArea *diagsArea,
				   NABoolean newTypeSynthesis)
{
  ItemExpr *result = this;
  Lng32 nc = getArity();

  // if the children of this expression changed after constant folding, then
  // return a duplicate of myself with the new children attached to it
  for (Lng32 i = 0; i < nc; i++)
    {
      ItemExpr *c = child(i)->foldConstants(diagsArea,newTypeSynthesis);

      if (c != child(i))
	{
          // This child was transformed into a different ItemExpr
	  if (result == this)
	    {
              // This was the first child to be transformed;
	      // make a copy of me and initialize its children with
	      // the same pointers that I have
	      result = copyTopNode(NULL, CmpCommon::statementHeap());
              // copy the previous children into the new expression
	      for (Lng32 j = 0; j < nc; j++)
		result->child(j) = child(j).getPtr();
	    }

	  result->child(i) = c;
	}
    }

  // make sure we return a tree with a correct type
  if (result != this)
    result->synthTypeAndValueId(newTypeSynthesis);

  return result;
}

ItemExpr * ItemExpr::applyInverseDistributivityLaw(
     OperatorTypeEnum backboneType,
     OperatorTypeEnum innerType)
{
  // operators other than OR will require some more code, see CMPASSERTs
  DCMPASSERT(backboneType == ITM_OR);

  // we must have a backbone of the backboneType for this to work
  if (getOperatorType() != backboneType)
    return this;

  // a default can switch this code off if required (should be needed
  // only if bugs are found in the code)
  if (CmpCommon::getDefault(FIND_COMMON_SUBEXPRS_IN_OR) != DF_ON)
    return this;

  ItemExpr *result = NULL;
  // NOTE: we'll use the words "disjuncts" and "conjuncts" that make
  // sense with the default operator types, but may not be a great choice
  // if the caller uses different types (sorry, but this might help
  // understand the code better)
  ValueIdSet disjuncts;
  ValueIdSet commonSubexprs;
  CollIndex numCommonSubexprs;
  ValueId c;

  // get a ValueIdSet with all the "disjuncts".
  convertToValueIdSet(disjuncts,NULL,backboneType,FALSE);

  // prime the common subexpressions with all of the conjuncts
  // of the first disjunct
  disjuncts.getFirst(c);
  c.getItemExpr()->convertToValueIdSet(commonSubexprs,NULL,innerType,FALSE);
  disjuncts.advance(c);

  // in a first loop, find the common subexpressions among all of the disjuncts
  for (/* c already initialized */; disjuncts.next(c); disjuncts.advance(c))
    {
      ValueIdSet conjuncts;

      c.getItemExpr()->convertToValueIdSet(conjuncts,NULL,innerType,FALSE);

      // find common subexpressions between the
      // previous and the current disjunct
      commonSubexprs.findCommonSubexpressions(conjuncts);

      // stop if we have no common subexpressions
      if (commonSubexprs.isEmpty())
	break;
    }

  numCommonSubexprs = commonSubexprs.entries();

  if (numCommonSubexprs > 0)
    {
      // Now that we know the real common subexpressions do the same loop
      // again, but this time modify the conjuncts by removing the
      // common parts from them, forming new conjuncts, and connecting
      // them to form a new backbone of disjuncts.

      for (ValueId c2 = disjuncts.init();
	   disjuncts.next(c2);
	   disjuncts.advance(c2))
	{
	  ValueIdSet conjuncts;

	  // one child of the backbone, eliminate common subexpressions
	  // from it
	  c2.getItemExpr()->convertToValueIdSet(conjuncts,
						NULL,
						innerType,
						FALSE);
	  commonSubexprs.findCommonSubexpressions(conjuncts, TRUE);

	  // make sure the common subexpressions haven't changed
	  CMPASSERT(numCommonSubexprs == commonSubexprs.entries());

	  // are there any non-common conjuncts left?
	  if (conjuncts.entries() == 0)
	    {
	      // No, one of the disjuncts consists of only the common
	      // subexpressions. This requires logic specific to the
	      // operator type. For example, (a=10 and b=11) or (a=10)
	      // is (a=10) and (b=11 or TRUE) which is (a=10).
	      CMPASSERT(backboneType == ITM_OR);
	      result = NULL;
	      // leave the inner loop with a NULL result, meaning
	      // that only the common subexpressions should survive
	      break;
	    }

	  // rebuild the ItemExpr tree for the conjuncts
	  ValueIdList conjunctList(conjuncts);
	  ItemExpr *newConjuncts = conjunctList.rebuildExprTree(innerType);

	  // rebuild the backbone
	  if (result == NULL)
	    result = newConjuncts;
	  else
	    result = connect2(backboneType,result,newConjuncts);
	}

      // create a tree with the common subexpressions
      ValueIdList commonSubexprsList(commonSubexprs);
      ItemExpr *commonSubexprsAsItem =
	commonSubexprsList.rebuildExprTree(innerType);

      // hook up common part and the non-common expressions (if any)
      if (result)
	result = connect2(innerType,commonSubexprsAsItem,result);
      else
	result = commonSubexprsAsItem;

      result->synthTypeAndValueId();
    }
  else
    {
      // sorry, no common subexpressions found, return original expression
      result = this;
    }

  return result;
}

// little helper for the above method
ItemExpr * ItemExpr::connect2(OperatorTypeEnum op,
			      ItemExpr *op1,
			      ItemExpr *op2)
{
  switch (op)
    {
    case ITM_AND:
    case ITM_OR:
      return new(CmpCommon::statementHeap()) BiLogic(op, op1, op2);
    default:
      CMPASSERT("Operator type not supported by connect2" == 0);
      return NULL;
    }
}

// -----------------------------------------------------------------------
// ItemExpr::synthTypeAndValueId()
// -----------------------------------------------------------------------

void ItemExpr::synthTypeAndValueId(NABoolean redriveTypeSynthesisFlag, NABoolean redriveChildTypeSynthesis)
{
  // If the redriveTypeSynthesisFlag is set, it synthesises iself.
  // If the redriveChildTypeSynthesis is set, it synthesizes the
  // types for the entire subtree, from the leaves upto this operator,
  // once again.

  if (nodeIsBound() AND NOT redriveTypeSynthesisFlag) return;

  Int32 nc = getArity();

  // do it recursively on the children
  for (Lng32 i = 0; i < (Lng32)nc; i++)
    {
      if (child(i))
	{
	  // If it is an Item Expressions
	  child(i)->synthTypeAndValueId(redriveChildTypeSynthesis, redriveChildTypeSynthesis);
	  // refer to the child by its valueid instead of its pointer
	  child(i) = child(i)->getValueId();
	}
      // else leave the RelExpr alone
    }

  // Now do the non-recursive part
  synthTypeAndValueId2( redriveTypeSynthesisFlag, redriveChildTypeSynthesis );
  
} // ItemExpr::synthTypeAndValueId()

//
// ItemExpr::synthTypeAndValueId2() - a helper routine for synthTypeAndValueId()
// NOTE: The code for this routine came from the previous version of
//       ItemExpr::synthTypeAndValueId().  It was pulled out as a separate
//       routine so that the C++ compiler would generate code for
//       ItemExpr::synthTypeAndValueId() that used significantly less stack space.
//
void ItemExpr::synthTypeAndValueId2(NABoolean redriveTypeSynthesisFlag, NABoolean redriveChildTypeSynthesis)
{
  Int32 nc = getArity();
  ValueDesc *vdesc;
  DomainDesc *ddesc;

  // make sure the expression has a value id
  if (valId_ == NULL_VALUE_ID)
    {
      vdesc = new (CmpCommon::statementHeap()) ValueDesc(this);
      // remember the value id and the type in the node
      setValueId(vdesc->getValueId());
    }
  else
    {
      vdesc = valId_.getValueDesc();
    }

  // if the type hasn't been set or if type synthesis is to be
  // redriven, set the type to the synthesized value
  ddesc = vdesc->getDomainDesc();

  if (ddesc == NULL OR (nc > 0 AND redriveTypeSynthesisFlag))
    {
      const NAType *t = synthesizeType();
      // changed from CMPASSERT to CMPABORT, because it could be null
      // for several reasons. In most cases it is because of User error
      // where, the diagnostics would be filled with the error number.
      // In such cases it is wrong to raise an unnecessary alarm. If the
      // diagnostics buffer is not filled, then raise an exception
      if (!t)
	CMPABORT;

      // Fix for "BR0094.txt", here and in Case::bindNode().
      // Special handling is required for CASE because its operand
      // is not one of its children (because the operand can be a subquery,
      // which the normalizer needs to move).  And when that operand IS a subq,
      // then the CASE can return NULL if the subq produces zero rows.
      if (getOperatorType() == ITM_CASE &&
          ((Case *)this)->caseOperandWasNullable())
	t = t->synthesizeNullableType(CmpCommon::statementHeap());

      if (ddesc == NULL)
	{
	  ddesc = new (CmpCommon::statementHeap())
	    DomainDesc(ActiveSchemaDB(), *t);
	  vdesc->setDomainDesc(ddesc);
	}
      else
	{
	  getValueId().changeType(t);
	}
    }

  // mark me as bound
  markAsBound();
} // ItemExpr::synthTypeAndValueId2()

// -----------------------------------------------------------------------
// ItemExpr::isCovered()
// -----------------------------------------------------------------------
NABoolean ItemExpr::isCovered
                      (const ValueIdSet& newExternalInputs,
		       const GroupAttributes& coveringGA,
		       ValueIdSet& referencedInputs,
		       ValueIdSet& coveredSubExpr,
		       ValueIdSet& unCoveredExpr) const
{

  NABoolean exprIsCovered;

  switch (getArity())
    {
    case 0:

      exprIsCovered = FALSE;
      break;

    default:
      {
        exprIsCovered = TRUE;
	NABoolean coverFlag;
	Lng32 index, nc = getArity();

	for (index = 0; index < nc; index++)
	  {
	    coverFlag = coveringGA.covers(child(index)->getValueId(),
					  newExternalInputs,
					  referencedInputs,
					  &coveredSubExpr,
					  &unCoveredExpr);
	    if (coverFlag)
	      coveredSubExpr += ((ItemExpr *)child(index))->getValueId();
	    exprIsCovered &= coverFlag;
	  } // for i'th child of expr

	break;

      } // default

    } // switch(getArity())

  return exprIsCovered;

} // ItemExpr::isCovered()

OrderComparison ItemExpr::sameOrder(ItemExpr *other,
				    NABoolean askOther)
{
  // first, check whether the item expressions are identical
  if (this == other)
    return SAME_ORDER;

  // second, try to simplify both item expressions
  OrderComparison order1;
  OrderComparison order2;
  OrderComparison result;
  Int32 inversions = 0;

  ItemExpr *simpThis = simplifyOrderExpr(&order1);
  ItemExpr *simpOther = other->simplifyOrderExpr(&order2);

  // check whether the expressions actually got simplified, return
  // DIFFERENT order if that was not the case
  if (this == simpThis AND other == simpOther)
    return DIFFERENT_ORDER;

  // Recursively call sameOrder with the simplified expressions
  // If it is a VEG reference, need to do a cast of "simpOther" to type
  // VEGReference so that the implementation of sameOrder that accepts
  // a VEGReference "other" parameter will be called.
  if (simpOther->getOperatorType() == ITM_VEG_REFERENCE)
    result = simpThis->sameOrder((VEGReference *)simpOther,askOther);
  else
    result = simpThis->sameOrder(simpOther,askOther);

  if (result != DIFFERENT_ORDER)
    {
      // if the order is not different, add up all the inversions
      // we encountered, either from simplifying expressions or
      // by comparing them
      if (order1 == INVERSE_ORDER)
	inversions++;
      if (order2 == INVERSE_ORDER)
	inversions++;
      if (result == INVERSE_ORDER)
	inversions++;

      // if we inverted an even number of times then the two expressions
      // have the same order
      if (inversions == 0 OR inversions == 2)
	result = SAME_ORDER;
      else
	result = INVERSE_ORDER;
    }

  return result;
}

OrderComparison ItemExpr::sameOrder(VEGReference *other,
				    NABoolean askOther)
{
  // First, check whether the "this" item expression is identical
  // to the "other" VegReference
  if (this == other)
    return SAME_ORDER;

  // Second, go through the "other" VegReference members one at a
  // time, and call sameOrder recursively to see if one of the member
  // ItemExpr's is identical to "this".
  const ValueIdSet &equivValues = other->getVEG()->getAllValues();
  OrderComparison result = DIFFERENT_ORDER;

  for (ValueId x = equivValues.init();
       equivValues.next(x) AND result == DIFFERENT_ORDER;
       equivValues.advance(x))
    {
      result = sameOrder(x.getItemExpr(),askOther);
    }

  return result;
}


ItemExpr * ItemExpr::simplifyOrderExpr(OrderComparison *newOrder)
{
  // The default implementation assumes that it is not possible
  // to simplify an expression.
  if (newOrder)
    *newOrder = SAME_ORDER;
  return this;
}

ItemExpr * ItemExpr::removeInverseOrder()
{
  // The default implementation just returns a pointer to itself,
  // since obviously there is no inverse order operator to remove.
  return this;
}

OperatorTypeEnum ItemExpr::getInverseOpType() const
{
  switch (getOperatorType())
    {
    case ITM_EQUAL:
      return ITM_NOT_EQUAL;
    case ITM_NOT_EQUAL:
      return ITM_EQUAL;
    case ITM_LESS:
      return ITM_GREATER;
    case ITM_LESS_EQ:
      return ITM_GREATER_EQ;
    case ITM_GREATER:
      return ITM_LESS;
    case ITM_GREATER_EQ:
      return ITM_LESS_EQ;
    case ITM_IS_TRUE:
      return ITM_IS_FALSE;
    case ITM_IS_FALSE:
      return ITM_IS_TRUE;
    case ITM_IS_NULL:
      return ITM_IS_NOT_NULL;
    case ITM_IS_NOT_NULL:
      return ITM_IS_NULL;
    case ITM_IS_UNKNOWN:
      return ITM_IS_NOT_UNKNOWN;
    case ITM_IS_NOT_UNKNOWN:
      return ITM_IS_UNKNOWN;

    case ITM_RETURN_FALSE:
      return ITM_RETURN_TRUE;
    case ITM_RETURN_TRUE:
      return ITM_RETURN_FALSE;

    default:
      return (getOperatorType());
    }
}

NABoolean ItemExpr::isAColumnReference( )
  { return FALSE; }

// return true iff maxSelectivity(this) == selectivity(this)
NABoolean ItemExpr::maxSelectivitySameAsSelectivity() const
{ 
  switch (getOperatorType())
    {
    case ITM_EQUAL:
    case ITM_LESS:
    case ITM_LESS_EQ:
    case ITM_GREATER:
    case ITM_GREATER_EQ:
      if (getArity() > 1)
        {
          // maxSelectivity(any op constant) == selectivity(any op constant) 
          // maxSelectivity(constant op any) == selectivity(constant op any) 
          // when op is oneof: =, <, <=, >, >=
          NABoolean negate;
          ItemExpr * rhs = child(1);
          ItemExpr * lhs = child(0);
          if (rhs->getOperatorType() == ITM_CACHE_PARAM) 
             rhs = ((ConstantParameter *)rhs)->getConstVal();
          else
            rhs = rhs->castToConstValue( negate );

          if (lhs->getOperatorType() == ITM_CACHE_PARAM) 
             lhs = ((ConstantParameter *)lhs)->getConstVal();
          else
            lhs = lhs->castToConstValue( negate );
          return ((lhs != NULL) || (rhs != NULL));
        }
      break;
      // maxSelectivity(any <> constant) is 1.0
    case ITM_IS_NULL:
    case ITM_IS_UNKNOWN:
    case ITM_IS_NOT_NULL:
    case ITM_IS_NOT_UNKNOWN:
      // maxSelectivity(any is null)     == selectivity(any is null)
      // maxSelectivity(any is not null) == selectivity(any is not null)
      return TRUE;
    default:
      return FALSE;
    }
  return FALSE; 
}
void ItemExpr::print(FILE * f,
		     const char * prefix,
		     const char * suffix) const
{
#ifndef NDEBUG
  ExprNode::print(f,prefix,suffix);

#ifndef NDEBUG
  fprintf(f,"%sItem Expression (Value Id %d): ",prefix, (CollIndex) valId_);

  if ( valId_ != NULL_VALUE_ID && &(valId_.getType()) != NULL )
    fprintf( f, "%s", valId_.getType().getTypeSQLname().data() );

  fprintf( f, "\n" );
#else
  fprintf(f,"%sItem Expression (Value Id %d):\n",prefix, (CollIndex) valId_);
#endif

  // print children
  Int32 nc = getArity();
  for (Lng32 i = 0; i < (Lng32)nc; i++)
    {
      fprintf(f,"%sExpression input %d:\n",prefix,i);
      if (child(i).getPtr())
	child(i)->print(f,CONCAT(prefix,"    "));
      else
	fprintf(f,"%snonexistent child\n",prefix);
    }
#endif
}

void ItemExpr::display()
{
  NAString result;
  unparse(result, PARSER_PHASE, USER_FORMAT_DELUXE);
  fprintf(stdout, "%s\n", result.data());
}


//
// computeKwdAndFlags() - a helper routine for ItemExpr::unparse()
//
// NOTE: The code in this routine came from the previous version of
//       ItemExpr::unparse().   It has been pulled out into
//       a separate routine so that the C++ compiler will produce
//       code that needs signficantly less stack space for the
//       recursive ItemExpr::unparse() routine.
//
void ItemExpr::computeKwdAndFlags( NAString &kwd,
		                   NABoolean &prefixFns,
		                   NABoolean &specialPrefixFns,
		                   PhaseEnum phase,
		                   UnparseFormatEnum form,
		                   TableDesc * tabId ) const
{
  OperatorTypeEnum operatorType = getOperatorType();

  if ( operatorType == ITM_BASECOLUMN)
  {
    if (form == QUERY_FORMAT)
    {
      if (CmpCommon::getDefault(MVQR_LOG_QUERY_DESCRIPTORS) != DF_DUMP_MV)
        kwd = ((BaseColumn *)this)->getTextForQuery();
      else
        kwd = getText();
    }
    else if ((form == COMPUTED_COLUMN_FORMAT) ||
	     (form == HIVE_MD_FORMAT))
      kwd = ToAnsiIdentifier(((BaseColumn *)this)->getColName());
    else
      kwd = getText();
  }
  else if ( operatorType == ITM_RENAME_COL)
  {
    if (form == HIVE_MD_FORMAT)
      kwd = ((RenameCol *)this)->getNewColRefName()->getColName();
    else
      kwd = getText();
  }
  else if (operatorType == ITM_NAMED_TYPE_TO_ITEM)
  {
    kwd = ToAnsiIdentifier(((NamedTypeToItem *)this)->getText());
  }
  else if (( operatorType == ITM_CACHE_PARAM) &&
           (form == QUERY_FORMAT) )
    ((ConstantParameter *)this)->getConstVal()->unparse(kwd, phase, QUERY_FORMAT, tabId);
  else
    kwd = getText();

  if (form == USER_FORMAT_DELUXE)
    // Do not upcase if string literal or delimited ident.
    if (!strchr(kwd, '\"') && !strchr(kwd, '\'')) //"
    {
      TrimNAStringSpace(kwd);
      kwd.toUpper();
    }

  switch (operatorType)
  {
    case ITM_BITAND:
    case ITM_CAST:
    case ITM_CHAR_LENGTH:
    case ITM_EXTRACT:
    case ITM_LEFT:
    case ITM_MOD:    
    case ITM_MOVING_SDEV:
    case ITM_MOVING_VARIANCE:
    case ITM_OFFSET:
    case ITM_POSITION:
    case ITM_POWER:
    case ITM_STDDEV:
    case ITM_SUBSTR:
    case ITM_VARIANCE:
      prefixFns = TRUE;
      break;

    case ITM_DATEDIFF_YEAR:
    case ITM_DATEDIFF_QUARTER:
    case ITM_DATEDIFF_MONTH:
    case ITM_DATEDIFF_WEEK:
    case ITM_YEARWEEK:
    case ITM_YEARWEEKD:
      specialPrefixFns = TRUE;
      break;

    case ITM_PLUS:
    case ITM_MINUS:
      if (((BiArith *) this)->isDateMathFunction() &&
          (form == QUERY_FORMAT ||
           form == COMPUTED_COLUMN_FORMAT))
        {
          // this is not a regular addition or subtractions, it's
          // a datetime function with special handling of the last
          // day of the month
          specialPrefixFns = TRUE;
        }
  }
}
//
// computeKwdAndPostfix() - a helper routine for ItemExpr::unparse()
//
// NOTE: Either computes or augments kwd, depending on the item expr involved.
//
// NOTE: The code in this routine came from the previous version of
//       ItemExpr::unparse().   It has been pulled out into
//       a separate routine so that the C++ compiler will produce
//       code that needs signficantly less stack space for the
//       recursive ItemExpr::unparse() routine.
//
void ItemExpr::computeKwdAndPostfix( NAString &kwd,
                                     NAString &postfix,
                                     UnparseFormatEnum form ) const
{
        // print function syntax of the form <kwd> <children> <postfix>
        //     <fname>(<prefix-args,> <children> <,postfix-args>)
        //     <--------kwd--------->            <----postfix--->

        // handle special prefix argument cases by adding to 'kwd' and 'postfix'

        OperatorTypeEnum operatorType = getOperatorType();
        switch (operatorType)
          {
          case ITM_CAST:
            {
              if (form == QUERY_FORMAT || form == COMPUTED_COLUMN_FORMAT)
                {
                  kwd += "(";
                  postfix = " AS ";

                  // Get the Data type after the Cast
                  const NAType *naType = ((Cast *) this)->getType();

                  // ignore NULLs description in getTypeSQLName, since it
                  // does not return valid SQL syntax
                  postfix += naType->getTypeSQLname(TRUE);
                  if (!naType->supportsSQLnull())
                    postfix += " NOT NULL";
                  postfix += ")";
                }
              else
                kwd += "(";
            }
            break;

          case ITM_EXTRACT:
          case ITM_EXTRACT_ODBC:
            switch(((Extract*) this)->getExtractField())
              {
              case REC_DATE_YEAR:
                kwd = "YEAR(";
                break;
              case REC_DATE_MONTH:
                kwd = "MONTH(";
                break;
              case REC_DATE_DAY:
                kwd = "DAY(";
                break;
              case REC_DATE_HOUR:
                kwd = "HOUR(";
                break;
              case REC_DATE_MINUTE:
                kwd = "MINUTE(";
                break;
              case REC_DATE_SECOND:
                kwd = "SECOND(";
                break;
              case REC_DATE_YEARQUARTER_EXTRACT:
                kwd = "DATE_PART('YEARQUARTER',";
                break;
              case REC_DATE_YEARMONTH_EXTRACT:
                kwd = "DATE_PART('YEARMONTH',";
                break;
              case REC_DATE_YEARQUARTER_D_EXTRACT:
                kwd = "DATE_PART('YEARQUARTERD',";
                break;
              case REC_DATE_YEARMONTH_D_EXTRACT:
                kwd = "DATE_PART('YEARMONTHD',";
                break;
                // YEARWEEK gets transformed into ITM_YEARWEEK, see below
              default:
                kwd += "(";
                break;
              }
            break;

          case ITM_DATE_TRUNC_YEAR:
            kwd = "DATE_TRUNC('YEAR',";
            break;
          case ITM_DATE_TRUNC_MONTH:
            kwd = "DATE_TRUNC('MONTH',";
            break;
          case ITM_DATE_TRUNC_DAY:
            kwd = "DATE_TRUNC('DAY',";
            break;
          case ITM_DATE_TRUNC_HOUR:
            kwd = "DATE_TRUNC('HOUR',";
            break;
          case ITM_DATE_TRUNC_MINUTE:
            kwd = "DATE_TRUNC('MINUTE',";
            break;
          case ITM_DATE_TRUNC_SECOND:
            kwd = "DATE_TRUNC('SECOND',";
            break;
          case ITM_DATE_TRUNC_CENTURY:
            kwd = "DATE_TRUNC('CENTURY',";
            break;
          case ITM_DATE_TRUNC_DECADE:
            kwd = "DATE_TRUNC('DECADE',";
            break;
          case ITM_DATEDIFF_YEAR:
            kwd = "DATEDIFF(YEAR,";
            break;
          case ITM_DATEDIFF_QUARTER:
            kwd = "DATEDIFF(QUARTER,";
            break;
          case ITM_DATEDIFF_MONTH:
            kwd = "DATEDIFF(MONTH,";
            break;
          case ITM_DATEDIFF_WEEK:
            kwd = "DATEDIFF(WEEK,";
            break;
          case ITM_YEARWEEK:
            kwd = "DATE_PART('YEARWEEK',";
            break;
          case ITM_YEARWEEKD:
            kwd = "DATE_PART('YEARWEEKD',";
            break;

          case ITM_PLUS:
          case ITM_MINUS:
            // we come here for special datetime functions that
            // get represented by a + or - operator with
            // isStandardNormalization() set
            if (((BiArith *) this)->isStandardNormalization())
              {
                // Here are the original expressions and their transformations,
                // (+) and (-) indicate the +/- operators with the standard
                // normalization flag set:
                //
                // ADD_MONTHS(<datetime_expr>, <num_expr> [, 0])  ==>
                //                <datetime_expr> (+) CAST(<num_expr> AS INTERVAL MONTHS)
                // DATE_ADD(<datetime_expr>, <interval_expr>)  ==>
                //                <datetime_expr> (+) <interval_expr>
                // DATE_SUB(<datetime_expr>, <interval_expr>)  ==>
                //                <datetime_expr> (-) <interval_expr>
                // DATEADD(<keyword>, <num_expr>, <datetime_expr>)  ==>
                //                <datetime_expr> (+) CAST(<num_expr> AS ...)
                // TIMESTAMPADD(<keyword>, <num_expr>, <datetime_expr>)  ==>
                //                <datetime_expr> (+) CAST(<num_expr> AS ...)
                //
                // We unparse all those as the equivalent DATE_ADD and DATE_SUB
                // functions:
                if (operatorType == ITM_PLUS)
                  kwd = "DATE_ADD(";
                else
                  kwd = "DATE_SUB(";
              }
            else if (((BiArith *) this)->isKeepLastDay() && operatorType == ITM_PLUS)
              {
                // Here are the original expressions and their transformations,
                // (+) and (-) indicate the +/- operators with the "keep last day"
                // normalization flag set:
                //
                // ADD_MONTHS(<datetime_expr>, <num_expr>, 1)  ==>
                //                <datetime_expr> (+) CAST(<num_expr> AS INTERVAL MONTHS)
                CMPASSERT(child(1)->getValueId().getType().getTypeQualifier() == NA_INTERVAL_TYPE &&
                          child(1)->getValueId().getType().getFSDatatype() == REC_INT_MONTH);
                kwd = "ADD_MONTHS(";
                postfix = ", 1" + postfix;
              }
            else
              DCMPASSERT(FALSE); // the above should have covered all datetime math expressions
            break;

          default:
            kwd += "(";
            break;
          }
}

void ItemExpr::unparse(NAString &result,
		       PhaseEnum phase,
		       UnparseFormatEnum form,
		       TableDesc * tabId) const
{
  // Avoid creating large strings which will only be truncated later
  // by EXPLAIN.
  if (form == EXPLAIN_FORMAT && (result.length() > 4096)) 
  {
    return;
  }

  // Allocate 3 procedure local variables and initialize them here.
  // They may get changed by the call to ItemExpr::computeKwdAndFlags() 
  // which follows, but we initialize them here so source analysis
  // tools won't complain about unitialized variables.
  //
  NAString  kwd(CmpCommon::statementHeap());
  NABoolean prefixFns = FALSE;          // prefix function, some with infix, arity 2
  NABoolean specialPrefixFns = FALSE;   // require special prefix argument, arity 1 or 2

  computeKwdAndFlags( kwd, prefixFns, specialPrefixFns, phase, form, tabId );

  OperatorTypeEnum operatorType = getOperatorType();

  Int32 arity = getArity();

  if (operatorType != origOpType() &&
      form == QUERY_FORMAT ||
      form == COMPUTED_COLUMN_FORMAT)
    {
      // handle some cases where the original function was rewritten
      // in the binder, using a ZZZBinderFunction
      switch (origOpType())
        {
        case ITM_DATE_TRUNC_MINUTE:
        case ITM_DATE_TRUNC_SECOND:
        case ITM_DATE_TRUNC_MONTH:
        case ITM_DATE_TRUNC_HOUR:
        case ITM_DATE_TRUNC_CENTURY:
        case ITM_DATE_TRUNC_DECADE:
        case ITM_DATE_TRUNC_YEAR:
        case ITM_DATE_TRUNC_DAY:
        case ITM_DATEDIFF_YEAR:
        case ITM_DATEDIFF_QUARTER:
        case ITM_DATEDIFF_MONTH:
        case ITM_DATEDIFF_WEEK:
        case ITM_YEARWEEK:
        case ITM_YEARWEEKD:
          {
            ItemExpr *unboundExpr =
              ZZZBinderFunction::tryToUndoBindTransformation((ItemExpr *) this);
            if (unboundExpr)
              {
                // we were able to undo this transformation, unparse
                // the ZZZBinderFunction instead
                unboundExpr->unparse(result,
                                     phase,
                                     form,
                                     tabId);
                return;
              }
          }
          break;
          
        default:
          break;
        }
    }

  switch (arity)
  {
    case 0:
      // simply print the text out for a leaf operator
      result += kwd;
      break;

    case 2:
      if (form != FILE_FORMAT && !specialPrefixFns)
      {
        if( ((form == MV_SHOWDDL_FORMAT) || 
             (form == QUERY_FORMAT) ||
             (form == COMPUTED_COLUMN_FORMAT)) && 
             prefixFns )
        {
          result += kwd;
          result += "(";

          if (child(0))
            child(0)->unparse(result, phase,form, tabId);
          else
            result += "NULL";

          if (operatorType == ITM_POSITION)
            result += " IN ";
          else
            result += ", ";

          if (child(1))
            child(1)->unparse(result, phase, form, tabId);
          else
            result += "NULL";
          result += ")";
          break;
        } // STDDEV, MOD, VARIANCE
        else  
          if ( (operatorType == ITM_TRIM)  && 
               ((form == QUERY_FORMAT) ||
                (form == COMPUTED_COLUMN_FORMAT)))
        {
          result += kwd;
          result += "(";
          child(1)->unparse(result,phase,form,tabId);
          result += ")";
        } 
        else 
          if((operatorType == ITM_ITEM_LIST ||
          operatorType == ITM_AND) &&
          (form != MV_SHOWDDL_FORMAT) &&
          (form != QUERY_FORMAT) )
          {
            if (child(0))
              child(0)->unparse(result,phase,form, tabId);
            else
              result += "NULL";

            if (operatorType != ITM_ITEM_LIST)
              result += " ";
            result += kwd;
            result += " ";

            if (child(1))
              child(1)->unparse(result,phase,form, tabId);
            else
              result += "NULL";
          }
          else
          {
            // assume this is an infix operator (<child0>) op (<child1>)

            result += "(";

            NABoolean list0 = FALSE, list1 = FALSE;
            if (operatorType != ITM_ITEM_LIST)
            {
              list0 = child(0)->getOperatorType() == ITM_ITEM_LIST;
              list1 = child(1)->getOperatorType() == ITM_ITEM_LIST;
            }

            if (list0) result += "(";
            child(0)->unparse(result,phase,form, tabId);
            if (list0) result += ")";

            result += " ";
            result += kwd;
            result += " ";

            if (list1) result += "(";
            child(1)->unparse(result,phase,form, tabId);
            if (list1) result += ")";

            result += ")";
          } // infix operator
          break; // for now, break here
        } 
    // otherwise fall through to next case

    default:
    {
      // usually, that's arity 1, but can be >1 as well
      if (form == USER_FORMAT_DELUXE && isQuantifiedComp(this))
      {
        child(0)->unparse(result,phase,form, tabId);
        result += " ";
        result += kwd;
        result += " (_subquery_)";
      } // QuantifiedComp
      else if (arity == 1 && isAPredicate() && operatorType != ITM_NOT)
      {
        child(0)->unparse(result,phase,form,tabId);
        result += " ";
        result += kwd;
      } // predicate and != ITM_NOT
      else if (form == MV_SHOWDDL_FORMAT && operatorType == ITM_RENAME_COL)
      {
        child(0)->unparse(result, phase, form, tabId);
      }
      else if (form == MV_SHOWDDL_FORMAT && operatorType == ITM_COUNT_NONULL)
      {
        result += "count(";
        child(0)->unparse(result, phase, form, tabId);
        result += ")";
      }
      else if (form == MV_SHOWDDL_FORMAT && operatorType == ITM_COUNT)
      {
        result += "count(*)";
      }
      else
      {
        NAString postfix = ")";

        computeKwdAndPostfix( kwd, postfix, form );

        // function name, open parenthesis, initial arguments
        result += kwd;

        // unparse all the children as arguments
        for (Lng32 i = 0; i < (Lng32)arity; i++)
          {
            if (i > 0) result += ", ";
            child(i)->unparse(result,phase,form,tabId);
          }

        // add any postfix and closing parenthesis
        result += postfix;
      } // else (print function syntax)
    } // default of switch(arity)
  } // end switch (arity)
} // ItemExpr::unparse

// MDAMR
DisjunctArray * ItemExpr::mdamTreeWalk()
{

  DisjunctArray * rc = new STMTHEAP DisjunctArray(new STMTHEAP ValueIdSet(getValueId()));
  return rc;
}
//MDAMR

NABoolean ItemExpr::equatesToAConstant() const
{
  if (getOperatorType() != ITM_EQUAL)
    return FALSE;

  ItemExpr *lhs = child(0);
  lhs = lhs->getLeafValueIfUseStats();

  if(lhs->getOperatorType() != ITM_VEG_REFERENCE)
    return FALSE;

  ItemExpr *rhs = child(1);
  rhs = rhs->getLeafValueIfUseStats();

  if (rhs->getOperatorType() == ITM_CACHE_PARAM)
    return TRUE;

  if(!rhs->doesExprEvaluateToConstant(TRUE, TRUE))
     return FALSE;

  return TRUE;
}

// The check performed to determine if a column 
// exists works only till binder phase. For use 
// in post-Binder phase, the logic in the method 
// will have to be changed.
NABoolean ItemExpr::containsColumn()
{
  OperatorTypeEnum op = getOperatorType();

  // This is a base column.
  if (op == ITM_BASECOLUMN)
    return TRUE;

  // This is a leaf item other than a base column.
  if (op >= ITM_CONSTANT && op <= ITM_VEG_REFERENCE)
    return FALSE;

  // Iterate through this item's inputs looking for a base column.
  for (Int32 i = 0; i < getArity(); i++) {
    ItemExpr *expr = child(i);

    if (!expr)
      return FALSE;

    if (expr->containsColumn())
      return TRUE;
  }

  return FALSE;
}

//++MV
// -----------------------------------------------------------------------
// Return the default selectivity for this predicate
// -----------------------------------------------------------------------
double ItemExpr::defaultSel()
{
  if (selectivityFactor_ < 0)
    return getOperatorType() == ITM_RETURN_FALSE ? 0.0 : 1.0;
  else
    return selectivityFactor_;
}
//--MV

ItemExpr * ItemExpr::containsRightmost(const ItemExpr *ie)
{
  if (this == ie) return this;
  if (!this || !ie) return NULL;
  for (Int32 arity = getArity(); arity-- > 0; )
    if (child(arity))
      return (child(arity) == ie) ? this : child(arity)->containsRightmost(ie);
  return NULL;
}

NABoolean ItemExpr::hasEquivalentProperties(ItemExpr * other)
{
  if (other == NULL )
    return FALSE;

  CMPASSERT(other->getValueId() != NULL_VALUE_ID && getValueId() != NULL_VALUE_ID);
  //defaults behavior is return false
  return FALSE;
}

NABoolean ItemExpr::hasBaseEquivalence(ItemExpr * other)
{
  if (other == NULL)
    return FALSE;

  CMPASSERT(other->getValueId() != NULL_VALUE_ID && this->getValueId()!= NULL_VALUE_ID);
  
  if (getOperatorType() != other->getOperatorType() || 
        getArity() != other->getArity())
    return FALSE;

  if (getValueId()== other->getValueId() ||
      (getOperatorType() == ITM_CONSTANT && ((ConstValue*)this)->isNull() && ((ConstValue*)other)->isNull()))
    return TRUE;
  else
    if (getArity()==0)
      return FALSE;

  for (Int32 i= 0 ; i < getArity(); i++)
  {
    ItemExpr * chld= child(i);
    if (!chld->hasBaseEquivalence(other->child(i)) || !chld->hasEquivalentProperties(other->child(i)) )
      return FALSE;
  }
  return TRUE;
}//ItemExpr::hasBaseEquivalence(ValueId otherId)


ItemExpr * ItemExpr::changeDefaultOrderToDesc()
{
  if (getOperatorType() == ITM_ITEM_LIST )
  {
    for(Int32 i=0; i<getArity(); i++)
    {
      child(i) = child(i)->changeDefaultOrderToDesc();
    }
    return this;
  }
  else
    if (getOperatorType()== ITM_INVERSE)
    {
      if (child(0)->getOperatorType() == ITM_INVERSE)
        return child(0)->child(0);
      else
        return this;
    }
    else
      return new (CmpCommon::statementHeap()) InverseOrder(this);
  }//ItemExpr::changeDefaultOrderToDesc()

ValueId ItemExpr::removeInverseFromExprTree( NABoolean & invExists)
{
  if (getOperatorType() == ITM_ITEM_LIST )
  {
    for(Int32 i=0; i<getArity(); i++)
      child(i) = child(i)->removeInverseFromExprTree(invExists);
    return getValueId();
  }
  else
      if (getOperatorType() == ITM_INVERSE)
        invExists = TRUE;
      return removeInverseOrder()->removeInverseOrder()->getValueId(); 

 }//ItemExpr::removeInverseFromExprTree()

///


void ItemExpr::transformOlapFunctions(CollHeap *wHeap)
{

  for (Int32 i= 0 ; i < getArity(); i++)
  {
    ItemExpr * mychild= child(i);
    if (mychild->isOlapFunction())
    {
      ItmSeqOlapFunction * olap = (ItmSeqOlapFunction*) mychild;
      ItemExpr * itmExpr = olap->transformOlapFunction(wHeap);
      itmExpr->synthTypeAndValueId(TRUE);
      child(i) = itmExpr;
    }
    //else  //olap function can t have another olap as descendant ????
   // {
    //  child(i)->transformOlapFunctions(wHeap);
    //}
    child(i)->transformOlapFunctions(wHeap);
  }

}//void ItemExpr::transformOlapFunctions(CollHeap *wHeap)


// -----------------------------------------------------------------------
// removeInverseFromExprTree
//
// overloading above method for special purpose use
// onlyDouble parameter is used when the Inverse should not be removed 
// unless two Inverse exprs are found in a row
// -----------------------------------------------------------------------
ItemExpr* 
ItemExpr::removeInverseFromExprTree( NABoolean & invExists,
                                     const NABoolean onlyDouble )
{
  if (getOperatorType() == ITM_ITEM_LIST )
  {
    for(Int32 i=0; i<getArity(); i++)
      child(i) = child(i)->removeInverseFromExprTree(invExists,
                                                     onlyDouble);
    return this;
  }
  else
  {
    if (getOperatorType() == ITM_INVERSE)
      invExists = TRUE;

    // if the onlyDouble flag is set to TRUE, then we
    // must find two Inverse exprs in a row to remove
    if( (!onlyDouble) ||
        getOperator().match(ITM_INVERSE) &&
        child(0)->getOperator().match(ITM_INVERSE) )
    {
      return removeInverseOrder()->removeInverseOrder();
    }
    else
    {
      return this;
    }
  }
 }//ItemExpr::removeInverseFromExprTree()

//


 void ItemExpr::removeNotCoveredFromExprTree(ItemExpr * &ie ,
                                             const ValueIdSet &seqColumns,
                                             NABoolean rootNode)
{
  if (rootNode)
  { 
    while (ie->getOperatorType() == ITM_NOTCOVERED && 
           seqColumns.contains(ie->getValueId()))
    {
      ie= ie->child(0);
    }
  }
 
  for(Int32 i=0; i<ie->getArity(); i++)
  {
    while (ie->child(i)->getOperatorType() == ITM_NOTCOVERED && 
      seqColumns.contains(ie->child(i)->getValueId()))
    {
      ie->child(i) = ie->child(i)->child(0);
    }
    ItemExpr * tmp = ie->child(i);
    removeNotCoveredFromExprTree(tmp,seqColumns, FALSE);
  }

}//ItemExpr::removeNotCoveredFromExprTree()

// -----------------------------------------------------------------------
// member functions for class ZZZBinderFunction
// -----------------------------------------------------------------------
ItemExpr *ZZZBinderFunction::copyTopNode(ItemExpr *derivedNode,
                                         CollHeap *outHeap)
{
  ItemExpr *result=0;

  if (derivedNode == NULL)
   {
    switch (getArity())
     {
       case 1:
               result = new (outHeap) ZZZBinderFunction(getOperatorType(),
                            child(0));
         break;
       case 2:
               result = new (outHeap) ZZZBinderFunction(getOperatorType(),
                            child(0), child(1));
         break;
       case 3:
               result = new (outHeap) ZZZBinderFunction(getOperatorType(),
                            child(0), child(1), child(2));
         break;
       case 4:
               result = new (outHeap) ZZZBinderFunction(getOperatorType(),
                            child(0), child(1), child(2), child(3));
         break;
       case 5:
               result = new (outHeap) ZZZBinderFunction(getOperatorType(),
                             child(0), child(1), child(2), child(3), child(4));
         break;
     } // switch
   }
  else
   {
    result = derivedNode;
   }

  return BuiltinFunction::copyTopNode(result, outHeap);
}

// -----------------------------------------------------------------------
// member functions for class BiArith
// -----------------------------------------------------------------------
Int32 BiArith::getArity() const { return 2;}

const NAString BiArith::getText() const
{
  switch (getOperatorType())
    {
    case ITM_PLUS:
      return "+";
    case ITM_MINUS:
      return "-";
    case ITM_TIMES:
      return "*";
    case ITM_DIVIDE:
      return "/";
    case ITM_EXPONENT:
      return "**";
    default:
      return "unknown BiArith";
    } // switch
} // BiArith::getText()

NABoolean BiArith::duplicateMatch(const ItemExpr& other) const
{
  if (NOT genericDuplicateMatch(other))
    return FALSE;

  const BiArith &o = (BiArith &) other;
  if (unaryNegate_ != o.unaryNegate_)
    return FALSE;

  if (normalizeFlags_ != o.normalizeFlags_ )
    return FALSE;

  if (intervalQualifier_ OR o.intervalQualifier_)
    {
      if (intervalQualifier_ == NULL OR
	  o.intervalQualifier_ == NULL OR
	  NOT (*intervalQualifier_ == *(o.intervalQualifier_)))
	return FALSE;
    }
  return TRUE;
}

ItemExpr * BiArith::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  BiArith *result;
  BiArith  *result2;

  if (derivedNode == NULL)
    result = new (outHeap) BiArith(getOperatorType());
  else
    result = (BiArith*)derivedNode;

  result->setRoundingMode(getRoundingMode());
  if ( ignoreSpecialRounding() ) result->setIgnoreSpecialRounding();
  result->setDivToDownscale(getDivToDownscale());

  result2 = (BiArith *)ItemExpr::copyTopNode(result, outHeap);
  result2->normalizeFlags_ = normalizeFlags_ ;
  return result2;
}

ItemExpr * BiArithSum::copyTopNode(ItemExpr *derivedNode, CollHeap *outHeap)
{
  ItemExpr *result;
  if (derivedNode == NULL)
    result = new (outHeap) BiArithSum(getOperatorType());
  else
    result = derivedNode;

  return ItemExpr::copyTopNode(result, outHeap);
}

ConstValue * BiArith::castToConstValue (NABoolean & negate_it)
{
  OperatorTypeEnum op = getOperatorType();

  if ((op == ITM_MINUS) || (op == ITM_PLUS))
  {
    NABoolean neg0 = FALSE;
    NABoolean neg1 = FALSE;
    ConstValue * lhs = child(0)->castToConstValue(neg0);
    ConstValue * rhs = child(1)->castToConstValue(neg1);

    if (lhs && rhs)
    {
      Lng32 scale0 = 0;
      if (lhs->canGetExactNumericValue() &&
          lhs->getExactNumericValue(scale0) == 0)
        {
          if (op == ITM_MINUS)
            negate_it = (!neg1);
          else
            negate_it = neg1;
          return (rhs);
        }
      else
      {
        Lng32 scale1 = 0;
        if (rhs->canGetExactNumericValue() &&
            rhs->getExactNumericValue(scale1) == 0)
          {
            negate_it = neg0;
            return (lhs);
          }
      }
    }
  }
  return NULL;
}

/*--------------------------------------------------------------
* this routine is mainly called by complifyAndRemoveUncoveredSuffix(),
* sameOrder() and shortCutGroupBy::topMatch() to find out if a
* simplified expression still has the same order or if it has inverse
* order. Based on this we decide to do a inverse scan or a forward
* scan to satisfy order by or min/max aggregate.
*-----------------------------------------------------------------*/
ItemExpr * BiArith::simplifyOrderExpr(OrderComparison *newOrder)
{
  ItemExpr *result = this;
  OrderComparison myOrder = SAME_ORDER;
  OrderComparison childOrder = SAME_ORDER;


  // - the following expressions are simplified and
  //   has the same order as "a"
  //     a + const
  //     const + a
  //     a - const
  //     a * positive const
  //     positive const * a
  //     a / positive const
  // - the following expressions have the inverse order of "a"
  // and are siplified
  //     const - a
  //     a * negative const
  //     negative const * a
  //     a / negative const
  // - the following expressions are not simplified because
  //  the order is not consistent
  // positive const / a
  // negative const / a
  //
  // example:
  //
  //   values for a : -2 , -1, 1, 2, 3
  //
  //  if we say that 1/a is inverse order of a
  // then a order by of 1/a results in
  //
  //    (ordering of a    1/a          but the correct order
  //     if we simplify)                would be
  //	3	             .33             -1     -1
  //    2                .5				-.5    -2
  //	1                 1             .33    3
  //	-1                -1            .5     2
  //    -2                -.5            1     1
  //
  //Note: as long as 'a' is an unsigned integer we can simplify but
  //      it is to rare an occasion that a user does 1/a or -1/a so
  //      it is not supported.


  if (child(0)->getOperatorType() == ITM_CONSTANT)
    {
      switch (getOperatorType())
	{
	case ITM_PLUS:
	  result = child(1)->simplifyOrderExpr(&childOrder);
	  myOrder = SAME_ORDER;
	  break;

	case ITM_MINUS:
	  result = child(1)->simplifyOrderExpr(&childOrder);
	  myOrder = INVERSE_ORDER;
	  break;

	case ITM_TIMES:
	  result = child(1)->simplifyOrderExpr(&childOrder);
	  break;

	case ITM_DIVIDE:
      break;

	default:
	  break;
	}
    }
  else if (child(1)->getOperatorType() == ITM_CONSTANT)
    {
      switch (getOperatorType())
	{
	case ITM_PLUS:
	case ITM_MINUS:
	  result = child(0)->simplifyOrderExpr(&childOrder);
	  myOrder = SAME_ORDER;
	  break;

	case ITM_TIMES:
	  result = child(0)->simplifyOrderExpr(&childOrder);
	  break;

	case ITM_DIVIDE:
      // part of fix to genesis case 10-070416-0218, soln 10-070416-4141
      // mxcmp must consider ORDER BY "v/const" incompatible with GROUP BY "v"
      // when "v/const" can lose precision relative to "v"
      if (getRoundingMode() != 0 &&
          CmpCommon::getDefault(COMP_BOOL_176) == DF_OFF)
        {
          // do NOT simplify. leave expr as is.
          break;
        }
      else
        {
          result = child(0)->simplifyOrderExpr(&childOrder);
        }
	  break;

	default:
	  break;
	}
    }
  else if (child(0)->getOperatorType() == ITM_MINUS AND
	  child(0)->child(0)->getOperatorType() == ITM_CONSTANT
	  AND child(0)->child(1)->getOperatorType() == ITM_CONSTANT
	  AND *(short *)((ConstValue *)((ItemExpr*)(child(0)->child(0))))->getConstValue()==0
	  )

  {
	  ItemExpr * constExpr = child(0)->child(1);
	  switch(getOperatorType())
	  {
	  case ITM_TIMES:
		  result = child(1)->simplifyOrderExpr(&childOrder);
		  myOrder = INVERSE_ORDER;
		  break;
	  case ITM_DIVIDE:
		  break;
	  }
  }
  else if (child(1)->getOperatorType() == ITM_MINUS AND
	  child(1)->child(0)->getOperatorType() == ITM_CONSTANT
	  AND child(1)->child(1)->getOperatorType() == ITM_CONSTANT
	  AND *(short *)((ConstValue *)((ItemExpr*)(child(1)->child(0))))->getConstValue()==0
	  )

  {
	  switch(getOperatorType())
	  {
	  case ITM_TIMES:
		  result = child(0)->simplifyOrderExpr(&childOrder);
		  myOrder = INVERSE_ORDER;
		  break;
	  case ITM_DIVIDE:
        // part of fix to genesis case 10-070416-0218, soln 10-070416-4141
        // mxcmp must consider ORDER BY "v/-const" incompatible 
        // with GROUP BY "v"
        // when "v/-const" can lose precision relative to "v"
        if (getRoundingMode() != 0 &&
            CmpCommon::getDefault(COMP_BOOL_176) == DF_OFF)
          {
            // do NOT simplify. leave expr as is.
            break;
          }
        else
          {
            result = child(0)->simplifyOrderExpr(&childOrder);
            myOrder = INVERSE_ORDER;
          }
		  break;
	  }

  }

  // return results
  if (newOrder)
    {
      // if both this and the child inverse or leave the order the
      // net result is the same order, otherwise we inverse the order once
      if (myOrder == childOrder)
	*newOrder = SAME_ORDER;
      else
	*newOrder = INVERSE_ORDER;
    }
  return result;
}

ItemExpr * BiArith::foldConstants(ComDiagsArea *diagsArea,
				  NABoolean newTypeSynthesis)
{
  ItemExpr *result = this;

  // attempt to do constant arithmetic if both operands are constants
  // and if we are allowed to pick the result type
  if (child(0)->getOperatorType() == ITM_CONSTANT AND
      child(1)->getOperatorType() == ITM_CONSTANT AND
      newTypeSynthesis)
    {
      // get the two operands into two Int64 variables if possible
      Int64 ops[2] = {0,0};
      Lng32 scales[2] = {0,0};
      Int64 numResult = 0;
      NABoolean canDoIt = TRUE; // give up once it becomes too difficult
      scales[0] = 0;  scales[1] = 0;
      ops[0] = 0;  ops[1] = 0;

      for (Int32 i = 0; i < 2 AND canDoIt; i++)
	{
	  NABoolean negate;
	  ConstValue *cv = child(i)->castToConstValue(negate);
	  if (cv AND cv->canGetExactNumericValue())
	    {
	      CMPASSERT(NOT negate);
	      ops[i] = cv->getExactNumericValue(scales[i]);
	    }
	  else
	    {
	      // can't do it yet if this isn't represented as a signed
	      // or unsigned binary number without any additional fluff
	      canDoIt = FALSE;
	    }
	}

      // -----------------------------------------------------------------
      // At this point, ops contains two 64 bit numbers that represent the
      // exact numeric operands. scales contains the scales of the operands.
      // Now do the arithmetic, but try not to cause overflow traps.
      // -----------------------------------------------------------------

      // for now, give up on any values with a scale != 0
      if (scales[0] != 0 OR scales[1] != 0)
	canDoIt = FALSE;

      if (canDoIt)
	{
	  // adjust scales, if necessary
	  switch (getOperatorType())
	    {
	    case ITM_PLUS:
	    case ITM_MINUS:
	      if (scales[0] != scales[1])
		// sorry, keep it simple for now
		canDoIt = FALSE;
	      break;

	    default:
	      break;
	    }
	}

      NABoolean overflow = FALSE;
      NABoolean zeroDivide = FALSE;

      // check for overflow
      // for now, just do it for reasonably small constants
      if (ops[0] < -10000000 OR ops[0] > 10000000 OR
	  ops[1] < -10000000 OR ops[1] > 10000000)
	canDoIt = FALSE;

      // -----------------------------------------------------------------
      // ok, now it's time to do the real thing
      // -----------------------------------------------------------------

      if (canDoIt AND NOT overflow)
	{
	  switch (getOperatorType())
	    {
	    case ITM_PLUS:
	      numResult = ops[0] + ops[1];
	      break;

	    case ITM_MINUS:
	      numResult = ops[0] - ops[1];
	      break;

	    case ITM_TIMES:
	      numResult = ops[0] * ops[1];
	      break;

	    case ITM_DIVIDE:
	      if (ops[1] == 0)
		zeroDivide = TRUE;
	      else
		numResult = ops[0] / ops[1];
	      break;
	    }
	}

      // error handling
      if (canDoIt AND (overflow OR zeroDivide))
	{
          NAString up(CmpCommon::statementHeap());
	  unparse(up);
	  *diagsArea << DgSqlCode(zeroDivide ? -4075 : -4076) << DgString0(up);
	  canDoIt = FALSE;
	}

      if (canDoIt)
	{
	  // now we're ready to do the switch

          if (numResult >= INT_MIN AND numResult <= INT_MAX)
	    {
	      // result can fit into a long, use the ConstValue(long)
	      // constructor
	      Lng32 num;

	      num = (Lng32) numResult;
	      result = new(CmpCommon::statementHeap()) SystemLiteral(num);
	    }
	  else
	    {
	      // the result becomes an 8 byte integer, use the ConstValue
	      // constructor with a type, the binary image, and a text string

	      char numstr[TEXT_DISPLAY_LENGTH];
	      convertInt64ToAscii(numResult,numstr);
              NAString runningOutOfNames(numstr, CmpCommon::statementHeap());

	      result = new(CmpCommon::statementHeap()) SystemLiteral(
		   new(CmpCommon::statementHeap()) SQLLargeInt(CmpCommon::statementHeap(), TRUE,FALSE),
		   (void *) &numResult,
		   sizeof(numResult),
		   &runningOutOfNames);
	    }
	}
    }

  // perform the generic tasks (recursion, type synthesis) on the
  // result, regardless of whether we transformed it or not
  return result->ItemExpr::foldConstants(diagsArea,newTypeSynthesis);
}


NABoolean BiArith::isEquivalentForCodeGeneration(const ItemExpr * other)
  {
  NABoolean rc = FALSE;        // assume failure

  if (hasBaseEquivalenceForCodeGeneration(other))
    {
    // we know that other is a BiArith, its operator type is the same,
    // and that the children are equivalent
    BiArith * otherBiArith = (BiArith *)other;

    if ( (unaryNegate_ == otherBiArith->unaryNegate_) &&
         (normalizeFlags_ == otherBiArith->normalizeFlags_ ) )
      {
      // make sure both have the same interval qualifier (if any)
      NABoolean sameIntervalQualifier = FALSE;  // assume failure
      if (intervalQualifier_)
        {
        if (otherBiArith->intervalQualifier_)
          {
          const NAType & otherIntervalQualifier = *(otherBiArith->intervalQualifier_);
          if (intervalQualifier_->operator==(otherIntervalQualifier))
            sameIntervalQualifier = TRUE;
          }
        }
      else if (otherBiArith->intervalQualifier_ == 0)
        sameIntervalQualifier = TRUE;

      if (sameIntervalQualifier)
        {
        // the next test distinguishes between BiArith and its special-case
        // inheriting classes, BiArithSum and BiArithCount
	if (getText() == otherBiArith->getText())  // same class?
          rc = TRUE;  // the two values can be produced by the same generated expr
        }
      }
    }

  return rc;
  }

QR::ExprElement BiArith::getQRExprElem() const
{
  return QR::QRBinaryOperElem;
}

NABoolean BiArith::hasEquivalentProperties(ItemExpr * other)
{  
  if (other == NULL)    
    return FALSE;  
  if (getOperatorType() != other->getOperatorType() ||     
    getArity() != other->getArity())    
    return FALSE;    
  
  BiArith * otherBiArith = (BiArith *) other;    
  
  return     
    (this->unaryNegate_ == otherBiArith->unaryNegate_) &&     
    (this->normalizeFlags_ == otherBiArith->normalizeFlags_) &&    
    (this->intervalQualifier_ == otherBiArith->intervalQualifier_) &&    
    (this->divToDownscale_ == otherBiArith->divToDownscale_);
}

ItemExpr * UnArith::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  UnArith *result;

  if (derivedNode == NULL)
    result = new (outHeap) UnArith();
  else
    result = (UnArith*)derivedNode;

  return result;
}

// -----------------------------------------------------------------------
// member functions for class ColReference
// -----------------------------------------------------------------------
Int32 ColReference::getArity() const { return 0; }

const NAString ColReference::getText() const
{
  NAColumn *nacol = getValueId() != NULL_VALUE_ID ?
    getValueId().getNAColumn() :
    NULL;
  return nacol ?
    nacol->getFullColRefNameAsAnsiString() :
    colRefName_->getColRefAsAnsiString();
}

HashValue ColReference::topHash()
{
  HashValue result = ItemExpr::topHash();

  // hash any local data members of the derived class
  result ^= colRefName_->getColRefAsString();

  return result;
}

NABoolean ColReference::duplicateMatch(const ItemExpr & other) const
{
  if (NOT genericDuplicateMatch(other))
    return FALSE;

  ColReference &o = (ColReference &) other;

  // compare any local data members of the derived class
  // and return FALSE if they don't match
  if (NOT (*colRefName_ == *(o.colRefName_)))
    return FALSE;

  return TRUE;
}

ItemExpr * ColReference::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
  {
    ColRefName *colName;
    if (colRefName_->isStar())
    {
      colName = new (outHeap) ColRefName(1);
    }
    else
    {
      colName = new (outHeap)
	ColRefName(colRefName_->getColName(),
		   colRefName_->getCorrNameObj(),
		   outHeap);
    }
    ColReference *newColRef = new (outHeap) ColReference(colName);
    newColRef->setTargetColumnClass(getTargetColumnClass());
    result = newColRef;
  }
  else
    result = derivedNode;

  return ItemExpr::copyTopNode(result, outHeap);
}

// -----------------------------------------------------------------------
// member functions for class HostVar
// -----------------------------------------------------------------------

HostVar::HostVar(const HostVar &hv)
       : ItemExpr(hv.getOperatorType()),
	 varName_(hv.varName_, CmpCommon::statementHeap()),
	 indicatorName_(hv.indicatorName_, CmpCommon::statementHeap()),
	 prototypeValue_(hv.prototypeValue_, CmpCommon::statementHeap()),
	 prototypeType_(hv.prototypeType_),
	 isEnvVar_(hv.isEnvVar_), isDefine_(hv.isDefine_),
	 isSystemGenerated_(hv.isSystemGenerated_),
	 paramMode_ (hv.paramMode_),
	 ordinalPosition_ (hv.ordinalPosition_),
	 hvIndex_ (hv.hvIndex_),
	 rowsetInfo_(hv.rowsetInfo_),
	 heading_(hv.heading_, CmpCommon::statementHeap()),
	 tablename_(hv.tablename_,CmpCommon::statementHeap())
{
  if (hv.varType_ == NULL)
     varType_ = NULL;
  else
     varType_ = hv.varType_->newCopy(CmpCommon::statementHeap());
}

Int32 HostVar::getArity() const { return 0; }

NABoolean HostVar::isAUserSuppliedInput() const             { return TRUE; }

const NAString HostVar::getText() const
{
  NAString punc(CmpCommon::statementHeap());
  if (isSystemGenerated_) punc = "\\:";			// backslash, colon
  if (!indicatorName_.isNull())
    return punc + varName_ + " " + punc + indicatorName_;
  else
    return punc + varName_;
}

HashValue HostVar::topHash()
{
  HashValue result = ItemExpr::topHash();

  // hash any local data members of the derived class
  result ^= (CollIndex) getValueId();

  return result;
}

NABoolean HostVar::duplicateMatch(const ItemExpr & other) const
{
  // rely on value id comparison since the binder should not
  // assign different value ids for the same hostvar
  return genericDuplicateMatch(other);
}

ItemExpr * HostVar::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) HostVar(*this);
  else
    result = derivedNode;

  return ItemExpr::copyTopNode(result, outHeap);
}

NABoolean HostVar::isCharTypeMatchRulesRelaxable()
{
  if ( getType()->getTypeQualifier() == NA_CHARACTER_TYPE &&
       ((CharType*)getType())->getCharSet() == CharInfo::UNICODE
     )
    return TRUE;
  else
    return FALSE;
}

ItemExpr * DefaultSpecification::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) DefaultSpecification();
  else
    result = derivedNode;

  return ItemExpr::copyTopNode(result, outHeap);
}



NABoolean RowsetArrayScan::isCharTypeMatchRulesRelaxable()
{
  if ( getOperatorType() == ITM_ROWSETARRAY_SCAN &&
       getType()->getTypeQualifier() == NA_CHARACTER_TYPE &&
       ((CharType*)getType())->getCharSet() == CharInfo::UNICODE
     )
    return TRUE;
  else
    return FALSE;
}

// -----------------------------------------------------------------------
// member functions for class ConstantParameter
// -----------------------------------------------------------------------
ConstantParameter::ConstantParameter(const ConstValue& v, NAMemory *h,
                                     NABoolean quantizeLen, UInt32 p)
  : val_((ConstValue*)&v), type_(CONST_CAST(NAType*, v.getType()))
  , Parameter(ITM_CACHE_PARAM)
{
  if (type_->getTypeQualifier() != NA_CHARACTER_TYPE) {
    type_ = type_->newCopy(h);
  }
  else {
    // convert char type to equivalent varchar type
    type_ = ((CharType*)type_)->equivalentVarCharType(h, quantizeLen);
  }
  posns_ = new(STMTHEAP) ClusteredBitmap(STMTHEAP);
  *posns_ += p;
}

ConstantParameter::ConstantParameter(ConstValue* v, NAMemory *h,
                                     const NAType* typ, UInt32 p)
  : val_(v), type_(typ->newCopy(h)), Parameter(ITM_CACHE_PARAM)
{
  // non-null ConstantParameters are non-nullable
  type_->setNullable(v->isNull());

  if (v->getType()->getTypeQualifier() == NA_CHARACTER_TYPE &&
      type_->getTypeQualifier() == NA_CHARACTER_TYPE) {
    // this is part of a fix to genesis case: 10-010618-3484.
    // ConstantParameter's type must take v's (not typ's) upshift.
    CharType *vt = (CharType*)v->getType();
    CharType *t = (CharType*)type_;
    t->setUpshifted(vt->isUpshifted());
  }
  posns_ = new(STMTHEAP) ClusteredBitmap(STMTHEAP);
  *posns_ += p;
}

ConstantParameter::ConstantParameter(const ConstantParameter& cp, NAHeap *h)
  : val_(new(h) ConstValue(*cp.val_,h)), type_(cp.type_->newCopy(h))
  , posns_(new(h) ClusteredBitmap(*cp.posns_,h))
  , Parameter(cp)
{
}

ConstantParameter::~ConstantParameter()
{
  // we don't own type_; the statementHeap does.
  // so, we leave it up to statementHeap to free it.
}

ItemExpr *ConstantParameter::copyTopNode
(ItemExpr *derivedNode, CollHeap* outHeap)
{
  CMPASSERT(derivedNode == NULL);
  ItemExpr *result = new (outHeap) ConstantParameter(*this, (NAHeap*)outHeap);
  return result;
}

NABoolean ConstantParameter::duplicateMatch(const ItemExpr& other) const
{
  if (NOT genericDuplicateMatch(other))
    return FALSE;

  CMPASSERT(val_ != NULL);
  const ConstantParameter &o = (ConstantParameter &) other;
  return val_->duplicateMatch(*(o.val_));
  // no comparison of type_ since it should be the same if the values are
}

const NAString ConstantParameter::getText() const
{
  if (val_)
    return NAString("%(", CmpCommon::statementHeap()) + val_->getText() + ")";
  else
    return NAString("%", CmpCommon::statementHeap());
}

const NAType* ConstantParameter::synthesizeType()
{
  return getType();
}

HashValue ConstantParameter::topHash()
{
  return val_ ? val_->topHash() : ItemExpr::topHash();
}

// return true if val matches this ConstantParameter
NABoolean ConstantParameter::matches(ConstValue *val) const
{
  if (!val_ || !val) 
    return FALSE;
  else
    return *val_ == *val;
}

// -----------------------------------------------------------------------
// member functions for class DynamicParam
// -----------------------------------------------------------------------
const NAString DynamicParam::getText() const
{
  if (!indicatorName_.isNull())
    return NAString("?") + paramName_ +
           NAString(" ?") + indicatorName_ ;
  else
    return NAString("?") + paramName_  ;
}

HashValue DynamicParam::topHash()
{
  HashValue result = ItemExpr::topHash();

  // hash any local data members of the derived class
  result ^= (CollIndex) getValueId();

  return result;
}

NABoolean DynamicParam::duplicateMatch(const ItemExpr & other) const
{
  // rely on value id comparison since the binder should not
  // assign different value ids for the same parameter
  return genericDuplicateMatch(other);
}

ItemExpr * Parameter::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result = NULL;
  if (derivedNode == NULL)
    ABORT("copyTopNode() can only be called for a derived class of Parameter");
  else
    result = derivedNode;
  return ItemExpr::copyTopNode(result, outHeap);
}

ItemExpr * DynamicParam::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  return this;
}

const NAType * DynamicParam::pushDownType(NAType& desiredType,
				  enum NABuiltInTypeEnum defaultQualifier)
{
   const NAType * currentType = &getValueId().getType();
   if ( desiredType.getTypeQualifier() == NA_CHARACTER_TYPE &&
        currentType-> getTypeQualifier() == NA_CHARACTER_TYPE
      )
   {
     CharType &desiredCT = (CharType&)desiredType;
     enum CharInfo::CharSet desiredCS = desiredCT.getCharSet();
     CharType* ct = (CharType*)currentType;

     if ( ct ->getCharSet() != desiredCS ) 
     {
       ct->setCharSet(desiredCS);
       ct->setCollation(desiredCT.getCollation());
       ct->setCoercibility(desiredCT.getCoercibility());
       ct->setCaseinsensitive(desiredCT.isCaseinsensitive());
     }
     return currentType;
   }
   return &desiredType;   
}


// -----------------------------------------------------------------------
// member functions for class RoutineParam
// -----------------------------------------------------------------------
const NAString RoutineParam::getText() const
{
    return NAString("?") + paramName_  ;
}

HashValue RoutineParam::topHash()
{
  HashValue result = ItemExpr::topHash();

  // hash any local data members of the derived class
  result ^= paramName_;
  result ^= optionalParam_;
  result ^= paramMode_;
  result ^= ordinalPosition_;
  result ^= rdesc_;
  result ^= (CollIndex) getValueId();

  return result;
}

NABoolean RoutineParam::duplicateMatch(const ItemExpr & other) const
{
  // rely on value id comparison since the binder should not
  // assign different value ids for the same parameter
  return genericDuplicateMatch(other);
}


ItemExpr * RoutineParam::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  RoutineParam *result;

  if (derivedNode == NULL) {
      // Does not copy the rdesc_ 
    result = new (outHeap) RoutineParam(paramName_, paramType_, 
                              ordinalPosition_,paramMode_, NULL, outHeap);
  }

  else
    result = (RoutineParam *) derivedNode;

  if (derivedNode != NULL)
  {
    result->paramName_       = paramName_;
    if (paramType_ != NULL)
      result->paramType_     = paramType_->newCopy (outHeap);
    result->paramMode_       = paramMode_;
    result->ordinalPosition_ = ordinalPosition_;
    result->rdesc_           = NULL; // Do not want to copy the RoutineDesc
                                     // nor does it make any sense to just
                                     // point to the one from the clone since
                                     // multiple routineParams typically will
                                     // point to the same routineDesc. If we
                                     // just make a deep copy here we will end
                                     // up with N new copies of the same info..
                                     // 
  }
  result->optionalParam_   = optionalParam_;
  result->isCacheable_     = isCacheable_;
  memcpy(result->argumentType_, argumentType_, sizeof(argumentType_));

  return Parameter::copyTopNode((ItemExpr *)result, outHeap);
}
// -----------------------------------------------------------------------
// member functions for class BaseColumn
// -----------------------------------------------------------------------

BaseColumn::~BaseColumn()
{}

// copy constructor
BaseColumn::BaseColumn(const BaseColumn &column) :
  ItemExpr(column),
  tableDesc_(column.tableDesc_),
  colNumber_(column.colNumber_),
  equivalentIndexCols_(column.equivalentIndexCols_),
  computedColumnExpr_(column.computedColumnExpr_)
{}


NAColumn *BaseColumn::getNAColumn() const
{
  return getTableDesc()->getNATable()->getNAColumnArray()[colNumber_];
}

const NAString& BaseColumn::getColName() const
{
  return getNAColumn()->getColName();
}

const NAType& BaseColumn::getType() const
{
  return *getNAColumn()->getType();
}

Int32 BaseColumn::getArity() const { return 0; }

const NAString BaseColumn::getText() const
{
  // getenv() calls are costly. avoid especially in release code.
#ifndef NDEBUG
  if (getenv("SIMPLE_BASECOL_DISPLAY") || getenv("SIMPLE_DISPLAY"))
  {
    return
      NAString(getTableDesc()->getNATable()->getTableName().getObjectName()) +
      NAString(".") +
      NAString(getTableDesc()->getNATable()->getNAColumnArray()[colNumber_]->
               getColName());
  }
#endif

  if (CmpCommon::getDefault(MVQR_LOG_QUERY_DESCRIPTORS) == DF_DUMP_MV)
  {
    // If a correlation name exists, use it.
    // Otherwise, just use the base column name.
    const CorrName& corr = getTableDesc()->getCorrNameObj();
    NAString result;
    if (corr.getCorrNameAsString() != "")
    {
      result += corr.getCorrNameAsString();
      result += ".";
    }
    result += getTableDesc()->getNATable()->getNAColumnArray()[colNumber_]->getColName();
    return result;
  }

  // return the table in the format "table.col"
  ColRefName name(
    getTableDesc()->getNATable()->getNAColumnArray()[colNumber_]->getColName(),
    getTableDesc()->getCorrNameObj(), CmpCommon::statementHeap());
  return name.getColRefAsAnsiString(FALSE, TRUE);
}

const NAString BaseColumn::getTextForQuery() const {
  // return the table in the format "table.col" where
  // table is the physical table name and not the corr
  // table name as in getText() version

  return
    NAString(getTableDesc()->getNATable()->getTableName().getCatalogName()) +
    NAString(".") +
    NAString(getTableDesc()->getNATable()->getTableName().getSchemaName()) +
    NAString(".") +
    NAString(getTableDesc()->getNATable()->getTableName().getObjectName()) +
    NAString(".") +
    NAString(getTableDesc()->getNATable()->getNAColumnArray()[colNumber_]->
      getColName());
}

// return the set of KeyColumns referenced in the Computed Column Expression

void BaseColumn::getUnderlyingColumnsForCC(ValueIdSet &underlyingCols)
{
  if (getNAColumn()->isComputedColumn()) 
    {
      ValueIdSet keyCols = getTableDesc()->getClusteringIndex()->getIndexKey();
      keyCols = keyCols.convertToBaseIds();

      ValueIdSet compExprSet =  getComputedColumnExpr();
      underlyingCols.accumulateReferencedValues(keyCols, compExprSet);
    }
}

HashValue BaseColumn::topHash()
{
  HashValue result = ItemExpr::topHash();

  // hash any local data members of the derived class
  result ^= (void *) getTableDesc();
  result ^= colNumber_;

  return result;
}

NABoolean BaseColumn::duplicateMatch(const ItemExpr & other) const
{
  if (NOT genericDuplicateMatch(other))
    return FALSE;

  BaseColumn &o = (BaseColumn &) other;

  // compare any local data members of the derived class
  // and return FALSE if they don't match
  if (getTableDesc() != o.getTableDesc() OR
      colNumber_ != o.colNumber_)
    return FALSE;

  return TRUE;
}

ItemExpr * BaseColumn::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;
  ItemExpr *oldBC;

  if (derivedNode == NULL)
    oldBC = new (outHeap) BaseColumn(*this);
  else
    oldBC = derivedNode;

  result = ItemExpr::copyTopNode(oldBC, outHeap);
  if (derivedNode != NULL)
     ((BaseColumn *)result)->computedColumnExpr_ = 
                               ((BaseColumn *)derivedNode)->computedColumnExpr_;
  return result;
}

NABoolean BaseColumn::isCovered(const ValueIdSet& newExternalInputs,
				const GroupAttributes& newRelExprAnchorGA,
				ValueIdSet& referencedInputs,
				ValueIdSet& /*coveredSubExpr*/,
				ValueIdSet& /*unCoveredExpr*/) const
{
  // ---------------------------------------------------------------------
  // A base column is also covered if any equivalent index column is
  // available in the group attributes or in the new inputs. Note that
  // the inverse of this is not true: the ValueId of an IndexColumn item
  // expression is NOT covered by group attributes that contain the value
  // id of the corresponding BaseColumn.
  // ---------------------------------------------------------------------
  ValueId x = equivalentIndexCols_.init();
  for (;
       equivalentIndexCols_.next(x);
       equivalentIndexCols_.advance(x))
    {
      if (newRelExprAnchorGA.isCharacteristicOutput(x) OR
	  newRelExprAnchorGA.isCharacteristicInput(x))
	return TRUE;

      if (newExternalInputs.contains(x))
	{
	  referencedInputs += x;
	  return TRUE;
	}
    }

  return FALSE;
}

OrderComparison BaseColumn::sameOrder(ItemExpr *other,
				      NABoolean askOther)
{
  OrderComparison result =
    ItemExpr::sameOrder(other,askOther);

  if (result != DIFFERENT_ORDER)
    return result;

  // try all equivalent index columns, but don't call sameOrder recursively
  // for them, rather do a simple look-up
  // 10-031114-1317: replaced a for loop that traverses the ValueIdSet
  // with the contains method that is more efficient

  if (equivalentIndexCols_.contains(other->getValueId()))
  {
    result = SAME_ORDER;
  }

  return result;
}

ValueIdList *BaseColumn::getClusteringKeyCols() const
{
  return (ValueIdList*)
    &(tableDesc_->getClusteringIndex()->getClusteringKeyCols());
}

QR::ExprElement BaseColumn::getQRExprElem() const
{
  return QR::QRColumnElem;
}

// -----------------------------------------------------------------------
// member functions for class IndexColumn
// -----------------------------------------------------------------------
IndexColumn::IndexColumn(const NAFileSet *indexPtr,
			 Lng32 indexColumnNumber,
			 const ValueId &colDefinition)
  : ItemExpr(ITM_INDEXCOLUMN),index_(indexPtr),
    indexColNumber_(indexColumnNumber),indexColDefinition_(colDefinition)
{}

IndexColumn::~IndexColumn()
{}

NAColumn * IndexColumn::getNAColumn() const
{
  return index_->getAllColumns()[indexColNumber_];
}

const NAType& IndexColumn::getType() const
{
  return *getNAColumn()->getType();
}

Int32 IndexColumn::getArity() const { return 0; }

const NAString IndexColumn::getText() const
{
  // As an indexcol is not an Ansi construct, we need not make an effort to
  // unparse it following Ansi rules; this quick-and-dirty method is fine
  // (should only be seen in gui-display tool):

  return ColRefName::getColRefAsString(
			 getNAColumn()->getColName(),
			 index_->getFileSetName().getQualifiedNameAsString());
}

void IndexColumn::unparse(NAString &result,
			  PhaseEnum /*phase*/,
			  UnparseFormatEnum form,
			  TableDesc * tabId) const
{
  // don't print the NSK name in Explain
  if (form == EXPLAIN_FORMAT)
    {
      // result += "indexcol(";
      /*      if (index_->isVolatile())
	      {
	      // only output the object part of the external name
	      // and exclude cat/sch names as these are internal IDs.
	      ComObjectName con(index_->getExtFileSetName());
	      result += ColRefName::getColRefAsString(
	      getNAColumn()->getColName(),
	      con.getObjectNamePartAsAnsiString());
	      }
	      else
	      {
      */
      result += ColRefName::getColRefAsString(
	   getNAColumn()->getColName(),
	   index_->getExtFileSetName());
     // result += ")";
    }
  else
    {
      // in all other cases do print the NSK name?
      result += getText();
    }
}

HashValue IndexColumn::topHash()
{
  HashValue result = ItemExpr::topHash();

  // hash any data members of the derived class
  // (the definition is functionally dependent on the index and
  // column number, so don't hash it)
  result ^= (void *) index_;
  result ^= indexColNumber_;

  return result;
}

NABoolean IndexColumn::duplicateMatch(const ItemExpr & other) const
{
  if (NOT genericDuplicateMatch(other))
    return FALSE;

  IndexColumn &o = (IndexColumn &) other;

  // compare any local data members of the derived class
  // and return FALSE if they don't match
  if (index_ != o.index_ OR
      indexColNumber_ != o.indexColNumber_ OR
      NOT (indexColDefinition_ == o.indexColDefinition_))
    return FALSE;

  return TRUE;
}

ItemExpr * IndexColumn::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap)
      IndexColumn(index_,indexColNumber_,indexColDefinition_);
  else
    result = derivedNode;

  return ItemExpr::copyTopNode(result, outHeap);
}

OrderComparison IndexColumn::sameOrder(ItemExpr *other,
				       NABoolean askOther)
{
  OrderComparison result =
    ItemExpr::sameOrder(other,askOther);

  if (result != DIFFERENT_ORDER)
    return result;

  // try it with the definition of the index column
  return indexColDefinition_.getItemExpr()->sameOrder(other,TRUE);
}

ValueId IndexColumn::mapAndRewrite(ValueIdMap &map,
				   NABoolean mapDownwards)
{
  // try the standard method first
  ValueId result = ItemExpr::mapAndRewrite(map,mapDownwards);

  // we're done if the map contained a mapping for this column
  if (result != getValueId())
    return result;

  // try to replace the index column with its base column and then map
  result = indexColDefinition_.getItemExpr()->mapAndRewrite(map,mapDownwards);

  // return the result if it could be mapped
  // (no need to cache the index col. mapping since no new expr is created)
  if (result != indexColDefinition_)
    return result;

  // if all failed, just return the value id unchanged
  return getValueId();
}

Lng32 IndexColumn::getOffset() const
{
  return index_->getIndexKeyColumns().getOffset((short) indexColNumber_);
}

// -----------------------------------------------------------------------
// member functions for class SelIndex
// -----------------------------------------------------------------------
ItemExpr * SelIndex::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  CMPASSERT(derivedNode == NULL);

  ItemExpr *result = new (outHeap)
    SelIndex(getSelIndex(), getExprInGrbyClause());
  ((SelIndex *)result)->setRenamedColNameInGrbyClause
    (renamedColNameInGrbyClause());

  return ItemExpr::copyTopNode(result, outHeap);
}

Int32 SelIndex::getArity() const { return 0; }

const NAString SelIndex::getText() const
{
  char cp[TEXT_DISPLAY_LENGTH];
  sprintf(cp, "%d", getSelIndex());
  return cp;
}

// -----------------------------------------------------------------------
// member functions for class ValueIdRef
// -----------------------------------------------------------------------
Int32 ValueIdRef::getArity() const { return 0; }

NABoolean ValueIdRef::isCovered(const ValueIdSet& newExternalInputs,
				const GroupAttributes& coveringGA,
				ValueIdSet& referencedInputs,
				ValueIdSet& coveredSubExpr,
				ValueIdSet& /*unCoveredExpr*/) const
{
  // ---------------------------------------------------------------------
  // The ValueIdRef isCovered if the expression that it derives from
  // is covered.
  // ---------------------------------------------------------------------
  return coveringGA.covers(isDerivedFrom(), newExternalInputs,
			   referencedInputs, &coveredSubExpr);
} // ValueIdRef::isCovered()

const NAString ValueIdRef::getText() const
{
  char cp[TEXT_DISPLAY_LENGTH];
  sprintf(cp,"ValueId (%d)",CollIndex(isDerivedFrom()));
  return cp;
} // ValueIdRef::getText()


HashValue ValueIdRef::topHash()
{
  HashValue result = ItemExpr::topHash();

  // hash any local data members of the derived class
  result ^= derivedFrom_;

  return result;
}

NABoolean ValueIdRef::duplicateMatch(const ItemExpr & other) const
{
  if (NOT genericDuplicateMatch(other))
    return FALSE;

  ValueIdRef &o = (ValueIdRef &) other;

  // compare any local data members of the derived class
  // and return FALSE if they don't match
  if (NOT (derivedFrom_ == o.derivedFrom_))
    return FALSE;

  return TRUE;
}

ItemExpr * ValueIdRef::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) ValueIdRef(derivedFrom_);
  else
    result = derivedNode;

  return ItemExpr::copyTopNode(result, outHeap);
}

OrderComparison ValueIdRef::sameOrder(ItemExpr *other,
				      NABoolean askOther)
{
  OrderComparison result =
    ItemExpr::sameOrder(other,askOther);

  if (result != DIFFERENT_ORDER)
    return result;

  // check with the original expression
  return isDerivedFrom().getItemExpr()->sameOrder(other,TRUE);
}

// -----------------------------------------------------------------------
// member functions for class ValueIdProxy
// -----------------------------------------------------------------------

NABoolean ValueIdProxy::isCovered(const ValueIdSet& newExternalInputs,
                                  const GroupAttributes& coveringGA,
                                  ValueIdSet& referencedInputs,
                                  ValueIdSet& coveredSubExpr,
                                  ValueIdSet& unCoveredExpr) const
{
  // ---------------------------------------------------------------------
  // The ValueIdProxy isCovered if the expression that it derives from
  // is covered.
  // ---------------------------------------------------------------------
  return coveringGA.covers(isDerivedFrom(), newExternalInputs,
                           referencedInputs, &coveredSubExpr, &unCoveredExpr);
} // ValueIdProxy::isCovered()

const NAString ValueIdProxy::getText() const
{
  char cp[TEXT_DISPLAY_LENGTH];
  sprintf(cp,"ValueIdProxy (%d:%d->%d)",CollIndex(isDerivedFrom()),
                                        CollIndex(getOutputNum()),
                                        CollIndex(getOutputId()));
  return cp;
} // ValueIdProxy::getText()


HashValue ValueIdProxy::topHash()
{
  HashValue result = ItemExpr::topHash();

  // hash any local data members of the derived class
  result ^= derivedFrom_;
  result ^= outputOrdinalNumber_;
  result ^= outputValueId_;

  return result;
}

NABoolean ValueIdProxy::duplicateMatch(const ItemExpr & other) const
{
  if (NOT genericDuplicateMatch(other))
    return FALSE;

  ValueIdProxy &o = (ValueIdProxy &) other;

  // compare any local data members of the derived class
  // and return FALSE if they don't match
  if ((NOT (derivedFrom_ == o.derivedFrom_)) AND 
      (NOT (outputValueId_ == o.outputValueId_)) AND
      (NOT (outputOrdinalNumber_ == o.outputOrdinalNumber_)))
    return FALSE;

  return TRUE;
}


ItemExpr * ValueIdProxy::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) ValueIdProxy(derivedFrom_, 
                                        outputValueId_, 
                                        outputOrdinalNumber_);
  else
  {
    result = derivedNode;
  }

  ValueIdProxy * tmpNode = (ValueIdProxy *) result;
 
  tmpNode->derivedFrom_ = derivedFrom_;
  tmpNode->outputValueId_ = outputValueId_;
  tmpNode->outputOrdinalNumber_ = outputOrdinalNumber_;
  tmpNode->transformDerivedFromValueId_ = transformDerivedFromValueId_;

  return ItemExpr::copyTopNode(result, outHeap);
}

ItemExpr *ValueIdProxy::containsUDF()
{
    // The transfromChild_ means that this ValueIdProxy represents the
    // the subquery or UDF, thus return true..
  if ((transformDerivedFromValueId_ == TRUE) && 
      derivedFrom_.getItemExpr()->containsUDF())
    return this;
  else
    return 0;

} // ValueIdProxy::containsUDF

NABoolean ValueIdProxy::containsIsolatedUDFunction()
{
    // The transfromChild_ means that this ValueIdProxy represents the
    // the subquery or UDF, thus return true..
  if ((transformDerivedFromValueId_ == TRUE) && 
      derivedFrom_.getItemExpr()->containsUDF())
  {
     UDFunction *udf = (UDFunction *) derivedFrom_.getItemExpr()->containsUDF();

     const RoutineDesc *rdesc = udf->getRoutineDesc();
     if (rdesc == NULL || rdesc->getEffectiveNARoutine() == NULL ) return FALSE;  
     return ( rdesc->getEffectiveNARoutine()->isIsolate() ? TRUE : FALSE ) ;
  }
  else
    return FALSE;

} // ValueIdProxy::containsIsolatedUDFunction

NABoolean ValueIdProxy::containsSubquery()     // virtual method
{

    // The transfromChild_ means that this ValueIdProxy represents the
    // the subquery or UDF, thus return true..
  if ((transformDerivedFromValueId_ == TRUE) && 
      derivedFrom_.getItemExpr()->containsSubquery())
    return TRUE;
  else
    return FALSE;

} // ValueIdProxy::containsSubquery

NABoolean ValueIdProxy::containsValueIdProxySibling(const ValueIdSet &siblings)
    // virtual method
{
  // This method is used to make sure we extract all valueIds associated with
  // a subquery or UDF from a predicate or list.

  for (ValueId s = siblings.init(); siblings.next(s); siblings.advance(s))
  {
    if (s.getItemExpr()->getOperatorType() == ITM_VALUEID_PROXY)
    {
       ValueIdProxy *proxy = (ValueIdProxy *) (s.getItemExpr());
       if ( derivedFrom_ == proxy->isDerivedFrom() ) return TRUE;
    }
  }
  return FALSE;

} // ValueIdProxy::containsValueIdProxySibling

// -----------------------------------------------------------------------
// member functions for class ValueIdUnion
// -----------------------------------------------------------------------
void ValueIdUnion::setSource(Lng32 index, ValueId v)
{
  if((Lng32)sources_.entries() <= index) {
    sources_.insertAt(index, v);
  } else {
    sources_[index] = v;
  }
}

Int32 ValueIdUnion::getArity() const { return 0; }

NABoolean ValueIdUnion::isCovered(const ValueIdSet& newExternalInputs,
				  const GroupAttributes& coveringGA,
				  ValueIdSet& referencedInputs,
				  ValueIdSet& coveredSubExpr,
				  ValueIdSet& /*unCoveredExpr*/ ) const
{
  // ---------------------------------------------------------------------
  // Check which of all the operands of the ValueIdUnion isCovered().
  // Return its ValueId in coveredSubExpr.
  // ---------------------------------------------------------------------

  // $$$ Question: why not return all of the operands of the ValueIdUnion which
  // $$$ are covered -- why do we break after we find the first, in the loop below?

  ValueIdSet localSubExpr;

  for(CollIndex i = 0; i < entries(); i++)
  {
    localSubExpr.clear();
    if (coveringGA.covers(getSource(i), newExternalInputs,
			  referencedInputs, &localSubExpr) )
      {
	coveredSubExpr += getSource(i);
        break;
      }
  }

  // ---------------------------------------------------------------------
  // An aggregate function is coerced to fail the coverage test even when
  // its operand isCovered(). This is because the computation of the
  // aggregate function requires "raw" values produced by its operand to
  // be grouped. The aggregated values cannot be treated in the same
  // manner as the constitutent raw values.
  // ---------------------------------------------------------------------
  // Is something similar to the above, copied from
  // Aggregate::isCovered(), also true for ValueIdUnion?  If this is so
  // (which sort of makes sense to me), then that explains why this
  // function is hardcoded to always return FALSE.
  // ---------------------------------------------------------------------

  return FALSE; // the ValueIdUnion is not covered by its child's coveringGA

} // ValueIdUnion::isCovered()

void ValueIdUnion::getLeafValuesForCoverTest(ValueIdSet & leafValues, 
                                             const GroupAttributes& coveringGA,
                                             const ValueIdSet & newExternalInputs) const
{
  // for now, not sure if this method is really necessary -- default to
  // the base class method:

  ItemExpr::getLeafValuesForCoverTest (leafValues, coveringGA, newExternalInputs) ;

  //  leafValues += getValueId();  // this MIGHT be the right definition of this
  //                               // class -- hard to say at this point ...
} // ValueIdUnion::getLeafValuesForCoverTest()

const NAString ValueIdUnion::getText(UnparseFormatEnum form) const
{
  NAString result(CmpCommon::statementHeap());
  const char *delim;

  if (form == USER_FORMAT_DELUXE)
    delim = " UNION ";				// keyword format
  else
  {
    delim = ", ";				// standard list format
    result = "ValueIdUnion(";
  }

  for (CollIndex i = 0; i < entries(); i++)
  {
    if (i > 0)
      result += delim;

    // guard against loops in the references
    // (can happen with common subexpressions, for example)
    if (!getSource(i).getItemExpr()->referencesTheGivenValue(getValueId()))
      getSource(i).getItemExpr()->unparse(result);
    else
      result += "...";
  }

  if (form == USER_FORMAT_DELUXE)
    result.toUpper();
  else
    result += ")";

  return result;

} // ValueIdUnion::getText(), the NON-virtual method

const NAString ValueIdUnion::getText() const
{
  return getText(USER_FORMAT/*standard list format*/);

} // ValueIdUnion::getText(), the virtual method

HashValue ValueIdUnion::topHash()
{
  HashValue result = ItemExpr::topHash();

  // hash any local data members of the derived class
  for(CollIndex i = 0; i < entries(); i++)
  {
    result ^= getSource(i);
  }

  result ^= result_;

  result ^= flags_;

  return result;
}

NABoolean ValueIdUnion::duplicateMatch(const ItemExpr & other) const
{
  if (NOT genericDuplicateMatch(other))
    return FALSE;

  ValueIdUnion &o = (ValueIdUnion &) other;

  // compare any local data members of the derived class
  // and return FALSE if they don't match
  for(CollIndex i = 0; i < entries(); i++)
  {
    if (getSource(i) != o.getSource(i))
      return FALSE;
  }

  if (result_ != o.result_ || flags_ != o.flags_)
    return FALSE;

  return TRUE;
}

ItemExpr * ValueIdUnion::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ValueIdUnion *result;

  if (derivedNode == NULL)
    result = new (outHeap) ValueIdUnion(sources_, result_, flags_);
  else
    result = (ValueIdUnion*)derivedNode;

  result->otherFlags_ = otherFlags_;

  return ItemExpr::copyTopNode(result, outHeap);
}

// -----------------------------------------------------------------------
// member functions for class VEG
// -----------------------------------------------------------------------
VEG::VEG()
  : ItemExpr(ITM_VEG), done_(FALSE), userInputs_(0), seenBefore_(FALSE),
   specialNulls_(FALSE)
{
  allocValueId();
  // Allocate a VegReference for representing any member of the VEG.
  vegRef_  = new (CmpCommon::statementHeap()) VEGReference(getValueId());
  // Allocate a VegPredicate for replacing the = predicate
  vegPred_ = new (CmpCommon::statementHeap()) VEGPredicate(getValueId());
} // VEG::VEG()

VEG::VEG(const ValueIdSet & vegSet)
 : ItemExpr(ITM_VEG), eqGroup_(vegSet), done_(FALSE), userInputs_(0),
   seenBefore_(FALSE), specialNulls_(FALSE)
{
  allocValueId();
  // Allocate a VegReference for representing any member of the VEG.
  vegRef_  = new (CmpCommon::statementHeap()) VEGReference(getValueId());
  // Allocate a VegPredicate for replacing the = predicate
  vegPred_ = new (CmpCommon::statementHeap()) VEGPredicate(getValueId());
} // VEG::VEG()

VEG::~VEG()
{
  delete vegRef_;
  delete vegPred_;
} // VEG::~VEG()

void VEG::insert(const ValueId & newValue)
{
  if (NOT eqGroup_.contains(newValue))
  {
    eqGroup_ += newValue;
    if (newValue.getItemExpr()->isAUserSuppliedInput())
      userInputs_++;
  }
} // VEG::insert()

void VEG::insert(const ValueIdSet & newValues)
{
  for (ValueId exprId = newValues.init();
       newValues.next(exprId);
       newValues.advance(exprId))
  {
    if (NOT eqGroup_.contains(exprId))
    {
      eqGroup_ += exprId;
      if (exprId.getItemExpr()->isAUserSuppliedInput())
        userInputs_++;
    }
  }
} // VEG::insert()

void VEG::merge(const VEG& other)
{
  // Add all members of the other VEG to my own
  eqGroup_ += other.eqGroup_;
  // Fixup the VEGReference and VEGPredicate of the
  // other VEG to reference me instead.
  other.getVEGReference()->replaceVEG(getValueId());
  other.getVEGPredicate()->replaceVEG(getValueId());
  userInputs_ += other.userInputs_;

  if (specialNulls_ && !other.getSpecialNulls())
    specialNulls_ = FALSE;
} // VEG::merge()

Int32 VEG::getArity() const { return 0; }

const NAString VEG::getText() const
{
  if (seenBefore())
  {
    // getenv() calls are costly. avoid especially in release code.
#ifndef NDEBUG
    if (getenv("SIMPLE_VEG_DISPLAY") || getenv("SIMPLE_DISPLAY"))
      return NAString("[...]");
#endif
    return NAString("...");
  }

  markAsSeenBefore();

  NAString result("(",CmpCommon::statementHeap());

  // getenv() calls are costly. avoid especially in release code.
#ifndef NDEBUG
  if (getenv("SIMPLE_VEG_DISPLAY") || getenv("SIMPLE_DISPLAY")) result = "[";
#endif
  NABoolean first = TRUE;

  //char cstrId[TEXT_DISPLAY_LENGTH];

  const ValueIdSet & eqGroup_ = getAllValues();

  for (ValueId x = eqGroup_.init(); eqGroup_.next(x); eqGroup_.advance(x))
  {
    // getenv() calls are costly. avoid especially in release code.
#ifndef NDEBUG
    if (getenv("NO_INDEXCOL_DISPLAY") || getenv("SIMPLE_DISPLAY"))
      if (x.getItemExpr()->getOperatorType() == ITM_INDEXCOLUMN) continue;
#endif

      if (x.getItemExpr()->getOperatorType() == ITM_INDEXCOLUMN) continue;
    if (NOT first)
    {
      result += " = ";
    }
    first = FALSE;
    x.getItemExpr()->unparse(result);
    // add valueId's after pred. name

    // getenv() calls are costly. avoid especially in release code.
#ifndef NDEBUG
    if ( (getenv("SIMPLE_VEG_DISPLAY") || getenv("SIMPLE_DISPLAY")) &&
          x.getItemExpr()->getOperatorType() == ITM_VEG_REFERENCE ) continue;
#endif



  }

  // getenv() calls are costly. avoid especially in release code.
#ifndef NDEBUG
  if (getenv("SIMPLE_VEG_DISPLAY") || getenv("SIMPLE_DISPLAY"))
    result += "]";
#endif
  result += ")";
  markAsNotSeenBefore();
  return result;
}

HashValue VEG::topHash()
{
  HashValue result = ItemExpr::topHash();

  // hash any local data members of the derived class
  result ^= (ValueIdSet &) *this;

  return result;
}

NABoolean VEG::duplicateMatch(const ItemExpr & other) const
{
  if (NOT genericDuplicateMatch(other))
    return FALSE;

  if (getVEGReference()->getVEG() !=
      ((VEG &)other).getVEGReference()->getVEG())
    return FALSE;

  return TRUE;

}

ItemExpr * VEG::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  ABORT("No methods for copying this object yet");

  if (derivedNode == NULL)
    result = new (outHeap) VEG();
  else
    result = derivedNode;

  return ItemExpr::copyTopNode(result, outHeap);
}


void
VEG::getAndExpandAllValues(ValueIdSet& expandedValues) const
{
  // Get all members of VEGRef:
  const ValueIdSet& vegGroup = getAllValues();
  for (ValueId vid = vegGroup.init();
       vegGroup.next(vid);
       vegGroup.advance(vid))
    {
      if (vid.getItemExpr()->getOperatorType() != ITM_VEG_REFERENCE)
         {
          expandedValues.insert(vid);
          continue;
         }

      if ( (vid.getItemExpr()->getOperatorType() == ITM_VEG_REFERENCE) &&
           (! expandedValues.contains(vid))
         )
        {

        // In some cases, a VEGRef might contain another VEGRef within
        // its VEG which recursively self-references the VEGRef.
        // In order to prevent running into an infinite loop there, we
        // insert the vid into the set and remove it after returning
        // from recursive call. (case 10-001201-9972)

          expandedValues.insert(vid);
         ((VEGReference *) (vid.getItemExpr())) -> getVEG() ->
           getAndExpandAllValues(expandedValues);
          expandedValues -=vid;
        }
    }
} // VEG::getAndExpandAllValues(ValueIdSet& expandedValues) const


// return a Constant, hostvar or parameter from this VEG
ValueId VEG::getAConstantHostVarOrParameter() const
{
  for (ValueId id = eqGroup_.init(); eqGroup_.next(id); eqGroup_.advance(id))
  {
    ItemExpr *ie = id.getItemExpr();

    OperatorTypeEnum oper = ie->getOperatorType();

    if ((oper == ITM_CONSTANT)  ||
        (oper == ITM_HOSTVAR)   ||
        (oper == ITM_DYN_PARAM) ||
        (oper == ITM_CACHE_PARAM))
      return id;
  }

  return NULL_VALUE_ID;
}

// return a Constant from this VEG. If includeCacheParam is TRUE, also accept
// the value of a constant parameter.
ValueId VEG::getAConstant(NABoolean includeCacheParam) const
{
  for (ValueId id = eqGroup_.init(); eqGroup_.next(id); eqGroup_.advance(id))
  {
    ItemExpr *ie = id.getItemExpr();

    OperatorTypeEnum oper = ie->getOperatorType();

    if (oper == ITM_CONSTANT)
      return id;
    else if (includeCacheParam && oper == ITM_CACHE_PARAM)
      return (static_cast<ConstantParameter*>(ie))->getConstVal()->getValueId();
  }

  return NULL_VALUE_ID;
}

// -----------------------------------------------------------------------
// member functions for class VEGPredicate
// -----------------------------------------------------------------------

// default selectivity for VEGPredicates (same as equality preds)
double VEGPredicate::defaultSel()
{
  return (1.0/(CURRSTMT_OPTDEFAULTS->defNoStatsUec()) );
}

VEGPredicate::VEGPredicate(const ValueId & ofVEG)
            : ItemExpr(ITM_VEG_PREDICATE)
	    , veg_(ofVEG)
	    , specialNulls_(FALSE) // ++MV - Irena
{
  CMPASSERT (ofVEG.getItemExpr()->getOperatorType() == ITM_VEG);
  synthTypeAndValueId();
}

VEGPredicate::VEGPredicate(const VEGPredicate& vp)
            : ItemExpr(ITM_VEG_PREDICATE)
	    , veg_(vp.veg_)
	    , specialNulls_(vp.specialNulls_)
	    , predsWithSelectivities_(vp.predsWithSelectivities_)
{
  synthTypeAndValueId();
}

VEGPredicate::~VEGPredicate() {}

void VEGPredicate::replaceVEG(const ValueId& vegId)
{
  CMPASSERT(vegId.getItemExpr()->getOperatorType() == ITM_VEG);
  veg_ = vegId;
} // VEGPredicate::replaceVEG()

Int32 VEGPredicate::getArity() const { return 0; }

NABoolean VEGPredicate::isAPredicate() const { return TRUE; }

// ----------------------------------------------------------------------
// Walk through an ItemExpr tree and gather the ValueIds of those
// expressions that behave as if they are "leaves" for the sake of
// the coverage test, e.g., expressions that have no children, or
// aggregate functions, or instantiate null. These are usually values
// that are produced in one "scope" and referenced above that "scope"
// in the dataflow tree for the query.
// ----------------------------------------------------------------------
void VEGPredicate::getLeafValuesForCoverTest(ValueIdSet & leafValues, 
                                             const GroupAttributes& coveringGA,
                                             const ValueIdSet & newExternalInputs) const
{
  leafValues += ((VEGPredicate *)this)->getVEG()->getVEGReference()->getValueId();
} // VEGPredicate::getLeafValuesForCoverTest()

NABoolean VEGPredicate::isCovered(const ValueIdSet& newExternalInputs,
				  const GroupAttributes& coveringGA,
				  ValueIdSet& referencedInputs,
				  ValueIdSet& /* coveredSubExpr*/,
				  ValueIdSet& /* unCoveredExpr*/ ) const
{
  ValueId VEGRefId = getVEG()->getVEGReference()->getValueId();
  ValueIdSet vegMembers = getVEG()->getAllValues();
  NABoolean covered = FALSE;

  // A VEGPredicate is covered if the child can supply the VEGRefId.
  // If the VEGRefId is only supplied by the inputs we want to return false.

  // The VEGRefId will be part of the child's required outputs since
  // the parent needed that to evaluate the VEGPredicate.
  // So simply check if the VEGRefId is part of the required outputs.
  // However, when FileScanRule::nextSubstitute is trying to determine
  // if a index is useful, the required output simply contains the
  // list of indexcol valueId's, and has not been remapped to the
  // VEGRefId's that correspond in that region. So check to see if
  // the indexcol intersects with the VEG members.

  // We cannot call coveringGA.covers() in this case because it will be fooled
  // by the presences of one of the members of the VEG in the required
  // inputs or newExternalInputs.

  if (coveringGA.isCharacteristicOutput(VEGRefId))
    {
      covered = TRUE;
    }
  else
    {
      // Check if a member of the VEG is in the characteristic outputs
      ValueIdSet outputs = coveringGA.getCharacteristicOutputs();
      outputs.intersectSet(vegMembers);
      if (NOT outputs.isEmpty())
        covered = TRUE;
    }

  // If the VEGPredicate is covered we want to include in the
  // characteristic inputs the VEGRefId for the VEG if
  // available
  if (covered)
    {
      // If the VEGPredicate is covered without supplying any
      // new external inputs, indicate which of the given
      // external inputs can help for evaluating this
      // VEGPredicate here.
      if (newExternalInputs.contains(VEGRefId))
        referencedInputs += VEGRefId;
      else
        {
          const NABoolean doNotLookInsideVegReferences = FALSE ;
          const NABoolean doNotLookInsideInstantiateNulls = FALSE ;
          //
          // It is likely that some member of the VEG appears in
          // the external inputs. For example, consider
          //       t1 left join t2 on t1.x = t2.y
          // The VEG will contain (t2.y, ixcol t2.y, VEGRef(t1.x ..))
          //
          // The nested loop join transformation will supply
          // VEGRef(t1.x ..), which belongs to an outer scope, as an
          // external input. Clearly, the latter new external input does
          // not contain the VEGReference for the former VEG. In fact,
          // the reverse situation is true. The case that is sketched
          // in these comments is detected by the code that appears below:
          referencedInputs.accumulateReferencedValues
            (newExternalInputs,
             vegMembers,
             doNotLookInsideVegReferences,
             doNotLookInsideInstantiateNulls);
        }
    } // if (covered)

  // The idea is to push the predicate down only when the tree can
  // produce a member of the VEG. However, we are having too many
  // problems with the above policy. We did not want to push a
  // VEGPredicate down the tree only because the VEG references a
  // constant that is needed in the tree. However, predicates of the
  // form :hv = 10 and other predicates that only reference correlated
  // values need to be pushed to some scan.

  // $$$$ Comments (Dec. 19, 1996)
  // Check whether the predicate should be pushed down by looking at
  // the number of user supplied inputs that are members of the
  // VEG. If the VEGPredicate is not covered because the tree cannot
  // produce a member of the VEG, push it down iff there are at least
  // two user supplied inputs that are members of the VEG. Indeed,
  // this is a kludge that is meant to permit the optimization
  // i.e., evaluating predicates such as :hv =
  // 10 on some scan. However, it has the advantage of eliminating the
  // really dumb behaviour of pushing a predicate down on the strength
  // of supplying a single constant value as an input.

  // The kludge added does not work. Predicates of the form
  // :hv = 10 are not stored in a VEGPred unless there also is a
  // predicate of the form col = :hv. So, all that needs to be handled
  // here are VEGPreds that reference correlated column values but
  // do not reference values supplied by the child's char outputs.
  // For example, 31 = T0.i1, and T0 is not a child.
  else
  {
     // Check if all value ids in the vegMembers set are either
     // user supplied inputs or correlated references (an embedded
     // vegRef must be a correlated reference or it's in an left join
     // ON clause).  If it's in an left join ON clause, this is ok,
     // it just means we may push down the pred to the right child
     // of the left join if the join is a TSJ and the pred only
     // refers to the left child and user inputs. For example,
     // select t0.a from t0 left join t1 on t0.a = 10. The pred
     // t0.a = 10 will get pushed to the right child (t1) if the
     // join is a TSJ. This would not happen without this fix but
     // this should not be a problem as it is legal to push an
     // ON clause pred to the right child of a left join.
     NABoolean allVEGMembersAreInputs = TRUE;
     NABoolean outerReferencesSeen = FALSE;
     NABoolean userSuppliedInputsSeen = FALSE;
     ValueIdSet outerReferences;
     ValueIdSet userSuppliedInputs;
     for (ValueId vid = vegMembers.init();
                        vegMembers.next(vid);
                        vegMembers.advance(vid))
     {
       // Check if the veg member is not a user supplied input or
       // a correlated reference. It is a correlated reference if it
       // is an embedded vegRef or if it is an instantiate null whose
       // child is an embedded vegRef. A instantiate null with an
       // embedded vegRef child represents a correlated reference to
       // the right child output of a left join. 
       
       if (NOT (vid.getItemExpr()->isAUserSuppliedInput() OR
                (vid.getItemExpr()->getOperatorType() == ITM_VEG_REFERENCE) OR
                ((vid.getItemExpr()->getOperatorType() ==
                    ITM_INSTANTIATE_NULL) AND
                 (vid.getItemExpr()->child(0)->getOperatorType() ==
                    ITM_VEG_REFERENCE))
               )
          )
       {
	 // If this column was a host var before binding, we consider it as such
         if (vid.getItemExpr()->previousHostVar())
         {
           allVEGMembersAreInputs = TRUE;
           break;
         }
         allVEGMembersAreInputs = FALSE;
       }

       // check for outer-references in form of embedded veg-references
       if (vid.getItemExpr()->getOperatorType() == ITM_VEG_REFERENCE)
       {
         outerReferencesSeen = TRUE;
         outerReferences +=vid;
       }
       else if (vid.getItemExpr()->isAUserSuppliedInput())
       {
         userSuppliedInputs +=vid;
         userSuppliedInputsSeen = TRUE;
       }
     } // for

     if (outerReferencesSeen &&
         NOT allVEGMembersAreInputs)
     {
       // This VEGPredicate has an outer reference in the VEG Members set.
       // In addition the set also has a NON-UserSuppliedInput such
       // as a base column or an index column (extra columns);
       // We already know that these extra columns are not part of the output
       // (A check is made at the beginning of this routine)
       //  Check if these are part of input and set covered to TRUE only when
       // they are NOT part of characteristic input set
       // CR 10-010314-1732

       if ( newExternalInputs.contains(VEGRefId) &&
            userSuppliedInputsSeen
          )
       {
         // VegMembers contain an user Supplied input and an outer Reference
         ValueIdSet inputset = vegMembers;
         inputset -= outerReferences;
         inputset -= userSuppliedInputs;
         inputset.intersectSet(newExternalInputs);

         if (inputset.isEmpty())
         {
           covered = TRUE;
           referencedInputs += VEGRefId;
         }
       }
     }

     // Allow the predicate to be pushed down if all vegMembers are
     // user supplied inputs or correlated references, and the VEGRef
     // or at least one of it's constiuent parts are covered by the
     // char. inputs.
     if (allVEGMembersAreInputs)
     {
       if (coveringGA.isCharacteristicInput(VEGRefId))
       {
         covered = TRUE;
       }
       if (newExternalInputs.contains(VEGRefId))
       {
         covered = TRUE;
         referencedInputs += VEGRefId;
       }
       if (NOT covered)
       {
         vegMembers.intersectSet(newExternalInputs);
         if (NOT vegMembers.isEmpty())
         {
           covered = TRUE;
           referencedInputs += vegMembers;
         }
       }
     } // end if all veg members are inputs
  } // end if not covered by outputs

  return covered;

} // VEGPredicate::isCovered()

const NAString VEGPredicate::getText() const
{
  char cp[TEXT_DISPLAY_LENGTH];

  // getenv() calls are costly. avoid especially in release code.
#ifndef NDEBUG
  if (getenv("SIMPLE_VEG_DISPLAY") || getenv("SIMPLE_DISPLAY"))
  {
    sprintf(cp,"VP%d",CollIndex(getValueId()));
    return NAString(cp) + veg_.getItemExpr()->getText();
  }
#endif

  //sprintf(cp,"VEGPred_%d(",CollIndex(getValueId()));
  cp[0] = 0;
  return NAString(cp) + veg_.getItemExpr()->getText(); // + ")";
} // VEGPredicate::getText()

// MVs -- 
void VEGPredicate::unparse(NAString &result,
			   PhaseEnum phase,
			   UnparseFormatEnum form,
			   TableDesc * tabId) const
{
  if ((form != MVINFO_FORMAT) &&
      (form != QUERY_FORMAT))
  {
    ItemExpr::unparse(result, phase, form, tabId);
    return;
  }

  const ValueIdList vegMembers(getVEG()->getAllValues());

  CMPASSERT(vegMembers.entries() >=2);
  ValueIdList copyList;  

  CollIndex startIndex;
  if (form == QUERY_FORMAT || form == MVINFO_FORMAT)
    startIndex = 0;
  else 
    startIndex = 1;

  ValueId  nextMemberId;
  for (CollIndex i=startIndex; i<vegMembers.entries(); i++)
  {
    nextMemberId = vegMembers[i];
    ItemExpr *nextExpr = nextMemberId.getItemExpr();
    if (nextExpr->getOperatorType() == ITM_INDEXCOLUMN)
      continue;
    if ((form == QUERY_FORMAT) &&
        (nextExpr->getOperatorType() == ITM_BASECOLUMN))
    {
      BaseColumn * bs = (BaseColumn *)nextExpr;
      if (bs->getTableDesc() != tabId && form != MVINFO_FORMAT)
        continue;
    }  
    copyList.insert(vegMembers[i]);
  }  

  if (copyList.entries() < 2) 
    return;

  ValueId  firstMemberId = copyList[0];
  NAString firstMemberText;
  firstMemberId.getItemExpr()->unparse(firstMemberText, phase, form, tabId);

  NAString nextMemberText("empty");
  for (CollIndex i=1; i<copyList.entries(); i++)
  {
    nextMemberId = copyList[i];

    // If this is not the first predicate, "AND" between predicates.
    if (nextMemberText != "empty")
      result += " AND ";

    nextMemberText = "";
    nextMemberId.getItemExpr()->unparse(nextMemberText, phase, form, tabId);

    result += firstMemberText;
    result += " = ";
    result += nextMemberText;
  }
}

HashValue VEGPredicate::topHash()
{
  HashValue result = ItemExpr::topHash();

  // hash any local data members of the derived class
  result ^= getVEG()->topHash();

  return result;
} // VEGPredicate::topHash()

NABoolean VEGPredicate::duplicateMatch(const ItemExpr & other) const
{
  if (NOT genericDuplicateMatch(other))
    return FALSE;

  // compare any local data members of the derived class
  // and return FALSE if they don't match
  if (veg_ != ((VEGPredicate &)other).veg_)
    return FALSE;

  return TRUE;
} // VEGPredicate::duplicateMatch()

ItemExpr * VEGPredicate::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result = NULL;

  if (derivedNode == NULL)
    //ABORT("No methods for copying this object yet");
    result = new VEGPredicate(*this);
  else
    result = derivedNode;

  return ItemExpr::copyTopNode(result, outHeap);
} // VEGPredicate::copyTopNode()

// -----------------------------------------------------------------------
// member functions for class VEGReference
// -----------------------------------------------------------------------
VEGReference::VEGReference(const ValueId & ofVEG)
            : ItemExpr(ITM_VEG_REFERENCE), veg_(ofVEG)
{
  CMPASSERT (ofVEG.getItemExpr()->getOperatorType() == ITM_VEG);
  allocValueId();
}

VEGReference::~VEGReference() {}

Int32 VEGReference::getArity() const { return 0; }

void VEGReference::replaceVEG(const ValueId& vegId)
{
  CMPASSERT(vegId.getItemExpr()->getOperatorType() == ITM_VEG);
  veg_ = vegId;
} // VEGReference::replaceVEG()

NABoolean VEGReference::isCovered(const ValueIdSet& newExternalInputs,
				  const GroupAttributes& coveringGA,
				  ValueIdSet& referencedInputs,
				  ValueIdSet& coveredSubExpr,
				  ValueIdSet& unCoveredExpr ) const
{
  // If we arrive here to check whether a VEGReference isCovered(),
  // it means that this VEGReference does not belong to the
  // Characteristic Inputs and Outputs. (Otherwise, the test in
  // covers() would have detected its presence.)
  // Walk through all the members of the set in order to return an
  // indication of which values are referenced inputs, which values
  // are covered sub expressions and which of them are uncovered expr.

  NABoolean retVal = FALSE;

  VEG *veg = getVEG();

  if (veg->seenBefore())
    return FALSE;

  // Remember valueId of the VEGReference that we've already seen.
  veg->markAsSeenBefore();

  for (ValueId x = veg->getAllValues().init();
                   veg->getAllValues().next(x);
                   veg->getAllValues().advance(x))
  {
    // I am covered if ANY ONE of my candidate values is covered
    if (coveringGA.covers(x, newExternalInputs, referencedInputs,
                          &coveredSubExpr, &unCoveredExpr))
    {
      retVal = TRUE;
      break;
    }
  }

  veg->markAsNotSeenBefore();
  return retVal;

} // VEGReference::isCovered()

OrderComparison VEGReference::sameOrder(ItemExpr * other,
					NABoolean /*askOther*/)
{
  // first, check whether the item expressions are identical
  if (this == other)
    return SAME_ORDER;

  // We can have circular VegRefs like :
  // VEGRef_285(TAB4.SSTUTKYOKI = VEGRef_310(TAB9.TKYOKI = VEGRef_285(..)))
  // In this case, sameOrder()will go into infinite loop (soln 10-110911-7326).
  // Not sure why we ended up constructing circular VegRefs in the first place,
  // but ItemExpr::referencesTheGivenValue() code indicates it's possible
  // and handles by marking Vegrefs as seen before and back out if VegRef is
  // being seen second time. Same logic is also used here as explained below:
  // 1. if VegRef has not seen before, mark it as seen before, also remember it.
  // 2. for every veg member who is of type vegreference and seen before,
  //    do not call sameOrder() again.
  // 3. if this method has called markAsSeenBefore(), then call
  //    markAsNotSeenBefore()
  NABoolean callNotSeen = FALSE;
  VEG *veg = getVEG();
  // step 1
  if (!veg->seenBefore())
  {
    veg->markAsSeenBefore();
    callNotSeen = TRUE;
  }

  // VEGReferences can be used for ordering comparison under the
  // assumption that all comparison predicates that can be applied
  // actually have been applied. For example, if we want "order by t1.x"
  // and t1.x is in a VEG with t2.y, then we can use an existing
  // order t2.y if we can assume that t1.x has already been compared
  // with t2.y. Note that we want order t1.x we should have t1.x
  // available at that time.
  const ValueIdSet &equivValues = getVEG()->getAllValues();
  OrderComparison result = DIFFERENT_ORDER;

  for (ValueId x = equivValues.init();
       equivValues.next(x) AND result == DIFFERENT_ORDER;
       equivValues.advance(x))
    {
      if((x.getItemExpr()->getOperatorType()) == ITM_VEG_REFERENCE)
      {
        // step 2
        VEG *innerVeg = ((VEGReference *)x.getItemExpr())->getVEG();
        if (!innerVeg->seenBefore())
          result = x.getItemExpr()->sameOrder(other,TRUE);
      }
      else
        result = x.getItemExpr()->sameOrder(other,TRUE);
    }

  // step 3
  if (callNotSeen)
    veg->markAsNotSeenBefore();

  return result;
}

// ----------------------------------------------------------------------
// Walk through members of VegReference and verify if any member of this
// VegReference, which is of TYPE ITM_VEG_REFERENCE contains passed
// argument. Also dig deep inside all ITM_VEG_REFERENCE objects to avoid
// circular vegRefences like :
// VEGRef_285((T4.SSTUTKYOKI = VEGRef_310((T9.TKYOKI = VEGRef_285(...))))
// This method gets called from VEGRegion::replaceVEGMember() and fixes
// bug QC_1348
// ----------------------------------------------------------------------
NABoolean VEGReference::referencesVegRefValue(ValueId& ofVegRef)
{
  // Get all members of VEGRef:
  const ValueIdSet &vegGroup = getVEG()->getAllValues();
  VEG *oldVEGPtr = ((VEGReference *)ofVegRef.getItemExpr())->getVEG();
  for (ValueId vid = vegGroup.init(); vegGroup.next(vid); vegGroup.advance(vid))
  {
    if (vid.getItemExpr()->getOperatorType() == ITM_VEG_REFERENCE)
    {
      VEG *newVEGPtr = ((VEGReference *) (vid.getItemExpr()))->getVEG();
      if (newVEGPtr == oldVEGPtr)
        return TRUE;
      else
        return ((VEGReference *) (vid.getItemExpr()))->referencesVegRefValue(ofVegRef);
    }
  }
  return FALSE;

}


const NAString VEGReference::getText() const
{
  char cp[TEXT_DISPLAY_LENGTH];
  sprintf(cp,"VEGRef_%d(",CollIndex(getValueId()));

  // getenv() calls are costly. avoid especially in release code.
#ifndef NDEBUG
  NABoolean simpleDisplay = FALSE;
  simpleDisplay = getenv("SIMPLE_VEG_DISPLAY") || getenv("SIMPLE_DISPLAY");
  if (simpleDisplay)
    sprintf(cp,"VR%d",CollIndex(getValueId()));
#endif
  NAString x(NAString(cp, CmpCommon::statementHeap())+
              veg_.getItemExpr()->getText(),
            CmpCommon::statementHeap());
  x += ")";
#ifndef NDEBUG
  if (simpleDisplay)
    x.remove(x.length()-1);
#endif
  return x;
} // VEGReference::getText()

void VEGReference::unparse(NAString &result,
			   PhaseEnum phase,
			   UnparseFormatEnum form,
			   TableDesc * tabId) const
{
  if ((form == EXPLAIN_FORMAT) || (form == MVINFO_FORMAT) ||
       (form == QUERY_FORMAT))
    {
      // End users won't know what a VegReference is, and
      // most items in EXPLAIN are already rewritten w/o VEGies.
      // Generate equiv(col) where col is the unparsed text
      // of some VEG member.

      /*if (form == EXPLAIN_FORMAT)
	result += "equiv(";
      */
      const ValueIdSet &vegMembers =
	((VEG *) veg_.getItemExpr())->getAllValues();

      for (ValueId someMemberId = vegMembers.init();
	   vegMembers.next(someMemberId);
	   vegMembers.advance(someMemberId))
        {
	  ItemExpr * someMemberExpr = someMemberId.getItemExpr();
	  if (form == QUERY_FORMAT)
	  {
	    // for QUERY_FORMAT, unparse the VEG member that belongs to the
	    // given tableDesc
	    if ((someMemberExpr->getOperatorType() == ITM_BASECOLUMN) &&
	        (((BaseColumn *)someMemberExpr)->getTableDesc() == tabId) ||
                 (CmpCommon::getDefault(MVQR_LOG_QUERY_DESCRIPTORS) == DF_DUMP_MV))
	    {
		someMemberExpr->unparse(result, phase, form, tabId);
		break;
	    }
	    else
	      continue;
	  }
	  else
	  {
	    // if not QUERY_FORMAT, unparse the first veg member
            someMemberExpr->unparse(result,phase,form);
	    break;
	  }
        }
      /*
      if (form == EXPLAIN_FORMAT)
        result += ") ";
	*/
    }
  else
    {
      result += getText();
    }
}

HashValue VEGReference::topHash()
{
  HashValue result = ItemExpr::topHash();

  // hash any local data members of the derived class
  result ^= getVEG()->topHash();

  return result;
} // VEGReference::topHash()

NABoolean VEGReference::duplicateMatch(const ItemExpr & other) const
{
  if (NOT genericDuplicateMatch(other))
    return FALSE;

  // compare any local data members of the derived class
  // and return FALSE if they don't match
  if (veg_ != ((VEGReference &)other).veg_)
    return FALSE;

  return TRUE;
} // VEGReference::duplicateMatch()

ItemExpr * VEGReference::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result = NULL;

  if (derivedNode == NULL)
    //ABORT("No methods for copying this object yet");
    result = new (outHeap) VEGReference(getVEG()->getValueId());
  else
    result = derivedNode;

  return ItemExpr::copyTopNode(result, outHeap);
} // VEGReference::copyTopNode()

QR::ExprElement VEGReference::getQRExprElem() const
{
  return QR::QRColumnElem;
}

// -----------------------------------------------------------------------
// member functions for class CheckConstraint
// -----------------------------------------------------------------------
Int32 CheckConstraint::getArity() const { return 0;}

ItemExpr * CheckConstraint::copyTopNode(ItemExpr *derivedNode,
					CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) CheckConstraint(*this, outHeap);
  else
    result = derivedNode;

  return ItemExpr::copyTopNode(result, outHeap);
}

const NAString CheckConstraint::getText() const
{
  return "CheckConstraint";
}

void CheckConstraint::unparse(NAString &result,
			     PhaseEnum /* phase */,
			     UnparseFormatEnum /* form */,
			     TableDesc * tabId) const
{
  result += getText();
  result += "(";
  result += getConstraintName().getQualifiedNameAsAnsiString();
  result += ")";
}

// -----------------------------------------------------------------------
// member functions for class OptConstraint
// -----------------------------------------------------------------------
ItemExpr * OptConstraint::copyTopNode(ItemExpr *derivedNode,
				      CollHeap* outHeap)
{
  return ItemExpr::copyTopNode(derivedNode, outHeap);
}

// -----------------------------------------------------------------------
// member functions for class CardConstraint
// -----------------------------------------------------------------------
Int32 CardConstraint::getArity() const { return 0;}

ItemExpr * CardConstraint::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) CardConstraint(lowerBound_,upperBound_);
  else
    result = derivedNode;

  return OptConstraint::copyTopNode(result, outHeap);
}

const NAString CardConstraint::getText() const
{
  return "CardConstraint";
}

void CardConstraint::unparse(NAString &result,
			     PhaseEnum /* phase */,
			     UnparseFormatEnum /* form */,
			     TableDesc * tabId) const
{
  char ascii[TEXT_DISPLAY_LENGTH];

  sprintf(ascii,"CardConstraint(%g,%g)",lowerBound_,upperBound_);
  result += ascii;
}

// -----------------------------------------------------------------------
// member functions for class UniqueOptConstraint
// -----------------------------------------------------------------------
Int32 UniqueOptConstraint::getArity() const { return 0;}

ItemExpr * UniqueOptConstraint::copyTopNode(ItemExpr *derivedNode,
					    CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) UniqueOptConstraint(uniqueCols_);
  else
    result = derivedNode;

  return OptConstraint::copyTopNode(result, outHeap);
}

const NAString UniqueOptConstraint::getText() const
{
  return "UniqueOptConstraint";
}

void UniqueOptConstraint::unparse(NAString &result,
				  PhaseEnum phase,
				  UnparseFormatEnum form,
				  TableDesc * tabId) const
{
  result += "UniqueOptConstraint";
  uniqueCols_.unparse(result,phase,form);
}

// -----------------------------------------------------------------------
// member functions for class FuncDependencyConstraint
// -----------------------------------------------------------------------
Int32 FuncDependencyConstraint::getArity() const
{
  return 0;
}

ItemExpr * FuncDependencyConstraint::copyTopNode(ItemExpr *derivedNode,
						 CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) FuncDependencyConstraint(determiningCols_,
						    dependentCols_);
  else
    result = derivedNode;

  return OptConstraint::copyTopNode(result, outHeap);
}

void FuncDependencyConstraint::synthFunctionalDependenciesFromChild(
     GroupAttributes &ga,
     const RelExpr *child,
     NABoolean createNewDependencies)
{
  const ValueIdSet & childConstraints =
    child->getGroupAttr()->getConstraints();
  ValueIdSet vegColsFromChild(child->getGroupAttr()->
			      getCharacteristicOutputs());

  // For now we want to maintain only VEGReferences as the dependent
  // columns. This is mainly done to avoid unusual situations
  // (monkeys at the keyboard) that might lead to errors. Restricting
  // functional dependencies to VEGRefs should still cover the majority
  // of all interesting situations.
  if (createNewDependencies)
    {
      for (ValueId co = vegColsFromChild.init();
	   vegColsFromChild.next(co);
	   vegColsFromChild.advance(co))
	{
	  if (co.getItemExpr()->getOperatorType() != ITM_VEG_REFERENCE)
	    vegColsFromChild -= co;
	}
    }

  // walk through the child constraints
  for (ValueId cx = childConstraints.init();
       childConstraints.next(cx);
       childConstraints.advance(cx))
    {
      ItemExpr *c = cx.getItemExpr();
      OperatorTypeEnum optype = c->getOperatorType();

      if (optype == ITM_UNIQUE_OPT_CONSTRAINT AND
	  createNewDependencies AND
	  NOT vegColsFromChild.isEmpty())
	{
	  UniqueOptConstraint *uc = ((UniqueOptConstraint *)c);

	  // Try to find unique columns in the child that are no longer
	  // unique in the parent. For each such uniqueness constraint,
	  // add a functional dependency constraint if the unique columns
	  // are visible to the parent.

	  // NOTE: At some later point we should consider taking out
	  // the check on the characteristic outputs, since it may
	  // suppress some interesting constraints (we don't check
	  // uniqueness constraints for being covered by char. outputs either)
	  // Example: select a from t1 join t2 may get
	  // different uniqueness constraints (and cardinality estimates)
	  // than select * from t1 join t2.

	  if (NOT ga.isUnique(uc->uniqueCols()) &&
	      child->getGroupAttr()->getCharacteristicOutputs().contains(
		   uc->uniqueCols()))
	    {
	      // yes, found unique columns that are visible to the parent,
	      // now check whether all unique columns are VEGRefs
	      // (sorry, we only consider those for now)
	      NABoolean NonVEGFound = FALSE;

	      for (ValueId ux=uc->uniqueCols().init();
		   uc->uniqueCols().next(ux);
		   uc->uniqueCols().advance(ux))
		if (ux.getItemExpr()->getOperatorType() != ITM_VEG_REFERENCE)
		  NonVEGFound = TRUE;

	      if (NOT NonVEGFound)
		{
		  ValueIdSet myDependentCols(vegColsFromChild);

		  // remove the unique columns from the dependent columns
		  // (don't want functional dependencies like A --> A)
		  myDependentCols -= uc->uniqueCols();

		  if (NOT myDependentCols.isEmpty())
		    {
		      FuncDependencyConstraint *nc =
			new(CmpCommon::statementHeap())
			FuncDependencyConstraint(uc->uniqueCols(),
						 myDependentCols);
		      ga.addConstraint(nc);
		    }
		}
	    }
	}
      else if (optype == ITM_FUNC_DEPEND_CONSTRAINT)
	{
	  // Found a functional dependency in the child constraints.
	  // Copy it if the determining columns are visible in the
	  // parent node.
	  FuncDependencyConstraint *fd = (FuncDependencyConstraint *) c;

	  // NOTE: At some later point we should consider taking out
	  // the check on the characteristic outputs (same as above).

	  if (child->getGroupAttr()->getCharacteristicOutputs().contains(
		   fd->getDeterminingCols()))
	    {
	      ga.addConstraint(c);
	    }
	}
    }
}

void FuncDependencyConstraint::minimizeUniqueCols(ValueIdSet &uniqueCols)
{
  if (uniqueCols.contains(determiningCols_))
    {
      // We know now that the uniqueCols determine our "dependentCols_".

      // As an example, let's assume that uniqueCols is (a,b,c,d),
      // determiningCols_ is (a,b), and dependentCols_ is (c).

      // If columns (a,b) determine (c), then it is true that if
      // (a,b,c) is unique then (a,b) is unique as well. This is
      // because the definition of functional dependency says that
      // there will never be two rows with the same (a,b) values that
      // have different (c) values.

      // The extra column (d) in the example does not invalidate this
      // argument.

      // at this point we only use simple ValueId operations, no
      // cover test methods for checks like "does (a,b) determine (a+c+2)?"

      // Could assert here that the intersection of determiningCols_ and
      // dependentCols_ is empty (more precisely: that the dependent columns
      // don't cover any of the unique columns, but we don't have the
      // necessary information to check this here). See method
      // FuncDependencyConstraint::createFunctionalDependenciesFromChild()
      // above for where this constraint is enforced.

      uniqueCols.subtractSet(dependentCols_);
    }
}

const NAString FuncDependencyConstraint::getText() const
{
  return "FuncDependencyConstraint";
}

void FuncDependencyConstraint::unparse(NAString &result,
				       PhaseEnum phase,
				       UnparseFormatEnum form,
				       TableDesc * tabId) const
{
  // use EXPLAIN format since we only talk about VEGRefs and
  // one member should be sufficient to represent the VEG
  result += "FuncDependencyConstraint(";
  determiningCols_.unparse(result,phase,EXPLAIN_FORMAT);
  result += " ---> ";
  dependentCols_.unparse(result,phase,EXPLAIN_FORMAT);
  result += ")";
}


// -----------------------------------------------------------------------
// member functions for class CheckOptConstraint
// -----------------------------------------------------------------------
CheckOptConstraint::~CheckOptConstraint() {}

Int32 CheckOptConstraint::getArity() const { return 0; }

ItemExpr * CheckOptConstraint::copyTopNode(ItemExpr *derivedNode,
                                           CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) CheckOptConstraint(checkPreds_);
  else
    result = derivedNode;

  return OptConstraint::copyTopNode(result, outHeap);
}

const NAString CheckOptConstraint::getText() const
{
  return "CheckOptConstraint";
}

void CheckOptConstraint::unparse(NAString &result,
                                 PhaseEnum phase,
                                 UnparseFormatEnum form,
                                 TableDesc * tabId) const
{
  result += "CheckOptConstraint";
  checkPreds_.unparse(result,phase,form);
}

// -----------------------------------------------------------------------
// member functions for class RefOptConstraint
// -----------------------------------------------------------------------
Int32 RefOptConstraint::getArity() const { return 0;}

ItemExpr * RefOptConstraint::copyTopNode(ItemExpr *derivedNode,
					    CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL) 
  {
    result = new (outHeap) RefOptConstraint(fkCols_, uniqueConstraintName_);
    ((RefOptConstraint*)result)->isMatched_ = isMatched_ ;
  }
  else
    result = derivedNode;

  return OptConstraint::copyTopNode(result, outHeap);
}

const NAString RefOptConstraint::getText() const
{
  return "RefOptConstraint";
}

void RefOptConstraint::unparse(NAString &result,
				  PhaseEnum phase,
				  UnparseFormatEnum form,
				  TableDesc * tabId) const
{
  result += "RefOptConstraint";
  fkCols_.unparse(result,phase,form);
  result += "(";
  result += uniqueConstraintName().getQualifiedNameAsAnsiString();
  result += ")";
}

// -----------------------------------------------------------------------
// member functions for class ComplementaryRefOptConstraint
// -----------------------------------------------------------------------
Int32 ComplementaryRefOptConstraint::getArity() const { return 0;}

ItemExpr * ComplementaryRefOptConstraint::copyTopNode(ItemExpr *derivedNode,
					    CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) ComplementaryRefOptConstraint(ucCols_, 
	    constraintName_, tabPtr_, tabDesc_, NULL, isMatchedForElimination_);
  else
    result = derivedNode;

  return OptConstraint::copyTopNode(result, outHeap);
}

const NAString ComplementaryRefOptConstraint::getText() const
{
  return "ComplementaryRefOptConstraint";
}

void ComplementaryRefOptConstraint::unparse(NAString &result,
				  PhaseEnum phase,
				  UnparseFormatEnum form,
				  TableDesc * tabId) const
{
  result += "ComplementaryRefOptConstraint";
  ucCols_.unparse(result,phase,form);
  result += "(";
  result += constraintName().getQualifiedNameAsAnsiString();
  result += ")";
}

// -----------------------------------------------------------------------
// member functions for class Aggregate
// -----------------------------------------------------------------------
Aggregate::~Aggregate() {}

NABoolean Aggregate::isAnAggregate() const { return TRUE; }

NABoolean Aggregate::containsAnAggregate() const { return TRUE; }

Int32 Aggregate::getArity() const
{
  // ##Should be same as Function::getNumChildren(), except added CMPASSERT here
  // (aggregates must have at least one child; stddev/variance can have more).

  if (!child(1)) return 1;	// most aggs have 1 child
  CMPASSERT(!child(2));		// no aggs have 3+ children
  return 2;			// STDDEV/VARIANCE may have 1 or 2
}

NABoolean Aggregate::operator== (const ItemExpr& other) const	// virtual meth
{
  if (ItemExpr::operator==(other)) return TRUE;

  if (getOperatorType() != other.getOperatorType()) return FALSE;

  const Aggregate &otherAgg = (const Aggregate &)other;

  if (getOperatorType() == ITM_MIN || getOperatorType() == ITM_MAX)
    {
      // Min/Max are order-sensitive
      ItemExprList arglist0(child(0), NULL);
      ItemExprList arglist1(otherAgg.child(0), NULL);
      if (arglist0.entries() != arglist1.entries()) return FALSE;
      for (CollIndex i = arglist0.entries(); i--; )
        if (arglist0[i] != arglist1[i]) return FALSE;
    }
  else
    {
      ValueIdSet argset0, argset1;
      child(0)->convertToValueIdSet(argset0, NULL, ITM_ITEM_LIST);
      otherAgg.child(0)->convertToValueIdSet(argset1, NULL, ITM_ITEM_LIST);
      if (argset0 != argset1) return FALSE;
    }

  return TRUE;
}

NABoolean Aggregate::duplicateMatch(const ItemExpr& other) const
{
  if (NOT genericDuplicateMatch(other))
    return FALSE;

  const Aggregate &ag = (Aggregate &)other;

  if (isDistinct_ != ag.isDistinct_)
    return FALSE;

  if (NOT isSensitiveToDuplicates())
    return FALSE;

  return TRUE;
}

NABoolean Aggregate::isCovered
                      (const ValueIdSet& newExternalInputs,
		       const GroupAttributes& coveringGA,
		       ValueIdSet& referencedInputs,
		       ValueIdSet& coveredSubExpr,
		       ValueIdSet& /*unCoveredExpr*/ ) const
{
  // ---------------------------------------------------------------------
  // If the operand of the aggregate isCovered(), then return its ValueId
  // in coveredSubExpr.
  // ---------------------------------------------------------------------
  ValueIdSet localSubExpr;
  for (Lng32 i = 0; i < (Lng32)getArity(); i++)
    {
      if ( coveringGA.covers(child(i)->getValueId(),
			     newExternalInputs,
			     referencedInputs,
			     &localSubExpr) )
	{
	  coveredSubExpr += child(i)->getValueId();
	}
    }

  // ---------------------------------------------------------------------
  // An aggregate function is coerced to fail the coverage test even
  // when its operand isCovered(). This is because the computation of
  // the aggregate function requires "raw" values produced by its
  // operand to be grouped. The aggregated values cannot be treated
  // in the same manner as the constituent raw values.
  // ---------------------------------------------------------------------
  return FALSE;  // sorry, i am a special case

} // Aggregate::isCovered()

// ----------------------------------------------------------------------
// Walk through an ItemExpr tree and gather the ValueIds of those
// expressions that behave as if they are "leaves" for the sake of
// the coverage test, e.g., expressions that have no children, or
// aggregate functions, or instantiate null. These are usually values
// that are produced in one "scope" and referenced above that "scope"
// in the dataflow tree for the query.
// ----------------------------------------------------------------------
void Aggregate::getLeafValuesForCoverTest(ValueIdSet & leafValues, 
                                          const GroupAttributes& coveringGA,
                                          const ValueIdSet & newExternalInputs) const
{
  leafValues += getValueId();
} // Aggregate::getLeafValuesForCoverTest()

const NAString Aggregate::getText() const
{
  NAString result(CmpCommon::statementHeap());
  NABoolean dumpMvMode = (CmpCommon::getDefault(MVQR_LOG_QUERY_DESCRIPTORS) == DF_DUMP_MV);

  switch (getOperatorType())
    {
    case ITM_AVG:
      result = "avg";
      break;
    case ITM_MAX:
      result = "max";
      break;
    case ITM_MIN:
      result = "min";
      break;
    case ITM_SUM:
      result = "sum";
      break;
    case ITM_COUNT:
      result = "count";
      break;
    case ITM_COUNT_NONULL:
      if (dumpMvMode)
        result = "count";
      else
        result = "count_nonull";
      break;
    case ITM_GROUPING:
      result = "grouping";
      break;
    case ITM_ONE_ROW:
      result = "one_Row";
      break;
    case ITM_ONE_TRUE:
      result = "oneTrue";
      break;
    case ITM_ANY_TRUE:
      result = "anytrue";
      break;
    case ITM_ANY_TRUE_MAX:
      result = "anytruemax";
      break;
    case ITM_STDDEV:
      result = "stddev";
      break;
    case ITM_VARIANCE:
      result = "variance";
      break;
    case ITM_ONEROW:
      result = "oneRow";
      break;
    case ITM_PIVOT_GROUP:
      result = "pivot_group";
      break;
    default:
      result = "unknown aggr";
      break;
    } // switch

  if (isDistinct_ && !dumpMvMode) {
    result += " distinct";
    if (distinctId_ != NULL_VALUE_ID) {
      char buf[13]; // CollIndex is UInt32 with a max value of 4,294,967,295
                    // We need 10 + 2 + 1=13 bytes to store all possible
                    // values.
      snprintf(buf, sizeof(buf), "(%u)", (CollIndex)distinctId_);
      result += buf;
      // ## Perhaps a better way of displaying this would instead be:
      //	result += "(";
      //	result += distinctId_.getItemExpr()->getText();
      //	result += ")";
    }
  }

  return result;
} // Aggregate::getText()

void Aggregate::unparse(NAString &result,
			PhaseEnum phase,
			UnparseFormatEnum form,
			TableDesc * tabId) const
{
  if (form == USER_FORMAT_DELUXE)
    {
      Aggregate *ncThis = (Aggregate *)this;		// cast away constness!

      OperatorTypeEnum saveType  = getOperatorType();	// save
      ItemExpr        *saveChild = child(0);
      ValueId	       saveVid   = getOriginalChild()->getValueId();

      getOriginalChild()->setValueId(NULL_VALUE_ID);	// BEFORE setChild()!
      ncThis->setOperatorType(origOpType());		// set to "orig"
      ncThis->setChild(0, getOriginalChild());

      ItemExpr::unparse(result,phase, form, tabId);		// invoke superclass

      getOriginalChild()->setValueId(saveVid);		// BEFORE setChild()!
      ncThis->setOperatorType(saveType);		// restore
      ncThis->setChild(0, saveChild);
    }
  else
  {
    if ((CmpCommon::getDefault(MVQR_LOG_QUERY_DESCRIPTORS) == DF_DUMP_MV) && isDistinct_)
    {
      // Fix DISTINCT to be parsable.
      result += getText();
      result += "( DISTINCT ";
      child(0)->unparse(result, phase, form, tabId);
      result += ")";
    }
    else
      ItemExpr::unparse(result, phase, form, tabId);	// invoke our superclass method
  }
} // Aggregate::unparse()

ItemExpr * Aggregate::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  Aggregate *result;

  if (derivedNode == NULL)
    result = new (outHeap) Aggregate(getOperatorType());
  else
    result = (Aggregate *) derivedNode;

  if (inScalarGroupBy())
    result->setInScalarGroupBy();

  if (topPartOfAggr())
    result->setTopPartOfAggr();

  result->origChild_ = origChild_;
  result->isDistinct_ = isDistinct_;
  result->inScalarGroupBy_ = inScalarGroupBy_;
  result->distinctId_ = distinctId_;

  // Copy OLAP Window Function information.
  //
  result->isOLAP_ = isOLAP_;

  result->olapPartitionBy_ = (olapPartitionBy_ ? 
                              olapPartitionBy_->copyTree(outHeap) :
                              NULL);

  result->olapOrderBy_ = (olapOrderBy_ ?
                          olapOrderBy_->copyTree(outHeap) : 
                          NULL);

  result->frameStart_ = frameStart_;
  result->frameEnd_ = frameEnd_;

  result->rollupGroupIndex_ = rollupGroupIndex_;

  return ItemExpr::copyTopNode(result, outHeap);
}

// One heck of an implementation for a virtual function!
NABoolean Aggregate::isSensitiveToDuplicates() const
{
  switch (getOperatorType())
    {
    case ITM_MAX:
    case ITM_MIN:
    case ITM_ANY_TRUE:
    case ITM_ONE_TRUE:
    case ITM_GROUPING:
      return FALSE;

    case ITM_SUM:
    case ITM_COUNT:
    case ITM_COUNT_NONULL:
    case ITM_ONE_ROW:
    case ITM_ONEROW:
    case ITM_AVG:
    default:
      return TRUE;
    } // switch
}

// Another hack of an implementation for a virtual function!!
NABoolean Aggregate::evaluationCanBeStaged() const
{
  switch (getOperatorType())
    {
    case ITM_ONE_ROW:
      // See Aggregate::rewriteForStagedEvaluation()
      return FALSE;

    default:
      return TRUE;
    } // switch
}

ItemExpr * Aggregate::rewriteForElimination()
{
  // rewrite the aggregate function to return the result it would have
  // returned if it were called on a group with exactly one member

  // NOTE: this method doesn't delete the existing aggregate node, but
  // it may reuse some of the children of the original expression.

  ItemExpr *result = NULL;

  switch (getOperatorType())
    {
    case ITM_AVG:
    case ITM_MAX:
    case ITM_MIN:
    case ITM_SUM:
    case ITM_ONEROW:
    case ITM_ANY_TRUE:
    case ITM_PIVOT_GROUP:
      // return the value of the aggregate function's argument
      result = child(0);
      break;

    case ITM_COUNT:
      // the count of a single value is always 1
      result = new (CmpCommon::statementHeap()) SystemLiteral(1);
      break;

    case ITM_COUNT_NONULL:
      if (child(0)->getValueId().getType().supportsSQLnullLogical())
      {
        // generate a CASE expression: CASE WHEN arg IS NOT NULL THEN 1 ELSE 0
        result = new (CmpCommon::statementHeap())
	  Case(NULL,
	       new (CmpCommon::statementHeap())
	       IfThenElse(new (CmpCommon::statementHeap())
			  UnLogic(ITM_IS_NOT_NULL,
				  child(0)),
			  new (CmpCommon::statementHeap()) SystemLiteral(1),
			  new (CmpCommon::statementHeap()) SystemLiteral(0)));
      }
      else
      {
        result = new (CmpCommon::statementHeap()) SystemLiteral(1);
      }
      break;

    case ITM_ONE_TRUE:
      // return TRUE only if the argument is TRUE, FALSE otherwise
      result = new (CmpCommon::statementHeap()) UnLogic(ITM_IS_TRUE,child(0));
      break;

    default:
      ABORT("unknown aggregate function encountered");
    }

  result->synthTypeAndValueId();
  return result;
}

ItemExpr * Aggregate::rewriteForStagedEvaluation(ValueIdList &initialAggrs,
						 ValueIdList &finalAggrs,
						 NABoolean sameFormat)
{
  // Split the aggregate function into three parts: the initial part is
  // executed in multiple groupby nodes whose results are sent to a
  // single, "final" groupby node that executes the final aggregate expression.
  // More than one aggregate function may be evaluated in the initial and/or
  // final nodes, therefore a set parameter is used. The return value is
  // an item expression equivalent to the original expression "this". The
  // return value is not necessarily an aggregate function, while
  // initialAggr and finalAggr contain only aggregate functions.

  // NOTE: this method doesn't delete the existing aggregate node, and it
  // produces new value ids for all three parts returned.

  ItemExpr *result = NULL;
  Aggregate *partial;
  Aggregate *sumOfCounts;
  Aggregate *sumOfSums;

  switch (getOperatorType())
    {
    case ITM_AVG:
      assert(NOT sameFormat);

      // divide the sum of sums by the sum of counts, but return NULL
      // if the sum of counts is zero
      // in pseudo-SQL, that sounds like transforming avg(x) into:
      // CASE WHEN SUM(COUNT(x)) > 0 THEN SUM(SUM(x)) / SUM(COUNT(x))
      //      ELSE NULL

      sumOfCounts = new (CmpCommon::statementHeap())
	Aggregate(ITM_SUM,
		  new (CmpCommon::statementHeap()) Aggregate(ITM_COUNT_NONULL,
							    child(0)));
      partial = new (CmpCommon::statementHeap())
                     Aggregate(ITM_SUM, child(0));

      sumOfSums = new (CmpCommon::statementHeap())
	               Aggregate(ITM_SUM, partial);

      if (inScalarGroupBy())
      {
        partial->setInScalarGroupBy();
        sumOfSums->setInScalarGroupBy();
        sumOfCounts->setInScalarGroupBy();
        ((Aggregate *)(sumOfCounts->child(0).getPtr()))->setInScalarGroupBy();
      }

      // The sum of the counts cannot be zero if the binder typed the
      // avg as non-nullable.
      // An AVG on a non scalar group by on a non-nullable
      // expression is always non-nullable, the sum(sum(x)) is always
      // non-nullable and the sum(count(x)) is always > 0

      if (getValueId().getType().supportsSQLnullLogical())
      {
        result = new (CmpCommon::statementHeap())
	  Case(NULL,
	       new (CmpCommon::statementHeap())
	       IfThenElse(
			  new (CmpCommon::statementHeap())
			  BiRelat(ITM_GREATER,
				  sumOfCounts,
				  new (CmpCommon::statementHeap()) SystemLiteral(0)),
			  new (CmpCommon::statementHeap())
			  BiArith(ITM_DIVIDE,sumOfSums,sumOfCounts),
			  new (CmpCommon::statementHeap()) SystemLiteral()));
      }
      else
      {
        result = new (CmpCommon::statementHeap())
                     BiArith(ITM_DIVIDE,sumOfSums,sumOfCounts);
      }

      result->synthTypeAndValueId();

      // execute the initial sum and count in the initial set
      initialAggrs.insert(sumOfCounts->child(0)->getValueId());
      initialAggrs.insert(sumOfSums->child(0)->getValueId());
      finalAggrs.insert(sumOfCounts->getValueId());
      finalAggrs.insert(sumOfSums->getValueId());
      break;

    case ITM_COUNT:
    case ITM_COUNT_NONULL:
      // compute the sum of the counts
      partial = new (CmpCommon::statementHeap())
                  Aggregate(getOperatorType(),child(0));

      sumOfCounts = new (CmpCommon::statementHeap())
                  Aggregate(ITM_SUM, partial);

      if (inScalarGroupBy())
      {
        partial->setInScalarGroupBy();
        sumOfCounts->setInScalarGroupBy();
      }
      sumOfCounts->setTreatAsACount();
      sumOfCounts->setTopPartOfAggr();
      result = sumOfCounts;

      result->synthTypeAndValueId();

      // If we have to force the same type for the initial and final
      // aggregate expressions, then force the type of the sum to
      // be the same as the type of the count.
      if (sameFormat)
	result->getValueId().changeType(&(result->child(0)->
					getValueId().getType()));

      // execute the nested aggregate function in the initial set
      initialAggrs.insert(result->child(0)->getValueId());
      finalAggrs.insert(result->getValueId());
      break;

    case ITM_MAX:
    case ITM_MIN:
    case ITM_SUM:
    case ITM_ANY_TRUE:
    case ITM_ONEROW:
    case ITM_GROUPING:
      // in these cases, just do the same aggregate function twice
      partial = new (CmpCommon::statementHeap())
                     Aggregate(getOperatorType(), child(0));

      result = new (CmpCommon::statementHeap())
                    Aggregate(getOperatorType(), partial);

      if (getOperatorType() == ITM_GROUPING)
        {
          ((Aggregate *)partial)->setRollupGroupIndex(getRollupGroupIndex());
          ((Aggregate *)result)->setRollupGroupIndex(getRollupGroupIndex());
        }

      if (inScalarGroupBy())
      {
        partial->setInScalarGroupBy();
        ((Aggregate *)result)->setInScalarGroupBy();
      }
      ((Aggregate *)result)->setTopPartOfAggr();

      // fix case 10-081203-5622, soln 10-081203-7701 by preserving this'
      // "treatAsACount_ & amTopPartOfAggr_" attribute settings.
      if (treatAsACount()) {
        partial->setTreatAsACount();
        ((Aggregate*)result)->setTreatAsACount();
      }
      if (topPartOfAggr()) {
        partial->setTopPartOfAggr();
      }
        
      result->synthTypeAndValueId();

      // If we have to force the same type for the initial and final
      // aggregate expressions, then force the type of the sum to
      // be the same as the type of the sum/min/max etc...
      if (sameFormat)
	result->getValueId().changeType(&(result->child(0)->
					  getValueId().getType()));

      // execute the nested aggregate function in the initial set
      initialAggrs.insert(result->child(0)->getValueId());
      finalAggrs.insert(result->getValueId());
      break;

    case ITM_ONE_TRUE:
      partial = new (CmpCommon::statementHeap())
                     Aggregate(getOperatorType(), child(0));

      result = new (CmpCommon::statementHeap())
                    Aggregate(ITM_ANY_TRUE, partial);

      if (inScalarGroupBy())
      {
        partial->setInScalarGroupBy();
        ((Aggregate *)result)->setInScalarGroupBy();
      }

      result->synthTypeAndValueId();

      // If we have to force the same type for the initial and final
      // aggregate expressions, then force the type of the sum to
      // be the same as the type of the sum/min/max etc...
      if (sameFormat)
	result->getValueId().changeType(&(result->child(0)->
					  getValueId().getType()));

      // execute the nested aggregate function in the initial set
      initialAggrs.insert(result->child(0)->getValueId());
      finalAggrs.insert(result->getValueId());
      break;

    case ITM_ONE_ROW:
      // need another aggregate function that handles the case where
      // some servers return NULL rows
      ABORT("sorry, one row aggregates cannot be implemented in a staged fashion");
      break;

    default:
      ABORT("unknown aggregate function encountered");
    }

  return result;
}

ItemExpr * PivotGroup::rewriteForStagedEvaluation(ValueIdList &initialAggrs,
                                                  ValueIdList &finalAggrs,
                                                  NABoolean sameFormat)
{
  // Split the aggregate function into three parts: the initial part is
  // executed in multiple groupby nodes whose results are sent to a
  // single, "final" groupby node that executes the final aggregate expression.
  // More than one aggregate function may be evaluated in the initial and/or
  // final nodes, therefore a set parameter is used. The return value is
  // an item expression equivalent to the original expression "this". The
  // return value is not necessarily an aggregate function, while
  // initialAggr and finalAggr contain only aggregate functions.

  // NOTE: this method doesn't delete the existing aggregate node, and it
  // produces new value ids for all three parts returned.

  ItemExpr *result = NULL;
  Aggregate *partial;

  partial = new (CmpCommon::statementHeap())
    PivotGroup(getOperatorType(), child(0), pivotOptionsList_, isDistinct());
  
  result = new (CmpCommon::statementHeap())
    PivotGroup(ITM_PIVOT_GROUP, partial, NULL);
  
  if (inScalarGroupBy())
    {
      partial->setInScalarGroupBy();
      ((Aggregate *)result)->setInScalarGroupBy();
    }
  
  result->synthTypeAndValueId();
  
  // If we have to force the same type for the initial and final
  // aggregate expressions, then force the type of the sum to
  // be the same as the type of the sum/min/max etc...
  if (sameFormat)
    result->getValueId().changeType(&(result->child(0)->
					  getValueId().getType()));
  
  // execute the nested aggregate function in the initial set
  initialAggrs.insert(result->child(0)->getValueId());
  finalAggrs.insert(result->getValueId());
  
  return result;
}

// Aggregate::isEquivalentForBinding Determine if these two
// ItemExprs are equivalent.  If so, one may be eliminated and
// replaced with the other.
// Inputs:
//   ItemExpr *other - the ItemExpr being compared to 'this'
//
// Outputs: return value: Returns TRUE if the 'other' ItemExpr is
// equivalent to 'this'.  In order to be equivalent, they must:
//     - Have equivalent children
//       (determined by 'hasBaseEquivalenceForCodeGeneration()
//     - Be the same aggregate. (same operatorType)
//       (determined by 'hasBaseEquivalenceForCodeGeneration()
//     - have the same distinct settings and if distinct, must both
//       be distinct with respect to the immediate child.  This could
//       prevent otherwise equivalent distinct STDDEV and VARIANCE aggregates
//       from being eliminated.
//
NABoolean Aggregate::isEquivalentForBinding(const ItemExpr * other)
{

  // Make sure that the children are equivalent and that this and
  // other are the same operator
  //
  if (hasBaseEquivalenceForCodeGeneration(other))
    {
      // we know that other is an Aggregate, its operator type is the same,
      // and that the children are equivalent
      Aggregate * otherAggregate = (Aggregate *)other;

      // Both must have the same distinct settings.
      //
      if(isDistinct() != otherAggregate->isDistinct()) {
        return FALSE;
      }

      // Both must have the same inScalarGroupBy settings.
      //
      if(inScalarGroupBy() != otherAggregate->inScalarGroupBy()) {
        return FALSE;
      }

      // If both are distinct (sufficient to check one since we know
      // both are the same).
      //
      if(isDistinct()) {

        // If they are distinct, both must be distinct on the
        // immediate child.  VARIANCE and STDDEV are transformed into
        // a more complicated expression and the distinct valueid will
        // not be the immediate child.  So this means that the
        // distinct versions of VARIANCE and STDDEV will not be
        // considered for elimination even though they may qualify.
        // Furthermore, the 'this' version of a distinct VARIANCE or
        // STDDEV will not have its distinctID set properly until
        // after this routine is called (but the 'other' one will).
        //
        if(getDistinctValueId() != child(0)->getValueId()) {
          return FALSE;
        }

        if(otherAggregate->getDistinctValueId() !=
           otherAggregate->child(0)->getValueId()) {
          return FALSE;
        }
      }

      // the two values are equivalent.
      return TRUE;
    }

  return FALSE;
}

// Return the equivalent running sequence function operator type
//
OperatorTypeEnum Aggregate::mapOperTypeToRunning() const
{
  switch(getOperatorType()) {
  case ITM_AVG:
    return ITM_RUNNING_AVG;
    break;
  case ITM_COUNT:
    return ITM_RUNNING_COUNT;
    break;
  case ITM_COUNT_NONULL:
    return ITM_RUNNING_COUNT;
    break;
  case ITM_MAX:
    return ITM_RUNNING_MAX;
    break;
  case ITM_MIN:
    return ITM_RUNNING_MIN;
    break;
  case ITM_STDDEV:
    return ITM_RUNNING_SDEV;
    break;
  case ITM_SUM:
    return ITM_RUNNING_SUM;
    break;
  case ITM_VARIANCE:
    return ITM_RUNNING_VARIANCE;
    break;
  case ITM_RUNNING_RANK:
    return ITM_RUNNING_RANK;
    break;
  case ITM_RUNNING_DRANK:
    return ITM_RUNNING_DRANK;
    break;
  default:
    return INVALID_OPERATOR_TYPE;
  }
}
OperatorTypeEnum Aggregate::mapOperTypeToOlap() const
{
  switch(getOperatorType()) {
  case ITM_AVG:
    return ITM_OLAP_AVG;
    break;
  case ITM_COUNT:
    return ITM_OLAP_COUNT;
    break;
  case ITM_COUNT_NONULL:
    return ITM_OLAP_COUNT;
    break;
  case ITM_MAX:
    return ITM_OLAP_MAX;
    break;
  case ITM_MIN:
    return ITM_OLAP_MIN;
    break;
  case ITM_STDDEV:
    return ITM_OLAP_SDEV;
    break;
  case ITM_SUM:
    return ITM_OLAP_SUM;
    break;
  case ITM_VARIANCE:
    return ITM_OLAP_VARIANCE;
    break;
  case ITM_RUNNING_RANK:
    return ITM_OLAP_RANK;
    break;
  case ITM_RUNNING_DRANK:
    return ITM_OLAP_DRANK;
    break;
  default:
    return INVALID_OPERATOR_TYPE;
  }
}


// Return the equivalent moving sequence function operator type
//
OperatorTypeEnum Aggregate::mapOperTypeToMoving() const
{
  switch(getOperatorType()) {
  case ITM_AVG:
    return ITM_MOVING_AVG;
    break;
  case ITM_COUNT:
    return ITM_MOVING_COUNT;
    break;
  case ITM_COUNT_NONULL:
    return ITM_MOVING_COUNT;
    break;
  case ITM_MAX:
    return ITM_MOVING_MAX;
    break;
  case ITM_MIN:
    return ITM_MOVING_MIN;
    break;
  case ITM_STDDEV:
    return ITM_MOVING_SDEV;
    break;
  case ITM_SUM:
    return ITM_MOVING_SUM;
    break;
  case ITM_VARIANCE:
    return ITM_MOVING_VARIANCE;
    break;
  case ITM_RUNNING_RANK:
    return ITM_MOVING_RANK;
    break;
  case ITM_RUNNING_DRANK:
    return ITM_MOVING_DRANK;
    break;
  default:
    return INVALID_OPERATOR_TYPE;
  }
}
OperatorTypeEnum ItmSeqOlapFunction::mapOperTypeToRunning() const
{
  switch(getOperatorType()) {
  case ITM_OLAP_AVG:
    return ITM_RUNNING_AVG;
    break;
  case ITM_OLAP_COUNT:
    return ITM_RUNNING_COUNT;
    break;
  case ITM_OLAP_MAX:
    return ITM_RUNNING_MAX;
    break;
  case ITM_OLAP_MIN:
    return ITM_RUNNING_MIN;
    break;
  case ITM_OLAP_SDEV:
    return ITM_RUNNING_SDEV;
    break;
  case ITM_OLAP_SUM:
    return ITM_RUNNING_SUM;
    break;
  case ITM_OLAP_VARIANCE:
    return ITM_RUNNING_VARIANCE;
    break;
  case ITM_OLAP_RANK:
    return ITM_RUNNING_RANK;
    break;
  case ITM_OLAP_DRANK:
    return ITM_RUNNING_DRANK;
    break;
  default:
    return INVALID_OPERATOR_TYPE;
  }
}



OperatorTypeEnum ItmSeqOlapFunction::mapOperTypeToMoving() const
{
  switch(getOperatorType()) {
  case ITM_OLAP_AVG:
    return ITM_MOVING_AVG;
    break;
  case ITM_OLAP_COUNT:
    return ITM_MOVING_COUNT;
    break;
  case ITM_OLAP_MAX:
    return ITM_MOVING_MAX;
    break;
  case ITM_OLAP_MIN:
    return ITM_MOVING_MIN;
    break;
  case ITM_OLAP_SDEV:
    return ITM_MOVING_SDEV;
    break;
  case ITM_OLAP_SUM:
    return ITM_MOVING_SUM;
    break;
  case ITM_OLAP_VARIANCE:
    return ITM_MOVING_VARIANCE;
    break;
  case ITM_OLAP_RANK:
    return ITM_MOVING_RANK;
    break;
  case ITM_OLAP_DRANK:
    return ITM_MOVING_DRANK;
    break;
  default:
    return INVALID_OPERATOR_TYPE;
  }
}


// transformOlapFunction.
// Transform OLAP Window aggregate functions into their equivalent 
// sequence functions.
//
// Also verifies that all OLAP Window function are using the same Window
// specification (partition by and order by).  If not, an error message
// is put into the diags area.
// 
// Inputs - this - the Aggregate with OLAP information 
//                 (partition by and order by)
//
//          bindWA - Used to get current scope for error handling

// Returns - transformed expression.
//         - NULL on error
//
ItemExpr *Aggregate::transformOlapFunction(BindWA *bindWA)
{
  if(NOT isOLAP_) {
    // Not an OLAP aggregate.
    return this;
  }

  // If this is an illegal Frame Specification, then issue an error.
  //
  if ((frameStart_ > frameEnd_) || 
      (isFrameStartUnboundedFollowing()) || // frameStart_ == INT_MAX) || 
      (isFrameEndUnboundedPreceding())) //frameEnd_ == -INT_MAX ))
    {
      *CmpCommon::diags() << DgSqlCode(-4342);
      bindWA->setErrStatus();
      return NULL;
    } 

  if (!olapOrderBy_ && ( getOperatorType() == ITM_RUNNING_RANK || getOperatorType() == ITM_RUNNING_DRANK))
    {//The use of RANK or DENSE_RANK window functions without a window ORDER BY clause is not supported.
      *CmpCommon::diags() << DgSqlCode(-4344);
      bindWA->setErrStatus();
      return NULL;     
    }
  // Distinct is not supported for Window Functions.
  //
  if (this->isDistinct_)
    {
      *CmpCommon::diags() << DgSqlCode(-4341);
      bindWA->setErrStatus();
      return NULL;
    }

  BindScope *currScope = bindWA->getCurrentScope();

  // OLAP Window functions can only be in the select list
  //
  if (! currScope->context()->inSelectList())
    {
      *CmpCommon::diags() << DgSqlCode(-4346);
      bindWA->setErrStatus();
      return NULL;     

    }
 
  if (currScope->context()->inAggregate())
    {
      *CmpCommon::diags() << DgSqlCode(-4375) << DgString0(getTextUpper());
      bindWA->setErrStatus();
      return NULL;     

    }

  ValueIdList  partition_vil, order_vil;
  ItemExpr * tmpItemExpr = NULL;

  // Verify that all Window Functions within this scope, use the
  // same Window Specification (partition by and order by)
  //

  // The Sequence functions are bound in the environment (RETDesc) of
  // the child of the OLAP Sequence if one exists
  //
  RelExpr *sequenceNode = currScope->getSequenceNode();
  RETDesc *currentRETDesc = currScope->getRETDesc();
   
  currScope->setRETDesc(sequenceNode->child(0)->getRETDesc());

  if (olapPartitionBy_)
    {
      currScope ->context()->inOrderBy() = TRUE;
      currScope ->context()->inOlapPartitionBy() = TRUE;
      olapPartitionBy_->convertToValueIdList(partition_vil, bindWA, ITM_ITEM_LIST);
      currScope ->context()->inOlapPartitionBy() = FALSE;
      currScope ->context()->inOrderBy() = FALSE;

      if (bindWA->errStatus())
        return NULL;
    }

  if (olapOrderBy_)
    {
      currScope->context()->inOtherSequenceFunction() = TRUE;
      currScope ->context()->inOrderBy() = TRUE;
      currScope ->context()->inOlapOrderBy() = TRUE;
      olapOrderBy_->convertToValueIdList(order_vil, bindWA, ITM_ITEM_LIST);
      currScope ->context()->inOlapOrderBy() = FALSE;
      currScope ->context()->inOrderBy() = FALSE;
      currScope->context()->inOtherSequenceFunction() = FALSE;

      if (bindWA->errStatus())
        return NULL;
    }
    
  currScope->setRETDesc(currentRETDesc);
    
  // If this is the first Window Function to be bound in this scope,
  // remember the partition and order by lists.
  //
  if ( currScope->getIsFirstOlapWindowSpec() )
    { 
      currScope->setOlapPartition( partition_vil );
      currScope->setOlapOrder( order_vil );
      currScope->setIsFirstOlapWindowSpec ( FALSE );
    } 
  else 
    {
      // Check to see if the partition by and order by for this Window
      // Function is the same as all the others we have bound in this
      // scope so far.
      //
      NABoolean olap = TRUE;
      if (partition_vil.entries() != currScope->getOlapPartition().entries() ||
	  order_vil.entries() != currScope->getOlapOrder().entries())
        {
          olap = FALSE;
        }
      for(CollIndex i = 0; olap && i < partition_vil.entries(); i++) 
        {
          ItemExpr *ie = currScope->getOlapPartition()[i].getItemExpr();
          ItemExpr *otherIe = partition_vil[i].getItemExpr();
          if(!ie->hasBaseEquivalence(otherIe)) 
            {
              olap = FALSE;
            }
        }

      for(CollIndex i = 0;  olap && i < order_vil.entries(); i++) 
        {
          ValueId vid1, vid2;
          vid1 = currScope->getOlapOrder()[i];
          vid2 = order_vil[i];
          if (order_vil[i].getItemExpr()->getOperatorType() == ITM_INVERSE &&
              currScope->getOlapOrder()[i].getItemExpr()->getOperatorType() == ITM_INVERSE)
            {
              vid1 = currScope->getOlapOrder()[i].getItemExpr()->child(0).getValueId();
              vid2 = order_vil[i].getItemExpr()->child(0).getValueId();
            }
	 
          ItemExpr *ie = vid1.getItemExpr();
          ItemExpr *otherIe = vid2.getItemExpr();
          if( !ie->hasBaseEquivalence(otherIe)) 
            {
              olap = FALSE;
            }
        }

      if (! olap)
        {
          // The Window Specification for this Window Function is not
          // the same as the others we have bound so far in this scope.
          //
          *CmpCommon::diags() << DgSqlCode(-4340);
          bindWA->setErrStatus();
          return NULL;
        }
    }
 
    CollHeap *heap = CmpCommon::statementHeap();

    OperatorTypeEnum op = mapOperTypeToOlap();

    ItmSeqOlapFunction *seqFunc = new (heap)
                ItmSeqOlapFunction(op, child(0));

    seqFunc->setOLAPInfo(olapPartitionBy_, olapOrderBy_);
    seqFunc->setOlapWindowFrame(frameStart_, frameEnd_);
                                        
    return seqFunc;


}


QR::ExprElement Aggregate::getQRExprElem() const
{
  return QR::QRFunctionElem;
}


// -----------------------------------------------------------------------
// member functions for class Variance
// -----------------------------------------------------------------------
Variance::~Variance() {}

ItemExpr * Variance::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  Variance *result;

  if (derivedNode == NULL)
    result = new (outHeap) Variance(getOperatorType(), NULL, NULL, isDistinct());
  else
    result = (Variance *) derivedNode;

  return Aggregate::copyTopNode(result, outHeap);
}

// -----------------------------------------------------------------------
// member functions for class PivotGroup
// -----------------------------------------------------------------------
PivotGroup::PivotGroup(OperatorTypeEnum otype,
                       ItemExpr *child0,
                       NAList<PivotOption*> * pivotOptionsList,
                       NABoolean isDistinct)
  : Aggregate(otype, child0, NULL, isDistinct),
    pivotOptionsList_(pivotOptionsList),
    maxLen_(DEFAULT_MAX_LEN),
    delim_(","),
    orderBy_(FALSE)
{
  if (pivotOptionsList)
    {
      for (CollIndex i = 0; i < pivotOptionsList->entries(); i++)
	{
	  PivotOption * po = (*pivotOptionsList)[i];
	  switch (po->option_)
	    {
	    case DELIMITER_:
	      {
		delim_ = *po->stringVal_;
              }
              break;

	    case MAX_LENGTH_:
	      {
		maxLen_ = po->numericVal_;
              }
              break;

            case ORDER_BY_:
              {
                orderBy_ = TRUE;
                // optionNode_ contains the ItemExpr 
                orgReqOrder_ = (ItemExpr *)po->optionNode_; 
              }
              break;
            }
        }
    }
}

PivotGroup::~PivotGroup() {}

ItemExpr * PivotGroup::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  PivotGroup *result;

  if (derivedNode == NULL)
    result = new (outHeap) PivotGroup(getOperatorType(), NULL, NULL, isDistinct());
  else
    result = (PivotGroup *) derivedNode;

  result->pivotOptionsList_ = pivotOptionsList_;
  result->delim_ = delim_;
  result->orderBy_ = orderBy_;
  result->reqdOrder_ = reqdOrder_;
  result->orgReqOrder_ = orgReqOrder_;
  result->maxLen_ = maxLen_;

  return Aggregate::copyTopNode(result, outHeap);
}

// -----------------------------------------------------------------------
// member functions for class Function
// -----------------------------------------------------------------------
Function::Function(OperatorTypeEnum otype,
                   NAMemory *h,
		   Lng32   argumentCount,
		   ItemExpr *child0,
		   ItemExpr *child1,
		   ItemExpr *child2,
		   ItemExpr *child3,
		   ItemExpr *child4,
		   ItemExpr *child5)
           : ItemExpr(otype),
	     children_(h,argumentCount),
	     allowsSQLnullArg_(TRUE)
{
  Lng32 lastInserted = -1;
  ItemExpr *childx;

  for (Lng32 i = 0; i < (Lng32)argumentCount; i++)
    {
      childx = IFX i==0
	THENX child0
	ELSEX IFX i==1
	THENX child1
	ELSEX IFX i==2
	THENX child2
	ELSEX IFX i==3
	THENX child3
	ELSEX IFX i==4
	THENX child4
	ELSEX IFX i==5
	THENX child5
	ELSEX (ItemExpr *) NULL;

      CMPASSERT((Lng32)children_.entries() == i);

      children_.insertAt(i, childx);
    } // end for
}

Function::Function(OperatorTypeEnum otype, const LIST(ItemExpr *) &children, 
                   CollHeap *h)
         : ItemExpr(otype),
	   children_(h)
{
  Lng32 ne = children.entries();

  for (Lng32 i = 0; i < ne; i++)
    {
      children_.insertAt(i,children[i]);
    }
}

Function::~Function() {}

Lng32 Function::getNumChildren() const
{
  Lng32 count = children_.entries();
  // $$$$ Skip all the NULL children at the tail end.
  // $$$$ Assumes children that are missing in the middle
  // $$$$ should figure in the count, e.g., F(a, NULL, b, NULL, NULL)
  while ( (count > 0) AND (children_[count-1].getPtr() == NULL) )
    count--;
  return count;
}

ItemExpr * Function::copyTopNode(ItemExpr * derivedNode, CollHeap* outHeap)
{
  Function *result = NULL;
  if (derivedNode == NULL)
    ABORT("copyTopNode() can only be called for a derived class of Function");
  else
    result = (Function *)derivedNode;

  result->allowsSQLnullArg() = allowsSQLnullArg();

  // Make sure we copy the kids as well.
  Lng32 ne = children_.entries();
  for (Lng32 i = 0; i < ne; i++)
    result->children_.insertAt(i, children_[i]);

  return ItemExpr::copyTopNode(result, outHeap);
}

ExprValueId & Function::operator[] (Lng32 index)
{
 CMPASSERT( (index >= 0) AND (index < (Lng32)children_.entries()) );
 return children_[index];
}

const ExprValueId & Function::operator[] (Lng32 index) const
{
  CMPASSERT( (index >= 0) AND (index < (Lng32)children_.entries()) );
  return children_[index];
}

// -----------------------------------------------------------------------
// member functions for class BuiltinFunction
// -----------------------------------------------------------------------
BuiltinFunction::BuiltinFunction(OperatorTypeEnum otype,
                                 NAMemory *h,
				 Lng32  argumentCount,
				 ItemExpr *child0,
				 ItemExpr *child1,
				 ItemExpr *child2,
				 ItemExpr *child3,
				 ItemExpr *child4,
				 ItemExpr *child5)
     : Function(otype,h,argumentCount,child0,child1,child2,child3,child4,child5)
{
  switch (getOperatorType())
    {
    case ITM_NULLIFZERO:
    case ITM_QUERYID_EXTRACT:
    case ITM_TOKENSTR:
    case ITM_REVERSE: {
	allowsSQLnullArg() = FALSE;
      }
    break;

    default:
      {
      }
    break;
    }
}

BuiltinFunction::~BuiltinFunction() {}

Int32 BuiltinFunction::getArity() const
{
  return getNumChildren();
}

// -----------------------------------------------------------------------
// BuiltinFunction::isCovered()
// -----------------------------------------------------------------------
NABoolean BuiltinFunction::isCovered
                             (const ValueIdSet& newExternalInputs,
		              const GroupAttributes& coveringGA,
		              ValueIdSet& referencedInputs,
		              ValueIdSet& coveredSubExpr,
		              ValueIdSet& unCoveredExpr) const
{

  // ITM_CURRENT_USER function should appear as an input characteristic
  // of the root for it to be evaluated by the executor. And hence it
  // needs to be treated differently from other BuiltinFunctions. For
  // it to be propogated to the root, it should not be covered.
  // Case 10-010419-2366

  if (isAUserSuppliedInput())  // for user(x), current_timestamp, extract (fix)
     return FALSE;

  // A BuiltinFunction with no arguments (children)
  // is like a constant. It is always covered.
  Lng32 nc = getNumChildren();
  if (nc == 0)
    return TRUE;

  // ---------------------------------------------------------------------
  // A BuiltinFunction can contain values that are produced by
  // different sources. The BuiltinFunction is covered if each
  // operand is covered.
  // The coverage test insists on a complete coverage of all the
  // children.
  // ---------------------------------------------------------------------
  ValueIdSet childValues;
  for (Int32 i = 0; i < nc; i++)
    childValues += child(i).getValueId();
  return childValues.isCovered(newExternalInputs,
			      coveringGA,
			      referencedInputs,
			      coveredSubExpr,
			      unCoveredExpr);
} // BuiltinFunction::isCovered()

NABoolean BuiltinFunction::isCacheableExpr(CacheWA& cwa)
{
  switch (getOperatorType())
    {
    case ITM_NULLIFZERO:
    case ITM_QUERYID_EXTRACT:
    case ITM_TOKENSTR:
      {
	return ItemExpr::isCacheableExpr(cwa);
      }
    break;

    case ITM_NVL:
    case ITM_REVERSE:
      {
	return FALSE;
      }
    break;
    case ITM_JSONOBJECTFIELDTEXT:
    {
	    return FALSE;
    }
    break;

    default:
      {
	return Function::isCacheableExpr(cwa);
      }
    break;
    }
}

const NAString BuiltinFunction::getText() const
{
  NABoolean dumpMvMode = (CmpCommon::getDefault(MVQR_LOG_QUERY_DESCRIPTORS) == DF_DUMP_MV);

  switch (getOperatorType())
    {
    case ITM_ABS:
      return "abs";
    case ITM_ASCII:
      return "ascii";
    case ITM_AUTHNAME:
      return "authname";
    case ITM_AUTHTYPE:
      return "authtype";
    case ITM_BETWEEN:
      return "between";
    case ITM_BLOCK:
      return "block";
    case ITM_BOOL_RESULT:
      return "bool_result";
    case ITM_CASE:
      return "case";
    case ITM_CAST:
      return "cast";
    case ITM_CAST_CONVERT:
      return "cast_convert";
    case ITM_CAST_TYPE:
      return "typecast";
    case ITM_CHAR:
      return "char";
    case ITM_CHAR_LENGTH:
      return "char_length";
    case ITM_COALESCE:
      return "coalesce";
    case ITM_COMP_ENCODE:
      return "comp_encode";
    case ITM_COMP_DECODE:
      return "comp_decode";
    case ITM_CONCAT:
      return "||";				// "concat";
    case ITM_CONVERTFROMHEX:
      return "CONVERTFROMHEX";
    case ITM_CONVERTTOHEX:
      return "CONVERTTOHEX";
    case ITM_CONVERTTOBITS:
      return "CONVERTTOBITS";
    case ITM_CONVERTTIMESTAMP:
      return "converttimestamp";
    case ITM_SLEEP:
      return "sleep";
    case ITM_UNIX_TIMESTAMP:
      return "unix_timestamp";
    case ITM_CURRENT_TIMESTAMP:
      return "current_timestamp";
    case ITM_CURRENT_TIMESTAMP_RUNNING:
      return "current_timestamp_running";
    case ITM_CURRENT_USER:
      return "current_user";
    case ITM_DATEFORMAT:
      return "dateformat";
    case ITM_DAYOFMONTH:
      return "dayofmonth";
    case ITM_DAYOFWEEK:
      return "dayofweek";
    case ITM_DO_WHILE:
      return "do while";
    case ITM_WHILE:
      return "while";
    case ITM_EXPLODE_VARCHAR:
      return "explodevarchar";
    case ITM_EXTRACT:
      return "extract";
    case ITM_EXTRACT_ODBC:
      return "extract_odbc";
    case ITM_GREATEST:
     return "greatest";
    case ITM_LEAST:
     return "least";
    case ITM_IN:
      return "in";
    case ITM_INSTANTIATE_NULL:
      // getenv() calls are costly. avoid especially in release code.
#ifndef NDEBUG
      if (getenv("SIMPLE_DISPLAY")) return "iNull";
#endif
      return "instantiate_null";
    case ITM_JULIANTIMESTAMP:
      return "juliantimestamp";
    case ITM_EXEC_COUNT:
      return "execution_count";
    case ITM_CURR_TRANSID:
      return "current_transid";
    case ITM_LIKE:
    case ITM_LIKE_DOUBLEBYTE:
      return "like";
    case ITM_REGEXP:
      return "regexp";
    case ITM_LOWER:
    case ITM_LOWER_UNICODE:
      return "lower";
    case ITM_NARROW:
      return "narrow";
    case ITM_NULLIFZERO:
      return "nullifzero";
    case ITM_NVL:
      return "nvl";
    case ITM_JSONOBJECTFIELDTEXT:
      return "json_object_field_text";
    case ITM_QUERYID_EXTRACT:
      return "queryid_extract";
    case ITM_UPPER:
    case ITM_UPPER_UNICODE:
      return "upper";
    case ITM_UNICODE_CHAR:
      return "unicode_char";
    case ITM_NO_OP:
      return "no_op";
    case ITM_POSITION:
      return "position";
    case ITM_REPEAT:
      return "repeat";
    case ITM_REPLACE:
      return "replace";
    case ITM_REPLACE_NULL:
      return "replace null";
    case ITM_RETURN_TRUE:
      if (dumpMvMode)
        return "1";
      else
        return "return_true";
    case ITM_RETURN_FALSE:
      if (dumpMvMode)
        return "0";
      else
        return "return_false";
    case ITM_RETURN_NULL:
      if (dumpMvMode)
        return "null";
      else
        return "return_unknown";
    case ITM_SESSION_USER:
      return "session_user";
    case ITM_OCTET_LENGTH:
      return "octet_length";
    case ITM_HASH:
      return "hash";
    case ITM_HASH2_DISTRIB:
      return "hash2_distrib";
    case ITM_MOD:
      return "mod";
    case ITM_INVERSE:
      return "inverse";
    case ITM_SUBSTR:
    case ITM_SUBSTR_DOUBLEBYTE:
      return "substring";
    case ITM_TRANSLATE:
      return "translate";
    case ITM_TRIM:
    case ITM_TRIM_DOUBLEBYTE:
      return "trim";
    case ITM_IF_THEN_ELSE:
      return "if_then_else";
    case ITM_LESS_OR_LE:
      return "< or <=";
    case ITM_GREATER_OR_GE:
      return "> or >=";
    case ITM_RANGE_LOOKUP:
      return "range_lookup";
    case ITM_RANDOMNUM:
      return "randomNum";
    case ITM_RAND_SELECTION:
      return "randomSelection";
    case ITM_ROUND_ROBIN:
      return "Round_Robin";
    case ITM_PACK_FUNC:
      return "pack";
    case ITM_SAMPLE_VALUE:
      return "sample_size";
    case ITM_UNIQUE_SHORT_ID:
      return "unique_short_id";
    case ITM_UNIQUE_ID:
      return "unique_id";
    case ITM_HBASE_COLUMN_LOOKUP:
      return "hbase_column_lookup";
    case ITM_HBASE_COLUMNS_DISPLAY:
      return "hbase_columns_display";
    case ITM_HBASE_COLUMN_CREATE:
      return "hbase_column_create";
    case ITM_SEQUENCE_VALUE:
      return "seqnum";
    case ITM_ROWNUM:
      return "rownum";
    case ITM_USER:
      return "user";
    case ITM_UNIQUE_EXECUTE_ID:
      return "unique_execute_id";
    case ITM_GET_TRIGGERS_STATUS:
      return "get_triggers_status";
    case ITM_GET_BIT_VALUE_AT:
      return "get_bit_value_at";
    case ITM_IS_BITWISE_AND_TRUE:
      return "is_bitwise_and_true";
    case ITM_USERID:
      return "os_userid";
    case ITM_CURRENTEPOCH:
      return "current_epoch";
    case ITM_VSBBROWTYPE:
      return "vsbb_row_type";
    case ITM_VSBBROWCOUNT:
      return "vsbb_row_count";
    case ITM_INTERNALTIMESTAMP:
      return "internal_timestamp";
    case ITM_SCALAR_MIN:
      return "scalar_min";
    case ITM_SCALAR_MAX:
      return "scalar_max";
    case ITM_TOKENSTR:
      return "TOKENSTR";
    case ITM_REVERSE:
      return "REVERSE";

    // ZZZBinderFunction classes (for error messages only)
    case ITM_DATE_TRUNC_YEAR:
    case ITM_DATE_TRUNC_MONTH:
    case ITM_DATE_TRUNC_DAY:
    case ITM_DATE_TRUNC_HOUR:
    case ITM_DATE_TRUNC_MINUTE:
    case ITM_DATE_TRUNC_SECOND:
    case ITM_DATE_TRUNC_CENTURY:
    case ITM_DATE_TRUNC_DECADE:
      return "date_trunc";
    case ITM_DATEDIFF_YEAR:
    case ITM_DATEDIFF_MONTH:
    case ITM_DATEDIFF_DAY:
    case ITM_DATEDIFF_HOUR:
    case ITM_DATEDIFF_MINUTE:
    case ITM_DATEDIFF_SECOND:
    case ITM_DATEDIFF_QUARTER:
    case ITM_DATEDIFF_WEEK:
      return "datediff";
    case ITM_TSI_YEAR:
    case ITM_TSI_MONTH:
    case ITM_TSI_DAY:
    case ITM_TSI_HOUR:
    case ITM_TSI_MINUTE:
    case ITM_TSI_SECOND:
    case ITM_TSI_QUARTER:
    case ITM_TSI_WEEK:
      return "timestampdiff";
    case ITM_DAYNAME:
      return "dayname";
    case ITM_DAYOFYEAR:
      return "dayofyear";
    case ITM_DECODE:
      return "decode";
    case ITM_FIRSTDAYOFYEAR:
      return "firstdayofyear";
    case ITM_LAST_DAY:
      return "last_day";
    case ITM_NEXT_DAY:
      return "next_day";
    case ITM_INSERT_STR:
      return "insert";
    case ITM_LEFT:
      return "left";
    case ITM_LPAD:
      return "lpad";
    case ITM_MONTHNAME:
      return "monthname";
    case ITM_NULLIF:
      return "nullif";
    case ITM_ODBC_LENGTH:
      return "LENGTH";
    case ITM_QUARTER:
      return "quarter";
    case ITM_RIGHT:
      return "right";
    case ITM_RPAD:
      return "rpad";
    case ITM_SIGN:
      return "sign";
    case ITM_SPACE:
      return "space";
    case ITM_CODE_VALUE:
    case ITM_UNICODE_CODE_VALUE:
    case ITM_NCHAR_MP_CODE_VALUE:
      return "code_value";
    case ITM_WEEK:
      return "week";
    case ITM_ZEROIFNULL:
      return "zeroifnull";

      
    case ITM_LOBINSERT:
      return "lobinsert";

    case ITM_LOBSELECT:
      return "lobselect";

    case ITM_LOBDELETE:
      return "lobdelete";

    case ITM_LOBUPDATE:
      return "lobupdate";

    case ITM_LOBCONVERTHANDLE:
      return "lobconverthandle";

    case ITM_LOBCONVERT:
      return "lobconvert";

    case ITM_LOBLOAD:
      return "lobload";
    
    case ITM_AGGR_GROUPING_FUNC:
      return "aggr_grouping";

    case ITM_TO_TIMESTAMP:
      return "to_timestamp";

    default:
      return "unknown func";
    } // switch
} // BuiltinFunction::getText()

//## Yuk -- embedded English text -- this is not per I18N standards!
const NAString BuiltinFunction::getTextForError() const
{
  switch (getOperatorType())
    {
    case ITM_CHAR_LENGTH:
      return "CHARACTER_LENGTH, CHAR_LENGTH, or LENGTH";

    case ITM_LOWER:
      return "LOWER or LCASE";

    case ITM_POSITION:
      return "POSITION or LOCATE";

    case ITM_TRIM:
    case ITM_TRIM_DOUBLEBYTE:
      return "TRIM, LTRIM, or RTRIM";

    case ITM_UPPER:
      return "UPPER, UPSHIFT, or UCASE";

    default: return getTextUpper();
    } // switch
} // BuiltinFunction::getTextForError()

ItemExpr * BuiltinFunction::copyTopNode(ItemExpr * derivedNode,
					CollHeap* outHeap)
{
  ItemExpr *result = NULL;
  if (derivedNode == NULL)
    {
      switch (getOperatorType())
	{
	case ITM_NULLIFZERO:
        case ITM_ISIPV4:
        case ITM_ISIPV6:
        case ITM_MD5:
        case ITM_CRC32:
	case ITM_SOUNDEX:
        case ITM_REVERSE:
	  {
	    result = new (outHeap) BuiltinFunction(getOperatorType(),
						   outHeap, 1, child(0));
	  }
	break;

	case ITM_NVL:
	case ITM_QUERYID_EXTRACT:
	case ITM_TOKENSTR:
	  {
	    result = new (outHeap) BuiltinFunction(getOperatorType(),
						   outHeap, 2, child(0), child(1));
	  }
	break;
    case ITM_JSONOBJECTFIELDTEXT:
	{
	    result = new (outHeap) BuiltinFunction(getOperatorType(),
						   outHeap, 2, child(0), child(1));
	}
	break;
	default:
	  {
	    ABORT("copyTopNode() can only be called for a derived class of BuiltinFunction");
	  }
	break;
	}
    }
  else
    result = derivedNode;

  return Function::copyTopNode(result, outHeap);
}

ItemExpr * HashCommon::copyTopNode(ItemExpr * derivedNode,
				   CollHeap* outHeap)
{
  ItemExpr *result = NULL;

  if (derivedNode == NULL)
    ABORT("copyTopNode() can only be called for a derived class of Function");
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

//++Triggers, 

// -----------------------------------------------------------------------
// member functions for class EvaluateOnceBuiltinFunction
// -----------------------------------------------------------------------


EvaluateOnceBuiltinFunction::~EvaluateOnceBuiltinFunction() {}

NABoolean EvaluateOnceBuiltinFunction::isAUserSuppliedInput() const    { return TRUE; }

NABoolean EvaluateOnceBuiltinFunction::isCovered(const ValueIdSet& newExternalInputs,
                               const GroupAttributes& newRelExprAnchorGA,
                               ValueIdSet& referencedInputs,
                               ValueIdSet& coveredSubExpr,
                               ValueIdSet& unCoveredExpr) const
{
	return FALSE;
}

//--Triggers, 

// -----------------------------------------------------------------------
// member functions for builtin functions
// -----------------------------------------------------------------------
Between::~Between()
{
  // NOTE: never destroy pDirectionVector_.
  // this is a pointer passed on to other objects as is.
  // if it is destroyed this may affect other items.

}

Concat::~Concat() {}

Case::~Case() {}

IfThenElse::~IfThenElse() {}

InstantiateNull::~InstantiateNull() {}

Hash::~Hash() {}

ReplaceNull::~ReplaceNull() {}

// -----------------------------------------------------------------------
// member functions for BoolVal
// -----------------------------------------------------------------------
BoolVal::~BoolVal() {}

NABoolean BoolVal::isCovered
                      (const ValueIdSet& newExternalInputs,
		       const GroupAttributes& coveringGA,
		       ValueIdSet& referencedInputs,
		       ValueIdSet& coveredSubExpr,
		       ValueIdSet& unCoveredExpr ) const
{
  // A BoolVal that returns a TRUE/FALSE/NULL unconditionally, i.e.,
  // its evaluation does not depend upon the boolean outcome of its
  // child subtree, is like a constant. It is always covered.
  if (getNumChildren() == 0)
    return TRUE;
  else
    // BoolVal is Covered if its operand is covered
    return coveringGA.covers(((ItemExpr *)child(0))->getValueId(),
			     newExternalInputs, referencedInputs,
			     &coveredSubExpr, &unCoveredExpr);
} // BoolVal::isCovered()

// -----------------------------------------------------------------------
// member functions for InverseOrder
// -----------------------------------------------------------------------
InverseOrder::~InverseOrder() {}

ItemExpr * InverseOrder::simplifyOrderExpr(OrderComparison *newOrder)
{
  OrderComparison resultOrder;
  ItemExpr *result = child(0)->simplifyOrderExpr(&resultOrder);

  // reverse the order of the simplified child
  if (resultOrder == SAME_ORDER)
    resultOrder = INVERSE_ORDER;
  else
    resultOrder = SAME_ORDER;

  if (newOrder)
    *newOrder = resultOrder;
  return result;
}

ItemExpr * InverseOrder::removeInverseOrder()
{
  return child(0);
}

// -----------------------------------------------------------------------
// member functions for PatternMatchingFunction.
// -----------------------------------------------------------------------
PatternMatchingFunction::~PatternMatchingFunction() {}

// -----------------------------------------------------------------------
// member functions for Like
// -----------------------------------------------------------------------
Like::~Like() {}

Regexp::~Regexp() {}


ItemExpr * Regexp::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result = NULL;

  if (derivedNode == NULL)
    {
      result = new (outHeap) Regexp(NULL, NULL,
	    numberOfNonWildcardChars_,
	    bytesInNonWildcardChars_,
	    patternAStringLiteral_,
	    oldDefaultSelForLikeWildCardUsed_,
	    beginEndKeysApplied_);
    }
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // Regexp::copyTopNode()

ItemExpr * Like::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result = NULL;

  if (derivedNode == NULL)
    {
      switch (getArity())
	{
	case 2:
	  result = new (outHeap) Like(child(0), child(1),
	    numberOfNonWildcardChars_,
	    bytesInNonWildcardChars_,
	    patternAStringLiteral_,
	    oldDefaultSelForLikeWildCardUsed_,
	    beginEndKeysApplied_);
	  break;
	case 3:
	  result = new (outHeap) Like(child(0), child(1), child(2),
	    numberOfNonWildcardChars_,
	    bytesInNonWildcardChars_,
	    patternAStringLiteral_,
	    oldDefaultSelForLikeWildCardUsed_,
	    beginEndKeysApplied_);
	  break;
	default:
	  CMPASSERT(0 == 1);
	  break;
	}
    }
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // Like::copyTopNode()

double PatternMatchingFunction::defaultSel()
{
  // if begin and end keys have been applied to this expression, then this means
  // that the original LIKE predicate was something like a%b. This was transformed
  // to >=a and < b and like %b. Here we would have already applied selectivity
  // to the first range predicate. We do not want to apply selectivity to the other
  // portions of the predicate. Hence return 1.0 for the last portion of the
  // predicate

  if ( beginEndKeysApplied( CmpCommon::statementHeap() ) )
     return 1.0;

  if (oldDefaultSelForLikeWildCardUsed_)
  {
    return ActiveSchemaDB()->getDefaults().getAsDouble(HIST_DEFAULT_SEL_FOR_LIKE_WILDCARD);
  }

  // For all other cases compute selectivity based on the number of non-wildcard
  // characters
  return computeSelForNonWildcardChars(); ;
}

void PatternMatchingFunction::setNumberOfNonWildcardChars(const LikePatternString &pattern)
{
  Int32 count = 0;
  Int32 byteCnt = 0;
  CharInfo::CharSet  cs = pattern.getPatternCharSet();

  LikePatternStringIterator i(pattern);

  while (i != LikePatternStringIterator::END_OF_PATTERN)
  {
    const char *currentChar = i.getCurrentChar();
    UInt16 number_bytes = Attributes::getFirstCharLength(currentChar, 8, cs);

    if (i == LikePatternStringIterator::NON_WILDCARD)
    {
        count++;
        byteCnt += number_bytes;
    }

    i += number_bytes + ((cs == CharInfo::UCS2) ? 1 : 0); // For UCS2, number_bytes is always 1
    i.determineCharType();
  }
  numberOfNonWildcardChars_ = count;
  bytesInNonWildcardChars_  = byteCnt ;
}

double PatternMatchingFunction::computeSelForNonWildcardChars()
{

  // get the default selectivity for like predicate
  double defaultSelectivity = CURRSTMT_OPTDEFAULTS->defSelForWildCard();

  // get the number of non_wildcard characters after the first wildcard char
  Int32 cnt = getNoOfNonWildcardChars();

  // Retuen default selectivity for the following cases:
  // 1. For some special cases, example when there is a dynamic parameter in the
  //    LIKE predicate, the LIKE expression is not optimized. In all such cases
  //    cnt is less than 0. For these, return the default selectivity
  // 2. if there are no non_wildcard characters in the like clause, then if the column
  //    is not nullable, we have already transformed the predicate to TRUE.
  //    For a nullable column, we apply default selectivity.
  // 3. If there is only one non_wildcard character, we go by the selectivity
  //    defined by HIST_DEFAULT_BASE_SEL_FOR_LIKE_WILDCARD,
  // 4. HIST_DEFAULT_SEL_FOR_LIKE_NO_WILDCARD is nearing 0 (e-16). We use default
  //    selectivity in that case.

  double reductionFactor = CURRSTMT_OPTDEFAULTS->defSelForNoWildCard();

  if ( (cnt <= 1) OR
       (reductionFactor <= MIN_SELECTIVITY) )
    return defaultSelectivity;

  // We compute selectivity as: if number of non-wild characters is 1, selectivity
  // is equal to default selectivity (which is 1/10 right now. If the number of
  // non-wild characters is 2, selectivity is 1/100. For number of non-wild characters
  // 3 or more, it is 1/1000. Multiplication factor each non-wildcard character is
  // defined by the CQD HIST_DEFAULT_SEL_FOR_LIKE_NO_WILDCARD

  Int32 nonWildCardChar = ((cnt > 4) ? 4 : cnt);

  defaultSelectivity = defaultSelectivity * pow(defaultSelectivity / reductionFactor, nonWildCardChar - 1);

  // Bind the selectivity between MIN_SELECTIVITY and 1.0

  if (defaultSelectivity < MIN_SELECTIVITY)
    return MIN_SELECTIVITY;
  if (defaultSelectivity > 1.0)
    return 1.0;
  return defaultSelectivity;
}

NABoolean PatternMatchingFunction::hasEquivalentProperties(ItemExpr * other)
{
  if (other == NULL)
    return FALSE;
  if (getOperatorType() != other->getOperatorType() || 
        getArity() != other->getArity())
    return FALSE;

  Like * tmp = (Like *) other;

  return 
      (this->numberOfNonWildcardChars_  == tmp->numberOfNonWildcardChars_) &&
      (this->bytesInNonWildcardChars_  == tmp->bytesInNonWildcardChars_) &&
      (this->patternAStringLiteral_ == tmp->patternAStringLiteral_ ) &&
      (this->oldDefaultSelForLikeWildCardUsed_ == tmp->oldDefaultSelForLikeWildCardUsed_) && 
      (this->beginEndKeysApplied_ == tmp->beginEndKeysApplied_ );

}

void PatternMatchingFunction::unparse(NAString &result,
		   PhaseEnum phase,
		   UnparseFormatEnum form,
		   TableDesc* tabId) const
{
  if (getArity() == 2)
    return CacheableBuiltinFunction::unparse(result, phase, form, tabId);
  else
  {
    result += "(";
    child(0)->unparse(result, phase, form, tabId);
    result += " like ";

    child(1)->unparse(result, phase, form, tabId);
    result += " escape ";

    child(2)->unparse(result, phase, form, tabId);
    result += ")";
  }                                               
}                                                 
                                                  

// -----------------------------------------------------------------------
// member functions for class ConvertHex
// -----------------------------------------------------------------------
ConvertHex::~ConvertHex() {}

ItemExpr * ConvertHex::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) ConvertHex(getOperatorType(), child(0));
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // ConvertHex::copyTopNode()

// -----------------------------------------------------------------------
// member functions for class CharLength
// -----------------------------------------------------------------------
CharLength::~CharLength() {}

ItemExpr * CharLength::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) CharLength(child(0));
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // CharLength::copyTopNode()

// -----------------------------------------------------------------------
// member functions for class OctetLength
// -----------------------------------------------------------------------
OctetLength::~OctetLength() {}

ItemExpr * OctetLength::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) OctetLength(child(0));
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // OctetLength::copyTopNode()

// -----------------------------------------------------------------------
// member functions for class PositionFunc
// -----------------------------------------------------------------------
PositionFunc::~PositionFunc() {}

ItemExpr * PositionFunc::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) PositionFunc(child(0), child(1), child(2), child(3));
  else
    result = derivedNode;

  ((PositionFunc*)result)->collation_ = collation_;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // PositionFunc::copyTopNode()

// -----------------------------------------------------------------------
// member functions for Substring
// -----------------------------------------------------------------------
Substring::~Substring() {}

ItemExpr * Substring::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result = NULL;

  if (derivedNode == NULL)
    {
      switch (getArity())
	{
	case 2:
	  result = new (outHeap) Substring(child(0), child(1));
	  break;
	case 3:
	  result = new (outHeap) Substring(child(0), child(1), child(2));
	  break;
	default:
	  CMPASSERT(0 == 1);
	  break;
	}
    }
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // Substring::copyTopNode()

// -----------------------------------------------------------------------
// member functions for class ConvertTimestamp
// -----------------------------------------------------------------------
ConvertTimestamp::~ConvertTimestamp() {}

ItemExpr * ConvertTimestamp::copyTopNode(ItemExpr *derivedNode,
					 CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) ConvertTimestamp(child(0));
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result,outHeap);

} // ConvertTimestamp::copyTopNode()

SleepFunction::~SleepFunction() {}
ItemExpr * SleepFunction::copyTopNode(ItemExpr *derivedNode,
					 CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) SleepFunction(child(0));
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result,outHeap);

} // SleepFunction::copyTopNode()
NABoolean SleepFunction::isAUserSuppliedInput() const    { return TRUE; }

UnixTimestamp::~UnixTimestamp() {}

ItemExpr * UnixTimestamp::copyTopNode(ItemExpr *derivedNode,
					 CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) UnixTimestamp();
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result,outHeap);

} // UnixTimestamp::copyTopNode()

NABoolean UnixTimestamp::isAUserSuppliedInput() const    { return TRUE; }

// -----------------------------------------------------------------------
// member functions for class CurrentTimestamp
// -----------------------------------------------------------------------
CurrentTimestamp::~CurrentTimestamp() {}

ItemExpr * CurrentTimestamp::copyTopNode(ItemExpr *derivedNode,
					 CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) CurrentTimestamp(dtCode_, fractPrec_);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result,outHeap);

} // CurrentTimestamp::copyTopNode()

NABoolean CurrentTimestamp::isAUserSuppliedInput() const    { return TRUE; }

ItemExpr * CurrentTimestamp::construct
(CollHeap * heap, 
 DatetimeType::Subtype dtCode ,
 Lng32 fractPrec)
{
  ItemExpr * ie = new(heap) CurrentTimestamp(dtCode, fractPrec);

  if ((fractPrec != SQLTimestamp::DEFAULT_FRACTION_PRECISION) ||
      (dtCode != DatetimeType::SUBTYPE_SQLTimestamp))
    {
      if (dtCode == DatetimeType::SUBTYPE_SQLDate)
        ie = new (heap)
          Cast(ie, new (heap) SQLDate(heap, FALSE));
      else if (dtCode == DatetimeType::SUBTYPE_SQLTime)
        ie = new (heap)
          Cast(ie, new (heap) SQLTime(heap, FALSE, fractPrec));
      else
        ie = new (heap)
          Cast(ie, new (heap) SQLTimestamp(heap, FALSE, fractPrec));
    }

  return ie;
}

// -----------------------------------------------------------------------
// member functions for class CurrentTimestampRunning
// -----------------------------------------------------------------------
CurrentTimestampRunning::~CurrentTimestampRunning() {}

ItemExpr * CurrentTimestampRunning::copyTopNode(ItemExpr *derivedNode,
						CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) CurrentTimestampRunning();
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result,outHeap);

} // CurrentTimestampRunning::copyTopNode()

// -----------------------------------------------------------------------
// member functions for class DateFormat
// -----------------------------------------------------------------------
DateFormat::~DateFormat() {}

ItemExpr * DateFormat::copyTopNode(ItemExpr *derivedNode,
				   CollHeap* outHeap)
{
  DateFormat *result;

  if (derivedNode == NULL)
    result = new (outHeap) DateFormat(child(0), 
                                      formatStr_, formatType_, 
                                      wasDateformat_);
  else
    result = (DateFormat*)derivedNode;

  result->frmt_ = frmt_;
  result->dateFormat_ = dateFormat_;

  return BuiltinFunction::copyTopNode(result,outHeap);

} // DateFormat::copyTopNode()

NABoolean DateFormat::hasEquivalentProperties(ItemExpr * other)
{
  if (other == NULL)
    return FALSE;
  if (getOperatorType() != other->getOperatorType() || 
        getArity() != other->getArity())
    return FALSE;

  DateFormat * df = (DateFormat *) other;

  return 
      (this->dateFormat_ == df->dateFormat_);
}

void DateFormat::unparse(NAString &result,
		      PhaseEnum phase,
                      UnparseFormatEnum form,
		      TableDesc * tabId) const
{
  if (wasDateformat_)
    result += "DATEFORMAT(";
  else if (formatType_ == FORMAT_TO_DATE)
    result += "TO_DATE(";
  else if (formatType_ == FORMAT_TO_CHAR)
    result += "TO_CHAR(";
  else
    result += "unknown(";

  child(0)->unparse(result, phase, form, tabId);

  result += ", ";

  if (wasDateformat_)
    {
      if (frmt_ == ExpDatetime::DATETIME_FORMAT_DEFAULT)
        result += "DEFAULT";
      else if (frmt_ == ExpDatetime::DATETIME_FORMAT_USA)
        result += "USA";
      else if (frmt_ == ExpDatetime::DATETIME_FORMAT_EUROPEAN)
        result += "EUROPEAN";
      else
        result += "unknown";
    }
  else
    {
      result += "'";
      result += formatStr_;
      result += "'";
    }

  result += ")";  
}

// -----------------------------------------------------------------------
// member functions for class DayOfWeek
// -----------------------------------------------------------------------
DayOfWeek::~DayOfWeek() {}

ItemExpr * DayOfWeek::copyTopNode(ItemExpr *derivedNode,
				  CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) DayOfWeek(child(0));
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result,outHeap);

} // DayOfWeek::copyTopNode()

// -----------------------------------------------------------------------
// member functions for class ExplodeVarchar
// -----------------------------------------------------------------------
ExplodeVarchar::~ExplodeVarchar() {}

ItemExpr * ExplodeVarchar::copyTopNode(ItemExpr *derivedNode,
				       CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) ExplodeVarchar(child(0), type_, forInsert_);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result,outHeap);

} // ExplodeVarchar::copyTopNode()

// -----------------------------------------------------------------------
// member functions for class Extract
// -----------------------------------------------------------------------
Extract::~Extract() {}

NABoolean Extract::duplicateMatch(const ItemExpr & other) const
{
  if (NOT genericDuplicateMatch(other))
    return FALSE;

  Extract &o = (Extract &) other;

  // compare any local data members of the derived class
  // and return FALSE if they don't match
  if (extractField_ != o.extractField_)
    return FALSE;

  return TRUE;
}

ItemExpr * Extract::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) Extract(getExtractField(), child(0), getFieldFunction());
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // Extract::copyTopNode()

ItemExpr * ExtractOdbc::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) ExtractOdbc(getExtractField(), child(0), getFieldFunction());
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // Extract::copyTopNode()

NABoolean Extract::isAUserSuppliedInput() const             
{ 
   ItemExpr * extractChild = NULL;
   if ( child(0) && (child(0)->getOperatorType() == ITM_CAST) && 
	child(0)->child(0) )
      extractChild = child(0)->child(0)->castToItemExpr();
   else if (child(0))
	extractChild = child(0)->castToItemExpr();

   if ((CmpCommon::getDefault(COMP_BOOL_185) == DF_ON) &&
       (extractChild && extractChild->isAUserSuppliedInput()) &&
       (NOT(extractChild->doesExprEvaluateToConstant(FALSE))))
      return TRUE; 
   else
      return FALSE;
} // Extract::isAUserSuppliedInput() 

// ----------------------------------------------------------------------
// Walk through an ItemExpr tree and gather the ValueIds of those
// expressions that behave as if they are "leaves" for the sake of
// the coverage test. In this case it is expressions of the type
// extract(cast(timestamp))
// ----------------------------------------------------------------------
void Extract::getLeafValuesForCoverTest(ValueIdSet & leafValues, 
                                        const GroupAttributes& coveringGA,
                                        const ValueIdSet & newExternalInputs) const
{ 
  if (isAUserSuppliedInput())
    leafValues += getValueId();
  else
    BuiltinFunction::getLeafValuesForCoverTest(leafValues, coveringGA, newExternalInputs);
}


NABoolean Extract::hasEquivalentProperties(ItemExpr * other)
{
  if (other == NULL)
    return FALSE;
  if (getOperatorType() != other->getOperatorType() || 
        getArity() != other->getArity())
    return FALSE;

  Extract * tmp = (Extract *) other;

  return 
    (this->extractField_ == tmp->extractField_ ) &&
      (this->fieldFunction_ == tmp->fieldFunction_);
}

QR::ExprElement Extract::getQRExprElem() const
{
  return QR::QRFunctionWithParameters;
}

// -----------------------------------------------------------------------
// member functions for class JulianTimestamp
// -----------------------------------------------------------------------
JulianTimestamp::~JulianTimestamp() {}

ItemExpr * JulianTimestamp::copyTopNode(ItemExpr *derivedNode,
					CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) JulianTimestamp(child(0));
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result,outHeap);

} // JulianTimestamp::copyTopNode()

// Fix for cr 10-010718-3967
// We dont need this method, the reason this method was added was to return
// true, the ItemExpr method already returns false, so we don't need this
// method. So basically we want FALSE to be returned for JulianTimestamp all
// the time.
// NABoolean JulianTimestamp::isAUserSuppliedInput() const      { return TRUE; }

// -----------------------------------------------------------------------
// member functions for class StatementExecutionCount
// -----------------------------------------------------------------------

NABoolean StatementExecutionCount::isAUserSuppliedInput() const { return TRUE; }

ItemExpr * StatementExecutionCount::copyTopNode(ItemExpr *derivedNode,
						CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) StatementExecutionCount();
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result,outHeap);
}

// -----------------------------------------------------------------------
// member functions for class CurrentTransId
// -----------------------------------------------------------------------

NABoolean CurrentTransId::isAUserSuppliedInput() const { return TRUE; }

ItemExpr * CurrentTransId::copyTopNode(ItemExpr *derivedNode,
				       CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) CurrentTransId();
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result,outHeap);
}

// -----------------------------------------------------------------------
// member functions for class Upper
// -----------------------------------------------------------------------
Upper::~Upper() {}

ItemExpr * Upper::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) Upper(child(0));
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // Upper::copyTopNode()

// -----------------------------------------------------------------------
// member functions for class Lower
// -----------------------------------------------------------------------
Lower::~Lower() {}

ItemExpr * Lower::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) Lower(child(0));
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // Lower::copyTopNode()

// -----------------------------------------------------------------------
// member functions for class Trim
// -----------------------------------------------------------------------
Trim::~Trim() {}

ItemExpr * Trim::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) Trim(getTrimMode(), child(0), child(1));
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // Trim::copyTopNode()

NABoolean Trim::hasEquivalentProperties(ItemExpr * other)
{
  if (other == NULL)
    return FALSE;
  if (getOperatorType() != other->getOperatorType() || 
        getArity() != other->getArity())
    return FALSE;

  Trim * t = (Trim *) other;

  return 
    (mode_ == t->mode_);
}
// -----------------------------------------------------------------------
// member functions for class Increment
// -----------------------------------------------------------------------
Increment::~Increment() {}

ItemExpr * Increment::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) Increment(child(0));
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // Increment::copyTopNode()

// -----------------------------------------------------------------------
// member functions for class Decrement
// -----------------------------------------------------------------------
Decrement::~Decrement() {}

ItemExpr * Decrement::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) Decrement(child(0));
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // Decrement::copyTopNode()

// -----------------------------------------------------------------------
// member functions for class TriRelational
// -----------------------------------------------------------------------

TriRelational::TriRelational(OperatorTypeEnum optype,
			     ItemExpr *val1Ptr,
			     ItemExpr *val2Ptr,
			     ItemExpr *val3Ptr)
     : BuiltinFunction(optype, CmpCommon::statementHeap(),
                       3, val1Ptr, val2Ptr, val3Ptr)
{
  CMPASSERT(optype == ITM_LESS_OR_LE OR
	 optype == ITM_GREATER_OR_GE);
}

TriRelational::~TriRelational() {}

ItemExpr * TriRelational::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) TriRelational(getOperatorType(),NULL,NULL,NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

// -----------------------------------------------------------------------
// member functions for ScalarVariance
// -----------------------------------------------------------------------
ScalarVariance::~ScalarVariance() {}

ItemExpr *
ScalarVariance::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    {
      CMPASSERT(getArity() == 3);
      result = new (outHeap)
	ScalarVariance(getOperatorType(), child(0), child(1), child(2));
    }
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // ScalarVariance::copyTopNode()


// -----------------------------------------------------------------------
// member functions for UnPackCol
// -----------------------------------------------------------------------
//
UnPackCol::~UnPackCol() {}

ItemExpr *
UnPackCol::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    {
      CMPASSERT(getArity() == 2);
      result = new (outHeap)
	UnPackCol(child(0),
		  child(1),
		  width_,
		  base_,
		  nullsPresent_,
		  type_->newCopy(outHeap));
    }
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // UnPackCol::copyTopNode()

NABoolean UnPackCol::isCovered(const ValueIdSet& newExternalInputs,
                               const GroupAttributes& newRelExprAnchorGA,
                               ValueIdSet& referencedInputs,
                               ValueIdSet& coveredSubExpr,
                               ValueIdSet& unCoveredExpr) const
{
  // ---------------------------------------------------------------------
  // If the operand is covered, then return its ValueId in coveredSubExpr.
  // ---------------------------------------------------------------------
  ValueIdSet localSubExpr;
  for(Lng32 i = 0; i < (Lng32)getArity(); i++)
  {
    if(newRelExprAnchorGA.covers(child(i)->getValueId(),
                                 newExternalInputs,
                                 referencedInputs,
                                 &localSubExpr))
    {
      coveredSubExpr += child(i)->getValueId();
    }
  }

  // ---------------------------------------------------------------------
  // The UnPackCol function is coerced to fail the coverage test even when
  // its operands isCovered(). This is because only the UnPackCol node can
  // evaluate the function. The function is associated with a UnPackCol
  // node at the very beginning and we don't allow it to be pushed down
  // even if the function's operands are covered at the node's child.
  // ---------------------------------------------------------------------
  return FALSE;
}

void UnPackCol::getLeafValuesForCoverTest(ValueIdSet& leafValues, 
                                          const GroupAttributes& coveringGA,
                                          const ValueIdSet & newExternalInputs) const
{
  // UnPackCol is considered a leaf operator for cover test.
  leafValues += getValueId();
}

// -----------------------------------------------------------------------
// member functions for RowsetArrayScan
// -----------------------------------------------------------------------
//
RowsetArrayScan::~RowsetArrayScan() {}

ItemExpr *
RowsetArrayScan::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL) {
    CMPASSERT(getArity() == 2);
    result = new (outHeap)
      RowsetArrayScan(child(0),
                      child(1),
                      maxNumElem_,
                      elemSize_,
                      elemNullInd_,
                      elemType_->newCopy(outHeap),
                      getOperatorType());
  }
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

}

NABoolean RowsetArrayScan::isCovered(const ValueIdSet& newExternalInputs,
                                     const GroupAttributes& newRelExprAnchorGA,
                                     ValueIdSet& referencedInputs,
                                     ValueIdSet& coveredSubExpr,
                                     ValueIdSet& unCoveredExpr) const
{
  // ---------------------------------------------------------------------
  // If the operand is covered, then return its ValueId in coveredSubExpr.
  // ---------------------------------------------------------------------
  ValueIdSet localSubExpr;
  for (Lng32 i = 0; i < (Lng32)getArity(); i++) {
    if (newRelExprAnchorGA.covers(child(i)->getValueId(),
                                  newExternalInputs,
                                  referencedInputs,
                                  &localSubExpr)) {
      coveredSubExpr += child(i)->getValueId();
    }

    coveredSubExpr += localSubExpr;

  }

  // ---------------------------------------------------------------------
  // The RowsetArrayScan function is coerced to fail the coverage test even
  // when its operands isCovered(). This is because only the RowsetArrayScan
  // node can evaluate the function. The function is associated with a
  // RowsetArrayScan node at the very beginning and we don't allow it to be
  // pushed down even if the function's operands are covered at the node's
  // child.
  // ---------------------------------------------------------------------
  return FALSE;
}

void RowsetArrayScan::getLeafValuesForCoverTest(ValueIdSet& leafValues, 
                                                const GroupAttributes& coveringGA,
                                                const ValueIdSet & newExternalInputs) const
{
  // RowsetArrayScan is considered a leaf operator for cover test.
  leafValues += getValueId();
}

// -----------------------------------------------------------------------
// member functions for RowsetArrayInto
// -----------------------------------------------------------------------
//
RowsetArrayInto::~RowsetArrayInto() {}

ItemExpr *
RowsetArrayInto::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL) {
    CMPASSERT(getArity() == 2);
    result = new (outHeap)
      RowsetArrayInto(child(0),
                      child(1),
                      maxNumElem_,
                      elemSize_,
                      elemNullInd_,
                      hostVarType_->newCopy(outHeap),
                      getOperatorType());
  }
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

NABoolean RowsetArrayInto::isCovered(const ValueIdSet& newExternalInputs,
                                     const GroupAttributes& newRelExprAnchorGA,
                                     ValueIdSet& referencedInputs,
                                     ValueIdSet& coveredSubExpr,
                                     ValueIdSet& unCoveredExpr) const
{
  // ---------------------------------------------------------------------
  // If the operand is covered, then return its ValueId in coveredSubExpr.
  // ---------------------------------------------------------------------
  ValueIdSet localSubExpr;
  for (Lng32 i = 0; i < (Lng32)getArity(); i++) {
    if (newRelExprAnchorGA.covers(child(i)->getValueId(),
                                  newExternalInputs,
                                  referencedInputs,
                                  &localSubExpr)) {
      coveredSubExpr += child(i)->getValueId();
    }
    coveredSubExpr += localSubExpr;
  }

  // ---------------------------------------------------------------------
  // The RowsetArrayInto function is coerced to fail the coverage test even
  // when its operands isCovered(). This is because only the RowsetArrayInto
  // node can evaluate the function. The function is associated with a
  // RowsetArrayInto node at the very beginning and we don't allow it to be
  // pushed down even if the function's operands are covered at the node's
  // child.
  // ---------------------------------------------------------------------
  return FALSE;
}

void RowsetArrayInto::getLeafValuesForCoverTest(ValueIdSet& leafValues, 
                                                const GroupAttributes& coveringGA,
                                                const ValueIdSet & newExternalInputs) const
{
  // RowsetArrayScan is considered a leaf operator for cover test.
  leafValues += getValueId();
}

// -----------------------------------------------------------------------
// member functions for class RangeLookup
// -----------------------------------------------------------------------

RangeLookup::RangeLookup(ItemExpr *val1Ptr,
			 const RangePartitioningFunction *partFunc) :
     BuiltinFunction(ITM_RANGE_LOOKUP, CmpCommon::statementHeap(), 1, val1Ptr),
     partFunc_(partFunc)
{
}

RangeLookup::~RangeLookup() {}

ItemExpr * RangeLookup::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) RangeLookup(NULL,partFunc_);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

Lng32 RangeLookup::splitKeysLen()
{
  // we assume a dense array of character strings, with #parts + 1 entries
  // (no NULL terminators, no fillers)
  return (partFunc_->getCountOfPartitions() + 1) *
    partFunc_->getRangePartitionBoundaries()->getEncodedBoundaryKeyLength();
}

void RangeLookup::copySplitKeys(char *tgt, Lng32 tgtLen)
{
  CMPASSERT(tgtLen = splitKeysLen());
  const RangePartitionBoundaries * b =
    partFunc_->getRangePartitionBoundaries();
  Lng32 numEntries = partFunc_->getCountOfPartitions() + 1;
  Lng32 entryLen   = b->getEncodedBoundaryKeyLength();
  Lng32 offset     = 0;

  for (Lng32 i = 0; i < numEntries; i++)
    {
      str_cpy_all(&tgt[offset],
		  b->getBinaryBoundaryValue(i),
		  entryLen);
      offset += entryLen;
    }
}

Lng32 RangeLookup::getNumOfPartitions()
{
  return partFunc_->getCountOfPartitions();
}

Lng32 RangeLookup::getEncodedBoundaryKeyLength()
{
  return partFunc_->getRangePartitionBoundaries()->
    getEncodedBoundaryKeyLength();
}

// -----------------------------------------------------------------------
// member functions for class PackFunc
// -----------------------------------------------------------------------

PackFunc::PackFunc(ItemExpr* val1Ptr,
                   ItemExpr* pf,
                   Lng32 base,
                   Lng32 width,
                   NABoolean nullsPresent)
 : BuiltinFunction(ITM_PACK_FUNC,
                   CmpCommon::statementHeap(),
                   2,val1Ptr,pf),
   isFormatInfoValid_(TRUE),
   base_(base),
   width_(width),
   nullsPresent_(nullsPresent),
   type_(NULL)
{
  deriveTypeFromFormatInfo();
}

PackFunc::PackFunc(ItemExpr* val1Ptr,
                  ItemExpr* pf,
                  const NAType* unpackType)
 : BuiltinFunction(ITM_PACK_FUNC,
                   CmpCommon::statementHeap(),
                   2,val1Ptr,pf),
   isFormatInfoValid_(FALSE)
{
  deriveFormatInfoFromUnpackType(unpackType);
}

void PackFunc::deriveTypeFromFormatInfo()
{
  CMPASSERT(isFormatInfoValid_);

  // The packing factor must be stored as a constant.
  NABoolean negateIt;
  ConstValue* pfconst = child(1)->castToConstValue(negateIt);
  CMPASSERT(pfconst AND negateIt == FALSE);

  // The packing factor must be stored as a long in the constant.
  CMPASSERT(pfconst->getStorageSize() == sizeof(Lng32));
  CMPASSERT(pfconst->getType()->getTypeQualifier() == NA_NUMERIC_TYPE);
  Lng32 pf;
  memcpy(&pf,pfconst->getConstValue(),sizeof(Lng32));

  Lng32 dataSizeInBytes = (width_ < 0 ? (-width_-1)/8+1 : width_);
  Lng32 packedRowSizeInBytes = (base_ + dataSizeInBytes);
  type_ = new(CmpCommon::statementHeap()) SQLChar(CmpCommon::statementHeap(), packedRowSizeInBytes,FALSE);
}

void PackFunc::deriveFormatInfoFromUnpackType(const NAType* unpackType)
{
  CMPASSERT(unpackType);

  // Packing of varying length column not (yet?) supported.
  // It should have been enforced when the packed table is created.
  CMPASSERT(NOT DFS2REC::isAnyVarChar(unpackType->getFSDatatype()));

  // Save four byte for the packing factor to be stored.
  Lng32 pfSizeInBytes = sizeof(Int32);

  // The packing factor must be stored as a constant.
  NABoolean negateIt;
  ConstValue* pfconst = child(1)->castToConstValue(negateIt);
  CMPASSERT(pfconst AND negateIt == FALSE);

  // The packing factor must be stored as a long in the constant.
  CMPASSERT(pfconst->getStorageSize() == sizeof(Lng32));
  CMPASSERT(pfconst->getType()->getTypeQualifier() == NA_NUMERIC_TYPE);
  Lng32 pf;
  memcpy(&pf,pfconst->getConstValue(),sizeof(Lng32));

  // No of bits reserved for null indicators.
  nullsPresent_ = unpackType->supportsSQLnullPhysical();
  Lng32 nullIndLenInBytes = (nullsPresent_ ? (pf-1)/8+1 : 0);
  base_ = pfSizeInBytes + nullIndLenInBytes;

  // Storage size for the actual packed column values in bytes.
  Lng32 dataSizeInBytes;

  // For bit precision integers, width needs to be in negative no of bits.
  if(unpackType->getFSDatatype() == REC_BPINT_UNSIGNED)
  {
    width_ = ((SQLBPInt*)unpackType)->getDeclaredLength();
    dataSizeInBytes = (width_*pf-1)/8+1;
    width_ = -width_;
  }
  else
  {
    width_ = unpackType->getNominalSize();
    dataSizeInBytes = width_ * pf;
  }

  // Now, the length of the contents of a packed record in bytes.
  Lng32 packedRowSizeInBytes = (base_ + dataSizeInBytes);

  // Synthesize type of the packed column.
  type_ = new(CmpCommon::statementHeap()) SQLChar(CmpCommon::statementHeap(), packedRowSizeInBytes,FALSE);
  isFormatInfoValid_ = TRUE;
}

PackFunc::~PackFunc() {}

NABoolean PackFunc::isCovered(const ValueIdSet& newExternalInputs,
                              const GroupAttributes& newRelExprAnchorGA,
                              ValueIdSet& referencedInputs,
                              ValueIdSet& coveredSubExpr,
                              ValueIdSet& unCoveredExpr) const
{
  // ---------------------------------------------------------------------
  // If the operand is covered, then return its ValueId in coveredSubExpr.
  // ---------------------------------------------------------------------
  ValueIdSet localSubExpr;
  for(Lng32 i = 0; i < (Lng32)getArity(); i++)
  {
    if(newRelExprAnchorGA.covers(child(i)->getValueId(),
                                 newExternalInputs,
                                 referencedInputs,
                                 &localSubExpr))
    {
      coveredSubExpr += child(i)->getValueId();
    }
  }

  // ---------------------------------------------------------------------
  // The packing function is coerced to fail the coverage test even when
  // its operands isCovered(). This is because only the Pack node can
  // evaluate a packing function. The function is associated with a Pack
  // node at the very beginning and we don't allow it to be pushed down
  // even if the function's operands are covered at the Pack node's child.
  // ---------------------------------------------------------------------
  return FALSE;
}

void PackFunc::getLeafValuesForCoverTest(ValueIdSet& leafValues, 
                                         const GroupAttributes& coveringGA,
                                         const ValueIdSet & newExternalInputs) const
{
  // see note in isCovered().
  leafValues += getValueId();
}

ItemExpr* PackFunc::copyTopNode(ItemExpr* derivedNode, CollHeap* outHeap)
{
  ItemExpr* result;

  if(derivedNode == NULL)
    result = new (outHeap) PackFunc (child(0),child(1));
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result,outHeap);
}

UDFunction::~UDFunction()
{
  delete udfDesc_;
}

Int32 UDFunction::getArity() const
{
  return getNumChildren(); // Function class member function.
}

const NAString UDFunction::getText() const
{
  return functionName_.getExternalName();
}

HashValue UDFunction::topHash()
{
  HashValue result = ItemExpr::topHash();

  // hash any local data members of the derived class
  result ^= functionName_.getExternalName() + actionName_;

  return result;
}

NABoolean Function::duplicateMatch(const ItemExpr & other) const
{
  if (NOT genericDuplicateMatch(other))
    return FALSE;

  return TRUE;
}

NABoolean UDFunction::duplicateMatch(const ItemExpr & other) const
{
  // Check to see if the arguments are the same, among other things.
  if (NOT genericDuplicateMatch(other))
    return FALSE;

  UDFunction &o = (UDFunction &) other;

  // compare all local data members of the derived class
  // and return FALSE if they don't match
  if (functionName_.getExternalName() != o.functionName_.getExternalName() ||
      actionName_                     != o.actionName_  ||
      hasSubquery_                    != o.hasSubquery_ ||
      inputVars_                      != o.inputVars_   ||
      outputVars_                     != o.outputVars_)
    return FALSE;

  if (udfDesc_ && o.udfDesc_) // RoutineDesc pointers
    if (!(*udfDesc_ == *o.udfDesc_))
      return FALSE;

  if (udfDesc_ != NULL || o.udfDesc_ != NULL) // Both must be NULL to proceed.
    return FALSE;


  return TRUE;
}

ItemExpr *UDFunction::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  UDFunction *result;

  if (derivedNode == NULL)
    result = new (outHeap) UDFunction(functionName_, getArity(), outHeap);
  else
    result = (UDFunction *) derivedNode;

  result->heap_        = outHeap;
  result->functionName_= functionName_;
  result->functionNamePos_= functionNamePos_;
  result->actionName_  = actionName_  ;
  result->udfDesc_     = udfDesc_ != NULL ? 
                           new (outHeap) RoutineDesc(*udfDesc_, outHeap) : NULL;
  result->hasSubquery_ = hasSubquery_ ;
  result->inputVars_   = inputVars_   ;
  result->outputVars_  = outputVars_  ;


  return Function::copyTopNode(result, outHeap);
}

void UDFunction::unparse(NAString &result,
		      PhaseEnum phase,
                      UnparseFormatEnum form,
		      TableDesc * tabId) const
{
  NAString kwd(getText(), CmpCommon::statementHeap());
  if (form == USER_FORMAT_DELUXE) kwd.toUpper();
  result += kwd;
  result += "(";
  CollIndex lastComma = getNumChildren() -1;
  for (CollIndex i=0; i<(CollIndex ) getNumChildren(); i++)
  {
     child(i)->unparse(result,phase,form,tabId);
     if (i < lastComma) result += ",";
  }
  result += ")";

}

ExprValueId &UDFunction::operator[] (Lng32 index)
{
  return Function::operator[](index);
}
const ExprValueId &UDFunction::operator[] (Lng32 index) const
{
  return Function::operator[](index);
}

ItemExpr *UDFunction::containsUDF()
{
  return this;
}

NABoolean UDFunction::containsIsolatedUDFunction()
{
  NABoolean containsIsolatedUDF(FALSE);

  for (CollIndex i=0; i < (CollIndex) getNumChildren(); i++)
  {
    if (child(i)->containsIsolatedUDFunction() == TRUE)
      containsIsolatedUDF = TRUE;
  }

  if (containsIsolatedUDF == TRUE) 
    return TRUE;

  // We didn't have one as an input parameter, check to see if we
  // are isolated..
  const RoutineDesc *rdesc = getRoutineDesc();
  if (rdesc == NULL || rdesc->getEffectiveNARoutine() == NULL ) return FALSE;  
  return ( rdesc->getEffectiveNARoutine()->isIsolate() ? TRUE : FALSE ) ;
} // UDFunction::containsIsolatedUDFunction

// Get the output degree of this function.  If it is >1, getOutputItem
// should be used to get the ItemExpr of each output.
int UDFunction::getOutputDegree()
{
  CCMPASSERT(getRoutineDesc() != NULL);
  if (!getRoutineDesc()) return -1; // Routine desc not set.  Error.
  else 
    return getRoutineDesc()->getOutputColumnList().entries();
}

// Get i'th output argument of UDF as ItemExpr.
ItemExpr *UDFunction::getOutputItem(unsigned int i)
{
  CCMPASSERT(getRoutineDesc() != NULL);
  if (!getRoutineDesc()) return NULL; // Routine desc not set.  Error.
  else 
  {
    if (i < getRoutineDesc()->getOutputColumnList().entries())
      return getRoutineDesc()->getOutputColumnList()[i].getItemExpr();
    else return NULL; // 'i' out of bounds.  Error.
  }
}

ItemExpr * NotIn::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  NotIn *result;

  if (derivedNode == NULL)
    result = new (outHeap) NotIn();
  else
    result = (NotIn *) derivedNode;

  //copy the data members
  result->equivEquiPredicate_ = equivEquiPredicate_;
  result->equivNonEquiPredicate_ = equivNonEquiPredicate_;
  result->isOneInnerBroadcastRequired_ = isOneInnerBroadcastRequired_;

  return BiRelat::copyTopNode(result, outHeap);
}

ValueId NotIn::createEquivEquiPredicate() const
{
  CMPASSERT ( child(0)->getOperatorType() != ITM_ITEM_LIST && 
              child(1)->getOperatorType() != ITM_ITEM_LIST) 

  ItemExpr * newPred = new (CmpCommon::statementHeap()) 
                        BiRelat(ITM_EQUAL, 
                                child(0),
                                child(1));
   
  newPred->synthTypeAndValueId(TRUE);
  
  return newPred->getValueId();
}
ValueId NotIn::createEquivNonEquiPredicate() const
{
  CMPASSERT ( child(0)->getOperatorType() != ITM_ITEM_LIST && 
              child(1)->getOperatorType() != ITM_ITEM_LIST) 

  ItemExpr * newPred = new (CmpCommon::statementHeap()) 
                        BiRelat(ITM_NOT_EQUAL, 
                                child(0),
                                child(1));
            
  newPred = new (CmpCommon::statementHeap()) 
                        UnLogic(ITM_IS_TRUE, newPred);
 
  newPred = new (CmpCommon::statementHeap()) 
                        UnLogic(ITM_NOT, newPred);

  newPred->synthTypeAndValueId(TRUE);
    
  return newPred->getValueId();
}

void NotIn::cacheEquivEquiPredicate()
{
      
  if (getEquivEquiPredicate() == NULL_VALUE_ID)
  {
    ValueId vid = createEquivEquiPredicate();
        
    ItemExpr * itm = vid.getItemExpr();
        
    ((BiRelat *)itm)->setIsNotInPredTransform(TRUE); 
        
    ((BiRelat *)itm)->setOuterNullFilteringDetected(
                          getOuterNullFilteringDetected());
    ((BiRelat *)itm)->setInnerNullFilteringDetected(
                          getInnerNullFilteringDetected());

    setEquivEquiPredicate(vid);
  }
}

void NotIn::cacheEquivNonEquiPredicate()
{
  if (getEquivNonEquiPredicate() == NULL_VALUE_ID )
  {
    setEquivNonEquiPredicate(
		  createEquivNonEquiPredicate());
  }
}


void  NotIn::cacheIsOneInnerBroadcastRequired()
{

  if (isOneInnerBroadcastRequired_ == NotIn::NOT_SET)
  {

    isOneInnerBroadcastRequired_ = NotIn::NOT_REQUIRED;

    ItemExpr * child0 = child(0);
    const NAType &outerType = child0->getValueId().getType();

    if (outerType.supportsSQLnull()  &&
        !getOuterNullFilteringDetected())
    {
      isOneInnerBroadcastRequired_ = NotIn::REQUIRED;
    }
  }
  
}//NotIn::cacheIsOneInnerBroadcastRequired()




// -----------------------------------------------------------------------
// member functions for class BiLogic
// -----------------------------------------------------------------------
Int32 BiLogic::getArity() const { return 2; }

NABoolean BiLogic::isAPredicate() const { return TRUE; }

// return true iff we're an expansion of a LIKE predicate
NABoolean BiLogic::isLike() const
{
  switch (getOperatorType()) {
  case ITM_AND:
  case ITM_OR:
    {
      Int32 arity = getArity();
      for (Int32 x = 0; x < arity; x++) {
        switch (child(x)->getOperatorType()) {
        case ITM_GREATER_EQ:
        case ITM_LESS:
          if (!((BiRelat*)child(x).getPtr())->derivativeOfLike())
            return FALSE; // we're not an expansion of a LIKE predicate
          else // we may be part of an expansion of a LIKE predicate
            continue; // keep looking
          break;
        default:
          return FALSE; // we're not an expansion of a LIKE predicate
          break;
        }
      }
      return TRUE; // yes, we are an expansion of a LIKE predicate
    }
    break;
  default:
    return FALSE; // we're not an expansion of a LIKE predicate
  }
}

// -----------------------------------------------------------------------
// BiLogic::isCovered()
// -----------------------------------------------------------------------
NABoolean BiLogic::isCovered
                      (const ValueIdSet& newExternalInputs,
		       const GroupAttributes& coveringGA,
		       ValueIdSet& referencedInputs,
		       ValueIdSet& coveredSubExpr,
		       ValueIdSet& unCoveredExpr) const
{
  if (getOperatorType() == ITM_OR)
    {
      // ----------------------------------------------------------------
      // The subtree that is rooted in an OR can contain values that
      // are produced by different sources. The entire expression tree
      // including the OR at the root is covered, if the subtree that
      // is rooted in the OR is covered. Otherwise it is not covered.
      // The coverage test insists on a complete coverage of all the
      // expressions at the leaves.
      // ----------------------------------------------------------------
      ValueIdSet leafValues;
      getLeafValuesForCoverTest(leafValues, coveringGA, newExternalInputs);
      return leafValues.isCovered(newExternalInputs,
				  coveringGA,
				  referencedInputs,
				  coveredSubExpr,
				  unCoveredExpr);
    }
  else
    return ItemExpr::isCovered(newExternalInputs,
			       coveringGA,
			       referencedInputs,
			       coveredSubExpr,
			       unCoveredExpr);
} // BiLogic::isCovered()

NABoolean BiLogic::duplicateMatch(const ItemExpr& other) const
{
  return genericDuplicateMatch(other);
}

ItemExpr * BiLogic::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  BiLogic *result;

  if (derivedNode == NULL)
    result = new (outHeap) BiLogic(getOperatorType());
  else
    result = (BiLogic*)derivedNode;

  result->setNumLeaves(getNumLeaves());
  result->createdFromINlist_ = createdFromINlist_;

  return ItemExpr::copyTopNode(result, outHeap);
}

ItemExpr* BiLogic::getINlhs() 
{
  if (createdFromINlist() && child(1)->getOperatorType() == ITM_EQUAL)
    return child(1)->child(0);
  else
    return NULL;
}

const NAString BiLogic::getText() const
{
  switch (getOperatorType())
    {
    case ITM_AND:
      return "and";
    case ITM_OR:
      return "or";
    default:
      return "unknown BiLogic";
    } // switch
} // BiLogic::getText()

QR::ExprElement BiLogic::getQRExprElem() const
{
  return QR::QRBinaryOperElem;
}

// -----------------------------------------------------------------------
// member functions for class UnLogic
// -----------------------------------------------------------------------
Int32 UnLogic::getArity() const { return 1; }

NABoolean UnLogic::isAPredicate() const { return TRUE; }

const NAString UnLogic::getText() const
{
  switch (getOperatorType())
    {
    case ITM_NOT:
      return "not";
    case ITM_IS_TRUE:
      return "is true";
    case ITM_IS_FALSE:
      return "is false";
    case ITM_IS_NULL:
      return "is null";
    case ITM_IS_NOT_NULL:
      return "is not null";
    case ITM_IS_UNKNOWN:
      return "is unknown";
    case ITM_IS_NOT_UNKNOWN:
      return "is not unknown";
    default:
      return "unknown UnLogic??";
    } // switch
} // UnLogic::getText()

NABoolean UnLogic::duplicateMatch(const ItemExpr & other) const
{
  if (NOT genericDuplicateMatch(other))
    return FALSE;

  return TRUE;
}

ItemExpr * UnLogic::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) UnLogic(getOperatorType());
  else
    result = derivedNode;

  return ItemExpr::copyTopNode(result, outHeap);
}

QR::ExprElement UnLogic::getQRExprElem() const
{
  return QR::QRUnaryOperElem;
}

// -----------------------------------------------------------------------
// member functions for class BiRelat
// -----------------------------------------------------------------------
NABoolean BiRelat::derivativeOfLike()
{
  if (originalLikeExprId() != NULL_VALUE_ID)
    return TRUE;
  else
    return FALSE;
}

void BiRelat::adjustRowcountAndUecForLike(const ColStatDescSharedPtr& colStatDesc,
					CostScalar rowCountBeforePreds,
					CostScalar totalUecBeforePreds,
					CostScalar baseUecBeforePreds)
{
  // This range predicate is a derivative of Like predicate.
  // Hence we cannot use the usual selectivity obtained after
  // applying range predicates. Here we use a portion of the
  // default selectivity for like predicates to obtain the
  // resultant rowcount. We still continue to use the histograms
  // obtained after applying range predicates the usual way
  // The selectivity would be applied to the inital rowcount
  // before any predicates were applied.

  ColStatsSharedPtr colStats = colStatDesc->getColStatsToModify() ;

  CostScalar nrc  = MIN_ONE_CS(rowCountBeforePreds * getLikeSelectivity());
  CostScalar nuec = MIN_ONE_CS(totalUecBeforePreds * getLikeSelectivity());
  CostScalar baseuec = MIN_ONE_CS(baseUecBeforePreds * getLikeSelectivity());


  if ( colStats->isUnique() )
  {
    // If this is a UNIQUE column, UEC == rowcount
    nuec = nrc;
  }
  else
  {
    nuec = MINOF(nrc, nuec);
  }

  HistogramSharedPtr hist = colStats->getHistogramToModify() ;
  hist->condenseToSingleInterval();
  colStats->setIsCompressed(TRUE);

  // first, set the aggregate values
  colStats->setRowsAndUec  ( nrc, nuec );
  colStats->setRedFactor   ( csOne );
  colStats->setUecRedFactor( csOne );
  colStats->setBaseUec(baseuec);

  // Set first interval's rowcount and uec.
  hist->getFirstInterval().setRowsAndUec( nrc, nuec );

  // from this point forward, we're going to consider this a fake histogram
  colStats->setFakeHistogram();
}

Int32 BiRelat::getArity() const { return 2; }

NABoolean BiRelat::isAPredicate() const { return TRUE; }

const NAString BiRelat::getText() const
{
  switch (getOperatorType())
    {
    case ITM_EQUAL:
      return "=";
    case ITM_NOT_EQUAL:
      return "<>";
    case ITM_LESS:
      return "<";
    case ITM_LESS_EQ:
      return "<=";
    case ITM_GREATER:
      return ">";
    case ITM_GREATER_EQ:
      return ">=";
    default:
      return "unknown BiRelat";
    } // switch

 } // BiRelat::getText()

NABoolean BiRelat::duplicateMatch(const ItemExpr& other) const
{
  if (NOT genericDuplicateMatch(other))
    return FALSE;

  const BiRelat &o = (BiRelat &) other;

  if (specialNulls_ != o.specialNulls_ OR
      specialMultiValuePredicateTransformation_ !=
      o.specialMultiValuePredicateTransformation_ OR
      directionVector_ != o.directionVector_ /* ptr comparison only */ OR
      isaPartKeyPred_ != o.isaPartKeyPred_ OR
      originalLikeExprId_ != o.originalLikeExprId_ OR
      likeSelectivity_ != o.likeSelectivity_ OR
      derivedFromMCRP_ != o.derivedFromMCRP_ OR
      preferForSubsetScanKey_ != o.preferForSubsetScanKey_
      )
    return FALSE;


  // do this if this a range predicate derived from a MCRP
  // A MCRP (MultiColumnRangePredicate) is a predicate of the form
  // (a, b, c) > (1, 2, 3). Such a predicate is transformed to
  // (a >= 1) and ((a, b, c) > (1, 2, 3)). Notice the transformation
  // adds predicate (a >= 1). The derivedFromMCRP flag is set to TRUE
  // for predicate (a >= 1).
  if ((derivedFromMCRP_ == TRUE) &&
      (listOfComparisonExprs_ != o.listOfComparisonExprs_))
  {
    if (listOfComparisonExprIds_.entries() != o.listOfComparisonExprIds_.entries())
      return FALSE;

    for (CollIndex i=0; i < listOfComparisonExprIds_.entries(); i++)
    {
      if (listOfComparisonExprIds_[i] != o.listOfComparisonExprIds_[i])
        return FALSE;
    }
  }

  return TRUE;
}

ItemExpr * BiRelat::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  BiRelat *result;

  if (derivedNode == NULL)
    result = new (outHeap) BiRelat(getOperatorType());
  else
    result = (BiRelat *) derivedNode;

  // copy the data members
  result->specialNulls_ = specialNulls_;
  result->specialMultiValuePredicateTransformation_ =
    specialMultiValuePredicateTransformation_;
  result->isaPartKeyPred_ = isaPartKeyPred_;
  result->originalLikeExprId_ = originalLikeExprId_;

  result->setDirectionVector(directionVector_);
  result->likeSelectivity_ = likeSelectivity_;
  result->derivedFromMCRP_ = derivedFromMCRP_;
  result->listOfComparisonExprs_ = listOfComparisonExprs_;
  result->listOfComparisonExprIds_ = listOfComparisonExprIds_;
  result->leftMCRPChildList_ = leftMCRPChildList_;
  result->rightMCRPChildList_ = rightMCRPChildList_;
  result->preferForSubsetScanKey_ = preferForSubsetScanKey_;

  result->createdFromINlist_ = createdFromINlist_;
  
  result->collationEncodeComp_  = collationEncodeComp_;
  result->isNotInPredTransform_ = isNotInPredTransform_;
  result->outerNullFilteringDetected_= outerNullFilteringDetected_;
  result->innerNullFilteringDetected_ = innerNullFilteringDetected_;

  result->rollupColumnNum_ = rollupColumnNum_;

  result->flags_ = flags_;

  return ItemExpr::copyTopNode(result, outHeap);
}

void BiRelat::getLeftMCRPChildList(ValueIdList & leftMCRPChildList)
{
  if ((!isDerivedFromMCRP()) ||
      (!listOfComparisonExprIds_.entries()))
    return;

  if (leftMCRPChildList_.entries())
  {
    leftMCRPChildList = leftMCRPChildList_;
    return;
  }

  // iterate over the list of comparisons
  for(CollIndex i=0; i < listOfComparisonExprIds_.entries(); i++)
  {
    //get comparison at location i
    BiRelat * comparison = (BiRelat *) listOfComparisonExprIds_[i].getItemExpr();

    ItemExpr * leftChild = (ItemExpr *) comparison->child(0);
    ItemExpr * rightChild = (ItemExpr *) comparison->child(1);
    leftMCRPChildList_.insert(leftChild->getValueId());
    rightMCRPChildList_.insert(rightChild->getValueId());
  }

  leftMCRPChildList = leftMCRPChildList_;
}

void BiRelat::getRightMCRPChildList(ValueIdList & rightMCRPChildList)
{
  if ((!isDerivedFromMCRP()) ||
      (!listOfComparisonExprIds_.entries()))
    return;

  if (rightMCRPChildList_.entries())
  {
    rightMCRPChildList = rightMCRPChildList_;
    return;
  }

  // iterate over the list of comparisons
  for(CollIndex i=0; i < listOfComparisonExprIds_.entries(); i++)
  {
    //get comparison at location i
    BiRelat * comparison = (BiRelat *) listOfComparisonExprIds_[i].getItemExpr();

    ItemExpr * leftChild = (ItemExpr *) comparison->child(0);
    ItemExpr * rightChild = (ItemExpr *) comparison->child(1);
    leftMCRPChildList_.insert(leftChild->getValueId());
    rightMCRPChildList_.insert(rightChild->getValueId());
  }

  rightMCRPChildList = rightMCRPChildList_;
}

QR::ExprElement BiRelat::getQRExprElem() const
{
  return QR::QRBinaryOperElem;
}

OperatorTypeEnum BiRelat::getRelaxedComparisonOpType() const
{
  switch (getOperatorType())
   {
   case ITM_LESS:
     return ITM_LESS_EQ;

   case ITM_GREATER:
     return ITM_GREATER_EQ;

   case ITM_NOT_EQUAL:
     CMPASSERT(0); // the relaxed form would be TRUE,
                   // but we don't handle that right now

   default:
     break;
   }

 return getOperatorType();
}


// Member functions for class KeyRangeCompare //

const NAString KeyRangeCompare::getText() const
{

  NAString result("", CmpCommon::statementHeap());

  switch (getOperatorType())
    {
    case ITM_EQUAL:
      result += "=";
      break;
    case ITM_NOT_EQUAL:
      result += "<>";
      break;
    case ITM_LESS:
      result += "<";
      break;
    case ITM_LESS_EQ:
      result += "<=";
      break;
    case ITM_GREATER:
      result += ">";
      break;
    case ITM_GREATER_EQ:
      result += ">=";
      break;
    default:
      result +=  "unknown BiRelat";
      return result;
    } // switch

  result += " (KEY_RANGE_COMPARE)";

  return result;

 } // KeyRangeCompare::getText()

// -----------------------------------------------------------------------
// member functions for class ConstValue
// -----------------------------------------------------------------------
// constructor for an untyped NULL constant
ConstValue::ConstValue()
: ItemExpr(ITM_CONSTANT)
     , isNull_(IS_NULL)
     , type_(new (CmpCommon::statementHeap()) SQLUnknown(CmpCommon::statementHeap(), TRUE))
     , value_(NULL)
     , storageSize_(0)
     , text_(new (CmpCommon::statementHeap()) NAString("NULL", CmpCommon::statementHeap()))
     , textIsValidatedSQLLiteralInUTF8_(FALSE)
     , isSystemSupplied_(FALSE)
     , locale_strval(0)
     , locale_wstrval(0)
     , isStrLitWithCharSetPrefix_(FALSE)
     , rebindNeeded_(FALSE)
{
}

// constructor for a numeric constant
ConstValue::ConstValue(Lng32 intval, NAMemory * outHeap)
           : ItemExpr(ITM_CONSTANT)
           , isNull_(IS_NOT_NULL)
           , textIsValidatedSQLLiteralInUTF8_(FALSE)
           , type_(new (CmpCommon::statementHeap()) SQLInt(CmpCommon::statementHeap(), TRUE, FALSE))
	   , isSystemSupplied_(FALSE)
           , locale_strval(0)
           , locale_wstrval(0)
           , isStrLitWithCharSetPrefix_(FALSE)
           , rebindNeeded_(FALSE)
{
  Int64 lintval = intval;
  char buf[TEXT_DISPLAY_LENGTH];
  char * S = buf;
  Int32 len = 0;
  sprintf(S,"%d %n",intval, &len);
  S[len++] = '\0';
  text_ = new (outHeap) NAString(S, outHeap);
  storageSize_ = sizeof(Lng32);
  value_ = (void *)( new (outHeap) char[storageSize_] );
  // copy the bit pattern as is
  memcpy(value_,(void *)(&intval),(Int32)storageSize_);
}

ConstValue::ConstValue(const NAString & strval,
             enum CharInfo::CharSet charSet,
             enum CharInfo::Collation collation,
             enum CharInfo::Coercibility coercibility,
             NAMemory * outHeap)
: ItemExpr(ITM_CONSTANT), isNull_(IS_NOT_NULL),
  textIsValidatedSQLLiteralInUTF8_(FALSE), isStrLitWithCharSetPrefix_(FALSE),
  isSystemSupplied_(FALSE), locale_wstrval(0), rebindNeeded_(FALSE)
{
   initCharConstValue(strval, charSet, collation, coercibility, FALSE, outHeap);
   locale_strval = new (outHeap) NAString
    ((char*)strval.data(), strval.length(), outHeap);
}

void ConstValue::initCharConstValue
(
     const NAString & strval,
     enum CharInfo::CharSet charSet,
     enum CharInfo::Collation collation,
     enum CharInfo::Coercibility coercibility,
     NABoolean isCaseInSensitive,
     NAMemory * outHeap
     )
{

  if (strval.length() == 0)
    {
      // create a varchar constant of length 0, in this case.
      type_ = new (outHeap)
		SQLVarChar(outHeap, 0, FALSE, FALSE, FALSE,
			   charSet, collation, coercibility);
      storageSize_ = type_->getVarLenHdrSize();
      value_ = (void *)( new (outHeap) 
			 char[storageSize_] );
      str_pad((char *)value_, (Int32)storageSize_, '\0');
    }
  else
    {

      // A "mini-cache" to avoid proc call, for performance,
      // local to the SINGLE-byte-charset NAString ctor
      // (distinct from the double-byte-charset ctor to prevent cache churn).
      static THREAD_P CharInfo::CharSet cachedCS  = CharInfo::UnknownCharSet;
      static THREAD_P Int32               cachedBPC = 1;
      if (cachedCS != charSet) {
        cachedCS = charSet;
	cachedBPC = CharInfo::maxBytesPerChar(charSet);
      }
      Int32 num_of_chars = (Int32)strval.length() / cachedBPC;
      if (CharInfo::isVariableWidthMultiByteCharSet(charSet))
      {
        Int32 actualCharsCount = ComputeStrLenInUCS4chars
          ( strval.data()             // const char * pStr
          , (Int32) strval.length()   // const Int32  strLenInBytes
          , charSet                   // const CharInfo::CharSet cs
          );
        CMPASSERT(actualCharsCount >= 0); // no errors
        type_ = new (outHeap) SQLChar (outHeap,  CharLenInfo ( actualCharsCount
                                                    , strval.length() // str len in bytes
                                                    )
                                      , FALSE           // allowSQLnull
                                      , FALSE           // isUpShifted
                                      , FALSE           // isCaseInsensitive
                                      , FALSE           // varLenFlag
                                      , charSet
                                      , collation
                                      , coercibility
                                      , /*encoding*/charSet
                                      );
      }
      else
      type_ = new (outHeap)
		SQLChar(outHeap, num_of_chars, FALSE, FALSE, FALSE, FALSE,
			charSet, collation, coercibility);


      storageSize_ = strval.length();
      value_ = (void *)( new (outHeap)
			 char[storageSize_] );
      memcpy(value_, (void *)(strval.data()), (Int32)storageSize_);
    }

  ((CharType*)type_)->setCaseinsensitive(isCaseInSensitive);

  text_ = new (outHeap)
    NAString(strval,
	     outHeap);
  textIsValidatedSQLLiteralInUTF8_ = FALSE;
}

ConstValue::ConstValue(const NAWString& wstrval,
             enum CharInfo::CharSet charSet,
             enum CharInfo::Collation collation,
             enum CharInfo::Coercibility coercibility,
             NAMemory * outHeap,
             enum CharInfo::CharSet strLitPrefixCharSet
)
 : ItemExpr(ITM_CONSTANT), isNull_(IS_NOT_NULL),
   isSystemSupplied_(FALSE),
   value_(0),
   text_(0),
   locale_strval(0),
   locale_wstrval(0),
   isStrLitWithCharSetPrefix_(FALSE),
   rebindNeeded_(FALSE)
{
   initCharConstValue(wstrval, charSet, collation, coercibility, FALSE, outHeap,
                      strLitPrefixCharSet);

   locale_wstrval = new (CmpCommon::statementHeap()) NAWString
      (wstrval.data(), wstrval.length(), CmpCommon::statementHeap());
}

void ConstValue::initCharConstValue(const NAWString& strval,
             enum CharInfo::CharSet charSet,
             enum CharInfo::Collation collation,
             enum CharInfo::Coercibility coercibility,
             NABoolean isCaseInSensitive,
             NAMemory * outHeap,
             enum CharInfo::CharSet strLitPrefixCharSet)
{
  if (strval.length() == 0)
    {
      // create a varchar constant of length 0, in this case.
      type_ = new (outHeap)
		SQLVarChar(outHeap, 0, FALSE, FALSE, FALSE,
			   charSet, collation, coercibility);
      storageSize_ = type_->getVarLenHdrSize();
      value_ = (void *)( new (outHeap) 
			 NAWchar[storageSize_] );
      wc_str_pad((NAWchar *)value_, (Int32)storageSize_, '\0');
    }
  else
    {
      // A "mini-cache" to avoid proc call, for performance,
      // local to the DOUBLE-byte-charset NAString ctor
      // (distinct from the single-byte-charset ctor to prevent cache churn).
      static CharInfo::CharSet cachedCS  = CharInfo::UNICODE;
      static Int32               cachedBPC = sizeof(NAWchar);

      if (cachedCS != charSet) {
        cachedCS = charSet;

        if (cachedCS == CharInfo::UnknownCharSet) {
          cachedCS = CharInfo::UNICODE;
          cachedBPC = sizeof(NAWchar);
        } else {
          cachedBPC = CharInfo::maxBytesPerChar(cachedCS);

          // make sure the incoming charset is double-byte
          CMPASSERT(cachedBPC == (Int32)sizeof(NAWchar));
        }
      }


      Int32 num_of_chars = (Int32)strval.length();

      type_ = new (outHeap)
		SQLChar(outHeap, num_of_chars, FALSE, FALSE, FALSE, FALSE,
			charSet, collation, coercibility);

      storageSize_ = cachedBPC * strval.length();
      value_ = (void *)( new (outHeap) 
			 NAWchar[storageSize_] );
      memcpy(value_, (void *)(strval.data()), (Int32)storageSize_);
    }

  ((CharType*)type_)->setCaseinsensitive(isCaseInSensitive);

  text_ = new (outHeap)
	    NAString((char*)strval.data(), storageSize_,
	     outHeap);
  textIsValidatedSQLLiteralInUTF8_ = FALSE;
}


ConstValue::ConstValue(NAString strval, NAWString wstrval,
             enum CharInfo::Collation collation,
             enum CharInfo::Coercibility coercibility,
             NAMemory * outHeap)
 : ItemExpr(ITM_CONSTANT), isNull_(IS_NOT_NULL),
   value_(0),
   text_(0),
   textIsValidatedSQLLiteralInUTF8_(FALSE),
   isSystemSupplied_(FALSE),
   isStrLitWithCharSetPrefix_(FALSE),
   rebindNeeded_(FALSE)
{
   initCharConstValue(strval, CharInfo::UnknownCharSet,
          collation, coercibility, FALSE, outHeap);

/*
   type_ =  new (CmpCommon::statementHeap())
       SQLVarChar(0, FALSE, FALSE,
                  CharInfo::UnknownCharSet, collation, coercibility);

   storageSize_ = type_->getVarLenHdrSize();
*/

   locale_strval = new (CmpCommon::statementHeap()) NAString
    ((char*)strval.data(), strval.length(), CmpCommon::statementHeap());

   locale_wstrval = new (CmpCommon::statementHeap()) NAWString
    (wstrval.data(), wstrval.length(), CmpCommon::statementHeap());
}


const NAType* ConstValue::pushDownType(NAType& newType,
				       enum NABuiltInTypeEnum defaultQualifier)
{
   if ( newType.getTypeQualifier() == NA_CHARACTER_TYPE &&
        type_ -> getTypeQualifier() == NA_CHARACTER_TYPE
      )
   {
     CharType &newCT = (CharType&)newType;
     enum CharInfo::CharSet newCS = ((const CharType&)newType).getCharSet();
     CharType* ct = (CharType*)type_;

     if ( ct ->getCharSet() != newCS ) {

       if ( newCS == CharInfo::UNICODE ) {
	 assert(locale_wstrval);
         // fix 10-070329-5979 by passing in the case-sensitivity flag.
         // Should re-implement this with collation some day.
	 initCharConstValue(*locale_wstrval, newCS,
			    ct->getCollation(),
			    ct->getCoercibility(),
                            ct->isCaseinsensitive());
       } else {

	 if ( locale_strval == NULL ) {

	   assert(locale_wstrval);

	   // init locale_strval from locale_wstrval
	   Lng32 wlen = (Lng32)(locale_wstrval->length());
	   Lng32 bufLen = wlen * CharInfo::maxBytesPerChar(newCS) + 1; // add the NULL
	   char* buf = new (CmpCommon::statementHeap()) char[bufLen];

	   Lng32 cLen = UnicodeStringToLocale(newCS, locale_wstrval->data(), wlen,
					     buf, bufLen, TRUE, FALSE);

	   if ( cLen == 0 ) {  // If conversion fails, do not change the type.
	     NADELETEBASIC(buf,CmpCommon::statementHeap());
	     return type_;
	   }

	   locale_strval = new (CmpCommon::statementHeap()) NAString
	     (buf, cLen, CmpCommon::statementHeap());

	   NADELETEBASIC(buf,CmpCommon::statementHeap());
	 }


	 // fix 10-040527-6468 (CQD infer_charset doesn't work with
	 // kanji character set correctly). We do not change this ConstValue
	 // object's attributes if the lendth of the literal is odd. The
	 // compatibility check code will catch the incompatible error (e.g.,
	 // T.KANJI_C1 = _unknown'abc').
	 if ( CharInfo::is_NCHAR_MP(newCS) == FALSE ||
	      locale_strval -> length() % SQL_DBCHAR_SIZE == 0
	      )
	   {
             // fix 10-070329-5979 by passing in the case-sensitivity flag.
             // Should re-implement this with collation some day.
	     initCharConstValue(*locale_strval, newCS,
				ct->getCollation(),
				ct->getCoercibility(),
                                ct->isCaseinsensitive());
	   }
       }
     }
     return synthesizeType();
   }

   return &newType;
}

// this constructor creates a constant of the given type and initializes
// it with the value.
ConstValue::ConstValue(const NAType * type, void * value, Lng32 value_len,
		       NAString * literal, NAMemory * outHeap)
  : ItemExpr(ITM_CONSTANT)
  , isNull_(IS_NOT_NULL)
  , type_(type)
  , isSystemSupplied_(FALSE)
  , locale_strval(0)
  , locale_wstrval(0)
  , isStrLitWithCharSetPrefix_(FALSE)
  , rebindNeeded_(FALSE)
{
  CMPASSERT(value_len > 0);
  CMPASSERT(type_);
  storageSize_ = value_len;
  value_ = (void *)( new (outHeap) char[storageSize_] );
  memcpy(value_,(void *)value,(Int32)storageSize_);

  if(type)
    type_ = type->newCopy(outHeap);

  NABoolean isNull = FALSE;

  // If a literal was not supplied, call a method to convert
  // the value from its binary form to UTF-8 and add any necessary
  // syntax modifiers like the charset and date and time qualifiers
  if (literal == NULL)
    {
      if (type_)
        textIsValidatedSQLLiteralInUTF8_ =
          type_->createSQLLiteral((const char *)value,
                                  text_,
                                  isNull,
                                  outHeap);
      DCMPASSERT(textIsValidatedSQLLiteralInUTF8_); // for now
      if (!textIsValidatedSQLLiteralInUTF8_)
        text_ = new (outHeap) NAString("<unknown value>", outHeap);
    }
  else
    {
      text_ = new (outHeap) NAString(*literal, outHeap);
      textIsValidatedSQLLiteralInUTF8_ = FALSE;
      if (type->supportsSQLnull())
        {
          // call the NAType base class method
          // just to check for a NULL value (sets isNull)
          NAString *dummyPtr;

          type->NAType::createSQLLiteral((const char *) value,
                                         dummyPtr,
                                         isNull,
                                         outHeap);
        }
    }

  if (isNull)
    isNull_ = IS_NULL;
}

/*soln:10-050710-9594 begin */

ConstValue::ConstValue(const NAType * type, void * value, Lng32 value_len,
		       NAString *lstrval, NAWString *wstrval, 
                     NAString * literal, NAMemory * outHeap, IsNullEnum isNull)
  : ItemExpr(ITM_CONSTANT)
  , isNull_(isNull)
  , type_(type)
  , isSystemSupplied_(FALSE)
  , locale_strval(0)
  , locale_wstrval(0)
  , isStrLitWithCharSetPrefix_(FALSE)
  , rebindNeeded_(FALSE)
{
  CMPASSERT(value_len > 0);
  CMPASSERT(type_);
  storageSize_ = value_len;
  value_ = (void *)( new (outHeap) char[storageSize_] );
  memcpy(value_,(void *)value,(Int32)storageSize_);

  if(type)
    type_ = type->newCopy(outHeap);

  // If a literal was not supplied, the text for this constant
  // is the bit pattern for the given value. Note that embedded
  // ascii nulls in the bit pattern are copied as is.
  if (literal == NULL)
    text_ = new (outHeap)
      NAString((char *)value,(UInt32)value_len, CmpCommon::statementHeap());
  else
    text_ = new (outHeap) NAString
      (*literal, outHeap);
  textIsValidatedSQLLiteralInUTF8_ = FALSE;

  if(lstrval)
     locale_strval = new (outHeap) NAString
      ((char*)lstrval->data(), lstrval->length(), outHeap);

  if(wstrval)
     locale_wstrval = new (outHeap) NAWString
      ((NAWchar *)wstrval->data(), wstrval->length(), outHeap);
}

/*soln:10-050710-9594 end */

// constructor for an extremal (min or max) value of a given type
// The allowNull parameter specifies whether NULL should be considered
// when generating the value; if it is TRUE and we want the max value,
// and the type is nullable, then NULL will be returned instead of the
// max non-null value.
ConstValue::ConstValue(const NAType * type,
		       const NABoolean wantMinValue,
		       const NABoolean includeNull,
                       NAMemory * outHeap)
: ItemExpr(ITM_CONSTANT)
, isNull_(IsNullEnum(type->supportsSQLnull() && includeNull && !wantMinValue))
, type_(type)
, isSystemSupplied_(FALSE)
, locale_strval(0)
, locale_wstrval(0)
, isStrLitWithCharSetPrefix_(FALSE)
, rebindNeeded_(FALSE)
{
  assert(type_);

  storageSize_ = type->getTotalSize();

  assert(storageSize_ > 0);

  char *storage = new (outHeap) char[storageSize_];
  value_ = (void *)storage;

  // if nullable, make the null indicator bytes 0 or NULL
  // depending on whether min or max value is needed.
  if (type->supportsSQLnull())
    {
      short indicatorVal;

      // the min value is non-NULL, the max value is the NULL
      // value unless we want the max non-NULL value
      if (wantMinValue || !includeNull)
	indicatorVal = 0;
      else
	indicatorVal = -1;

      // move the NULL indicator into the first few bytes of the value
      switch (type->getSQLnullHdrSize())
	{
	case 2:
	  *(short *)value_ = indicatorVal;
          break;
	case 4:
	  *(Lng32 *)value_ = (Lng32) indicatorVal;
          break;
	default:
	  CMPASSERT(0); // unsupported type of NULL indicator
	}
    }

  Lng32 startOfData = type->getSQLnullHdrSize();
  Lng32 templen = storageSize_ - startOfData;

  if (wantMinValue) // min value
  {
    type->minRepresentableValue(&storage[startOfData],
                                &templen,
                                NULL,
                                outHeap);
    text_ = new (outHeap) NAString("<min>", outHeap);
  }
  else
  {
    type->maxRepresentableValue(&storage[startOfData],
                                &templen,
                                NULL,
                                outHeap);
   text_ = new (outHeap) NAString("<max>", outHeap);
  }
  textIsValidatedSQLLiteralInUTF8_ = FALSE;
}

// A copy constructor used by the SampleSize derived class
//
ConstValue::ConstValue(OperatorTypeEnum otype,
                       ConstValue *other,
                       NAMemory * outHeap)
  : ItemExpr(otype)
//  , isNull_(other.isNull())
  , type_(other->getType())
  , storageSize_(other->getStorageSize())
  , textIsValidatedSQLLiteralInUTF8_(other->textIsValidatedSQLLiteralInUTF8_)
  , isSystemSupplied_(other->isSystemSupplied_)
  , locale_strval(other->locale_strval)
  , locale_wstrval(other->locale_wstrval)
  , isStrLitWithCharSetPrefix_(other->isStrLitWithCharSetPrefix_)
  , rebindNeeded_(other->rebindNeeded_)
{
  value_ = (void *)( new (outHeap) char[storageSize_] );
  memcpy(value_,(void *)other->getConstValue(),(Int32)storageSize_);
  text_ = new (outHeap)
               NAString(other->getText(), outHeap);
}

ConstValue::ConstValue(const ConstValue& s, NAHeap *h)
  : ItemExpr(ITM_CONSTANT), isNull_(s.isNull_), type_(s.type_)
  , storageSize_(s.storageSize_)
  , textIsValidatedSQLLiteralInUTF8_(s.textIsValidatedSQLLiteralInUTF8_)
  , isSystemSupplied_(s.isSystemSupplied_)
  , isStrLitWithCharSetPrefix_(s.isStrLitWithCharSetPrefix_)
  , rebindNeeded_(s.rebindNeeded_)
{
  if (s.value_) {
    value_ = (void *)( new (h) char[storageSize_] );
    memcpy(value_,(void *)s.value_,(Int32)storageSize_);
  }
  if (s.text_) {
    text_ = new (h) NAString(*s.text_, h);
  }
}

ConstValue::ConstValue(const ConstValue& s)
  : ItemExpr(ITM_CONSTANT), isNull_(s.isNull_), type_(s.type_)
  , storageSize_(s.storageSize_), value_(s.value_)
  , textIsValidatedSQLLiteralInUTF8_(s.textIsValidatedSQLLiteralInUTF8_)
  , text_(s.text_), isSystemSupplied_(s.isSystemSupplied_)
  , isStrLitWithCharSetPrefix_(s.isStrLitWithCharSetPrefix_)
  , rebindNeeded_(s.rebindNeeded_)
{
}

ConstValue::~ConstValue()
{
  // type_ can be shared by multiple consts --
  // see ConstValue::copyTopNode for a good example --
  // so we must not delete it!
     // delete type_;
  NADELETEBASIC((char*)value_,CmpCommon::statementHeap());   // value_ is a void*

  if (text_)
    NADELETEBASIC((NAString*)text_,CmpCommon::statementHeap());
}

NABoolean ConstValue::isAUserSuppliedInput() const    { return TRUE; }

void ConstValue::changeStringConstant(const NAString* strval)
{
   NADELETEBASIC((char*)value_,CmpCommon::statementHeap());   // value_ is a void*

   if (strval -> length() == 0)
   {
     // create a varchar constant of length 0, in this case.
     storageSize_ = type_->getVarLenHdrSize();
     value_ = (void *)( new (CmpCommon::statementHeap()) char[storageSize_] );
     str_pad((char *)value_, (Int32)storageSize_, '\0');
   } else {
     storageSize_ = strval -> length();
     value_ = (void *)( new (CmpCommon::statementHeap()) char[storageSize_] );
     memcpy(value_,(void *)(strval -> data()),(Int32)storageSize_);
   }

   *text_ = *strval;
}

NABoolean ConstValue::isAFalseConstant() const
{
  NABoolean result = FALSE;

  if (type_->getTypeQualifier() == NA_BOOLEAN_TYPE && !isNull())
    {
      CMPASSERT(storageSize_ == sizeof(Int32));
      if (*(reinterpret_cast<Int32 *>(value_)) == 0)
        result = TRUE; // that means the constant is FALSE!!
    }

  return result;          
}

NABoolean ConstValue::isExactNumeric() const
{
  return (type_->getTypeQualifier() == NA_NUMERIC_TYPE AND
	  ((NumericType *)type_)->isExact());
}

// exact numeric value can only be returned for certain types
// and if the value is within max largeint range.
NABoolean ConstValue::canGetExactNumericValue() const
{
  if (isExactNumeric())
    {
      NumericType &t = (NumericType &) *type_;

      // if unsigned largeint and value greater than largeint max,
      // cannot return exact numeric value.
      if ((t.getFSDatatype() == REC_BIN64_UNSIGNED) &&
          ((*(UInt64*)value_) > LLONG_MAX))
        return FALSE;

      // for now we can't do it for arbitrary exact numeric types, sorry
      if (NOT t.isDecimal() AND
	  NOT t.isComplexType() AND
	  NOT t.supportsSQLnull() AND
	  NOT t.getPrefixSize())
        return TRUE;
    }
  return FALSE;
}

Int64 ConstValue::getExactNumericValue(Lng32 &scale) const
{
  CMPASSERT(canGetExactNumericValue());

  Int64 result = 0;
  NumericType &t = (NumericType &) *type_;

  // for now we are looking at a binary representation of a number
  // that is either 2, 4, or 8 bytes.
  scale = t.getScale();
  CMPASSERT(t.getNominalSize() == storageSize_);
  switch (storageSize_)
    {
    case 1:
      if (t.isUnsigned())
	result = *((UInt8 *) value_);
      else
	result = *((Int8 *) value_);
      break;

    case 2:
      if (t.isUnsigned())
	result = *((unsigned short *) value_);
      else
	result = *((short *) value_);
      break;

    case 4:
      if (t.isUnsigned())
	result = uint32ToInt64(*((ULng32 *) value_));
      else
	result = *((Lng32 *) value_);
      break;

    case 8:
      if (t.isUnsigned())
        {
          if ((*(UInt64*)value_) > LLONG_MAX)
            {
              CMPASSERT(0);
            }
          else
            result = *(UInt64*)value_;
        }
      else
        result = *((Int64 *) value_);
      break;

    default:
      CMPASSERT(0);
      break;
    }

  return result;
}

NABoolean ConstValue::canGetApproximateNumericValue() const
{
  // return TRUE if this is an approximate numeric type or if we
  // can return an exact numeric value
  return (type_->getTypeQualifier() == NA_NUMERIC_TYPE &&
          ((!((NumericType *) type_)->isExact() ||
            canGetExactNumericValue())));
}

double ConstValue::getApproximateNumericValue() const
{
  CMPASSERT(canGetApproximateNumericValue());

  switch (type_->getFSDatatype())
    {
    case REC_IEEE_FLOAT32:
      return *((float *) value_);

    case REC_IEEE_FLOAT64:
      return *((double *) value_);

    default:
      {
        Int32 scale;
        double tempResult = (double) getExactNumericValue(scale);
        return tempResult * pow(10,-scale);
      }
    }
}

void ConstValue::getOffsetsInBuffer(int &nullIndOffset,
                                    int &vcLenOffset,
                                    int &dataOffset)
{
  int nextOffset = 0;

  // This uses the alignment method of the ConstVal, which is slightly
  // different from other formats, no alignment is used.
  // See also method ExpGenerator::placeConstants()
  if (type_->supportsSQLnull())
    {
      nullIndOffset = nextOffset;
      nextOffset += type_->getSQLnullHdrSize();
    }
  else
    nullIndOffset = -1;

  if (type_->isVaryingLen())
    {
      vcLenOffset = nextOffset;
      nextOffset += type_->getVarLenHdrSize();
    }
  else
    vcLenOffset = -1;

  dataOffset = nextOffset;
}

// The implementation checks for identity rather than equality,
// that is, the following method returns TRUE when the two
// ConstValues are identical in all respects except that they
// are implemented in two different storage locations.
NABoolean ConstValue::operator== (const ItemExpr& other) const	// virtual meth
{
  if (ItemExpr::operator==(other)) return TRUE;

  if (getOperatorType() != other.getOperatorType()) return FALSE;

  const ConstValue &otherConst = (const ConstValue &)other;

  // There is room for more creativity here, but it requires
  // the use of type conversion functions.

  if (type_ != otherConst.type_) return FALSE;

  if (storageSize_ != otherConst.storageSize_) return FALSE;

  // Perform a byte-by-byte comparison of the bit pattern for the value.
  if (memcmp(value_, otherConst.value_, (size_t)storageSize_)) return FALSE;

  return TRUE;
}

ConstValue * ConstValue::castToConstValue(NABoolean & negate_it)
{
  negate_it = FALSE;
  return this;
}

Int32 ConstValue::getArity() const { return 0; }

NAString ConstValue::getConstStr(NABoolean transformNeeded) const
{
  if ((*text_ == "<min>") || (*text_ == "<max>"))
    return *text_ ;

  if (getType()->getTypeQualifier() == NA_DATETIME_TYPE &&
      getType()->getPrecision() != SQLDTCODE_MPDATETIME)
  {
    return getType()->getSimpleTypeName() + " '" + *text_ + "'";
  }
  else if(getType()->getTypeQualifier() == NA_CHARACTER_TYPE)
  {
    CharType* chType = (CharType*)getType();
    NAString txt;

    if ( transformNeeded )
      txt = getText();
    else
      txt = getTextForQuery(QUERY_FORMAT);

    // if result doesn't have a charset specifier already, add one
    if (txt.index(SQLCHARSET_INTRODUCER_IN_LITERAL) == 0)
      return txt;
    else
      return chType->getCharSetAsPrefix() + txt;
  }
  else
  {
    return *text_;
  }
}

// Genesis 10-980402-1556 (see Binder)
ConstValue * ConstValue::toUpper(CollHeap *h)
{
  ConstValue *cv;

  if (isNull()) return this;                  // nothing to be done

  const CharType *typ = (const CharType *)getType();

  if (getType()->getTypeQualifier() != NA_CHARACTER_TYPE)
    return this;

  switch(typ->getCharSet())
    {
      case CharInfo::KSC5601_MP:
      case CharInfo::KANJI_MP:
        {
          // MP does not allow SQL upper/lower functions
          // to be applicable to KANJI/KSC5601 charsets.
          return this;
        }

      case CharInfo::UNICODE:
        {
          // upshift the text and put it into wcUpshift
          NAWString wcUpshift(h);
          unicode_char_set::to_upper((NAWchar *)value_,
                                     typ->getStrCharLimit(),
                                     wcUpshift);

          // create new ConstValue with the upshifted text
          cv = new (h) ConstValue(wcUpshift,
                                  typ->getCharSet(),
                                  typ->getCollation(),
                                  typ->getCoercibility());
	  cv->changeType(typ);
          break;
        }

      default:
        {
          const unsigned char *c = (const unsigned char*)(text_->data());

          // check if it's already upshifted
          for (; *c; c++)
            if (islower(*c)) break;
          if (!*c) return this;

          // upshift the text and return a new constant
          NAString upshift(*text_);
          upshift.toUpper();
          cv = new (h) ConstValue(upshift,
                                  typ->getCharSet(),
                                  typ->getCollation(),
                                  typ->getCoercibility());
          cv->changeType(typ);
          break;
        }
    }

  CMPASSERT(*typ == *cv->getType());
  return cv;
}

const NAString ConstValue::getText4CacheKey() const
{
  if(getType()->getTypeQualifier() != NA_CHARACTER_TYPE) {
    return getText();
  }
  else {
    NAString result = getText();

    // we want to return _charset'strfoo' instead of 'strfoo'.
    // This is to fix genesis case 10-040616-0347 "NF: query cache does not
    // work properly on || for certain character set". The root cause here
    // was ItemExpr::generateCacheKey() incorrectly returning the same string
    // keys for both
    //   select ?p1 || _ksc5601'arg' from ...
    //   select ?p1 || _kanji'arg from ...
    // The solution is to make them different via charset prefixes.
    if (result.index(SQLCHARSET_INTRODUCER_IN_LITERAL) != 0)
      result.prepend(((CharType*)getType())->getCharSetAsPrefix());

    return result;
  }
}

const NAString ConstValue::getTextForQuery() const
{
  if(getType()->getTypeQualifier() == NA_CHARACTER_TYPE)
    {
      NAString result("\'", CmpCommon::statementHeap());
      if (text_) result += *text_;
      RemoveTrailingZeros(result);

      result += "\'";
      return result;
    }
  else
    return *text_;
}

const NAString ConstValue::getTextForQuery(UnparseFormatEnum form) const
{
  if(getType()->getTypeQualifier() != NA_CHARACTER_TYPE ||
     textIsValidatedSQLLiteralInUTF8_)
    return *text_;

  //
  // getType()->getTypeQualifier() == NA_CHARACTER_TYPE)
  //

  NABoolean charSetConvFailed = FALSE;
  switch (form)
  {
  case QUERY_FORMAT:
  case MV_SHOWDDL_FORMAT:
  case USER_FORMAT_DELUXE:
    {
      NAString result((NAMemory *)CmpCommon::statementHeap());
      if (text_)
      {
        switch (((CharType*)getType())->getCharSet())
        {
        case CharInfo::UCS2:
          {
            // Assume that *text_ contains Unicode UCS-2/UTF-16 encoding values.
            // For SeaQuest, query text should be in Unicode UTF-8 encoding format.
            NAString *utf8Str = unicodeToChar ( (const NAWchar *)text_->data() // source
                                              , text_->length/*in_bytes*/() / BYTES_PER_NAWCHAR
                                              , CharInfo::UTF8                 // target CS
                                              , CmpCommon::statementHeap()     // heap for target
                                              );
            if (utf8Str) // Translation was successful
            {
              result += *utf8Str;
              delete utf8Str;
              utf8Str = NULL;
            }
            else // Translation failed - Assume *text_ already in UTF-8 encoding
            {
              result += *text_;
              charSetConvFailed = TRUE;
            }
          }
          break;
        case CharInfo::ISO88591:
          {
            NAString utf8String = Latin1StrToUTF8 ( *text_, CmpCommon::statementHeap() );
            if (utf8String.isNull()) // Translation failed -  Assume *text_ already in UTF-8 encoding
            {
              result += *text_;
              charSetConvFailed = TRUE;
            }
            else // Translation was successful
              result += utf8String;
          }
          break;
          // case CharInfo::SJIS:
          //   {
          //     NAString utf8Str2 = SjisStrToUTF8 ( *text_, CmpCommon::statementHeap() );
          //     if (utf8Str2.isNull()) // Translation failed -  Assume *text_ already in UTF-8 encoding
          //     {
          //       result += *text_;
          //       charSetConvFailed = TRUE;
          //     }
          //     else // Translation was successful
          //       result += utf8Str2;
          //   }
          //   break;
        default: // Assume *text_ already in UTF-8 encoding
          result += *text_;
          break;
        } // switch (((CharType*)getType())->getCharSet())

      } // if (text_)

      RemoveTrailingZeros(result);

      NAString extStrLit;
      if (result.isNull())
        extStrLit = "''";
      else if (charSetConvFailed)
      {
        extStrLit  = "'";
        extStrLit += result;
        extStrLit += "'";
      }
      else
        ToQuotedString(extStrLit/*out*/, result/*in - internalString*/, TRUE/*in - encloseInQuotes*/);

      return extStrLit;
    }
    break;

  default:
    return getTextForQuery();
    break;
  } // switch (((CharType*)getType())->getCharSet())

  return getTextForQuery(); // to keep the C++ compiler happy
}

const NAString ConstValue::getText() const
{
  if(getType()->getTypeQualifier() == NA_CHARACTER_TYPE)
    {
      NAString result(CmpCommon::statementHeap());
      if (!textIsValidatedSQLLiteralInUTF8_)
        result += "\'";
      if (text_) result += *text_;
      if (!textIsValidatedSQLLiteralInUTF8_)
        result += "\'";

      // Change imbedded NULL and \377 chars to \0 and \377
      // This comes up in key values quite often.
      size_t index;
      while((index = result.first('\0')) != NA_NPOS
	    && index != result.length())
	result(index,1) = "\\0";
      while((index = result.first('\377')) != NA_NPOS
	    && index != result.length())
	result(index,1) = "\\377";

      return result;
    }
  else
    return *text_;
}

NABoolean ConstValue::isEmptyString() const
{
  if (getType()->getTypeQualifier() == NA_CHARACTER_TYPE) {
    if (text_ && text_->length() == 0) { return TRUE; }
  }
  return FALSE;
}

void ConstValue::unparse(NAString &result,
			 PhaseEnum /*phase*/,
			 UnparseFormatEnum form,
			 TableDesc * tabId) const
{
  if (form == EXPLAIN_FORMAT)
    {
      // for EXPLAIN, abbreviate very long text values:
      // drop any repeated text from the end, and drop any text that
      // is more than 30 characters

      NAString fullText(getText(), CmpCommon::statementHeap());
      const Int32 tooLong = 30;     // keep strings shorter than this
      const Int32 shortEnough = 10; // leave strings of this length alone

      // get the full text in query text format first
      fullText = getTextForQuery(QUERY_FORMAT);

      // then truncate it if too long
      if (fullText.length() > shortEnough)
	{
	  NABoolean truncated = FALSE;
	  // the last character often is a quote and should be preserved
	  char lastchar = fullText[fullText.length()-1];

	  // more than <tooLong> characters are unlikely to convey
	  // a lot of extra info
	  if (fullText.length() > tooLong)
	    {
	      fullText.remove(tooLong);
              // if there are unprintable characters in the string,
              // remove entire escape sequences
              if (fullText.last('\\') != NA_NPOS)
                fullText.remove(fullText.last('\\'));
              truncated = TRUE;
	    }

	  // try to reduce the text even further if the information is
	  // repetitive at the end of the string
	  CollIndex len = fullText.length();

	  // skip the last character unless we have already removed it
	  if (NOT truncated)
	    len--;

          // remove repeating patterns of length 1, 2, or 4 from the end
          // of the string (patterns could be ' ', '\0', '377', etc.)
	  while (len >= 8 AND fullText(len-4,4) == fullText(len-8,4))
	    len -= 4;
	  while (len >= 4 AND fullText(len-2,2) == fullText(len-4,2))
	    len -= 2;
	  while (len >= 2 AND fullText(len-1,1) == fullText(len-2,1))
	    len -= 1;

	  // remove all the repetitive information except 3 characters
	  // but only if it's worth it (we have to add 4 extra characters
	  // to indicate the omission and want to leave 3 repeating chars...)
	  if (len+7 < fullText.length())
	    {
	      fullText.remove(len+3);
	      truncated = TRUE;
	    }

	  if (truncated)
	    {
	      fullText += " ...";
	      fullText += lastchar;
	    }
	}
      result += fullText;
    }
  else if ((form == MVINFO_FORMAT) || (form == QUERY_FORMAT) ||
           (form == MV_SHOWDDL_FORMAT) || (form == COMPUTED_COLUMN_FORMAT))
    {
    if (getType()->getTypeQualifier() == NA_CHARACTER_TYPE)
      {
        CharType* chType = (CharType*)getType();

        if (form == MVINFO_FORMAT)
          result += getText();
        else
          {
            if (!textIsValidatedSQLLiteralInUTF8_)
              result += chType->getCharSetAsPrefix();

            if ((form == MV_SHOWDDL_FORMAT) || (form == QUERY_FORMAT))
              result += getTextForQuery(form);
            else
              result += getTextForQuery();
          }
      }
    else
      {
        if (getType()->getTypeQualifier() == NA_DATETIME_TYPE &&
            !textIsValidatedSQLLiteralInUTF8_)
        {
          if (getType()->getTypeName() == "DATE")
              result += " DATE '";
          else if (getType()->getTypeName() == "TIME")
              result += " TIME '";
          else if (getType()->getTypeName() == "TIMESTAMP")
              result += " TIMESTAMP '";
        }
        result += getText();
        if (getType()->getTypeQualifier() == NA_DATETIME_TYPE &&
            !textIsValidatedSQLLiteralInUTF8_)
          result += "'";
      }
    } // MVINFO_FORMAT || QUERY_FORMAT || MV_SHOWDDL_FORMAT || COMPUTED_COLUMN_FORMAT
  else if ((form == USER_FORMAT_DELUXE) ||
	   (form == HIVE_MD_FORMAT))
    {
      if (getType()->getTypeQualifier() == NA_CHARACTER_TYPE)
        {
          // Intentionally not adding the string literal character set prefix
          // to avoid updating the regression test expected results.
          result += getTextForQuery(form);
        }
      else
        result += getText();
    }
  else
    {
      // in all other cases use the getText() method
      result += getText();
    }
}

const NAString * ConstValue::getRawText() const
{
  return text_;
}

HashValue ConstValue::topHash()
{
  HashValue result = ItemExpr::topHash();

  // hash any local data members of the derived class
  result ^= isNull();

  if (NOT isNull())
    {
      // hash binary representation of value, but no more than 10
      // bytes (diminishing return for hashing very long strings)
      Int32 maxc = MINOF(storageSize_, 10);
      for (Int32 i=0; i < maxc; i++)
	result ^= ((char *)value_)[i];
    }

  return result;
}

NABoolean ConstValue::duplicateMatch(const ItemExpr & other) const
{
  if (NOT genericDuplicateMatch(other))
    return FALSE;

  ConstValue &o = (ConstValue &) other;

  // compare any local data members of the derived class
  // and return FALSE if they don't match
  if (NOT (*type_ == *(o.type_)))
    return FALSE;

  if (isNull() != o.isNull())
    return FALSE;

  if (isNull())
    return TRUE;

  if (storageSize_ != o.storageSize_)
    return FALSE;

  if (str_cmp((char *) value_, (char *)o.value_, storageSize_) != 0 OR
      isSystemSupplied_ != o.isSystemSupplied_)
    return FALSE;

  return TRUE;
}

ItemExpr * ConstValue::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ConstValue *result;

  if (derivedNode == NULL)
    {
      // According to the constructor that initiates isNull_ to NULL the value_
      // void pointer is set to NULL, however there are places in the code
      // like SearchKeyBounds::::computeMissingKeyValue() that creates a 
      // ConstValue with isNull set to IS_NULL and Value set to NULL
      // indicator.  So it is not right to assume that when isNULL is set
      // value will be empty.  So creating an empty ConstValue only when
      // isNULL() is true and value_ not set, otherwise we go to else
      // and call a constructor that copies isNULL_ flag along with value_
      if (isNull() && !value_)
        {
          //CMPASSERT(!value_);
          result = new (outHeap) ConstValue; // a NULL
        }
      else
        {
          /* soln:10-050710-9594 begin */
          /* Changed the constructor that is being called so that value
           * of locale_strval and locale_wstrval are not lost
           */
          result = new (outHeap) ConstValue(type_,value_,storageSize_,
                                            locale_strval, locale_wstrval,
                                            text_,outHeap, isNull_);
          
          /* soln:10-050710-9594 end */

          result->textIsValidatedSQLLiteralInUTF8_ =
            textIsValidatedSQLLiteralInUTF8_;
          result->setRebindNeeded(isRebindNeeded());
        }
    }
  else
    result = (ConstValue *) derivedNode;

  return ItemExpr::copyTopNode(result, outHeap);
}

NABoolean ConstValue::isCovered(const ValueIdSet& /* newExternalInputs */,
				const GroupAttributes& /* coveringGA */,
				ValueIdSet& /* referencedInputs */,
				ValueIdSet& /* coveredSubExpr */,
				ValueIdSet& /*unCoveredExpr*/) const
{
  // ---------------------------------------------------------------------
  // Constants are always covered
  // ---------------------------------------------------------------------
  return TRUE;
} // ConstValue::isCovered()

// ------------------------------------------------------------------------
// computeHashValues creates a hash value for a constant.
// Hash value is created only for character and numeric column types
// ------------------------------------------------------------------------
UInt32 ConstValue::computeHashValue(const NAType& columnType) 
{
  UInt32 hashValue = 0;
  switch ( getType()->getTypeQualifier() )
   {
     case NA_CHARACTER_TYPE:
       {
         UInt32 flags = ExHDPHash::NO_FLAGS;
         const CharType *cType = (CharType *)(&columnType);

         if(cType->getCharSet() == CharInfo::UNICODE) {
           flags = ExHDPHash::SWAP_TWO;
         }
     // For a case-insensitive char type, it is necessary to upper-case the 
     // boundary value first before compute the hash. This is to mimic the
     // run-time behavior where values of such char type are always 
     // upper shifted before case-insensitive comparison, being hashed or
     // encoded. Upshifting has already been done during encoding step.
         hashValue = ExHDPHash::hash((char*)(getConstValue()), flags, getStorageSize());
       }
       break;

     case NA_NUMERIC_TYPE :

       // only handle non-big NUMERICs that require 8-or-less bytes to store
       // for now.
       if ( getType()->getTypeName() == LiteralNumeric AND
            columnType.getTypeName() == LiteralNumeric AND
            columnType.getNominalSize() <= 8
          ) 
       {

         // 10-080124-0055 (Skewbuster numeric uneven distribution 
         // different scales).
         // Convert the constant to the exact NUMERIC type of the column
         // before applying the hash on it. This is necessary because for
         // example 4 bytes is sufficient to represent a small scale boundary 
         // value such as 1.0, while the storage size of the column can be 
         // 8-bytes. Without converting the number of bytes of the value to 
         // that of the column, the hashing result can be different.
         // 
         // There is still a chance that the skews are not busted when the
         // fact table side has a scale smaller than that of the dimension
         // table. For example numeric(18,2) on fact side and 
         // numeric(18, 4) on dimension side. In this case, the hash values 
         // computed for the fact table side will not match the actual 
         // values used for repartition or hashing because a CAST will be 
         // used on the fact side and repartition and hashing will use the
         // output from the CAST.

         const SQLNumeric& type = (const SQLNumeric&)(columnType);

         Lng32 len = type.getNominalSize();

         char result[8];

         // Ignore errors because the boundary value pointed by cvPtr
         // is read from the histogram table and should be have been cleared
         // off any precision or scale problems by the update histogram
         // utility.
         short retCode = convDoIt((char*)(getConstValue()),
                  getStorageSize(),
                  (short)getType()->getFSDatatype(), 
                  getType()->getPrecision(),
                  getType()->getScale(), 
                  result,
                  len, 
                  (short)(type.getFSDatatype()), 
                  type.getPrecision(), 
                  type.getScale(), 
                  NULL /* null varchar ptr*/, 0 /* varchar len*/);

         DCMPASSERT(retCode == ex_expr::EXPR_OK);

         UInt32 flags = ExHDPHash::NO_FLAGS;

         switch(type.getFSDatatype()) {
         case REC_NUM_BIG_UNSIGNED:
         case REC_NUM_BIG_SIGNED:
         case REC_BIN16_SIGNED:
         case REC_BIN16_UNSIGNED:
           flags = ExHDPHash::SWAP_TWO;
           break; 
         case REC_BIN32_SIGNED:
         case REC_BIN32_UNSIGNED:
         case REC_IEEE_FLOAT32:
           flags = ExHDPHash::SWAP_FOUR;
           break;
         case REC_BIN64_SIGNED:
         case REC_BIN64_UNSIGNED:
         case REC_IEEE_FLOAT64:
           flags = ExHDPHash::SWAP_EIGHT;
           break;
         }

         hashValue = ExHDPHash::hash(result, flags, len);
       }
       break;
 
     default:
       break;
   }
  return hashValue;
}

// -----------------------------------------------------------------------
// does the value of this constant (if char) has trailing blanks
// -----------------------------------------------------------------------
NABoolean ConstValue::valueHasTrailingBlanks()
{
   NABoolean hasATrailingBlanks = FALSE;

   if (value_ && (getType()->getTypeQualifier() == NA_CHARACTER_TYPE))
   {
      const CharType *typ = (const CharType *)getType();
      if (typ->getCharSet() == CharInfo::UNICODE)
      {
          NAWchar* nawCharVal = (NAWchar *) value_;
          Int32 bytesPerChar = (CharInfo::maxBytesPerChar)(typ->getCharSet());
          Int32 lastPos = (storageSize_/bytesPerChar)-1;
          if ((lastPos >= 0) && (nawCharVal[lastPos] == L' '))
          { 
             hasATrailingBlanks = TRUE;
          }
      }
      else
      {
          char* charVal = (char *) value_;
          Int32 lastPos = storageSize_-1;
          if ((lastPos >= 0) && (charVal[lastPos] == ' '))
          {
             hasATrailingBlanks = TRUE;
          }
          
      }
   }
   return hasATrailingBlanks;
}

QR::ExprElement ConstValue::getQRExprElem() const
{
  return QR::QRScalarValueElem;
}

// -----------------------------------------------------------------------
// member functions for class RenameCol
// -----------------------------------------------------------------------
Int32 RenameCol::getArity() const { return (child(0) ? 1 : 0); }

const NAString RenameCol::getText() const
{
  return ("rename as " + newColRefName_->getColName());
}

HashValue RenameCol::topHash()
{
  HashValue result = ItemExpr::topHash();

  // hash any local data members of the derived class
  result ^= newColRefName_->getColRefAsString();

  return result;
}

NABoolean RenameCol::duplicateMatch(const ItemExpr & other) const
{
  if (NOT genericDuplicateMatch(other))
    return FALSE;

  RenameCol &o = (RenameCol &) other;

  // compare any local data members of the derived class
  // and return FALSE if they don't match
  if (NOT (*newColRefName_ == *(o.newColRefName_)))
    return FALSE;

  return TRUE;
}

ItemExpr * RenameCol::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
  {
    RenameCol *newRename = new (outHeap)
      RenameCol(NULL,
		new (outHeap)
		ColRefName(newColRefName_->getColName(),
			   newColRefName_->getCorrNameObj(),
                           outHeap));
    newRename->setTargetColumnClass(getTargetColumnClass());
    result = newRename;
  }
  else
    result = derivedNode;

  return ItemExpr::copyTopNode(result, outHeap);
}

// -----------------------------------------------------------------------
// member functions for class Convert
// -----------------------------------------------------------------------
Int32 Convert::getArity() const { return 1; }

HashValue Convert::topHash()
{
  HashValue result = ItemExpr::topHash();

  // hash any local data members of the derived class

  return result;
}

ItemExpr * Convert::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  Convert *result;

  if (derivedNode == NULL)
    result = new (outHeap) Convert(NULL);
  else
    result = (Convert *) derivedNode;

  return ItemExpr::copyTopNode(result, outHeap);
}

// -----------------------------------------------------------------------
// member functions for class Assign
// -----------------------------------------------------------------------
Int32 Assign::getArity() const  { return 2; }

NABoolean Assign::isCovered(const ValueIdSet& newExternalInputs,
			    const GroupAttributes& coveringGA,
			    ValueIdSet& referencedInputs,
			    ValueIdSet& coveredSubExpr,
			    ValueIdSet& unCoveredExpr ) const
{
  // ---------------------------------------------------------------------
  // Compute the referenced input values, covered subexpressions and
  // uncovered expressions for the Assign.
  // ---------------------------------------------------------------------
  // The target is never covered
  if (coveringGA.covers(getSource(), newExternalInputs,
			referencedInputs,
			&coveredSubExpr, &unCoveredExpr))
    coveredSubExpr += getSource();

  // ---------------------------------------------------------------------
  // Regardless of whether its operands are covered, the Assignment
  // must be performed by the RelExpr with which it is associated.
  // ---------------------------------------------------------------------
  return FALSE;  // sorry, i am a special case
} // Assign::isCovered()

ItemExpr * Assign::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  Assign *result;

  if (derivedNode == NULL)
    result = new (outHeap) Assign(NULL, NULL);
  else
    result = (Assign *) derivedNode;

  return ItemExpr::copyTopNode(result, outHeap);
}

HashValue Assign::topHash()
{
  HashValue result = ItemExpr::topHash();

  // hash any local data members of the derived class

  return result;
}

// -----------------------------------------------------------------------
// member functions for class ItemList
// -----------------------------------------------------------------------
Int32 ItemList::getArity() const { return 2; }

NABoolean ItemList::isCovered
                      (const ValueIdSet& newExternalInputs,
		       const GroupAttributes& coveringGA,
		       ValueIdSet& referencedInputs,
		       ValueIdSet& coveredSubExpr,
		       ValueIdSet& unCoveredExpr) const
{
  ValueId exprId;
  NABoolean exprIsCovered = TRUE;

  NABoolean coverFlag;

  for (Lng32 i = 0; i < (Lng32)getArity(); i++)
    {
      ItemExpr *thisChild = (ItemExpr *)child(i);
      ItemExprList childList(thisChild,0);
      for (CollIndex j = 0; j < childList.entries(); j++)
	{
	  // Recurse, inserting leaf valueids into the cov/uncov sets
	  // without looking at or setting the local exprIsCovered var
	  exprId = childList[j]->getValueId();
	  coverFlag = coveringGA.covers(exprId,
					newExternalInputs,
					referencedInputs,
					&coveredSubExpr,
					&unCoveredExpr);
	  if (coverFlag)
	    coveredSubExpr += exprId;

	  exprIsCovered &= coverFlag;

	} // for j'th item in list

    } // for i'th child

  return exprIsCovered;

} // ItemList::isCovered()

ItemExpr * ItemList::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemList *result;

  if (derivedNode == NULL)
    result = new (outHeap) ItemList(NULL,NULL);
  else
    result = (ItemList *) derivedNode;

  return ItemExpr::copyTopNode(result, outHeap);
}

NABoolean ItemList::duplicateMatch(const ItemExpr& other) const
{
  if (NOT genericDuplicateMatch(other))
    return FALSE;

  return TRUE;
}

NABoolean ItemList::hasEquivalentProperties(ItemExpr * other)
{
  if (other == NULL)
    return FALSE;
  if (getOperatorType() != other->getOperatorType() || 
        getArity() != other->getArity())
    return FALSE;

  ItemList * otherList = (ItemList *) other;

  return 
      (this->numOfItems() == otherList->numOfItems()) && 
      (this->constChild() == otherList->constChild()) ;
}
// -----------------------------------------------------------------------
// member functions for Subquery operators
// -----------------------------------------------------------------------
Int32 Subquery::getArity() const
{
  switch (getOperatorType())
    {
    case ITM_ROW_SUBQUERY:
    case ITM_EXISTS:
    case ITM_NOT_EXISTS:
      return 0;
    default:
      return 1;
    }
} // Subquery::getArity()

// Virtual method
NABoolean Subquery::isASubquery() const { return TRUE; }

NABoolean Subquery::isAnAnySubquery() const
{
  switch (getOperatorType())
    {
    case ITM_EQUAL_ANY:
    case ITM_NOT_EQUAL_ANY:
    case ITM_GREATER_ANY:
    case ITM_GREATER_EQ_ANY:
    case ITM_LESS_EQ_ANY:
    case ITM_LESS_ANY:
      return TRUE;
    default:
      return FALSE;
    }

} // Subquery::isAnAnySubquery()

NABoolean Subquery::isAnAllSubquery() const
{
  switch (getOperatorType())
    {
    case ITM_EQUAL_ALL:
    case ITM_NOT_EQUAL_ALL:
    case ITM_GREATER_ALL:
    case ITM_GREATER_EQ_ALL:
    case ITM_LESS_EQ_ALL:
    case ITM_LESS_ALL:
      return TRUE;
    default:
      return FALSE;
    }

} // Subquery::isAnAnySubquery()

const NAString Subquery::getText() const
{
  return "unknown subquery";
} // Subquery::getText()

void Subquery::addLocalExpr(LIST(ExprNode *) &xlist,
			    LIST(NAString) &llist) const
{
  xlist.insert(tableExpr_);
  llist.insert("Subquery");
}

NABoolean Subquery::containsSubquery()
{
  return TRUE;
} // Subquery::containsSubquery

// <aviv> BEGIN
ItemExpr *
Subquery::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;
  if (derivedNode == NULL) {
	RelExpr* tableExprCopy = tableExpr_->copyTree(outHeap);
    result = new (outHeap) Subquery(getOperatorType(), tableExprCopy);
  }
  else
    result = derivedNode;

  ((Subquery *)result)->setAvoidHalloweenR2(getAvoidHalloweenR2());
  return ItemExpr::copyTopNode(result, outHeap);
}

// output degree functions to handle multi-output subqueries.
// Returns the number of outputs and the ItemExpr for each.
Int32 Subquery::getOutputDegree()
{
  if (!getRETDesc()) return -1; // Routine desc not set.  Error.
  else 
    return getRETDesc()->getColumnList()->entries();
}

ItemExpr *Subquery::getOutputItem(UInt32 i) 
{ 
  if (!getRETDesc()) return NULL; // Routine desc not set.  Error.
  else 
  {
    if (i < getRETDesc()->getColumnList()->entries())
      return getRETDesc()->getValueId(i).getItemExpr();
    else return NULL; // 'i' out of bounds.  Error.
  }
}
// <aviv> END


// -----------------------------------------------------------------------
// member functions for row subquery operators
// -----------------------------------------------------------------------
const NAString RowSubquery::getText() const
{
  //return "row subquery";
  NAString tmp(CmpCommon::statementHeap());
  if (getSubquery()->child(0))
    getSubquery()->child(0)->unparse(tmp);	// unparse below the subq root
  else
    getSubquery()->unparse(tmp);		// unparse the tuple
  return tmp;
}

ItemExpr *
RowSubquery::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;
  if (derivedNode == NULL) {
	RelExpr* tableExprCopy = getSubquery()->copyTree(outHeap);
    result = new (outHeap) RowSubquery(tableExprCopy);
  }
  else
    result = derivedNode;

  return Subquery::copyTopNode(result, outHeap);
}

// -----------------------------------------------------------------------
// member functions for Quantified comparison subquery operators
// -----------------------------------------------------------------------
const NAString QuantifiedComp::getText() const
{
  switch (getOperatorType())
    {
    case ITM_EQUAL_ANY:
      return "= any";
    case ITM_NOT_EQUAL_ANY:
      return "<> any";
    case ITM_GREATER_ANY:
      return "> any";
    case ITM_GREATER_EQ_ANY:
      return ">= any";
    case ITM_LESS_EQ_ANY:
      return "<= any";
    case ITM_LESS_ANY:
      return "< any";
    case ITM_EQUAL_ALL:
      return "= all";
    case ITM_NOT_EQUAL_ALL:
      return "<> all";
    case ITM_GREATER_ALL:
      return "> all";
    case ITM_GREATER_EQ_ALL:
      return ">= all";
    case ITM_LESS_EQ_ALL:
      return "<= all";
    case ITM_LESS_ALL:
      return "< all";
    default:
      return "? any|all ";
    }

} // QuantifiedComp::getText()

// Instead of this next function, we could add a wildcard to OperatorTypeEnum
// and augment the OperatorType::match() function in ExprNode.cpp...
static NABoolean isQuantifiedComp(const ItemExpr *ie)
{
  switch (ie->getOperatorType())
    {
    case ITM_EQUAL_ANY:
    case ITM_NOT_EQUAL_ANY:
    case ITM_GREATER_ANY:
    case ITM_GREATER_EQ_ANY:
    case ITM_LESS_EQ_ANY:
    case ITM_LESS_ANY:
    case ITM_EQUAL_ALL:
    case ITM_NOT_EQUAL_ALL:
    case ITM_GREATER_ALL:
    case ITM_GREATER_EQ_ALL:
    case ITM_LESS_EQ_ALL:
    case ITM_LESS_ALL:
      return TRUE;
    default:
      return FALSE;
    }

} // isQuantifiedComp()


// <aviv> BEGIN
ItemExpr *
QuantifiedComp::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  QuantifiedComp *result;
  if (derivedNode == NULL) {
    RelExpr* tableExprCopy = getSubquery()->copyTree(outHeap);

    // NOTICE: using child(0) here is based on the Subquery and ItemExpr constructors
    //         This is bad programming !!! A solution could be to change the order of
    //		   the parameters in this ctor and using defaults (NULL), yet it involves
    //		   changes in many other places in the code <aviv>
    result = new (outHeap) QuantifiedComp(getOperatorType(),
                                          (child(0))->copyTree(outHeap),
                                          tableExprCopy,
                                          getAvoidHalloweenR2());
  }
  else
    result = (QuantifiedComp*)derivedNode;

  result->createdFromINlist_ = createdFromINlist_;
  result->createdFromALLpred_ = createdFromALLpred_;

  return Subquery::copyTopNode(result, outHeap);
}
// <aviv> END


// -----------------------------------------------------------------------
// member functions for In subquery operators
// -----------------------------------------------------------------------
const NAString InSubquery::getText() const { return "in"; }

// <aviv> BEGIN
ItemExpr *
InSubquery::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;
  if (derivedNode == NULL) {
	RelExpr* tableExprCopy = getSubquery()->copyTree(outHeap);

	// NOTICE: using child(0) here is based on the Subquery and ItemExpr constructors
	//         This is bad programming !!! A solution could be to change the order of
	//		   the parameters in this ctor and using defaults (NULL), yet it involves
	//		   changes in many other places in the code <aviv>
    result = new (outHeap) InSubquery(getOperatorType(), (child(0))->copyTree(outHeap), tableExprCopy);
  }
  else
    result = derivedNode;

  return Subquery::copyTopNode(result, outHeap);
}
// <aviv> END


// --------------------------------------------------------------
// member functions for Abs operator
// --------------------------------------------------------------

ItemExpr * Abs::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) Abs(child(0));
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

// --------------------------------------------------------------
// member functions for CodeVal operator
// --------------------------------------------------------------

ItemExpr * CodeVal::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) CodeVal(getOperatorType(), child(0));
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

const NAString CodeVal::getText() const
{
  // to fix case 10-040504-4753  (Incorrect error text when using NULL as k
  // CODE_VALUE function parameter). The operator type for CodeVal is
  // NO_OPERATOR_TYPE until after the type is synthesized. getText() can be
  // called before that (e.g., in checkForSQLnullChild()).
  //
  // Use the general code_value name for such case.
  //
  if (getOperatorType() == NO_OPERATOR_TYPE )
     return "code_value";
  else
     return BuiltinFunction::getText();
}


// --------------------------------------------------------------
// member functions for AggrMinMax
// --------------------------------------------------------------

ItemExpr * AggrMinMax::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) AggrMinMax(NULL, NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

// --------------------------------------------------------------
// member functions for AggrGrouping function
// --------------------------------------------------------------
ItemExpr * AggrGrouping::copyTopNode(ItemExpr * derivedNode, CollHeap* outHeap)
{
  AggrGrouping *result;

  if (derivedNode == NULL)
    result = new (outHeap) AggrGrouping(-1);
  else
    result = (AggrGrouping*)derivedNode;

  result->rollupGroupIndex_ = rollupGroupIndex_;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

// -----------------------------------------------------------------------
// member functions for Exists subquery operators
// -----------------------------------------------------------------------

Exists::Exists(RelExpr  * tableExpr)
     : Subquery(ITM_EXISTS, tableExpr) {}

Exists::~Exists() {}

const NAString Exists::getText() const 
{
  if (isNotExists())
    return "not_exists";
  else
    return "exists";
}

// <aviv> BEGIN
ItemExpr *
Exists::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;
  if (derivedNode == NULL) {
	RelExpr* tableExprCopy = getSubquery()->copyTree(outHeap);
    result = new (outHeap) Exists(tableExprCopy);
    if (isNotExists())
      result->setOperatorType(getOperatorType());
  }
  else
    result = derivedNode;

  return Subquery::copyTopNode(result, outHeap);
}
// <aviv> END


// --------------------------------------------------------------
// member functions for Between operator
// --------------------------------------------------------------
ItemExpr * Between::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
  {
    result = new (outHeap) Between(NULL,NULL,NULL);
    ((Between*)result)->leftBoundryIncluded_ = leftBoundryIncluded_;
    ((Between*)result)->rightBoundryIncluded_ = rightBoundryIncluded_;

    // NOTICE: we are copying the pointer, not the allocating new memory
    // and copying the object. because of this the vector must never be
    // destroyed in any destructor
    ((Between*)result)->pDirectionVector_ = pDirectionVector_;

  }
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

void Between::unparse(NAString &result,
		      PhaseEnum phase,
                      UnparseFormatEnum form,
		      TableDesc * tabId) const
{
  child(0)->unparse(result,phase,form,tabId);

  result += " ";
  NAString kwd(getText(), CmpCommon::statementHeap());
  if (form == USER_FORMAT_DELUXE) kwd.toUpper();
  result += kwd;
  result += " ";

  child(1)->unparse(result,phase,form,tabId);

  kwd = " and ";
  if (form == USER_FORMAT_DELUXE) kwd.toUpper();
  result += kwd;

  child(2)->unparse(result,phase,form,tabId);
}

NABoolean Between::hasEquivalentProperties(ItemExpr * other)
{
  if (other == NULL)
    return FALSE;
  if (getOperatorType() != other->getOperatorType() || 
        getArity() != other->getArity())
    return FALSE;

  Between * tmp = (Between *) other;

  return 
    (this->leftBoundryIncluded_ == tmp->leftBoundryIncluded_) &&
    (this->rightBoundryIncluded_ == tmp->rightBoundryIncluded_ ) &&
    (this->pDirectionVector_ == tmp->pDirectionVector_);

}
// --------------------------------------------------------------
// member functions for BoolResult operator
// --------------------------------------------------------------

BoolResult::~BoolResult() {}

ItemExpr * BoolResult::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) BoolResult(NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

// --------------------------------------------------------------
// member functions for BoolVal operator
// --------------------------------------------------------------
ItemExpr * BoolVal::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    {
      if (getArity() == 0)
	result = new (outHeap) BoolVal(getOperatorType());
      else
	result = new (outHeap) BoolVal(getOperatorType(), NULL);
    }
  else
    result = derivedNode;

  return ItemExpr::copyTopNode(result, outHeap);
}

// --------------------------------------------------------------
// member functions for Case operator
// --------------------------------------------------------------
ItemExpr * Case::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) Case(NULL, NULL);
  else
    result = derivedNode;

  //++MV bug fix
  if (caseOperand_)
	((Case*) result)->caseOperand_ = caseOperand_->copyTree(outHeap);

  ((Case*) result)->caseOperandWasNullable_ = caseOperandWasNullable_;
  //--MV

  return BuiltinFunction::copyTopNode(result, outHeap);
}


// This method recursively removes from coveredSubExpr,
// all IfThenElse nodes that are part of 'expr' and for those IfThenElse
// nodes, adds its children to coveredSubExpr.
// input: expr, a non-null IfThenElse node.
// Added another parameter boolean ifThenEsleExists, which would be passed
// from the parent ifThenElse to its children. This will ensure that if there
// is more than two levels of if_then_else nesting, then even the inner
// if then else is correctly fixed. Sol: 10-041025-1038
void Case::fixIfThenElse(ItemExpr * expr, ValueIdSet& coveredSubExpr, NABoolean ifThenElseExists) const
{
  if ((! expr) ||
      (expr->getOperatorType() != ITM_IF_THEN_ELSE))
    return;

  // remove expr from coveredSubExpr, if it is there
  if (coveredSubExpr.contains(expr->getValueId()))
    {
      ifThenElseExists = TRUE;
      coveredSubExpr.remove(expr->getValueId());
    }

  // and add all its children to it
  for (Lng32 index = 0; index < expr->getArity(); index++)
    {
      if (expr->child(index))
	{
	  if (expr->child(index)->getOperatorType() == ITM_IF_THEN_ELSE)
	    fixIfThenElse(expr->child(index), coveredSubExpr, ifThenElseExists);
	  else if (ifThenElseExists)
	    coveredSubExpr.insert(expr->child(index)->getValueId());
	}
    }
}

NABoolean Case::isCovered
                  (const ValueIdSet& newExternalInputs,
		   const GroupAttributes& coveringGA,
		   ValueIdSet& referencedInputs,
		   ValueIdSet& coveredSubExpr,
		   ValueIdSet& unCoveredExpr ) const
{
  ValueIdSet coveredSubExprForCase ;
  NABoolean retVal =
  BuiltinFunction::isCovered(newExternalInputs, coveringGA,
			       referencedInputs, coveredSubExprForCase,
			       unCoveredExpr);

  // The case expression is covered as a unit. Parts of a case 
  // expression must not be pushed down independently of each other
  // as this cause divide by zero type errors (if the case expression
  // has different branches for the zero and non-zero cases, see soln.
  // 10-081107-7119). We do not column references and leaf values
  // to be counted as covered if they are. We use the getLeafValuesForCoverTest
  // for this purpose. Note that Case::getLeafValuesForCoverTest() returns 
  // itself.
  const ValueIdSet emptySet;
  //coveredSubExprForCase.getLeafValuesForCoverTest(coveredSubExpr, coveringGA, emptySet);
  coveredSubExprForCase.getLeafValuesForCoverTest(coveredSubExpr, coveringGA, newExternalInputs);

  return retVal;

}

void Case::unparse(NAString &result,
		       PhaseEnum phase,
		       UnparseFormatEnum form,
		       TableDesc * tabId) const
{
  // Is this for MV use?
  if ((form != MV_SHOWDDL_FORMAT) &&
      (form != QUERY_FORMAT) &&
      (form != COMPUTED_COLUMN_FORMAT) )
  {
    // No - sorry, use the default code.
    ItemExpr::unparse(result,phase, form, tabId);
  }
  else
  {
    // Yes - avoid the parenthasis:
    // Instead of "case (when....)"
    // Do "case when ...
    result += "case";
    child(0)->unparse(result, phase, form, tabId);
  }
}

void Case::getLeafValuesForCoverTest(ValueIdSet & leafValues, 
                                     const GroupAttributes& coveringGA,
                                     const ValueIdSet & newExternalInputs) const
{
  leafValues += getValueId();
} // Case::getLeafValuesForCoverTest()

NABoolean Case::hasEquivalentProperties(ItemExpr * other)
{
  if (other == NULL)
    return FALSE;
  if (getOperatorType() != other->getOperatorType() || 
        getArity() != other->getArity())
    return FALSE;

  Case * otherCase = (Case *) other;

  return  
      (this->getCaseOperand()== otherCase->getCaseOperand()) && 
      (this->caseOperandWasNullable() == otherCase->caseOperandWasNullable());
}
// --------------------------------------------------------------
// member functions for Cast operator
// --------------------------------------------------------------

Cast::Cast(ItemExpr *val1Ptr, const NAType *type, OperatorTypeEnum otype,
	   NABoolean checkForTrunc, NABoolean noStringTrunWarnings)
  :
  CacheableBuiltinFunction(otype, 1, val1Ptr), type_(type),
  reverseDataErrorConversionFlag_(FALSE),
  flags_(0)
{
  ValueId vid = val1Ptr ? val1Ptr->getValueId() : NULL_VALUE_ID;

  checkForTruncation_ = FALSE;
  if (checkForTrunc)
    if (vid == NULL_VALUE_ID)
      checkForTruncation_ = TRUE;
    else if ( type && type->getTypeQualifier()         == NA_CHARACTER_TYPE &&
              vid.getType().getTypeQualifier() == NA_CHARACTER_TYPE )
    {
       if ( type->getNominalSize() < vid.getType().getNominalSize() )
        checkForTruncation_ = TRUE;
       else
       { // If UTF8 and *any* chance of truncation error
         // Ex: casting CHAR(8 BYTES) to CHAR(3) 
          if ( ((CharType *)type)->getCharSet() == CharInfo::UTF8  &&
               ((CharType *)type)->getStrCharLimit() < vid.getType().getNominalSize() )
          checkForTruncation_ = TRUE;
       }
    }
             
  setNoStringTruncationWarnings(noStringTrunWarnings);
}

Cast::Cast(ItemExpr *val1Ptr, ItemExpr *errorOutPtr, const NAType *type,
	   OperatorTypeEnum otype, NABoolean checkForTrunc,
           NABoolean reverseDataErrorConversionFlag,
           NABoolean noStringTrunWarnings)
  :
  CacheableBuiltinFunction(otype, 2, val1Ptr, errorOutPtr), type_(type),
  reverseDataErrorConversionFlag_(reverseDataErrorConversionFlag),
  flags_(0)
{
  checkForTruncation_ = checkForTrunc;
  setNoStringTruncationWarnings(noStringTrunWarnings);
}

Cast::~Cast() {}

ConstValue * Cast::castToConstValue(NABoolean & negate_it)
{
  return child(0)->castToConstValue(negate_it);
}

ItemExpr * Cast::foldConstants(ComDiagsArea * diagsArea,
			       NABoolean newTypeSynthesis)
{
  // Convert a cast on top of a constant into a new constant with
  // the correct type. The reason for implementing this special
  // case of constant folding is that the optimizer needs to generate
  // the actual binary representation of constants in some cases
  // (e.g. when generating the split ranges of a partitioning scheme).

  ItemExpr *result = this;

  if (child(0)->getOperatorType() == ITM_CONSTANT)
    {
      const NAType &t = child(0)->getValueId().getType();

      // simple case, the cast is unnecessary because the child
      // already has the correct type: eliminate this node
      if (t == *type_)
	return child(0);

      // try one more case, mapping of numeric data types:

    }

  return ItemExpr::foldConstants(diagsArea,newTypeSynthesis);
}

NABoolean Cast::isCovered
                   (const ValueIdSet& newExternalInputs,
		    const GroupAttributes& coveringGA,
		    ValueIdSet& referencedInputs,
		    ValueIdSet& coveredSubExpr,
		    ValueIdSet& unCoveredExpr) const
{
  NABoolean coverFlag = TRUE;
  if (coveringGA.covers(getExpr()->getValueId(),
			newExternalInputs, referencedInputs,
			&coveredSubExpr, &unCoveredExpr))
    coveredSubExpr += getExpr()->getValueId();
  else
    coverFlag = FALSE;

  if (getOperatorType() == ITM_INSTANTIATE_NULL)
    return FALSE; //
  else
    return coverFlag;
} // Cast::isCovered()

// MV -- 
// If this is a Cast over an NATypeToItem, return this ValueId instead
// of the child's. This fixes a problem with using the TupleList for the
// MVLog command.
void Cast::getLeafValuesForCoverTest(ValueIdSet & leafValues, 
                                     const GroupAttributes& coveringGA,
                                     const ValueIdSet & newExternalInputs) const
{
  if(ITM_NATYPE == child(0)->getOperatorType())
  {
    leafValues += getValueId();
  }
  else
  {
    // Otherwise - call the super class.
    BuiltinFunction::getLeafValuesForCoverTest(leafValues, coveringGA, newExternalInputs);
  }
}

ItemExpr * Cast::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    {
      result = new (outHeap) Cast(NULL, type_->newCopy(outHeap),
		this->getOperatorType(), this->checkForTruncation_);

      // Fix CR 10-010426-2464: Copy other members of the class as well
      ((Cast *)result)->reverseDataErrorConversionFlag_ =
		this->reverseDataErrorConversionFlag_;

      ((Cast *)result)->flags_ = this->flags_;
    }
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

ItemExpr * CastConvert::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) CastConvert(NULL, getType()->newCopy(outHeap));
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

ItemExpr * CastType::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) 
      CastType(NULL, 
               (getType() ? getType()->newCopy(outHeap) : NULL));
  else
    result = derivedNode;
  
  ((CastType*)result)->makeNullable_ = makeNullable_;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

NABoolean Cast::isEquivalentForCodeGeneration(const ItemExpr * other)
  {
  NABoolean rc = FALSE;        // assume failure

  if (hasBaseEquivalenceForCodeGeneration(other))
    {
    // we know that other is a Cast, and that the children are equivalent
    Cast * otherCast = (Cast *)other;
    const NAType & otherCastType = *(otherCast->type_);

    if (type_->operator==(otherCastType))
      if (checkForTruncation_ == otherCast->checkForTruncation_)
        rc = TRUE;        // the two casts can be produced by the same code
    }

  return rc;
  }

NABoolean Cast::hasEquivalentProperties(ItemExpr * other)
{
  if (other == NULL)
    return FALSE;
  if (getOperatorType() != other->getOperatorType() || 
        getArity() != other->getArity())
    return FALSE;

  Cast * tmp = (Cast *) other;
  
  return  
      (this->type_->operator == (*(tmp->type_) )) &&
      (this->checkForTruncation_ == tmp->checkForTruncation_ ) &&
      (this->reverseDataErrorConversionFlag_ == tmp->reverseDataErrorConversionFlag_ ) &&
    //      (this->noStringTruncationWarnings_ == tmp->noStringTruncationWarnings_  ) &&
      (this->flags_ == tmp->flags_);
}
// --------------------------------------------------------------
// member functions for CharFunc operator
// --------------------------------------------------------------

ItemExpr * CharFunc::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL) {
    result = new (outHeap) CharFunc(charSet_, child(0));
  }
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}


// --------------------------------------------------------------
// member functions for IfThenElse operator
// --------------------------------------------------------------
ItemExpr * IfThenElse::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) IfThenElse(NULL, NULL, NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

NABoolean IfThenElse::isCharTypeMatchRulesRelaxable()
{
   NABoolean ok =
             child(0)->isCharTypeMatchRulesRelaxable() &&
             child(1)->isCharTypeMatchRulesRelaxable();

   if (child(2).getPtr() != NULL)
      ok = ok && child(2)->isCharTypeMatchRulesRelaxable();

   return ok;
}

void IfThenElse::unparse(NAString &result,
		       PhaseEnum phase,
		       UnparseFormatEnum form,
		       TableDesc * tabId) const
{
  // Is this for MV use?
  if ( (form != MV_SHOWDDL_FORMAT) &&
       (form != QUERY_FORMAT) &&
       (form != COMPUTED_COLUMN_FORMAT))
  {
    // No - sorry, use the default code.
    ItemExpr::unparse(result, phase, form, tabId);
  }
  else
  {
    // Instead of: case( if_then_else(cond1, op1, if_then_else(cond2, op2, op3)))
    // do this: CASE WHEN cond1 THEN op1 WHEN cond2 THEN op2 ELSE op3 END
    result += " WHEN ";
    child(0)->unparse(result, phase, form, tabId);
    result += " THEN ";
    child(1)->unparse(result, phase, form, tabId);
    // Any more nested conditions?
    if (child(2)->getOperatorType() == ITM_IF_THEN_ELSE)
    {
      // Yes - Recursive call to the next condition
      child(2)->unparse(result, phase, form, tabId);
    }
    else
    {
      // No - Do the ELSE.
      result += " ELSE ";
      child(2)->unparse(result, phase, form, tabId);
      result += " END ";
    }
  }
}

//----------------------------------------------------------------
// member functions of RaiseError operator
//----------------------------------------------------------------

RaiseError::~RaiseError() {}

const NAString RaiseError::getText() const
{
  return NAString("RaiseError(") + getConstraintName() + ")";
}

ItemExpr * RaiseError::copyTopNode (ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
  {
	if (getArity() > 0) // Do we have string expressions?
	  result = new (outHeap) RaiseError(getSQLCODE(),
					    getConstraintName(),
					    child(0)->copyTree(outHeap),
					    outHeap);
	else
	  result = new (outHeap) RaiseError(getSQLCODE(),
					    getConstraintName(),
					    getTableName(),
					    outHeap);
  }
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

// --------------------------------------------------------------
// member functions for Narrow operator
// --------------------------------------------------------------

Narrow::~Narrow() {}

// Note:  We simply inherit isCovered() from Cast

ItemExpr * Narrow::copyTopNode(ItemExpr *derivedNode,
			       CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
  {
    // Begin_Fix 10-040114-2431
    // 02/18/2004
    // changed to copy data member matchChildNullability_
    result = new (outHeap) Narrow(NULL,
                                  NULL,
                                  getType()->newCopy(outHeap),
                                  ITM_NARROW,
                                  FALSE,
                                  matchChildNullability_);
    // End_Fix 10-040114-2431

    ((Narrow*)result)->setMatchChildType(matchChildType());
  }
  else
    result = derivedNode;

  // $$$
  // $$$ shouldn't this last line instead be something like
  // $$$   Cast::copyTopNode(result, outHeap); ?!!??
  return ItemExpr::copyTopNode(result, outHeap);
}

NABoolean Narrow::hasEquivalentProperties(ItemExpr * other)
{
  if (other == NULL)
    return FALSE;
  if (getOperatorType() != other->getOperatorType() || 
        getArity() != other->getArity())
    return FALSE;

  Narrow * tmp = (Narrow *) other;

  return 
    (this->matchChildNullability_ == tmp->matchChildNullability_);

}
// -----------------------------------------------------------------------
// member functions for class InstantiateNull
// -----------------------------------------------------------------------

// ----------------------------------------------------------------------
// Walk through an ItemExpr tree and gather the ValueIds of those
// expressions that behave as if they are "leaves" for the sake of
// the coverage test, e.g., expressions that have no children, or
// aggregate functions, or instantiate null. These are usually values
// that are produced in one "scope" and referenced above that "scope"
// in the dataflow tree for the query.
// ----------------------------------------------------------------------
void InstantiateNull::getLeafValuesForCoverTest(ValueIdSet & leafValues, 
                                                const GroupAttributes& coveringGA,
                                                const ValueIdSet & newExternalInputs) const
{
  leafValues += getValueId();
} // InstantiateNull::getLeafValuesForCoverTest()

ItemExpr * InstantiateNull::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap)
      InstantiateNull(NULL, getType()->newCopy(outHeap));
  else
    result = derivedNode;

  ((InstantiateNull *)result)->beginLOJTransform_ = beginLOJTransform_;
  return BuiltinFunction::copyTopNode(result, outHeap);
}

NABoolean InstantiateNull::isAColumnReference( )
  { 
    if (child(0)) {
     /*  return child(0)->isAColumnReference();
     commenting this line out as it causes regression tests to fail */
      if ((child(0)->getOperatorType() != ITM_VALUEIDUNION) &&
	  (NOT child(0)->isAnAggregate()))
	  return TRUE;
    }
      return FALSE;
  }

NABoolean InstantiateNull::hasEquivalentProperties(ItemExpr * other)
{
  if (other == NULL)
    return FALSE;
  if (getOperatorType() != other->getOperatorType() || 
        getArity() != other->getArity())
    return FALSE;

  InstantiateNull * tmp = (InstantiateNull *) other;

  return  
    (this->NoCheckforLeftToInnerJoin == tmp->NoCheckforLeftToInnerJoin ) &&
    (this->beginLOJTransform_ == tmp->beginLOJTransform_ );
}

// InstantiateNull is never equivalent to another instance.  Even when
// two instances are similar, they cannot be considered equivalent
// since they may have come from different outer joins.  The
// InstantiateNull ItemExpr operates in the context of a join, but
// this is not recorded in the data members of the class.
NABoolean InstantiateNull::isEquivalentForCodeGeneration(const ItemExpr * other)
{
  return FALSE;
}



// --------------------------------------------------------------
// member functions for BitOperFunc operator
// --------------------------------------------------------------
Int32 BitOperFunc::getArity() const
{
  if (child(0) == NULL)
    return 0;
  else if (child(1) == NULL)
    return 1;
  else if (child(2) == NULL)
    return 2;
  else
    return 3;
}

ItemExpr * BitOperFunc::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) BitOperFunc(getOperatorType(), NULL,NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

const NAString BitOperFunc::getText() const
{
  switch (getOperatorType())
    {
    case ITM_BITAND:       return "bitand";
    case ITM_BITOR:        return "bitor";
    case ITM_BITXOR:       return "bitxor";
    case ITM_BITNOT:       return "bitnot";
    case ITM_BITEXTRACT:   return "bitextract";
    default:
      return "unknown bit func";
    } // switch
}

// --------------------------------------------------------------
// member functions for CompEncode operator
// --------------------------------------------------------------

CompEncode::~CompEncode() {}

ItemExpr * CompEncode::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) CompEncode(NULL, 
                                      descFlag_, 
                                      length_,
                                      collationType_,
                                      regularNullability_,
                                      outHeap);
  else
    result = derivedNode;

  ((CompEncode *) result)->caseinsensitiveEncode_ = caseinsensitiveEncode_;
  ((CompEncode *) result)->encodedCollation_ = encodedCollation_;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

Lng32  CompEncode::getEncodedLength(  const CharInfo::Collation collation,
				  const CollationInfo::CollationType ct,
				  const Lng32 srcLength,
				  const NABoolean nullable)
{
  CMPASSERT(CollationInfo::isSystemCollation(collation));
    	
  Int32 nPasses= CollationInfo::getCollationNPasses(collation);

  switch (ct)
  {
    case CollationInfo::Sort:
    {
      return nPasses *  (srcLength + 1 ) +  
	      (nullable? ExpTupleDesc::KEY_NULL_INDICATOR_LENGTH: 0 )  ;
    }
    case CollationInfo::Compare:
    {
	return nPasses * (srcLength + 1 ) ;
    }
    case CollationInfo::Search:
    {
      return nPasses * srcLength;
    }
    default:
    {
	    CMPASSERT(0);
	    return NULL;
    }
  }
}

// --------------------------------------------------------------
// member functions for CompDecode operator
// --------------------------------------------------------------

CompDecode::~CompDecode() {}

ItemExpr * CompDecode::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) CompDecode(NULL,
                                      unencodedType_->newCopy(outHeap),
                                      descFlag_,
				      length_,
                                      collationType_,
				      regularNullability_,
                                      outHeap);
  else
    result = derivedNode;

  return CompEncode::copyTopNode(result, outHeap);
}


// --------------------------------------------------------------
// member functions for LOBoper operator
// --------------------------------------------------------------
ItemExpr * LOBoper::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  LOBoper *result;

  if (derivedNode == NULL)
    result = new (outHeap) LOBoper(getOperatorType(), NULL, NULL, NULL,obj_);
  else
    result = (LOBoper*)derivedNode;

  result->lobNum() = lobNum();
  result->lobStorageType() = lobStorageType();
  result->lobStorageLocation() = lobStorageLocation();

  return BuiltinFunction::copyTopNode(result, outHeap);
}

ItemExpr * LOBinsert::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  LOBinsert *result;

  if (derivedNode == NULL)
    result = new (outHeap) LOBinsert(NULL, NULL, obj_, append_);
  else
    result = (LOBinsert*)derivedNode;

  result->insertedTableObjectUID() = insertedTableObjectUID();
  result->insertedTableSchemaName() = insertedTableSchemaName();
  //  result->lobNum() = lobNum();
  result->lobSize() = lobSize();
  result->lobFsType() = lobFsType();

  return LOBoper::copyTopNode(result, outHeap);
}

ItemExpr * LOBselect::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) LOBselect(NULL, NULL, obj_);
  else
    result = derivedNode;

  return LOBoper::copyTopNode(result, outHeap);
}

ItemExpr * LOBdelete::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) LOBdelete(NULL);
  else
    result = derivedNode;

  return LOBoper::copyTopNode(result, outHeap);
}

ItemExpr * LOBupdate::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  LOBupdate *result;

  if (derivedNode == NULL)
    result = new (outHeap) LOBupdate(NULL, NULL, NULL,obj_, append_);
  else
    result = (LOBupdate*)derivedNode;

  result->updatedTableObjectUID() = updatedTableObjectUID();
  result->updatedTableSchemaName() = updatedTableSchemaName();

  return LOBoper::copyTopNode(result, outHeap);
}
/*
Int32 LOBupdate::getArity() const
{
  if (obj_ == EMPTY_LOB_)
    return 0;
  else
    return getNumChildren();
}
*/
ItemExpr * LOBconvert::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) LOBconvert(NULL,obj_,tgtSize_);
  else
    result = derivedNode;

  return LOBoper::copyTopNode(result, outHeap);
}

ItemExpr * LOBconvertHandle::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) LOBconvertHandle(NULL, obj_);
  else
    result = derivedNode;

  return LOBoper::copyTopNode(result, outHeap);
}

ItemExpr * LOBextract::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) LOBextract(NULL, tgtSize_);
  else
    result = derivedNode;

  return LOBoper::copyTopNode(result, outHeap);
}


// --------------------------------------------------------------
// member functions for Concat operator
// --------------------------------------------------------------
ItemExpr * Concat::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) Concat(NULL, NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

// --------------------------------------------------------------
// member functions for Format operator
// --------------------------------------------------------------

Format::~Format() {}

ItemExpr * Format::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  Format *result;

  if (derivedNode == NULL)
    result = new (outHeap) Format(NULL, formatStr_, formatCharToDate_);
  else
    result = (Format*)derivedNode;

  result->formatCharToDate_ = formatCharToDate_;
  result->formatType_ = formatType_;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

// --------------------------------------------------------------
// member functions for Hash operator
// --------------------------------------------------------------

ItemExpr * Hash::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) Hash(NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

// --------------------------------------------------------------
// member functions for HashComp operator
// --------------------------------------------------------------

HashComb::~HashComb() {}

ItemExpr * HashComb::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) HashComb(NULL,NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

// --------------------------------------------------------------
// member functions for HashDistPartHash operator
// Hash Function used by Hash Partitioning. This function cannot change
// once Hash Partitioning is released!  Defined for all data types,
// returns a 32 bit non-nullable hash value for the data item.
//--------------------------------------------------------------
HashDistPartHash::~HashDistPartHash() {}

ItemExpr *
HashDistPartHash::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) HashDistPartHash(NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

// --------------------------------------------------------------
// member functions for HashDistPartHashComp operator
// This function is used to combine two hash values to produce a new
// hash value. Used by Hash Partitioning. This function cannot change
// once Hash Partitioning is released!  Defined for all data types,
// returns a 32 bit non-nullable hash value for the data item.
// --------------------------------------------------------------

HashDistPartHashComb::~HashDistPartHashComb() {}

ItemExpr *
HashDistPartHashComb::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) HashDistPartHashComb(NULL,NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

// --------------------------------------------------------------
// member functions for HiveFunc operator
// --------------------------------------------------------------
ItemExpr * HiveHash::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) HiveHash(NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

// --------------------------------------------------------------
// member functions for HiveHashComb operator
// --------------------------------------------------------------
ItemExpr * HiveHashComb::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) HiveHashComb(NULL,NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}



// --------------------------------------------------------------
// member functions for MathFunc operator
// --------------------------------------------------------------
Int32 MathFunc::getArity() const
{
  if (child(0) == NULL)
    return 0;
  else if (child(1) == NULL)
    return 1;
  else
    return 2;
}

ItemExpr * MathFunc::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) MathFunc(getOperatorType(), NULL,NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

const NAString MathFunc::getText() const
{
  switch (getOperatorType())
    {
    case ITM_ABS:          return "abs";
    case ITM_ACOS:         return "acos";
    case ITM_ASIN:         return "asin";
    case ITM_ATAN:         return "atan";
    case ITM_ATAN2:        return "atan2";
    case ITM_CEIL:         return "ceiling";
    case ITM_COS:          return "cos";
    case ITM_COSH:         return "cosh";
    case ITM_DEGREES:      return "degrees";
    case ITM_EXP:          return "exp";
    case ITM_EXPONENT:     return "'**'";
    case ITM_FLOOR:        return "floor";
    case ITM_LOG:          return "log";
    case ITM_LOG10:        return "log10";
    case ITM_LOG2:         return "log2";
    case ITM_PI:           return "pi";
    case ITM_POWER:        return "power";
    case ITM_RADIANS:      return "radians";
    case ITM_ROUND:        return "round";
    case ITM_SCALE_TRUNC:  return "truncate";
    case ITM_SIN:          return "sin";
    case ITM_SINH:         return "sinh";
    case ITM_SQRT:         return "sqrt";
    case ITM_TAN:          return "tan";
    case ITM_TANH:         return "tanh";

    default:
      return "unknown math func";
    } // switch
}

// --------------------------------------------------------------
// member functions for Modulus operator
// --------------------------------------------------------------

Modulus::~Modulus() {}

ItemExpr * Modulus::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) Modulus(NULL,NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

// --------------------------------------------------------------
// member functions for Repeat operator
// --------------------------------------------------------------

ItemExpr * Repeat::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) Repeat(NULL, NULL);
  else
    result = derivedNode;
  
  ((Repeat *) result)->setMaxLength(getMaxLength());
  ((Repeat *) result)->maxLengthWasExplicitlySet_ = maxLengthWasExplicitlySet_;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

// --------------------------------------------------------------
// member functions for Replace operator
// --------------------------------------------------------------

ItemExpr * Replace::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) Replace(NULL, NULL, NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

// --------------------------------------------------------------
// member functions for ReplaceNull operator
// --------------------------------------------------------------

ItemExpr * ReplaceNull::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) ReplaceNull(NULL, NULL, NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

// --------------------------------------------------------------
// member functions for HashDistrib operator
// --------------------------------------------------------------

HashDistrib::~HashDistrib() {}

ItemExpr * HashDistrib::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  CMPASSERT (derivedNode != NULL);

  return BuiltinFunction::copyTopNode(derivedNode, outHeap);
}

// --------------------------------------------------------------
// member functions for Hash2Distrib operator
// --------------------------------------------------------------

Hash2Distrib::~Hash2Distrib() {}

ItemExpr * Hash2Distrib::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) Hash2Distrib(NULL,NULL);
  else
    result = derivedNode;

  return HashDistrib::copyTopNode(result, outHeap);
}

// --------------------------------------------------------------
// member functions for ProgDistrib operator
// --------------------------------------------------------------

ProgDistrib::~ProgDistrib() {}

ItemExpr * ProgDistrib::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) ProgDistrib(NULL,NULL);
  else
    result = derivedNode;

  return HashDistrib::copyTopNode(result, outHeap);
}

// --------------------------------------------------------------
// member functions for ProgDistribKey operator
// --------------------------------------------------------------

ProgDistribKey::~ProgDistribKey() {}

ItemExpr *
ProgDistribKey::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) ProgDistribKey(NULL,NULL,NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

// --------------------------------------------------------------
// member functions for PAGroup operator
// --------------------------------------------------------------

PAGroup::~PAGroup() {}

ItemExpr * PAGroup::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) PAGroup(NULL,NULL, NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

// --------------------------------------------------------------
// member functions for InverseOrder operator
// --------------------------------------------------------------

ItemExpr * InverseOrder::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) InverseOrder(NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}

// --------------------------------------------------------------
// member functions for In operator
// --------------------------------------------------------------
ItemExpr * In::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) In(NULL, NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}
// --------------------------------------------------------------
// member functions for NATypeToItem operator
// --------------------------------------------------------------
Int32 NATypeToItem::getArity() const { return 0; }
const NAString NATypeToItem::getText() const
{  return natype_pointer->getTypeSQLname(TRUE); }

ItemExpr * NATypeToItem::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) NATypeToItem( natype_pointer );
  else
    result = derivedNode;

  return ItemExpr::copyTopNode(result, outHeap);
}

// --------------------------------------------------------------
// member functions for NamedTypeToItem operator
// --------------------------------------------------------------

ItemExpr* NamedTypeToItem::copyTopNode(ItemExpr *derivedNode, CollHeap *outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) NamedTypeToItem(name_.data(),
                                           natype_pointer,
                                           outHeap);
  else
    result = derivedNode;

  return NATypeToItem::copyTopNode(result, outHeap);
}

const NAString NamedTypeToItem::getText() const
{
  return name_;
}

// --------------------------------------------------------------
// member functions for NoOp operator
// --------------------------------------------------------------

NoOp::~NoOp() {}

ItemExpr * NoOp::copyTopNode(ItemExpr * derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) NoOp(NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
}


// -----------------------------------------------------------------------
// member functions for class RandomNum
// -----------------------------------------------------------------------

RandomNum::~RandomNum() {}

ItemExpr * RandomNum::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) RandomNum(NULL, simpleRandom_);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // RandomNum::copyTopNode()

// MV, 
// -----------------------------------------------------------------------
// member functions for class GenericUpdateOutputFunction
// -----------------------------------------------------------------------
ItemExpr * GenericUpdateOutputFunction::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) GenericUpdateOutputFunction(getOperatorType());
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // GenericUpdateOutputFunction::copyTopNode()

// Triggers - 
// -----------------------------------------------------------------------
// member functions for class InternalTimestamp
// -----------------------------------------------------------------------
InternalTimestamp::~InternalTimestamp() {}

ItemExpr * InternalTimestamp::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) InternalTimestamp();
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // Timestamp::copyTopNode()
//++Triggers, 

// -----------------------------------------------------------------------
// member functions for class UniqueExecuteId
// -----------------------------------------------------------------------

UniqueExecuteId::~UniqueExecuteId() {}

ItemExpr * UniqueExecuteId::copyTopNode(ItemExpr *derivedNode,
					 CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) UniqueExecuteId();
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result,outHeap);

} // UniqueExecuteId::copyTopNode()


// -----------------------------------------------------------------------
// member functions for class GetTriggersStatus
// -----------------------------------------------------------------------
GetTriggersStatus::~GetTriggersStatus() {}

ItemExpr * GetTriggersStatus::copyTopNode(ItemExpr *derivedNode,
										  CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) GetTriggersStatus();
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result,outHeap);

} // GetTriggersStatus::copyTopNode()

// -----------------------------------------------------------------------
// member functions for GetBitValueAt
// -----------------------------------------------------------------------
GetBitValueAt::~GetBitValueAt() {}

ItemExpr * GetBitValueAt::copyTopNode(ItemExpr *derivedNode,
									  CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
  {
    result = new (outHeap) GetBitValueAt(child(0), child(1));
  }
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // GetBitValueAt::copyTopNode()

//--Triggers, 

//++MV, 
// -----------------------------------------------------------------------
// member functions for IsBitwiseAndTrue
// -----------------------------------------------------------------------
IsBitwiseAndTrue::~IsBitwiseAndTrue() {}

ItemExpr * IsBitwiseAndTrue::copyTopNode(ItemExpr *derivedNode,
					 CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
  {
    result = new (outHeap) IsBitwiseAndTrue(child(0), child(1));
  }
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // IsBitwiseAndTrue::copyTopNode()

//--MV, 


// -----------------------------------------------------------------------
// member functions for class Mask
// -----------------------------------------------------------------------

Mask::~Mask() {}

ItemExpr * Mask::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) Mask(ITM_MASK_SET, NULL, NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // Mask::copyTopNode()

// -----------------------------------------------------------------------
// member functions for class Shift
// -----------------------------------------------------------------------

Shift::~Shift() {}

ItemExpr * Shift::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) Shift(ITM_SHIFT_RIGHT, NULL, NULL);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // Shift::copyTopNode()

// -----------------------------------------------------------------------
// member functions for class AnsiUSERFunction
// -----------------------------------------------------------------------
AnsiUSERFunction::~AnsiUSERFunction() {}

NABoolean AnsiUSERFunction::isAUserSuppliedInput() const	{ return TRUE; }

ItemExpr * AnsiUSERFunction::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) AnsiUSERFunction(getOperatorType());
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // AnsiUSERFunction::copyTopNode()

// -----------------------------------------------------------------------
// member functions for class MonadicUSERFunction
// -----------------------------------------------------------------------
MonadicUSERFunction::~MonadicUSERFunction() {}

NABoolean MonadicUSERFunction::isAUserSuppliedInput() const	{ return TRUE; }

ItemExpr * MonadicUSERFunction::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) MonadicUSERFunction(child(0));
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // MonadicUSERFunction::copyTopNode()

NABoolean MonadicUSERFunction::isCovered
                   (const ValueIdSet& newExternalInputs,
		    const GroupAttributes& coveringGA,
		    ValueIdSet& referencedInputs,
		    ValueIdSet& coveredSubExpr,
		    ValueIdSet& unCoveredExpr) const
{
  // If the argument of USER function is not a constant then it can be
  // evaluated anywhere in the tree. So check for its coverage
  ValueIdSet localSubExpr;
  for (Lng32 i = 0; i < (Lng32)getArity(); i++)
    {
      if ( coveringGA.covers(child(i)->getValueId(),
			     newExternalInputs,
			     referencedInputs,
			     &localSubExpr) )
	{
	  coveredSubExpr += child(i)->getValueId();
	}
    }

  // The USER function is not pushed down.

  return FALSE;

} // MonadicUSERFunction::isCovered

// -----------------------------------------------------------------------
// member functions for class MonadicUSERIDFunction
// -----------------------------------------------------------------------
MonadicUSERIDFunction::~MonadicUSERIDFunction() {}

ItemExpr * MonadicUSERIDFunction::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) MonadicUSERIDFunction(child(0));
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // MonadicUSERIDFunction::copyTopNode()



// -----------------------------------------------------------------------
// member functions for class Translate
// -----------------------------------------------------------------------
Translate::Translate(ItemExpr *valPtr, NAString* map_table_name)
: CacheableBuiltinFunction(ITM_TRANSLATE, 1, valPtr)
{

  if ( _strcmpi(map_table_name->data(), "UNICODE_TO_SJIS") == 0 ||
       _strcmpi(map_table_name->data(), "UTOSJ") == 0
     )
    map_table_id_ = Translate::UNICODE_TO_SJIS;
  else
    if ( _strcmpi(map_table_name->data(), "UCS2TOSJIS") == 0)
      map_table_id_ = Translate::UCS2_TO_SJIS;
    else
      if ( _strcmpi(map_table_name->data(), "UCS2TOUTF8") == 0)
        map_table_id_ = Translate::UCS2_TO_UTF8;
      else
        if ( _strcmpi(map_table_name->data(), "UCS2TOISO88591") == 0 )
          map_table_id_ = Translate::UNICODE_TO_ISO88591;
        else
          if ( _strcmpi(map_table_name->data(), "SJIS_TO_UNICODE") == 0 ||
               _strcmpi(map_table_name->data(), "SJTOU") == 0
            )
            map_table_id_ = Translate::SJIS_TO_UNICODE;
          else
            if ( _strcmpi(map_table_name->data(), "SJISTOUCS2") == 0)
              map_table_id_ = Translate::SJIS_TO_UCS2;
            else
              if ( _strcmpi(map_table_name->data(), "UTF8TOUCS2") == 0 )
                map_table_id_ = Translate::UTF8_TO_UCS2;
              else
                if ( _strcmpi(map_table_name->data(), "ISO88591TOUCS2") == 0 )
                  map_table_id_ = Translate::ISO88591_TO_UNICODE;

  else if ( _strcmpi(map_table_name->data(), "ISO88591TOUTF8") == 0 )
    map_table_id_ = Translate::ISO88591_TO_UTF8;
  else if ( _strcmpi(map_table_name->data(), "UTF8TOISO88591") == 0 )
    map_table_id_ = Translate::UTF8_TO_ISO88591;
  else if ( _strcmpi(map_table_name->data(), "SJISTOUTF8") == 0 )
    map_table_id_ = Translate::SJIS_TO_UTF8;
  else if ( _strcmpi(map_table_name->data(), "UTF8TOSJIS") == 0 )
    map_table_id_ = Translate::UTF8_TO_SJIS;
  else if ( _strcmpi(map_table_name->data(), "GBKTOUTF8") == 0 )
    map_table_id_ = Translate::GBK_TO_UTF8;

                else
                  if ( _strcmpi(map_table_name->data(), "KANJITOISO88591") == 0 )
                    map_table_id_ = Translate::KANJI_MP_TO_ISO88591;
                  else
                    if ( _strcmpi(map_table_name->data(), "KSC5601TOISO88591") == 0 )
                      map_table_id_ = Translate::KSC5601_MP_TO_ISO88591;
                    else
                      map_table_id_ = UNKNOWN_TRANSLATION;

  allowsSQLnullArg() = FALSE;
}

Translate::Translate(ItemExpr *valPtr, Int32 map_table_id)
       : CacheableBuiltinFunction(ITM_TRANSLATE, 1, valPtr)
{
    map_table_id_ = map_table_id;
    allowsSQLnullArg() = FALSE;
}

ItemExpr * Translate::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) Translate(child(0), getTranslateMapTableId());
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // Translate::copyTopNode()


// do not know why. But if this function is put inside Translate's
// class definition, cl.exe aborts with the following info:
// cl.exe ... sooutput.cpp
//../rogue\rw/locale.h(243) : fatal error C1001: INTERNAL COMPILER ERROR
//                (compiler file 'msc1.cpp', line 1188)
//    Please choose the Technical Support command on the Visual C++
//    Help menu, or open the Technical Support help file for more information
NABoolean Translate::isCharTypeMatchRulesRelaxable()
{
  return child(0)->isCharTypeMatchRulesRelaxable();
}

void Translate::unparse(NAString &result,
                        PhaseEnum phase,
                        UnparseFormatEnum form,
                        TableDesc* tabId) const
{
  if (CmpCommon::getDefault(MVQR_LOG_QUERY_DESCRIPTORS) != DF_DUMP_MV)
    return CacheableBuiltinFunction::unparse(result, phase, form, tabId);
  else
  {
    result += "translate(";
    child(0)->unparse(result, phase, form, tabId);
    result += " using ";
    NAString translation;
    switch (map_table_id_)
    {
      case UNICODE_TO_SJIS         : translation="UCS2_TO_SJIS";        break;
      case UNICODE_TO_ISO88591     : translation="UCS2TOISO88591";      break;
      case ISO88591_TO_UNICODE     : translation="ISO88591TOUCS2";      break;
      case SJIS_TO_UNICODE         : translation="SJIS_TO_UCS2";        break;
      case UCS2_TO_SJIS            : translation="UCS2TOSJIS";          break;
      case SJIS_TO_UCS2            : translation="SJISTOUCS2";          break;
      case UCS2_TO_UTF8            : translation="UCS2TOUTF8";          break;
      case UTF8_TO_UCS2            : translation="UTF8TOUCS2";          break;
      case UTF8_TO_SJIS            : translation="UTF8TOSJIS";          break;
      case SJIS_TO_UTF8            : translation="SJISTOUTF8";          break;
      case UTF8_TO_ISO88591        : translation="UTF8TOISO88591";      break;
      case ISO88591_TO_UTF8        : translation="ISO88591TOUTF8";      break;
      case KANJI_MP_TO_ISO88591    : translation="KANJITOISO88591";     break;
      case KSC5601_MP_TO_ISO88591  : translation="KSC5601TOISO88591";   break;
      case UNKNOWN_TRANSLATION     : translation="UNKNOWN_TRANSLATION"; break;                                                  
    }
    result += translation;
    result += ")";
  }                                               
}                                                 
                                                  
HbaseColumnLookup::~HbaseColumnLookup()
{
}

ItemExpr * HbaseColumnLookup::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) HbaseColumnLookup(child(0), hbaseCol_, naType_);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // HbaseColumnLookup::copyTopNode()
                                                  
HbaseColumnsDisplay::~HbaseColumnsDisplay()
{
}

ItemExpr * HbaseColumnsDisplay::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    result = new (outHeap) HbaseColumnsDisplay(child(0), csl_, displayWidth_);
  else
    result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // HbaseColumnsDisplay::copyTopNode()

HbaseColumnCreate::~HbaseColumnCreate()
{
}

ItemExpr * HbaseColumnCreate::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  HbaseColumnCreate *result;

  if (derivedNode == NULL)
    result = new (outHeap) HbaseColumnCreate(hccol_);
  else
    result = (HbaseColumnCreate*)derivedNode;

  result->colNameMaxLen_ = colNameMaxLen_;
  result->colValMaxLen_ = colValMaxLen_;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // HbaseColumnLookup::copyTopNode()
                                                  
SequenceValue::~SequenceValue()
{
}

ItemExpr * SequenceValue::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  SequenceValue *result;

  if (derivedNode == NULL)
    result = new (outHeap) SequenceValue(seqCorrName_, currVal_, nextVal_);
  else
    result = (SequenceValue*)derivedNode;

  result->naTable_ = naTable_;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // SequenceValue::copyTopNode()
        
// HbaseTimestamp                                          
HbaseTimestamp::~HbaseTimestamp()
{
}

ItemExpr * HbaseTimestamp::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  HbaseTimestamp *result;

  if (derivedNode == NULL)
    result = new (outHeap) HbaseTimestamp(col_);
  else
    result = (HbaseTimestamp*)derivedNode;

  result->colIndex_ = colIndex_;
  result->colName_ = colName_;
  result->tsVals_ = tsVals_;

  return BuiltinFunction::copyTopNode(result, outHeap);
} // HbaseTimestamp::copyTopNode()
  
// HbaseTimestampRef                                          
HbaseTimestampRef::~HbaseTimestampRef()
{
}

ItemExpr * HbaseTimestampRef::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  HbaseTimestampRef *result;

  if (derivedNode == NULL)
    result = new (outHeap) HbaseTimestampRef(col_);
  else
    result = (HbaseTimestampRef*)derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
} // HbaseTimestamp::copyTopNode()
  
NABoolean HbaseTimestamp::isCovered
(const ValueIdSet& newExternalInputs,
 const GroupAttributes& coveringGA,
 ValueIdSet& referencedInputs,
 ValueIdSet& coveredSubExpr,
 ValueIdSet& unCoveredExpr) const
{
  //return TRUE;
  return FALSE;
}

// HbaseVersion                                          
HbaseVersion::~HbaseVersion()
{
}

ItemExpr * HbaseVersion::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  HbaseVersion *result;

  if (derivedNode == NULL)
    result = new (outHeap) HbaseVersion(col_);
  else
    result = (HbaseVersion*)derivedNode;

  result->colIndex_ = colIndex_;
  result->colName_ = colName_;
  result->tsVals_ = tsVals_;

  return BuiltinFunction::copyTopNode(result, outHeap);
} // HbaseVersion::copyTopNode()
  
// HbaseVersionRef                                          
HbaseVersionRef::~HbaseVersionRef()
{
}

ItemExpr * HbaseVersionRef::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  HbaseVersionRef *result;

  if (derivedNode == NULL)
    result = new (outHeap) HbaseVersionRef(col_);
  else
    result = (HbaseVersionRef*)derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
} // HbaseVersion::copyTopNode()
  
NABoolean HbaseVersion::isCovered
(const ValueIdSet& newExternalInputs,
 const GroupAttributes& coveringGA,
 ValueIdSet& referencedInputs,
 ValueIdSet& coveredSubExpr,
 ValueIdSet& unCoveredExpr) const
{
  //return TRUE;
  return FALSE;
}

// RowNumFunc                        
RowNumFunc::~RowNumFunc()
{
}

ItemExpr * RowNumFunc::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  RowNumFunc *result;

  if (derivedNode == NULL)
    result = new (outHeap) RowNumFunc();
  else
    result = (RowNumFunc*)derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);

} // RowNumFunc::copyTopNode()
                                                  
NABoolean RowNumFunc::isCovered
                   (const ValueIdSet& newExternalInputs,
		    const GroupAttributes& coveringGA,
		    ValueIdSet& referencedInputs,
		    ValueIdSet& coveredSubExpr,
		    ValueIdSet& unCoveredExpr) const
{
  // The ROWNUM function is not pushed down.
  return FALSE;
} // RowNumFunc::isCovered
                                                  
// -----------------------------------------------------------------------
// Member functions for ItmSequenceFunction
//------------------------------------------------------------------------
// -----------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------
ItmSequenceFunction::~ItmSequenceFunction() {}

NABoolean ItmSequenceFunction::isASequenceFunction() const   // virtual method
  { return TRUE; }

NABoolean ItmSequenceFunction::isCovered(const ValueIdSet& newExternalInputs,
                               const GroupAttributes& newRelExprAnchorGA,
                               ValueIdSet& referencedInputs,
                               ValueIdSet& coveredSubExpr,
                               ValueIdSet& unCoveredExpr) const
{
  // ---------------------------------------------------------------------
  // If the operand is covered, then return its ValueId in coveredSubExpr.
  // ---------------------------------------------------------------------
  ValueIdSet localSubExpr;
  for(Lng32 i = 0; i < (Lng32)getArity(); i++)
  {

     if (child(i)->getOperatorType() == ITM_ITEM_LIST)
      {
        // child is a multi-valued expression, test coverage on individuals
        // 
        ExprValueId treePtr = child(i);

        ItemExprTreeAsList values(&treePtr,
                                  ITM_ITEM_LIST,
                                  RIGHT_LINEAR_TREE);

        CollIndex nc = values.entries();
        for (CollIndex m = 0; m < nc; m++)
          {
            if(newRelExprAnchorGA.covers(values[m]->getValueId(),
                                         newExternalInputs,
                                         referencedInputs,
                                         &localSubExpr))
              {
                coveredSubExpr += values[m]->getValueId();
              }
            coveredSubExpr += localSubExpr;
          }
      }
    else 
      {

	if(newRelExprAnchorGA.covers(child(i)->getValueId(),
				     newExternalInputs,
				     referencedInputs,
				     &localSubExpr))
	{
	  coveredSubExpr += child(i)->getValueId();
	}
	coveredSubExpr += localSubExpr;
    }

  }
  // ---------------------------------------------------------------------
  // The ItmSequenceFunction function is coerced to fail the coverage test even
  // when its operands isCovered(). This is because only the RelSequence node
  // can evaluate the function. The function is associated with a RelSequence
  // node at the very beginning and we don't allow it to be pushed down
  // even if the function's operands are covered at the node's child.
  // ---------------------------------------------------------------------
  return FALSE;
}

void ItmSequenceFunction::getLeafValuesForCoverTest(ValueIdSet& leafValues, 
                                                    const GroupAttributes& coveringGA,
                                                    const ValueIdSet & newExternalInputs) const
{
  // ItmSequenceFunction is considered a leaf operator for cover test.
  leafValues += getValueId();
}


const NAString ItmSequenceFunction::getText() const
{
  switch (getOperatorType())
    {
    case ITM_DIFF1:
      return "diff1";
    case ITM_DIFF2:
      return "diff2";
    case ITM_LAST_NOT_NULL:
      return "lastnotnull";
    case ITM_MOVING_AVG:
      return "movingavg";
    case ITM_MOVING_COUNT:
      return "movingcount";
    case ITM_MOVING_MAX:
      return "movingmax";
    case ITM_MOVING_MIN:
      return "movingmin";
    case ITM_MOVING_RANK:
      return "movingrank";
    case ITM_MOVING_SDEV:
      return "movingsdev";
    case ITM_MOVING_SUM:
      return "movingsum";
    case ITM_MOVING_VARIANCE:
      return "movingvariance";
    case ITM_RUNNING_AVG:
      return "runningavg";
    case ITM_RUNNING_CHANGE:
      return "rows since changed";
    case ITM_RUNNING_COUNT:
      return "runningcount";
    case ITM_RUNNING_MAX:
      return "runningmax";
    case ITM_RUNNING_MIN:
      return "runningmin";
    case ITM_RUNNING_RANK:
      return "runningrank";
    case ITM_RUNNING_SDEV:
      return "runningsdev";
    case ITM_RUNNING_SUM:
      return "runningsum";
    case ITM_RUNNING_VARIANCE:
      return "runningvariance";
    case ITM_OFFSET:
      if (getArity() == 1 )// internally created offsets
      {
        char str[30]; 
        str_sprintf(str, "offset[%d]",((ItmSeqOffset *)this)->getOffsetConstantValue());
        return str;
      }
      else
      {
        return "offset";
      }
    case ITM_THIS:
      return "this";
    case ITM_NOT_THIS:
      return "not this";

    case ITM_OLAP_COUNT:
      return "olap count";
    case ITM_OLAP_MAX:
      return "olap max";
    case ITM_OLAP_MIN:
      return "olap min";
    case ITM_OLAP_RANK:
      return "olap rank";
    case ITM_OLAP_DRANK:
      return "olap dense rank";
    case ITM_OLAP_SDEV:
      return "olap sdev";
    case ITM_OLAP_SUM:
      return "olap sum";
    case ITM_OLAP_VARIANCE:
      return "olap variance";

    default:
      return "unknown sequence function";
    } // switch
}

ItemExpr * ItmSequenceFunction::copyTopNode(ItemExpr *derivedNode,
                                            CollHeap* outHeap)
{
  ItmSequenceFunction *result = NULL;

  if (derivedNode == NULL)
   ABORT(
   "copyTopNode() can only be called for a derived class of ItmSequenceFunction"
         );
  else
    result = (ItmSequenceFunction *)derivedNode;

  // Copy OLAP Window Function information.
  //
  result->isOLAP_ = isOLAP_;
  result->olapPartitionBy_ = olapPartitionBy_;
  result->olapOrderBy_ = olapOrderBy_;
  result->isTDFunction_ = isTDFunction_;

  return BuiltinFunction::copyTopNode(result, outHeap);
} // ItmSequenceFunction::copyTopNode()

ItemExpr * ItmSequenceFunction::transformTDFunction(BindWA * bindWA)
{
  if (getOperatorType() != ITM_RUNNING_RANK) // we are only doing td rank in this ohase
    return this;

  if (!isTDFunction())
    return this;

  if (!olapPartitionBy_)
    return this;

  ItmSequenceFunction *partClause = NULL;    

  partClause = new (bindWA->getCurrentScope()->collHeap())
                    ItmSeqRunningFunction(ITM_RUNNING_CHANGE,
                                          olapPartitionBy_->copyTree(bindWA->getCurrentScope()->collHeap()) );

  partClause->setIsTDFunction(TRUE);
  partClause->setOlapOrderBy(olapOrderBy_->copyTree(bindWA->getCurrentScope()->collHeap()));
  partClause->setOlapPartitionBy(olapPartitionBy_->copyTree(bindWA->getCurrentScope()->collHeap()));

  ItmSequenceFunction *seqFunc = new (bindWA->getCurrentScope()->collHeap())
                                      ItmSeqMovingFunction(ITM_MOVING_RANK, child(0), partClause);

  seqFunc->setIsTDFunction(TRUE);
  seqFunc->setOlapOrderBy(olapOrderBy_->copyTree(bindWA->getCurrentScope()->collHeap()));
  seqFunc->setOlapPartitionBy(olapPartitionBy_->copyTree(bindWA->getCurrentScope()->collHeap()));
                                    
  return seqFunc;
}

// -----------------------------------------------------------------------
// member functions for ItmSeqRunningFunction
// -----------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------
ItmSeqRunningFunction::~ItmSeqRunningFunction() {}

NABoolean ItmSeqOlapFunction::isOlapFunction() const   // virtual method
  { return TRUE; }


ItmSeqOlapFunction::~ItmSeqOlapFunction() {}


ItemExpr * ItmSeqRunningFunction::copyTopNode(ItemExpr *derivedNode,
                                              CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    {
     result = new (outHeap) ItmSeqRunningFunction(getOperatorType(),
                                                  child(0));
     ((ItmSeqRunningFunction *)result)->setIsOLAP(isOLAP());
    }
  else
    result = derivedNode;

  return ItmSequenceFunction::copyTopNode(result, outHeap);
} // ItmSeqRunningFunction::copyTopNode()


ItemExpr * ItmSeqOlapFunction::copyTopNode(ItemExpr *derivedNode,
                                              CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    {
     result = new (outHeap) ItmSeqOlapFunction(getOperatorType(),
                                                  child(0));
    }
  else
    result = derivedNode;

  ((ItmSeqOlapFunction *)result)->frameStart_ = frameStart_;
  ((ItmSeqOlapFunction *)result)->frameEnd_ = frameEnd_;

  return ItmSequenceFunction::copyTopNode(result, outHeap);
} // ItmSeqOlapFunction::copyTopNode()


NABoolean
ItmSeqOlapFunction::inverseOLAPOrder(CollHeap *heap)
{
  //if (frameStart_ != -INT_MAX) {
  if (getOlapOrderBy())
    {
      ItemExprList orderList(getOlapOrderBy(),0);

      ItemExpr *newOrder = NULL;
      for (CollIndex i = 0; i < orderList.entries(); i++) {

        ItemExpr *itm = orderList[i];
        if (itm->getOperatorType() == ITM_INVERSE) {
          itm = itm->child(0);
        } else {
          itm = new (heap) InverseOrder(itm);
        }
        if(newOrder) {
          newOrder = new(heap) ItemList(newOrder, itm);
        } else {
          newOrder = itm;
        }
      }
      
      setOlapOrderBy(newOrder);
    }

  Lng32 olapRowsTemp = frameEnd_;
  frameEnd_ = -frameStart_;
  frameStart_ = -olapRowsTemp;
  return TRUE;
  //}
  //return FALSE;
}

NABoolean ItmSeqOlapFunction::hasEquivalentProperties(ItemExpr * other)
{
  if (other == NULL)
    return FALSE;
  if (getOperatorType() != other->getOperatorType() || 
        getArity() != other->getArity())
    return FALSE;

  ItmSeqOlapFunction * otherOSeq = (ItmSeqOlapFunction *) other;

  return 
      (this->frameStart_ == otherOSeq->frameStart_ &&
       this->frameEnd_ == otherOSeq->frameEnd_) ;
}

NABoolean ItmSequenceFunction::isEquivalentForBinding(const ItemExpr * other)
{
  
  
  if ( getOperatorType() != other->getOperatorType() || getArity() != other->getArity() )
  {
    return FALSE;
  }
  
  for (Lng32 i = 0; (i < getArity()); i++)
  {
    if (child(i)->isASequenceFunction())
    {
      ItmSequenceFunction * seqFunc = (ItmSequenceFunction * ) child(i).getValueId().getItemExpr();
      if (!seqFunc->isEquivalentForBinding(other->child(i)))
      {
	return FALSE;
      }
    }
    else 
    {
      if (!child(i)->hasBaseEquivalenceForCodeGeneration(other->child(i)))
    {
      return FALSE;
    }
    }
  }
  return TRUE;
 }
// -----------------------------------------------------------------------
// member functions for Offset
// -----------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------
ItmSeqOffset::~ItmSeqOffset() {}

// -----------------------------------------------------------------------
Int32 ItmSeqOffset::getArity() const
{
  if (child(1))
  {
    if (child(2))
      return 3;
    else
      return 2;
  }
  else
    return 1;
}

ItemExpr * ItmSeqOffset::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
   {
    switch (getArity())
    {
      case 2:
         result = new (outHeap) ItmSeqOffset(child(0), child(1), NULL, 
                                             nullRowIsZero());
         break;

      case 3:
         result = new (outHeap) ItmSeqOffset(child(0), child(1), child(2),
                                             nullRowIsZero());
         break;

      default:
         result = new (outHeap) ItmSeqOffset( child(0),
                                             nullRowIsZero(),
                                              getOffsetConstantValue(),
                                              isLeading(),
                                              winSize());
         break;
    }
    ((ItmSeqOffset *)result)->setIsOLAP(isOLAP());
   }
  else
   {
    result = derivedNode;
   }

  return ItmSequenceFunction::copyTopNode(result, outHeap);

} // ItmSeqOffset::copyTopNode()

NABoolean ItmSeqOffset::hasEquivalentProperties(ItemExpr * other)
{
  if (other == NULL)
    return FALSE;
  if (getOperatorType() != other->getOperatorType() || 
        getArity() != other->getArity())
    return FALSE;

  ItmSeqOffset * otherOffset = (ItmSeqOffset *) other;

  return 
    (this->offsetConstantValue_ == otherOffset->offsetConstantValue_) &&
    (this->nullRowIsZero_ == otherOffset->nullRowIsZero_) &&
    (this->leading_ == otherOffset->leading_) &&
    (this->winSize_ == otherOffset->winSize_);
}

// -----------------------------------------------------------------------
// member functions for DIFF1
// -----------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------
ItmSeqDiff1::~ItmSeqDiff1() {}

// -----------------------------------------------------------------------

ItemExpr * ItmSeqDiff1::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
   {
    if (getArity() == 1)
    {
     result = new (outHeap) ItmSeqDiff1(child(0));
    }
    else
    {
     result = new (outHeap) ItmSeqDiff1(child(0), child(1));
    }
   }
  else
   {
    result = derivedNode;
   }

  return ItmSequenceFunction::copyTopNode(result, outHeap);

} // ItmSeqDiff1::copyTopNode()

// -----------------------------------------------------------------------
// member functions for DIFF2
// -----------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------
ItmSeqDiff2::~ItmSeqDiff2() {}

// -----------------------------------------------------------------------

ItemExpr * ItmSeqDiff2::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
   {
    if (getArity() == 1)
    {
     result = new (outHeap) ItmSeqDiff2(child(0));
    }
    else
    {
     result = new (outHeap) ItmSeqDiff2(child(0), child(1));
    }
   }
  else
   {
    result = derivedNode;
   }

  return ItmSequenceFunction::copyTopNode(result, outHeap);

} // ItmSeqDiff2::copyTopNode()

// -----------------------------------------------------------------------
// member functions for ItmSeqRowsSince
// -----------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------
ItmSeqRowsSince :: ~ItmSeqRowsSince() {};

ItemExpr  *ItmSeqRowsSince :: copyTopNode(ItemExpr *derivedNode,
                                          CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    {
     if (getArity() == 1)
     {
      result = new (outHeap) ItmSeqRowsSince(child(0), NULL, includeCurrentRow());
     }
     else
     {
      result = new (outHeap) ItmSeqRowsSince(child(0), child(1), includeCurrentRow());
     }
    }
  else
  {
   result = derivedNode;
  }

  return ItmSequenceFunction::copyTopNode(result, outHeap);
} // ItmSeqRowsSince::copyTopNode()

const NAString ItmSeqRowsSince :: getText() const
{
  if (includeCurrentRow())
   return "rows since inclusive";
  else
   return "rows since";
}  // ItmSeqRowsSince::getText()

// -----------------------------------------------------------------------
// member functions for ItmSeqMovingFunction
// -----------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------
ItmSeqMovingFunction::~ItmSeqMovingFunction() {}

ItemExpr * ItmSeqMovingFunction::copyTopNode(ItemExpr *derivedNode,
                                             CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL) {
    result = new (outHeap) ItmSeqMovingFunction(getOperatorType(),
                                                child(0), child(1), child(2));
  ((ItmSeqMovingFunction *)result)->setIsOLAP(isOLAP());
  }
  else
    result = derivedNode;

  if (this->getSkipMovingMinMaxTransformation() == TRUE)
  {
   ((ItmSeqMovingFunction *)result)->setSkipMovingMinMaxTransformation();
  }

  return ItmSequenceFunction::copyTopNode(result, outHeap);
} // ItmSeqMovingFunction::copyTopNode()

NABoolean ItmSeqMovingFunction::hasEquivalentProperties(ItemExpr * other)
{
  if (other == NULL)
    return FALSE;
  if (getOperatorType() != other->getOperatorType() || 
        getArity() != other->getArity())
    return FALSE;

  ItmSeqMovingFunction * otherMSeq = (ItmSeqMovingFunction *) other;

  return 
      (this->skipMovingMinMaxTransformation_ == otherMSeq->skipMovingMinMaxTransformation_) ;
}
// -----------------------------------------------------------------------
// member functions for THIS function
// -----------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------
ItmSeqThisFunction::~ItmSeqThisFunction() {}

ItemExpr * ItmSeqThisFunction::copyTopNode(ItemExpr *derivedNode,
                                           CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
   {
     result = new (outHeap) ItmSeqThisFunction (child(0));
   }
  else
   {
    result = derivedNode;
   }

  return ItmSequenceFunction::copyTopNode(result, outHeap);

} // ItmSeqThisFunction::copyTopNode()

// -----------------------------------------------------------------------
// member functions for NotTHIS function
// -----------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------

ItmSeqNotTHISFunction::~ItmSeqNotTHISFunction(){}

ItemExpr *ItmSeqNotTHISFunction::copyTopNode(ItemExpr *derivedNode,
                                             CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
   {
     result = new (outHeap) ItmSeqNotTHISFunction (child(0));
   }
  else
   {
    result = derivedNode;
   }

  return ItmSequenceFunction::copyTopNode(result, outHeap);

} // ItmSeqNotTHISFunction::copyTopNode()

// -----------------------------------------------------------------------
// member functions for ItmScalarMinMax
// -----------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------
ItmScalarMinMax::~ItmScalarMinMax() {};

ItemExpr *ItmScalarMinMax::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
   result = new (outHeap)ItmScalarMinMax(getOperatorType(), child(0), child(1));
  else
   result = derivedNode;

  return BuiltinFunction::copyTopNode(result, outHeap);
} // ItmScalarMinMax::copyTopNode

NABoolean ItemExpr::containsOneRowAggregate()
{

  if ( getOperatorType() == ITM_ONE_ROW )
     return TRUE;

  for (Int32 i=0; i < getArity(); i++)
  {
    if (child(i)->castToItemExpr()->containsOneRowAggregate())
      return TRUE;
  }
  return FALSE;
} // ItemExpr::containsOneRowAggregate()

NABoolean ItemExpr::containsOpType(OperatorTypeEnum opType) const
{

  if ( getOperator().match(opType) )
     return TRUE;

  for (Int32 i=0; i < getArity(); i++)
  {
    if (child(i)->castToItemExpr()->containsOpType(opType))
      return TRUE;
  }
  return FALSE;
} // ItemExpr::containsOpType()

// If I am untransformed, I tell my parent, which in turn will mark itself
// as untransformed, and tell its parent, ..., all the way up to the
// original place where this method was called.

NABoolean ItemExpr::markPathToUnTransformedNode()
{
  NABoolean retval = FALSE ;

  if ( !nodeIsTransformed() )
    retval = TRUE ;

  for (Int32 i=0; i < getArity(); i++)
  {
    if ( child(i)->castToItemExpr()->markPathToUnTransformedNode() )
      {
        markAsUnTransformed() ;
        retval = TRUE ;
        // NB: Since this function is marking nodes as untransformed, we
        // can't simply break after the first child which is found to
        // be untransformed.
      }
  }
  return retval;
} // ItemExpr::markPathToUnTransformedNode()


NABoolean ItemExpr::isEquivalentForCodeGeneration(const ItemExpr * other)
  {
  NABoolean rc = FALSE;// by default, return FALSE (suppress common subexpr elimination

  if (getArity() == 0)  // to limit needless recursion
    {
    if (hasBaseEquivalenceForCodeGeneration(other))
      {
      // we know other is non-null, has same operator type, same arity, and
      // that its children are equivalent

      OperatorTypeEnum myOp = getOperatorType();
      const ItemExpr & refOther = (const ItemExpr &) *other;

      // as it happens, with 0-arity operators, we know that operator==
      // should return false for all cases below (because of the way the
      // code in hasBaseEquivalenceForCodeGeneration() works; but I want
      // to see if virtual forms of operator== are selected)

      if (myOp == ITM_CONSTANT)
        {
        rc = (operator==(refOther));
        }
      else if (myOp == ITM_REFERENCE)
        {
        rc = (operator==(refOther));
        }
      else if (myOp == ITM_BASECOLUMN)
        {
        rc = (operator==(refOther));
        }
      else if (myOp == ITM_INDEXCOLUMN)
        {
        rc = (operator==(refOther));
        }
      }
    }
  return rc;
  }


NABoolean ItemExpr::hasBaseEquivalenceForCodeGeneration(const ItemExpr * other)
  {
  NABoolean rc = FALSE;    // assume not

  if (other)
    {
    const ItemExpr & refOther = (const ItemExpr &) *other;  // we know it exists

    if (operator==(refOther))  // $$$$ will this get virtual operator==????
      rc = TRUE;    // equal nodes are considered equivalent
    else
      {
      if (getOperatorType() == other->getOperatorType())
        {
        Lng32 arity = getArity();

        if (arity == other->getArity())
          {
          // make sure children are equivalent
          rc = TRUE;       // be optimistic now; assume equivalent
          for (Lng32 i = 0; (i < arity) && (rc); i++)
            {
            if (!(child(i)->isEquivalentForCodeGeneration(other->child(i))))
              rc = FALSE;   // oops -- found non-equivalent children
            }
          }  // end if arity's are equal
        }  // end if oper types are equal
      }  // end else nodes aren't equal
    }  // end if other is non-null

  return rc;
  }

  ItemExpr* ItemExpr::getParticularItemExprFromTree(NAList<Lng32>& childNum, 
                                          NAList<OperatorTypeEnum>& opType) const
  {
    ItemExpr * root = (ItemExpr *) this;
    for (CollIndex i = 0; i < childNum.entries(); i++)
    {
      if ((root->getArity() > childNum[i]) && 
          (root->child(childNum[i])) && 
          (root->child(childNum[i])->getOperatorType() == opType[i])) 
      {
          root = root->child(childNum[i]);
      }
      else
      {
        DCMPASSERT(FALSE);
        return NULL;
      }
    }
    return root;
  }

ItemExpr* ItemExpr::removeRangeSpecItems(NormWA* normWA)
{
  for (Lng32 i = 0; i < getArity(); i++)
  {
    child(i) = child(i)->removeRangeSpecItems(normWA);
  }
  return this;
};

// Raj P - 1/01
// Support for OUT parameters in Stored Procedures for Java
// Set Parameter Mode, Ordinal Position and Variable Index for a
// host variable or dynamic parameter
void
HostVar::setPMOrdPosAndIndex( ComColumnDirection paramMode,
			      Int32 ordinalPosition,
			      Int32 index )
{
    paramMode_ = paramMode;
    ordinalPosition_ = ordinalPosition;
    hvIndex_ = index;
}

NABoolean HostVar::isSystemGeneratedOutputHV() const
{  
  return (isSystemGenerated() &&
           getName() == "_sys_ignored_CC_convErrorFlag"); 
}

void
DynamicParam::setPMOrdPosAndIndex( ComColumnDirection paramMode,
				   Int32 ordinalPosition,
				   Int32 index )
{
    paramMode_ = paramMode;
    ordinalPosition_ = ordinalPosition;
    dpIndex_ = index;
}

ComColumnDirection ItemExpr::getParamMode () const
{
  CMPASSERT (0);
  return COM_UNKNOWN_DIRECTION;
};

Int32 ItemExpr::getOrdinalPosition () const
{
  CMPASSERT (0);
  return -1;
}

Int32 ItemExpr::getHVorDPIndex () const
{
  CMPASSERT (0);
  return -1;
}

NABoolean ItemExpr::isARangePredicate() const
{
  OperatorTypeEnum oper = getOperatorType();

  if ((oper == ITM_GREATER)    ||
      (oper == ITM_GREATER_EQ) ||
      (oper == ITM_LESS)       ||
      (oper == ITM_LESS_EQ))
  {
    return TRUE;
  }

  return FALSE;
}


QR::ExprElement Function::getQRExprElem() const
{
  return QR::QRFunctionElem;
}

// Flipping the tree in 1 pass top->bottom
//
//ITEM_LIST  (OLD TREE)
//    /   \
//   4    ITEM_LIST
//            /   \
//           3   ITEM_LIST
//                  /    \
//                 2      1
//
//ITEM_LIST   (NEW TREE)
//   /    \	
//   1     ITEM_LIST       
//          /     \               
//         2     ITEM_LIST
//                 /    \
//                 3     4

ItemExpr * ItemExpr::reverseTree() 
{
	ItemExpr *grammarTree = this;
	ItemExpr *topNode = NULL;


	// Special Case: 1, 2 & 3 columns. Base of tree
	// only 1 column.
	if (grammarTree->getOperatorType()!=ITM_ITEM_LIST) 
		return grammarTree;

	if (grammarTree->child(1)->getOperatorType()==ITM_ITEM_LIST ) {
		
		// more than 2 columns	
		topNode = grammarTree->child(1)->child(1);
		grammarTree->child(1)->child(1) = grammarTree->child(0);

		if (topNode->getOperatorType() != ITM_ITEM_LIST) { 
			// extactly 3 columns
			grammarTree->child(0) = topNode;		
			return grammarTree;
		}
		else {
			// more than 3 columns
			grammarTree->child(0) = topNode->child(0);
		}
	}
	else {
		// exactly 2 columns
		ItemExpr *temp = grammarTree->child(1);
		grammarTree->child(1) = grammarTree->child(0);
		grammarTree->child(0) = temp; 
		return grammarTree;
	}

	while (topNode) {

		if (topNode->child(1)->getOperatorType()==ITM_ITEM_LIST ) { 
		  // not bottom of tree
			ItemExpr *temp = topNode->child(1);
			topNode->child(1) = grammarTree;
			grammarTree = topNode;
			topNode = temp;
			grammarTree->child(0) = topNode->child(0);
		}
		else {  // bottom of the tree
			topNode->child(0) = topNode->child(1);
			topNode->child(1) = grammarTree;
			grammarTree = topNode;
			break;
		}
	}

	return grammarTree;

} // end of function

QR::ExprElement ItemExpr::getQRExprElem() const
{
  return QR::QRNoElem;
}

QR::ExprElement ConstantParameter::getQRExprElem() const
{
  return QR::QRScalarValueElem;
}

// Constructor for the wrapper class RangeSpecRef:
RangeSpecRef::RangeSpecRef(OperatorTypeEnum otype,
			   OptNormRangeSpec* range,
			   ItemExpr *colValueId,
			   ItemExpr *reConsIExpr)
  : ItemExpr(ITM_RANGE_SPEC_FUNC,colValueId,reConsIExpr),
    range_(range)
{}

/* Get the already generated ValueId */
DisjunctArray * RangeSpecRef::mdamTreeWalk()
{
  return new (CmpCommon::statementHeap()) DisjunctArray(new (CmpCommon::statementHeap()) ValueIdSet(getValueId()));
}

/* Need to get the access rightchild to print out the value , rightchild is reconstructed though */
/* This will affect explain "xx" output, this needs to be completed while we get a pointer to the right child
Item expression, then it will print something like <column> "Range in" Item expression corresponding to 
<subranges> */ 
const NAString RangeSpecRef::getText()  const
{   
  return "Range in";
}

short RangeSpecRef::mdamPredGen(Generator * generator,
                                MdamPred ** head,
                                MdamPred ** tail,
                                MdamCodeGenHelper & mdamHelper,
                                ItemExpr * parent)
{
  // return dummy;
  return 0;
}

Int32 RangeSpecRef::getArity() const 
{ 
  return 2; 
}

// delete this and the range_ object associated with this, if present */
RangeSpecRef::~RangeSpecRef()
{
  if(range_)
    delete range_;
}

ItemExpr * RangeSpecRef::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  RangeSpecRef *result;
  if (derivedNode == NULL)
    // Need a Deep copy of range_ object. - Change needs to be done after
    // Copy ctor is available.
    // Curently range_->clone(outHeap) gives Null value, while copying the tree
    // So again back to shallow copy
    result = new (outHeap) RangeSpecRef(getOperatorType(),range_, NULL,NULL);
  else
    result = (RangeSpecRef *) derivedNode;

  // copy the data members
  return ItemExpr::copyTopNode(result, outHeap);
}

short RangeSpecRef::codeGen(Generator* generator)
{
  child(1)->codeGen(generator);
  return 0;
}

void RangeSpecRef::unparse(NAString &result,
                           PhaseEnum phase,
                           UnparseFormatEnum form,
                           TableDesc * tabId) const
{
  // Don't include rangespec op if query format -- it won't parse.
  if (form == QUERY_FORMAT || form == COMPUTED_COLUMN_FORMAT)
    child(1)->unparse(result, phase, form, tabId);
  else
    ItemExpr::unparse(result, phase, form, tabId);
}

ItemExpr* RangeSpecRef::removeRangeSpecItems(NormWA* normWA)
{
  return getRangeObject()->getRangeItemExpr(normWA);
};

void RangeSpecRef::getValueIdSetForReconsItemExpr(ValueIdSet &outvs)
{
  ValueIdSet items;
  ItemExpr* ie;
  child(1)->convertToValueIdSet(items, NULL, ITM_ITEM_LIST);
  for (ValueId vid=items.init(); items.next(vid); items.advance(vid))
  {
    ie = vid.getItemExpr();
    if (!ie->isLike())
      ie->convertToValueIdSet(outvs, NULL, ITM_AND);
    else
      outvs.insert(vid);  // Add LIKE expansion without decomposing
  }
}

ItemExpr* revertBackToOldTree(CollHeap *heap, ItemExpr* newTree) 
{
  if(newTree->getOperatorType() != ITM_AND && 
     newTree->getOperatorType() != ITM_OR)
  {
    if (newTree->getOperatorType() == ITM_RANGE_SPEC_FUNC ) 
    {
      return(newTree->child(1));
    }
    else
    {
      return (newTree);	
    }
  }
  else
  {
    ItemExpr* newLeftNode = revertBackToOldTree(heap,newTree->child(0));
    ItemExpr* newRightNode = revertBackToOldTree(heap,newTree->child(1));
    assert(newLeftNode != NULL && newRightNode != NULL);
    newTree->setChild(0, newLeftNode);
    newTree->setChild(1, newRightNode);
    return newTree;
  }
}

// This method reverts back to Old Tree as valueIdSet from transformed Tree as valueIdSet.
void revertBackToOldTreeUsingValueIdSet(  ValueIdSet& inputSet /* IN */, ValueIdSet& outputSet /* OUT */) 
{
	ValueIdSet orSet,outorSet;
	ItemExpr * inputItemExprTree = NULL;
    for (ValueId predId = inputSet.init();
       inputSet.next(predId);
	   inputSet.advance(predId) ){
		if( predId.getItemExpr()->getOperatorType() == ITM_RANGE_SPEC_FUNC){
          outputSet += predId.getItemExpr()->child(1)->castToItemExpr()->getValueId();
		  if(inputItemExprTree != NULL)
		  {
            outputSet += inputItemExprTree->getValueId();
			inputItemExprTree = NULL;
			outorSet.clear();
		  }
		}
		else if( predId.getItemExpr()->getOperatorType() == ITM_OR){
        predId.getItemExpr()->convertToValueIdSet(orSet, NULL, ITM_OR, FALSE);
        for (ValueId predIdOr = orSet.init();
             orSet.next(predIdOr);
	         orSet.advance(predIdOr) ){
			 if(predIdOr.getItemExpr()->getOperatorType() == ITM_RANGE_SPEC_FUNC){
				 outorSet += predIdOr.getItemExpr()->child(1)->castToItemExpr()->getValueId();
			 }
			 else
			  outorSet += predIdOr;
			}
		  if(outorSet.entries())
		  inputItemExprTree = outorSet.rebuildExprTree(ITM_OR,FALSE,FALSE);
		}
		else
		{
         outputSet += predId;
		  if(inputItemExprTree != NULL)
		  {
            outputSet += inputItemExprTree->getValueId();
			inputItemExprTree = NULL;
			outorSet.clear();
		  }
		}
	}// for (1)
	if(inputItemExprTree != NULL)
	{
      outputSet += inputItemExprTree->getValueId();
	  inputItemExprTree = NULL;
	  outorSet.clear();
	}
}


NABoolean LOBoper::isCovered
(const ValueIdSet& newExternalInputs,
 const GroupAttributes& coveringGA,
 ValueIdSet& referencedInputs,
 ValueIdSet& coveredSubExpr,
 ValueIdSet& unCoveredExpr) const
{
  // If the argument is not a constant then it can be
  // evaluated anywhere in the tree. So check for its coverage
  ValueIdSet localSubExpr;
  for (Lng32 i = 0; i < (Lng32)getArity(); i++)
    {
      if ( coveringGA.covers(child(i)->getValueId(),
			     newExternalInputs,
			     referencedInputs,
			     &localSubExpr) )
	{
	  coveredSubExpr += child(i)->getValueId();
	}
    }

  // cannot be pushed down. Must be evaluated in master exe.
  return FALSE;
}

// Evalaute the exprssion at compile time. Assume all operands are constants.
// Return NULL if the computation fails and CmpCommon::diags() may be side-affected.
ConstValue* ItemExpr::evaluate(CollHeap* heap)
{
  ValueIdList exprs;
  exprs.insert(getValueId());

  const NAType& dataType = getValueId().getType();

  Lng32 decodedValueLen = dataType.getNominalSize() + dataType.getSQLnullHdrSize();

  char staticDecodeBuf[200];
  Lng32 staticDecodeBufLen = 200;

  char* decodeBuf = staticDecodeBuf;
  Lng32 decodeBufLen = staticDecodeBufLen;

  // For character types, multiplying by 6 to deal with conversions between
  // any two known character sets allowed. See CharInfo::maxBytesPerChar()
  // for a list of max bytes per char for each supported character set.  
  Lng32 factor = (DFS2REC::isAnyCharacter(dataType.getFSDatatype())) ? 6 : 1;

  if ( staticDecodeBufLen < decodedValueLen * factor) {
    decodeBufLen = decodedValueLen * factor;
    decodeBuf = new (STMTHEAP) char[decodeBufLen];
  }

  Lng32 resultLength = 0;
  Lng32 resultOffset = 0;

  // Produce the decoded key. Refer to 
  // ex_function_encode::decodeKeyValue() for the 
  // implementation of the decoding logic.
  ex_expr::exp_return_type rc = exprs.evalAtCompileTime
    (0, ExpTupleDesc::SQLARK_EXPLODED_FORMAT, decodeBuf, decodeBufLen,
     &resultLength, &resultOffset, CmpCommon::diags()
     );


  ConstValue* result = NULL;

  if ( rc == ex_expr::EXPR_OK ) {
    CMPASSERT(resultOffset == dataType.getPrefixSizeWithAlignment());
    // expect the decodeBuf to have this layout
    // | null ind. | varchar length ind. | alignment | result |
    // |<---getPrefixSizeWithAlignment-------------->|
    // |<----getPrefixSize-------------->|

    // The method getPrefixSizeWithAlignment(), the diagram above,
    // and this code block assumes that varchar length ind. is
    // 2 bytes if present. If it is 4 bytes we should fail the 
    // previous assert

    // Next we get rid of alignment bytes by prepending the prefix
    // (null ind. + varlen ind.) to the result. ConstValue constr.
    // will process prefix + result. The assert above ensures that 
    // there are no alignment fillers at the beginning of the 
    // buffer. Given the previous assumption about size
    // of varchar length indicator, alignment bytes will be used by
    // expression evaluator only if column is of nullable type.
    // For a description of how alignment is computed, please see
    // ExpTupleDesc::sqlarkExplodedOffsets() in exp/exp_tuple_desc.cpp

    if (dataType.getSQLnullHdrSize() > 0)
      memmove(&decodeBuf[resultOffset - dataType.getPrefixSize()], 
                        decodeBuf, dataType.getPrefixSize());
    result =
      new (heap) 
      ConstValue(&dataType,
                 (void *) &(decodeBuf[resultOffset - 
                                      dataType.getPrefixSize()]),
                 resultLength+dataType.getPrefixSize(),
                 NULL,
                 heap);
  }

  return result;
}

ItemExpr * ItmLagOlapFunction::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
    ItemExpr *result = NULL;

    if (derivedNode == NULL)
    {
        switch (getArity()) { 
           case 2:
               result = new (outHeap) ItmLagOlapFunction(child(0), child(1));
               break;
           case 3:
               result = new (outHeap) ItmLagOlapFunction(child(0), child(1), child(2));
               break;
           default:
               CMPASSERT(FALSE);
        }
    }
    else              
        result = derivedNode;                 

  return ItmSeqOlapFunction::copyTopNode(result, outHeap);
}

ItmLeadOlapFunction::~ItmLeadOlapFunction() {}

ItemExpr * 
ItmLeadOlapFunction::copyTopNode(ItemExpr *derivedNode, CollHeap* outHeap)
{
  ItemExpr *result;

  if (derivedNode == NULL)
    {
     switch (getArity()) { 
      case 2:
         result = new (outHeap) ItmLeadOlapFunction(child(0), child(1));
         break;
      
      case 1:
      default:
         result = new (outHeap) ItmLeadOlapFunction(child(0));
         break;
     }
    }
  else              
    result = derivedNode;                 

  ((ItmLeadOlapFunction*)result)->setOffset(getOffset());

  return ItmSeqOlapFunction::copyTopNode(result, outHeap);
}

NABoolean ItmLeadOlapFunction::hasEquivalentProperties(ItemExpr * other)
{
  if (other == NULL)
    return FALSE;

  if (getOperatorType() != other->getOperatorType() ||
        getArity() != other->getArity())
    return FALSE;

  //return getOffsetExpr()->hasEquivalentProperties(((ItmLeadOlapFunction*)other)->getOffsetExpr());
  return TRUE;
}

ItemExpr *ItmLeadOlapFunction::transformOlapFunction(CollHeap *heap)
{
   return this;
}

