/**********************************************************************
// @@@ 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)
{
  ItemExpr *result;

  if (derivedNode == NULL) {
    result = new (outHeap) DynamicParam(paramName_, indicatorName_, outHeap);
    ((DynamicParam *) result)->setRowsetSize(rowsetSize_);
    ((DynamicParam *) result)->setRowsetInfo(rowsetInfo_);
    ((DynamicParam *) result)->setParamHeading(heading_);
    ((DynamicParam *) result)->setParamTablename(tablename_);
    // we remember our original dynamic parameter because we
    // must use their valueid at dynamicparam::codegen time
    ((DynamicParam *) result)->setOriginal(this);
  }

  else
    result = derivedNode;

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

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;
}

