// replace constant with new or existing SelParameter void CacheWA::replaceWithNewOrOldSelParam (ConstValue *val, const NAType *typ, const Selectivity sel, ExprValueId& tgt, BindWA &bindWA) { // match SelParameters only in complex queries Lng32 complexity = (Lng32)CmpCommon::getDefaultNumeric (MATCH_CONSTANTS_OF_EQUALITY_PREDICATES); if (complexity >= 0 && numberOfScans_ >= complexity) { SelParameter *sParm; if (actuals_.find(val, (ConstantParameter**)&sParm)) { sParm->addPosition(++posCounter_); tgt = sParm; // replace with existing SelParameter return; } if (sels_.find(val, &sParm)) { sParm->addPosition(++posCounter_); tgt = sParm; // replace with existing SelParameter return; } } // query is simple or there is no matching constant. // introduce new SelParameter. SelParameter *nParam = new (wHeap()) SelParameter (val, wHeap(), typ, sel, ++posCounter_); addSelParam(nParam, bindWA); tgt = nParam; }
// return current query's formal SelParamTypes const SelParamTypeList *CacheWA::getFormalSelParamTypes() { // selTypes_ is always derived from sels_; so, free any previous // selTypes_ before deriving it again from sels_ if (selTypes_) { NADELETE(selTypes_,SelParamTypeList,wHeap()); } // save pointer in selTypes_ so ~CacheWA() can free it selTypes_ = new (wHeap()) SelParamTypeList(&sels_, wHeap()); return selTypes_; }
// return current query's formal parameter types const ParameterTypeList *CacheWA::getFormalParamTypes() { // parmTypes_ is always derived from actuals_; so, free any previous // parmTypes_ before deriving it again from actuals_ if (parmTypes_) { NADELETE(parmTypes_,ParameterTypeList,wHeap()); } // save pointer in parmTypes_ so ~CacheWA() can free it parmTypes_ = new (wHeap()) ParameterTypeList(&actuals_, wHeap()); return parmTypes_; }
// compose and return TextKey of current query TextKey* CacheWA::getTextKey(const char *sText, Lng32 charset, const QryStmtAttributeSet& attrs) { if (!tkey_) { // capture compiler environment for this query CompilerEnv *env = new (wHeap()) CompilerEnv (wHeap(), CmpMain::PREPARSE, attrs); // use query's formal parameter types, etc in creating its candidate Key // because the Key must hash to the same address as its cache entry. tkey_ = new (wHeap()) TextKey(sText, env, wHeap(), charset); } return tkey_; }
// compose and return cache key of current query CacheKey* CacheWA::getCacheKey(const QryStmtAttributeSet& attrs) { if (!ckey_) { // capture compiler environment for this query CompilerEnv *env = new (wHeap()) CompilerEnv(wHeap(), phase_, attrs); // use query's formal parameter types, etc in creating its candidate Key // because the Key must hash to the same address as its cache entry. ckey_ = new (wHeap()) CacheKey (qryText_, phase_, env, *getFormalParamTypes(), *getFormalSelParamTypes(), wHeap(), reqdShape_, isoLvl_, accMode_, isoLvlIDU_, autoCmt_, flags_, rbackMode_, tables_, useView_); } return ckey_; }
// ----------------------------------------------------------------------- // make an IndexDesc from an existing TableDesc and an NAFileSet // ----------------------------------------------------------------------- IndexDesc::IndexDesc(TableDesc *tdesc, NAFileSet *fileSet, CmpContext* cmpContext) : tableDesc_(tdesc), clusteringIndexFlag_(FALSE), identityColumnUniqueIndexFlag_(FALSE), partFunc_(NULL), fileSet_(fileSet), cmpContext_(cmpContext), scanBasicCosts_(NULL) { DCMPASSERT( tdesc != NULL AND fileSet != NULL ); Lng32 ixColNumber; ValueId keyValueId; ValueId baseValueId; const NATable *naTable = tdesc->getNATable(); indexLevels_ = fileSet_->getIndexLevels(); // --------------------------------------------------------------------- // Make the column list for the index or vertical partition. // Any reference to index also holds for vertical partitions. // --------------------------------------------------------------------- const NAColumnArray & allColumns = fileSet_->getAllColumns(); // any index gets a new set of IndexColumn // item expressions and new value ids CollIndex i = 0; for (i = 0; i < allColumns.entries(); i++) { ItemExpr *baseItemExpr = NULL; // make a new IndexColumn item expression, indicate how it is // defined (in terms of base table columns) and give a value // id to the new IndexColumn expression if (allColumns[i]->getPosition() >= 0) { baseValueId = tdesc->getColumnList()[allColumns[i]->getPosition()]; baseItemExpr = baseValueId.getItemExpr(); } else { // this column doesn't exist in the base table. // This is the KEYTAG column of sql/mp indices. ItemExpr * keytag = new(wHeap()) NATypeToItem((NAType *)(allColumns[i]->getType())); keytag->synthTypeAndValueId(); baseValueId = keytag->getValueId(); baseItemExpr = NULL; } #pragma nowarn(1506) // warning elimination IndexColumn *ixcol = new(wHeap()) IndexColumn(fileSet_,i,baseValueId); #pragma warn(1506) // warning elimination ixcol->synthTypeAndValueId(); // add the newly obtained value id to the index column list indexColumns_.insert(ixcol->getValueId()); // if the index column is defined as a 1:1 copy of a base // column, add it as an equivalent index column (EIC) to the // base column item expression if ((baseItemExpr) && (baseItemExpr->getOperatorType() == ITM_BASECOLUMN)) ((BaseColumn *) baseItemExpr)->addEIC(ixcol->getValueId()); } // --------------------------------------------------------------------- // make the list of access key columns in the index and make a list // of the order that the index provides // --------------------------------------------------------------------- const NAColumnArray & indexKeyColumns = fileSet_->getIndexKeyColumns(); for (i = 0; i < indexKeyColumns.entries(); i++) { // which column of the index is this (usually this will be == i) #pragma nowarn(1506) // warning elimination if ( !naTable->isHbaseTable() ) ixColNumber = allColumns.index(indexKeyColumns[i]); else { // For Hbase tables, a new NAColumn is created for every column // in an index. The above pointer-based lookup for the key column // in base table will only find the index column itself. The // fix is to lookup by the column name and type as is // implemented by the getColumnPosition() method. ixColNumber = allColumns.getColumnPosition(*indexKeyColumns[i]); CMPASSERT(ixColNumber >= 0); } #pragma warn(1506) // warning elimination // insert the value id of the index column into the key column // value id list keyValueId = indexColumns_[ixColNumber]; indexKey_.insert(keyValueId); // insert the same value id into the order list, if the column // is in ascending order, otherwise insert the inverse of the // column if (indexKeyColumns.isAscending(i)) { orderOfKeyValues_.insert(keyValueId); } else { InverseOrder *invExpr = new(wHeap()) InverseOrder(keyValueId.getItemExpr()); invExpr->synthTypeAndValueId(); orderOfKeyValues_.insert(invExpr->getValueId()); } } markIdentityColumnUniqueIndex(tdesc); // --------------------------------------------------------------------- // Find the clustering key columns in the index and store their value // ids in clusteringKey_ // --------------------------------------------------------------------- NABoolean found = TRUE; const NAColumnArray & clustKeyColumns = naTable->getClusteringIndex()->getIndexKeyColumns(); for (i = 0; i < clustKeyColumns.entries() AND found; i++) { // which column of the index is this? #pragma nowarn(1506) // warning elimination ixColNumber = allColumns.index(clustKeyColumns[i]); #pragma warn(1506) // warning elimination found = (ixColNumber != NULL_COLL_INDEX); if (found) { // insert the value id of the index column into the clustering key // value id list keyValueId = indexColumns_[ixColNumber]; clusteringKey_.insert(keyValueId); } else { // clustering key isn't contained in this index, clear the // list that is supposed to indicate the clustering key clusteringKey_.clear(); } } // --------------------------------------------------------------------- // make the list of partitioning key columns in the index and make a list // of the order that the partitioning provides // --------------------------------------------------------------------- const NAColumnArray & partitioningKeyColumns = fileSet_->getPartitioningKeyColumns(); for (i = 0; i < partitioningKeyColumns.entries(); i++) { // which column of the index is this #pragma nowarn(1506) // warning elimination ixColNumber = allColumns.index(partitioningKeyColumns[i]); #pragma warn(1506) // warning elimination // insert the value id of the index column into the partitioningkey column // value id list keyValueId = indexColumns_[ixColNumber]; partitioningKey_.insert(keyValueId); // insert the same value id into the order list, if the column // is in ascending order, otherwise insert the inverse of the // column if (partitioningKeyColumns.isAscending(i)) { orderOfPartitioningKeyValues_.insert(keyValueId); } else { InverseOrder *invExpr = new(wHeap()) InverseOrder(keyValueId.getItemExpr()); invExpr->synthTypeAndValueId(); orderOfPartitioningKeyValues_.insert(invExpr->getValueId()); } } // --------------------------------------------------------------------- // If this index is partitioned, find the partitioning key columns // and build a partitioning function. // --------------------------------------------------------------------- if ((fileSet_->getCountOfFiles() > 1) || (fileSet_->getPartitioningFunction() && fileSet_->getPartitioningFunction()-> isARoundRobinPartitioningFunction())) partFunc_ = fileSet_->getPartitioningFunction()-> createPartitioningFunctionForIndexDesc(this); } // IndexDesc::IndexDesc()