// change literals of a cacheable query into ConstantParameters ItemExpr* Like::normalizeForCache(CacheWA& cwa, BindWA& bindWA) { if (nodeIsNormalizedForCache()) { return this; } // replace only the matchValue child(0) = child(0)->normalizeForCache(cwa, bindWA); // but, don't touch the pattern or the escapeChar. markAsNormalizedForCache(); return this; }
// change literals of a cacheable query into ConstantParameters RelExpr* MergeDelete::normalizeForCache(CacheWA& cwa, BindWA& bindWA) { if (nodeIsNormalizedForCache()) { return this; } if (insertValues_) { insertValues_ = insertValues_->normalizeForCache(cwa, bindWA); } // replace descendants' literals into ConstantParameters return Delete::normalizeForCache(cwa, bindWA); }
// selectively change literals of a cacheable query into input parameters ItemExpr* BiLogic::normalizeForCache(CacheWA& cwa, BindWA& bindWA) { if (nodeIsNormalizedForCache()) { return this; } if (getOperatorType() == ITM_AND) { return ItemExpr::normalizeForCache(cwa, bindWA); } else { // do not replace literals in OR predicates markAsNormalizedForCache(); return this; } }
// change literals of a cacheable query into ConstantParameters ItemExpr* BiArith::normalizeForCache(CacheWA& cwa, BindWA& bindWA) { if (nodeIsNormalizedForCache()) { return this; } if (!isUnaryNegate()) { // set in sqlparser.y which transforms "-i" into // "0 - i" because apparently the executor does not have a unary negate. // so, we must avoid replacing this system-introduced "0". child(0) = child(0)->normalizeForCache(cwa, bindWA); } child(1) = child(1)->normalizeForCache(cwa, bindWA); markAsNormalizedForCache(); return this; }
// change literals of a cacheable query into ConstantParameters RelExpr* Tuple::normalizeForCache(CacheWA& cwa, BindWA& bindWA) { if (nodeIsNormalizedForCache()) { return this; } if (tupleExprTree_) { tupleExprTree_ = tupleExprTree_->normalizeForCache(cwa, bindWA); } else { tupleExpr_.normalizeForCache(cwa, bindWA); } // replace descendants' literals into ConstantParameters return RelExpr::normalizeForCache(cwa, bindWA); }
// change literals of a cacheable query into ConstantParameters ItemExpr* Assign::normalizeForCache(CacheWA& cwa, BindWA& bindWA) { if (nodeIsNormalizedForCache()) { return this; } if (cwa.getPhase() == CmpMain::PARSE) { child(1) = child(1)->normalizeForCache(cwa, bindWA); } else if (cwa.getPhase() >= CmpMain::BIND) { ItemExpr *leftC=child(0), *rightC=child(1); OperatorTypeEnum leftO = leftC->getOperatorType(); OperatorTypeEnum rightO = rightC->getOperatorType(); ConstantParameter *cParam; if (leftO == ITM_BASECOLUMN && rightO == ITM_CONSTANT // normalizeForCache only constants that can be safely backpatched. // part of fix to CR 10-010726-4109. && isSafelyCoercible(cwa) // normalizeForCache only constants that are contained in the original // SQL query so that each parameter can be backpatched by the // corresponding constant from the query. This is to fix regression // failure MP core/test055 where a SystemLiteral was inserted when the // Keytag for a MP table column is not zero. see LeafInsert::bindNode(). // The offending query in MP core/test055 is // update t055t9v set b = b + 1 where current of c10; && NOT ((ConstValue*)rightC)->isSystemProvided() ) { ConstValue *val = (ConstValue*)rightC; if (!val->isNull()) { cParam = new (cwa.wHeap()) ConstantParameter ((ConstValue*)rightC, cwa.wHeap(), ((BaseColumn*)leftC)->getNAColumn()->getType()); cwa.addConstParam(cParam, bindWA); child(1) = cParam; } // else val is null; keep null as is. // this is part of a fix to genesis case: 10-010618-3484. } else { child(1) = child(1)->normalizeForCache(cwa, bindWA); } } markAsNormalizedForCache(); return this; }
// change literals of a cacheable query into ConstantParameters ItemExpr* ValueIdProxy::normalizeForCache(CacheWA& cwa, BindWA& bindWA) { if (nodeIsNormalizedForCache()) { return this; } if (cwa.getPhase() == CmpMain::PARSE) { // we want to parameterize tuple inserts derivedFrom_ = derivedFrom_.getItemExpr()->normalizeForCache(cwa, bindWA)->getValueId(); } else if (cwa.getPhase() == CmpMain::BIND) { if (derivedFrom_.getItemExpr()->isSafelyCoercible(cwa)) { // fix CR 10-010726-4109: make sure queries with constants that // cannot be safely backpatched such as // select case smallintcol when 4294967393 then 'max' end from t // are not parameterized derivedFrom_ = derivedFrom_.getItemExpr()->normalizeForCache(cwa, bindWA)->getValueId(); } } markAsNormalizedForCache(); return this; }
// change literal of a cacheable query into ConstantParameter ItemExpr* ConstValue::normalizeForCache(CacheWA& cwa, BindWA& bindWA) { // skip system supplied or empty string literals if (isSystemSupplied_ || isEmptyString()) { return this; } if (nodeIsNormalizedForCache()) { return this; } // for now, do not parameterize NULLs because they can cause false // constraint violations, eg, fullstack/TEST005 // create table t005t2(a int, b int not null, c char(10) not null, // d int, primary key (c) ); // insert into t005t2 values (NULL,7,'?-7-?',NULL); // gets "ERROR[8421] NULL cannot be assigned to a NOT NULL column." if (isNull()) { return this; } NAHeap* heap = cwa.wHeap(); // quantize length of strings only in after parse case ConstantParameter* result = new(heap) ConstantParameter (*this, heap, cwa.getPhase() == CmpMain::PARSE); if (result) { // "after-parser" ConstantParameters will undergo complete binding, so // addConstParam does not have to bind "after-parser" ConstantParameters cwa.addConstParam(result, bindWA); result->markAsNormalizedForCache(); } // do not mark this ConstValue as normalizedForCache because it may // be "shared" and may need to be replaced into a ConstantParameter // again in another referencing expression context. For example, the // binder visits the case operand "3" more than once in // insert into t values(case 3 when 4 then 0 when 3 then 1 end) return result; }
// change literals of a cacheable query into ConstantParameters and save // true root into cachewa so we can "bind" ConstantParameters as "inputvars" RelExpr* RelRoot::normalizeForCache(CacheWA& cwa, BindWA& bindWA) { if (nodeIsNormalizedForCache()) { return this; } if (isTrueRoot()) { cwa.setTopRoot(this); } if (cwa.getPhase() >= CmpMain::BIND) { // replace any select list literals into constant parameters if (compExprTree_) { compExprTree_ = compExprTree_->normalizeForCache(cwa, bindWA); } else { compExpr_.normalizeForCache(cwa, bindWA); } } // replace descendants' literals into ConstantParameters RelExpr *result = RelExpr::normalizeForCache(cwa, bindWA); if (cwa.getPhase() >= CmpMain::BIND) { // query tree has undergone BINDing, but RelExpr::normalizeForCache // may have introduced new ConstantParameters in place of ConstValues; // we want to BIND these new ConstantParameters but a RelRoot::bindNode() // call here would be overkill; we just want these new ConstantParameters // to be "bound" as "inputvars"; so, we selectively cut and paste code // from BindRelExpr.cpp RelRoot::bindNode into here to "bind" any new // ConstantParameters as "inputvars". ItemExpr *inputVarTree = removeInputVarTree(); if (inputVarTree) { inputVarTree->convertToValueIdList(inputVars(), &bindWA, ITM_ITEM_LIST); if (bindWA.errStatus()) { return NULL; } } } return result; }
// change literals of a cacheable query into ConstantParameters ItemExpr* ItemExpr::normalizeForCache(CacheWA& cwa, BindWA& bindWA) { if (nodeIsNormalizedForCache()) { return this; } Int32 arity = getArity(); for (Int32 x = 0; x < arity; x++) { if (cwa.getPhase() == CmpMain::PARSE) { // we want to parameterize tuple inserts child(x) = child(x)->normalizeForCache(cwa, bindWA); } else if (cwa.getPhase() == CmpMain::BIND) { if (child(x)->isSafelyCoercible(cwa)) { // fix CR 10-010726-4109: make sure queries with constants that // cannot be safely backpatched such as // select case smallintcol when 4294967393 then 'max' end from t // are not parameterized child(x) = child(x)->normalizeForCache(cwa, bindWA); } } } markAsNormalizedForCache(); return this; }
// change literals of a cacheable query into ConstantParameters RelExpr* RelExpr::normalizeForCache(CacheWA& cwa, BindWA& bindWA) { if (nodeIsNormalizedForCache()) { return this; } // replace descendants' literals into ConstantParameters normalizeKidsForCache(cwa, bindWA); if (cwa.getPhase() >= CmpMain::BIND) { if (selection_) { selection_ = selection_->normalizeForCache(cwa, bindWA); } else { selectionPred().normalizeForCache(cwa, bindWA); } // RelExpr::bindSelf has done this line during binding; but, we // must redo it to recognize any new constantparameters created // by the above normalizeForCache call(s) as RelExpr inputs. getGroupAttr()->addCharacteristicInputs (bindWA.getCurrentScope()->getOuterRefs()); } markAsNormalizedForCache(); return this; }
// change literals of a cacheable query into ConstantParameters ItemExpr* UDFunction::normalizeForCache(CacheWA& cwa, BindWA& bindWA) { if (nodeIsNormalizedForCache()) { return this; } // Since the UDFunction::transformNode refers to both the // inputVars_ ValueIdSet and the children array we need to make sure // they are consistent. // The children array may contain cast() of the expressions in inputVars_ // If we have a UUDF function the inputs that were given // at parse time, really do not reflect reality anymore. // So here we will simply reinitialize them with what we find in the // inputVars_. CMPASSERT(udfDesc_); // we better have one after binding. NABoolean isUUDF(udfDesc_->isUUDFRoutine()); // Save off a copy of the original inputVars_ set. ValueIdSet origInputVars(inputVars_); // Loop through the given inputs for (Int32 x = 0; x < getArity(); x++) { NABoolean origInputIsChildOfCast(FALSE); ItemExpr * origIe = child(x); ItemExpr * newIe = NULL; ValueId vid = origIe->getValueId(); if (cwa.getPhase() == CmpMain::BIND) { if (origIe->isSafelyCoercible(cwa)) { // fix CR 10-010726-4109: make sure queries with constants that // cannot be safely backpatched such as // select case smallintcol when 4294967393 then 'max' end from t // are not parameterized newIe = origIe->normalizeForCache(cwa, bindWA); if (newIe != origIe ) { // normalizeForCache returned a new ItemExpr. We have to update // the UDFunction inputVars_ set, as this is used to determine // characteristic inputs for IsolatedScalarUDF at transform time. child(x) = newIe; // Is it a input that UDFunction::bindNode put a cast around? if ((origIe->getOperatorType() == ITM_CAST) && (origInputVars.contains(origIe->child(0)->getValueId()))) { // Since the original child was a CAST that UDFunction::bindNode // created, check to see if that CAST's child is part of the new // expression, if it is, we don't have to do anything, since the // CASTED value is part of the inputVars set, otherwise, we have // to update the inputVars set to keep the characteristic inputs // consistent. if (! newIe->referencesTheGivenValue( origIe->child(0)->getValueId()), TRUE) { // remove the original input from inputVars. It is the child // of origIe because origIe is a cast that UDFunction::bindNode // introduced. inputVars_ -= origIe->child(0)->getValueId(); if (newIe->getOperatorType() == ITM_CAST) { // If the new expression is a CAST, we assume the child is the // real input. We don't expect CAST(CAST(CAST(expr))) type // expressions only simple CAST(expr) ones. inputVars_ += newIe->child(0)->getValueId(); } else { // add the newIe itself if it was not a CAST. inputVars_ += newIe->getValueId(); } } } else { // If the newIe doesn't contain the original one, we need to update // the inputVars set. if (! newIe->referencesTheGivenValue( origIe->getValueId()), TRUE) { // the origIe was not a CAST introduced by UDFunction::bindNode() if (newIe->getOperatorType() == ITM_CAST) { if (!origInputVars.contains(newIe->child(0)->getValueId())) { inputVars_ -= origIe->getValueId(); // If the new expression is a CAST, we assume the child is the // real input. We don't expect CAST(CAST(CAST(expr))) type // expressions only simple CAST(expr) ones. inputVars_ += newIe->child(0)->getValueId(); } // we don't need to update inputVars_ if the origInputVars // contains the valueId of the newIe child already. } else { // This is an entirely new input. Remove the old one, and // add in the new. inputVars_ -= origIe->getValueId(); inputVars_ += newIe->getValueId(); } } } } } } } markAsNormalizedForCache(); return this; }
RelExpr* Scan::normalizeForCache(CacheWA& cwa, BindWA& bindWA) { if (nodeIsNormalizedForCache()) { return this; } if (CmpCommon::getDefault(QUERY_CACHE_TABLENAME) == DF_OFF) { // replace descendants' literals into ConstantParameters return RelExpr::normalizeForCache(cwa, bindWA); } // replace tablename with a prototyped tablename. TableDesc * td = getTableDesc(); CorrName &origName = td->getCorrNameObj(); if (origName.getPrototype() == NULL) { Lng32 CACHED_MAX_ANSI_NAME_EXTERNAL_LEN = 128; NAString hvName("dummy_name"); HostVar * hv = new(bindWA.wHeap()) HostVar(hvName, new(bindWA.wHeap()) SQLChar(CACHED_MAX_ANSI_NAME_EXTERNAL_LEN)); hv->setPrototypeValue(origName.getQualifiedNameAsString()); hv->synthTypeAndValueId(); hv->setIsCachedParam(TRUE); CorrName cn("HostVar$", bindWA.wHeap(), hv->getName(), // debugging ease "$bogus"); cn.setPrototype(hv); NAString *tmpName = new (bindWA.wHeap()) NAString(hv->getPrototypeValue(), bindWA.wHeap()); cn.setUgivenName(*tmpName); cn.applyDefaults(&bindWA, bindWA.getDefaultSchema()); td->setCorrName(cn); setTableName(cn); char * strval = new(bindWA.wHeap()) char[CACHED_MAX_ANSI_NAME_EXTERNAL_LEN]; strcpy(strval, origName.getQualifiedNameAsString().data()); CharType * typ = new(bindWA.wHeap()) SQLChar(CACHED_MAX_ANSI_NAME_EXTERNAL_LEN, FALSE); ConstValue * cv = new(bindWA.wHeap()) ConstValue(typ, strval, CACHED_MAX_ANSI_NAME_EXTERNAL_LEN); ConstantParameter* result = new(bindWA.wHeap()) ConstantParameter (*cv, bindWA.wHeap(), cwa.getPhase() == CmpMain::PARSE); result->synthTypeAndValueId(); cwa.addConstParam(result, bindWA); hv->setPMOrdPosAndIndex(COM_UNKNOWN_DIRECTION, -1, (Int32)cwa.getConstParams().entries()); } // replace descendants' literals into ConstantParameters return RelExpr::normalizeForCache(cwa, bindWA); }