// is this entire expression cacheable after this phase? NABoolean MergeDelete::isCacheableExpr(CacheWA& cwa) { if ((insertValues_) && (insertValues_->isCacheableExpr(cwa))) { setNonCacheable(); return FALSE; } return Delete::isCacheableExpr(cwa); }
// is this entire expression cacheable after this phase? NABoolean Join::isCacheableExpr(CacheWA& cwa) { if (cwa.getPhase() >= CmpMain::BIND) { // must first descend to scans to get cwa.numberOfScans_ if (!RelExpr::isCacheableExpr(cwa)) { return FALSE; } if (isCacheableNode(cwa.getPhase())) { cwa.setConditionallyCacheable(); } // if we allow joins of views to be cached, query caching cannot // distinguish between (see note at bottom of cachewa.h) // select avg(f.a) from v f, v s group by f.b; // select avg(s.a) from v f, v s group by f.b; // select avg(t.a) from v f, t group by f.b; // assuming v is "create view v from select * from t". We avoid // false cache hits by detecting the possible occurrence of such // view joins here and later using cwa.isViewJoin_ to include // their query texts into their cache keys. // // A view is repsented by a renamed table with isView() returnning // TRUE. RelExpr *c0 = child(0); RelExpr *c1 = child(1); if ((c0->getOperatorType() == REL_RENAME_TABLE && ((RenameTable *)c0)->isView() == TRUE) || (c1->getOperatorType() == REL_RENAME_TABLE && ((RenameTable *)c1)->isView() == TRUE)) { cwa.foundViewJoin(); } // check its join predicate ItemExpr *pred = joinPredTree_ ? joinPredTree_ : joinPred_.rebuildExprTree(); if (pred) { cwa.setHasPredicate(); // is join predicate cacheable? if (pred->hasNoLiterals(cwa)) { // predicate with no literals is cacheable } else { cwa.setPredHasNoLit(FALSE); if (!pred->isCacheableExpr(cwa)) { // a non-cacheable predicate renders Join non-cacheable. setNonCacheable(); return FALSE; } } } return TRUE; // join may be cacheable } return FALSE; }
// is this entire expression cacheable after this phase? NABoolean RelExpr::isCacheableExpr(CacheWA& cwa) { switch (cwa.getPhase()) { case CmpMain::PARSE: 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; } if (isNonCacheable()) { // this node is not cacheable return FALSE; // so the entire expression is not cacheable // don't mark this node non-cacheable because this // RelExpr may be cacheable after the next phase. } if (isCacheableNode(cwa.getPhase())) { // must be an INSERT, UPDATE, DELETE, or SELECT node; // so, mark this expression as conditionally cacheable. cwa.setConditionallyCacheable(); } // must descend to scans to get cwa.numberOfScans_ if (!cacheableKids(cwa)) { return FALSE; } // this node is either cacheable or maybecacheable // check its selection predicate ItemExpr *pred = selPredTree() ? selPredTree() : getSelectionPred().rebuildExprTree(); if (pred) { cwa.setHasPredicate(); // is selection predicate cacheable? if (pred->hasNoLiterals(cwa)) { // predicate with no literals is cacheable } else { cwa.setPredHasNoLit(FALSE); if (!pred->isCacheableExpr(cwa)) { // a non-cacheable selection predicate // renders entire RelExpr non-cacheable. setNonCacheable(); return FALSE; } } } return TRUE; // RelExpr may be cacheable } default: { const NABoolean notYetImplemented = FALSE; CMPASSERT(notYetImplemented); return FALSE; } } }
// are RelExpr's kids cacheable after this phase? NABoolean RelExpr::cacheableKids(CacheWA& cwa) { switch (cwa.getPhase()) { case CmpMain::PARSE: case CmpMain::BIND: { Int32 arity = getArity(); if (arity <= 0) { // we have no kids if (cwa.isConditionallyCacheable()) { // we're conditionally cacheable and have no kids setCacheableNode(cwa.getPhase()); return TRUE; // so, we're cachable } else { return FALSE; // MAYBECACHEABLE is not cacheable at this phase // don't mark this node non-cacheable because this // RelExpr may be cacheable after the next phase. } } // cacheability of child(ren) determine our cacheability for (Int32 x = 0; x < arity; x++) { if (!child(x) || // cases like "insert into t default values" // return 1 from getArity() even if child(0) is NULL; so // guard against this potential mxcmp crash and consider // these cases non-cacheable during the PARSE stage. child(x)->isNonCacheable()) { // the 1st noncacheable child makes us noncacheable setNonCacheable(); return FALSE; } else if (!child(x)->isCacheableExpr(cwa)) { // noncacheable child return FALSE; // don't mark this node non-cacheable because this // RelExpr may be cacheable after the next phase. } else { // cacheable child continue; // look at next child } } // all children are cacheable, so we're cacheable too setCacheableNode(cwa.getPhase()); return TRUE; } default: return FALSE; } }
UnPackRows::UnPackRows(Lng32 maxPackingFactor, ItemExpr *rwrsInputSizeExpr, ItemExpr *rwrsMaxInputRowlenExpr, ItemExpr *rwrsBufferAddrExpr, RelExpr *child, CollHeap *oHeap) : RelExpr(REL_UNPACKROWS, child, NULL, oHeap), maxPackingFactor_(maxPackingFactor), unPackExprTree_(NULL), packingFactorTree_(NULL), unPackedTable_(NULL), indexValue_(NULL_VALUE_ID), sysKeyId_(NULL_VALUE_ID), originalPreds_(NULL), rewrittenPreds_(NULL), rowwiseRowset_(TRUE), rwrsInputSizeExpr_(rwrsInputSizeExpr), rwrsMaxInputRowlenExpr_(rwrsMaxInputRowlenExpr), rwrsBufferAddrExpr_(rwrsBufferAddrExpr) { setNonCacheable(); }
UnPackRows::UnPackRows(Lng32 maxPackingFactor, ItemExpr *unPackExprs, ItemExpr *packingFactor, TableDesc *unPackedTable, RelExpr *child, ValueId indexHostVarValueId, CollHeap *oHeap) : RelExpr(REL_UNPACKROWS, child, NULL, oHeap), maxPackingFactor_(maxPackingFactor), unPackExprTree_(unPackExprs), packingFactorTree_(packingFactor), unPackedTable_(unPackedTable), indexValue_(indexHostVarValueId), sysKeyId_(NULL_VALUE_ID), originalPreds_(NULL), rewrittenPreds_(NULL), rowwiseRowset_(FALSE), rwrsInputSizeExpr_(NULL), rwrsMaxInputRowlenExpr_(NULL), rwrsBufferAddrExpr_(NULL) { setNonCacheable(); }
// 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; }