{"action":"created","comment":{"url":"https://api.github.com/repos/apache/incubator-trafodion/pulls/comments/41295292","id":41295292,"diff_hunk":"@@ -3632,6 +3632,561 @@ CostMethodMergeUnion::scmComputeOperatorCostInternal(RelExpr *op,\n \t   \n //<pb>\n \n+// -------------------------------------------------------------------\n+// Cost methods for write DML operations\n+// -------------------------------------------------------------------\n+\n+\n+// -------------------------------------------------------------------\n+// This method is a stub for obsolete old cost model\n+// -------------------------------------------------------------------\n+Cost*\n+CostMethodHbaseUpdateOrDelete::computeOperatorCostInternal(RelExpr* op,\n+  const Context * context,\n+  Lng32& countOfStreams)\n+{\n+  CMPASSERT(false);  // should never be called\n+  return NULL;\n+}\n+\n+// -----------------------------------------------------------------------\n+// CostMethodHbaseUpdateOrDelete::allKeyColumnsHaveHistogramStatistics()\n+//\n+// Returns TRUE if all key columns have histograms, FALSE if not.\n+// -----------------------------------------------------------------------\n+NABoolean CostMethodHbaseUpdateOrDelete::allKeyColumnsHaveHistogramStatistics(\n+  const IndexDescHistograms & histograms,\n+  const IndexDesc * CIDesc\n+  ) const\n+{\n+  // Check if all key columns have histogram statistics\n+  NABoolean statsForAllKeyCols = TRUE;\n+  for ( CollIndex j = 0; j < CIDesc->getIndexKey().entries(); j++ )\n+  {\n+    if (histograms.isEmpty())\n+    {\n+      statsForAllKeyCols = FALSE;\n+      break;\n+    }\n+    else if (!histograms.getColStatsPtrForColumn((CIDesc->getIndexKey()) [j]))\n+    {\n+      // If we get a null pointer when we try to retrieve a\n+      // ColStats for a column of this table, then no histogram\n+      // data was created for that column.\n+      statsForAllKeyCols = FALSE;\n+      break;\n+    }\n+  }\n+\n+  return statsForAllKeyCols;\n+}   // CostMethodHbaseUpdateOrDelete::allKeyColumnsHaveHistogramStatistics()\n+\n+// -----------------------------------------------------------------------\n+// CostMethodHbaseUpdateOrDelete::numRowsToScanWhenAllKeyColumnsHaveHistograms()\n+//\n+// Returns an estimate of the number of rows that will be scanned as a\n+// result of applying key predicates. Assumes that histograms exist for\n+// all key columns.\n+// -----------------------------------------------------------------------\n+#pragma nowarn(262)   // warning elimination\n+CostScalar\n+CostMethodHbaseUpdateOrDelete::numRowsToScanWhenAllKeyColumnsHaveHistograms(\n+  IndexDescHistograms & histograms,\n+  const ColumnOrderList & keyPredsByCol,\n+  const CostScalar & activePartitions,\n+  const IndexDesc * CIDesc\n+  ) const\n+{\n+\n+  // Determine if there are single subset predicates:\n+  CollIndex singleSubsetPrefixOrder;\n+  NABoolean itIsSingleSubset =\n+    keyPredsByCol.getSingleSubsetOrder( singleSubsetPrefixOrder );\n+\n+  NABoolean thereAreSingleSubsetPreds = FALSE;\n+  if ( singleSubsetPrefixOrder > 0 )\n+  {\n+    thereAreSingleSubsetPreds = TRUE;\n+  }\n+  else\n+  {\n+    //  singleSubsetPrefixOrder==0  means either there\n+    // is an equal, an IN,  or there are no key preds in the\n+    // first column.\n+    // singleSubsetPrefixOrder==0 AND itIsSingleSubset\n+    // means there is an EQUAL or there are no key preds\n+    // in the first column, check for existance of\n+    // predicates in this case:\n+    if (     itIsSingleSubset // this FALSE for an IN predicate\n+\t AND keyPredsByCol[0] != NULL\n+       )\n+    {\n+      thereAreSingleSubsetPreds = TRUE;\n+    }\n+  }\n+\n+\n+  CMPASSERT(NOT histograms.isEmpty());\n+\n+  if ( thereAreSingleSubsetPreds )\n+  {\n+    // ---------------------------------------------------------\n+    // There are some key predicates, so apply them\n+    // to the histograms and get the total rows:\n+    // ---------------------------------------------------------\n+\n+    // Get all the key preds for the key columns up to the first\n+    // key column with no key preds\n+    ValueIdSet singleSubsetPrefixPredicates;\n+    NABoolean conflict = FALSE;\n+    for ( CollIndex i = 0; i <= singleSubsetPrefixOrder; i++ )\n+    {\n+\n+      const ValueIdSet *predsPtr = keyPredsByCol[i];\n+      CMPASSERT( predsPtr != NULL ); // it must contain preds\n+      singleSubsetPrefixPredicates.insert( *predsPtr );\n+\n+    } // for every key col in the sing. subset prefix\n+\n+    // Apply those key predicates that reference key columns\n+    // before the first missing key to the histograms:\n+    const SelectivityHint * selHint = CIDesc->getPrimaryTableDesc()->getSelectivityHint();\n+    const CardinalityHint * cardHint = CIDesc->getPrimaryTableDesc()->getCardinalityHint();\n+\n+    RelExpr * dummyExpr = new (STMTHEAP) RelExpr(ITM_FIRST_ITEM_OP,\n+\t\t\t\t                 NULL,\n+\t\t\t\t                 NULL,\n+\t\t\t\t                 STMTHEAP);\n+\n+    histograms.applyPredicates( singleSubsetPrefixPredicates, *dummyExpr, selHint, cardHint);\n+\n+  } // if there are key predicates\n+\n+  // If there is no key predicates, a full table scan will be generated.\n+  // Otherwise, key predicates will be applied to the histograms.\n+  // Now, compute the number of rows after key preds are applied,\n+  // and accounting for asynchronous parallelism:\n+  CostScalar numRowsToScan =\n+    ((histograms.getRowCount()/activePartitions).getCeiling()).minCsOne();\n+\n+  return numRowsToScan;\n+}   // CostMethodHbaseUpdateOrDelete::numRowsToScanWhenAllKeyColumnsHaveHistograms()\n+#pragma warn(262)  // warning elimination\n+\n+// -----------------------------------------------------------------------\n+// CostMethodHbaseUpdateOrDelete::computeIOCostsForCursorOperation().\n+// -----------------------------------------------------------------------\n+void CostMethodHbaseUpdateOrDelete::computeIOCostsForCursorOperation(\n+  CostScalar & randomIOs,        // out\n+  CostScalar & sequentialIOs,    // out\n+  const IndexDesc * CIDesc,\n+  const CostScalar & numRowsToScan,\n+  NABoolean probesInOrder\n+  ) const\n+{\n+  const CostScalar indexLevels = CIDesc->getIndexLevels();\n+  const CostScalar & kbPerBlock = CIDesc->getBlockSizeInKb();\n+  const CostScalar rowsPerBlock =\n+    ((kbPerBlock * csOneKiloBytes) /\n+     CIDesc->getNAFileSet()->getRecordLength()).getFloor();\n+  CostScalar totalIndexBlocks(csZero);\n+\n+  if (probesInOrder)\n+  {\n+    // If the probes are in order, assume that each successive\n+    // probe refers to the next record in the table, i.e. the\n+    // probes are \"highly inclusive\", or in other words, there\n+    // are no gaps in the records to be updated. So, assuming\n+    // this, the number of blocks that need to be read is\n+    // the # of probes divided by the rows per block. This is\n+    // guaranteed to be correct if we are updating most of the\n+    // rows, we can only go wrong if we are updating a small\n+    // number of dispersed rows. This seems unlikely, and anyway\n+    // even if it's true we won't be that far off. If the rows\n+    // are highly inclusive, we could also assume that since the\n+    // blocks will be contiguous that there will only by one seek.\n+    // But, we'd be way off in the case where the assumption\n+    // doesn't hold so we won't do it for now. What we need is\n+    // some way to determine the \"inclusiveness factor\".\n+    sequentialIOs = (numRowsToScan / rowsPerBlock).getCeiling();\n+    // The # of index blocks to read is based on the number of data\n+    // blocks that must be read\n+    totalIndexBlocks =\n+      CIDesc->getEstimatedIndexBlocksLowerBound(sequentialIOs);\n+    randomIOs = totalIndexBlocks;\n+  }\n+  else  // probes not in order\n+  {\n+    // Assume all IOs are random. This is a bit pessimistic\n+    // because at some point much of the file will be in cache,\n+    // so one could argue that as the number of rows updated\n+    // or deleted grows large the number of random IOs should\n+    // decrease. We'll leave that to future work.\n+    sequentialIOs = csZero;\n+    totalIndexBlocks =\n+      CIDesc->getEstimatedIndexBlocksLowerBound(numRowsToScan);\n+    randomIOs = numRowsToScan + totalIndexBlocks;\n+  }\n+\n+} // CostMethodHbaseUpdateOrDelete::computeIOCostsForCursorOperation()\n+\n+\n+\n+// ----QUICKSEARCH FOR HbaseUpdate........................................\n+\n+/**********************************************************************/\n+/*                                                                    */\n+/*                      CostMethodHbaseUpdate                         */\n+/*                                                                    */\n+/**********************************************************************/\n+\n+//*******************************************************************\n+// This method computes the cost vector of the HbaseUpdate operation\n+//*******************************************************************\n+Cost*\n+CostMethodHbaseUpdate::scmComputeOperatorCostInternal(RelExpr* op,\n+  const PlanWorkSpace* pws,\n+  Lng32& countOfStreams)\n+{\n+  // TODO: Write this method; the line below is a stub\n+  return CostMethod::scmComputeOperatorCostInternal(op,pws,countOfStreams);\n+}\n+\n+// ----QUICKSEARCH FOR HbaseDelete........................................\n+\n+/**********************************************************************/\n+/*                                                                    */\n+/*                      CostMethodHbaseDelete                         */\n+/*                                                                    */\n+/**********************************************************************/\n+\n+//*******************************************************************\n+// This method computes the cost vector of the HbaseDelete operation\n+//*******************************************************************\n+Cost*\n+CostMethodHbaseDelete::scmComputeOperatorCostInternal(RelExpr* op,\n+  const PlanWorkSpace* pws,\n+  Lng32& countOfStreams)\n+{\n+  const Context * myContext = pws->getContext();\n+\n+  cacheParameters(op,myContext);\n+  estimateDegreeOfParallelism();\n+\n+  const InputPhysicalProperty* ippForMe =\n+    myContext->getInputPhysicalProperty();\n+\n+  // -----------------------------------------\n+  // Save off estimated degree of parallelism.\n+  // -----------------------------------------\n+  countOfStreams = countOfStreams_;\n+\n+  HbaseDelete* delOp = (HbaseDelete *)op;   // downcast\n+\n+  CMPASSERT(partFunc_ != NULL);\n+  CostScalar activePartitions =\n+   (CostScalar)\n+     (((NodeMap *)(partFunc_->getNodeMap()))->getNumActivePartitions());\n+  const IndexDesc* CIDesc = delOp->getIndexDesc();\n+  const CostScalar & recordSizeInKb = CIDesc->getRecordSizeInKb();\n+\n+  CostScalar tuplesProcessed(csZero);\n+  CostScalar tuplesProduced(csZero);\n+  CostScalar tuplesSent(csZero);  // we use tuplesSent to model sending rowIDs to Hbase \n+  CostScalar randomIOs(csZero);\n+  CostScalar sequentialIOs(csZero);\n+\n+  CostScalar countOfAsynchronousStreams = activePartitions;\n+\n+  // figure out if the probes are in order - if they are, then when\n+  // scanning, I/O will tend to be sequential\n+\n+  NABoolean probesInOrder = FALSE;\n+  if (ippForMe != NULL)  // input physical properties exist?\n+  {\n+    // See if the probes are in order.\n+\n+    // For delete, a partial order is ok.\n+    NABoolean partiallyInOrderOK = TRUE;\n+    NABoolean probesForceSynchronousAccess = FALSE;\n+    ValueIdList targetSortKey = CIDesc->getOrderOfKeyValues();\n+    ValueIdSet sourceCharInputs =\n+      delOp->getGroupAttr()->getCharacteristicInputs();\n+\n+    ValueIdSet targetCharInputs;\n+    // The char inputs are still in terms of the source. Map them to the target.\n+    // Note: The source char outputs in the ipp have already been mapped to\n+    // the target. CharOutputs are a set, meaning they do not have duplicates\n+    // But we could have cases where two columns of the target are matched to the\n+    // same source column, example: Sol: 10-040416-5166, where we have\n+    // INSERT INTO b6table1\n+    //\t\t  ( SELECT f, h_to_f, f, 8.4\n+    //            FROM btre211\n+    //            );\n+    // Hence we use lists here instead of sets.\n+    // Check to see if there are any duplicates in the source Characteristics inputs\n+    // if no, we shall perform set operations, as these are faster\n+    ValueIdList bottomValues = delOp->updateToSelectMap().getBottomValues();\n+    ValueIdSet bottomValuesSet(bottomValues);\n+    NABoolean useListInsteadOfSet = FALSE;\n+\n+    CascadesGroup* group1 = (*CURRSTMT_OPTGLOBALS->memo)[delOp->getGroupId()];\n+\n+    GenericUpdate* upOperator = (GenericUpdate *) group1->getFirstLogExpr();\n+\n+    if (((upOperator->getTableName().getSpecialType() == ExtendedQualName::NORMAL_TABLE ) || (upOperator->getTableName().getSpecialType() == ExtendedQualName::GHOST_TABLE )) &&\n+     (bottomValuesSet.entries() != bottomValues.entries() ) )\n+    {\n+\n+      ValueIdList targetInputList;\n+      // from here get all the bottom values that appear in the sourceCharInputs\n+      bottomValues.findCommonElements(sourceCharInputs );\n+      bottomValuesSet = bottomValues;\n+\n+      // we can use the bottomValues only if these contain some duplicate columns of\n+      // characteristics inputs, otherwise we shall use the characteristics inputs.\n+      if (bottomValuesSet == sourceCharInputs)\n+      {\n+        useListInsteadOfSet = TRUE;\n+\tdelOp->updateToSelectMap().rewriteValueIdListUpWithIndex(\n+\t  targetInputList,\n+\t  bottomValues);\n+\ttargetCharInputs = targetInputList;\n+      }\n+    }\n+\n+    if (!useListInsteadOfSet)\n+    {\n+      delOp->updateToSelectMap().rewriteValueIdSetUp(\n+\ttargetCharInputs,\n+\tsourceCharInputs);\n+    }\n+\n+    // If a target key column is covered by a constant on the source side,\n+    // then we need to remove that column from the target sort key\n+    removeConstantsFromTargetSortKey(&targetSortKey,\n+                                   &(delOp->updateToSelectMap()));\n+    NABoolean orderedNJ = TRUE;\n+    // Don't call ordersMatch if njOuterOrder_ is null.\n+    if (ippForMe->getAssumeSortedForCosting())\n+      orderedNJ = FALSE;\n+    else\n+      // if leading keys are not same then don't try ordered NJ.\n+      orderedNJ =\n+        isOrderedNJFeasible(*(ippForMe->getNjOuterOrder()), targetSortKey);\n+\n+    if (orderedNJ AND \n+        ordersMatch(ippForMe,\n+                    CIDesc,\n+                    &targetSortKey,\n+                    targetCharInputs,\n+                    partiallyInOrderOK,\n+                    probesForceSynchronousAccess))\n+    {\n+      probesInOrder = TRUE;\n+      if (probesForceSynchronousAccess)\n+      {\n+        // The probes form a complete order across all partitions and\n+        // the clustering key and partitioning key are the same. So, the\n+        // only asynchronous I/O we will see will be due to ESPs. So,\n+        // limit the count of streams in DP2 by the count of streams in ESP.\n+\n+        // Get the logPhysPartitioningFunction, which we will use\n+        // to get the logical partitioning function. If it's NULL,\n+        // it means the table was not partitioned at all, so we don't\n+        // need to limit anything since there already is no asynch I/O.\n+\n+     // TODO: lppf is always null in Trafodion; figure out what to do instead...\n+        const LogPhysPartitioningFunction* lppf =\n+            partFunc_->castToLogPhysPartitioningFunction();\n+        if (lppf != NULL)\n+        {\n+          PartitioningFunction* logPartFunc =\n+            lppf->getLogPartitioningFunction();\n+          // Get the number of ESPs:\n+          CostScalar numParts = logPartFunc->getCountOfPartitions();\n+\n+          countOfAsynchronousStreams = MINOF(numParts,\n+                                             countOfAsynchronousStreams);\n+        } // lppf != NULL\n+      } // probesForceSynchronousAccess\n+    } // probes are in order\n+  } // if input physical properties exist\n+\n+  CostScalar currentCpus = \n+    (CostScalar)myContext->getPlan()->getPhysicalProperty()->getCurrentCountOfCPUs();\n+  CostScalar activeCpus = MINOF(countOfAsynchronousStreams, currentCpus);\n+  CostScalar streamsPerCpu =\n+    (countOfAsynchronousStreams / activeCpus).getCeiling();\n+\n+\n+  CostScalar noOfProbesPerPartition(csOne);\n+\n+  CostScalar numRowsToDelete(csOne);\n+  CostScalar numRowsToScan(csOne);\n+\n+  CostScalar commonComputation;\n+\n+  // Determine # of rows to scan and to delete\n+\n+  if (delOp->getSearchKey() && delOp->getSearchKey()->isUnique() && \n+    (noOfProbes_ == 1))\n+  {\n+    // unique access\n+\n+    activePartitions = csOne;\n+    countOfAsynchronousStreams = csOne;\n+    activeCpus = csOne;\n+    streamsPerCpu = csOne;\n+    numRowsToScan = csOne;\n+    // assume the 1 row always satisfies any executor predicates so\n+    // we'll always do the Delete\n+    numRowsToDelete = csOne;\n+  }\n+  else\n+  {\n+    // non-unique access\n+\n+    numRowsToDelete =\n+      ((myRowCount_ / activePartitions).getCeiling()).minCsOne();\n+    noOfProbesPerPartition =\n+      ((noOfProbes_ / countOfAsynchronousStreams).getCeiling()).minCsOne();\n+\n+    // need to compute the number of rows that satisfy the key predicates\n+    // to compute the I/Os that must be performed\n+\n+    // need to create a new histogram, since the one from input logical\n+    // prop. has the histogram for the table after all executor preds are\n+    // applied (i.e. the result cardinality)\n+    IndexDescHistograms histograms(*CIDesc,CIDesc->getIndexKey().entries());\n+\n+    // retrieve all of the key preds in key column order\n+    ColumnOrderList keyPredsByCol(CIDesc->getIndexKey());\n+    delOp->getSearchKey()->getKeyPredicatesByColumn(keyPredsByCol);\n+\n+    if ( NOT allKeyColumnsHaveHistogramStatistics( histograms, CIDesc ) )\n+    {\n+      // All key columns do not have histogram data, the best we can\n+      // do is use the number of rows that satisfy all predicates\n+      // (i.e. the number of rows we will be updating)\n+      numRowsToScan = numRowsToDelete;\n+    }\n+    else\n+    {\n+      numRowsToScan = numRowsToScanWhenAllKeyColumnsHaveHistograms(\n+\thistograms,\n+\tkeyPredsByCol,\n+\tactivePartitions,\n+\tCIDesc\n+\t);\n+    }","path":"core/sql/optimizer/ScmCostMethod.cpp","position":451,"original_position":451,"commit_id":"aa0994e15698341727a1ec5414303a7cd5924727","original_commit_id":"aa0994e15698341727a1ec5414303a7cd5924727","user":{"login":"DaveBirdsall","id":5659628,"avatar_url":"https://avatars.githubusercontent.com/u/5659628?v=3","gravatar_id":"","url":"https://api.github.com/users/DaveBirdsall","html_url":"https://github.com/DaveBirdsall","followers_url":"https://api.github.com/users/DaveBirdsall/followers","following_url":"https://api.github.com/users/DaveBirdsall/following{/other_user}","gists_url":"https://api.github.com/users/DaveBirdsall/gists{/gist_id}","starred_url":"https://api.github.com/users/DaveBirdsall/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DaveBirdsall/subscriptions","organizations_url":"https://api.github.com/users/DaveBirdsall/orgs","repos_url":"https://api.github.com/users/DaveBirdsall/repos","events_url":"https://api.github.com/users/DaveBirdsall/events{/privacy}","received_events_url":"https://api.github.com/users/DaveBirdsall/received_events","type":"User","site_admin":false},"body":"Good point. I will add this.","created_at":"2015-10-06T17:30:08Z","updated_at":"2015-10-06T17:30:08Z","html_url":"https://github.com/apache/incubator-trafodion/pull/102#discussion_r41295292","pull_request_url":"https://api.github.com/repos/apache/incubator-trafodion/pulls/102","_links":{"self":{"href":"https://api.github.com/repos/apache/incubator-trafodion/pulls/comments/41295292"},"html":{"href":"https://github.com/apache/incubator-trafodion/pull/102#discussion_r41295292"},"pull_request":{"href":"https://api.github.com/repos/apache/incubator-trafodion/pulls/102"}}},"pull_request":{"url":"https://api.github.com/repos/apache/incubator-trafodion/pulls/102","id":46808351,"html_url":"https://github.com/apache/incubator-trafodion/pull/102","diff_url":"https://github.com/apache/incubator-trafodion/pull/102.diff","patch_url":"https://github.com/apache/incubator-trafodion/pull/102.patch","issue_url":"https://api.github.com/repos/apache/incubator-trafodion/issues/102","number":102,"state":"open","locked":false,"title":"[TRAFODION-25] First draft of costing code for DELETE.","user":{"login":"DaveBirdsall","id":5659628,"avatar_url":"https://avatars.githubusercontent.com/u/5659628?v=3","gravatar_id":"","url":"https://api.github.com/users/DaveBirdsall","html_url":"https://github.com/DaveBirdsall","followers_url":"https://api.github.com/users/DaveBirdsall/followers","following_url":"https://api.github.com/users/DaveBirdsall/following{/other_user}","gists_url":"https://api.github.com/users/DaveBirdsall/gists{/gist_id}","starred_url":"https://api.github.com/users/DaveBirdsall/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DaveBirdsall/subscriptions","organizations_url":"https://api.github.com/users/DaveBirdsall/orgs","repos_url":"https://api.github.com/users/DaveBirdsall/repos","events_url":"https://api.github.com/users/DaveBirdsall/events{/privacy}","received_events_url":"https://api.github.com/users/DaveBirdsall/received_events","type":"User","site_admin":false},"body":"This is the first draft of costing code for the Delete operator\r\nin Trafodion. Formerly a cost of 1 was returned for the Delete\r\noperator. With this change, we can expect better plans for DELETE\r\nstatements.\r\n\r\nPart of the code for the Update operator is in this check-in as\r\nwell, but the main part of the Update code remains to be written.\r\n\r\nTwo CQDs have been added to control execution of this code.\r\n\r\nCQD HBASE_DELETE_COSTING 'ON' causes the new Delete costing code\r\nto be executed. A value of 'OFF' causes the old stub logic (a\r\ncost of 1) to be executed instead. The default for this CQD is\r\n'ON', so this code can be exercised.\r\n\r\nCQD HBASE_UPDATE_COSTING 'ON' causes partial Update costing code\r\nto be executed. This results in a stub cost object of 1e32 to\r\nbe returned. (Actually, this activates a stub that was already\r\nthere in the code; this turned out to be useful in discovering\r\ncertain bugs, fixed below.) A value of 'OFF' causes earlier \r\nstub logic (a cost of 1) to be executed instead. The default\r\nfor this CQD is 'OFF' for now.\r\n\r\nOnce this code has been sufficiently validated, these CQDs will be\r\nremoved.\r\n\r\nSeveral bugs are also fixed in this check-in. All are latent,\r\nexisting bugs that became more visible when regression-testing the\r\nnew costing code due to plan changes.\r\n\r\n1. MERGE with a NOT MATCHED action was being (incorrectly)\r\ntransformed into a nested join in some plans. This caused the\r\nNOT MATCHED action to not be executed. (optimizer/TransRule.cpp,\r\noptimizer/RelUpdate.h)\r\n\r\n2. MERGE error messages generated by the compiler were sometimes\r\nincorrect. (optimizer/BindRelExpr.cpp, generator/GenPreCode.cpp)\r\n\r\n3. A check constraint error message was not being reported when\r\nit should have on a table with SERIALIZED columns. This was caused\r\nby an HBase filter expression being generated with operators\r\nhaving the wrong sense (e.g., < instead of >).\r\n(generator/GenPreCode.cpp)\r\n\r\n4. CLEANUP would fail if the record in the OBJECTS_UNIQ_IDX index\r\nwas missing. This happened because it was using a vanilla DELETE\r\nand the plan for the DELETE changed with the costing changes to \r\nuse index access. The fix was to use CQDs to avoid accessing the\r\nindex when deleting from the OBJECTS table.\r\n(sqlcomp/CmpSeabaseDDLcleanup.cpp)\r\n\r\n5. INITIALIZE AUTHORIZATION would fail if there was a row in\r\nthe OBJECTS table with an object_owner that does not exist in\r\nthe AUTHS table. (The latter can happen in rare circumstances\r\nwhen toggling authorization off and on repeatedly. That is a\r\nbug in its own right that remains outstanding.) This has been\r\nworked around by writing 'DB__ROOT' to the OBJECT_PRIVILEGES\r\ntable when the object_owner is invalid.\r\n\r\nSome other issues were noticed during unit testing that will\r\nbe addressed in later check-ins:\r\n\r\n1. Scan costs for DELETEs using TSJ plans are grossly over-\r\nestimated. The cause is that the generated join predicates between\r\nthe Scan and Delete operators are being assigned a default\r\nselectivity of 1/3. This is an existing, latent bug.\r\n\r\n2. The HBaseDeleteRule in the optimizer considers a Delete-only\r\nplan (that is, without a TSJ of a Scan to a Delete) when there\r\nare equality predicates on all key columns, and when there are\r\nno predicates on key columns at all. The former is correct, the\r\nlatter is almost never a good plan. Costing should prevent the\r\nlatter from being chosen but still this is unnecessary extra\r\ncomputation. (The rule does not consider Delete-only plans when\r\na proper subset of the key columns have equality predicates.)\r\nThis is an existing, latent bug.\r\n\r\n ","created_at":"2015-10-05T17:21:02Z","updated_at":"2015-10-06T17:30:08Z","closed_at":null,"merged_at":null,"merge_commit_sha":"257f52a9981dfa67d87b9ad7bf1983df623f7709","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/apache/incubator-trafodion/pulls/102/commits","review_comments_url":"https://api.github.com/repos/apache/incubator-trafodion/pulls/102/comments","review_comment_url":"https://api.github.com/repos/apache/incubator-trafodion/pulls/comments{/number}","comments_url":"https://api.github.com/repos/apache/incubator-trafodion/issues/102/comments","statuses_url":"https://api.github.com/repos/apache/incubator-trafodion/statuses/aa0994e15698341727a1ec5414303a7cd5924727","head":{"label":"DaveBirdsall:DeleteCostingDraft1","ref":"DeleteCostingDraft1","sha":"aa0994e15698341727a1ec5414303a7cd5924727","user":{"login":"DaveBirdsall","id":5659628,"avatar_url":"https://avatars.githubusercontent.com/u/5659628?v=3","gravatar_id":"","url":"https://api.github.com/users/DaveBirdsall","html_url":"https://github.com/DaveBirdsall","followers_url":"https://api.github.com/users/DaveBirdsall/followers","following_url":"https://api.github.com/users/DaveBirdsall/following{/other_user}","gists_url":"https://api.github.com/users/DaveBirdsall/gists{/gist_id}","starred_url":"https://api.github.com/users/DaveBirdsall/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DaveBirdsall/subscriptions","organizations_url":"https://api.github.com/users/DaveBirdsall/orgs","repos_url":"https://api.github.com/users/DaveBirdsall/repos","events_url":"https://api.github.com/users/DaveBirdsall/events{/privacy}","received_events_url":"https://api.github.com/users/DaveBirdsall/received_events","type":"User","site_admin":false},"repo":{"id":38782828,"name":"incubator-trafodion","full_name":"DaveBirdsall/incubator-trafodion","owner":{"login":"DaveBirdsall","id":5659628,"avatar_url":"https://avatars.githubusercontent.com/u/5659628?v=3","gravatar_id":"","url":"https://api.github.com/users/DaveBirdsall","html_url":"https://github.com/DaveBirdsall","followers_url":"https://api.github.com/users/DaveBirdsall/followers","following_url":"https://api.github.com/users/DaveBirdsall/following{/other_user}","gists_url":"https://api.github.com/users/DaveBirdsall/gists{/gist_id}","starred_url":"https://api.github.com/users/DaveBirdsall/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DaveBirdsall/subscriptions","organizations_url":"https://api.github.com/users/DaveBirdsall/orgs","repos_url":"https://api.github.com/users/DaveBirdsall/repos","events_url":"https://api.github.com/users/DaveBirdsall/events{/privacy}","received_events_url":"https://api.github.com/users/DaveBirdsall/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/DaveBirdsall/incubator-trafodion","description":"Mirror of Apache Trafodion (Incubating)","fork":true,"url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion","forks_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/forks","keys_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/keys{/key_id}","collaborators_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/teams","hooks_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/hooks","issue_events_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/issues/events{/number}","events_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/events","assignees_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/assignees{/user}","branches_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/branches{/branch}","tags_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/tags","blobs_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/git/refs{/sha}","trees_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/git/trees{/sha}","statuses_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/statuses/{sha}","languages_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/languages","stargazers_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/stargazers","contributors_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/contributors","subscribers_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/subscribers","subscription_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/subscription","commits_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/commits{/sha}","git_commits_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/git/commits{/sha}","comments_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/comments{/number}","issue_comment_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/issues/comments{/number}","contents_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/contents/{+path}","compare_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/compare/{base}...{head}","merges_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/merges","archive_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/downloads","issues_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/issues{/number}","pulls_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/pulls{/number}","milestones_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/milestones{/number}","notifications_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/labels{/name}","releases_url":"https://api.github.com/repos/DaveBirdsall/incubator-trafodion/releases{/id}","created_at":"2015-07-08T22:12:46Z","updated_at":"2015-07-08T22:13:26Z","pushed_at":"2015-10-05T17:16:17Z","git_url":"git://github.com/DaveBirdsall/incubator-trafodion.git","ssh_url":"git@github.com:DaveBirdsall/incubator-trafodion.git","clone_url":"https://github.com/DaveBirdsall/incubator-trafodion.git","svn_url":"https://github.com/DaveBirdsall/incubator-trafodion","homepage":null,"size":56919,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"apache:master","ref":"master","sha":"bb759855b4ff2488a3f0d3f10585589eacdba1cb","user":{"login":"apache","id":47359,"avatar_url":"https://avatars.githubusercontent.com/u/47359?v=3","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"repo":{"id":36349344,"name":"incubator-trafodion","full_name":"apache/incubator-trafodion","owner":{"login":"apache","id":47359,"avatar_url":"https://avatars.githubusercontent.com/u/47359?v=3","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/apache/incubator-trafodion","description":"Mirror of Apache Trafodion (Incubating)","fork":false,"url":"https://api.github.com/repos/apache/incubator-trafodion","forks_url":"https://api.github.com/repos/apache/incubator-trafodion/forks","keys_url":"https://api.github.com/repos/apache/incubator-trafodion/keys{/key_id}","collaborators_url":"https://api.github.com/repos/apache/incubator-trafodion/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/apache/incubator-trafodion/teams","hooks_url":"https://api.github.com/repos/apache/incubator-trafodion/hooks","issue_events_url":"https://api.github.com/repos/apache/incubator-trafodion/issues/events{/number}","events_url":"https://api.github.com/repos/apache/incubator-trafodion/events","assignees_url":"https://api.github.com/repos/apache/incubator-trafodion/assignees{/user}","branches_url":"https://api.github.com/repos/apache/incubator-trafodion/branches{/branch}","tags_url":"https://api.github.com/repos/apache/incubator-trafodion/tags","blobs_url":"https://api.github.com/repos/apache/incubator-trafodion/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/apache/incubator-trafodion/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/apache/incubator-trafodion/git/refs{/sha}","trees_url":"https://api.github.com/repos/apache/incubator-trafodion/git/trees{/sha}","statuses_url":"https://api.github.com/repos/apache/incubator-trafodion/statuses/{sha}","languages_url":"https://api.github.com/repos/apache/incubator-trafodion/languages","stargazers_url":"https://api.github.com/repos/apache/incubator-trafodion/stargazers","contributors_url":"https://api.github.com/repos/apache/incubator-trafodion/contributors","subscribers_url":"https://api.github.com/repos/apache/incubator-trafodion/subscribers","subscription_url":"https://api.github.com/repos/apache/incubator-trafodion/subscription","commits_url":"https://api.github.com/repos/apache/incubator-trafodion/commits{/sha}","git_commits_url":"https://api.github.com/repos/apache/incubator-trafodion/git/commits{/sha}","comments_url":"https://api.github.com/repos/apache/incubator-trafodion/comments{/number}","issue_comment_url":"https://api.github.com/repos/apache/incubator-trafodion/issues/comments{/number}","contents_url":"https://api.github.com/repos/apache/incubator-trafodion/contents/{+path}","compare_url":"https://api.github.com/repos/apache/incubator-trafodion/compare/{base}...{head}","merges_url":"https://api.github.com/repos/apache/incubator-trafodion/merges","archive_url":"https://api.github.com/repos/apache/incubator-trafodion/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/apache/incubator-trafodion/downloads","issues_url":"https://api.github.com/repos/apache/incubator-trafodion/issues{/number}","pulls_url":"https://api.github.com/repos/apache/incubator-trafodion/pulls{/number}","milestones_url":"https://api.github.com/repos/apache/incubator-trafodion/milestones{/number}","notifications_url":"https://api.github.com/repos/apache/incubator-trafodion/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/apache/incubator-trafodion/labels{/name}","releases_url":"https://api.github.com/repos/apache/incubator-trafodion/releases{/id}","created_at":"2015-05-27T07:00:05Z","updated_at":"2015-10-05T00:52:23Z","pushed_at":"2015-10-06T16:37:30Z","git_url":"git://github.com/apache/incubator-trafodion.git","ssh_url":"git@github.com:apache/incubator-trafodion.git","clone_url":"https://github.com/apache/incubator-trafodion.git","svn_url":"https://github.com/apache/incubator-trafodion","homepage":null,"size":61395,"stargazers_count":17,"watchers_count":17,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":41,"mirror_url":"git://git.apache.org/incubator-trafodion.git","open_issues_count":5,"forks":41,"open_issues":5,"watchers":17,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/apache/incubator-trafodion/pulls/102"},"html":{"href":"https://github.com/apache/incubator-trafodion/pull/102"},"issue":{"href":"https://api.github.com/repos/apache/incubator-trafodion/issues/102"},"comments":{"href":"https://api.github.com/repos/apache/incubator-trafodion/issues/102/comments"},"review_comments":{"href":"https://api.github.com/repos/apache/incubator-trafodion/pulls/102/comments"},"review_comment":{"href":"https://api.github.com/repos/apache/incubator-trafodion/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/apache/incubator-trafodion/pulls/102/commits"},"statuses":{"href":"https://api.github.com/repos/apache/incubator-trafodion/statuses/aa0994e15698341727a1ec5414303a7cd5924727"}}}}