Exemplo n.º 1
0
// append an ascii-version of UDFunction into cachewa.qryText_
void UDFunction::generateCacheKey(CacheWA& cwa) const
{
  NARoutine *routine = NULL;
  NARoutine *action = NULL;

  cwa += " nam:"; 
  cwa += functionName_.getExternalName().data();
  if (cwa.getPhase() >= CmpMain::BIND && 
      getRoutineDesc() && 
      (routine=getRoutineDesc()->getNARoutine()) != NULL) 
  {
    char redefTime[40];
    convertInt64ToAscii(routine->getRedefTime(), redefTime);
    cwa += " redef:";
    cwa += redefTime;
    if ((routine->getSchemaLabelFileName()) &&
        (str_len(routine->getSchemaLabelFileName()) > 0)) 
    {
      char schRedefTime[40];
      convertInt64ToAscii(routine->getSchemaRedefTime(), schRedefTime);
      cwa += " schredef:";
      cwa += schRedefTime;
    }
  }

  if (getRoutineDesc() && 
      getRoutineDesc()->getActionNameAsGiven().length() != 0)
  {
    cwa += " actnam:"; 
    cwa += getRoutineDesc()->getActionNameAsGiven();

    if (cwa.getPhase() >= CmpMain::BIND && 
        getRoutineDesc() && 
        (action=getRoutineDesc()->getActionNARoutine()) != NULL) 
    {
      char redefTime[40];
      convertInt64ToAscii(action->getRedefTime(), redefTime);
      cwa += " actredef:";
      cwa += redefTime;
    }
  }

  cwa += "(";
  Lng32 arity =  (Lng32) getArity();
  for (Lng32 i = 0; i < arity; i++) {
    if (i > 0) {
      cwa += ", ";
    }
    child(i)->generateCacheKey(cwa);
  }
 
  if (getRoutineDesc()->getLocale() != 0 )
  {
    cwa += ", LOCALE: ";
    char dFmt[20]; 
    str_itoa(getRoutineDesc()->getLocale(), dFmt); 
    cwa += dFmt;
  }
  cwa += ")";
}
Exemplo n.º 2
0
// is this entire expression cacheable after this phase?
NABoolean Scan::isCacheableExpr(CacheWA& cwa)
{
  if (cwa.getPhase() >= CmpMain::BIND) {
    // save scan's TableDesc
    cwa.incNofScans(tabId_);

    // native hbase access is not cacheable for now.
    if ((getTableDesc()->getNATable()->isHbaseRowTable()) ||
	(getTableDesc()->getNATable()->isHbaseCellTable()))
      return FALSE;

    if (stream_) { // pub-sub streams are not cacheable
      return FALSE;
    }
    // mpalias SELECT is not cacheable unless explicitly requested
    if (getTableDesc()->getNATable()->isAnMPTableWithAnsiName() &&
        CmpCommon::getDefault(QUERY_CACHE_MPALIAS) == DF_OFF) {
      return FALSE;
    }
    cwa.setConditionallyCacheable(); 
    if (CmpCommon::getDefaultLong(MVQR_REWRITE_LEVEL) >= 1 &&
        QRDescGenerator::hasRewriteEnabledMVs(getTableDesc())) {
      cwa.setRewriteEnabledMV();
    }
    return RelExpr::isCacheableExpr(cwa);
  }
  return FALSE;
}
Exemplo n.º 3
0
// Only alow UDFunctions to be cached after BIND time.
NABoolean UDFunction::isCacheableExpr(CacheWA& cwa)
{ 
  if (cwa.getPhase() >= CmpMain::BIND) 
    return TRUE;
  else 
    return FALSE; 
}
Exemplo n.º 4
0
// is any literal in this expr safely coercible to its target type?
NABoolean ItemExpr::isSafelyCoercible(CacheWA &cwa) const
{
  if (cwa.getPhase() >= CmpMain::BIND) {
    Int32 arity = getArity();
    for (Int32 x = 0; x < arity; x++) {
      if (!child(x)->isSafelyCoercible(cwa)) { 
        return FALSE; 
      }
    }
    if (arity == 2) {
      // we have to disallow caching of the following types of exprs:
      //   expr + 123456789012345678901234567890
      //   expr || 'overlylongstringthatwouldoverflow'
      ItemExpr *left = child(0), *right = child(1);
      if (left->getOperatorType() == ITM_CONSTANT) {
        if (right->getOperatorType() == ITM_CONSTANT) {
          // "10 + 1" should be safely coercible
          return TRUE;
        } else {
          return ((ConstValue*)left)->canBeSafelyCoercedTo
            (right->getValueId().getType());
        }
      }      
      else if (right->getOperatorType() == ITM_CONSTANT) {
        return ((ConstValue*)right)->canBeSafelyCoercedTo
          (left->getValueId().getType());
      }      
      // else both are nonliterals; fall thru
    }
    // else nondyadic expr; fall thru
    return TRUE; 
  }
  return FALSE;
}
Exemplo n.º 5
0
// we want BiLogic to be cacheable
NABoolean BiLogic::isCacheableExpr(CacheWA& cwa)
{
  if (cwa.getPhase() >= CmpMain::BIND && getArity() == 2) {
    if (getOperatorType() == ITM_AND) {
      ItemExpr *leftC=child(0), *rightC=child(1);
      // we want to descend to both left & right
      // so cwa.usedKeys & cwa.keyCols get updated
      NABoolean leftOK = leftC->isCacheableExpr(cwa);
      NABoolean rightOK = rightC->isCacheableExpr(cwa);
      // return FALSE if both left & right are not cacheable.
      if (!leftOK && !rightOK) 
        return FALSE;

      // allow "select * from t where k1=1 and k2=2" as potentially cacheable
      return TRUE;
      // the definitive check whether a query's predicate covers
      // all referenced tables' key columns can be (and is) done
      // only in RelRoot::isCacheableExpr() when cwa.usedKeys &
      // cwa.keyCols are fully defined. Otherwise, queries like
      //   "select * from t1 join t2 on a=x and a=7 where x=7"
      // may be incorrectly rejected as non-cacheable if t1 has
      // primary key(a) and t2 has primary key(x).
    }
    else if (getOperatorType() == ITM_OR) {
      return TRUE;
      // ORs can be cacheable but are not necessarily
      // parameterizable, see Bilogic::normalizeForCache below.
    }
  }
  return FALSE;
}
Exemplo n.º 6
0
// 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;
  }
}
Exemplo n.º 7
0
// append an ascii-version of IsolatedScalarUDF into cachewa.qryText_
void IsolatedScalarUDF::generateCacheKey(CacheWA &cwa) const
{
  NARoutine *routine = NULL;
  NARoutine *action = NULL;

  RelExpr::generateCacheKey(cwa);

  cwa += " UDFname:";
  cwa += getRoutineName().getQualifiedNameAsAnsiString().data();
  if (cwa.getPhase() >= CmpMain::BIND &&
      getRoutineDesc() &&
      (routine=getRoutineDesc()->getNARoutine()) != NULL)
  {
    char redefTime[40];
    convertInt64ToAscii(routine->getRedefTime(), redefTime);
    cwa += " redef:";
    cwa += redefTime;
  }

  if (getRoutineDesc() != NULL && getRoutineDesc()->isUUDFRoutine())
  {
    cwa += " action:";
    cwa += getRoutineDesc()->getActionNameAsGiven();

    if (cwa.getPhase() >= CmpMain::BIND &&
       getRoutineDesc() &&
       (action=getRoutineDesc()->getActionNARoutine()) != NULL)
    {
       char redefTime[40];
       convertInt64ToAscii(action->getRedefTime(), redefTime);
       cwa += " actredef:";
       cwa += redefTime;
    }
  }

  const ItemExpr *paramExpr = (getProcAllParamsTree() == NULL) ? 
                      getProcInputParamsVids().rebuildExprTree(ITM_ITEM_LIST) :
                      getProcAllParamsTree(); 
  if (paramExpr)
  { 
    cwa += " arg:(";
    paramExpr->generateCacheKey(cwa); 
    cwa += ")";
  }
}
Exemplo n.º 8
0
// is any literal in this expr safely coercible to its target type?
NABoolean ValueIdProxy::isSafelyCoercible(CacheWA& cwa) const
{
  if (cwa.getPhase() >= CmpMain::BIND) {
      if (!derivedFrom_.getItemExpr()->isSafelyCoercible(cwa))
        return FALSE; 
      else
        return TRUE;
  }
  return FALSE;
}
Exemplo n.º 9
0
// does this ItemExpr (dis)qualify query to be cacheable after this phase?
NABoolean ConstValue::isCacheableExpr(CacheWA& cwa)
{
  if (cwa.getPhase() <= CmpMain::PARSE && hasUnknownCharSet()) {
    // string literal with unknown character set cannot be considered
    // cacheable by pre-binder stages because the information needed
    // to determine their character set is not known until bind-time.
    // This fixes genesis case 10-041215-6141, soln 10-041215-2826.
    return FALSE;
  }
  return ItemExpr::isCacheableExpr(cwa);
}
Exemplo n.º 10
0
// we want BiRelat to be cacheable
NABoolean BiRelat::isCacheableExpr(CacheWA& cwa)
{
  if (cwa.getPhase() >= CmpMain::BIND && getArity() == 2) {
    if (getOperatorType() == ITM_EQUAL) {
      ItemExpr *leftC=child(0), *rightC=child(1);
      OperatorTypeEnum leftO = leftC->getOperatorType();
      OperatorTypeEnum rightO = rightC->getOperatorType();
      BaseColumn *base;
      if (leftO == ITM_BASECOLUMN) {
        base = (BaseColumn*)leftC;
        if (base->isKeyColumnValue(*rightC)) {
          cwa.addToUsedKeys(base);
        }
        return TRUE;
      }
      else if (rightO == ITM_BASECOLUMN) {
        base = (BaseColumn*)rightC;
        if (base->isKeyColumnValue(*leftC)) {
          cwa.addToUsedKeys(base);
        }
        return TRUE;
      }
      else if (leftO == ITM_ITEM_LIST && rightO == ITM_ITEM_LIST &&
               ((ItemList*)leftC)->isListOfCacheableSelPred
               (cwa, (ItemList*)rightC)) {
        return TRUE;
      }
      else {
        // we want all other equality comparisons to be cacheable, eg,
        // retail_div_cd||acct_type_cd||substring(acct_id,1,8)='20V43085193'
        return TRUE;
      }
    }
    else {
      return TRUE;
      // other binary comparison predicates can be cacheable, but are
      // not necessarily parameterizable, see BiRelat::normalizeForCache
    }
  }
  return FALSE;
}
Exemplo n.º 11
0
// does this query's selection predicate list qualify query 
// to be cacheable after this phase?
NABoolean ItemList::isListOfCacheableSelPred
(CacheWA& cwa, ItemList *other) const
{
  Int32 arity = getArity();
  NABoolean result = FALSE;
  if (cwa.getPhase() >= CmpMain::BIND && 
      other && arity == other->getArity()) {
    // assume this is an AND list, so, we need only one
    // cacheable conjunct to consider the list cacheable.
    for (Int32 x = 0; x < arity; x++) {
      ItemExpr *leftC = child(x), *rightC = other->child(x);
      OperatorTypeEnum leftO = leftC->getOperatorType();
      OperatorTypeEnum rightO = rightC->getOperatorType();
      BaseColumn *base;
      if (leftO == ITM_BASECOLUMN) {
        base = (BaseColumn*)leftC;
        if (base->isKeyColumnValue(*rightC)) {
          cwa.addToUsedKeys(base);
        }
        result = TRUE;
        continue;
      }
      else if (rightO == ITM_BASECOLUMN) {
        base = (BaseColumn*)rightC;
        if (base->isKeyColumnValue(*leftC)) {
          cwa.addToUsedKeys(base);
        }
        result = TRUE;
        continue;
      }
      else if (leftO == ITM_ITEM_LIST && rightO == ITM_ITEM_LIST &&
               ((ItemList*)leftC)->isListOfCacheableSelPred
               (cwa, (ItemList*)rightC)) {
        result = TRUE;
        continue;
      }
    }
  }
  return result;
}
Exemplo n.º 12
0
// helper to change literals of a cacheable query into input parameters
void BiRelat::parameterizeMe(CacheWA& cwa, BindWA& bindWA, ExprValueId& child,
                             BaseColumn *base, ConstValue *val)
{
  NABoolean parameterizableMVQRplan = cwa.hasRewriteEnabledMV() && 
    CmpCommon::getDefault(MVQR_PARAMETERIZE_EQ_PRED) == DF_ON;
  NABoolean parameterizablePlan = parameterizableMVQRplan || 
    !cwa.hasRewriteEnabledMV();

  if (val->isNull()) {
    // val is null; keep null as is.
    // this is part of a fix to genesis case: 10-010618-3484.
  }
  else if (base->isKeyColumnValue(*val) // keyCol = constant
           && cwa.isParameterizable(base) && parameterizablePlan) {
    cwa.replaceWithNewOrOldConstParam(val, base->getNAColumn()->getType(),
                                      child, bindWA);
    if (parameterizableMVQRplan)
      cwa.setParameterizedPred(TRUE);
  }
  else if (!base->canSafelyCoerce(*val)) {
    // term is not parameterizable, keep it as is.
  }
  else { // nonKeyCol = constant
    if (parameterizablePlan) {
      computeAndAddSelParamIfPossible(cwa, bindWA, child, base, val);
      if (parameterizableMVQRplan)
        cwa.setParameterizedPred(TRUE);
    }
  }
}
Exemplo n.º 13
0
// is any literal in this expr safely coercible to its target type?
NABoolean UDFunction::isSafelyCoercible(CacheWA& cwa) const
{
  if (cwa.getPhase() >= CmpMain::BIND) {
    Int32 arity = getArity();
    for (Int32 x = 0; x < arity; x++) {
      if (!child(x)->isSafelyCoercible(cwa)) { 
        return FALSE; 
      }
    }
    return TRUE;
  }
  return FALSE;
}
Exemplo n.º 14
0
// is any literal in this expr safely coercible to its target type?
NABoolean Cast::isSafelyCoercible(CacheWA &cwa) const
{
  if (cwa.getPhase() >= CmpMain::BIND) {
    ItemExpr *opd = child(0);
    if (!opd->isSafelyCoercible(cwa)) { 
      return FALSE; 
    }
    if (opd->getOperatorType() == ITM_CONSTANT) {
      return ((ConstValue*)opd)->canBeSafelyCoercedTo(*type_);
    }      
    return TRUE; 
  }
  return FALSE;
}
Exemplo n.º 15
0
// is this entire expression cacheable after this phase?
NABoolean RelRoot::isCacheableExpr(CacheWA& cwa)
{
  //queries prefixed by display are not cacheable e.g. display select * from ...
  if(getDisplayTree())
    return FALSE;
  
  // Parallel extract producer queries are not cacheable
  if (numExtractStreams_ > 0)
    return FALSE;

  // descend to scans early to get cwa.numberOfScans_ 
  if (!RelExpr::isCacheableExpr(cwa)) {
    return FALSE;
  }
  if (cwa.getPhase() == CmpMain::PARSE) {
    if (compExprTree_ || compExpr_.entries() > 0) {
      // insert-returning is not cacheable after parse
      return FALSE; 
    }
  }
  else if (cwa.getPhase() >= CmpMain::BIND) {
    // make sure select list is cacheable
    if (compExprTree_) {
      if (!compExprTree_->isCacheableExpr(cwa)) { 
        return FALSE; 
      }
    }
    else if (!compExpr_.isCacheableExpr(cwa)) {
      return FALSE;
    }
  }

  if (isAnalyzeOnly())
    return FALSE;

  return TRUE;
}
Exemplo n.º 16
0
void computeAndAddSelParamIfPossible(
             CacheWA& cwa, BindWA& bindWA, ExprValueId& child,
             BaseColumn *base, ConstValue *val)
{
    ColStatsSharedPtr cStatsPtr = (base->getTableDesc()->tableColStats()).
                             getColStatsPtrForColumn(base->getValueId());

    if (cStatsPtr == NULL )
        return;

    HistogramSharedPtr hist = cStatsPtr->getHistogram();

    if ( hist == NULL )
       return;

    CostScalar sel;
    NABoolean canComputeSelectivity = hist -> computeSelectivityForEquality(
            val, cStatsPtr->getRowcount(), cStatsPtr->getTotalUec(),
            sel);

    if ( canComputeSelectivity == TRUE ) {
      const NAType * newType = base->getNAColumn()->getType();

      // for char datatypes, assign the caseinsensitive attribute from
      // the const node.
      if (newType->getTypeQualifier() == NA_CHARACTER_TYPE)
	{
	  newType = 
	    base->getNAColumn()->getType()->newCopy(cwa.wHeap());
	  ((CharType*)newType)->setCaseinsensitive(((CharType*)val->getType())->isCaseinsensitive());
	}
      
      cwa.replaceWithNewOrOldSelParam(val, newType, Selectivity(sel), 
                                      child, bindWA);

    }
}
Exemplo n.º 17
0
// 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;
}
Exemplo n.º 18
0
// 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;
    }
  }
}
Exemplo n.º 19
0
// append an ascii-version of Insert into cachewa.qryText_
void Insert::generateCacheKey(CacheWA &cwa) const
{
  GenericUpdate::generateCacheKey(cwa);
  if (insertColTree_) { 
    cwa += " insCol:"; 
    insertColTree_->generateCacheKey(cwa); 
  }
  // order by clause is important
  ItemExpr *orderBy = orderByTree_ ? orderByTree_ :
    reqdOrder_.rebuildExprTree();
  if (orderBy) { 
    cwa += " order:"; 
    orderBy->generateCacheKey(cwa); 
  }

  const NATable *tbl;
  if (cwa.getPhase() >= CmpMain::BIND && 
      getTableDesc() && (tbl=getTableDesc()->getNATable()) != NULL) {
    // If PARTITION clause has been used we must reflect that in the key.
    if (tbl->isPartitionNameSpecified()) {
      cwa += " partition:";
      cwa += tbl->getClusteringIndex()->getFileSetName().getQualifiedNameAsString().data();
    }
    // If PARTITION range has been used we must reflect that in the key.
    else if (tbl->isPartitionRangeSpecified()) {
      cwa += " partition:";

      char str[100];
      sprintf(str, " from %d to %d", 
	      tbl->getExtendedQualName().getPartnClause().getBeginPartitionNumber() ,
	      tbl->getExtendedQualName().getPartnClause().getEndPartitionNumber());
      cwa += str;
    }
  }

  if (isUpsert())
    {
      cwa += " upsert:";
    }
}
Exemplo n.º 20
0
// is any literal in this expr safely coercible to its target type?
NABoolean Assign::isSafelyCoercible(CacheWA &cwa) const
{
  if (cwa.getPhase() >= CmpMain::BIND) {
    // we have to disallow caching of the following types of updates:
    //   update t set col = overlylongliteral
    ItemExpr *src = getSource().getItemExpr();
    if (src->getOperatorType() == ITM_CONSTANT) {
      // source is a literal; make sure this update is cacheable only if
      // literal can be safely coerced into its target type.
      return ((ConstValue*)src)->canBeSafelyCoercedTo(getTarget().getType());
    }      
    else { // source is not a literal
      // we need to descend into this expr to verify that no 
      // errors can occur during backpatching. For example, 
      //   update t set i = i + 123456789012345678901234567890
      // should not be cacheable if i is a smallint.
      // reject "update t set c=(subquery)" as noncacheable
      // as part of a fix to CR 10-020108-8401.
      return src->isSafelyCoercible(cwa) && src->isCacheableExpr(cwa);
    }
  }
  return FALSE;
}
Exemplo n.º 21
0
// is this entire expression cacheable after this phase?
NABoolean GenericUpdate::isCacheableExpr(CacheWA& cwa)
{
  // descend to scans early to get cwa.numberOfScans_ 
  if (!RelExpr::isCacheableExpr(cwa)) {
    return FALSE;
  }

  // Make "{update|delete} ... where current of cursor" non-cacheable
  // so that stale cache will not lead to timestamp mismatch error at
  // runtime.  AQR attempts to handle this error, but only after the 
  // referenced cursor is closed due to transaction rollback.  This is
  // Solution 10-100425-9755.
  if (currOfCursorName()) { 
    return FALSE; 
  }

  if (cwa.getPhase() >= CmpMain::BIND) {
    // make sure any literals in the assignment clause can be safely
    // cast and assigned to their target types at plan-backpatch-time
    ItemExpr *newExpr = newRecExprTree_ ? newRecExprTree_ :
      newRecExpr_.rebuildExprTree(ITM_ITEM_LIST);
    if (newExpr && !newExpr->isSafelyCoercible(cwa)) { 
      return FALSE; 
    }
    // reject as non-cacheable queries such as
    //   prepare s from select * from (update t042qT8 set b=7 
    //   set on rollback c=12345678901234567890 where a=2) as t;
    ItemExpr *setOnRollback;
    if (newRecBeforeExpr_.entries() > 0 &&
        (setOnRollback=newRecBeforeExpr_.rebuildExprTree(ITM_ITEM_LIST)) 
        && !setOnRollback->isSafelyCoercible(cwa)) {
      return FALSE; 
    }
    // make sure any executor predicate is cacheable
    ItemExpr *execPred = executorPredTree_ ? executorPredTree_ :
      executorPred_.rebuildExprTree();
    if (execPred) {
      cwa.setHasPredicate();
      if (execPred->hasNoLiterals(cwa)) {
        // predicate with no literals is cacheable
      }
      else {
        cwa.setPredHasNoLit(FALSE);
        return execPred->isCacheableExpr(cwa);
      }
    }

    // at this time, not cacheable if subquery is specified in 
    // UPDATE SET clause.
    // This could be enabled later.
    if (subqInUpdateAssign()) {
      return FALSE;
    }
  }
  else {
    if ((getTableName().isPartitionNameSpecified()) ||
	(getTableName().isLocationNameSpecified()) ||
	(getTableName().isPartitionRangeSpecified()))
      return FALSE; // If PartnClause is used no cache hit before bind stage.
  }
  return TRUE; // may be cacheable
}
Exemplo n.º 22
0
// 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;
}
Exemplo n.º 23
0
// does this entire ItemExpr qualify query to be cacheable after this phase?
NABoolean DynamicParam::isCacheableExpr(CacheWA& cwa)
{
  // a dynamic parameter is not cacheable after parse
  return (cwa.getPhase() <= CmpMain::PARSE) ? FALSE : TRUE;
}
Exemplo n.º 24
0
// append an ascii-version of GenericUpdate into cachewa.qryText_
void GenericUpdate::generateCacheKey(CacheWA& cwa) const
  // NB: This comment applies to all generateCacheKey methods. 
  // generateCacheKey is used to generate a string representation s of the
  // "parameterized" query. Since this string s is used by QCache::lookUp
  // to determine if a query is in the cache, it is essential that:
  //   (1) two different queries have different string representations
  //   (2) two queries that differ only in their query literals should
  //       have the same string representations
  // One possible implementation of generateCacheKey is to use the query's
  // original query text. But, original query text does not satisfy (2). 
  // To get (2), we call generateCacheKey() from RelRoot::normalizeForCache
  // which, by definition, replaced query literals with constant parameters.
  // However, generateCacheKey must also satisfy (1). generateCacheKey must
  // generate two different strings for two logically different queries.
  //
  // To satisfy requirements (1) and (2), generateCacheKey and
  // normalizeForCache must be in sync -- every user-specified expr that 
  // generateCacheKey emits into cwa.qryText_ must be examined by 
  // normalizeForCache for possible replacement of any literal there into 
  // a constant parameter. 
  //
  // In order for the literal-into-constantparameter replacement to be safe,
  // isCacheableExpr must visit all user-specified exprs to make sure that
  // only constants that can be safely cast into the query's target types
  // are considered cacheable. For example, given this update query
  //   update t set a = 'xyz' where pk = 1;
  // isCacheableeExpr, normalizeForCache, and generateCacheKey must cooperate
  // so that:
  // 1) isCacheableExpr rejects the query as noncacheble if 'xyz' cannot be
  //    safely cast into a's target type, eg, 'xyz' may be too long if a's
  //    type is char(1).
  // 2) normalizeForCache must visit and replace both 'xyz' and 1 with
  //    appropriate constant parameters.
  // 3) generateCacheKey must emit some string representation of the
  //    parameterized query, eg, "update t set a = % where pk = %".
  //    generateCacheKey can emit more stuff, eg, internally specified
  //    begin/end-key predicates, but it must emit a string representation
  //    of all user-specified parts of the query.
{
  // append to cwa.qryText_ GenericUpdate's "essential" data members
  RelExpr::generateCacheKey(cwa);
  // An extension of the fix to 10-010618-3505, 10-010619-3515: 
  // for "after bind" Insert/Update/Delete queries, include table's 
  // RedefTime into cwa.qryText_ to make sure we get a cache hit only on 
  // query that reference table(s) that have not changed since the query's 
  // addition to the cache. The queries that reference altered table(s) 
  // will never be hit again and will eventually age out of the cache.
  // This is not strictly necessary, but it speeds up the processing
  // of insert/update/delete queries on altered tables.
  const NATable *tbl;
  if (cwa.getPhase() >= CmpMain::BIND && 
      getTableDesc() && (tbl=getTableDesc()->getNATable()) != NULL) {
    char redefTime[40];
    convertInt64ToAscii(tbl->getRedefTime(), redefTime);
    cwa += " redef:";
    cwa += redefTime;
  }
  ItemExpr *newExpr = newRecExprTree_ ? newRecExprTree_ :
    newRecExpr_.rebuildExprTree(ITM_ITEM_LIST);
  if (newExpr) { 
    cwa += " newRecExpr:"; 
    newExpr->generateCacheKey(cwa); 
  }
  // make sure cache key can distinguish these 2 queries:
  // prepare s from select * from (update t042qT8 set b=7 where a=2) as t;
  // prepare s from select * from (update t042qT8 set b=7 set on rollback c=2 
  //                               where a=2) as t;
  ItemExpr *setOnRollback;
  if (newRecBeforeExpr_.entries() > 0 &&
      (setOnRollback=newRecBeforeExpr_.rebuildExprTree(ITM_ITEM_LIST))) {
    cwa += " setOnRollback:"; 
    setOnRollback->generateCacheKey(cwa); 
  }
  ItemExpr *execPred = executorPredTree_ ? executorPredTree_ :
    executorPred_.rebuildExprTree();
  if (execPred) { 
    cwa += " execPred:"; 
    execPred->generateCacheKey(cwa); 
  }

  // MVs --
  // The NOLOG parameter is essential.
  if (isNoLogOperation()) { 
    cwa += " NOLOG"; 
  }

  // "current of cursor/hostvar" is essential
  if (currOfCursorName_) {
    currOfCursorName_->generateCacheKey(cwa); 
  }

  // not sure if the following are essential, but better to be safe & 
  // slightly inefficient than to deliver a false hit (ie, wrong plan)
  cwa += mtsStatement_ ? "m1" : "m0";
  cwa += noFlow_ ? "n1" : "n0";
  cwa += noRollback_ ? "o1" : "o0";
  cwa += noCheck_ ? "nc" : "dc";

  // not sure if the following are essential, but we don't know how
  // to quickly & cheaply include them into our cachekey:
  //   updatedTableName_, tabId_, updateToSelectMap_, indexDesc_,
  //   newRecExprArray_, usedColumns_, newRecBeforeExpr_,
  //   newRecBeforeExprArray_, usedBeforeColumns_, potentialOutputs_
  //   indexNumberArray_, scanIndexDesc_, rowsAffected_, stoi_,
  //   oldToNewMap_

  // The following data members are not "essential" to generateCacheKey
  // (at least "after bind") because they are either covered by other
  // data members (eg, beginKeyPred and endKeyPred_ are covered by the
  // selection pred in RelExpr) or they are not yet defined until later
  // (eg, after the optimize phase):
  //   indexNewRecExprArrays_, beginKeyPred_, endKeyPred_,
  //   pathKeys_, partKeys_, indexBeginKeyPredArray_,
  //   indexEndKeyPredArray_, checkConstraints_
}
Exemplo n.º 25
0
// append an ascii-version of RelRoot into cachewa.qryText_
void RelRoot::generateCacheKey(CacheWA &cwa) const
{
  RelExpr::generateCacheKey(cwa);
  ItemExpr *cExpr = compExprTree_ ? compExprTree_ : 
    compExpr_.rebuildExprTree();
  if (cExpr) { 
    // append any select list into cache key
    cwa += " cExpr:"; 
    cExpr->generateCacheKey(cwa);
    // reflect any "[first n]"
    cwa += ((RelRoot*)this)->needFirstSortedRows() ? " 1stN" : " ";
    // Should the select_list aliases be a part of the cache key?
    // Their not affecting the compiled plan argues for their exclusion.
    // Their affecting sqlci's expected output argues for their inclusion.
    RETDesc *rDesc = getRETDesc(); 
    CollIndex degree, x;

    if (rDesc && (degree=rDesc->getDegree()) > 0) {
      cwa += " sla:";
      for (x = 0; x < degree; x++){
        cwa += rDesc->getColRefNameObj(x).getColName().data(); 
        cwa += " ";
      }

        // fix 0-061115-0532 (query cache didn't handle select with embedded 
        // update correctly). New/Old corr. names are recorded for embedded
        // updates here for exact match. This is important because otherwise 
        // a reuse of a query returning the old/new version of values for 
        // a query requesting new/old version is totally possible and 
        // unacceptable.
        //
        // Sample embedded update queries
        // select * from (update tab1 set x = x + 1 where x > 1 return new.*) y;
        // select * from (update tab1 set x = x + 1 where x > 1 return new.x, old.y) y;
        //
      if ( cwa.isUpdate() && isTrueRoot() == FALSE ) {
         cwa += " corrNamTok:";
         cwa += rDesc->getBindWA()->getCorrNameTokens();
      }
    }
  }
  // order by clause is important
  ItemExpr *orderBy = orderByTree_ ? orderByTree_ :
    reqdOrder_.rebuildExprTree();
  if (orderBy) { 
    cwa += " order:"; 
    orderBy->generateCacheKey(cwa); 
  }
  // statement-level access type & lock mode are important for multiuser 
  // applications. both are reflected in the stmt-level and/or context-wide
  // TransMode. So, we mimic RelRoot::codeGen logic here: "copy the current 
  //   context-wide TransMode, then overlay with this stmt's 'FOR xxx ACCESS' 
  //   setting, if any".
  TransMode tmode;
  tmode.updateTransMode(CmpCommon::transMode());

  StmtLevelAccessOptions &opts = ((RelRoot*)this)->accessOptions();
  if (opts.accessType() != ACCESS_TYPE_NOT_SPECIFIED_) {
    tmode.updateAccessModeFromIsolationLevel
      (TransMode::ATtoIL(opts.accessType()));
    tmode.setStmtLevelAccessOptions();
  }
  if (isTrueRoot()) {
    // these are needed by Javier's qc stats virtual tbl interface
    cwa.setIsoLvl(tmode.getIsolationLevel());
    cwa.setAccessMode(tmode.getAccessMode());
    cwa.setAutoCommit(tmode.getAutoCommit());
    cwa.setFlags(tmode.getFlags());
    cwa.setRollbackMode(tmode.getRollbackMode());
    cwa.setAutoabortInterval(tmode.getAutoAbortIntervalInSeconds());
    cwa.setMultiCommit(tmode.getMultiCommit());
  }

  // needed to distinguish these queries and avoid a false hit
  // select * from (delete from t where a=2) as t;
  // select * from (delete from t where a=2 for SKIP CONFLICT ACCESS) as t;
  char mode[40]; 
  str_itoa(tmode.getIsolationLevel(), mode); cwa += " il:"; cwa += mode;
  str_itoa(tmode.getAccessMode(), mode); cwa += " am:"; cwa += mode;

  // Solution: 10-060418-5903
  str_itoa(cwa.getIsoLvlForUpdates(), mode); cwa += " ilu:"; cwa += mode;

  str_itoa(tmode.getAutoCommit(), mode); cwa += " ac:"; cwa += mode;
  str_itoa(tmode.getFlags(), mode); cwa += " fl:"; cwa += mode;
  str_itoa(tmode.getRollbackMode(), mode); cwa += " rm:"; cwa += mode;
  str_itoa(tmode.getAutoAbortIntervalInSeconds(), mode); cwa += " ai:"; cwa += mode;
  str_itoa(tmode.getMultiCommit(), mode); cwa += " mc:"; cwa += mode;

  if (opts.lockMode() != LOCK_MODE_NOT_SPECIFIED_) {
    // need to distinguish these queries and avoid a false hit
    //   select * from t in share mode;
    //   select * from t in exclusive mode;
    str_itoa(opts.lockMode(), mode); cwa += " lm:"; cwa += mode;
  }

  // updatableSelect_ is essential. Otherwise, queries like
  // "select * from t" and "select * from t for update" can confuse
  // query caching into a false hit, causing fullstack/test051 to fail.
  if (updatableSelect_) { 
    cwa += " 4updt "; 
  }
  // for update of col [,col]... clause is important
  ItemExpr *updCol = updateColTree_ ? updateColTree_ :
    updateCol_.rebuildExprTree();
  if (updCol) { 
    cwa += " updCol:"; 
    updCol->generateCacheKey(cwa); 
  }
  // making the CQS part of the key is more efficient than calling
  // CompilerEnv::changeEnv() in ControlDB::setRequiredShape()
  if (reqdShape_) { 
    reqdShape_->unparse(cwa.reqdShape_); 
  }
}
Exemplo n.º 26
0
// append an ascii-version of Scan into cachewa.qryText_
void Scan::generateCacheKey(CacheWA &cwa) const
{
  RelExpr::generateCacheKey(cwa);
  // Fix to 10-010618-3505, 10-010619-3515: include this Scan table's 
  // RedefTime into cwa.qryText_ to make sure we get a cache hit only on 
  // query that reference table(s) that have not changed since the query's 
  // addition to the cache. The queries that reference altered table(s) 
  // will never be hit again and will eventually age out of the cache.
  const NATable *tbl;
  if (cwa.getPhase() >= CmpMain::BIND && 
      getTableDesc() && (tbl=getTableDesc()->getNATable()) != NULL) {
    char redefTime[40];
    convertInt64ToAscii(tbl->getRedefTime(), redefTime);
    cwa += " redef:";
    cwa += redefTime;

    if (tbl->isHiveTable()) {
      char lastModTime[40];
      Int64 mTime = tbl->getClusteringIndex()->getHHDFSTableStats()->getModificationTS();
      convertInt64ToAscii(mTime, lastModTime);
      cwa += " lastMod:";
      cwa += lastModTime;

      cwa += " numFiles:";
      char numFiles[20];
      Int64 numberOfFiles = tbl->getClusteringIndex()->getHHDFSTableStats()->getNumFiles();
      sprintf(numFiles, " %ld", numberOfFiles); 
      cwa += numFiles ;
    }
    // save pointer to this table. later, QueryCache::addEntry will use
    // this pointer to get to this table's histograms's timestamp
    cwa.addTable( (NATable*)tbl );
    // If PARTITION clause has been used we must reflect that in the key.
    if (tbl->isPartitionNameSpecified()) {
      cwa += " partition:";
      cwa += tbl->getClusteringIndex()->getFileSetName().getQualifiedNameAsString().data();
    }
    // If PARTITION range has been used we must reflect that in the key.
    else if (tbl->isPartitionRangeSpecified()) {
      cwa += " partition:";

      char str[100];
      sprintf(str, " from %d to %d", 
	      tbl->getExtendedQualName().getPartnClause().getBeginPartitionNumber() ,
	      tbl->getExtendedQualName().getPartnClause().getEndPartitionNumber());
      cwa += str;
    }
  }
  // We must reflect userTableName_.location into cache key.
  // Otherwise, two queries which differ only in location such as
  //   table table (table T058a, location $system.zsd12345.x1234500);
  //   table table (table T058a, location $data  .zsd12345.x1234500);
  // can confuse our query caching code to return a false hit and 
  // cause fullstack/test058 to fail.
  cwa += userTableName_.getLocationName().data();

  // Same with stream_ because queries like
  // "select * from t" and "select * from stream(t)" can
  // confuse query caching into a false hit causing test079 to fail.
  if (stream_) { 
    cwa += " stream "; 
  }
  // mark mpalias queries so they can be decached upon user request
  if (getTableDesc()->getNATable()->isAnMPTableWithAnsiName()) {
    cwa += AM_AN_MPALIAS_QUERY;
  }

  if (getHbaseAccessOptions())
    {
      cwa += " hbaseVersions: ";
      char numVersions[20];
      sprintf(numVersions, " %d", getHbaseAccessOptions()->getHbaseVersions());
      cwa += numVersions ;
    }
}
Exemplo n.º 27
0
NABoolean Update::isCacheableExpr(CacheWA& cwa)
{
  cwa.setIsUpdate(TRUE);
  return GenericUpdate::isCacheableExpr(cwa);
}