/**********************************************************************
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
**********************************************************************/
/* -*-C++-*-
******************************************************************************
*
* File:         ImplRule.C
* Description:  DBI-defined implementation rules
* Created:      9/14/94
* Language:     C++
*
*
*
*
******************************************************************************
*/

#include "Sqlcomp.h"
#include "GroupAttr.h"
#include "opt.h"
#include "PhyProp.h"
#include "ImplRule.h"
#include "AllRelExpr.h"
#include "RelPackedRows.h"
#include "RelSequence.h"
#include "RelSample.h"
#include "AllItemExpr.h"
#include "ValueDesc.h"
#include "mdam.h"
#include "CmpContext.h"
#include "Cost.h"
#include "CostMethod.h"
#include "ScanOptimizer.h"

#include "NADefaults.h"
#include "OptimizerSimulator.h"
#include "RelScan.h"

// -----------------------------------------------------------------------
// Global variables
// -----------------------------------------------------------------------
THREAD_P NAUnsigned              HashJoinRuleNumber;
THREAD_P NAUnsigned              NestedJoinRuleNumber;
THREAD_P NAUnsigned              MergeJoinRuleNumber;
THREAD_P NAUnsigned              SortEnforcerRuleNumber;

// -----------------------------------------------------------------------
// Global function to add implementation rules to the rule set
// -----------------------------------------------------------------------
static const NAString LiteralAnyName("any name");

void CreateImplementationRules(RuleSet* set)
{
  Rule *r;

  CorrName anyCorrName(LiteralAnyName);

  r = new(CmpCommon::contextHeap()) FileScanRule
    ("File Scan implementation rule",
     new(CmpCommon::contextHeap()) Scan(REL_SCAN, CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
       FileScan(CorrName(),
                NULL,
                NULL,
                REL_FILE_SCAN,
                CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) HbaseScanRule
    ("Hbase Scan implementation rule",
     new(CmpCommon::contextHeap()) Scan(REL_SCAN, CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
     HbaseAccess(REL_HBASE_ACCESS, CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) HashJoinRule
    ("Hash join implementation rule",
     new(CmpCommon::contextHeap())
       WildCardOp(REL_ANY_JOIN,
                  0,
                  new(CmpCommon::contextHeap())
                    CutOp(0, CmpCommon::contextHeap()),
                  new(CmpCommon::contextHeap())
                    CutOp(1, CmpCommon::contextHeap()),
                  CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
     HashJoin(new(CmpCommon::contextHeap())
                CutOp(0, CmpCommon::contextHeap()),
              new(CmpCommon::contextHeap())
                CutOp(1, CmpCommon::contextHeap()),
              CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  HashJoinRuleNumber = r->getNumber();

  r = new(CmpCommon::contextHeap())
    MergeJoinRule(
                  "Merge join implementation rule",
                  new(CmpCommon::contextHeap())
                  WildCardOp(REL_ANY_JOIN,
                             0,
                             new(CmpCommon::contextHeap())
                               CutOp(0, CmpCommon::contextHeap()),
                             new(CmpCommon::contextHeap())
                               CutOp(1, CmpCommon::contextHeap()),
                             CmpCommon::contextHeap()),
                  new(CmpCommon::contextHeap())
                  MergeJoin(new(CmpCommon::contextHeap())
                              CutOp(0, CmpCommon::contextHeap()),
                            new(CmpCommon::contextHeap())
                              CutOp(1, CmpCommon::contextHeap()),
                            REL_MERGE_JOIN,
                            NULL,
                            CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber(),
                        set->getSecondPassNumber());

  // set global variable
  MergeJoinRuleNumber = r->getNumber();

  r = new(CmpCommon::contextHeap()) NestedJoinRule
    ("Nested join implementation rule",
     new(CmpCommon::contextHeap())
     WildCardOp(REL_ANY_JOIN,
                0,
                new(CmpCommon::contextHeap())
                  CutOp(0, CmpCommon::contextHeap()),
                new(CmpCommon::contextHeap())
                  CutOp(1, CmpCommon::contextHeap()),
                CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
     NestedJoin(new(CmpCommon::contextHeap())
                  CutOp(0, CmpCommon::contextHeap()),
                new(CmpCommon::contextHeap())
                  CutOp(1, CmpCommon::contextHeap()),
                REL_NESTED_JOIN,
                CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  NestedJoinRuleNumber = r->getNumber();

  r = new(CmpCommon::contextHeap()) NestedJoinFlowRule
    ("Nested join flow implementation rule",
     new(CmpCommon::contextHeap())
     Join(new(CmpCommon::contextHeap())
            CutOp(0, CmpCommon::contextHeap()),
          new(CmpCommon::contextHeap())
            CutOp(1, CmpCommon::contextHeap()),
          REL_TSJ_FLOW,
          NULL,
          FALSE,
          FALSE,
          CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
     NestedJoinFlow(new(CmpCommon::contextHeap())
                      CutOp(0, CmpCommon::contextHeap()),
                    new(CmpCommon::contextHeap())
                      CutOp(1, CmpCommon::contextHeap()),
                    NULL,
                    NULL,
                    CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) HashGroupByRule
    ("Impl: Groupby with a hash table",
     new(CmpCommon::contextHeap())
     WildCardOp(REL_ANY_GROUP,
                0,
                new(CmpCommon::contextHeap())
                  CutOp(0, CmpCommon::contextHeap()),
                NULL,
                CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
     HashGroupBy(new(CmpCommon::contextHeap())
                   CutOp(0, CmpCommon::contextHeap()),
                 REL_HASHED_GROUPBY,
                 NULL,
                 NULL,
                 CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) SortGroupByRule
    ("Impl: Groupby of sorted table",
     new(CmpCommon::contextHeap())
     WildCardOp(REL_ANY_GROUP,
                0,
                new(CmpCommon::contextHeap())
                  CutOp(0, CmpCommon::contextHeap()),
                NULL,
                CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
     SortGroupBy(new(CmpCommon::contextHeap())
                   CutOp(0, CmpCommon::contextHeap()),
                 REL_ORDERED_GROUPBY,
                 NULL,
                 NULL,
                 CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber(),
                        set->getSecondPassNumber());

  r = new(CmpCommon::contextHeap()) AggregateRule
    ("Impl: Aggregate with no grouping columns",
     new(CmpCommon::contextHeap())
     WildCardOp(REL_ANY_GROUP,
                0,
                new(CmpCommon::contextHeap())
                  CutOp(0, CmpCommon::contextHeap()),
                NULL,
                CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
     SortGroupBy(new(CmpCommon::contextHeap())
                   CutOp(0, CmpCommon::contextHeap()),
                 REL_ORDERED_GROUPBY,
                 NULL,
                 NULL,
                 CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) PhysShortCutGroupByRule
    ("Implement ShortCutGroupBy by a PhysicalShortCutGroupBy ",
     new(CmpCommon::contextHeap())
       ShortCutGroupBy(new(CmpCommon::contextHeap())
                        CutOp(0, CmpCommon::contextHeap()),
                       REL_SHORTCUT_GROUPBY,
                       NULL,
                       NULL,
                       CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
       PhysShortCutGroupBy(new(CmpCommon::contextHeap())
                            CutOp(0, CmpCommon::contextHeap()),
                           REL_SHORTCUT_GROUPBY,
                           NULL,
                           NULL,
                           CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber(),
                        set->getSecondPassNumber());

  r = new(CmpCommon::contextHeap()) UnionRule
    ("Implementation rule for Union nodes",
     new(CmpCommon::contextHeap())
       Union(new(CmpCommon::contextHeap()) CutOp(0, CmpCommon::contextHeap()),
             new(CmpCommon::contextHeap()) CutOp(1, CmpCommon::contextHeap()),
             NULL,
             NULL,
             REL_UNION,
             CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
       MergeUnion(new(CmpCommon::contextHeap())
                    CutOp(0, CmpCommon::contextHeap()),
                  new(CmpCommon::contextHeap())
                    CutOp(1, CmpCommon::contextHeap()),
                  NULL,
                  REL_MERGE_UNION,
                  CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) HbaseDeleteRule
    ("Hbase Delete Implementation rule",
     new(CmpCommon::contextHeap())
       Delete(anyCorrName,
              NULL,
              REL_UNARY_DELETE,
              new(CmpCommon::contextHeap())
                Scan(REL_SCAN, CmpCommon::contextHeap()),
              NULL, NULL,
	      NULL,
              CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
       HbaseDelete(
                 CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) HbaseUpdateRule
    ("Hbase Update Implementation rule",
     new(CmpCommon::contextHeap())
       Update(anyCorrName,
              NULL,
              REL_UNARY_UPDATE,
              new(CmpCommon::contextHeap())
                Scan(REL_SCAN, CmpCommon::contextHeap()),
              NULL, NULL,
              CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
       HbaseUpdate(
                 CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) HiveInsertRule
    ("Implementation rule for hive Insert",
     new(CmpCommon::contextHeap())
       Insert(anyCorrName,
              NULL,
              REL_LEAF_INSERT,
              NULL,
              NULL,
              NULL,
              CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
     HiveInsert(anyCorrName,
                        NULL,
                        REL_HIVE_INSERT,
                        NULL,
               CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) HbaseInsertRule
    ("Implementation rule for hbase Insert",
     new(CmpCommon::contextHeap())
       Insert(anyCorrName,
              NULL,
              REL_LEAF_INSERT,
              NULL,
              NULL,
              NULL,
              CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
     HbaseInsert(anyCorrName,
                        NULL,
                        REL_HBASE_INSERT,
                        NULL,
               CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) HbaseDeleteCursorRule
    ("Hbase Delete using cursor",
     new(CmpCommon::contextHeap())
       Delete(anyCorrName,
              NULL,
              REL_LEAF_DELETE,
	      NULL,
              NULL, NULL,
	      NULL,
              CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
       HbaseDelete(
                 CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) HbaseUpdateCursorRule
    ("Hbase Update using cursor",
     new(CmpCommon::contextHeap())
       Update(anyCorrName,
              NULL,
              REL_LEAF_UPDATE,
	      NULL,
              NULL, NULL,
              CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
       HbaseUpdate(
                 CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) PhysicalMapValueIdsRule
    ("Implement MapValueIds by a PhysicalMapValueIds",
     new(CmpCommon::contextHeap())
     MapValueIds(new(CmpCommon::contextHeap())
                   CutOp(0, CmpCommon::contextHeap()),
                 CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
     PhysicalMapValueIds(new(CmpCommon::contextHeap())
                           CutOp(0, CmpCommon::contextHeap()),
                         CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) PhysicalRelRootRule
    ("Implement RelRoot by a PhysicalRelRoot",
     new(CmpCommon::contextHeap())
     RelRoot(new(CmpCommon::contextHeap())
               CutOp(0, CmpCommon::contextHeap()),
             REL_ROOT,
             NULL,
             NULL,
             NULL,
             NULL,
             CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
     PhysicalRelRoot(new(CmpCommon::contextHeap())
                       CutOp(0, CmpCommon::contextHeap()),
                     CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) PhysicalTupleRule
    ("Implement Tuple by a PhysicalTuple",
     new(CmpCommon::contextHeap()) Tuple(NULL, CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap()) PhysicalTuple(CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) PhysicalTupleListRule
   ("Implement TupleList by a PhysicalTupleList",
    new(CmpCommon::contextHeap()) TupleList(NULL, CmpCommon::contextHeap()),
    new(CmpCommon::contextHeap()) PhysicalTupleList(CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) SortEnforcerRule(
       "Enforcer rule to sort a result",
       new(CmpCommon::contextHeap())
         CutOp(0, CmpCommon::contextHeap()),
       new(CmpCommon::contextHeap())
         Sort(new(CmpCommon::contextHeap())
                CutOp(0, CmpCommon::contextHeap()),
              CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  // set global variable
  SortEnforcerRuleNumber = r->getNumber();

  r = new(CmpCommon::contextHeap()) ExchangeEnforcerRule(
       "Enforce partitioning or plan location",
       new(CmpCommon::contextHeap())
         CutOp(0, CmpCommon::contextHeap()),
       new(CmpCommon::contextHeap())
         Exchange(new(CmpCommon::contextHeap())
                    CutOp(0, CmpCommon::contextHeap()),
                  CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) PhysicalExplainRule
    ("Implement ExplainFunc by a PhysicalExplain",
     new(CmpCommon::contextHeap())
       ExplainFunc(NULL, CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
       PhysicalExplain(CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) PhysicalHiveMDRule
    ("Implement HiveMDaccessFunc by a PhysicalExplain",
     new(CmpCommon::contextHeap())
     HiveMDaccessFunc(NULL, NULL, NULL, CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
       PhysicalHiveMD(CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) PhysicalTransposeRule
    ("Implement Transpose by a PhysicalTranspose",
     new(CmpCommon::contextHeap())
     Transpose(NULL,
               NULL,
               new(CmpCommon::contextHeap())
               CutOp(0, CmpCommon::contextHeap()),
               CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
     PhysTranspose(new(CmpCommon::contextHeap())
                   CutOp(0, CmpCommon::contextHeap()),
                   CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) PhysicalPackRule
    ("Implement Pack by a PhysicalPack",
     new(CmpCommon::contextHeap())
     Pack(0,
          new(CmpCommon::contextHeap()) CutOp(0,CmpCommon::contextHeap()),
          NULL,
          CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
     PhyPack(0,
             new(CmpCommon::contextHeap()) CutOp(0,CmpCommon::contextHeap()),
             CmpCommon::contextHeap())
     );
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) PhysicalUnPackRowsRule
    ("Implement UnPackRows by a PhysUnPackRows",
     new(CmpCommon::contextHeap())
     UnPackRows(0,
                NULL,
                NULL,
                NULL,
                new(CmpCommon::contextHeap())
                CutOp(0,CmpCommon::contextHeap()),
                NULL_VALUE_ID,
                CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
     PhysUnPackRows(new(CmpCommon::contextHeap())
                    CutOp(0,CmpCommon::contextHeap()),
                    CmpCommon::contextHeap())
     );
  set->insert(r);
  set->enable(r->getNumber());

  r = new (CmpCommon::contextHeap())
          PhysCompoundStmtRule
                ( "CompoundStmt Operator to PhysCompoundStmt operator",
                   new (CmpCommon::contextHeap())
                       CompoundStmt(
                         new (CmpCommon::contextHeap())
                           CutOp(0, CmpCommon::contextHeap()),
                         new (CmpCommon::contextHeap())
                           CutOp(1, CmpCommon::contextHeap()),
                         REL_COMPOUND_STMT, CmpCommon::contextHeap()),
                   new (CmpCommon::contextHeap())
                       PhysCompoundStmt(new (CmpCommon::contextHeap())
                         CutOp(0, CmpCommon::contextHeap()),
                           new (CmpCommon::contextHeap())
                         CutOp(1, CmpCommon::contextHeap()),
                         REL_COMPOUND_STMT,
                         CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) PhysicalSequenceRule
    ("Implement RelSequence by a PhysSequence",
     new(CmpCommon::contextHeap())
     RelSequence(new(CmpCommon::contextHeap())
                 CutOp(0,CmpCommon::contextHeap()),
                 NULL,
                 CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
     PhysSequence(new(CmpCommon::contextHeap())
                  CutOp(0,CmpCommon::contextHeap()),
                  CmpCommon::contextHeap())
     );
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) PhysicalSampleRule
    ("Implement RelSample by a PhysSample",
     new(CmpCommon::contextHeap())
     RelSample(new(CmpCommon::contextHeap())
               CutOp(0,CmpCommon::contextHeap()),
               RelSample::ANY,
               NULL,
               NULL,
               CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
     PhysSample(new(CmpCommon::contextHeap())
                CutOp(0,CmpCommon::contextHeap()),
                RelSample::ANY,
                CmpCommon::contextHeap())
     );
  set->insert(r);
  set->enable(r->getNumber());

  r = new (CmpCommon::contextHeap()) PhysicalSPProxyFuncRule
    ("Implement SPProxyFunc by a PhysicalSPProxyFunc",
     new (CmpCommon::contextHeap())
       SPProxyFunc(CmpCommon::contextHeap()),
     new (CmpCommon::contextHeap())
       PhysicalSPProxyFunc(CmpCommon::contextHeap())
     );
  set->insert(r);
  set->enable(r->getNumber());

  r = new (CmpCommon::contextHeap()) PhysicalExtractSourceRule
    ("Implement ExtractSource by a PhysicalExtractSource",
     new (CmpCommon::contextHeap())
       ExtractSource(CmpCommon::contextHeap()),
     new (CmpCommon::contextHeap())
       PhysicalExtractSource(CmpCommon::contextHeap())
     );
  set->insert(r);
  set->enable(r->getNumber());

  r = new(CmpCommon::contextHeap()) PhysicalIsolatedScalarUDFRule
    ("Implement IsolatedScalarUDF by a PhysicalIsolatedScalarUDF",
     new(CmpCommon::contextHeap())
     IsolatedScalarUDF(NULL, CmpCommon::contextHeap()),
     new(CmpCommon::contextHeap())
                   PhysicalIsolatedScalarUDF(CmpCommon::contextHeap()));
  set->insert(r);
  set->enable(r->getNumber());

  r = new (CmpCommon::contextHeap())
          PhysicalTMUDFRule
             ("Implement a Table Mapping Function",
              NULL,
              NULL
              );
  set->insert(r);
  set->enable(r->getNumber());

  r = new (CmpCommon::contextHeap())
            PhysicalFastExtractRule
               ("Implement a Fast Extract",
                new (CmpCommon::contextHeap())
                  FastExtract(new(CmpCommon::contextHeap())
                                CutOp(0,CmpCommon::contextHeap()),
                              CmpCommon::contextHeap()),
                new (CmpCommon::contextHeap())
                  PhysicalFastExtract(new(CmpCommon::contextHeap())
                                        CutOp(0,CmpCommon::contextHeap()),
                                      CmpCommon::contextHeap())
                );
    set->insert(r);
    set->enable(r->getNumber());
}

// -----------------------------------------------------------------------
// Static methods for rules operating on GenericUpdate
// (should be a GU method but I'm too lazy to do all the recompiles entailed)
// -----------------------------------------------------------------------

void copyCommonGenericUpdateFields(GenericUpdate *result,
                                   /*const*/ GenericUpdate *bef,
                                   NABoolean setSelectStoi = FALSE)
{
  result->setGroupAttr(bef->getGroupAttr());

  result->updateToSelectMap()      = bef->updateToSelectMap();
  result->newRecExpr()             = bef->newRecExpr();
  result->newRecExprArray()        = bef->newRecExprArray();
  // QSTUFF
  result->newRecBeforeExpr()       = bef->newRecBeforeExpr();
  result->newRecBeforeExprArray()  = bef->newRecBeforeExprArray();
  // QSTUFF
  result->accessOptions()          = bef->accessOptions();
  result->checkConstraints()       = bef->checkConstraints();

  result->beginKeyPred()           = bef->beginKeyPred();
  result->endKeyPred()             = bef->endKeyPred();
  result->executorPred()           = bef->executorPred();
  result->indexNewRecExprArrays()  = bef->indexNewRecExprArrays();
  result->indexBeginKeyPredArray() = bef->indexBeginKeyPredArray();
  result->indexEndKeyPredArray()   = bef->indexEndKeyPredArray();
  result->indexNumberArray()       = bef->indexNumberArray();

  result->setIndexDesc(bef->getTableDesc()->getClusteringIndex());
  result->setScanIndexDesc(bef->getScanIndexDesc());

  result->setMtsStatement(bef->isMtsStatement());

  result->setIsMergeUpdate(bef->isMergeUpdate());
  result->setIsMergeDelete(bef->isMergeDelete());

  result->setNoRollbackOperation(bef->isNoRollback());

  // potentialOutputs_ needs to be copied, even in an implementation rule,
  // for the DP2xxx::codeGen - getReturnRow - producesOutputs call.
  ValueIdSet outputs;
  bef->getPotentialOutputValues(outputs);
  result->setPotentialOutputValues(outputs);

  result->setOptStoi(bef->getOptStoi());
  if (setSelectStoi)
    result->getOptStoi()->getStoi()->setSelectAccess();

  if (bef->currOfCursorName())
    result->currOfCursorName() =
      bef->currOfCursorName()->copyTree(CmpCommon::statementHeap())->castToItemExpr();

  // Note that these last are not simple *copying* operations...
  result->computeUsedCols();
  result->finalizeRowsAffected(bef);

  result->getInliningInfo().merge(&bef->getInliningInfo());

  result->setAvoidHalloweenR2(bef->avoidHalloweenR2());
  result->setAvoidHalloween(bef->avoidHalloween());
  result->setHalloweenCannotUseDP2Locks(bef->getHalloweenCannotUseDP2Locks());
  result->setUpdateCKorUniqueIndexKey(bef->getUpdateCKorUniqueIndexKey());

  // this field is in the base class RelExpr.
  // We should write a RelExpr::copyCommonRelExprFields method instead
  // of copying them here.
  result->setTolerateNonFatalError(bef->getTolerateNonFatalError());
  result->setNoCheck(bef->noCheck());
  result->setPrecondition(bef->getPrecondition());
  result->setProducedMergeIUDIndicator(bef->getProducedMergeIUDIndicator());
  result->setReferencedMergeIUDIndicator(bef->getReferencedMergeIUDIndicator());
}

void copyCommonUpdateFields(Update *result,
			    /*const*/ Update *bef)
{
  result->setGroupAttr(bef->getGroupAttr());

  result->mergeInsertRecExpr()          = bef->mergeInsertRecExpr();
  result->mergeInsertRecExprArray()     = bef->mergeInsertRecExprArray();
  result->mergeUpdatePred()             = bef->mergeUpdatePred();
  
}

void copyCommonDeleteFields(Delete *result,
			    /*const*/ Delete *bef)
{
  result->setGroupAttr(bef->getGroupAttr());

  result->mergeInsertRecExpr()          = bef->mergeInsertRecExpr();
  result->mergeInsertRecExprArray()     = bef->mergeInsertRecExprArray();

  result->csl() = bef->csl();
}

// -----------------------------------------------------------------------
// methods for class FileScanRule
// -----------------------------------------------------------------------

FileScanRule::~FileScanRule() {} 

/**************************************************************************
* Input : list of indexes of the same table
* Output: smallest index and position of the index in the list
* Finds smallest index based on Kb per volume which can be normalized to
* rowSize/volumes because rowCount for the indexes are same.
***************************************************************************/


IndexDesc * findSmallestIndex(const LIST(IndexProperty *) & indexes /*in*/,
			      CollIndex& entry/*out*/)
{
  CostScalar minKbPerVol=csZero;
  CostScalar kbPerVol=csZero;
  IndexDesc * smallestIndex = NULL;
  IndexDesc * index = NULL;
  CollIndex numIndexOnlyIndexes = indexes.entries();
  for(CollIndex i=0;i<numIndexOnlyIndexes;i++)
    {
      index = indexes[i]->getIndexDesc();
      if (index->isClusteringIndex())
	{
	  const PartitioningFunction* physicalPartFunc =
	    index->getPartitioningFunction();

	  // if an explicit partition range has been specified 
	  // as part of the table name to restrict the scan on user specified
	  // partitions, then disable index scan.
	  // This is needed since the index and base table partitions may
	  // not be distributed the same way and an index only scan may not
	  // restrict the partitions as intended by user.
	  // Return the clustering index
	  if (physicalPartFunc && 
	      physicalPartFunc->partitionRangeRestricted())
	    {
	      entry = i;
	      smallestIndex = index;
	      break;
	    }
	}

      kbPerVol = index->getKbPerVolume();
      if(kbPerVol < minKbPerVol OR smallestIndex == NULL)
      {
	minKbPerVol = kbPerVol;
	smallestIndex = index;
	entry = i;
      }
    }
  return smallestIndex;

}

/****************************************************************
* Input : set of indexes of the same table
* Output: smallest index
* Finds smallest index based on Kb per volume which can be normalized to
* rowSize/volumes because rowCount for the indexes are same.
****************************************************************/

IndexDesc * findSmallestIndex(const SET(IndexDesc *) & indexes)
{
  CostScalar minKbPerVol=csZero;
  CostScalar kbPerVol=csZero;
  IndexDesc * smallestIndex = NULL;
  IndexDesc * index = NULL;
  CollIndex numIndexOnlyIndexes = indexes.entries();
  int maxPriorityDelta = 0;
  int priorityDelta = 0;

  for(CollIndex i=0;i<numIndexOnlyIndexes;i++)
    {
      index = indexes[i];
      if (index->isClusteringIndex())
	{
	  const PartitioningFunction* physicalPartFunc =
	    index->getPartitioningFunction();

	  // if an explicit partition range has been specified 
	  // as part of the table name to restrict the scan on user specified
	  // partitions, then disable index scan.
	  // This is needed since the index and base table partitions may
	  // not be distributed the same way and an index only scan may not
	  // restrict the partitions as intended by user.
	  // Return the clustering index
	  if (physicalPartFunc && 
	      physicalPartFunc->partitionRangeRestricted())
	    {
	      smallestIndex = index;
	      break;
	    }
	}

      priorityDelta = index->indexHintPriorityDelta();
      // check priority first, then size
      if (priorityDelta >= maxPriorityDelta)
      {
        kbPerVol = index->getKbPerVolume();
        if(kbPerVol < minKbPerVol OR
           smallestIndex == NULL OR
           priorityDelta > maxPriorityDelta)
          {
            minKbPerVol = kbPerVol;
            smallestIndex = index;
          }
        maxPriorityDelta = priorityDelta;
      }
    }
  return smallestIndex;

}

/**************************************************************************
* Input : list of indexes
* Output: Most partitioned index and position of the index in the list
***************************************************************************/

IndexDesc * findMostPartitionedIndex(const LIST(IndexProperty *)& indexes,CollIndex& entry)
{
  CollIndex numPartitions = 0;
  CollIndex maxNumPartitions = 0;
  IndexDesc * index = NULL;
  IndexDesc * mostPartitionedIndex = NULL;
  CollIndex numIndexOnlyIndex = indexes.entries();
  for(CollIndex i=0;i<numIndexOnlyIndex;i++)
    {
      index = indexes[i]->getIndexDesc();
      numPartitions = (index->getPartitioningFunction()?((NodeMap *)(index->
	getPartitioningFunction()->getNodeMap()))->getNumActivePartitions():1);
      if(numPartitions > maxNumPartitions OR mostPartitionedIndex == NULL)
      {
	maxNumPartitions = numPartitions;
	mostPartitionedIndex = index;
	entry = i;
      }
    }
  return mostPartitionedIndex;
}
/**************************************************************************
* Input : list of indexes
* Output: Return TRUE if one of the index can provide a promising index join
* plan.
***************************************************************************/
// This function is never code in the code base (checked in M5):1064
NABoolean oneViableIndexJoin(const LIST(IndexProperty *) & indexes)
{
  CollIndex ixCount = indexes.entries();
  for(CollIndex i=0;i<ixCount; i++)
  {
    if(indexes[i]->getSelectivity() == INDEX_JOIN_VIABLE)
    {
      return TRUE;
    }
  }
  return FALSE;
}


/**************************************************************************
* Input : list of indexes, order comparison enums and input context.
* Output: Removes indexes from the list that are not promising for an index
* join plan. Removes corresponding oc enums. Have to make sure inputEstLogProp
* is in the error range of initialEstLogProp used to determine the promise.
***************************************************************************/
void removeLowSelectivityIndexJoins(	LIST(IndexProperty *)& indexes,
					LIST(OrderComparison)& ocEnums,
					const Context * context
					)
{

  CostScalar inputCardinality = csOne;
  CostScalar defInputCardinality = csOne;
  if(context->getInputLogProp())
    inputCardinality = context->getInputLogProp()->getResultCardinality();
  if(indexes[0]->getInputEstLogProp())
    defInputCardinality = indexes[0]->getInputEstLogProp()->getResultCardinality();
  if(inputCardinality > defInputCardinality * CURRSTMT_OPTDEFAULTS->acceptableInputEstLogPropError())
  {
    for(CollIndex i=0;i<indexes.entries();i++)
    {
      if(indexes[i]->getSelectivity()==EXCEEDS_BT_SCAN AND indexes.entries() >1)
      {
	indexes.removeAt(i);
	ocEnums.removeAt(i);
	i--;
      }
    }
  }
}

/**************************************************************************
* Input : list of indexes
* Output: Return TRUE if one of the index has bad key access or in other words
* MDAM is not viable.
***************************************************************************/
NABoolean oneWithMdamOff(const LIST(IndexProperty *) & indexes)
{
  CollIndex ixCount = indexes.entries();
  for(CollIndex i=0;i<ixCount; i++)
  {
    if(indexes[i]->getMdamFlag() == MDAM_OFF)
    {
      return TRUE;
    }
  }
  return FALSE;
}

/**************************************************************************
* Input : list of indexes
* Output: Return TRUE if one of the index has good key access or in other
* words MDAM is viable.
***************************************************************************/
NABoolean oneWithMdamOn(const LIST(IndexProperty *) & indexes)
{
  CollIndex ixCount = indexes.entries();
  for(CollIndex i=0;i<ixCount; i++)
  {
    if(indexes[i]->getMdamFlag() == MDAM_ON)
    {
      return TRUE;
    }
  }
  return FALSE;
}

/*************************************************************************
* Input: Index list and corresponding OrderComparisons.
* Output: Removes indexes that have bad key access unless they are partitioned
* better than the indexes with good key access.
*************************************************************************/
void removeBadKeyIndexes( LIST(IndexProperty *)& indexes,
			  LIST(OrderComparison)& ocEnums
			  )
{
  CollIndex numOfVols = 1;
  CollIndex maxNumOfVols = 1;
  if(oneWithMdamOff(indexes) AND oneWithMdamOn(indexes))
  {
    for(CollIndex i=0;i<indexes.entries();i++)
    {
      if(indexes[i]->getMdamFlag() == MDAM_ON)
      {
	numOfVols = (indexes[i]->getIndexDesc()->getPartitioningFunction()?((NodeMap *)(indexes[i]
		->getIndexDesc()->getPartitioningFunction()->getNodeMap()))->getNumOfDP2Volumes():1);
	if(numOfVols > maxNumOfVols)
	{
	  maxNumOfVols = numOfVols;
	}
      }
    }

    if(maxNumOfVols >1)
    {
      for(CollIndex j=0;j<indexes.entries();j++)
      {
       if(indexes[j]->getMdamFlag() == MDAM_OFF AND (indexes[j]->getIndexDesc()->getPartitioningFunction() == NULL
	OR ((NodeMap *)(indexes[j]->getIndexDesc()->getPartitioningFunction()
		->getNodeMap()))->getNumOfDP2Volumes() <= maxNumOfVols))
	{
	  indexes.removeAt(j);
	  ocEnums.removeAt(j);
	  j--;
	}
      }
    }
  }
}

/*********************************************************************
* Just a cut and pasted from FileScanRule::nextSubstitute(). Creates
* DP2Scan for the given index.
*********************************************************************/
void createAndInsertDP2Scan( const IndexDesc * idesc,
			     Scan * bef,
			      RuleSubstituteMemory *& memory,
			      const Disjuncts * disjunctsPtr,
			      OrderComparison oc,
                             MdamFlags ixMdamFlag = UNDECIDED)
{
  // generate a file scan node to scan the index

        FileScan *fileScan =
            new(CmpCommon::statementHeap())
          DP2Scan(bef->getTableName(),
                  bef->getTableDesc(),
                  idesc,
                  oc==INVERSE_ORDER,
                  bef->getBaseCardinality(),
                  bef->accessOptions(),
                  bef->getGroupAttr(),
                  bef->getSelectionPred(),
                  *disjunctsPtr);


        (void) bef->copyTopNode(fileScan, CmpCommon::statementHeap());

        fileScan->setOptStoi(bef->getOptStoi());
        fileScan->setSingleVerticalPartitionScan(
                    bef->isSingleVerticalPartitionScan());
        fileScan->pkeyHvarList() = bef->pkeyHvarList();

        // Set the sampling related fields
        fileScan->sampledColumns() += bef->sampledColumns();
        fileScan->samplePercent(bef->samplePercent());
        fileScan->clusterSize(bef->clusterSize());
	fileScan->setMdamFlag(ixMdamFlag);

        if (fileScan->isHiveTable())
          {
            ValueIdSet preds(bef->selectionPred());
            HivePartitionAndBucketKey *hpk =
              new(CmpCommon::statementHeap()) HivePartitionAndBucketKey(
                   bef->getTableDesc()->getClusteringIndex()->
                   getNAFileSet()->getHHDFSTableStats(),
                   ValueIdList(), // dummies for now
                   ValueIdList(),
                   preds);
            fileScan->setHiveSearchKey(hpk);
          }

        // add the file scan to the list of substitutes
        memory->insert(fileScan);
}

void createAndInsertHbaseScan(IndexDesc * idesc,
			     Scan * bef,
			     RuleSubstituteMemory *& memory,
			     //const MaterialDisjuncts * disjunctsPtr,
			     const Disjuncts * disjunctsPtr,
                             const ValueIdSet &generatedCCPreds,
			     OrderComparison oc,
                             MdamFlags ixMdamFlag = UNDECIDED)
{
  // generate a hbase scan node 

   HbaseAccess * hbaseScan = new(CmpCommon::statementHeap())
          HbaseAccess(bef->getTableName(),
                  bef->getTableDesc(),
                  idesc,
                  oc==INVERSE_ORDER,
                  bef->getBaseCardinality(),
                  bef->accessOptions(),
                  bef->getGroupAttr(),
                  bef->getSelectionPred(),
                  *disjunctsPtr,
                  generatedCCPreds
                 );

   idesc->getPrimaryTableDesc()->getTableColStats();

   (void) bef->copyTopNode(hbaseScan, CmpCommon::statementHeap());

   hbaseScan->setOptStoi(bef->getOptStoi());
   hbaseScan->setSingleVerticalPartitionScan(
               bef->isSingleVerticalPartitionScan());
   hbaseScan->pkeyHvarList() = bef->pkeyHvarList();

   // Set the sampling related fields
   hbaseScan->sampledColumns() += bef->sampledColumns();
   hbaseScan->samplePercent(bef->samplePercent());
   hbaseScan->clusterSize(bef->clusterSize());
   hbaseScan->setMdamFlag(ixMdamFlag);


  /////////////////////////////////////////////////////////////////////////
  // now set the group attributes of the result's top node
  hbaseScan->setGroupAttr(bef->getGroupAttr());

  // add the scan to the list of substitutes
  memory->insert(hbaseScan);
}

void createAndInsertScan(IndexDesc * idesc,
			 Scan * bef,
			 RuleSubstituteMemory *& memory,
			 //const MaterialDisjuncts * disjunctsPtr,
			 const Disjuncts * disjunctsPtr,
                         const ValueIdSet &generatedCCPreds,
			 OrderComparison oc,
                         MdamFlags ixMdamFlag = UNDECIDED,
                         NABoolean isHbase = FALSE)
{
   if ( !isHbase )
     createAndInsertDP2Scan(idesc, bef, memory, disjunctsPtr, oc, ixMdamFlag);
   else
     createAndInsertHbaseScan(idesc, bef, memory, disjunctsPtr, generatedCCPreds, oc, ixMdamFlag);
}

NABoolean FileScanRule::topMatch(RelExpr * relExpr, Context *context)
{
  if (NOT Rule::topMatch(relExpr,context))
    return FALSE;

  const Scan * bef = (Scan *) relExpr;

  if ((bef->isHbaseTable()))
     return FALSE; // hbase scan is handled by the HbaseScanRule


  if ((bef->isHiveTable()))
    {
      const ReqdPhysicalProperty* rppForMe = context->getReqdPhysicalProperty();
      PartitioningRequirement * partReq = rppForMe->getPartitioningRequirement();

      // Hive table scan executes in master or ESP
      if (rppForMe->executeInDP2())
        return FALSE;

      // The Hive scan can handle only fuzzy and single partition requests for now
      if (partReq &&
          ! partReq->isRequirementExactlyOne() &&
          ! partReq->isRequirementFuzzy())
        return FALSE;

      // A hive scan doesn't have a partitioning key for now (change that later)
      //
      if (partReq &&
          partReq->partitioningKeyIsSpecified() &&
          ! partReq->isRequirementExactlyOne())
        return FALSE;
    }
  else
    {
      // Regular DP2Scan can only execute in DP2.
      if (NOT context->getReqdPhysicalProperty()->executeInDP2())
        return FALSE;
    }

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(context->getReqdPhysicalProperty()))
    return FALSE;

  return TRUE;

}

RelExpr * generateScanSubstitutes(RelExpr * before,
                                  Context * context,
                                  RuleSubstituteMemory *& memory, NABoolean isHbase)
{
  RelExpr *result;

  if (memory == NULL)
  {
    // -----------------------------------------------------------------
    // this is the first call, create all possible file scans
    // -----------------------------------------------------------------

    CMPASSERT(before->getOperatorType() == REL_SCAN);

    // input structures (readonly)
    Scan * bef = (Scan *) before;

    NABoolean resultNeedsToBeOrdered = (context AND context->requiresOrder());
    const ReqdPhysicalProperty* const rppForMe =
                                context->getReqdPhysicalProperty();
    const InputPhysicalProperty* const ippForMe =
                                context->getInputPhysicalProperty();

    // allocate a new memory for multiple substitutes
    memory = new(CmpCommon::statementHeap())
                RuleSubstituteMemory(CmpCommon::statementHeap());

    bef->addIndexInfo();


    // Materialize the disjunct array from the logical scan's
    // (i.e. bef) selection predicates:

    // Must always generate disjuncts, even if MDAM will not be
    // considered.  The 'common' disjunct is used to produce the begin
    // and end keys for the single subset case.
    //
    ValueIdSet inSet(bef->selectionPred());
    const ValueIdSet &generatedComputedColPreds = 
      bef->getComputedPredicates();

    inSet += generatedComputedColPreds;
    Disjuncts *disjunctsPtr =  new (CmpCommon::statementHeap())
      MaterialDisjuncts(inSet);
    Disjuncts *disjunctsPtr0 = disjunctsPtr;
    CMPASSERT(disjunctsPtr);
    CMPASSERT(disjunctsPtr0);
    // -----------------------------------------------------------------
    // Now create all the FileScans for this scan:
    // -----------------------------------------------------------------


    CollIndex numIndexOnlyIndexes = bef->getIndexOnlyIndexes().entries();

    LIST(IndexProperty *) viableIndexes(CmpCommon::statementHeap());
    LIST(OrderComparison) comparisonSet(CmpCommon::statementHeap());


    OrderComparison oc =
	  bef->forceInverseOrder() ? INVERSE_ORDER : SAME_ORDER;
    CollIndex entry =0;
    NABoolean isStream = before->getGroupAttr()->isStream();

    const IndexDesc* fastDeleteIndexDesc = 
        CURRSTMT_OPTDEFAULTS->getRequiredScanDescForFastDelete();

    //No predicates and no requirements just select the smallest index
    if(	CURRSTMT_OPTDEFAULTS->indexEliminationLevel() != OptDefaults::MINIMUM AND
	resultNeedsToBeOrdered == FALSE AND
	(ippForMe == NULL OR ippForMe->getAssumeSortedForCosting()) AND
	rppForMe->getDp2SortOrderPartReq() == NULL AND
	NOT  isStream AND
	bef->selectionPred().isEmpty() AND
        fastDeleteIndexDesc == NULL
      )
    {
      IndexDesc * smallestIndex;
      if(bef->getIndexOnlyIndexes().entries() >1)
	smallestIndex = findSmallestIndex(
					    bef->deriveIndexOnlyIndexDesc());
      else
	smallestIndex = bef->deriveIndexOnlyIndexDesc()[0];

      createAndInsertScan(smallestIndex,bef,memory,disjunctsPtr,generatedComputedColPreds,oc,MDAM_OFF,isHbase);

    }
    else
    {
      for (CollIndex i = 0; i < numIndexOnlyIndexes; i++)
      {
	NABoolean indexQualifies = TRUE;

        // hbase does not support inverse order scan
	oc =
	  (!isHbase && bef->forceInverseOrder()) ? INVERSE_ORDER : SAME_ORDER;

	IndexProperty *ixProp = bef->getIndexOnlyIndexes()[i];
	IndexDesc * idesc = ixProp->getIndexDesc();

        if ( fastDeleteIndexDesc && fastDeleteIndexDesc != idesc )
           continue;

	if (idesc->isClusteringIndex())
	  {
	    const PartitioningFunction* physicalPartFunc =
	      idesc->getPartitioningFunction();
	    
	    // if an explicit partition range has been specified 
	    // as part of the table name to restrict the scan on user
	    // specified partitions, then disable index scan.
	    // This is needed since the index and base table partitions may
	    // not be distributed the same way and an index only scan may not
	    // restrict the partitions as intended by user.
	    // Return the clustering index.
	    if (physicalPartFunc && 
		physicalPartFunc->partitionRangeRestricted())
	      {
		viableIndexes.clear();
		comparisonSet.clear();
		viableIndexes.insert(ixProp);
		comparisonSet.insert(oc);
		
		break;
	      }
	  }

	// if an ordering is required, the index must supply the required
	// order or arrangement
	if (resultNeedsToBeOrdered)
	{
	  ValueIdList sortKey = idesc->getOrderOfKeyValues();

	  // Make sure it satisfies the required order and also
	  // determine the scan direction. If computed column predicates
          // select only one salt or division value, for example,
          // then make use of this to satisfy order requirements.
          if ((rppForMe->getSortKey() != NULL) AND
              ((oc = sortKey.satisfiesReqdOrder(
                       *rppForMe->getSortKey(),
                       before->getGroupAttr(),
                       &bef->getComputedPredicates())) == DIFFERENT_ORDER))
            indexQualifies = FALSE;

          // hbase does not support inverse order scan
          if ( oc == INVERSE_ORDER && isHbase )
            indexQualifies = FALSE;
	  
	  // make sure it satisfies the required arrangement
          if (indexQualifies AND
              (rppForMe->getArrangedCols() != NULL) AND
              NOT sortKey.satisfiesReqdArrangement(
                    *rppForMe->getArrangedCols(),
                    before->getGroupAttr(),
                    &bef->getComputedPredicates()))
            indexQualifies = FALSE;
	}

	// If there is a DP2 sort order partitioning requirement, make
	// sure the physical partitioning function of the index matches it.
	if (indexQualifies AND
	    (rppForMe->getDp2SortOrderPartReq() != NULL))
	{
	  const PartitioningFunction* physicalPartFunc =
          idesc->getPartitioningFunction();
	  if (physicalPartFunc == NULL)
	  {
	    physicalPartFunc = new(CmpCommon::statementHeap())
            SinglePartitionPartitioningFunction();
	  }

	  if (NOT rppForMe->getDp2SortOrderPartReq()->partReqAndFuncCompatible(
	       physicalPartFunc))
	    indexQualifies = FALSE;

	}

        // Skip NJ with Hive table as the inner for now
        //
        //if (isHiveTable AND (ippForMe != NULL))
        //  indexQualifies = FALSE;

	// If there are input physical properties, the index must be
	// able to use the outer table ordering.
	if (indexQualifies AND (ippForMe != NULL)
	    AND (!(ippForMe->getAssumeSortedForCosting())))
	{
	  CMPASSERT((ippForMe->getNjOuterOrder() != NULL) AND
                  NOT ippForMe->getNjOuterOrder()->isEmpty());
	  CMPASSERT(ippForMe->getNjOuterOrderPartFunc() != NULL);

	  const PartitioningFunction* physicalPartFunc =
	    idesc->getPartitioningFunction();
	  if (physicalPartFunc == NULL)
	  {
	    physicalPartFunc = new(CmpCommon::statementHeap())
	      SinglePartitionPartitioningFunction();
	  }

	  // If the outer order is a DP2 sort order, then the
	  // njDp2OuterOrderPartFunc and the index partitioning
	  // function must match exactly or the outer order cannot be used.
	  const PartitioningFunction* njDp2OuterOrderPartFunc =
	    ippForMe->getNjDp2OuterOrderPartFunc();
	  if ((njDp2OuterOrderPartFunc != NULL) AND
	     (njDp2OuterOrderPartFunc->
	        comparePartFuncToFunc(*physicalPartFunc) != SAME))
	    indexQualifies = FALSE;

	  // To be able to use an outer table ordering, the outer
	  // table partitioning function must be a replicateNoBroadcast
	  // partitioning function or must be a grouping of the
	  // index partitioning function.
	  const PartitioningFunction* njOuterOrderPartFunc =
	    ippForMe->getNjOuterOrderPartFunc();
	  if (indexQualifies AND
	     NOT njOuterOrderPartFunc->
                  isAReplicateNoBroadcastPartitioningFunction() AND
	      NOT njOuterOrderPartFunc->isAGroupingOf(*physicalPartFunc) )
	    indexQualifies = FALSE;

	  if (indexQualifies)
	  {
	    // Don't create a plan with this index unless it can use
	    // the outer table order for reducing it's I/O cost. In
	    // other words, the outer table order - i.e. the probes
	    // order - must be at least partially in the same order
	    // as the index sort key columns that are covered by
	    // equijoin predicates.

	    // Determine which columns of the index sort key are
	    // equijoin columns, up to the first column not covered
	    // by a constant or equijoin column.
	    ValueIdList sortKey = idesc->getOrderOfKeyValues();
	    ValueIdList uncoveredCols;
	    ValueIdList equiJoinCols =
	      sortKey.findNJEquiJoinCols(
              ippForMe->getNjOuterCharOutputs(),
              before->getGroupAttr()->getCharacteristicInputs(),
              uncoveredCols);

	    if (equiJoinCols.isEmpty())
	    {
	      // Can't use outer table order for this index if it doesn't
	      // have any leading equijoin columns.
	      indexQualifies = FALSE;
	    }
	    else
	    {
	      // Determine if the leading equijoin column and the leading
	      // column of the outer order are the same.
	      ValueIdList njOuterOrder = *(ippForMe->getNjOuterOrder());

	      // Remove any inverse node on the leading equijoin column
	      // and remember if there was one.
	      ValueId equiJoinCol = equiJoinCols[0];
	      ValueId noInverseEquiJoinCol =
              equiJoinCol.getItemExpr()->removeInverseOrder()->getValueId();
	      NABoolean equiJoinColIsDesc = FALSE;
	      if (noInverseEquiJoinCol != equiJoinCol)
		equiJoinColIsDesc = TRUE;

	      // Remove any inverse node on the leading outer order column
	      // and remember if there was one.
	      ValueId outerOrderCol = njOuterOrder[0];
	      ValueId noInverseOuterOrderCol =
		outerOrderCol.getItemExpr()->removeInverseOrder()->getValueId();
	      NABoolean outerOrderColIsDesc = FALSE;
	      if (noInverseOuterOrderCol != outerOrderCol)
		outerOrderColIsDesc = TRUE;

	      // Leading equijoin column of the index sort key and the
	      // leading column of the outer table sort key must be
	      // the same. If one is DESC, they must both be DESC.
	      if ((noInverseEquiJoinCol != noInverseOuterOrderCol) OR
	         (equiJoinColIsDesc != outerOrderColIsDesc))
		indexQualifies = FALSE;

	    } // end if index key has leading equijoin cols
	  } // end if index still qualifies
	} // end if ipp exist and index still qualifies


	// QSTUFF
	if (indexQualifies && before->getGroupAttr()->isStream())
	{
	  if (NOT idesc->isClusteringIndex())
          {
	    // we only test whether the condition holds for a secondary
	    // index, the cluster index, i.e. the base table will produce
	    // all output values
	    ValueIdSet outputs =
              (before->getGroupAttr()->isEmbeddedUpdate() ?
               before->getGroupAttr()->getGenericUpdateRootOutputs() :
               before->getGroupAttr()->getCharacteristicOutputs());

            ValueIdList vegcolumns;

            ((Scan *)before)->getTableDesc()->
              getEquivVEGCols(idesc->getIndexColumns(),vegcolumns);

            ValueIdSet columns(vegcolumns);
            outputs.removeCoveredExprs(columns);


            if (NOT (outputs.isEmpty() ||
              before->getGroupAttr()->isEmbeddedDelete()))
              {
                *CmpCommon::diags() << DgSqlCode(4207)
                  << DgTableName(idesc->getNAFileSet()->getExtFileSetName());

                indexQualifies = FALSE;
              }
          }

        if (indexQualifies &&
            resultNeedsToBeOrdered &&
            idesc->isPartitioned())
          {
            // 10-010109-0583 "select ... from stream ...order by" causes hang
            // if stream is partn'd."

            //The following check is made to avoid insertion of
            //duplicate combination of error number 4212 and its
            //associated extFileSetName.
            if(!((*CmpCommon::diags()).containsForFile(4212,
			((idesc->getNAFileSet()->getExtFileSetName()).data()))))
               *CmpCommon::diags() << DgSqlCode(4212)
                      << DgTableName(idesc->getNAFileSet()->getExtFileSetName());

            indexQualifies = FALSE;
          }

         //Do not consider plans which have stream access on partitioned
         //access paths when the flag ATTEMPT_ASYNCHRONOUS_ACCESS is
         //OFF. This is because, the split top operator is not used.
         //Instead, a partition access operator is used, but the PA handles
         //multiple partitions by looking for the end-of-data from the current
         //partition, and then sending the request to the next partition.
         //For streams, there is no end-of-data.

        if(indexQualifies &&
	    isStream &&
	     idesc->isPartitioned() &&
              CmpCommon::getDefault(ATTEMPT_ASYNCHRONOUS_ACCESS) == DF_OFF)
	  {
	   if(!((*CmpCommon::diags()).containsForFile(4320,
               ((idesc->getNAFileSet()->getExtFileSetName()).data()))))
               *CmpCommon::diags() << DgSqlCode(4320)
               << DgTableName(idesc->getNAFileSet()->getExtFileSetName());

             indexQualifies = FALSE;
         }
     }
      // QSTUFF

	if (indexQualifies)
	{

	  viableIndexes.insert(ixProp);
	  comparisonSet.insert(oc);


	}  // if index qualifies
      } // for every index
    }
  if(viableIndexes.entries() ==1)
  {
    ValueIdSet keyColSet(viableIndexes[0]->getIndexDesc()->getIndexKey());
    usePartofSelectionPredicatesFromTheItemExpressionTree(inSet,keyColSet.convertToBaseIds());
    disjunctsPtr0 =  new (CmpCommon::statementHeap())
      MaterialDisjuncts(inSet);
    CMPASSERT(disjunctsPtr0);

    createAndInsertScan(viableIndexes[0]->getIndexDesc(),bef,memory,disjunctsPtr0,generatedComputedColPreds,
		        comparisonSet[0],viableIndexes[0]->getMdamFlag(),isHbase);
  }

  else if(	CURRSTMT_OPTDEFAULTS->indexEliminationLevel() != OptDefaults::MINIMUM AND
	NOT isStream AND
	bef->selectionPred().isEmpty() AND viableIndexes.entries() >1)
    {
      //No predicates so select the smallest order/part satisfying index. All the
      //index that are in the viable index set satisfy requirements naturally.
      IndexDesc * smallestIndex = findSmallestIndex(viableIndexes,entry);
      createAndInsertScan(smallestIndex,bef,memory,disjunctsPtr,generatedComputedColPreds,
                          comparisonSet[entry],MDAM_OFF, isHbase);
      //if it is under a nested join then select the index that most number of
      //partitions.
      if((ippForMe!=NULL) AND (!(ippForMe->getAssumeSortedForCosting())))
      {
	IndexDesc * partitionedIndex =
	      findMostPartitionedIndex(viableIndexes,entry);
	if(partitionedIndex != smallestIndex)
	{
	  createAndInsertScan(partitionedIndex,bef,memory,disjunctsPtr,
			      generatedComputedColPreds,comparisonSet[entry],MDAM_OFF, isHbase);
	}
      }
    }
    else //there are predicates
    {

      //eliminate indexes with bad key access and bad index joins
      CollIndex numIndex = viableIndexes.entries();
      if(CURRSTMT_OPTDEFAULTS->indexEliminationLevel() == OptDefaults::MAXIMUM AND
	numIndex >1 AND NOT isStream)
      {
	  removeLowSelectivityIndexJoins(viableIndexes,comparisonSet,context);
	if(viableIndexes.entries() >1)
	  removeBadKeyIndexes(viableIndexes,comparisonSet);
      }

      numIndex = viableIndexes.entries();
      for(CollIndex j=0;j<numIndex;j++)
      {
	createAndInsertScan(viableIndexes[j]->getIndexDesc(),bef,memory,disjunctsPtr0,
		            generatedComputedColPreds,comparisonSet[j],viableIndexes[j]->getMdamFlag(), isHbase);
      }

    }
  }


  // ---------------------------------------------------------------------
  // handle case of multiple substitutes
  // ---------------------------------------------------------------------
  if (memory)
  {
    result = memory->getNextSubstitute();

    if (result == NULL)
    {
      // returned all the substitutes
      // now delete the substitute memory, so we won't be called again
      delete memory;
      memory = NULL;
    }

    // return the next retrieved substitute
    return result;
  }
  else
    return NULL; // rule didn't fire
}

RelExpr * FileScanRule::nextSubstitute(RelExpr * before,
                                      Context * context,
                                      RuleSubstituteMemory *& memory)
{
   return generateScanSubstitutes(before, context, memory, FALSE);
}


// -----------------------------------------------------------------------
// methods for class HbaseScanRule
// -----------------------------------------------------------------------

HbaseScanRule::~HbaseScanRule() {} 

NABoolean HbaseScanRule::topMatch(RelExpr * relExpr, Context *context)
{
  if (NOT Rule::topMatch(relExpr,context))
    return FALSE;

  Scan * scan= (Scan *) relExpr;
  if (scan->getTableDesc()->getNATable()->isHbaseTable() == FALSE)
    return FALSE;

  const ReqdPhysicalProperty* rppForMe = context->getReqdPhysicalProperty();

  // Hbase table scan executes in master or ESP
  if (rppForMe->executeInDP2())
      return FALSE;

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(context->getReqdPhysicalProperty()))
    return FALSE;


  return TRUE;
}

RelExpr * HbaseScanRule::nextSubstitute(RelExpr * before,
                                        Context * context,
                                        RuleSubstituteMemory *& memory)
{
   return generateScanSubstitutes(before, context, memory, TRUE);
}


// -----------------------------------------------------------------------
// methods for class UnionRule
// -----------------------------------------------------------------------

UnionRule::~UnionRule() {} 

NABoolean UnionRule::topMatch(RelExpr * relExpr, Context * context)
{

  if (NOT Rule::topMatch(relExpr,context))
    return FALSE;

  if (((Union *)relExpr)->getSerialUnion() &&
      context->getReqdPhysicalProperty()->getPlanExecutionLocation() != EXECUTE_IN_MASTER)
  {
    return FALSE;
  }

  // QSTUFF
  CMPASSERT(NOT(relExpr->getGroupAttr()->isEmbeddedUpdateOrDelete()));
  // QSTUFF

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(context->getReqdPhysicalProperty()))
    return FALSE;

  // -----------------------------------------------------------------
  // Check whether the union can potentially satisfy the required
  // physical properties.
  // -----------------------------------------------------------------
  if (NOT ((Union *)relExpr)->rppAreCompatibleWithOperator
                     (context->getReqdPhysicalProperty()))
    return FALSE;

  return TRUE;

} // UnionRule::topMatch

RelExpr * UnionRule::nextSubstitute(RelExpr * before,
                                    Context *  /* context */,
                                    RuleSubstituteMemory *& /*memory*/)
{
  MergeUnion *result;
  Union *bef = (Union *) before;

  CMPASSERT(bef->getOperatorType() == REL_UNION);

  // a union node must not have any predicates
  CMPASSERT(bef->getSelectionPred().entries() == 0);

  // return a physical merge union node
  result = new(CmpCommon::statementHeap()) MergeUnion(bef->child(0),
                                                      bef->child(1),
                                                      bef->getUnionMap());

  (void) bef->copyTopNode(result, CmpCommon::statementHeap());

  // now set the attributes of the result's top node
  result->setCondExpr(bef->getCondExpr());
  result->setAlternateRightChildOrderExpr(bef->getAlternateRightChildOrderExpr()); //++ MV
  result->setGroupAttr(bef->getGroupAttr());
  result->setUnionFlags(bef->getUnionFlags());
  result->setControlFlags(bef->getControlFlags()); //++ Triggers -
  result->setBlockStmt(before->isinBlockStmt());

  return result;
}

// -----------------------------------------------------------------------
// methods for class SortGroupByRule
// -----------------------------------------------------------------------

SortGroupByRule::~SortGroupByRule() {} 

NABoolean SortGroupByRule::topMatch (RelExpr *relExpr,
                                     Context *context)
{
  // check if this rule has been disabled via RuleGuidanceCQD
  // the CQD is COMP_INT_77 and it represents a bitmap
  // below we check if the bit # 7 is ON
  if(CURRSTMT_OPTDEFAULTS->isRuleDisabled(7))
    return FALSE;

  if (NOT Rule::topMatch(relExpr,context))
    return FALSE;

  if (relExpr->getOperatorType() == REL_SHORTCUT_GROUPBY)
    return FALSE;

  CMPASSERT(relExpr->getOperatorType() == REL_GROUPBY);

  // QSTUFF
  CMPASSERT(NOT(relExpr->getGroupAttr()->isStream() OR
                relExpr->getGroupAttr()->isEmbeddedUpdateOrDelete()));
  // QSTUFF

  GroupByAgg *grbyagg = (GroupByAgg *) relExpr;

  // Don't apply this rule for aggregate queries with no grouping
  // columns - fire the Aggregate Rule instead.
  if (grbyagg->groupExpr().isEmpty())
    return FALSE;

  // must use sortGroupBy for rollup aggregates
  if (grbyagg->isRollup())
    return TRUE;

  // Settings to limit Sort Group By application
  Lng32 sortGbySetting = CURRSTMT_OPTDEFAULTS->robustSortGroupBy();
  if (context->getReqdPhysicalProperty()->getMustMatch() == NULL &&
      sortGbySetting > 0)
  {
    if (grbyagg->isAPartialGroupByRoot())
    {
      // disallow sortGroupBy from partialGrpByRoot if no order requirement
      if (sortGbySetting >= 1 && !context->requiresOrder())
        return FALSE;

      // disallow sortGroupBy from partialGrpByRoot if requested
    if (sortGbySetting >= 2)
        return FALSE;
    }

    // disallow sortGroupBy in ESP if requested
    if (!context->getReqdPhysicalProperty()->executeInDP2() &&
        sortGbySetting >= 3)
        return FALSE;
  }

  // Do not apply this rule if the Group By elimination rule
  // can be applied.
  if ( grbyagg->isNotAPartialGroupBy() &&
       grbyagg->child(0).getGroupAttr()->isUnique(grbyagg->groupExpr()) )
    return FALSE;

  // can't use this algorithm if there are distinct aggregates
  const ValueIdSet &aggrs = grbyagg->aggregateExpr();
  for (ValueId x = aggrs.init(); aggrs.next(x); aggrs.advance(x))
    {
      Aggregate *agg = (Aggregate *) x.getItemExpr();

      CMPASSERT(x.getItemExpr()->isAnAggregate());

      if (agg->isDistinct())
        {
          ValueIdSet uniqueSet = grbyagg->groupExpr();
          uniqueSet += agg->getDistinctValueId();
          if (NOT grbyagg->child(0).getGroupAttr()->isUnique(uniqueSet))
            return FALSE;
        }
    }

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(context->getReqdPhysicalProperty()))
    return FALSE;

  // Test the eligibility of creating a plan using the given
  // partitioning and location requirements.
  if (NOT grbyagg->rppAreCompatibleWithOperator
                     (context->getReqdPhysicalProperty()))
    return FALSE;

  // if at most 1 row is being returned, then the rule matches
  if (relExpr->getGroupAttr()->getMaxNumOfRows() <= 1)
    return TRUE;


  return TRUE;

} // SortGroupByRule::topMatch()

RelExpr * SortGroupByRule::nextSubstitute(RelExpr * before,
                                          Context * /*context*/,
                                          RuleSubstituteMemory *& /*memory*/)
{
  SortGroupBy *result;
  GroupByAgg *bef = (GroupByAgg *) before;

  // create a sort groupby node
  result = new(CmpCommon::statementHeap()) SortGroupBy(bef->child(0));

  // now set the group attributes of the result's top node
  result->setGroupAttr(bef->getGroupAttr());

  (void) bef->copyTopNode(result, CmpCommon::statementHeap());

  // the required order is determined by SortGroupBy::createContextForAChild()

  return result;
} // SortGroupByRule::nextSubstitute()

// -----------------------------------------------------------------------
// methods for class AggregateRule
// -----------------------------------------------------------------------
AggregateRule::~AggregateRule() {} 

NABoolean AggregateRule::topMatch (RelExpr *relExpr,
                                   Context *context)
{
  if (NOT Rule::topMatch(relExpr,context))
    return FALSE;

  if (relExpr->getOperatorType() == REL_SHORTCUT_GROUPBY)
    return FALSE;

  CMPASSERT(relExpr->getOperatorType() == REL_GROUPBY);

  // QSTUFF
  CMPASSERT(NOT(relExpr->getGroupAttr()->isStream() OR
                relExpr->getGroupAttr()->isEmbeddedUpdateOrDelete()));
  // QSTUFF


  GroupByAgg *grbyagg = (GroupByAgg *) relExpr;

  // Don't apply this rule if there are grouping columns -
  // apply the SortGroupByRule instead.
  if (NOT grbyagg->groupExpr().isEmpty())
    return FALSE;

  // can't use this algorithm if there are distinct aggregates
  // that aren't fake distincts
  const ValueIdSet &aggrs = grbyagg->aggregateExpr();
  for (ValueId x = aggrs.init(); aggrs.next(x); aggrs.advance(x))
    {
      Aggregate *agg = (Aggregate *) x.getItemExpr();

      CMPASSERT(x.getItemExpr()->isAnAggregate());

      if (agg->isDistinct())
        {
          if (NOT grbyagg->child(0).getGroupAttr()->
                             isUnique(agg->getDistinctValueId()))
            return FALSE;
        }
    }

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(context->getReqdPhysicalProperty()))
    return FALSE;

  // Test the eligibility of creating a plan using the given
  // partitioning and location requirements.
  if (NOT grbyagg->rppAreCompatibleWithOperator(
                     context->getReqdPhysicalProperty()))
    return FALSE;

  return TRUE;

} // AggregateRule::topMatch()

// -----------------------------------------------------------------------
// methods for class PhysShortCutGroupByRule
// -----------------------------------------------------------------------

PhysShortCutGroupByRule::~PhysShortCutGroupByRule() {} 

NABoolean PhysShortCutGroupByRule::topMatch (RelExpr *relExpr,
                                             Context *context)
{
  if (NOT Rule::topMatch(relExpr,context))
    return FALSE;

  // make sure we are looking at a short cut group by
  CMPASSERT(relExpr->getOperatorType() == REL_SHORTCUT_GROUPBY);

  // Cast the relexpr pointer to groupbyagg type
  GroupByAgg *grbyagg = (GroupByAgg *) relExpr;

  // The ShortCutGroupBy transformation rule should have already
  // verified that this group by has no group by clause.
  CMPASSERT (grbyagg->groupExpr().isEmpty());

  // The ShortCutGroupBy transformation rule already verified that
  // this group by has an aggregate. Determine what type of aggregate.
  const ValueIdSet &aggrs = grbyagg->aggregateExpr();
  CMPASSERT (NOT aggrs.isEmpty());
  ValueId aggr_valueid = aggrs.init();
  aggrs.next(aggr_valueid);
  ItemExpr *item_expr = aggr_valueid.getItemExpr();
  OperatorTypeEnum aggrType = item_expr->getOperatorType();

  if(aggrType==ITM_ANY_TRUE)
  {
    // AnyTrueGroupByAgg can only be executed in ESP.
    if (context->getReqdPhysicalProperty()->executeInDP2())
      return FALSE;
  }

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(context->getReqdPhysicalProperty()))
    return FALSE;

  // Test the eligibility of creating a plan using the given
  // partitioning and location requirements.
  if (NOT grbyagg->rppAreCompatibleWithOperator
                     (context->getReqdPhysicalProperty()))
    return FALSE;

  return TRUE;

} // PhysShortCutGroupByRule::topMatch()

RelExpr * PhysShortCutGroupByRule::nextSubstitute(RelExpr * before,
                                     Context * /*context*/,
                                     RuleSubstituteMemory *& /*memory*/)
{
  PhysShortCutGroupBy *result;
  ShortCutGroupBy *bef = (ShortCutGroupBy *) before;

  // create a physical shortcut groupby node
  result = new(CmpCommon::statementHeap()) PhysShortCutGroupBy(bef->child(0));

  // now set the group attributes of the result's top node
  result->setGroupAttr(bef->getGroupAttr());

  // Copy over the shortcut groupby private fields, then
  // call the groupbyagg copytopnode to copy the groupby private fields,
  // then call the relexpr copytopnode to copy over all common fields.
  (void) bef->copyTopNode(result, CmpCommon::statementHeap());

  return result;

} // PhysShortCutGroupByRule::nextSubstitute()


// -----------------------------------------------------------------------
// methods for class HashGroupByRule
// -----------------------------------------------------------------------

HashGroupByRule::~HashGroupByRule() {} 

NABoolean HashGroupByRule::topMatch (RelExpr *relExpr,
                                     Context *context)
{
  // check if this rule has been disabled via RuleGuidanceCQD
  // the CQD is COMP_INT_77 and it represents a bitmap
  // below we check if the bit # 6 is ON
  if(CURRSTMT_OPTDEFAULTS->isRuleDisabled(6))
    return FALSE;

  if (NOT Rule::topMatch(relExpr,context))
    return FALSE;

  if (relExpr->getOperatorType() == REL_SHORTCUT_GROUPBY)
    return FALSE;

  CMPASSERT(relExpr->getOperatorType() == REL_GROUPBY);

  GroupByAgg *grbyagg = (GroupByAgg *) relExpr;

  // QSTUFF
  CMPASSERT(NOT(relExpr->getGroupAttr()->isStream() OR
                relExpr->getGroupAttr()->isEmbeddedUpdateOrDelete()));
  // QSTUFF


  // don't apply this rule for aggregate queries
  // a sort group by will do a better job
  if (grbyagg->groupExpr().isEmpty())
    return FALSE;

  // Do not apply this rule if the Group By elimination rule
  // can be applied.
  if ( grbyagg->isNotAPartialGroupBy() &&
       grbyagg->child(0).getGroupAttr()->isUnique(grbyagg->groupExpr()) )
    return FALSE;

  // can't use this algorithm if there are distinct aggregates
  const ValueIdSet &aggrs = grbyagg->aggregateExpr();

  for (ValueId x = aggrs.init(); aggrs.next(x); aggrs.advance(x))
    {
      Aggregate *agg = (Aggregate *) x.getItemExpr();

      CMPASSERT(x.getItemExpr()->isAnAggregate());

      //if it is pivot_group(), currently, hash groupby is not supported
      if (agg->getOperatorType() == ITM_PIVOT_GROUP)
        return FALSE;

      if (agg->isDistinct())
        {
          ValueIdSet uniqueSet = grbyagg->groupExpr();
         uniqueSet += agg->getDistinctValueId();
          if (NOT grbyagg->child(0).getGroupAttr()->isUnique(uniqueSet))
            return FALSE;
        }
    }

  // a hash groupby doesn't produce any useful ordering
  if (context->requiresOrder())
    return FALSE;

  // a hash group cannot be pushed completely to DP2, since overflow
  // cannot be handled in DP2.
  if (grbyagg->isNotAPartialGroupBy() AND
      context->getReqdPhysicalProperty()->executeInDP2())
    return FALSE;

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(context->getReqdPhysicalProperty()))
    return FALSE;

  // Test the eligibility of creating a plan using the given
  // partitioning and location requirements.
  if (NOT grbyagg->rppAreCompatibleWithOperator(
                     context->getReqdPhysicalProperty()))
    return FALSE;

  // groupby rollup is evaluated using SortGroupBy
  if (grbyagg->isRollup())
    return FALSE;

  return TRUE;

} // HashGroupByRule::topMatch()

RelExpr * HashGroupByRule::nextSubstitute(RelExpr * before,
                                          Context * context,
                                          RuleSubstituteMemory *& memory)
{
  HashGroupBy *result;
  GroupByAgg *bef = (GroupByAgg *) before;

  // return a physical node
  result = (HashGroupBy *) Rule::nextSubstitute(before,context,memory);

  (void) bef->copyTopNode(result, CmpCommon::statementHeap());

  return result;
} // HashGroupByRule::nextSubstitute()

// -- MVs
// This method checks is the data to be inserted is ordered according to the
// table's clustering index, so that VSBB insert can be used.
// The code was mostly adapted from CostMethodDP2Insert::computeOperatorCost()
NABoolean Insert::isDataSorted(Insert *bef, const Context *context)
{
  NABoolean probesForceSynchronousAccess; // an unused parameter for ordersMatch().

  const IndexDesc* indexDesc = bef->getTableDesc()->getClusteringIndex();
  ValueIdList targetSortKey = indexDesc->getOrderOfKeyValues();

  // If a target key column is covered by a constant on the source side,
  // then we need to remove that column from the target sort key
  removeConstantsFromTargetSortKey(&targetSortKey,
	                           &(bef->updateToSelectMap()));

  ValueIdSet sourceCharInputs =
    bef->getGroupAttr()->getCharacteristicInputs();
  ValueIdSet targetCharInputs;
  // The char inputs are still in terms of the source. Map them to the target.
  // Note: The source char outputs in the ipp have already been mapped to
  // the target.
  bef->updateToSelectMap().rewriteValueIdSetUp(targetCharInputs,
					       sourceCharInputs);

  return ordersMatch(context->getInputPhysicalProperty(),
		     indexDesc,
		     &targetSortKey,
		     targetCharInputs,
		     FALSE,
		     probesForceSynchronousAccess,
		     TRUE);
}

// -----------------------------------------------------------------------
// methods for class HbaseDeleteRule
// -----------------------------------------------------------------------

HbaseDeleteRule::~HbaseDeleteRule() {} 

NABoolean HbaseDeleteRule::topMatch(RelExpr * relExpr, Context *context)
{
  //  if (NOT ((GenericUpdate *)relExpr)->selectionPred().isEmpty())
  //    return FALSE;

  if (NOT Rule::topMatch(relExpr,context))
    return FALSE;

  Delete * del = (Delete *) relExpr;
  if (del->getTableDesc()->getNATable()->isHbaseTable() == FALSE)
    return FALSE;

  if (del->getTableDesc()->getNATable()->hasLobColumn())
    return FALSE;
  
  // HbaseDelete can only execute above DP2
  if (context->getReqdPhysicalProperty()->executeInDP2())
    return FALSE;

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  //  if (relExpr->rppRequiresEnforcer(context->getReqdPhysicalProperty()))
  // return FALSE;

  CostScalar numberOfRowsToBeDeleted =
    context->getInputLogProp()->getResultCardinality();

  if ((numberOfRowsToBeDeleted > 1) &&
      (NOT del->noCheck()) &&
      (CmpCommon::getDefault(HBASE_SQL_IUD_SEMANTICS) == DF_ON) &&
      (CmpCommon::getDefault(HBASE_UPDEL_CURSOR_OPT) == DF_ON) &&
      ((ActiveSchemaDB()->getDefaults()).getAsLong(COMP_INT_74) == 0))
    return FALSE;

  return TRUE;

}

RelExpr * HbaseDeleteRule::nextSubstitute(RelExpr * before,
                                        // QSTUFF
                                        Context * context,
                                        // QSTUFF
                                        RuleSubstituteMemory *& /*memory*/)
{
  HbaseDelete * result;
  Delete * bef  = (Delete *) before;
  Scan* scan = (Scan*) before->child(0).getPtr();

  // This transformation can be performed only if the table scanned
  // is the same as that being updated.
  if (scan->getTableDesc()->getNATable() != bef->getTableDesc()->getNATable())
    return NULL;

  // Build the new HbaseDelete node
  result = new(CmpCommon::statementHeap())
    HbaseDelete(bef->getTableName(), bef->getTableDesc());

  copyCommonGenericUpdateFields(result, bef);
  copyCommonDeleteFields(result, bef);

  /////////////////////////////////////////////////////////////////////////
  // Setup the hbase search key. The logic is modeled based on 
  // SimpleFileScanOptimizer::constructSearchKey()
  /////////////////////////////////////////////////////////////////////////
  ValueIdSet exePreds(scan->getSelectionPred());

  // only get the first member from the index set
  if ( scan->deriveIndexOnlyIndexDesc().entries() == 0 )
    return NULL;

  IndexDesc* idesc = (scan->deriveIndexOnlyIndexDesc())[0];

  ValueIdSet nonKeyColumnSet;
  idesc->getNonKeyColumnSet(nonKeyColumnSet);

  SearchKey * skey = new(CmpCommon::statementHeap())
    SearchKey(idesc->getIndexKey(),
              idesc->getOrderOfKeyValues(),
              bef->getGroupAttr()->getCharacteristicInputs(),
              TRUE, // forward scan
              exePreds,
              nonKeyColumnSet,
              idesc,
              bef->getTableDesc()->getClusteringIndex());
  result->setSearchKey(skey);
  result->executorPred() = exePreds;
  result->beginKeyPred().clear();

  if ((! skey->isUnique()) &&
      (skey->areAllChosenPredsEqualPreds()) &&
      (NOT bef->noCheck()) &&
      (CmpCommon::getDefault(HBASE_SQL_IUD_SEMANTICS) == DF_ON) &&
      (CmpCommon::getDefault(HBASE_UPDEL_CURSOR_OPT) == DF_ON) &&
      ((ActiveSchemaDB()->getDefaults()).getAsLong(COMP_INT_74) == 0))
    result = NULL;

  return result;
}

// -----------------------------------------------------------------------
// methods for class HbaseDeleteCursorRule
// -----------------------------------------------------------------------

HbaseDeleteCursorRule::~HbaseDeleteCursorRule() {} 

NABoolean HbaseDeleteCursorRule::topMatch(RelExpr * relExpr, Context *context)
{
  //  if (NOT ((GenericUpdate *)relExpr)->selectionPred().isEmpty())
  //    return FALSE;

  if (NOT Rule::topMatch(relExpr,context))
    return FALSE;

  Delete * del = (Delete *) relExpr;
  if (del->getTableDesc()->getNATable()->isHbaseTable() == FALSE)
    return FALSE;
  
  // HbaseDelete can only execute above DP2
  if (context->getReqdPhysicalProperty()->executeInDP2())
    return FALSE;

  CMPASSERT(relExpr->getOperatorType() == REL_LEAF_DELETE);

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  //  if (relExpr->rppRequiresEnforcer(context->getReqdPhysicalProperty()))
  // return FALSE;

  return TRUE;

}

RelExpr * HbaseDeleteCursorRule::nextSubstitute(RelExpr * before,
                                        // QSTUFF
                                        Context * context,
                                        // QSTUFF
                                        RuleSubstituteMemory *& /*memory*/)
{
  HbaseDelete * result;
  Delete * bef  = (Delete *) before;

  // Build the new HbaseDelete node
  result = new(CmpCommon::statementHeap())
    HbaseDelete(bef->getTableName(), bef->getTableDesc());
  result->cursorHbaseOper() = TRUE;

  copyCommonGenericUpdateFields(result, bef);
  copyCommonDeleteFields(result, bef);

  /////////////////////////////////////////////////////////////////////////
  // Setup the hbase search key. The logic is modeled based on 
  // SimpleFileScanOptimizer::constructSearchKey()
  /////////////////////////////////////////////////////////////////////////
  ValueIdSet exePreds(bef->getSelectionPred());
  const IndexDesc* idesc =  bef->getTableDesc()->getClusteringIndex();

  ValueIdSet nonKeyColumnSet;
  idesc->getNonKeyColumnSet(nonKeyColumnSet);

  ValueIdSet beginKeyPreds(bef->getBeginKeyPred());
  exePreds += beginKeyPreds;

  SearchKey * skey = new(CmpCommon::statementHeap())
    SearchKey(idesc->getIndexKey(),
              idesc->getOrderOfKeyValues(),
              bef->getGroupAttr()->getCharacteristicInputs(),
              TRUE, // forward scan
              exePreds,
              nonKeyColumnSet,
              idesc);
  result->setSearchKey(skey);
  result->executorPred() = exePreds;
  result->beginKeyPred().clear();

  return result;
}

// -----------------------------------------------------------------------
// methods for class HbaseUpdateRule
// -----------------------------------------------------------------------

HbaseUpdateRule::~HbaseUpdateRule() {} 

NABoolean HbaseUpdateRule::topMatch(RelExpr * relExpr, Context *context)
{
  //  if (NOT ((GenericUpdate *)relExpr)->selectionPred().isEmpty())
  //    return FALSE;

  if (NOT Rule::topMatch(relExpr,context))
    return FALSE;

  Update * upd = (Update *) relExpr;
  if (upd->getTableDesc()->getNATable()->isHbaseTable() == FALSE)
    return FALSE;
  
  // HbaseUpdate can only execute above DP2
  if (context->getReqdPhysicalProperty()->executeInDP2())
    return FALSE;

  CostScalar numberOfRowsToBeUpdated =
    context->getInputLogProp()->getResultCardinality();

  if ((numberOfRowsToBeUpdated > 1) &&
      (NOT upd->isMerge()) &&
      (CmpCommon::getDefault(HBASE_SQL_IUD_SEMANTICS) == DF_ON) &&
      (CmpCommon::getDefault(HBASE_UPDEL_CURSOR_OPT) == DF_ON))
    return FALSE;

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  //  if (relExpr->rppRequiresEnforcer(context->getReqdPhysicalProperty()))
  // return FALSE;

  return TRUE;

}

RelExpr * HbaseUpdateRule::nextSubstitute(RelExpr * before,
                                        // QSTUFF
                                        Context * context,
                                        // QSTUFF
                                        RuleSubstituteMemory *& /*memory*/)
{
  HbaseUpdate * result;
  Update * bef  = (Update *) before;
  Scan* scan = (Scan*) before->child(0).getPtr();

  // This transformation can be performed only if the table scanned
  // is the same as that being updated.
  if (scan->getTableDesc()->getNATable() != bef->getTableDesc()->getNATable())
    return NULL;

  // Build the new HbaseUpdate node
  result = new(CmpCommon::statementHeap())
    HbaseUpdate(bef->getTableName(), bef->getTableDesc());

  copyCommonGenericUpdateFields(result, bef);
  copyCommonUpdateFields(result, bef);

  /////////////////////////////////////////////////////////////////////////
  // Setup the hbase search key. The logic is modeled based on 
  // SimpleFileScanOptimizer::constructSearchKey()
  /////////////////////////////////////////////////////////////////////////
  ValueIdSet exePreds(scan->getSelectionPred());
  // Use indexdesc of base table, een if the optimizer has chosen an
  // index access path for this soon to be gone scan.
  const IndexDesc* idesc = scan->getTableDesc()->getClusteringIndex();
  ValueIdSet clusteringKeyCols(
       idesc->getClusteringKeyCols());
  ValueIdSet generatedComputedColPreds;

  ValueIdSet nonKeyColumnSet;
  idesc->getNonKeyColumnSet(nonKeyColumnSet);

  if (CmpCommon::getDefault(MTD_GENERATE_CC_PREDS) == DF_ON)
    ScanKey::createComputedColumnPredicates(
         exePreds,
         clusteringKeyCols,
         bef->getGroupAttr()->getCharacteristicInputs(),
         generatedComputedColPreds);

  SearchKey * skey = new(CmpCommon::statementHeap())
    SearchKey(idesc->getIndexKey(),
              idesc->getOrderOfKeyValues(),
              bef->getGroupAttr()->getCharacteristicInputs(),
              TRUE, // forward scan
              exePreds,
              nonKeyColumnSet,
              idesc,
              bef->getTableDesc()->getClusteringIndex());
  result->setSearchKey(skey);
  result->executorPred() = exePreds;
  result->beginKeyPred().clear();

  if ((! skey->isUnique()) &&
      (NOT bef->isMerge()) &&
      (skey->areAllChosenPredsEqualPreds()) &&
      (CmpCommon::getDefault(HBASE_SQL_IUD_SEMANTICS) == DF_ON) &&
      (CmpCommon::getDefault(HBASE_UPDEL_CURSOR_OPT) == DF_ON))
    result = NULL;

  return result;
}

// -----------------------------------------------------------------------
// methods for class HbaseUpdateCursorRule
// -----------------------------------------------------------------------

HbaseUpdateCursorRule::~HbaseUpdateCursorRule() {} 

NABoolean HbaseUpdateCursorRule::topMatch(RelExpr * relExpr, Context *context)
{
  //  if (NOT ((GenericUpdate *)relExpr)->selectionPred().isEmpty())
  //    return FALSE;

  if (NOT Rule::topMatch(relExpr,context))
    return FALSE;

  Update * del = (Update *) relExpr;
  if (del->getTableDesc()->getNATable()->isHbaseTable() == FALSE)
    return FALSE;
  
  // HbaseUpdate can only execute above DP2
  if (context->getReqdPhysicalProperty()->executeInDP2())
    return FALSE;

  CMPASSERT(relExpr->getOperatorType() == REL_LEAF_UPDATE);

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  //  if (relExpr->rppRequiresEnforcer(context->getReqdPhysicalProperty()))
  // return FALSE;

  return TRUE;

}

RelExpr * HbaseUpdateCursorRule::nextSubstitute(RelExpr * before,
                                        // QSTUFF
                                        Context * context,
                                        // QSTUFF
                                        RuleSubstituteMemory *& /*memory*/)
{
  HbaseUpdate * result;
  Update * bef  = (Update *) before;

  // Build the new HbaseUpdate node
  result = new(CmpCommon::statementHeap())
    HbaseUpdate(bef->getTableName(), bef->getTableDesc());
  result->cursorHbaseOper() = TRUE;

  copyCommonGenericUpdateFields(result, bef);
  copyCommonUpdateFields(result, bef);

  /////////////////////////////////////////////////////////////////////////
  // Setup the hbase search key. The logic is modeled based on 
  // SimpleFileScanOptimizer::constructSearchKey()
  /////////////////////////////////////////////////////////////////////////
  ValueIdSet exePreds(bef->getSelectionPred());
  const IndexDesc* idesc = bef->getTableDesc()->getClusteringIndex();

  ValueIdSet nonKeyColumnSet;
  idesc->getNonKeyColumnSet(nonKeyColumnSet);

  ValueIdSet beginKeyPreds(bef->getBeginKeyPred());
  exePreds += beginKeyPreds;

  SearchKey * skey = new(CmpCommon::statementHeap())
    SearchKey(idesc->getIndexKey(),
              idesc->getOrderOfKeyValues(),
              bef->getGroupAttr()->getCharacteristicInputs(),
              TRUE, // forward scan
              exePreds,
              nonKeyColumnSet,
              idesc);
  result->setSearchKey(skey);
  result->executorPred() = exePreds;
  result->beginKeyPred().clear();

  return result;
}

// -----------------------------------------------------------------------
// methods for class HiveInsertRule
// -----------------------------------------------------------------------
HiveInsertRule::~HiveInsertRule() {} 

NABoolean HiveInsertRule::topMatch(RelExpr * relExpr, Context *context)
{
  if (NOT Rule::topMatch(relExpr,context))
    return FALSE;

  CMPASSERT(relExpr->getOperatorType() == REL_LEAF_INSERT);
  Insert * ins= (Insert *) relExpr;

  if (ins->getTableDesc()->getNATable()->isHiveTable() == FALSE)
    return FALSE;

  // HiveInsert can only execute above DP2.
  if (context->getReqdPhysicalProperty()->executeInDP2())
    return FALSE;

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  //if (relExpr->rppRequiresEnforcer(context->getReqdPhysicalProperty()))
  //  return FALSE;

  return TRUE;
}

RelExpr * HiveInsertRule::nextSubstitute(RelExpr * before,
                                              Context * context,
                                              RuleSubstituteMemory *& /*mem*/)
{
  CMPASSERT(before->getOperatorType() == REL_LEAF_INSERT);
  CMPASSERT(before->getArity() == 0);

  HiveInsert * result;
  Insert * bef = (Insert *) before;

  // build the key for the insert from the expression for the new record
  SearchKey * skey = NULL;
  const IndexDesc * CIdesc = bef->getTableDesc()->getClusteringIndex();
  const PartitioningFunction* insPartFunc = CIdesc->getPartitioningFunction();

  ValueIdSet externalInputs = before->getGroupAttr()->getCharacteristicInputs();

   NABoolean rangeLoggingRequired =
    bef->getTableDesc()->getNATable()->getMvAttributeBitmap().getAutomaticRangeLoggingRequired();

  CostScalar numberOfRowsToBeInserted =
    context->getInputLogProp()->getResultCardinality();

  if (CIdesc->isPartitioned())
    {
      ValueIdSet tempNewRecExpr (bef->newRecExpr());

      // From the new record expression, divide predicates into
      // partitioning key predicates (on the primary index) vs. non
      // partitioning key predicates.
      ValueIdSet dummySet;
      skey = new(CmpCommon::statementHeap())
        SearchKey (CIdesc->getPartitioningKey(),
                   CIdesc->getOrderOfPartitioningKeyValues(),
                   externalInputs,
                   TRUE,
                   tempNewRecExpr,
                   dummySet,
                   CIdesc);

      // insert is always a row-at-a-time operator
      //CMPASSERT(skey->isUnique());
    }

  result = new(CmpCommon::statementHeap()) 
              HiveInsert(HiveInsert(bef->getTableName(),bef->getTableDesc()));

  copyCommonGenericUpdateFields(result, bef);

  result->setPartKey(skey);
  result->rrKeyExpr()              = bef->rrKeyExpr();
  result->rowPosInput()            = bef->rowPosInput();
  result->partNumInput()           = bef->partNumInput();
  result->totalNumPartsInput()     = bef->totalNumPartsInput();
  result->reqdOrder()              = bef->reqdOrder();
  result->setNoBeginCommitSTInsert(bef->noBeginSTInsert(), bef->noCommitSTInsert());
  result->enableTransformToSTI() = bef->enableTransformToSTI();

  if (result->getGroupAttr()->isEmbeddedInsert())
    result->executorPred() += bef->selectionPred();

  return result;
}

// -----------------------------------------------------------------------
// methods for class HbaseInsertRule
// -----------------------------------------------------------------------
HbaseInsertRule::~HbaseInsertRule() {} 

NABoolean HbaseInsertRule::topMatch(RelExpr * relExpr, Context *context)
{
  if (NOT Rule::topMatch(relExpr,context))
    return FALSE;

  CMPASSERT(relExpr->getOperatorType() == REL_LEAF_INSERT);
  Insert * ins= (Insert *) relExpr;

  if (ins->getTableDesc()->getNATable()->isHbaseTable() == FALSE)
    return FALSE;

  // HbaseInsert can only execute above DP2.
  if (context->getReqdPhysicalProperty()->executeInDP2())
    return FALSE;

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  //if (relExpr->rppRequiresEnforcer(context->getReqdPhysicalProperty()))
  //  return FALSE;

  return TRUE;
}

RelExpr * HbaseInsertRule::nextSubstitute(RelExpr * before,
                                              Context * context,
                                              RuleSubstituteMemory *& /*mem*/)
{
  CMPASSERT(before->getOperatorType() == REL_LEAF_INSERT);
  CMPASSERT(before->getArity() == 0);

  HbaseInsert * result;
  Insert * bef = (Insert *) before;

  // build the key for the insert from the expression for the new record
  SearchKey * skey = NULL;
  const IndexDesc * CIdesc = bef->getTableDesc()->getClusteringIndex();
  const PartitioningFunction* insPartFunc = CIdesc->getPartitioningFunction();

  ValueIdSet externalInputs = before->getGroupAttr()->getCharacteristicInputs();

   NABoolean rangeLoggingRequired =
    bef->getTableDesc()->getNATable()->getMvAttributeBitmap().getAutomaticRangeLoggingRequired();

  CostScalar numberOfRowsToBeInserted =
    context->getInputLogProp()->getResultCardinality();

  if (CIdesc->isPartitioned())
    {
      ValueIdSet tempNewRecExpr (bef->newRecExpr());

      // From the new record expression, divide predicates into
      // partitioning key predicates (on the primary index) vs. non
      // partitioning key predicates.
      ValueIdSet dummySet;
      skey = new(CmpCommon::statementHeap())
        SearchKey (CIdesc->getPartitioningKey(),
                   CIdesc->getOrderOfPartitioningKeyValues(),
                   externalInputs,
                   TRUE,
                   tempNewRecExpr,
                   dummySet,
                   CIdesc);

      // insert is always a row-at-a-time operator
      //CMPASSERT(skey->isUnique());
    }

  result = new(CmpCommon::statementHeap()) 
    HbaseInsert(bef->getTableName(),bef->getTableDesc());

  result->setInsertType(bef->getInsertType());

  DefaultToken vsbbTok = CmpCommon::getDefault(INSERT_VSBB);
  if ((numberOfRowsToBeInserted > 1) &&
      (vsbbTok != DF_OFF) &&
      (result->getInsertType() != Insert::UPSERT_LOAD))
    {
      result->setInsertType(Insert::VSBB_INSERT_USER);
    }

  copyCommonGenericUpdateFields(result, bef);

  result->setPartKey(skey);
  result->rrKeyExpr()              = bef->rrKeyExpr();
  result->rowPosInput()            = bef->rowPosInput();
  result->partNumInput()           = bef->partNumInput();
  result->totalNumPartsInput()     = bef->totalNumPartsInput();
  result->reqdOrder()              = bef->reqdOrder();
  result->setNoBeginCommitSTInsert(bef->noBeginSTInsert(), bef->noCommitSTInsert());
  result->enableTransformToSTI() = bef->enableTransformToSTI();
  result->setIsUpsert(bef->isUpsert());
  result->setIsTrafLoadPrep(bef->getIsTrafLoadPrep());
  result->setCreateUstatSample(bef->getCreateUstatSample());

  if (result->getGroupAttr()->isEmbeddedInsert())
    result->executorPred() += bef->selectionPred();

  return result;
}

// -----------------------------------------------------------------------
// methods for class NestedJoinRule
// -----------------------------------------------------------------------

NestedJoinRule::~NestedJoinRule() {} 

NABoolean NestedJoinRule::topMatch(RelExpr * relExpr,
                                   Context * context)
{

  if (NOT Rule::topMatch(relExpr,context))
    return FALSE;

  Join *joinExpr = (Join *) relExpr;

  // Only TSJ nodes are converted to Nested Joins.
  // Join nodes for which Nested Joins are possible should have
  // been converted to TSJs first.
  // So we want to make sure that if we have a RoutineJoin, which is a
  // type of TSJ, we don't want this rule to apply until we have converted
  // it to a TSJ, so return FALSE for RoutineJoins. isNonRoutineTSJ() returns
  // true for all TSJs except for RoutineJoins.
  if (NOT joinExpr->isNonRoutineTSJ()) return FALSE;

  // The avoidHalloweenR2 flag will be set on two Join nodes.  The join
  // used for the Subquery and the Tuple Flow Join used for write.  If
  // avoidHalloween is set and this is the join used for the subquery,
  // then it must use a hash join. So do not fire the nested join in
  // this case.  If this is the tuple flow for write, then this should fire.
  //
  if (joinExpr->avoidHalloweenR2() &&
      !joinExpr->isTSJForWrite())
    return FALSE;

  // nested join is not supported for Full_Outer_Join
  if (relExpr->getOperator().match(REL_ANY_FULL_JOIN))
    return FALSE;

  //++MV
  //If this node was marked in inlining for single execution ,the rule will be fired
  //only if there is a single input request.
  if (relExpr->getInliningInfo().isSingleExecutionForTSJ() &&
      !context->getInputLogProp()->isCardinalityEqOne())
  {
    return FALSE;
  }
  //--MV

  // QSTUFF
  // we can only implement embedded deletes if no join
  // is multiplying the number of delete tuples returned
  // this rejection hopefully causes the commutativity rule to trigger
  // right now is not really needed, only if we allow deletes on
  // as inner/right child.

  // if (joinExpr->getGroupAttr()->isEmbeddedUpdateOrDelete())
  //   if (NOT (joinExpr->isSemiJoin() OR
  //            joinExpr->isAntiSemiJoin() OR
  //            joinExpr->isCursorUpdate()))
  //     if (NOT joinExpr->rowsFromLeftHaveUniqueMatch())
  //       return FALSE;
  // QSTUFF

/*
  // ********************************************************************
  // This part is disabled untill we have a better way of protecting
  // the normalizer output TSJs, and TSJs for write, and TSJs for
  // index joins. In other words, we should only do this heuristic
  // for "optional" TSJ's, i.e. those that were added by the
  // JoinToTSJRule.
  // ********************************************************************
  if (CURRSTMT_OPTDEFAULTS->optimizerHeuristic4() &&
      context->getInputLogProp()->getResultCardinality() <= 1 &&
      NOT relExpr->getOperator().match(REL_ANY_ANTI_SEMITSJ) &&
      NOT relExpr->getOperator().match(REL_ANY_SEMITSJ) )
     // logic of this heuristic does not apply for subqueries
     // also we will not prune semi joins cuz they might be normalizer
     // output (have no nontsj equivalent). Also we do not prune
     // anti-semi-join cuz so far this is its only implementation.

  {
    CostScalar myCardinality =
      relExpr->child(0).getGroupAttr()->getResultCardinalityForEmptyInput();
    //CostScalar cardinality0 =
      //relExpr->child(0).getGroupAttr()->getResultCardinalityForEmptyInput();
    CostScalar cardinality1 =
      relExpr->child(1).getGroupAttr()->getResultCardinalityForEmptyInput();

    if (myCardinality > cardinality1 AND cardinality1 > 10)
      return FALSE;
  }
*/
  const ReqdPhysicalProperty* const rppForMe =
                                context->getReqdPhysicalProperty();

  // ---------------------------------------------------------------
  // Only allow nested joins to be pushed down to dp2 if flag is on 
  // and the join node is allowed to be pushed down. Currently the
  // TSJRule sets the non-push-down flag to prevent the transformed
  // NestedJoin (for UNARY_INSERT) from being pushed down. 
  // 
  // Colocation check will be done later (need to improve here).
  // Currently, NJ in DP2 for write is disabled.
  // ---------------------------------------------------------------

  if (rppForMe->executeInDP2() AND 
      ( NOT CURRSTMT_OPTDEFAULTS->pushDownDP2Requested() OR
        joinExpr->allowPushDown() == FALSE ))
    return FALSE;

  // disallow pushdown of IM plans
  if (rppForMe->executeInDP2() AND
      relExpr->getInliningInfo().isDrivingIM())
    return FALSE;

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(rppForMe))
    return FALSE;

  // If nested join is being forced for this operator then return TRUE now.
  if ((rppForMe->getMustMatch() != NULL) AND
      (rppForMe->getMustMatch()->getOperatorType() == REL_FORCE_NESTED_JOIN))
    return TRUE;

  // Fix genesis case 10-040524-2077 "NE:RG:mxcmp internal error when stream
  // used with rowset in WHERE clause" by commenting out the following code on
  // This code was intended to provide partial
  // support for identifying which element of a rowset caused an exception as
  // exemplified by regress/rowsets/teste140.sql's test10.
  // An Unpack node should never be the right child of a nested join as this would
  // cause the rownumber feature to  work incorrectly. We are enforcing
  // this condition below.
  //if ((joinExpr->isRowsetIterator()) &&
  //    (joinExpr->child(1).getGroupAttr()->getNumBaseTables() == 0) )
  //  return FALSE;

  // --------------------------------------------------------------------
  // Fire the rule only if NESTED_JOINS default is on, with the
  // following exceptions:
  // - If hash and merge joins are disabled or if hash and merge joins
  //   cannot work, we pick the nested join, even if it was disabled.
  //   A merge join will not work when the query does not have equi-join
  //   predicates.
  // ---------------------------------------------------------------------
  if (NOT CURRSTMT_OPTDEFAULTS->isHashJoinConsidered() AND
      (NOT CURRSTMT_OPTDEFAULTS->isMergeJoinConsidered() OR
       joinExpr->getEquiJoinPredicates().isEmpty()))
    return TRUE;
  else if ((CmpCommon::getDefault(COMP_BOOL_151) == DF_ON) &&
           (NOT CURRSTMT_OPTDEFAULTS->isNestedJoinConsidered())) {
    // allow mandatory nested joins even under nested_joins OFF
    // to fix genesis case 10-070215-6221, solution 10-070215-2604.
    // comp_bool_151 is a hedge if you want ALL nested_joins OFF.
    return FALSE;
  }

  // nested join is not good for filtering joins in the star join schema
  // This check already done in joinToTSJRule, but doublecheck again here
  if (CmpCommon::getDefault(COMP_BOOL_85) == DF_OFF &&
      (joinExpr->getSource() == Join::STAR_FILTER_JOIN) &&
      !(joinExpr->derivedFromRoutineJoin()))
    return FALSE;



  // ---------------------------------------------------------------------
  // Fire the NJ rule for reads that are not index joins and are not
  // for subqueries only if a join predicate exists or if there is a
  // required order or arrangement.  If a join predicate does not exist,
  // a hybrid hash join will perform better for building the cartesian
  // product, unless there is a required order, in which case a HHJ
  // won't work, because a HHJ cannot preserve order.
  // ---------------------------------------------------------------------
  // ********************************************************************
  //   We can't do this until the JoinToTSJRule passes us some indication
  // on whether the original pre-TSJ join was a cross product or not.
  // We cannot figure this out here because the join predicates have
  // already been pushed down. The ideal thing for the JoinToTSJRule
  // to do would be to stash the original join predicates in a new field
  // in the TSJ node. If we do this, we can also use the original join
  // predicates for other purposes, such as determining what the
  // equijoin columns are for doing Type-1 nested joins in DP2.
  //   Also, we need TSJ's added by the JoinToTSJRule to
  // be marked as "optional". For non-optional TSJ's, such as those
  // for write, for subqueries, or for index joins, we MUST always
  // fire the Nested Join rule because there is no other join method
  // available to them.
  //   SO, FOR NOW, ALWAYS SET isACrossProduct TO FALSE.
  // ********************************************************************

  // ---------------------------------------------------------------------
  // If hash joins are disabled consider doing a nested join even if
  // it is a cross product
  // ---------------------------------------------------------------------
  NABoolean isACrossProduct = FALSE;

  // Only consider NJ for cross products if there is a
  // order or arrangement requirement.Otherwise HHJ is better.
  // Now: HHJ can keep order
  if (isACrossProduct)
  {
    //if ((NOT rppForMe->getSortKey() OR
	//    (rppForMe->getSortKey()->entries() == 0)) AND

      if (NOT rppForMe->getArrangedCols() OR
         (rppForMe->getArrangedCols()->entries() == 0))
      return FALSE;
    // One other possible heuristic  we can have here is to require
    // that xproduct output is less than say 10% of largest table size
    // we can do this later
  }



  // MV --
  // If the Join was forced to some other type - fail it.
  if (joinExpr->isPhysicalJoinTypeForced() &&
      joinExpr->getForcedPhysicalJoinType() != Join::NESTED_JOIN_TYPE)
    return FALSE;


  return TRUE;

} // NestedJoinRule::topMatch

RelExpr * NestedJoinRule::nextSubstitute(RelExpr * before,
                                         Context * context, //*context*/,
                                         RuleSubstituteMemory *& /*memory*/)
{
  NestedJoin * result;
  Join     * bef = (Join *) before;

  // QSTUFF
  CMPASSERT (NOT bef->child(1).getGroupAttr()->isStream());
  //  CMPASSERT (NOT bef->child(1).getGroupAttr()->isEmbeddedUpdateOrDelete());
  // QSTUFF


  // build the result from the join node in the before pattern
  result = new(CmpCommon::statementHeap())
    NestedJoin(bef->child(0),
               bef->child(1),
               bef->getNestedJoinOpType(),
               CmpCommon::statementHeap(),
               bef->updateTableDesc(),
               bef->updateSelectValueIdMap());

  // now set the group attributes of the result's top node
  result->setGroupAttr(before->getGroupAttr());

  // transfer all the join fields to the new NestedJoin
  (void) bef->copyTopNode(result,CmpCommon::statementHeap());

  // now we need to make sure that the order and arrangement requirement
  // , if any, can be passed to the NJ childeren
  const ReqdPhysicalProperty* const rppForMe =
                                context->getReqdPhysicalProperty();

  ValueIdList dummy1, dummy2;
  if (rppForMe->getSortKey() AND
      rppForMe->getSortKey()->entries() > 0 AND
      NOT result->splitOrderReq(*(rppForMe->getSortKey()),dummy1,dummy2))
    return NULL;

  ValueIdSet dummy3, dummy4;
  if (rppForMe->getArrangedCols() AND
      rppForMe->getArrangedCols()->entries() > 0 AND
      NOT result->splitArrangementReq(*(rppForMe->getArrangedCols()),dummy3,dummy4))
    return NULL;

  // Pass the original equal join expression to the physical nest join
  // operator so that OCR can use it to check if the equi join expression
  // completes covers right child's partitioning key.
  result->setOriginalEquiJoinExpressions(bef->getOriginalEquiJoinExpressions());

  return result;

} // NestedJoinRule::nextSubstitute()

NABoolean NestedJoinRule::canBePruned(RelExpr * relExpr) const
{
  // We do not want to prune Nested Join Rule if expr is an AntiSemiJoin
  // since thats its only possible implementation in many cases
  // *************************************************************
  // What about Nested Join for write ops? Or subqueries? Or
  // index joins? For all of these, Nested Join is the only
  // possible implementation. Shouldn't we not prune NJ for them?
  // We should only prune NJ for TSJ's that are marked as "optional",
  // i.e. were added by the JoinToTSJRule.
  // HOW DOES THIS POSSIBLY WORK? IT SEEMS THAT PRUNING CAN PRUNE
  // MANDATORY NJ's AND SOME PLANS SHOULD FAIL WITH PRUNING ON. ???
  // *************************************************************
  return NOT relExpr->getOperator().match(REL_ANY_ANTI_SEMIJOIN);
}

// -----------------------------------------------------------------------
// methods for class NestedJoinFlowRule
// -----------------------------------------------------------------------

NestedJoinFlowRule::~NestedJoinFlowRule() {} 

NABoolean NestedJoinFlowRule::topMatch (RelExpr *relExpr,
                                        Context *context)
{
  if (NOT Rule::topMatch(relExpr, context))
    return FALSE;

  Join * joinExpr = (Join *) relExpr; // QSTUFF ?

  // QSTUFF
  // we can only implement embedded deletes if no join
  // is multiplying the number of delete tuples returned
  // this rejection hopefully causes the commutativity rule to trigger

  // if (joinExpr->getGroupAttr()->isEmbeddedUpdateOrDelete() &&
  //      !joinExpr->rowsFromLeftHaveUniqueMatch()){
  //      return FALSE;
  // }
  // QSTUFF

  // if execution inside DP2 is intended, check a few more things.
  // NSJ is allowed to run inside DP2 only if it is inside a CS.
  if (context->getReqdPhysicalProperty()->executeInDP2())
  {
     // if there is no request for pushing down, return false.
     if ( NOT CURRSTMT_OPTDEFAULTS->pushDownDP2Requested() )
        return FALSE;
  }

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(context->getReqdPhysicalProperty()))
    return FALSE;

  return TRUE;
}

RelExpr * NestedJoinFlowRule::nextSubstitute(RelExpr * before,
                                             Context * /*context*/,
                                             RuleSubstituteMemory *& /*memory*/)
{
  NestedJoinFlow * result;
  Join     * bef = (Join *) before;

  // QSTUFF
  CMPASSERT (NOT bef->child(1).getGroupAttr()->isStream());
  CMPASSERT (NOT bef->child(1).getGroupAttr()->isEmbeddedUpdateOrDelete());
  // QSTUFF

  // A tuple substitution flow operator must not have any predicates.
  CMPASSERT(bef->nullInstantiatedOutput().entries() == 0);
  CMPASSERT(bef->selectionPred().entries() == 0);
  CMPASSERT(bef->joinPred().entries() == 0);

  // build the result from the join node in the before pattern
  result = new(CmpCommon::statementHeap())
    NestedJoinFlow(bef->child(0),
                   bef->child(1),
                   bef->updateTableDesc(),
                   bef->updateSelectValueIdMap());


  // now set the group attributes of the result's top node
  result->setGroupAttr(before->getGroupAttr());

  result->setBlockStmt(before->isinBlockStmt());

 // transfer all the join fields to the new NestedJoinFlow
  (void) bef->copyTopNode(result,CmpCommon::statementHeap());

  // The following code adds clustering index into GA's availableBtreeIndexes.
  // The logic is no longer needed because we can not use the availableBtreeIndexes
  // to check the partition func to the inner target table is compatible with the
  // table, because the part keys of the table is never exposed in its char. output.

  //GroupAttributes* ga = bef->child(1)->getGroupAttr();
  //RelExpr * r = bef->child(1)->castToRelExpr();
  //if ( r->getOperatorType() == REL_UNARY_INSERT ) {
  //   
  //   Insert* insNode = (Insert*)r;
  //
  //    if ( insNode->getTableDesc()->getNATable()->isHiveTable() ) {
  //      SET(IndexDesc *) x;
  //     x.insert((IndexDesc*)(insNode->getTableDesc()->getClusteringIndex()));
  //      ga->addToAvailableBtreeIndexes(x);
  //   }
  //}

  return result;

} // NestedJoinFlowRule::nextSubstitute()

// -----------------------------------------------------------------------
// methods for class HashJoinRule
// -----------------------------------------------------------------------

HashJoinRule::~HashJoinRule() {} 

NABoolean HashJoinRule::topMatch (RelExpr * relExpr,
                                  Context * context)
{
  if (NOT Rule::topMatch(relExpr,context))
    return FALSE;

  Join * joinExpr = (Join *) relExpr;

  // Execute the hash join transformation iff this is not a tsj.
  if ( joinExpr->isTSJ() )
    return FALSE;

  // -----------------------------------------------------------------
  // Hybrid hash join cannot preserve order,
  // if it is not implementing a cross product.
  // We will try to choose a cross-product if the join predicate and
  // selection predicate are empty. So if the context requires order
  // no longer assume that OHJ is the only operator that can provide
  // that order. If the join & selection predicates are empty
  // a cross product can provide the order required by the context.
  // -----------------------------------------------------------------
  NABoolean contextRequiresOnlyLeftOrder = (context->requiresOrder() AND
		  (NOT (joinExpr->isInnerNonSemiJoinWithNoPredicates())));
  if (contextRequiresOnlyLeftOrder AND
      (NOT CURRSTMT_OPTDEFAULTS->isOrderedHashJoinConsidered()))
	return FALSE;

  // Don't allow hash joins if this is not the first pass and
  // hash joins have been disabled.
  if(NOT CURRSTMT_OPTDEFAULTS->isHashJoinConsidered() AND
     // We no longer need to protect hash join from being turned off for pass 1
     // because now we allow nested join in pass 1 too
     ((CmpCommon::getDefault(COMP_BOOL_81) == DF_OFF) OR
      (GlobalRuleSet->getCurrentPassNumber() >
       GlobalRuleSet->getFirstPassNumber())))
    return FALSE;

  // QSTUFF
  // can't yet join two streams or
  // have right child being a stream
  if (joinExpr->getGroupAttr()->isStream())
    return FALSE;

  // Don't want to hash joins and GET_NEXT_N commands yet
  if (context->getGroupAttr()->isEmbeddedUpdateOrDelete())
    return FALSE;
  // QSTUFF

  const ReqdPhysicalProperty* const rppForMe =
                                context->getReqdPhysicalProperty();

  // -----------------------------------------------------------------
  // Hybrid hash joins cannot be done in dp2.
  // -----------------------------------------------------------------
  if (rppForMe->executeInDP2())
    return FALSE;

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(rppForMe))
    return FALSE;

  // MV --
  // If the Join was forced to some other type - fail it.
  if (joinExpr->isPhysicalJoinTypeForced() &&
      joinExpr->getForcedPhysicalJoinType() != Join::HASH_JOIN_TYPE)
    return FALSE;

  // don't consider hash joins if we don't expect to have more
  // than one row in the left child table
  // But don't apply this rule is the join is configured to 
  // avoid halloween (for Neo R2 compatibility).

  // Full Outer Join is supported ONLY by Hash join, so let's
  // not eliminate our ONLY option.
  // Moreover, COMP_BOOL_196 guard is there because,
  // we want to be able to reproduce the scenario, where,
  // when direct Pass 2 optimization fails to produce
  // a plan, the engine goes backs and tries Pass 1.
  // Currently this (retrying Pass 1) does not happen.
  // When that problem is fixed, the COMP_BOOL_196 guard
  // must be removed.

  if (joinExpr->allowHashJoin() == FALSE AND context AND
      context->getReqdPhysicalProperty()->getMustMatch() == NULL)
    return FALSE;

  if (contextRequiresOnlyLeftOrder)
  {
    // Heuristically eliminate less promising ordered hash joins.
    if (CURRSTMT_OPTDEFAULTS->isOrderedHashJoinControlEnabled() AND
        (CmpCommon::getDefault(COMP_BOOL_31) == DF_OFF) AND
        context->getInputLogProp()->getResultCardinality() <= 1)
      {
        // innerS is HIGH bound size estimate of inner table in OHJ plan.
        // This max cardinality based innerS should hopefully allow us 
        // to safely use CQD HJ_TYPE 'SYSTEM' as the default setting.
        GroupAttributes * innerGA = relExpr->child(1).getGroupAttr();
        CostScalar innerS = innerGA->getResultMaxCardinalityForEmptyInput() 
          * innerGA->getCharacteristicOutputs().getRowLength();

        // avoid OHJ if inner table will not fit into memory
        if (innerS > CostScalar(1024* CURRSTMT_OPTDEFAULTS->getMemoryLimitPerCPU()))
          return FALSE;
      }
  }

  return TRUE;
}

// internal routine, used only by HashJoinRule::nextSubstitute() to set
// the flags in the "result" before returning.
static RelExpr * setResult(HashJoin * result,
			   Join     * bef,
			   NABoolean isLeftOrdered,
			   NABoolean isOrderedCrossProduct)
{
  // for ordred cross products order cannot be be promised
  // unless setNoOverflow flag is set. i.e in case
  // there is overflow we want to raise error rather than
  // handle the overflow.
  result->setNoOverflow(isLeftOrdered || isOrderedCrossProduct);
  result->setIsOrderedCrossProduct(isOrderedCrossProduct) ;

  if (NOT (isLeftOrdered))
    result->setReuse(FALSE); // HYBRID CANNOT DO REUSE,

  // Don't reuse the cluster for Full Outer Join (FOJ), till
  // the executor support, FOJ with cluster reuse.

  if(bef->getOperatorType() == REL_FULL_JOIN)
     result->setReuse(FALSE);

  // Don't reuse when under an AFTER ROW trigger !
  // This avoids the problem of reusing the trigger temporary table while
  // also inserting into that TTT in the same plan (i.e., the reused hash-table
  // does not have the newly inserted rows.)
  if (CURRSTMT_OPTDEFAULTS->areTriggersPresent())
    result->setReuse(FALSE);

  if (isLeftOrdered)
    result->setOperatorType( bef->getHashJoinOpType(isLeftOrdered));

  return result;
}

RelExpr * HashJoinRule::nextSubstitute(RelExpr * before,
                                       Context * context,
                                       RuleSubstituteMemory *& /*memory*/)
{
  Join       * bef = (Join *) before;

  // Atmost only one of these two flags will be true.
  // if context->requiresOrder() is FALSE then requiresOnlyLeftOrder = FALSE
  // and orderedCrossProduct may be TRUE.
  // if context->requiresOrder() is TRUE then if the ordering
  // requirement can be satisfied by the left child alone we will
  // try to produce an OHJ plan, otherwise if conditions
  // for orderedCrossProduct are satisfied (no predicates etc.)
  // we will try to produce an Ordered-cross-product (OCP) plan,
  // by checking if the ordering requirements can be split.
  // If this fails too we return NULL as the ordering requirement
  // cannot be satisfied by OHJ or OCP. In summary the block of
  // code below decides if the order required by the context can be
  // satisfied by an OHJ plan or an OCP plan (in that order)
  NABoolean requiresOnlyLeftOrder = FALSE;
  NABoolean orderedCrossProduct = FALSE;
  const ReqdPhysicalProperty* const rppForMe =
			    context->getReqdPhysicalProperty();

  // if context requires order then we try an OHJ first
  if (context->requiresOrder() AND
      (CURRSTMT_OPTDEFAULTS->isOrderedHashJoinConsidered()))
  {
    // Can Order or arrangement requirements be satisfied by the left
    // child alone?

    ValueIdSet orderArrangementExpr, newInputs,
      coveredExpr, referencedInputs;

    if (rppForMe->getSortKey())
      orderArrangementExpr.insertList(*rppForMe->getSortKey());
    if (rppForMe->getArrangedCols())
      orderArrangementExpr += *rppForMe->getArrangedCols();

    bef->child(0).getGroupAttr()->coverTest(orderArrangementExpr,
						newInputs,
						coveredExpr,
						referencedInputs);

    if (coveredExpr == orderArrangementExpr)
    {
      // order required by context can be satisfied by left child alone
      requiresOnlyLeftOrder = TRUE;
    }
  }

  // Join::isInnerNonSemiJoinwithNoPredicates() is a stricter version
  // of Join::isCrossProduct(). This method returns TRUE if
  // join predicate is empty AND selectionPred is  empty and
  // the join is not (a semijoin, or anti join or outer join).
  // We use this method instead of isCrossProduct() because
  // isCrossProduct will return TRUE if the Selection/Join predicates
  // have something other than a VEG predicate. The one we saw was
  // a > predicate.
  if ((NOT requiresOnlyLeftOrder) AND
      bef->isInnerNonSemiJoinWithNoPredicates() AND
      bef->getSource() == Join::STAR_KEY_JOIN AND
      CmpCommon::getDefault(COMP_BOOL_73) == DF_OFF)
  {
      // satisfies the basic conditions of being
      // an order-preserving-cross-product
      // right now OCP plans are enabled only for
      // joining dimension tables for a StarJoin rule.
      orderedCrossProduct = TRUE;

      // If the HJ is implementing a cross-product and the context
      // requires order then check to see if the required order and
      // arrangement can be split among the children.
      if (context->requiresOrder())
      {
	// for a cross-product whose context requires order return FALSE if the
	// ordering requirement cannot be split among the children.
	ValueIdList dummy1, dummy2;
	ValueIdSet dummy3, dummy4;
	if ((rppForMe->getSortKey() AND
	    rppForMe->getSortKey()->entries() > 0 AND
	    NOT bef->splitOrderReq(*(rppForMe->getSortKey()),dummy1,dummy2))
	OR
	    (rppForMe->getArrangedCols() AND
	    rppForMe->getArrangedCols()->entries() > 0 AND
	    NOT bef->splitArrangementReq(*(rppForMe->getArrangedCols()),dummy3,dummy4)))
	{
	  // order required by context cannot be satisfied by OHJ or OCP
	  return NULL;
	}
      }
  }

  // if not OHJ and not OCP and context requires order
  // then no HJ node can satisfy the order req.
  if (context->requiresOrder() AND
      (NOT orderedCrossProduct) AND
      (NOT requiresOnlyLeftOrder))
	return NULL;

  Int32 multipleCallsToChild = FALSE;


  // Build the result tree,
  // temporarily assume a hybrid hash join when choosing an operator type
  HashJoin   * result = new(CmpCommon::statementHeap())
    HashJoin(bef->child(0),
	     bef->child(1),
	     bef->getHashJoinOpType(FALSE));

  result->setGroupAttr(before->getGroupAttr());

  // transfer all the join fields to the new HashJoin
  (void) bef->Join::copyTopNode(result,CmpCommon::statementHeap());

  result->resolveSingleColNotInPredicate();

  // input log prop for the node
  EstLogPropSharedPtr inLogProp = context->getInputLogProp();

  NABoolean joinStrategyIsOrderSensitive = FALSE;
  result->separateEquiAndNonEquiJoinPredicates(joinStrategyIsOrderSensitive);

  // Get addressability to the defaults table.
  NADefaults &defs = ActiveSchemaDB()->getDefaults();
  // OHJ_BMO_REUSE_SORTED_UECRATIO_UPPERLIMIT = 0.70
  double BMOReuseSortedUECRatioUpperlimit =
  defs.getAsDouble(OHJ_BMO_REUSE_SORTED_UECRATIO_UPPERLIMIT);

  // number of parent probes
  CostScalar probeCount =
    MAXOF(1.,inLogProp->getResultCardinality().value());

  // ---------------------------------------------------------------------
  // Determine REUSE possibility.
  // Reuse may be a good idea if this hash join gets invoked multiple
  // times and if the data returned from the right child fits in memory.
  // ---------------------------------------------------------------------
  if ( inLogProp->getResultCardinality() > 1 )
    {
      // We may declare a REUSE here as a possiblity. However, later, during
      // costing, IFF we find out that REUSE is not very useful,
      // because the calls to the inner table are too numerous and the inputs
      // are NOT SORTED, we will OVERTURN this decision and go with HYBRID AND
      // NO REUSE. Since we do not have the information on whether the inputs
      // are SORTED, we cannot make that decision here.

      // check whether the right child is dependent on the
      // characteristic inputs of this join (set multipleCallsToChild to
      // true if so)
      EstLogPropSharedPtr inputLogPropForChild = result->child(1).getGroupAttr()->
	materializeInputLogProp(
	     context->getInputLogProp(),&multipleCallsToChild);
      result->multipleCalls()=multipleCallsToChild;

      if(NOT multipleCallsToChild)
	result->setReuse(TRUE); // Set this to be a REUSE Candidate

      // if, however, the inner table will be called multiple times, make sure
      // that these calls are not so numerous that reuse becomes too expensive
      // ********how to find order of the char inputs
      else
	{
	  // Characteristic inputs are the values whose change causes
	  // reinitialization of the table.
	  ValueIdSet tochild =
	    result->child(1).getGroupAttr()->getCharacteristicInputs();
	  result->valuesGivenToChild() = tochild;

	  // Unique entry Count for the parent probes
	  CostScalar uniqueProbeCount =
	    inLogProp->getAggregateUec(result->valuesGivenToChild());

	  CostScalar uniqueRatio = uniqueProbeCount/probeCount;

	  if(uniqueRatio <= BMOReuseSortedUECRatioUpperlimit)
	    result->setReuse(TRUE);
	}
    } // end resultCardinality > 1

  // ---------------------------------------------------------------------
  // The following code compares hybrid hash join and ordered hash join
  // and picks the better one. It tries to handle the easy cases first.
  //
  // An ordered hash join should only be used if there is a reason for
  // it, because of the added risk of thrashing if the in-memory table
  // gets too large. There are two reasons for an ordered hash join:
  // a) an order is required and/or b) the reuse feature of the ordered
  // hash join is desired
  // ---------------------------------------------------------------------

  // ordered hash joins are treated like a materialize node with respect
  // to triggers, disable them when materialize nodes are forbidden
  if (CURRSTMT_OPTDEFAULTS->areTriggersPresent())
    if (requiresOnlyLeftOrder)
      return NULL;
    else
    {
      // no cross-product ordering can be promised with triggers
      return setResult(result,bef,FALSE,FALSE);
    }


  // Check if CQS is in force (it will override CQDs and other considerations)
  const RelExpr * mm = context->getReqdPhysicalProperty()->getMustMatch() ;
  if (mm)
    {
      switch (mm->getOperatorType())
	{
	case REL_FORCE_ORDERED_HASH_JOIN:
	  return setResult(result,bef,TRUE, FALSE);
	case REL_FORCE_HYBRID_HASH_JOIN:
	  return setResult(result,bef,FALSE, FALSE);
	case REL_FORCE_ORDERED_CROSS_PRODUCT:
	  return setResult(result,bef,FALSE, TRUE); 
	default:
	  break;
	}
    }

  // deal with the HJ_TYPE CQD if not both join types are enabled
  if (NOT (CURRSTMT_OPTDEFAULTS->isOrderedHashJoinConsidered() AND
           CURRSTMT_OPTDEFAULTS->isHybridHashJoinConsidered()))
    {
      if (CURRSTMT_OPTDEFAULTS->isOrderedHashJoinConsidered())
	// user wants only ordered hash joins
	return setResult(result,bef,TRUE, FALSE);
      else if (CURRSTMT_OPTDEFAULTS->isHybridHashJoinConsidered())
	if (context->requiresOrder() AND (NOT orderedCrossProduct))
	  // user wants hybrid joins, which can't be used here
	  return NULL;
	else
          // user wants hybrid hash joins, disable reuse if needed
	  return setResult(result,bef,FALSE, orderedCrossProduct);
    }

  // use a hybrid hash join if neither reason a) nor b) above applies
  if (NOT result->isReuse() AND
      NOT requiresOnlyLeftOrder)
    return setResult(result,bef,FALSE,orderedCrossProduct);

  // bmoFactor tells how big is it? =inner-tab_size/mem_size
  double bmoFactor = 0;
  double vBMOlimit = defs.getAsDouble(OHJ_VBMOLIMIT); // 5.0
  double bmoMemLimit = defs.getAsDouble(BMO_MEMORY_SIZE); // 200Mb

  // ---------------------------------------------------------------------
  // Now we have a case where we would like to reuse or benefit from
  // the order of the ordered hash join. Determine based on heuristics
  // what is better: Ordered hash join (with reuse), not to generate
  // any plan at all, or a hybrid hash join w/o reuse. In short, the
  // choices are reuse, refuse, or refuse to reuse ;-)
  // ---------------------------------------------------------------------
  // OHJ fixes
  // 1) If the memoryLimit_>200MB then temorarily set memoryLimit_ to 
  //    200MB. The idea is not to choose OHJ if the inner table size is
  //    > 200MB per ESP.
  if (CmpCommon::getDefault(COMP_BOOL_37) == DF_OFF) {
    double memoryLimitPerCPU = CURRSTMT_OPTDEFAULTS->getMemoryLimitPerCPU();
    if (memoryLimitPerCPU > bmoMemLimit)  // memory limit is in KB.
      // Temporarily set memory limit to 200MB.
      // BMO_MEMORY_SIZE can be used to control this 200MB limit.
      CURRSTMT_OPTDEFAULTS->setMemoryLimitPerCPU(bmoMemLimit);
    // Check if this is a BMO
    NABoolean isBMO = result->isBigMemoryOperatorSetRatio(context, 0, bmoFactor);
    // Reset memoryLimit
    CURRSTMT_OPTDEFAULTS->setMemoryLimitPerCPU(memoryLimitPerCPU);
    if (isBMO ) 
      if (requiresOnlyLeftOrder)
        // can't preserve order for this large hash join
        return NULL;
      else 
        // sacrifice reuse and do a hybrid hash join
        // order cannot be promised for orderedCrossProducts
        return setResult(result,bef,FALSE, FALSE);
    else  // Not a BMO => Great case for ordered hash join
      if (orderedCrossProduct)
        return setResult(result,bef,FALSE, TRUE);
      else
        return setResult(result,bef,TRUE, FALSE);
  }


  // The following block of code is old and contains bugs.
  // Mask the block out for code coverage.

  // Check if this is a BMO
  NABoolean isBMO = result->isBigMemoryOperatorSetRatio(context, 0, bmoFactor);
  NABoolean useOrderedHashJoin = FALSE;

  // Not a BMO => Great case for ordered hash join
  if (NOT isBMO) {
    if (orderedCrossProduct)
      return setResult(result,bef,FALSE, TRUE);
    else
      return setResult(result,bef,TRUE, FALSE);
  }

  // If the ratio > OHJ_VBMOLIMIT, the join is very big mem operator and there
  // is no use trying ordered hash join because of pagefaults.

  if (isBMO AND bmoFactor > vBMOlimit)
    {
      if (requiresOnlyLeftOrder)
	// can't preserve order for this large hash join
	return NULL;
      else
	// sacrifice reuse and do a hybrid hash join
	// (this should be a rare event, it's expensive to perform
	// a large hash join several times over)
	return setResult(result,bef,FALSE, FALSE); // order cannot be promised for orderedCrossProducts
    }

  // Heuristics to decide between Ordered and Hybrid when
  // BMO and REUSE and operator size is between memoryLimit
  // and VBMOFACTOR*memoryLimit. In this range be pessimistic and
  // do not make any promises about whether a crossproduct will
  // be ordered.

  // If the inner table is to be built only once, do Left-Ordered
  // (typically with Reuse).
  if(NOT multipleCallsToChild)
    return setResult(result,bef,TRUE, FALSE);

  // Unique entry Count for the parent probes
  CostScalar uniqueProbeCount =
    inLogProp->getAggregateUec (result->valuesGivenToChild());
  CostScalar UECRatio = uniqueProbeCount / probeCount;

  // There is no easy way to determine if the input probes from the parent
  // are sorted. So, for now, assume they are not sorted. This is pessimistic
  // approach and favors selection of hybrid_hash over ordered_hash.
  // The heuristics below use these defaults:
  // OHJ_BMO_REUSE_SORTED_BMOFACTOR_LIMIT = 3.0
  // OHJ_BMO_REUSE_UNSORTED_UECRATIO_UPPERLIMIT = 0.01
  if( context->getPlan() &&
      context->getPlan()->getPhysicalProperty() &&
      context->getPlan()->getPhysicalProperty()->isSorted() ) //input is sorted
    {
      double BMOReuseSortedBmofactorLimit =
	defs.getAsDouble(OHJ_BMO_REUSE_SORTED_BMOFACTOR_LIMIT);

      if( bmoFactor <= BMOReuseSortedBmofactorLimit) {

	useOrderedHashJoin = UECRatio <= BMOReuseSortedUECRatioUpperlimit ;
      }
      else  // if bmoFactor > OHJ_BMO_REUSE_SORTED_BMOFACTOR_LIMIT
	useOrderedHashJoin = UECRatio <= BMOReuseSortedUECRatioUpperlimit / 3;
    }
  else    // input is not sorted
    {
      double BMOReuseUnsortedUECRatioUpperlimit =
      	defs.getAsDouble(OHJ_BMO_REUSE_UNSORTED_UECRATIO_UPPERLIMIT) ;

      useOrderedHashJoin = UECRatio <= BMOReuseUnsortedUECRatioUpperlimit ;
    }

  return setResult(result,bef,useOrderedHashJoin, FALSE);
  //end Heuristics


} // HashJoinRule::nextSubstitute()

// -----------------------------------------------------------------------
// methods for class MergeJoinRule
// -----------------------------------------------------------------------

MergeJoinRule::~MergeJoinRule() {} 

NABoolean MergeJoinRule::topMatch (RelExpr *relExpr,
                                   Context * context)
{
  if (NOT Rule::topMatch(relExpr, context))
    return FALSE;

  Join * joinExpr = (Join *) relExpr;

  // Fire the merge join rule iff this is not a tsj nor a part of a
  // compound statement.
  if ( joinExpr->isTSJ() || relExpr->isinBlockStmt() )
    return FALSE;

  // avoid merge join on seabase MD tables
  if (joinExpr->getGroupAttr()->isSeabaseMDTable())
    return FALSE;

  // The avoidHalloweenR2 flag will be set on two Join nodes.  The join
  // used for the Subquery and the Tuple Flow Join used for write.  If
  // avoidHalloweenR2 is set and this is the join used for the subquery,
  // then it must use a hash join. So do not fire the merge join in
  // either case.
  //
  if (joinExpr->avoidHalloweenR2())
    return FALSE;

  // merge join is not supported for Full_Outer_Join
  if (relExpr->getOperator().match(REL_ANY_FULL_JOIN))
    return FALSE;

  // QSTUFF
  // can't do a merge join with streams
  // as we are missing end-of-data to kick of a sort
  if (joinExpr->getGroupAttr()->isStream())
    return FALSE;

  // Don't want to tangle merge joins and GET_NEXT_N commands yet
  if (context->getGroupAttr()->isEmbeddedUpdateOrDelete())
    return FALSE;
  // QSTUFF

  // Allow merge joins
  if (NOT CURRSTMT_OPTDEFAULTS->isMergeJoinConsidered())
    return FALSE;

  const ReqdPhysicalProperty * rppForMe = context->getReqdPhysicalProperty();

  // disallow merge join in dp2
  if (rppForMe->executeInDP2())
    return FALSE;

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(rppForMe))
    return FALSE;

  // MV --
  // If the Join was forced to some other type - fail it.
  if (joinExpr->isPhysicalJoinTypeForced() &&
      joinExpr->getForcedPhysicalJoinType() != Join::MERGE_JOIN_TYPE)
    return FALSE;

  // ---------- Merge Join Control Heuristic --------------------------
  NABoolean checkForceMJ = 
    ((rppForMe->getMustMatch() != NULL) AND
     (rppForMe->getMustMatch()->getOperatorType() == REL_FORCE_MERGE_JOIN));
  if (!checkForceMJ &&
      (CURRSTMT_OPTDEFAULTS->isMergeJoinControlEnabled() ||
       CmpCommon::getDefault(COMP_BOOL_104) == DF_ON) &&
      (CURRSTMT_OPTDEFAULTS->isNestedJoinConsidered() ||
       CURRSTMT_OPTDEFAULTS->isHashJoinConsidered())
      )
  {
    CostScalar r0 =
      relExpr->child(0).getGroupAttr()->getResultCardinalityForEmptyInput()
      * relExpr->child(0).getGroupAttr()->getRecordLength();

    CostScalar r1 =
      relExpr->child(1).getGroupAttr()->getResultCardinalityForEmptyInput()
      * relExpr->child(1).getGroupAttr()->getRecordLength();

      if ( (r1 < CostScalar(1024* CURRSTMT_OPTDEFAULTS->getMemoryLimitPerCPU()))  OR
           ((CURRSTMT_OPTDEFAULTS->isMergeJoinControlEnabled()) &&
            (r0 < CostScalar(1024* CURRSTMT_OPTDEFAULTS->getMemoryLimitPerCPU()))))
        return FALSE;  //Hash is better ??unless zigzag off then one case void
  }
  // -------------------------------------------------------------------

  if (CmpCommon::getDefault(MERGE_JOIN_ACCEPT_MULTIPLE_NJ_PROBES) == DF_OFF && 
      context->getInputLogProp()->getResultCardinality() > 1)
    return FALSE;

  // Consider the merge join only if there's an equi-join predicate
  if ( joinExpr->getEquiJoinPredicates().isEmpty() )
    return FALSE;

  // consider merge join only if its join predicate has no constants.
  // otherwise, we may get the problem reported in 
  // genesis case 10-081117-8475 soln 10-081117-7342
  ItemExpr *constant = NULL;
  return (NOT (joinExpr->getJoinPred().referencesAConstValue(&constant)));
}

RelExpr * MergeJoinRule::nextSubstitute(RelExpr * before,
                                        Context * context,
                                        RuleSubstituteMemory *& /*memory*/)
{
  MergeJoin * result;
  Join      * bef = (Join *) before;

  result = new (CmpCommon::statementHeap())
               MergeJoin (bef->child(0),
                          bef->child(1),
                          bef->getMergeJoinOpType());

  // Set the group attributes of the result's top node
  result->setGroupAttr (bef->getGroupAttr());

  // transfer all the join fields to the new MergeJoin
  (void) bef->copyTopNode(result,CmpCommon::statementHeap());
  
  result->resolveSingleColNotInPredicate();

  NABoolean joinStrategyIsOrderSensitive = TRUE;
  result->separateEquiAndNonEquiJoinPredicates(joinStrategyIsOrderSensitive);

  // We must have at least 1 equijoin predicate and the partitioning
  // requirement should be a compatible one.
  if ( (NOT result->getEquiJoinPredicates().isEmpty()) AND
      (result->parentAndChildPartReqsCompatible
                 (context->getReqdPhysicalProperty())))
    return result;
  else
    return NULL;

}

NABoolean MergeJoinRule::canBePruned(RelExpr * relExpr) const
{
  // We do not want to prune Merge Join Rule if expr is an AntiSemiJoin.
  // Since Hash Join is not possible for ASJ and so MJ may be the only
  // good alternative.
  return NOT relExpr->getOperator().match(REL_ANY_ANTI_SEMIJOIN);
}

// -----------------------------------------------------------------------
// methods for class PhysCompoundStmtRule
// -----------------------------------------------------------------------

NABoolean PhysCompoundStmtRule::topMatch(RelExpr *relExpr,
                                      Context *context)
{
  if (relExpr->getOperatorType() != REL_COMPOUND_STMT)
    return FALSE;

  if (NOT Rule::topMatch(relExpr, context))
    return FALSE;

   // QSTUFF
  CMPASSERT(NOT(relExpr->getGroupAttr()->isStream() OR
                relExpr->getGroupAttr()->isEmbeddedUpdateOrDelete()));
  // QSTUFF

  const ReqdPhysicalProperty * rppForMe = context->getReqdPhysicalProperty();

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(rppForMe))
    return FALSE;

  if ( CURRSTMT_OPTDEFAULTS->pushDownDP2Requested() )
  {
    // If this CS is to be pushed down and its total input/output
    // length is large than 36KB, we reject the request.
    //
    // 36KB is the upper limit of the space allocated
    // for inputs/outputs to DP2, and the summary of the total sizes of
    // of all types involved should be close to the final
    // SQLARK_EXPLODED_FORMAT size. Here we use a fudge factor of 4K.
    //
    // It is found that DP2 goes into infinite loop if we have rowsize
    // of approximately > 30000. Internally the executor has a max buffer
    // size of 31000 for nodes with remotepartition and 56000 for local
    // partitions.30000 bytes limit is experimentally found to be safe after
    // taking into consideration the additional bytes that will be added for
    // header information and control information in executor.
    //

    // Using the CQD to increase this limit to 55000 for the DBlimits project
    // to support large rows.

    if ( rppForMe->executeInDP2() == TRUE ) {

      Int32 limit =
          (CmpCommon::getDefault(GEN_DBLIMITS_LARGER_BUFSIZE) == DF_OFF) ?
          ROWSIZE_TO_EXECUTE_IN_DP2 : ROWSIZE_TO_EXECUTE_IN_DP2_DBL;

      if ( relExpr->getGroupAttr()->getCharacteristicInputs().getRowLength() +
           relExpr->getGroupAttr()->getCharacteristicOutputs().getRowLength()
          > limit )
        return FALSE;

    } else {
      if (rppForMe->getPlanExecutionLocation() != EXECUTE_IN_MASTER)
        return FALSE;
    }
  }
  else {
    if (rppForMe->getPlanExecutionLocation() != EXECUTE_IN_MASTER)
      return FALSE;
  }

  return TRUE;
} // PhysCompoundStmtRule::topMatch

RelExpr *PhysCompoundStmtRule::nextSubstitute(
                             RelExpr *before,
                             Context *context,
                             RuleSubstituteMemory * & memory)
{
  RelExpr *result;

  CMPASSERT(before->getOperatorType() == REL_COMPOUND_STMT);

  result = new (CmpCommon::statementHeap())
    PhysCompoundStmt(*((CompoundStmt *)before));

  result->setGroupAttr(before->getGroupAttr());

  result->allocateAndPrimeGroupAttributes();

  result->pushdownCoveredExpr(
               result->getGroupAttr()->getCharacteristicOutputs(),
               result->getGroupAttr()->getCharacteristicInputs(),
               result->selectionPred());

  return result;

} // PhysCompoundStmtRule::nextSubstitute()

//  -----------------------------------------------------------------------
// methods for class PhysicalMapValueIdsRule
// -----------------------------------------------------------------------

PhysicalMapValueIdsRule::~PhysicalMapValueIdsRule() {} 

// This rule is context sensitive
NABoolean PhysicalMapValueIdsRule::isContextSensitive() const
{
  return TRUE;
}

NABoolean PhysicalMapValueIdsRule::topMatch (RelExpr *relExpr,
                                             Context * context)
{
  // Transform the MapValueIds to a PhysicalMapValueIds iff
  // all the selection() predicates are pushed down.
  if (NOT Rule::topMatch(relExpr, NULL))
    return FALSE;

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(context->getReqdPhysicalProperty()))
    return FALSE;

  if (relExpr->selectionPred().isEmpty())
    return TRUE;
  else
    return FALSE;
}

RelExpr * PhysicalMapValueIdsRule::nextSubstitute(RelExpr * before,
                                                  Context * ,
                                                  RuleSubstituteMemory *& )
{
  CMPASSERT(before->getOperatorType() == REL_MAP_VALUEIDS);

  // Simply copy the contents of the MapValueIds from the before pattern.
  PhysicalMapValueIds * result = new(CmpCommon::statementHeap())
    PhysicalMapValueIds(*((MapValueIds *) before));

  // now set the group attributes of the result's top node
  result->setGroupAttr(before->getGroupAttr());

  return result;
}

NABoolean PhysicalMapValueIdsRule::canMatchPattern (const RelExpr *) const
{
  // map value ids are independent of required patterns, always apply this rule
  return TRUE;
}

// -----------------------------------------------------------------------
// methods for class PhysicalRelRootRule
// -----------------------------------------------------------------------

PhysicalRelRootRule::~PhysicalRelRootRule() {} 

RelExpr * PhysicalRelRootRule::nextSubstitute(RelExpr * before,
                                              Context * /*context*/,
                                              RuleSubstituteMemory *& /*mem*/)
{
  CMPASSERT(before->getOperatorType() == REL_ROOT);
  RelRoot * bef = (RelRoot *) before;

  // Simply copy the contents of the Materialize from the before pattern.
  PhysicalRelRoot * result = new(CmpCommon::statementHeap())
    PhysicalRelRoot(*bef);

  // now set the group attributes of the result's top node
  result->setGroupAttr(before->getGroupAttr());

  (void) bef->copyTopNode(result, CmpCommon::statementHeap());

  return result;
}

// -----------------------------------------------------------------------
// methods for class PhysicalTupleRule
// -----------------------------------------------------------------------

PhysicalTupleRule::~PhysicalTupleRule() {} 

NABoolean PhysicalTupleRule::topMatch (RelExpr *relExpr,
                                       Context *context)
{
  if (NOT Rule::topMatch(relExpr, context))
    return FALSE;

  // ---------------------------------------------------------------
  // allow a tuple operator to be pushed down to dp2 if flag is on
  // and do colocation check later.
  // ---------------------------------------------------------------
 if (! CURRSTMT_OPTDEFAULTS->pushDownDP2Requested() &&
     context->getReqdPhysicalProperty()->executeInDP2())
   return FALSE;

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(context->getReqdPhysicalProperty()))
    return FALSE;

  return TRUE;
}

RelExpr * PhysicalTupleRule::nextSubstitute(RelExpr * before,
                                            Context * /*context*/,
                                            RuleSubstituteMemory *& /*memory*/)
{
  CMPASSERT(before->getOperatorType() == REL_TUPLE);
  Tuple * bef = (Tuple *) before;

  // Simply copy the contents of the Tuple from the before pattern.
  PhysicalTuple * result = new(CmpCommon::statementHeap())
    PhysicalTuple(*((Tuple *) before));

  // now set the group attributes of the result's top node
  result->setGroupAttr(before->getGroupAttr());

  (void) bef->copyTopNode(result, CmpCommon::statementHeap());

  result->setBlockStmt(before->isinBlockStmt());

  return result;
}

// -----------------------------------------------------------------------
// methods for class PhysicalTupleListRule
// -----------------------------------------------------------------------
PhysicalTupleListRule::~PhysicalTupleListRule() {} 

NABoolean PhysicalTupleListRule::topMatch (RelExpr *relExpr,
                                           Context *context)
{
  if (NOT Rule::topMatch(relExpr, context))
    return FALSE;

  // ---------------------------------------------------------------
  // allow a tuple operator to be pushed down to dp2 if flag is on
  // and do colocation check later.
  // ---------------------------------------------------------------
 if (! CURRSTMT_OPTDEFAULTS->pushDownDP2Requested() &&
     context->getReqdPhysicalProperty()->executeInDP2())
   return FALSE;

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(context->getReqdPhysicalProperty()))
    return FALSE;

  return TRUE;
}

RelExpr * PhysicalTupleListRule::nextSubstitute(RelExpr * before,
                                            Context * /*context*/,
                                            RuleSubstituteMemory *& /*memory*/)
{
  CMPASSERT(before->getOperatorType() == REL_TUPLE_LIST);

  // Simply copy the contents of the Tuple from the before pattern.
  // no need to call copyTopNode as the copy constructor is called

  PhysicalTupleList * result = new(CmpCommon::statementHeap())
    PhysicalTupleList( *((TupleList *) before) );

  // now set the group attributes of the result's top node
  result->setGroupAttr(before->getGroupAttr());

  return result;
} //  PhysicalTupleListRule::nextSubstitute()

// -----------------------------------------------------------------------
// methods for class PhysicalExplainRule
// -----------------------------------------------------------------------

PhysicalExplainRule::~PhysicalExplainRule() {} 

RelExpr * PhysicalExplainRule::nextSubstitute(RelExpr * before,
                                              Context * /*context*/,
                                              RuleSubstituteMemory *& /*mem*/)
{
  CMPASSERT(before->getOperatorType() == REL_EXPLAIN);
  ExplainFunc * bef = (ExplainFunc *) before;

  // Simply copy the contents of the Explain from the before pattern.
  PhysicalExplain *result = new(CmpCommon::statementHeap()) PhysicalExplain();

  bef->copyTopNode(result, CmpCommon::statementHeap());

  // now set the group attributes of the result's top node
  result->selectionPred() = bef->selectionPred();
  result->setGroupAttr(before->getGroupAttr());

  return result;
}

// -----------------------------------------------------------------------
// methods for class PhysicalHiveMDRule
// -----------------------------------------------------------------------

PhysicalHiveMDRule::~PhysicalHiveMDRule() {} 

RelExpr * PhysicalHiveMDRule::nextSubstitute(RelExpr * before,
                                              Context * /*context*/,
                                              RuleSubstituteMemory *& /*mem*/)
{
  CMPASSERT(before->getOperatorType() == REL_HIVEMD_ACCESS);
  HiveMDaccessFunc * bef = (HiveMDaccessFunc *) before;

  // Simply copy the contents of the HiveMD from the before pattern.
  PhysicalHiveMD *result = new(CmpCommon::statementHeap()) PhysicalHiveMD();

  bef->copyTopNode(result, CmpCommon::statementHeap());

  // now set the group attributes of the result's top node
  result->selectionPred() = bef->selectionPred();
  result->setGroupAttr(before->getGroupAttr());

  return result;
}

// -----------------------------------------------------------------------
// methods for class PhysicalPackRule
// -----------------------------------------------------------------------

// Destructor.
PhysicalPackRule::~PhysicalPackRule()
{
}

// PhysicalPackRule::topMatch()
NABoolean PhysicalPackRule::topMatch(RelExpr* relExpr, Context* context)
{
  // Match the node type first.
  if (NOT Rule::topMatch(relExpr,context)) return FALSE;
  CMPASSERT(relExpr->getOperatorType() == REL_PACK);

  Pack* packNode = (Pack *) relExpr;

  const ReqdPhysicalProperty* rppForMe = context->getReqdPhysicalProperty();

  // If the defaults table does not indicate that this query is to be
  // executed in DP2, return FALSE
  if (rppForMe->executeInDP2() AND
      NOT CURRSTMT_OPTDEFAULTS->pushDownDP2Requested())
    return FALSE;

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(rppForMe))
    return FALSE;

  if ( CURRSTMT_OPTDEFAULTS->pushDownDP2Requested() )
  {
    // If the OPTS_PUSH_DOWN_DAM CQD is set to '1', and if this rowsets total input/output
    // length * packingFactorLong_ is larger than 30000 bytes, we reject the request.

    // It is found that DP2 goes into infinite loop if we select into a rowset of
    // approximately of size > 30000. Internally the executor has a max buffer size of 31000
    // for nodes with remotepartition and 56000 for local partitions.30000 bytes limit is experimentally
    // found to be safe after taking into consideration the additional bytes that will be added for header
    // information and control information in executor.
    //
    if ((CmpCommon::getDefault(GEN_DBLIMITS_LARGER_BUFSIZE) == DF_OFF))
      {
	if ( (   ( ( relExpr->getGroupAttr()->getCharacteristicInputs().getRowLength() +
		     relExpr->getGroupAttr()->getCharacteristicOutputs().getRowLength()
		     ) * packNode->packingFactorLong()
		   )
		 > ROWSIZE_TO_EXECUTE_IN_DP2
		 )
	     AND
	     rppForMe->executeInDP2()
	     )
	  {
	    return FALSE;
	  }
      }
    else
      {
	if ( (   ( ( relExpr->getGroupAttr()->getCharacteristicInputs().getRowLength() +
		     relExpr->getGroupAttr()->getCharacteristicOutputs().getRowLength()
		     ) * packNode->packingFactorLong()
		   )
		 > ROWSIZE_TO_EXECUTE_IN_DP2_DBL
		 )
	     AND
	     rppForMe->executeInDP2()
	     )
	  {
	    return FALSE;
	  }
      }
    // For 10-050816-0628 soln. The dp2 loop happens if the data selected is more than 30,000.
    // The check above takes care of the rowset size declared in the program
    // into consideration. But, if there is mismatch between the rowsets size declared
    // and the column size that is being filled in rowset, the eid buffer will be unable
    // to handle it and will lead to dp2 loop.
    // Ex: Suppose we declare ROWSET [100] char[10] and table column col1  of size char(1000) is
    // used in a statement like "select col1 into :rowset".
    // Here we are trying to fill 100 * 1000 = 100000 bytes into a rowset of size
    // 100 * 10 = 1000 bytes and into an eid buffer of 31000.
    // This is because when you have "ROWSET [100] char[10]" and the corresponding column is
    // char[1000] the conversion happens after the pack node. Hence we are considering the record
    // size of 1000 in our calculation as this is the data that needs to be transferred. 
    // This will lead to dp2 loop since 100000 > 30000 limit which eid can work with. This check
    // will take care of this scenario.
    // Here we get the characteristic output values of pack nodes children and check if the size
    // of output is greater than 30000.
    if ((CmpCommon::getDefault(GEN_DBLIMITS_LARGER_BUFSIZE) == DF_OFF))
      { 
	RowSize
	  outputrowSize = relExpr->child(0).getGroupAttr()->getRecordLength()
	  * packNode->packingFactorLong();

	if (outputrowSize > ROWSIZE_TO_EXECUTE_IN_DP2
	    AND   rppForMe->executeInDP2())
	  {
	    return FALSE;
	  }
      }
    else
      {
	RowSize
	  outputrowSize = relExpr->child(0).getGroupAttr()->getRecordLength()
	  * packNode->packingFactorLong();

	if (outputrowSize > ROWSIZE_TO_EXECUTE_IN_DP2_DBL
	    AND   rppForMe->executeInDP2())
	  {
	    return FALSE;
	  }
      }

  }
  // ---------------------------------------------------------------------
  // Some limitations for now.
  //
  // 1. Pack node cannot satisfy any ordering requirements.
  // 2. Pack node must execute in one stream.
  // ---------------------------------------------------------------------

  if (rppForMe->getSortKey()) return FALSE;
  if (rppForMe->getArrangedCols()) return FALSE;

  if ((rppForMe->getPartitioningRequirement() != NULL) AND
      (NOT(rppForMe->getPartitioningRequirement()->isRequirementExactlyOne())))
      return FALSE;

  return TRUE;
}

RelExpr* PhysicalPackRule::nextSubstitute(RelExpr* before,
                                          Context* /*context*/,
                                          RuleSubstituteMemory*& memory)
{
  CMPASSERT(before->getOperatorType() == REL_PACK);
  CMPASSERT(memory == NULL);

  Pack* original = (Pack *) before;

  // ---------------------------------------------------------------------
  // Create empty PhyPack substitute and copy packing factor over.
  // ---------------------------------------------------------------------
  PhyPack* substitute = new (CmpCommon::statementHeap()) PhyPack();
  original->copyTopNode(substitute);

  // ---------------------------------------------------------------------
  // Fields which are not copied need to be filled in.
  // ---------------------------------------------------------------------
  substitute->setGroupAttr(original->getGroupAttr());
  substitute->child(0) = original->child(0);

  return substitute;
}

NABoolean PhysicalPackRule::canMatchPattern (const RelExpr *) const
{
  // Pack is independent of required patterns, always apply this rule
  return TRUE;
}

// -----------------------------------------------------------------------
// methods for class PhysicalTransposeRule
// -----------------------------------------------------------------------

// Destructor for the PhysicalTransposeRule
//
PhysicalTransposeRule::~PhysicalTransposeRule() {} 

// PhysicalTransposeRule::topMatch() -------------------------------------
// The method is used to determine if a rule should fire.  If
// Rule::topMatch() returns TRUE, then the relExpr has matched the
// pattern of the rule. Here we do further examination of the context
// and relExpr to determine if this rule should be applied.
//
// Parameters:
//
// RelExpr *relExpr
//  IN : The relExpr node
//
NABoolean PhysicalTransposeRule::topMatch (RelExpr *relExpr,
                                           Context *context)
{
  // Check to see if this relExpr matches the Rules pattern.
  //
  if (NOT Rule::topMatch(relExpr,context))
    return FALSE;

  // If it matched, then this must be a Transpose node.
  //
  CMPASSERT(relExpr->getOperatorType() == REL_TRANSPOSE);

  // Do a down cast. This should be safe.
  //
  Transpose *transposeNode = (Transpose *)relExpr;

  // If there are any physical requirements, make sure that
  // Transpose can satisfy them.
  // Transpose can not satisfy:
  //   - a sort requirement on any of the columns generated by transpose.
  //   - an arranged requirement on any of the columns generated by
  //     transpose.
  //   - a partitioning requirement on any of the columns generated by
  //     transpose.
  //
  // If any of these requirements exist, then this method will return
  // FALSE and the rule will not fire.
  //

  const ReqdPhysicalProperty *rppForMe = context->getReqdPhysicalProperty();

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(rppForMe))
    return FALSE;

  // A set of valueIds containing the sortKeys, arrangedCols,
  // and partitioningKeys.
  //
  ValueIdSet allOrderColumns;

  if (rppForMe->getSortKey())
    allOrderColumns.insertList(*rppForMe->getSortKey());

  if (rppForMe->getArrangedCols())
    allOrderColumns += *rppForMe->getArrangedCols();

  if (rppForMe->getPartitioningRequirement() &&
      rppForMe->getPartitioningKey().entries() > 0)
    allOrderColumns += rppForMe->getPartitioningKey();

  // If any of the order columns or partitioning columns are the
  // generated transpose columns this node cannot satisfy the
  // reqirement.  If they are on the childs columns (or other
  // inputs) then it is up to the child.

  // The valueIds for the generated columns.
  //
  ValueIdSet transVals;

  for (CollIndex v = 0; v < transposeNode->transUnionVectorSize(); v++)
    transVals.insertList(transposeNode->transUnionVector()[v]);

  // If there are references to the generated columns in the
  // ordering/partitioning columns, then the rule cannot fire.
  if (allOrderColumns.referencesOneValueFromTheSet(transVals))
    return FALSE;

  // If there are no physical requirements, then this rule can fire.
  //
  return TRUE;
} // PhysicalTranspose::topMatch()


// PhysicalTransposeRule::nextSubstitute() ---------------------------------
// Generate the result of the application of a rule.
// This method returns a 'substitute' from applying the rule to the binding
// 'before'.  This method is called repeatedly until it returns a NULL
// pointer in the 'memory' argument.  Since the 'memory' argument initially
// points to a NULL pointer, if nothing is done with 'memory' this method
// will be called once per rule application.  If the rule needs to be called
// multiple times, then the method needs to alter memory to point to a non
// NULL pointer.  This 'memory' area can be used to hold state between calls
// to this method.
//
// Parameters
//
//  RelExpr *before
//   IN - A Binding for the rules pattern
//
//  Context *context
//   IN - The optimization context if the rule is applied during optimization
//        or NULL.
//
//  RuleSubstituteMemory *&memory
//   IN/OUT - a pointer to a NULL pointer to a RuleSubstituteMemory object
//            on the first call per rule application, a pointer to whatever
//            the previous call left there on subsequent calls.
//
// The PhysicalTransposeRule implementation of nextSubstitute unconditionally
// creates a PhysTranspose node from a Transpose node.  It does not examine
// the 'context' and it does not use the 'memory' (it is called once per rule
// application).  By the time nextSubstitute is called, PhysicalTranspose::
// topMatch() has returned TRUE and has qualified this binding in this context
// for this rule.
//
RelExpr * PhysicalTransposeRule::nextSubstitute(RelExpr * before,
                                                Context * /*context*/,
                                                RuleSubstituteMemory *& memory)
{
  // Just to make sure things are working as expected.
  //   (If these asserts are every taken out, the compiler will
  //    likely complain about not using the 'memory' parameter)
  //
  CMPASSERT(before->getOperatorType() == REL_TRANSPOSE);
  CMPASSERT(memory == NULL);

  // We know at this point that the binding is a Transpose node.
  //
  Transpose * transBinding = (Transpose *) before;

  // Create an empty PhysTranspose node and simply copy the
  // contents of the Transpose from the before pattern.
  //
  PhysTranspose *substitute = new(CmpCommon::statementHeap())
    PhysTranspose();

  // Copy the transpose value expressions from the (before) transpose node.
  //
  substitute->setTransUnionVectorSize(transBinding->transUnionVectorSize());

  substitute->transUnionVector() =
    new (CmpCommon::statementHeap())
    ValueIdList[transBinding->transUnionVectorSize()];

  for (CollIndex i = 0; i < transBinding->transUnionVectorSize(); i++)
    substitute->transUnionVector()[i] = transBinding->transUnionVector()[i];

  // Now copy the field defined in the RelExpr and ExprNode classes.
  //
  substitute->selectionPred() = transBinding->selectionPred();
  substitute->setGroupAttr(transBinding->getGroupAttr());
  substitute->child(0) = transBinding->child(0);

  return substitute;
}

// -----------------------------------------------------------------------
// methods for class PhysicalUnPackRowsRule
// -----------------------------------------------------------------------

// Destructor for the PhysicalUnPackRowsRule
//
PhysicalUnPackRowsRule::~PhysicalUnPackRowsRule() {} 

// PhysicalUnPackRowsRule::topMatch() -------------------------------------
// The method is used to determine if a rule should fire.  If
// Rule::topMatch() returns TRUE, then the relExpr has matched the
// pattern of the rule. Here we do further examination of the context
// and relExpr to determine if this rule should be applied.
//
// Parameters:
//
// RelExpr *relExpr
//  IN : The relExpr node
//
NABoolean PhysicalUnPackRowsRule::topMatch (RelExpr *relExpr,
                                            Context *context)
{
  // Check to see if this relExpr matches the Rules pattern.
  //
  if (NOT Rule::topMatch(relExpr,context))
    return FALSE;

  // If it matched, then this must be an UnPackRows node.
  //
  CMPASSERT(relExpr->getOperatorType() == REL_UNPACKROWS);

  // Do a down cast. This should be safe.
  //
  UnPackRows *UnPackRowsNode = (UnPackRows *)relExpr;

  // Make sure UnPackRows can satisfy the physical requirements.
  // UnPackRows can not satisfy:
  //   - a sort requirement on any of the columns generated by UnPackRows.
  //   - an arranged requirement on any of the columns generated by
  //     UnPackRows.
  //   - a partitioning requirement on any of the columns generated by
  //     UnPackRows.
  //
  // If any of these requirements exist, then this method will return
  // FALSE and the rule will not fire.
  //

  const ReqdPhysicalProperty *rppForMe = context->getReqdPhysicalProperty();

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(rppForMe))
    return FALSE;

  // We check whether above-DP2 unpacking is allowed only if
  // the source is a table.
  //
  if ( UnPackRowsNode->unPackedTable() )
  {

    // If the size of the input row is larger than about 31000 / 2,
    // then the UnPackRows node should be performed in DP2.  This is
    // because the File System has a buffer limit (EXPAND_LIMIT) equal
    // to 31000 (see dml/fs_session.cpp and dml/fsglobals.h) and two
    // rows must be able to fit in the buffer.
    //
    // WARNING - If the value of EXPAND_LIMIT ever changes (becomes
    // smaller), this code could break.  A more permanent solution
    // would be to allow the DP2->ESP interface to handle any size
    // message, breaking it up into smaller chunks if necessary.

    // This value should always be equal to the #define EXPAND_LIMIT
    // as defined in dml/fsglobals.h.
    //
    const Int32 expandLimit = 31000;

    RowSize inputRowSize =
      UnPackRowsNode->child(0).getGroupAttr()->getRecordLength();

    if((NOT rppForMe->executeInDP2()) AND
       (inputRowSize > (expandLimit/2)))
      return FALSE;
  }
  else { // we're a rowset unpack
    // rowset unpack should run in master because it's inefficient and
    // risky to send rowsets from master to an ESP. An ESP eventually
    // flows the rowset's data back to the master. An ESP parallel plan
    // fragment with a large rowset can exceed IPC size limit and crash
    // at run-time (see genesis case 10-060510-3471).
    if (UnPackRowsNode->child(0).getGroupAttr()->
        getResultCardinalityForEmptyInput() >
        ActiveSchemaDB()->getDefaults().getAsLong(COMP_INT_5)) {
      if (rppForMe->getPlanExecutionLocation() != EXECUTE_IN_MASTER) {
        return FALSE;
      }
    }
  }

  // A set of valueIds containing the sortKeys, arrangedCols,
  // and partitioningKeys.
  //
  ValueIdSet allOrderColumns;

  if (rppForMe->getSortKey())
    allOrderColumns.insertList(*rppForMe->getSortKey());

  if (rppForMe->getArrangedCols())
    allOrderColumns += *rppForMe->getArrangedCols();

  if (rppForMe->getPartitioningRequirement() &&
      rppForMe->getPartitioningKey().entries() > 0)
    allOrderColumns += rppForMe->getPartitioningKey();

  // If any of the order columns or partitioning columns are the
  // generated UnPackRows columns this node cannot satisfy the
  // reqirement.

  // If there are no requirements, then this rule should fire.
  //
  if (NOT allOrderColumns.isEmpty())
    return FALSE;

  if (rppForMe->executeInDP2())
  {
     // if we are a rowsetIterator, return false.
    if (UnPackRowsNode->isRowsetIterator())
        return FALSE;
  }

  return TRUE;
} // PhysicalUnPackRows::topMatch()


// PhysicalUnPackRowsRule::nextSubstitute() ---------------------------------
// Generate the result of the application of a rule.
// This method returns a 'substitute' from applying the rule to the binding
// 'before'.  This method is called repeatedly until it returns a NULL
// pointer in the 'memory' argument.  Since the 'memory' argument initially
// points to a NULL pointer, if nothing is done with 'memory' this method
// will be called once per rule application.  If the rule needs to be called
// multiple times, then the method needs to alter memory to point to a non
// NULL pointer.  This 'memory' area can be used to hold state between calls
// to this method.
//
// Parameters
//
//  RelExpr *before
//   IN - A Binding for the rules pattern
//
//  Context *context
//   IN - The optimization context if the rule is applied during optimization
//        or NULL.
//
//  RuleSubstituteMemory *&memory
//   IN/OUT - a pointer to a NULL pointer to a RuleSubstituteMemory object
//            on the first call per rule application, a pointer to whatever
//            the previous call left there on subsequent calls.
//
// The PhysicalUnPackRowsRule implementation of nextSubstitute unconditionally
// creates a PhysUnPackRows node from a UnPackRows node.  It does not examine
// the 'context' and it does not use the 'memory' (it is called once per rule
// application).  By the time nextSubstitute is called, PhysicalUnPackRowsRule
// ::topMatch() has returned TRUE and has qualified this binding in this
// context for this rule.
//
RelExpr * PhysicalUnPackRowsRule::nextSubstitute(RelExpr * before,
                                                 Context * /*context*/,
                                                 RuleSubstituteMemory *& memory)
{
  // Just to make sure things are working as expected.
  //   (If these asserts are every taken out, the compiler will
  //    likely complain about not using the 'memory' parameter)
  //
  CMPASSERT(before->getOperatorType() == REL_UNPACKROWS);
  CMPASSERT(memory == NULL);

  // We know at this point that the binding is a UnPackRows node.
  //
  UnPackRows *unPackBinding = (UnPackRows *)before;

  // Create an empty PhysUnPackRows node and simply copy the
  // contents of the UnPackRows from the before pattern.
  //
  PhysUnPackRows *substitute = new(CmpCommon::statementHeap())
    PhysUnPackRows();

  // Copy the UnPackRows value expressions from the (before) UnPackRows node.
  //
  substitute->unPackExpr() = unPackBinding->unPackExpr();

  substitute->packingFactor() = unPackBinding->packingFactor();

  substitute->indexValue() = unPackBinding->indexValue();

  substitute->unPackedTable() = unPackBinding->unPackedTable();

  substitute->setRowsetIterator(unPackBinding->isRowsetIterator());

  substitute->setTolerateNonFatalError(unPackBinding->getTolerateNonFatalError());


  substitute->setRowwiseRowset(unPackBinding->rowwiseRowset());
  substitute->setRwrsInputSizeExpr(unPackBinding->rwrsInputSizeExpr());
  substitute->setRwrsMaxInputRowlenExpr(unPackBinding->rwrsMaxInputRowlenExpr());
  substitute->setRwrsBufferAddrExpr(unPackBinding->rwrsBufferAddrExpr());
  substitute->setRwrsOutputVids(unPackBinding->rwrsOutputVids());
  
  // Now copy the field defined in the RelExpr and ExprNode classes.
  //
  substitute->selectionPred() = unPackBinding->selectionPred();
  substitute->setGroupAttr(unPackBinding->getGroupAttr());
  substitute->child(0) = unPackBinding->child(0);

  return substitute;
}

NABoolean PhysicalUnPackRowsRule::canMatchPattern (const RelExpr *) const
{
  // UnPack is independent of required patterns, always apply this rule
  return TRUE;
}

// -----------------------------------------------------------------------
// methods for class SortEnforcerRule
// -----------------------------------------------------------------------

SortEnforcerRule::~SortEnforcerRule() {} 

NABoolean SortEnforcerRule::topMatch (RelExpr *  /* relExpr */,
                                      Context *context)
{
  const ReqdPhysicalProperty *rppForMe = context->getReqdPhysicalProperty();

  // QSTUFF
  // can't sort streams
  if (context->getGroupAttr()->isStream()){
    return FALSE;
  }

  // Don't want to tangle sorts and GET_NEXT_N commands yet
  if (context->getGroupAttr()->isEmbeddedUpdateOrDelete())
    return FALSE;
  // QSTUFF  ^^

  // If no required physical properties, there won't be any sort
  // requirement to sort for, so return FALSE. Note there can only
  // be no rpp if the operator the rule is firing on is RelRoot.
  if (rppForMe == NULL)
    return FALSE;

  // make sure a sort order is required
  if (NOT  context->requiresOrder())
    return FALSE;

  //  don't run in DP2
  if (rppForMe->executeInDP2())
    return FALSE;

  PartitioningRequirement* partReqForMe =
    rppForMe->getPartitioningRequirement();

  // If a partitioning requirement exists and it requires broadcast
  // replication, then return FALSE. Only an exchange operator
  // can satisfy a broadcast replication partitioning requirement.
  if ((partReqForMe != NULL) AND
      partReqForMe->isRequirementReplicateViaBroadcast())
    return FALSE;

  SortOrderTypeEnum sortOrderTypeReq =
    rppForMe->getSortOrderTypeReq();

  // If a sort order type requirement of ESP_NO_SORT, DP2, or
  // DP2_OR_ESP_NO_SORT exists, then return FALSE now.
  // A sort operator can only produce a sort order type of
  // ESP_VIA_SORT.
  if ((sortOrderTypeReq == ESP_NO_SORT_SOT) OR
      (sortOrderTypeReq == DP2_SOT) OR
      (sortOrderTypeReq == DP2_OR_ESP_NO_SORT_SOT))
    return FALSE;

  return TRUE;
}

RelExpr * SortEnforcerRule::nextSubstitute(RelExpr * before,
                                           Context * context,
                                           RuleSubstituteMemory *&)
{
  const ReqdPhysicalProperty* const rppForMe =
    context->getReqdPhysicalProperty();
  Sort *result = new(CmpCommon::statementHeap()) Sort(before);

  // store the required orders in the sort node
  if (rppForMe->getSortKey())
  {
    result->getSortKey() = *rppForMe->getSortKey();
  }

  if (rppForMe->getArrangedCols())
  {
    result->getArrangedCols() = *rppForMe->getArrangedCols();
  }

  result->setGroupAttr(before->getGroupAttr());
  return result;
}

Int32 SortEnforcerRule::promiseForOptimization(RelExpr *,
                                               Guidance *,
                                               Context *)
{
  // A sort enforcer is less promising than an implementation or
  // a transformation rule. This way, we will optimize the expressions
  // with a required order before trying the enforcer. When we try the
  // enforcer, the expressions with required order supply good cost bounds.
  return DefaultEnforcerRulePromise;
}

// -----------------------------------------------------------------------
// methods for class ExchangeEnforcerRule
// -----------------------------------------------------------------------

ExchangeEnforcerRule::~ExchangeEnforcerRule() {} 

NABoolean ExchangeEnforcerRule::topMatch(RelExpr *  /* relExpr */,
                                         Context *context)
{
  const ReqdPhysicalProperty *rppForMe = context->getReqdPhysicalProperty();

  // If no required physical properties, there won't be any location
  // or partitioning requirement to enforce, so return FALSE.
  // Note there can only be no rpp if the operator the rule is firing
  // on is RelRoot.
  if (rppForMe == NULL)
    return FALSE;

  // the exchange enforcer itself can't run in DP2, in all other cases
  // it could enforce either location or partitioning
  if (rppForMe->executeInDP2())
    return FALSE;

  return TRUE;
}

RelExpr * ExchangeEnforcerRule::nextSubstitute(RelExpr * before,
                                               Context * context,
                                               RuleSubstituteMemory *&)
{
  Exchange *result = new(CmpCommon::statementHeap())
    Exchange(before);

  result->setGroupAttr(before->getGroupAttr());
  return result;
}

Int32 ExchangeEnforcerRule::promiseForOptimization(RelExpr *,
                                                   Guidance *,
                                                   Context *)
{
  // A sort enforcer is less promising than an implementation or
  // a transformation rule. This way, we will optimize the expressions
  // with a required order before trying the enforcer. When we try the
  // enforcer, the expressions with required order supply good cost bounds.
  return DefaultEnforcerRulePromise;
}

// -----------------------------------------------------------------------
// methods for class PhysicalSequenceRule
// -----------------------------------------------------------------------
// Destructor for the PhysicalSequenceRule
//
PhysicalSequenceRule::~PhysicalSequenceRule() {} 

// PhysicalSequenceRule::topMatch() ----------------------------------
// The method is used to determine if a rule should fire.  If
// Rule::topMatch() returns TRUE, then the relExpr has matched the
// pattern of the rule. Here we do further examination of the context
// and relExpr to determine if this rule should be applied.
//
// Parameters:
//
// RelExpr *relExpr
//  IN : The relExpr node
//
NABoolean PhysicalSequenceRule::topMatch (RelExpr *relExpr,
                                          Context *context)
{
  // Check to see if this relExpr matches the Rules pattern.
  //
  if (NOT Rule::topMatch(relExpr,context))
    return FALSE;

  // If it matched, then this must be an RelSequence node.
  //
  CMPASSERT(relExpr->getOperatorType() == REL_SEQUENCE);

  // QSTUFF
  // Sequence functions don't work with embedded update/delete
  CMPASSERT(NOT(relExpr->getGroupAttr()->isEmbeddedUpdateOrDelete()));
  // QSTUFF

  const RelSequence *sequenceNode = (RelSequence *)relExpr;

  const ReqdPhysicalProperty *rppForMe = context->getReqdPhysicalProperty();

  // For now, the sequence node can not execute in DP2, since it
  // allocates a bunch of memory.
  //
  if(rppForMe->executeInDP2()) {
    return FALSE;
  }

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(rppForMe))
    return FALSE;

  ValueIdList reqdOrder =
    sequenceNode->mapSortKey(sequenceNode->partition());

  reqdOrder.insert(sequenceNode->mapSortKey(sequenceNode->requiredOrder()));

  // The sequence node will produce its results in the order of the
  // required order.
  //
  if(rppForMe->getSortKey() AND
     (reqdOrder.satisfiesReqdOrder(
       *rppForMe->getSortKey()) == DIFFERENT_ORDER))
  {
    return FALSE;
  }

  if(rppForMe->getArrangedCols() AND
     (reqdOrder.satisfiesReqdArrangement(
         *rppForMe->getArrangedCols()) == DIFFERENT_ORDER))
  {
    return FALSE;
  }

  return TRUE;
} // PhysicalSequenceRule::topMatch()


// PhysicalSequenceRule::nextSubstitute() ----------------------------
// Generate the result of the application of a rule.  This method
// returns a 'substitute' from applying the rule to the binding
// 'before'.  This method is called repeatedly until it returns a NULL
// pointer in the 'memory' argument.  Since the 'memory' argument
// initially points to a NULL pointer, if nothing is done with
// 'memory' this method will be called once per rule application.  If
// the rule needs to be called multiple times, then the method needs
// to alter memory to point to a non NULL pointer.  This 'memory' area
// can be used to hold state between calls to this method.
//
// Parameters
//
//  RelExpr *before
//   IN - A Binding for the rules pattern
//
//  Context *context
//   IN - The optimization context if the rule is applied during optimization
//        or NULL.
//
//  RuleSubstituteMemory *&memory
//   IN/OUT - a pointer to a NULL pointer to a RuleSubstituteMemory object
//            on the first call per rule application, a pointer to whatever
//            the previous call left there on subsequent calls.
//
// The PhysicalSequenceRule implementation of nextSubstitute
// unconditionally creates a PhysSequence node from a RelSequence
// node.  It does not examine the 'context' and it does not use the
// 'memory' (it is called once per rule application).  By the time
// nextSubstitute is called, PhysicalSequenceRule::topMatch() has
// returned TRUE and has qualified this binding in this context for
// this rule.
//
RelExpr * PhysicalSequenceRule::nextSubstitute(RelExpr * before,
                                               Context * /*context*/,
                                               RuleSubstituteMemory *& memory)
{
  // Just to make sure things are working as expected.
  //   (If these asserts are every taken out, the compiler will
  //    likely complain about not using the 'memory' parameter)
  //
  CMPASSERT(before->getOperatorType() == REL_SEQUENCE);
  CMPASSERT(memory == NULL);

  // We know at this point that the binding is a RelSequence node.
  //
  const RelSequence *relSequenceBinding = (RelSequence *)before;

  // Create an empty PhysSequence node and simply copy the
  // contents of the RelSequence from the before pattern.
  //
  PhysSequence *substitute = new(CmpCommon::statementHeap())
    PhysSequence();

  // Copy the expressions from the (before) RelSequence node.
  //
  substitute->setRequiredOrder(relSequenceBinding->requiredOrder());

  substitute->setPartition(relSequenceBinding->partition());

  substitute->setSequenceFunctions(relSequenceBinding->sequenceFunctions());

  substitute->setSequencedColumns(relSequenceBinding->sequencedColumns());

  substitute->setCancelExpr(relSequenceBinding->cancelExpr());

  substitute->setHasTDFunctions(relSequenceBinding->getHasTDFunctions());

  substitute->setHasOlapFunctions(relSequenceBinding->getHasOlapFunctions());

  // Now copy the field defined in the RelExpr and ExprNode classes.
  //
  substitute->selectionPred() = relSequenceBinding->getSelectionPred();
  substitute->setGroupAttr(relSequenceBinding->getGroupAttr());
  substitute->child(0) = relSequenceBinding->child(0);

  substitute->retrieveCachedHistoryInfo((RelSequence *) relSequenceBinding);

  return substitute;
}


// -----------------------------------------------------------------------
// methods for class PhysicalSampleRule
// -----------------------------------------------------------------------

// Destructor for the PhysicalSampleRule
//
PhysicalSampleRule::~PhysicalSampleRule() {} 

// PhysicalSampleRule::topMatch() -------------------------------------
// The method is used to determine if a rule should fire.  If
// Rule::topMatch() returns TRUE, then the relExpr has matched the
// pattern of the rule. Here we do further examination of the context
// and relExpr to determine if this rule should be applied.
//
// Parameters:
//
// RelExpr *relExpr
//  IN : The relExpr node
//
NABoolean PhysicalSampleRule::topMatch (RelExpr *relExpr,
                                        Context *context)
{
  // Check to see if this relExpr matches the Rules pattern.
  //
  if (NOT Rule::topMatch(relExpr,context))
    return FALSE;

  // If it matched, then this must be a RelSample node.
  //
  CMPASSERT(relExpr->getOperatorType() == REL_SAMPLE);

  RelSample *sampleNode = (RelSample *)relExpr;

  // If this is a CLUSTER sample, then this may have already been
  // transformed into a sample scan by the SampleScanRule
  // (TransRule.cpp) and we do not want to implement this with a
  // physical sample node (this rule).  If the SampleScanRule
  // succeeded, then do not apply this rule.  On the other hand, if
  // for whatever reason, the SampleScanRule did not succeed, then use
  // this rule to implement a physical scan node.  In this case an
  // appropriate error message will be returned indicating that a
  // plan with CLUSTER sampling could not be found.  Note that the
  // promiseForOptimization for the SampleScanRule has been raised to
  // force the SampleScanRule::nextSubstitute (but not necessarily the
  // topMatch method) to be applied before this Rule.
  //
  if (sampleNode->sampleType() == RelSample::CLUSTER &&
      sampleNode->sampleScanSucceeded())
  {
    return FALSE;
  }

  const ReqdPhysicalProperty *rppForMe = context->getReqdPhysicalProperty();

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(rppForMe))
    return FALSE;

  ValueIdList reqdOrder =
    sampleNode->mapSortKey(sampleNode->requiredOrder());

  // The Sample node will produce its results in the order of the
  // required order.
  //
  if(rppForMe->getSortKey() AND
     (reqdOrder.satisfiesReqdOrder(
       *rppForMe->getSortKey()) == DIFFERENT_ORDER))
  {
    return FALSE;
  }

  if(rppForMe->getArrangedCols() AND
     (reqdOrder.satisfiesReqdArrangement(
        *rppForMe->getArrangedCols()) == DIFFERENT_ORDER))
  {
    return FALSE;
  }

  return TRUE;
} // PhysicalSample::topMatch()


// PhysicalSampleRule::nextSubstitute() ---------------------------------
// Generate the result of the application of a rule.
// This method returns a 'substitute' from applying the rule to the binding
// 'before'.  This method is called repeatedly until it returns a NULL
// pointer in the 'memory' argument.  Since the 'memory' argument initially
// points to a NULL pointer, if nothing is done with 'memory' this method
// will be called once per rule application.  If the rule needs to be called
// multiple times, then the method needs to alter memory to point to a non
// NULL pointer.  This 'memory' area can be used to hold state between calls
// to this method.
//
// Parameters
//
//  RelExpr *before
//   IN - A Binding for the rules pattern
//
//  Context *context
//   IN - The optimization context if the rule is applied during optimization
//        or NULL.
//
//  RuleSubstituteMemory *&memory
//   IN/OUT - a pointer to a NULL pointer to a RuleSubstituteMemory object
//            on the first call per rule application, a pointer to whatever
//            the previous call left there on subsequent calls.
//
// The PhysicalSampleRule implementation of nextSubstitute unconditionally
// creates a PhysSample node from a RelSample node.  It does not examine
// the 'context' and it does not use the 'memory' (it is called once per rule
// application).  By the time nextSubstitute is called, PhysicalSampleRule
// ::topMatch() has returned TRUE and has qualified this binding in this
// context for this rule.
//
RelExpr * PhysicalSampleRule::nextSubstitute(RelExpr * before,
                                             Context * /*context*/,
                                             RuleSubstituteMemory *& memory)
{
  // Just to make sure things are working as expected.
  //   (If these asserts are every taken out, the compiler will
  //    likely complain about not using the 'memory' parameter)
  //
  CMPASSERT(before->getOperatorType() == REL_SAMPLE);
  CMPASSERT(memory == NULL);

  // We know at this point that the binding is a UnPackRows node.
  //
  RelSample *sampleBinding = (RelSample *)before;

  // If this is a CLUSTER sample, then this should have been
  // transformed into a sample scan by the SampleScanRule
  // (TransRule.cpp) and we do not want to implement this with a
  // physical sample node (this rule).  If the SampleScanRule
  // succeeded, then do not apply this rule.  On the other hand, if
  // for whatever reason, the SampleScanRule did not succeed, then use
  // this rule to implement a physical scan node.  In this case an
  // appropriate error message will be returned indicating that a
  // plan with CLUSTER sampling could not be found.  Note that the
  // promiseForOptimization for the SampleScanRule has been raised to
  // force the SampleScanRule::nextSubstitute (but not necessarily the
  // topMatch method) to be applied before this Rule's nextSubstitute.
  //
  if (sampleBinding->sampleType() == RelSample::CLUSTER &&
      sampleBinding->sampleScanSucceeded())
  {
    return NULL;
  }

  // Create an empty PhysSample node and simply copy the
  // contents of the RelSample from the before pattern.
  //
  PhysSample *substitute = new(CmpCommon::statementHeap())
    PhysSample();

  // Copy the RelSample value expressions from the (before) UnPackRows node.
  //
  substitute->sampleType(sampleBinding->sampleType());

  substitute->balanceExpr() = sampleBinding->balanceExpr();

  substitute->sampledColumns() = sampleBinding->sampledColumns();

  substitute->requiredOrder() = sampleBinding->requiredOrder();

  // Now copy the field defined in the RelExpr and ExprNode classes.
  //
  substitute->selectionPred() = sampleBinding->selectionPred();
  substitute->setGroupAttr(sampleBinding->getGroupAttr());
  substitute->child(0) = sampleBinding->child(0);

  return substitute;
}

// -----------------------------------------------------------------------
// methods for class PhysicalSPProxyFuncRule
// -----------------------------------------------------------------------
PhysicalSPProxyFuncRule::~PhysicalSPProxyFuncRule()
{}

NABoolean PhysicalSPProxyFuncRule::topMatch(RelExpr *relExpr,
                                            Context *context)
{
  if (NOT Rule::topMatch(relExpr,context))
    return FALSE;
  
  return TRUE;
}

RelExpr *PhysicalSPProxyFuncRule::nextSubstitute(RelExpr *before,
                                                 Context *context,
                                                 RuleSubstituteMemory *&)
{
  // Create a new physical node and copy all attributes. The parent
  // class method RelExpr::copyTopNode() does a "deeper" copy than the
  // RelExpr copy constructor.
  PhysicalSPProxyFunc *result = new (CmpCommon::statementHeap()) 
                                                     PhysicalSPProxyFunc();

  before->copyTopNode(result, CmpCommon::statementHeap());

  // Some fields are not copied and need to be filled in.
  result->setGroupAttr(before->getGroupAttr());
  
  return result;
}

// -----------------------------------------------------------------------
// methods for class PhysicalExtractSourceRule
// -----------------------------------------------------------------------
PhysicalExtractSourceRule::~PhysicalExtractSourceRule() {} 

NABoolean PhysicalExtractSourceRule::topMatch(RelExpr *relExpr,
                                              Context *context)
{
  if (NOT Rule::topMatch(relExpr,context))
    return FALSE;
  return TRUE;
}

RelExpr *PhysicalExtractSourceRule::nextSubstitute(RelExpr *before,
                                                   Context *context,
                                                   RuleSubstituteMemory *&)
{
  // Create a new physical node and copy all attributes. The parent
  // class method RelExpr::copyTopNode() does a "deeper" copy than the
  // RelExpr copy constructor.
  PhysicalExtractSource *result = new (CmpCommon::statementHeap()) 
                                                    PhysicalExtractSource();
  before->copyTopNode(result, CmpCommon::statementHeap());
  
  // Some fields are not copied and need to be filled in.
  result->setGroupAttr(before->getGroupAttr());
  
  return (RelExpr *) result;
}

PhysicalIsolatedScalarUDFRule::~PhysicalIsolatedScalarUDFRule() {} 

NABoolean PhysicalIsolatedScalarUDFRule::topMatch (RelExpr *relExpr,
                                                Context *context)
{
  if (NOT Rule::topMatch(relExpr, context))
    return FALSE;

  const ReqdPhysicalProperty* const rppForMe =
    context->getReqdPhysicalProperty();

  // UDFs cannot execute in DP2 so if we are asked to do so, refuse.
  if (rppForMe->executeInDP2())
    return FALSE;

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(rppForMe))
    return FALSE;

  if ((rppForMe->getPartitioningRequirement() != NULL) AND
      (NOT(rppForMe->getPartitioningRequirement()->isRequirementExactlyOne()))
      AND
      (NOT(rppForMe->getPartitioningRequirement()->isRequirementReplicateNoBroadcast())))
    return FALSE;


  return TRUE;
}

RelExpr * PhysicalIsolatedScalarUDFRule::nextSubstitute(RelExpr * before,
                                            Context * /*context*/,
                                            RuleSubstituteMemory *& /*memory*/)
{
  CMPASSERT(before->getOperatorType() == REL_ISOLATED_SCALAR_UDF);
  IsolatedScalarUDF * bef = (IsolatedScalarUDF *) before;

  // Simply copy the contents of the IsolatedScalarUDF from the before pattern.
  PhysicalIsolatedScalarUDF *result = new (CmpCommon::statementHeap())
    PhysicalIsolatedScalarUDF(CmpCommon::statementHeap());

  bef->copyTopNode(result, CmpCommon::statementHeap());

  // now set the group attributes of the result's top node
  result->setGroupAttr(before->getGroupAttr());

  return result;
}

PhysicalTMUDFRule::~PhysicalTMUDFRule() {} 

NABoolean PhysicalTMUDFRule::topMatch (RelExpr *relExpr,
                                       Context *context)
{
  if (NOT relExpr->getOperator().match(REL_ANY_TABLE_MAPPING_UDF))
    return FALSE;
  if (relExpr->isPhysical())
    return FALSE;

  if (context->getReqdPhysicalProperty()->executeInDP2())
    return FALSE;

  const ReqdPhysicalProperty* const rppForMe =
    context->getReqdPhysicalProperty();
  
  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(rppForMe))
    return FALSE;

  return TRUE;
}

RelExpr * PhysicalTMUDFRule::nextSubstitute(RelExpr * before,
                                            Context * /*context*/,
                                            RuleSubstituteMemory *& /*memory*/)
{
  CMPASSERT(before->getOperator().match(REL_ANY_TABLE_MAPPING_UDF));
  TableMappingUDF * bef = (TableMappingUDF *) before;

  // Simply copy the contents of the TableMappingUDF from the before pattern.
  PhysicalTableMappingUDF *result = new (CmpCommon::statementHeap())
    PhysicalTableMappingUDF(before->getArity(), CmpCommon::statementHeap());
  bef->TableMappingUDF::copyTopNode(result, CmpCommon::statementHeap());

  // now set the group attributes of the result's top node
  result->setGroupAttr(before->getGroupAttr());
  for (Int32 i=0; i < before->getArity(); i++)
    result->child(i) = before->child(i);

  return result;
}

NABoolean PhysicalTMUDFRule::canMatchPattern (const RelExpr *pattern) const
{
  switch (pattern->getOperatorType())
    {
    case REL_ANY_TABLE_MAPPING_UDF:
    case REL_ANY_LEAF_TABLE_MAPPING_UDF:
    case REL_ANY_UNARY_TABLE_MAPPING_UDF:
    case REL_ANY_BINARY_TABLE_MAPPING_UDF:
      return TRUE;

    default:
      if (pattern->getOperator().isWildcard())
        return FALSE;
      else
        return pattern->getOperator().match(REL_ANY_TABLE_MAPPING_UDF);
    }
}

PhysicalFastExtractRule::~PhysicalFastExtractRule() {}

NABoolean PhysicalFastExtractRule::topMatch (RelExpr *relExpr,
                                                Context *context)
{
  if (NOT relExpr->getOperator().match(REL_FAST_EXTRACT))
    return FALSE;
  if (relExpr->isPhysical())
    return FALSE;

    if ((context->getReqdPhysicalProperty()->executeInDP2()))
      return FALSE;

  const ReqdPhysicalProperty* const rppForMe =
    context->getReqdPhysicalProperty();

  // Check for required physical properties that require an enforcer
  // operator to succeed.
  if (relExpr->rppRequiresEnforcer(rppForMe))
    return FALSE;

  if ((rppForMe->getPartitioningRequirement() != NULL) AND
      (rppForMe->getPartitioningRequirement()->isRequirementReplicateNoBroadcast()))
    return FALSE;

  return TRUE;
}

RelExpr * PhysicalFastExtractRule::nextSubstitute(RelExpr * before,
                                            Context * /*context*/,
                                            RuleSubstituteMemory *& /*memory*/)
{
  CMPASSERT(before->getOperatorType() == REL_FAST_EXTRACT);
  FastExtract * bef = (FastExtract *) before;

  // Simply copy the contents of the TableMappingUDF from the before pattern.
  PhysicalFastExtract *result = new (CmpCommon::statementHeap())
    PhysicalFastExtract(before->child(0)->castToRelExpr(),
    					CmpCommon::statementHeap());
  bef->copyTopNode(result, CmpCommon::statementHeap());

  // now set the group attributes of the result's top node
  result->setGroupAttr(before->getGroupAttr());

  return result;
}
