Exemplo n.º 1
0
void ElemDDLUdfOptimizationHint::synthesize(void)
{
  if (getOptimizationKind() NEQ COM_UDF_NUMBER_OF_UNIQUE_OUTPUT_VALUES OR
      uniqueOutputValuesParseTree_ EQU NULL)
    return;

  NABoolean    isErrMsgIssued = FALSE;
  ComSInt64    value = 0;
  ItemExpr   * pItemExpr = NULL;
  ConstValue * pConstVal = NULL;
  for (CollIndex i = 0; i < uniqueOutputValuesParseTree_->entries(); i++)
  {
    pItemExpr = (*uniqueOutputValuesParseTree_)[i];
    pConstVal = (ConstValue *)pItemExpr;
    if (NOT pConstVal->canGetExactNumericValue() AND NOT isErrMsgIssued)
    {
      *SqlParser_Diags << DgSqlCode(-3017) << DgString0(pConstVal->getConstStr());
      isErrMsgIssued = TRUE;
    }
    value = pConstVal->getExactNumericValue();
    uniqueOutputValues_.insert(value);
    if (value < -1 AND NOT isErrMsgIssued) // only issue the error message once
    {
      // Error: Expected a positive value or -1 (representing the default SYSTEM setting option)
      NAString valueStr = Int64ToNAString(value);
      *SqlParser_Diags << DgSqlCode(-3017) << DgString0(valueStr);
      isErrMsgIssued = TRUE;
    }
  } // for
} // ElemDDLUdfOptimizationHint::synthesize()
// ItmSeqOffset::preCodeGen
//
// Casts the second child to SqlInt.
//
ItemExpr *ItmSeqOffset::preCodeGen(Generator *generator)
{
  if (nodeIsPreCodeGenned())
    return this;
  
  CollHeap *wHeap = generator->wHeap();

  // The following code is being disabled (0 && ...) since it will
  // sometimes incorrectly think that the output of a tuple list of
  // contants is a single constant.  For example:
  //   SELECT a, b, c, MOVINGSUM(c,b) as MSUM, MOVINGAVG(c,b) as MAVG
  //   FROM (values
  //             (1,1, 1),
  //             (2,0, 2),
  //             (3,2, NULL),
  //             (4,0, 6),
  //             (5,3, 7)) as T(a,b,c)
  //   SEQUENCE BY a;
  //
  // For this query it will think that the offset index (b) is a
  // constant and it will use the value 3 for the
  // offsetConstantValue_.
  //
  if (0 && getArity() > 1)
  {
    NABoolean negate;
    ConstValue *cv = child(1)->castToConstValue(negate);
    if (cv AND cv->canGetExactNumericValue())
      {
        Lng32 scale;
        Int64 value = cv->getExactNumericValue(scale);

        if(scale == 0 && value >= 0 && value < INT_MAX) 
          {
            value = (negate ? -value : value);
            offsetConstantValue_ = (Int32)value;
            child(1) = NULL;
          }
      }
  }
    
  if (getArity() > 1)
  {

    const NAType &cType = child(1)->getValueId().getType();

    // (must be) signed; nulls allowed (if allowed by child1)   
   ItemExpr *castExpr   = new (wHeap) Cast (child(1),
                                           new (wHeap)
                                           SQLInt(wHeap, TRUE, cType.supportsSQLnullLogical()));
   castExpr->synthTypeAndValueId(TRUE);
   child (1) = castExpr;
  }
  return ItemExpr::preCodeGen(generator);
}
// computeHistoryBuffer
//
// Helper function that traverses the set of root sequence functions
// supplied by the compiler and dynamically determines the size
// of the history buffer.
// 
void PhysSequence::computeHistoryRows(const ValueIdSet &sequenceFunctions,//historyIds
                                      Lng32 &computedHistoryRows,
                                      Lng32 &unableToCalculate,
                                      NABoolean &unboundedFollowing, 
                                      Lng32 &minFollowingRows,
                                      const ValueIdSet &outputFromChild) 
{
  ValueIdSet children;
  ValueIdSet historyAttributes;
  Lng32 value = 0;

  for(ValueId valId = sequenceFunctions.init();
      sequenceFunctions.next(valId);
      sequenceFunctions.advance(valId)) 
  {
    if(valId.getItemExpr()->isASequenceFunction()) 
    {
      ItemExpr *itmExpr = valId.getItemExpr();

      switch(itmExpr->getOperatorType())
        {

        // THIS and NOT THIS are not dynamically computed
        //
        case ITM_THIS:
        case ITM_NOT_THIS:
          break;

        // The RUNNING functions and LastNotNull all need to go back just one row.
        //
        case ITM_RUNNING_SUM:
        case ITM_RUNNING_COUNT:
        case ITM_RUNNING_MIN:
        case ITM_RUNNING_MAX:
        case ITM_RUNNING_CHANGE:   
        case ITM_LAST_NOT_NULL:
          computedHistoryRows = MAXOF(computedHistoryRows, 2);
          break;
        ///set to unable to compute for now-- will change later to compte values from frameStart_ and frameEnd_
        case ITM_OLAP_SUM:
        case ITM_OLAP_COUNT:
        case ITM_OLAP_MIN:
        case ITM_OLAP_MAX:
        case ITM_OLAP_RANK:
        case ITM_OLAP_DRANK:
        {
          if ( !outputFromChild.contains(itmExpr->getValueId()))
          {
            ItmSeqOlapFunction * olap = (ItmSeqOlapFunction*)itmExpr;

            if (olap->isFrameStartUnboundedPreceding()) //(olap->getframeStart() == - INT_MAX)
            {
              computedHistoryRows = MAXOF(computedHistoryRows, 2);
            }
            else
            {
              computedHistoryRows = MAXOF(computedHistoryRows, ABS(olap->getframeStart()) + 2);
            }
            if (!olap->isFrameEndUnboundedFollowing()) //(olap->getframeEnd() != INT_MAX)
            {
              computedHistoryRows = MAXOF(computedHistoryRows, ABS(olap->getframeEnd()) + 1);
            }

            if (olap->isFrameEndUnboundedFollowing()) //(olap->getframeEnd() == INT_MAX)
            {
              unboundedFollowing = TRUE;
              if (olap->getframeStart() > 0) 
              {
                minFollowingRows = ((minFollowingRows > olap->getframeStart()) ?  
                                    minFollowingRows : olap->getframeStart());
              }
            } else  if (olap->getframeEnd() > 0)
            {
              minFollowingRows = ((minFollowingRows > olap->getframeEnd()) ?  
                                  minFollowingRows : olap->getframeEnd());
            }
          }
        }

        break;

        // If 'rows since', we cannot determine how much history is needed.  
        case ITM_ROWS_SINCE:
          unableToCalculate = 1;
          break;

        // The MOVING and OFFSET functions need to go back as far as the value
        // of their second child.
        //
        //  The second argument can be:
        //    Constant: for these, we can use the constant value to set the upper bound
        //              for the history buffer.
        //    ItmScalarMinMax(child0, child1) (with operType = ITM_SCALAR_MIN)  
        //      - if child0 or child1 is a constant, then we can use either one
        //        to set the upper bound.
        
        case ITM_MOVING_MIN:
        case ITM_MOVING_MAX:
        case ITM_OFFSET:
         
          for(Lng32 i = 1; i < itmExpr->getArity(); i++)
          {
            if (itmExpr->child(i)->getOperatorType() != ITM_NOTCOVERED)
            {
              ItemExpr * exprPtr = itmExpr->child(i);
              NABoolean negate;
              ConstValue *cv = exprPtr->castToConstValue(negate);
              if (cv AND cv->canGetExactNumericValue())
                {
                  Lng32 scale;
                  Int64 value64 = cv->getExactNumericValue(scale);

                  if(scale == 0 && value64 >= 0 && value64 < INT_MAX) 
                    {
                      value64 = (negate ? -value64 : value64);
                      value = MAXOF((Lng32)value64, value);
                    }
                 }
              else
                {
                  if (exprPtr->getOperatorType() == ITM_SCALAR_MIN)
                    {
                      for(Lng32 j = 0; j < exprPtr->getArity(); j++)
                        {
                          if (exprPtr->child(j)->getOperatorType()
                            != ITM_NOTCOVERED)
                            {
                               ItemExpr * exprPtr1 = exprPtr->child(j);
                               NABoolean negate1;
                               ConstValue *cv1 = exprPtr1->castToConstValue(negate1);
                               if (cv1 AND cv1->canGetExactNumericValue())
                                 {
                                   Lng32 scale1;
                                   Int64 value64_1 = cv1->getExactNumericValue(scale1);

                                   if(scale1 == 0 && value64_1 >= 0 && value64_1 < INT_MAX) 
                                     {
                                       value64_1 = (negate1 ? -value64_1 : value64_1);
                                       value = MAXOF((Lng32)value64_1, value);
                                     }
                                  }
                              }
                          }   
                     }   
                }  // end of inner else
            }// end of if

          }// end of for

          // Check if the value is greater than zero.
          // If it is, then save the value, but first
          // increment the returned ConstValue by one.
          // Otherwise, the offset or moving value was unable
          // to be calculated.

          if (value > 0)
          {
            value++;
            computedHistoryRows = MAXOF(computedHistoryRows, value);
            value = 0;
          }
          else
            unableToCalculate = 1;

          break;

        default:
          CMPASSERT(0);
        }
    }
   
    // Gather all the children, and if not empty, recurse down to the
    // next level of the tree.
    //

    for(Lng32 i = 0; i < valId.getItemExpr()->getArity(); i++) {
      if (//valId.getItemExpr()->child(i)->getOperatorType() != ITM_NOTCOVERED //old stuff
          !outputFromChild.contains(valId.getItemExpr()->child(i)->getValueId()))
      {
        children += valId.getItemExpr()->child(i)->getValueId();
      }
    }
  }
  
  if (NOT children.isEmpty())
  {
    computeHistoryRows(children, 
                       computedHistoryRows, 
                       unableToCalculate, 
                       unboundedFollowing, 
                       minFollowingRows,
                       outputFromChild);  
  }
} // PhysSequence::computeHistoryRows