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