/**********************************************************************
// @@@ 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:         ItemCache.cpp
* Description:  All the ItemExpr methods introduced by query caching
* Created:      2/23/2001
* Language:     C++
*
*
******************************************************************************
*/
#include "AllItemExpr.h"
#include "CacheWA.h"
#include "CmpMain.h"
#include "NumericType.h"
#include "SchemaDB.h"
#include "ItemFuncUDF.h"

void computeAndAddSelParamIfPossible(
             CacheWA& cwa, BindWA& bindWA, ExprValueId& child,
             BaseColumn *base, ConstValue *val)
{
    ColStatsSharedPtr cStatsPtr = (base->getTableDesc()->tableColStats()).
                             getColStatsPtrForColumn(base->getValueId());

    if (cStatsPtr == NULL )
        return;

    HistogramSharedPtr hist = cStatsPtr->getHistogram();

    if ( hist == NULL )
       return;

    CostScalar sel;
    NABoolean canComputeSelectivity = hist -> computeSelectivityForEquality(
            val, cStatsPtr->getRowcount(), cStatsPtr->getTotalUec(),
            sel);

    if ( canComputeSelectivity == TRUE ) {
      const NAType * newType = base->getNAColumn()->getType();

      // for char datatypes, assign the caseinsensitive attribute from
      // the const node.
      if (newType->getTypeQualifier() == NA_CHARACTER_TYPE)
	{
	  newType = 
	    base->getNAColumn()->getType()->newCopy(cwa.wHeap());
	  ((CharType*)newType)->setCaseinsensitive(((CharType*)val->getType())->isCaseinsensitive());
	}
      
      cwa.replaceWithNewOrOldSelParam(val, newType, Selectivity(sel), 
                                      child, bindWA);

    }
}

ConstValue * SelParameter::castToConstValue(NABoolean & negate_it)
{
  negate_it = FALSE;
  return getConstVal();
}

// append an ascii-version of aggregate into cachewa.qryText_
void Aggregate::generateCacheKey(CacheWA& cwa) const
{
  ItemExpr::generateCacheKey(cwa); 
  cwa += " all:"; 
  cwa += isDistinct_ ? "a0" : "a1";
}

// is any literal in this expr safely coercible to its target type?
NABoolean Assign::isSafelyCoercible(CacheWA &cwa) const
{
  if (cwa.getPhase() >= CmpMain::BIND) {
    // we have to disallow caching of the following types of updates:
    //   update t set col = overlylongliteral
    ItemExpr *src = getSource().getItemExpr();
    if (src->getOperatorType() == ITM_CONSTANT) {
      // source is a literal; make sure this update is cacheable only if
      // literal can be safely coerced into its target type.
      return ((ConstValue*)src)->canBeSafelyCoercedTo(getTarget().getType());
    }      
    else { // source is not a literal
      // we need to descend into this expr to verify that no 
      // errors can occur during backpatching. For example, 
      //   update t set i = i + 123456789012345678901234567890
      // should not be cacheable if i is a smallint.
      // reject "update t set c=(subquery)" as noncacheable
      // as part of a fix to CR 10-020108-8401.
      return src->isSafelyCoercible(cwa) && src->isCacheableExpr(cwa);
    }
  }
  return FALSE;
}

// change literals of a cacheable query into ConstantParameters 
ItemExpr* Assign::normalizeForCache(CacheWA& cwa, BindWA& bindWA)
{
  if (nodeIsNormalizedForCache()) { 
    return this; 
  }
  if (cwa.getPhase() == CmpMain::PARSE) {
    child(1) = child(1)->normalizeForCache(cwa, bindWA);
  }
  else if (cwa.getPhase() >= CmpMain::BIND) {
    ItemExpr *leftC=child(0), *rightC=child(1);
    OperatorTypeEnum leftO = leftC->getOperatorType();
    OperatorTypeEnum rightO = rightC->getOperatorType();
    ConstantParameter *cParam;
    if (leftO == ITM_BASECOLUMN && rightO == ITM_CONSTANT
        // normalizeForCache only constants that can be safely backpatched.
        // part of fix to CR 10-010726-4109.
        && isSafelyCoercible(cwa)  
        // normalizeForCache only constants that are contained in the original
        // SQL query so that each parameter can be backpatched by the
        // corresponding constant from the query. This is to fix regression 
        // failure MP core/test055 where a SystemLiteral was inserted when the 
        // Keytag for a MP table column is not zero. see LeafInsert::bindNode().
        // The offending query in MP core/test055 is
        //   update t055t9v set b = b + 1 where current of c10;
        && NOT ((ConstValue*)rightC)->isSystemProvided() ) {

      ConstValue *val = (ConstValue*)rightC;
      if (!val->isNull()) {
        cParam = new (cwa.wHeap()) ConstantParameter
          ((ConstValue*)rightC, cwa.wHeap(),
          ((BaseColumn*)leftC)->getNAColumn()->getType());
        cwa.addConstParam(cParam, bindWA);
        child(1) = cParam;
      }
         // else val is null; keep null as is.
         // this is part of a fix to genesis case: 10-010618-3484.
    }
    else {
      child(1) = child(1)->normalizeForCache(cwa, bindWA);
    }
  }
  markAsNormalizedForCache();
  return this;
}

// is val a constant that can be safely coerced to BaseColumn's type?
NABoolean BaseColumn::canSafelyCoerce(ItemExpr& val) const
{
  NAColumn *baseCol = getNAColumn();
  OperatorTypeEnum valTyp = val.getOperatorType();
  return
    (baseCol != NULL &&
    ((valTyp == ITM_CONSTANT &&
      ((ConstValue*)&val)->canBeSafelyCoercedTo(*baseCol->getType()))
     // we don't need to check the types of param & hostvar here because we
     // are called after ItemExpr::bindNode has successfully type-checked
     // the current search predicate that is being tested for cacheability
     || valTyp == ITM_HOSTVAR
     || valTyp == ITM_DYN_PARAM 
     || valTyp == ITM_CACHE_PARAM
     ));
}

// append an ascii-version of ItemExpr into cachewa.qryText_
void BaseColumn::generateCacheKey(CacheWA& cwa) const
{
  if (getTableDesc()->getCorrNameObj().getPrototype() == NULL) {
    // return the table in the format "table.col"
    ColRefName name
      (getTableDesc()->getNATable()->getNAColumnArray()[colNumber_]->
       getColName(),
       getTableDesc()->getCorrNameObj(), CmpCommon::statementHeap());
    cwa += name.getColRefAsAnsiString();
  }
  else {
    ColRefName name
      (getTableDesc()->getNATable()->getNAColumnArray()[colNumber_]->
       getColName(), CmpCommon::statementHeap());
    cwa += name.getColRefAsAnsiString();
  }
}

// is this BaseColumn a primary or partitioning key and is val a single 
// value or a constant that can be safely coerced to BaseColumn's type?
NABoolean BaseColumn::isKeyColumnValue(ItemExpr& val) const
{
  NAColumn *baseCol = getNAColumn();
  return
    (baseCol != NULL &&
     (baseCol->isPrimaryKey() || baseCol->isPartitioningKey()) &&
     canSafelyCoerce(val));
}

// append an ascii-version of BETWEEN into cachewa.qryText_
void Between::generateCacheKey(CacheWA& cwa) const
{ 
  cwa += leftBoundryIncluded_ ? "L1" : "L0";
  cwa += rightBoundryIncluded_ ? "R1" : "R0";
  if (pDirectionVector_) {
    cwa += "dV";
    Int32 x, limit=pDirectionVector_->entries();
    for (x = 0; x<limit; x++) {
      cwa += ((pDirectionVector_->at(x) == -1) ? "d" : "a");
    }
  }
  BuiltinFunction::generateCacheKey(cwa);
}

// append an ascii-version of biarith 
void BiArith::generateCacheKey(CacheWA& cwa) const
{
  ItemExpr::generateCacheKey(cwa); 

  // append an indication of rounding mode for datetime arithmetic functions
  if ( isKeepLastDay() ) cwa += "r1";
  else if ( isStandardNormalization() ) cwa += "r0";

  if (getOperatorType() == ITM_DIVIDE)
    {
      cwa += " arm:"; // arith rounding mode
      char dFmt[20]; 
      str_itoa(roundingMode_, dFmt); 
      cwa += dFmt;
    }
}

// change literals of a cacheable query into ConstantParameters 
ItemExpr* BiArith::normalizeForCache(CacheWA& cwa, BindWA& bindWA)
{
  if (nodeIsNormalizedForCache()) {
    return this;
  }
  if (!isUnaryNegate()) { // set in sqlparser.y which transforms "-i" into
    // "0 - i" because apparently the executor does not have a unary negate.
    // so, we must avoid replacing this system-introduced "0".
    child(0) = child(0)->normalizeForCache(cwa, bindWA);
  }
  child(1) = child(1)->normalizeForCache(cwa, bindWA);
  markAsNormalizedForCache();
  return this;
}

// we want BiLogic to be cacheable
NABoolean BiLogic::isCacheableExpr(CacheWA& cwa)
{
  if (cwa.getPhase() >= CmpMain::BIND && getArity() == 2) {
    if (getOperatorType() == ITM_AND) {
      ItemExpr *leftC=child(0), *rightC=child(1);
      // we want to descend to both left & right
      // so cwa.usedKeys & cwa.keyCols get updated
      NABoolean leftOK = leftC->isCacheableExpr(cwa);
      NABoolean rightOK = rightC->isCacheableExpr(cwa);
      // return FALSE if both left & right are not cacheable.
      if (!leftOK && !rightOK) 
        return FALSE;

      // allow "select * from t where k1=1 and k2=2" as potentially cacheable
      return TRUE;
      // the definitive check whether a query's predicate covers
      // all referenced tables' key columns can be (and is) done
      // only in RelRoot::isCacheableExpr() when cwa.usedKeys &
      // cwa.keyCols are fully defined. Otherwise, queries like
      //   "select * from t1 join t2 on a=x and a=7 where x=7"
      // may be incorrectly rejected as non-cacheable if t1 has
      // primary key(a) and t2 has primary key(x).
    }
    else if (getOperatorType() == ITM_OR) {
      return TRUE;
      // ORs can be cacheable but are not necessarily
      // parameterizable, see Bilogic::normalizeForCache below.
    }
  }
  return FALSE;
}

// selectively change literals of a cacheable query into input parameters 
ItemExpr* BiLogic::normalizeForCache(CacheWA& cwa, BindWA& bindWA)
{
  if (nodeIsNormalizedForCache()) { 
    return this; 
  }
  if (getOperatorType() == ITM_AND) {
    return ItemExpr::normalizeForCache(cwa, bindWA);
  }
  else { 
    // do not replace literals in OR predicates
    markAsNormalizedForCache();
    return this;
  }
}

// append an ascii-version of ItemExpr into cachewa.qryText_
void BiRelat::generateCacheKey(CacheWA& cwa) const
{
  cwa += specialNulls_ ? "s1" : "s0";
  cwa += specialMultiValuePredicateTransformation_ ? "m1" : "m0";
  cwa += isaPartKeyPred_ ? "p1" : "p0";
  if (directionVector_) {
    cwa += "Dv";
    Int32 x, limit=directionVector_->entries();
    for (x = 0; x<limit; x++) {
      cwa += ((directionVector_->at(x) == -1) ? "d" : "a");
    }
  }
  // we are deliberately excluding from the cachekey the following BiRelat
  // data members: likeSelectivity_, originalLikeExprId_
  // because we believe they are "internal" variables, ie, they are not
  // essential to distinguishing between two different queries.
  ItemExpr::generateCacheKey(cwa);
}

// we want BiRelat to be cacheable
NABoolean BiRelat::isCacheableExpr(CacheWA& cwa)
{
  if (cwa.getPhase() >= CmpMain::BIND && getArity() == 2) {
    if (getOperatorType() == ITM_EQUAL) {
      ItemExpr *leftC=child(0), *rightC=child(1);
      OperatorTypeEnum leftO = leftC->getOperatorType();
      OperatorTypeEnum rightO = rightC->getOperatorType();
      BaseColumn *base;
      if (leftO == ITM_BASECOLUMN) {
        base = (BaseColumn*)leftC;
        if (base->isKeyColumnValue(*rightC)) {
          cwa.addToUsedKeys(base);
        }
        return TRUE;
      }
      else if (rightO == ITM_BASECOLUMN) {
        base = (BaseColumn*)rightC;
        if (base->isKeyColumnValue(*leftC)) {
          cwa.addToUsedKeys(base);
        }
        return TRUE;
      }
      else if (leftO == ITM_ITEM_LIST && rightO == ITM_ITEM_LIST &&
               ((ItemList*)leftC)->isListOfCacheableSelPred
               (cwa, (ItemList*)rightC)) {
        return TRUE;
      }
      else {
        // we want all other equality comparisons to be cacheable, eg,
        // retail_div_cd||acct_type_cd||substring(acct_id,1,8)='20V43085193'
        return TRUE;
      }
    }
    else {
      return TRUE;
      // other binary comparison predicates can be cacheable, but are
      // not necessarily parameterizable, see BiRelat::normalizeForCache
    }
  }
  return FALSE;
}

// is it safe to parameterize this selection predicate term?
// change literals of a cacheable query into input parameters 
ItemExpr* BiRelat::normalizeForCache(CacheWA& cwa, BindWA& bindWA)
{
  if (cwa.getPhase() >= CmpMain::BIND) {
    // NB: we assume here that when a query is cacheable because it has a key
    //     equi-predicate, then its key equi-predicates can be parameterized
    if (getArity() == 2) {
      if (getOperatorType() == ITM_EQUAL) {
        // normalizeForCache only constants that can be safely backpatched.
        // part of fix to CR 10-010726-4109.
        ItemExpr *leftC=child(0), *rightC=child(1);
        OperatorTypeEnum leftO = leftC->getOperatorType();

        // fix case 10-061027-0129: discover the potential base column 
        // below the InstantiateNull node
        if ( leftO == ITM_INSTANTIATE_NULL ) {
           leftC = leftC->child(0);
           leftO = leftC->getOperatorType();
        }

        OperatorTypeEnum rightO = rightC->getOperatorType();

        // fix case 10-061027-0129.
        if ( rightO == ITM_INSTANTIATE_NULL ) {
           rightC = rightC->child(0);
           rightO = rightC->getOperatorType();
        }

        if (leftO == ITM_BASECOLUMN && rightO == ITM_CONSTANT) {
          parameterizeMe(cwa, bindWA, child(1),
                         (BaseColumn*)leftC, (ConstValue*)rightC);
		  //HQC collect histogram for column
		 ItemExpr * cParameter = child(1);
		 cwa.bindConstant2SQC((BaseColumn*)leftC, (ConstantParameter*)cParameter);
        }
        else if (rightO == ITM_BASECOLUMN && leftO == ITM_CONSTANT) {
          parameterizeMe(cwa, bindWA, child(0),
                         (BaseColumn*)rightC, (ConstValue*)leftC);
             //HQC collect histogram for column
          ItemExpr * cParameter = child(0);
          cwa.bindConstant2SQC((BaseColumn*)rightC, (ConstantParameter*)cParameter);
        }
        else if (leftO == ITM_ITEM_LIST && rightO == ITM_ITEM_LIST) {
          child(0) = ((ItemList*)leftC)->normalizeListForCache
            (cwa, bindWA, (ItemList*)rightC);
        }
      }
      // FIXME: ie, parameterize other binary comparison predicates
      // if we can guarantee the correctness of such parameterizations
    }
  }
  markAsNormalizedForCache();
  return this;
}

// helper to change literals of a cacheable query into input parameters
void BiRelat::parameterizeMe(CacheWA& cwa, BindWA& bindWA, ExprValueId& child,
                             BaseColumn *base, ConstValue *val)
{
  NABoolean parameterizableMVQRplan = cwa.hasRewriteEnabledMV() && 
    CmpCommon::getDefault(MVQR_PARAMETERIZE_EQ_PRED) == DF_ON;
  NABoolean parameterizablePlan = parameterizableMVQRplan || 
    !cwa.hasRewriteEnabledMV();

  if (val->isNull()) {
    // val is null; keep null as is.
    // this is part of a fix to genesis case: 10-010618-3484.
  }
  else if (base->isKeyColumnValue(*val) // keyCol = constant
           && cwa.isParameterizable(base) && parameterizablePlan) {
    cwa.replaceWithNewOrOldConstParam(val, base->getNAColumn()->getType(),
                                      child, bindWA);
    if (parameterizableMVQRplan)
      cwa.setParameterizedPred(TRUE);
  }
  else if (!base->canSafelyCoerce(*val)) {
    // term is not parameterizable, keep it as is.
  }
  else { // nonKeyCol = constant
    if (parameterizablePlan) {
      computeAndAddSelParamIfPossible(cwa, bindWA, child, base, val);
      if (parameterizableMVQRplan)
        cwa.setParameterizedPred(TRUE);
    }
  }
}

// append an ascii-version of ItemExpr into cachewa.qryText_
void Case::generateCacheKey(CacheWA& cwa) const
{
  // print any caseOperand before the case itself. That's out-of-order,
  // but, we must differentiate 2 case exprs that differ only in their
  // caseOperands. Otherwise, we will fail on a test, ie,
  // we'll cache this insert
  //   insert into t values(case 3 when 4 then 0 when 3 then 1 end)
  // and then later incorrectly consider this insert as a hit
  //   insert into t values(case 4 when 4 then 0 when 3 then 1 end)
  // because their cache keys are identical
  if (caseOperand_) {
    cwa += " caseOpd:"; 
    caseOperand_->generateCacheKey(cwa);
    cwa += caseOperandWasNullable_ ? " 1" : " 0";
  }
  cwa += " builtinFunc:"; 
  BuiltinFunction::generateCacheKey(cwa);
}

// does this entire ItemExpr qualify query to be cacheable after this phase?
NABoolean Case::isCacheableExpr(CacheWA& cwa)
{
  if (caseOperand_ && !caseOperand_->isCacheableExpr(cwa)) {
    return FALSE;
  }
  return ItemExpr::isCacheableExpr(cwa);
}

// change literals of a cacheable query into input parameters 
ItemExpr* Case::normalizeForCache(CacheWA& cwa, BindWA& bindWA)
{
  if (caseOperand_) {
    caseOperand_ = caseOperand_->normalizeForCache(cwa, bindWA);
  }
  return BuiltinFunction::normalizeForCache(cwa, bindWA);
}

// append an ascii-version of Cast into cachewa.qryText_
void Cast::generateCacheKey(CacheWA& cwa) const
{
  BuiltinFunction::generateCacheKey(cwa);
  if (type_) { 
    cwa += " "; 
    cwa += type_->getTypeSQLname().data(); 
  }
}

// is any literal in this expr safely coercible to its target type?
NABoolean Cast::isSafelyCoercible(CacheWA &cwa) const
{
  if (cwa.getPhase() >= CmpMain::BIND) {
    ItemExpr *opd = child(0);
    if (!opd->isSafelyCoercible(cwa)) { 
      return FALSE; 
    }
    if (opd->getOperatorType() == ITM_CONSTANT) {
      return ((ConstValue*)opd)->canBeSafelyCoercedTo(*type_);
    }      
    return TRUE; 
  }
  return FALSE;
}

// append an ascii-version of ConstantParameter into cachewa.qryText_
void ConstantParameter::generateCacheKey(CacheWA& cwa) const
{ 
  cwa += "%"; 
}

// return our size in bytes
Lng32 ConstantParameter::getSize() const
{ 
  return (Lng32)(sizeof(*this) + type_->getSize() + val_->getSize());
}

// can this ConstValue be safely coerced into this target type?
NABoolean ConstValue::canBeSafelyCoercedTo(const NAType& target)
{
  // if errorsCanOccur says it's safe then it is
  if (!type_->errorsCanOccur(target)) {
    if ((target.getTypeQualifier() == NA_CHARACTER_TYPE) &&
        (type_->getTypeQualifier() == NA_CHARACTER_TYPE)) {
      if (((CharType&)target).isCaseinsensitive() !=
          (((CharType*)type_)->isCaseinsensitive()))
        return FALSE;
      else {
        // fix bugzilla 2764 by skipping parameterization of long
        // char literals because backpatching those does not work.
        // not yet.
        return target.getNominalSize() < 
          CmpCommon::getDefaultNumeric(QUERY_CACHE_MAX_CHAR_LEN);
      }
    }
    return TRUE;
  }

  // a NULL can be safely coerced to any nullable type
  if (isNull()) {
    return target.supportsSQLnullLogical();
  }

  // If the ConstValue type and the target type are both numeric
  // and if the ConstValue can fit in the target type,
  // it should be ok.
  if ( target.getTypeQualifier() == NA_NUMERIC_TYPE && 
       type_->getTypeQualifier() == NA_NUMERIC_TYPE ) {

    NumericType *srcType = (NumericType*)type_;
    NumericType *tgtType = (NumericType*)(&target);
    if (tgtType->shouldCheckValueFitInType()) {
      double val = srcType->getNormalizedValue(value_);
      if ((val >= 0) && (val <= (tgtType->getMaxValue())) ) {
        if ( srcType->isExact() && tgtType->isExact() &&
             (srcType->getScale() > tgtType->getScale() ) )
           return FALSE;
        else
           return TRUE;
      }
      if ((val < 0) && (val >= (tgtType->getMinValue())) ) {
        if ( srcType->isExact() && tgtType->isExact() &&
             (srcType->getScale() > tgtType->getScale() ) )
           return FALSE;
        else
           return TRUE;
      }
    }
    // NUMERIC and DECIMAL should be (but are not always) covered in 
    // errorsCanOccur.  
    if (srcType->isExact() && tgtType->isExact()) {
      // Source and target are exact.
      if (srcType->isUnsigned() || tgtType->isSigned()) {
        // If the magnitude and scale of the target are greater
        // than or equal to the source, then no conversion
        // error can occur
        if ((srcType->getMagnitude() <= tgtType->getMagnitude()) &&
            (srcType->getScale() <= tgtType->getScale())
            )
          return TRUE;
      }
      else { // source literal is signed and target is unsigned
        // errors can NOT occur if source literal >= 0 and the
        // magnitude and scale of the target are >= those of source
        if (type_->encode(value_) >= 0.0 &&
            (srcType->getMagnitude() <= tgtType->getMagnitude()) &&
            (srcType->getScale() <= tgtType->getScale()))
          return TRUE;
      }
    }
  }

  // except if target is unsigned exact numeric and
  // our type is signed exact numeric and our value is non-negative
  // in which case we morph our type into signed
  // and then retry the errorsCanOccur test
  if (target.getTypeQualifier() == NA_NUMERIC_TYPE && 
      ((const NumericType&)target).isExact() &&
      ((const NumericType&)target).isUnsigned() && 
      isExactNumeric() && ((NumericType*)type_)->isSigned() &&
      type_->encode(value_) >= 0.0) {
    ((NumericType*)type_)->makeUnsigned();
    NABoolean result = !type_->errorsCanOccur(target);
    ((NumericType*)type_)->makeSigned();
    return result;
  }
  // except if source & target types are INTERVALs and 
  // our constant's SQLnullFlag_ == NOT_NULL_NOT_DROPPABLE
  // and target's SQLnullFlag_ == ALLOWS_NULLS
  if (target.getTypeQualifier() == NA_INTERVAL_TYPE && 
      type_->getTypeQualifier() == NA_INTERVAL_TYPE &&
      target.supportsSQLnullLogical() && !type_->supportsSQLnullPhysical()) {
    // in which case, we morph our constant's SQLnullFlag_ to ALLOWS_NULLS
    // and then retry the errorsCanOccur test
    ((NAType*)type_)->setSQLnullFlag();
    NABoolean result = !type_->errorsCanOccur(target);
    ((NAType*)type_)->resetSQLnullFlag();
    return result;
  }

  return FALSE; // we can't guarantee a safe coercion into target
}

// return our size in bytes
Lng32 ConstValue::getSize() const
{
  return (Lng32)(sizeof(*this) + getStorageSize() + 
    (text_ ? text_->length() : 0) +
    (locale_strval ? locale_strval->length() : 0) +
    (locale_wstrval ? locale_wstrval->length() : 0));
}

// return true iff I am a string literal with unknown character set
NABoolean ConstValue::hasUnknownCharSet()
{
  return type_->getTypeQualifier() == NA_CHARACTER_TYPE &&
    ((CharType*)type_)->getCharSet() == CharInfo::UnknownCharSet;
}

// does this ItemExpr (dis)qualify query to be cacheable after this phase?
NABoolean ConstValue::isCacheableExpr(CacheWA& cwa)
{
  if (cwa.getPhase() <= CmpMain::PARSE && hasUnknownCharSet()) {
    // string literal with unknown character set cannot be considered
    // cacheable by pre-binder stages because the information needed
    // to determine their character set is not known until bind-time.
    // This fixes genesis case 10-041215-6141, soln 10-041215-2826.
    return FALSE;
  }

  // string of length zero causes a problem during backpatching in method 
  // CacheData::backpatchParams.
  // For now, do not cache it.
  if ((NOT isNull()) &&
      (isEmptyString()))
    return FALSE;

  return ItemExpr::isCacheableExpr(cwa);
}

// change literal of a cacheable query into ConstantParameter
ItemExpr* ConstValue::normalizeForCache(CacheWA& cwa, BindWA& bindWA)
{
  // skip system supplied or empty string literals
  if (isSystemSupplied_ || isEmptyString()) { 
    return this; 
  }
  if (nodeIsNormalizedForCache()) { 
    return this; 
  }
  // for now, do not parameterize NULLs because they can cause false 
  // constraint violations, eg, fullstack/TEST005 
  //   create table t005t2(a int, b int not null, c char(10) not null,
  //                       d int, primary key (c) );
  //   insert into t005t2 values (NULL,7,'?-7-?',NULL);
  // gets "ERROR[8421] NULL cannot be assigned to a NOT NULL column."
  if (isNull()) { 
    return this; 
  }

  NAHeap* heap = cwa.wHeap();
  // quantize length of strings only in after parse case
  ConstantParameter* result = new(heap) ConstantParameter
    (*this, heap, cwa.getPhase() == CmpMain::PARSE);
  if (result) {
    // "after-parser" ConstantParameters will undergo complete binding, so
    // addConstParam does not have to bind "after-parser" ConstantParameters
    cwa.addConstParam(result, bindWA);
    cwa.bindConstant2SQC((BaseColumn*)NULL, result);
    result->markAsNormalizedForCache();
  }
  // do not mark this ConstValue as normalizedForCache because it may
  // be "shared" and may need to be replaced into a ConstantParameter
  // again in another referencing expression context. For example, the
  // binder visits the case operand "3" more than once in
  //   insert into t values(case 3 when 4 then 0 when 3 then 1 end)

  return result;
}

// append an ascii-version of DateFormat into cachewa.qryText_
void DateFormat::generateCacheKey(CacheWA& cwa) const
{
  BuiltinFunction::generateCacheKey(cwa); 
  cwa += " fmt:";
  char dFmt[20]; 
  str_itoa(dateFormat_, dFmt); 
  cwa += dFmt;
  str_itoa(frmt_, dFmt);
  cwa += dFmt;
}

// does this entire ItemExpr qualify query to be cacheable after this phase?
NABoolean DynamicParam::isCacheableExpr(CacheWA& cwa)
{
  // a dynamic parameter is not cacheable after parse
  return (cwa.getPhase() <= CmpMain::PARSE) ? FALSE : TRUE;
}

// append an ascii-version of Cast into cachewa.qryText_
void Extract::generateCacheKey(CacheWA& cwa) const
{
  BuiltinFunction::generateCacheKey(cwa); 
  cwa += " xFld:"; 
  char xFld[20]; str_itoa(extractField_, xFld); 
  cwa += xFld;
  cwa += " fldFun:"; 
  cwa += fieldFunction_ ? "1" : "0";
}

// append an ascii-version of HbaseTimestamp into cachewa.qryText_
void HbaseTimestamp::generateCacheKey(CacheWA& cwa) const
{
  BuiltinFunction::generateCacheKey(cwa); 

  col()->generateCacheKey(cwa);
}

// append an ascii-version of HbaseVersion into cachewa.qryText_
void HbaseVersion::generateCacheKey(CacheWA& cwa) const
{
  BuiltinFunction::generateCacheKey(cwa); 

  col()->generateCacheKey(cwa);
}

// does this entire ItemExpr qualify query to be cacheable after this phase?
NABoolean HostVar::isCacheableExpr(CacheWA& cwa)
{
  // a HostVar is always cacheable
  return TRUE;
}

// append an ascii-version of PivotGroup into cachewa.qryText_
void PivotGroup::generateCacheKey(CacheWA& cwa) const
{
  Aggregate::generateCacheKey(cwa); 
  cwa += delim_;

  char xFld[20]; str_itoa(maxLen_, xFld); 
  cwa += xFld;

  cwa += orderBy_ ? "1" : "0";
}

// append an ascii-version of ItemExpr into cachewa.qryText_
void ItemExpr::generateCacheKey(CacheWA& cwa) const
{
  Int32 arity = getArity();
  switch (arity) {
  case 0:
    // simply print the text out for a leaf operator
    cwa += getText4CacheKey();
    break;
  case 2:
    if (getOperatorType() == ITM_ITEM_LIST || getOperatorType() == ITM_AND) {
      if (child(0)) {
        child(0)->generateCacheKey(cwa);
      }
      else {
        cwa += "NULL";
      }
      if (getOperatorType() != ITM_ITEM_LIST) {
        cwa += " ";
      }
      cwa += getText4CacheKey();
      cwa += " ";

      if (child(1)) {
        child(1)->generateCacheKey(cwa);
      }
      else {
        cwa += "NULL";
      }
    }
    else {
      // assume this is an infix operator (<child0>) op (<child1>)
      cwa += "(";

      NABoolean list0 = FALSE, list1 = FALSE;
      if (getOperatorType() != ITM_ITEM_LIST) {
        list0 = child(0)->getOperatorType() == ITM_ITEM_LIST;
        list1 = child(1)->getOperatorType() == ITM_ITEM_LIST;
      }
      if (list0) {
        cwa += "(";
      }
      child(0)->generateCacheKey(cwa);
      if (list0) {
        cwa += ")";
      }
      cwa += " ";
      cwa += getText4CacheKey();
      cwa += " ";
      if (list1) {
        cwa += "(";
      }
      child(1)->generateCacheKey(cwa);
      if (list1) {
        cwa += ")";
      }
      cwa += ")";
    }
    break;

  default:
    if (arity == 1 && isAPredicate() && getOperatorType() != ITM_NOT) {
      child(0)->generateCacheKey(cwa);
      cwa += " ";
      cwa += getText4CacheKey();
    }
    else {
      // any other arity: assume a function op(<child>,<child>,...)
      cwa += getText4CacheKey();
      cwa += "(";
      for (Lng32 i = 0; i < (Lng32)arity; i++) {
        if (i > 0) {
          cwa += ", ";
        }
        child(i)->generateCacheKey(cwa);
      }
      cwa += ")";
      break;
    }
  }
  addSelectivityFactor( cwa ) ;
}

//
// addSelectivityFactor() - a helper routine for ItemExpr::generateCacheKey()
//
// NOTE: The code in this routine came from the previous version of
//       ItemExpr::generateCacheKey().   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::generateCacheKey() routine.
//
void ItemExpr::addSelectivityFactor( CacheWA& cwa ) const
{
  if(((ItemExpr *)this)->isSelectivitySetUsingHint()) 
  {
    char str[100];
    sprintf(str, " sel:%g", getSelectivityFactor());
    cwa += str;
  }
}

// return true if ItemExpr & its descendants have no constants & noncacheables
NABoolean ItemExpr::hasNoLiterals(CacheWA& cwa)
{
  if (isNonCacheable()) {
    return FALSE;
  }
  OperatorTypeEnum opTyp = getOperatorType();
  switch (opTyp) {
  case ITM_CONSTANT:
  case ITM_HOSTVAR:
  case ITM_DYN_PARAM:
  case ITM_CACHE_PARAM: 
    return FALSE;
  default: // fall thru
    break;
  }
  NABoolean result = TRUE;
  Int32 arity = getArity();
  for (Int32 x = 0; x < arity && result; x++) {
    if (child(x)) { 
      result = child(x)->hasNoLiterals(cwa); 
    }
  }
  return result;
}

// does this entire ItemExpr qualify query to be cacheable after this phase?
NABoolean ItemExpr::isCacheableExpr(CacheWA& cwa)
{
  switch (cwa.getPhase()) {
  default: { const NABoolean notYetImplemented = FALSE; 
    CMPASSERT(notYetImplemented);
    break;
  }
  case CmpMain::PARSE:
    // ItemExpr::isCacheableExpr is used by Tuple::isCacheable to
    // determine whether a tuple-insert or a tuplelist-insert is
    // cacheable after parse. It traverses a tuple's values list
    // looking for non-cacheable ItemExprs such as HostVar, 
    // DynamicParam, Subquery, etc.  
    // determine cacheability of tuple INSERT's itemexprs here
    if (isNonCacheable() || !cwa.isConditionallyCacheable()) {
      return FALSE;
    }
    else { // we're either cacheable or maybecacheable
      Int32 arity = getArity();
      if (arity <= 0) { // we have no kids & we're conditionally cacheable
        return TRUE; // we're cacheable
      }
      // cacheability of child(ren) determine our cacheability
      for (Int32 x = 0; x < arity; x++) {
        if (!child(x) || child(x)->isNonCacheable()) {
          // the 1st noncacheable child makes us noncacheable
          setNonCacheable();
          return FALSE;
        }
        else if (!child(x)->isCacheableExpr(cwa)) {
          // noncacheable child
          return FALSE;
        }
        else { // cacheable child
          continue; // look at next child
        }
      }
      // all children are cacheable, so we're cacheable too
      setCacheableNode(cwa.getPhase());
      return TRUE;
    }
    break;
  case CmpMain::BIND:
    // does query have too many ExprNodes?
    if (cwa.inc_N_check_still_cacheable() == FALSE) {
      // yes. query with too many ExprNodes is not cacheable.
      return FALSE;
    }
    // ItemExpr::isCacheableExpr is used in "after BIND" cases to
    // visit all operands of an ItemExpr looking for noncacheable
    // expressions. For example, it discovers that
    //   SELECT (SELECT a FROM t2 WHERE MAX(o.c)>1) FROM t1 o;
    // is noncacheable only after it visits the outer query's select list.
    if (isNonCacheable()) {
      return FALSE;
    }
    else if (isCacheableNode(cwa.getPhase())) {
      return TRUE;
    }
    else { // we're either cacheable or maybecacheable
      // Assume this ItemExpr is an operand of a function or a list. In
      // this case, a single noncacheable child renders us noncacheable.
      Int32 arity = getArity();
      for (Int32 x = 0; x < arity; x++) {
        if (!child(x) || !child(x)->isCacheableExpr(cwa)) {
          // noncacheable child
          return FALSE;
        }
        else { // cacheable child
          continue; // look at next child
        }
      }
      // all children are cacheable, so we're cacheable too
      setCacheableNode(cwa.getPhase());
      return TRUE;
    }
    break;
  }
  return FALSE;
}

// is this ExprNode cacheable after this phase?
NABoolean ItemExpr::isCacheableNode(CmpPhase phase) const
{ 
  switch (phase) {
  case CmpMain::PARSE: 
    return cacheable_ == ExprNode::CACHEABLE_PARSE;
  case CmpMain::BIND:
    return cacheable_ == ExprNode::CACHEABLE_BIND ||
      cacheable_ == ExprNode::CACHEABLE_PARSE;
  default:
    break;
  }
  return FALSE;
}

// is any literal in this expr safely coercible to its target type?
NABoolean ItemExpr::isSafelyCoercible(CacheWA &cwa) const
{
  if (cwa.getPhase() >= CmpMain::BIND) {
    Int32 arity = getArity();
    for (Int32 x = 0; x < arity; x++) {
      if (!child(x)->isSafelyCoercible(cwa)) { 
        return FALSE; 
      }
    }
    if (arity == 2) {
      // we have to disallow caching of the following types of exprs:
      //   expr + 123456789012345678901234567890
      //   expr || 'overlylongstringthatwouldoverflow'
      ItemExpr *left = child(0), *right = child(1);
      if (left->getOperatorType() == ITM_CONSTANT) {
        if (right->getOperatorType() == ITM_CONSTANT) {
          // "10 + 1" should be safely coercible
          return TRUE;
        } else {
          return ((ConstValue*)left)->canBeSafelyCoercedTo
            (right->getValueId().getType());
        }
      }      
      else if (right->getOperatorType() == ITM_CONSTANT) {
        return ((ConstValue*)right)->canBeSafelyCoercedTo
          (left->getValueId().getType());
      }      
      // else both are nonliterals; fall thru
    }
    // else nondyadic expr; fall thru
    return TRUE; 
  }
  return FALSE;
}

// change literals of a cacheable query into ConstantParameters 
ItemExpr* ItemExpr::normalizeForCache(CacheWA& cwa, BindWA& bindWA)
{
  if (nodeIsNormalizedForCache()) { 
    return this; 
  }
  Int32 arity = getArity();
  for (Int32 x = 0; x < arity; x++) {
    if (cwa.getPhase() == CmpMain::PARSE) {
      // we want to parameterize tuple inserts
      child(x) = child(x)->normalizeForCache(cwa, bindWA);
    }
    else if (cwa.getPhase() == CmpMain::BIND) {
      if (child(x)->isSafelyCoercible(cwa)) {
        // fix CR 10-010726-4109: make sure queries with constants that 
        // cannot be safely backpatched such as 
        //   select case smallintcol when 4294967393 then 'max' end from t
        // are not parameterized
        child(x) = child(x)->normalizeForCache(cwa, bindWA);
      }
    }
  }
  markAsNormalizedForCache();
  return this;
}

// mark this ExprNode as cacheable after this phase
void ItemExpr::setCacheableNode(CmpPhase phase)
{ 
  switch (phase) {
  case CmpMain::PARSE: 
    cacheable_ = ExprNode::CACHEABLE_PARSE;
    break;
  case CmpMain::BIND:
    cacheable_ = ExprNode::CACHEABLE_BIND;
    break;
  default:
    break;
  }
}

// does this query's selection predicate list qualify query 
// to be cacheable after this phase?
NABoolean ItemList::isListOfCacheableSelPred
(CacheWA& cwa, ItemList *other) const
{
  Int32 arity = getArity();
  NABoolean result = FALSE;
  if (cwa.getPhase() >= CmpMain::BIND && 
      other && arity == other->getArity()) {
    // assume this is an AND list, so, we need only one
    // cacheable conjunct to consider the list cacheable.
    for (Int32 x = 0; x < arity; x++) {
      ItemExpr *leftC = child(x), *rightC = other->child(x);
      OperatorTypeEnum leftO = leftC->getOperatorType();
      OperatorTypeEnum rightO = rightC->getOperatorType();
      BaseColumn *base;
      if (leftO == ITM_BASECOLUMN) {
        base = (BaseColumn*)leftC;
        if (base->isKeyColumnValue(*rightC)) {
          cwa.addToUsedKeys(base);
        }
        result = TRUE;
        continue;
      }
      else if (rightO == ITM_BASECOLUMN) {
        base = (BaseColumn*)rightC;
        if (base->isKeyColumnValue(*leftC)) {
          cwa.addToUsedKeys(base);
        }
        result = TRUE;
        continue;
      }
      else if (leftO == ITM_ITEM_LIST && rightO == ITM_ITEM_LIST &&
               ((ItemList*)leftC)->isListOfCacheableSelPred
               (cwa, (ItemList*)rightC)) {
        result = TRUE;
        continue;
      }
    }
  }
  return result;
}

// is any literal in this expr safely coercible to its target type?
NABoolean ItemList::isSafelyCoercible(CacheWA& cwa) const
{
  if (cwa.getPhase() >= CmpMain::BIND) {
    Int32 arity = getArity();
    for (Int32 x = 0; x < arity; x++) {
      if (!child(x)->isSafelyCoercible(cwa)) { 
        return FALSE; 
      }
    }
    return TRUE;
  }
  return FALSE;
}

// change literals of a cacheable query into input parameters 
ItemExpr* ItemList::normalizeListForCache
(CacheWA& cwa, BindWA& bindWA, ItemList *other)
{
  Int32 arity = getArity();
  if (cwa.getPhase() >= CmpMain::BIND && 
      other && arity == other->getArity()) {
    for (Int32 x = 0; x < arity; x++) {
      ItemExpr *leftC = child(x), *rightC = other->child(x);
      OperatorTypeEnum leftO = leftC->getOperatorType();
      OperatorTypeEnum rightO = rightC->getOperatorType();
      if (leftO == ITM_BASECOLUMN && rightO == ITM_CONSTANT) {
        parameterizeMe(cwa, bindWA, other->child(x), (BaseColumn*)leftC,
                       (ConstValue*)rightC);
		 //HQC collect histogram for column
		 ItemExpr * cParameter = other->child(x);
        cwa.bindConstant2SQC((BaseColumn*)leftC, (ConstantParameter*)cParameter);
      }
      else if (rightO == ITM_BASECOLUMN && leftO == ITM_CONSTANT) {
        parameterizeMe(cwa, bindWA, child(x), (BaseColumn*)rightC,
                       (ConstValue*)leftC);
		 //HQC collect histogram for column
		 ItemExpr * cParameter = child(x);
        cwa.bindConstant2SQC((BaseColumn*)rightC, (ConstantParameter*)cParameter);
      }
      else if (leftO == ITM_ITEM_LIST && rightO == ITM_ITEM_LIST) {
        child(x) = ((ItemList*)leftC)->normalizeListForCache
          (cwa, bindWA, (ItemList*)rightC);
      }
    }
  }
  return this;
}

// helper to change literals of a cacheable query into input parameters
void ItemList::parameterizeMe(CacheWA& cwa, BindWA& bindWA, ExprValueId& child,
                              BaseColumn *base, ConstValue *val)
{
  NABoolean parameterizableMVQRplan = cwa.hasRewriteEnabledMV() && 
    CmpCommon::getDefault(MVQR_PARAMETERIZE_EQ_PRED) == DF_ON;
  NABoolean parameterizablePlan = parameterizableMVQRplan || 
    !cwa.hasRewriteEnabledMV();

  if (val->isNull()) {
    // val is null; keep null as is.
    // this is part of a fix to genesis case: 10-010618-3484.
  }
  else if (base->isKeyColumnValue(*val) // keyCol = constant
           && cwa.isParameterizable(base) && parameterizablePlan) {
    cwa.replaceWithNewOrOldConstParam(val, base->getNAColumn()->getType(),
                                      child, bindWA);
    if (parameterizableMVQRplan)
      cwa.setParameterizedPred(TRUE);
  }
  else if (!base->canSafelyCoerce(*val)) {
    // term is not parameterizable, keep it as is.
  }
  else { // nonKeyCol = constant
    if (parameterizablePlan) {
      computeAndAddSelParamIfPossible(cwa, bindWA, child, base, val);
      if (parameterizableMVQRplan)
        cwa.setParameterizedPred(TRUE);
    }
  }
}

// append an ascii-version of LIKE into cachewa.qryText_
void PatternMatchingFunction::generateCacheKey(CacheWA& cwa) const
{
  // we are deliberately excluding from cachekey the data members: 
  // numberOfNonWildcardChars_, patternAStringLiteral_, 
  // oldDefaultSelForLikeWildCardUsed_
  // because we believe they are "internal" variables, ie, they are
  // not essential to distinguishing two different LIKEs.
  BuiltinFunction::generateCacheKey(cwa);
}

// change literals of a cacheable query into ConstantParameters 
ItemExpr* PatternMatchingFunction::normalizeForCache(CacheWA& cwa, BindWA& bindWA)
{
  if (nodeIsNormalizedForCache()) { 
    return this; 
  }
  // replace only the matchValue
  child(0) = child(0)->normalizeForCache(cwa, bindWA);
  // but, don't touch the pattern or the escapeChar.

  markAsNormalizedForCache();
  return this;
}

// Note: When this method is used during query cache lookup (actually the 
// verification step), this belongs to the item in the bucket that matches
// the key, and other is the selectivity computed for an equal-predicate 
// constant in the query to be looked up. 
//
// This method is called to verify that this and other are not different
// very much.
//
// We return TRUE iff 
//  this.val_ / (1+delta)  <= other.val_ <= this.val_ * (1 + delta)
//
// where delta is 
//    the value stored in QUERY_CACHE_SELECTIVITY_TOLERANCE
//
NABoolean Selectivity::operator==(const Selectivity& other) const
{
  CostScalar delta = 
    CostScalar((ActiveSchemaDB()->getDefaults()).getAsDouble(QUERY_CACHE_SELECTIVITY_TOLERANCE)) + 1;

  return (val_ / delta <= other.val_) && (other.val_ <= val_ * delta);
}

// append an ascii-version of SelParameter into cachewa.qryText_
void SelParameter::generateCacheKey(CacheWA& cwa) const
{ 
  cwa += "#"; 
}

// append an ascii-version of SequenceValue into cachewa.qryText_
void SequenceValue::generateCacheKey(CacheWA& cwa) const
{
  BuiltinFunction::generateCacheKey(cwa); 
  cwa += seqCorrName_.getQualifiedNameAsString();

  if (currVal_)
    cwa += "currVal";
  else if (nextVal_)
    cwa += "nextVal";
}

// append an ascii-version of Subquery into cachewa.qryText_
void Subquery::generateCacheKey(CacheWA& cwa) const
{
  ItemExpr::generateCacheKey(cwa); 
  cwa += " tExp:";
  getSubquery()->generateCacheKey(cwa);
}

// return true if ItemExpr & its descendants have no constants 
// and no noncacheable nodes
NABoolean Subquery::hasNoLiterals(CacheWA& cwa)
{
  return ItemExpr::hasNoLiterals(cwa) && getSubquery()->isCacheableExpr(cwa);
}

// we want Subquery to be cacheable
NABoolean Subquery::isCacheableExpr(CacheWA& cwa)
{
  if (!getSubquery()->isCacheableExpr(cwa)) {
    return FALSE;
  }
  return ItemExpr::isCacheableExpr(cwa);
}

// change literals of a cacheable query into ConstantParameters 
ItemExpr* Substring::normalizeForCache(CacheWA& cwa, BindWA& bindWA)
{
  if (nodeIsNormalizedForCache()) { 
    return this; 
  }
  // parameterize S in "substring(S from B for L)" but skip B & L
  child(0) = child(0)->normalizeForCache(cwa, bindWA);

  markAsNormalizedForCache();
  return this;
}

// append an ascii-version of Translate into cachewa.qryText_
void Translate::generateCacheKey(CacheWA& cwa) const
{
  BuiltinFunction::generateCacheKey(cwa); 
  cwa += " map:";
  char map[20]; str_itoa(map_table_id_, map); 
  cwa += map;
}

// append an ascii-version of Trim into cachewa.qryText_
void Trim::generateCacheKey(CacheWA& cwa) const
{
  BuiltinFunction::generateCacheKey(cwa); 
  cwa += " tlb:";
  char mode[20]; str_itoa(mode_, mode); 
  cwa += mode;
}

// Only alow UDFunctions to be cached after BIND time.
NABoolean UDFunction::isCacheableExpr(CacheWA& cwa)
{ 
  if (cwa.getPhase() >= CmpMain::BIND) 
    return TRUE;
  else 
    return FALSE; 
}

// change literals of a cacheable query into ConstantParameters 
ItemExpr* UDFunction::normalizeForCache(CacheWA& cwa, BindWA& bindWA)
{
  if (nodeIsNormalizedForCache()) { 
    return this; 
  }
  // Since the UDFunction::transformNode refers to both the 
  // inputVars_ ValueIdSet and the children array we need to make sure
  // they are consistent.
  // The children array may contain cast() of the expressions in inputVars_


  // If we have a UUDF function the inputs that were given 
  // at parse time, really do not reflect reality anymore.
  // So here we will simply reinitialize them with what we find in the
  // inputVars_.

  CMPASSERT(udfDesc_); // we better have one after binding.
  NABoolean isUUDF(udfDesc_->isUUDFRoutine());

  // Save off a copy of the original inputVars_ set.
  ValueIdSet origInputVars(inputVars_);


  // Loop through the given inputs
  for (Int32 x = 0; x < getArity(); x++)
  {
    NABoolean origInputIsChildOfCast(FALSE);
    ItemExpr * origIe = child(x);
    ItemExpr * newIe = NULL;
    ValueId vid = origIe->getValueId();
    if (cwa.getPhase() == CmpMain::BIND) 
    {
      if (origIe->isSafelyCoercible(cwa)) 
      {
   
        // fix CR 10-010726-4109: make sure queries with constants that 
        // cannot be safely backpatched such as 
        //   select case smallintcol when 4294967393 then 'max' end from t
        // are not parameterized
   
   
        newIe = origIe->normalizeForCache(cwa, bindWA);
   
        if (newIe != origIe )
        {
          // normalizeForCache returned a new ItemExpr. We have to update
          // the UDFunction inputVars_ set, as this is used to determine
          // characteristic inputs for IsolatedScalarUDF at transform time.

          child(x) = newIe;

          // Is it a input that UDFunction::bindNode put a cast around?
          if ((origIe->getOperatorType() == ITM_CAST) &&
              (origInputVars.contains(origIe->child(0)->getValueId())))
          {

            // Since the original child was a CAST that UDFunction::bindNode
            // created, check to see if that CAST's child is part of the new
            // expression, if it is, we don't have to do anything, since the
            // CASTED value is part of the inputVars set, otherwise, we have
            // to update the inputVars set to keep the characteristic inputs
            // consistent.
            if (! newIe->referencesTheGivenValue(
                    origIe->child(0)->getValueId()), TRUE)
            {
              // remove the original input from inputVars. It is the child
              // of origIe because origIe is a cast that UDFunction::bindNode
              // introduced.
              inputVars_ -= origIe->child(0)->getValueId();

              if (newIe->getOperatorType() == ITM_CAST)
              {
                // If the new expression is a CAST, we assume the child is the
                // real input. We don't expect CAST(CAST(CAST(expr))) type
                // expressions only simple CAST(expr) ones.
                inputVars_ += newIe->child(0)->getValueId();
              }
              else
              {
                // add the newIe itself if it was not a CAST.
                inputVars_ += newIe->getValueId();
              }
            }
          }
          else
          {
            // If the newIe doesn't contain the original one, we need to update
            // the inputVars set.
            if (! newIe->referencesTheGivenValue(
                    origIe->getValueId()), TRUE)
            {
              // the origIe was not a CAST introduced by UDFunction::bindNode()
              if (newIe->getOperatorType() == ITM_CAST) 
              {
                if (!origInputVars.contains(newIe->child(0)->getValueId()))
                {
                  inputVars_ -= origIe->getValueId();
                  // If the new expression is a CAST, we assume the child is the
                  // real input. We don't expect CAST(CAST(CAST(expr))) type
                  // expressions only simple CAST(expr) ones.
                  inputVars_ += newIe->child(0)->getValueId();
                }
                // we don't need to update inputVars_ if the origInputVars 
                // contains the valueId of the newIe child already.
              } 
              else
              {
                // This is an entirely new input. Remove the old one, and 
                // add in the new.
                inputVars_ -= origIe->getValueId();
                inputVars_ += newIe->getValueId();
              }
            }
          }
        }
      }
    }
  }

  markAsNormalizedForCache();
  return this;
}


// append an ascii-version of UDFunction into cachewa.qryText_
void UDFunction::generateCacheKey(CacheWA& cwa) const
{
  NARoutine *routine = NULL;
  NARoutine *action = NULL;

  cwa += " nam:"; 
  cwa += functionName_.getExternalName().data();
  if (cwa.getPhase() >= CmpMain::BIND && 
      getRoutineDesc() && 
      (routine=getRoutineDesc()->getNARoutine()) != NULL) 
  {
    char redefTime[40];
    convertInt64ToAscii(routine->getRedefTime(), redefTime);
    cwa += " redef:";
    cwa += redefTime;
  }

  if (getRoutineDesc() && 
      getRoutineDesc()->getActionNameAsGiven().length() != 0)
  {
    cwa += " actnam:"; 
    cwa += getRoutineDesc()->getActionNameAsGiven();

    if (cwa.getPhase() >= CmpMain::BIND && 
        getRoutineDesc() && 
        (action=getRoutineDesc()->getActionNARoutine()) != NULL) 
    {
      char redefTime[40];
      convertInt64ToAscii(action->getRedefTime(), redefTime);
      cwa += " actredef:";
      cwa += redefTime;
    }
  }

  cwa += "(";
  Lng32 arity =  (Lng32) getArity();
  for (Lng32 i = 0; i < arity; i++) {
    if (i > 0) {
      cwa += ", ";
    }
    child(i)->generateCacheKey(cwa);
  }
 
  if (getRoutineDesc()->getLocale() != 0 )
  {
    cwa += ", LOCALE: ";
    char dFmt[20]; 
    str_itoa(getRoutineDesc()->getLocale(), dFmt); 
    cwa += dFmt;
  }
  cwa += ")";
}

// is any literal in this expr safely coercible to its target type?
NABoolean UDFunction::isSafelyCoercible(CacheWA& cwa) const
{
  if (cwa.getPhase() >= CmpMain::BIND) {
    Int32 arity = getArity();
    for (Int32 x = 0; x < arity; x++) {
      if (!child(x)->isSafelyCoercible(cwa)) { 
        return FALSE; 
      }
    }
    return TRUE;
  }
  return FALSE;
}

// append an ascii-version of Subquery into cachewa.qryText_
void ValueIdProxy::generateCacheKey(CacheWA& cwa) const
{
  ItemExpr::generateCacheKey(cwa); 
  cwa += " tExp:";
  derivedFrom_.getItemExpr()->generateCacheKey(cwa);
}

// return true if ItemExpr & its descendants have no constants 
// and no noncacheable nodes
NABoolean ValueIdProxy::hasNoLiterals(CacheWA& cwa)
{
  return derivedFrom_.getItemExpr()->hasNoLiterals(cwa) && 
         derivedFrom_.getItemExpr()->isCacheableExpr(cwa);
}

// is any literal in this expr safely coercible to its target type?
NABoolean ValueIdProxy::isSafelyCoercible(CacheWA& cwa) const
{
  if (cwa.getPhase() >= CmpMain::BIND) {
      if (!derivedFrom_.getItemExpr()->isSafelyCoercible(cwa))
        return FALSE; 
      else
        return TRUE;
  }
  return FALSE;
}

// change literals of a cacheable query into ConstantParameters 
ItemExpr* ValueIdProxy::normalizeForCache(CacheWA& cwa, BindWA& bindWA)
{
  if (nodeIsNormalizedForCache()) { 
    return this; 
  }
  if (cwa.getPhase() == CmpMain::PARSE) {
    // we want to parameterize tuple inserts
    derivedFrom_ = derivedFrom_.getItemExpr()->normalizeForCache(cwa, bindWA)->getValueId();
  }
  else if (cwa.getPhase() == CmpMain::BIND) {
      if (derivedFrom_.getItemExpr()->isSafelyCoercible(cwa)) {
        // fix CR 10-010726-4109: make sure queries with constants that 
        // cannot be safely backpatched such as 
        //   select case smallintcol when 4294967393 then 'max' end from t
        // are not parameterized
        derivedFrom_ = derivedFrom_.getItemExpr()->normalizeForCache(cwa, bindWA)->getValueId();
      }
  }
  markAsNormalizedForCache();
  return this;
}

