Exemplo n.º 1
0
// 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;
}