// index access (both reference and value) ItemExpr * ItemExprTreeAsList::operator [] (CollIndex i) { // think of three different cases: // // a) i is out of range (< 0 or >= #entries) // // b) the node we are looking for is neither the only nor the last // node in the backbone // // c) we are looking for the last element in the backbone (which // may be the only element) // ItemExpr *aNodePtr = *treePtr_; Int32 j = (Int32) i; // j may become negative, i may be unsigned if (j < 0) return NULL; // case a if (aNodePtr->getOperatorType() != operator_ AND j == 0) return aNodePtr; // case b while (aNodePtr != NULL AND j >= 0) { if (aNodePtr->getOperatorType() == operator_ AND aNodePtr->getArity() >= 2) { if (shape_ == LEFT_LINEAR_TREE) { if (j == 0) aNodePtr = aNodePtr->child(1); // case b else aNodePtr = aNodePtr->child(0); } else if (shape_ == RIGHT_LINEAR_TREE) { if (j == 0) aNodePtr = aNodePtr->child(0); // case b else aNodePtr = aNodePtr->child(1); } else ABORT("can't do bushy trees"); } j--; } // if we are looking for the only element, the while loop // is not executed at all return aNodePtr; }
// check whether an element is in the collection NABoolean ItemExprTreeAsList::contains(const ItemExpr *treeToCheck) { ItemExpr *aNodePtr = *treePtr_; while (aNodePtr != NULL) { if (aNodePtr == treeToCheck) return TRUE; if (aNodePtr->getOperatorType() == operator_ AND aNodePtr->getArity() >= 2) { if (shape_ == RIGHT_LINEAR_TREE) aNodePtr = aNodePtr->child(1); else ABORT("can't do other than right-linear trees"); } else aNodePtr = NULL; } return FALSE; }
// return number of entries Lng32 ItemExprTreeAsList::entries() const { ItemExpr *aNode = *treePtr_; Lng32 result = 0; while (aNode != NULL) { result++; if (aNode->getOperatorType() == operator_ AND aNode->getArity() >= 2) { if (shape_ == LEFT_LINEAR_TREE) aNode = aNode->child(0); else if (shape_ == RIGHT_LINEAR_TREE) aNode = aNode->child(1); else ABORT("can't do other than right-linear trees"); } else aNode = NULL; } return result; }
// 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
void PhysSequence::computeReadNReturnItems( ValueId topSeqVid, ValueId vid, const ValueIdSet &outputFromChild, CollHeap *wHeap) { ItemExpr * itmExpr = vid.getItemExpr(); if (outputFromChild.contains(vid)) { return; } //test if itm_minus and then if negative offset .... if ( itmExpr->getOperatorType() == ITM_OFFSET && ((ItmSeqOffset *)itmExpr)->getOffsetConstantValue() < 0) { readSeqFunctions() -= topSeqVid; returnSeqFunctions() += topSeqVid; readSeqFunctions() += itmExpr->child(0)->castToItemExpr()->getValueId(); return; } if (itmExpr->getOperatorType() == ITM_MINUS) { ItemExpr * chld0 = itmExpr->child(0)->castToItemExpr(); if ( chld0->getOperatorType() == ITM_OFFSET && ((ItmSeqOffset *)chld0)->getOffsetConstantValue() <0) { readSeqFunctions() -= topSeqVid; returnSeqFunctions() += topSeqVid; readSeqFunctions() += chld0->child(0)->castToItemExpr()->getValueId(); ItemExpr * chld1 = itmExpr->child(1)->castToItemExpr(); if (chld1->getOperatorType() == ITM_OFFSET && ((ItmSeqOffset *)chld1)->getOffsetConstantValue() < 0) { readSeqFunctions() += chld1->child(0)->castToItemExpr()->getValueId(); } else { readSeqFunctions() += chld1->getValueId(); } return; } } if (itmExpr->getOperatorType() == ITM_OLAP_MIN || itmExpr->getOperatorType() == ITM_OLAP_MAX) { ItmSeqOlapFunction * olap = (ItmSeqOlapFunction *)itmExpr; if (olap->getframeEnd()>0) { readSeqFunctions() -= topSeqVid; returnSeqFunctions() += topSeqVid; ItemExpr *newChild = new(wHeap) Convert (itmExpr->child(0)->castToItemExpr()); newChild->synthTypeAndValueId(TRUE); itmExpr->child(0) = newChild; readSeqFunctions() += newChild->getValueId(); return; } } if (itmExpr->getOperatorType() == ITM_SCALAR_MIN || itmExpr->getOperatorType() == ITM_SCALAR_MAX) { ItemExpr * chld0 = itmExpr->child(0)->castToItemExpr(); ItemExpr * chld1 = itmExpr->child(1)->castToItemExpr(); if ((chld0->getOperatorType() == ITM_OLAP_MIN && chld1->getOperatorType() == ITM_OLAP_MIN )|| (chld0->getOperatorType() == ITM_OLAP_MAX && chld1->getOperatorType() == ITM_OLAP_MAX )) { ItmSeqOlapFunction * olap0 = (ItmSeqOlapFunction *)chld0; ItmSeqOlapFunction * olap1 = (ItmSeqOlapFunction *)chld1; if ( olap1->getframeEnd()>0) { CMPASSERT(olap0->getframeEnd()==0); readSeqFunctions() -= topSeqVid; returnSeqFunctions() += topSeqVid; readSeqFunctions() += olap0->getValueId(); ItemExpr *newChild = new(wHeap) Convert (olap1->child(0)->castToItemExpr()); newChild->synthTypeAndValueId(TRUE); olap1->child(0) = newChild; readSeqFunctions() += newChild->getValueId(); } else { CMPASSERT(olap1->getframeEnd()==0); readSeqFunctions() -= topSeqVid; returnSeqFunctions() += topSeqVid; readSeqFunctions() += olap1->getValueId(); ItemExpr *newChild = new(wHeap) Convert (olap0->child(0)->castToItemExpr()); newChild->synthTypeAndValueId(TRUE); olap0->child(0) = newChild; readSeqFunctions() += newChild->getValueId(); } return; } } for (Int32 i= 0 ; i < itmExpr->getArity(); i++) { ItemExpr * chld= itmExpr->child(i); computeReadNReturnItems(topSeqVid, chld->getValueId(), outputFromChild, wHeap); } }//void PhysSequence::computeReadNReturnItems(ItemExpr * other)
// remove an element that is given by its value ItemExpr * ItemExprTreeAsList::remove(ItemExpr *treeToRemove) { ItemExpr *andNodePtr = treePtr_->getPtr(); ItemExpr *predecessor = NULL; NABoolean found = FALSE; // assume the predicate is represented in right-linear // form: // // op // / \ // A op // / \ // B ... // // and search for the <op> node that is directly above the // predicate that we want to remove. if (shape_ != RIGHT_LINEAR_TREE) ABORT("delete is supported for right linear trees only"); // is the node to delete the only node? if (treeToRemove == andNodePtr) { found = TRUE; delete andNodePtr; *treePtr_ = NULL; } else // traverse the backbone looking for "treeToRemove" while (andNodePtr != NULL AND andNodePtr->getOperatorType() == operator_ AND andNodePtr->getArity() == 2 AND NOT found) { // did we find the right node? if (andNodePtr->child(0).getPtr() == treeToRemove) { found = TRUE; // take "andNode" out of the original tree if (predecessor != NULL) { predecessor->child(1) = andNodePtr->child(1); } else *treePtr_ = andNodePtr->child(1); // set all children of "andNode" to NULL, then delete it andNodePtr->child(0) = NULL; andNodePtr->child(1) = NULL; delete andNodePtr; andNodePtr = NULL; } else { predecessor = andNodePtr; andNodePtr = andNodePtr->child(1); } } if (found) return treeToRemove; else return NULL; }
// insert a new entry. // The new entry is created at the end of the current tree. void ItemExprTreeAsList::insert(ItemExpr *treeToInsert) { if (treePtr_->getPtr() == NULL) { *treePtr_ = treeToInsert; } else { if (shape_ == RIGHT_LINEAR_TREE) { switch (operator_) { case ITM_AND: *treePtr_ = new(CmpCommon::statementHeap()) BiLogic(operator_, treeToInsert, treePtr_->getPtr()); break; case ITM_ITEM_LIST: { ItemExpr *aNode = treePtr_->getPtr(); ItemExpr *pNode = treePtr_->getPtr(); if (aNode->getOperatorType() != operator_ AND aNode->getArity() < 2) { // case of current number of entries equal to 1. *treePtr_ = new(CmpCommon::statementHeap()) ItemList(treePtr_->getPtr(), treeToInsert); } else { // current number of entries > 1 while (aNode != NULL) { if (aNode->getOperatorType() == operator_ AND aNode->getArity() >= 2) { if (shape_ == RIGHT_LINEAR_TREE) { pNode = aNode; aNode = aNode->child(1); } else ABORT("can't do other than right-linear trees"); } else aNode = NULL; } pNode->child(1) = new(CmpCommon::statementHeap()) ItemList(pNode->child(1), treeToInsert); } } break; default: ABORT("Can't do backbones with this node type"); } } else ABORT("can only insert into right-linear trees"); } }