/**********************************************************************
//
// @@@ 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:         RelRoutine.cpp
* Description:  RelExprs related to support for Routines and UDFs
*               Old RelRoutine class got renamed to RelRoutine
*               class resturcturing effort to support UDFs.
* Created:      6/29/09
* Language:     C++
*
*************************************************************************
*/

#define SQLPARSERGLOBALS_FLAGS               // must precede all #include's
#define SQLPARSERGLOBALS_NADEFAULTS

#include "Debug.h"
#include "Sqlcomp.h"
#include "AllRelExpr.h"
#include "GroupAttr.h"
#include "opt.h"
#include "PhyProp.h"
#include "mdam.h"
#include "ControlDB.h"
#include "disjuncts.h"
#include "ScanOptimizer.h"
#include "CmpContext.h"
#include "StmtDDLCreateTrigger.h"
#include "ExpError.h"
#include "ComTransInfo.h"
#include "BindWA.h"
#include "Refresh.h"
#include "CmpMain.h"
#include "ControlDB.h"
#include "ElemDDLColDef.h"
#include "Analyzer.h"
#include "OptHints.h"
#include "ComTdbSendTop.h"
#include "DatetimeType.h"
#include "ItemNAType.h"
#include "SequenceGeneratorAttributes.h"
#include "SqlParserGlobals.h"
#include "RelRoutine.h"
#include "ElemDDLColDefArray.h"
#include "CmpSeabaseDDL.h"
#include "UdfDllInteraction.h"
#include "TrafDDLdesc.h"


// -----------------------------------------------------------------------
// methods for class RelRoutine
// -----------------------------------------------------------------------

//! RelRoutine::RelRoutine Copy Constructor
RelRoutine::RelRoutine(const RelRoutine & other, CollHeap *h )
: RelExpr(other.getOperatorType(), NULL, NULL, h)
{
  setSelectionPredicates(other.getSelectionPred());
  procAllParamsTree_ = other.procAllParamsTree_;
  procAllParamsVids_ = other.procAllParamsVids_;
  procInputParamsVids_ = other.procInputParamsVids_;
  procOutputParamsVids_ = other.procOutputParamsVids_;
  routineName_ = other.routineName_;

   // Just make a deep copy of the Routine Desc
  if (other.routined_ != NULL)
    routined_ = new (h) RoutineDesc(*other.routined_, h);
  else 
    routined_ = NULL;
  hasSubquery_ = other.hasSubquery_;
}

//! RelRoutine::~RelRoutine Destructor
RelRoutine::~RelRoutine()
{
   // do not deallocate routine_ - shallow copy
}

//! RelRoutine::getPotentialOutputValues method
//  gets the output values for the Routine from the RoutineDesc
void RelRoutine::getPotentialOutputValues(
     ValueIdSet & outputValues) const
{
  outputValues.clear();
  //
  // The attached Routine descriptor has a list of all the columns
  // that this node can possibly generate.
  //
  RoutineDesc *rDesc = getRoutineDesc();
  if (rDesc != NULL) 
    outputValues.insertList( getRoutineDesc()->getOutputColumnList() );
} // RelRoutine::getPotentialOutputValues()

//! RelRoutine::topHash method
HashValue RelRoutine::topHash()
{
  HashValue result = RelExpr::topHash();

  result ^= arity_;
  result ^= procAllParamsVids_;
  result ^= routineName_.getQualifiedNameAsAnsiString();

  return result;
}

//! RelRoutine::duplicateMatch method
NABoolean RelRoutine::duplicateMatch(const RelExpr & other) const
{
  if (!RelExpr::duplicateMatch(other))
    return FALSE;

  RelRoutine &o = (RelRoutine &) other;

  if (NOT (procAllParamsVids_ == o.procAllParamsVids_))
   return FALSE;
  if (NOT (routineName_ == o.routineName_))
   return FALSE;
  if (NOT (arity_ == o.arity_))
   return FALSE;

  return TRUE;
}

//! RelRoutine::copyTopNode method
RelExpr * RelRoutine::copyTopNode(RelExpr *derivedNode, CollHeap* outHeap)
{
  RelRoutine *result;

  if (derivedNode == NULL)
    result = new (outHeap) RelRoutine(NULL,
                                      REL_ROUTINE,
                                      outHeap);
  else
    result = (RelRoutine *) derivedNode;

  result->hasSubquery_           = hasSubquery_;
  result->routineName_           = routineName_;
  result->procAllParamsVids_     = procAllParamsVids_;
  result->procInputParamsVids_   = procInputParamsVids_;
  result->procOutputParamsVids_  = procOutputParamsVids_;
  result->arity_ = arity_;

  // Make a deep copy unless we have been transformed. Once we have 
  // ValueIds for all the parameters, we don't need the tree.
  if (nodeIsTransformed())
  {
    result->procAllParamsTree_ = NULL;
  }
  else
  {
    // Since we are not transformed, we know that  we will not have any
    // VEGReferences in the tree and it is safe to copy it, otherwise
    // we would assert since VEGReferences do not have a copyTopNode() 
    // method.. 
    if (procAllParamsTree_ != NULL)
                    result->procAllParamsTree_ = procAllParamsTree_->
                                           copyTree(outHeap)->castToItemExpr();
  }

    // Copy routine descriptor, by creating another instance
  if (routined_ != NULL)
  {
    result->routined_ = new (outHeap) RoutineDesc(*routined_, outHeap);

  } 
  else
  {
    result->routined_ = NULL;
  }
      
    // we make sure we copy the rest of the class structure by calling the 
    // parent class copyTopNode()
  return RelExpr::copyTopNode(result, outHeap);
}

//! RelRoutine::addLocalExpr method
void RelRoutine::addLocalExpr(LIST(ExprNode *) &xlist,
                              LIST(NAString) &llist) const
{
  if (procAllParamsTree_ != NULL OR
      NOT procAllParamsVids_.isEmpty())
  {
    if(procAllParamsVids_.isEmpty())
      xlist.insert(procAllParamsTree_);
    else
      xlist.insert(procAllParamsVids_.rebuildExprTree());

    llist.insert("actual_parameters");
  }
  
  RelExpr::addLocalExpr(xlist,llist);
}

//! RelRoutine::getText method
const NAString RelRoutine::getText() const
{
  return "relroutine";
}

// -----------------------------------------------------------------------
// methods for class TableValuedFunction
// -----------------------------------------------------------------------


//! TableValuedFunction::~TableValuedFunction Destructor
TableValuedFunction::~TableValuedFunction()
{
}

//! TableValuedFunction::getPotentialOutputValues method
void TableValuedFunction::getPotentialOutputValues(
     ValueIdSet & outputValues) const
{
  outputValues.clear();
  //
  // The attached table descriptor has a list of all the columns
  // that this node can possibly generate.
  //
  outputValues.insertList( getTableDesc()->getColumnList() );
} // TableValuedFunction::getPotentialOutputValues()


//! TableValuedFunction::duplicateMatch method
NABoolean TableValuedFunction::duplicateMatch(const RelExpr & other) const
{
   if (! RelRoutine::duplicateMatch(other)) 
      return FALSE;

   TableValuedFunction &o = (TableValuedFunction &) other;
   if (tabId_ == o.tabId_)
   {
      return TRUE;
   }

   return FALSE;

}

//! TableValuedFunction::copyTopNode method
RelExpr * TableValuedFunction::copyTopNode(RelExpr *derivedNode,
                                CollHeap* outHeap)

{
   TableValuedFunction *result;

   if (derivedNode == NULL)
   {
     result = new (outHeap) TableValuedFunction(NULL,
                               getOperatorType(),
                               outHeap);
   }
   else
     result = (TableValuedFunction *) derivedNode;

   // Make a shallow copy of the table decriptor. This works the same was 
   // as what we do for  a Scan node.
   result->tabId_ = tabId_;
   result->userTableName_ = userTableName_ ;

   return RelRoutine::copyTopNode(result, outHeap);
}

//! TableValuedFunction::getText method
const NAString TableValuedFunction::getText() const
{
  return "TableValuedFunction";
}

// -----------------------------------------------------------------------
// methods for class TableMappingUDFChildInfo
// -----------------------------------------------------------------------

TableMappingUDFChildInfo::TableMappingUDFChildInfo
                (const TableMappingUDFChildInfo &other)
{
  inputTabName_ = other.inputTabName_;
  inputTabCols_ = other.inputTabCols_; 
  partType_ = other.partType_;
  partitionBy_ = other.partitionBy_;
  orderBy_ = other.orderBy_;
  outputs_ = other.outputs_;
}

void TableMappingUDFChildInfo::removeColumn(CollIndex i)
{
  CMPASSERT(!partitionBy_.contains(outputs_[i]));
  CMPASSERT(!orderBy_.contains(outputs_[i]));
  inputTabCols_.removeAt(i);
  outputs_.removeAt(i);
}

// -----------------------------------------------------------------------
// methods for class TableMappingUDF
// -----------------------------------------------------------------------

//! TableMappingUDF::TableMappingUDF Copy Constructor
TableMappingUDF::TableMappingUDF(const TableMappingUDF & other)
  : TableValuedFunction(other),childInfo_(STMTHEAP)
{
  selectivityFactor_ = other.selectivityFactor_;
  cardinalityHint_ = other.cardinalityHint_;
  for(CollIndex i = 0; i < other.childInfo_.entries(); i++)
  {
    childInfo_.insert(other.childInfo_[i]); // shallow copy, since copt ctor 
  }// called during nextSubstitue
  scalarInputParams_ = other.scalarInputParams_;
  outputParams_ = other.outputParams_;
  dllInteraction_ = other.dllInteraction_ ;
  invocationInfo_ = other.invocationInfo_;
  routineHandle_ = other.routineHandle_;
  constParamBuffer_ = other.constParamBuffer_; // shallow copy is ok
  constParamBufferLen_ = other.constParamBufferLen_;
  udfOutputToChildInputMap_ = other.udfOutputToChildInputMap_;
  isNormalized_ = other.isNormalized_;
}

//! TableMappingUDF::~TableMappingUDF Destructor
TableMappingUDF::~TableMappingUDF()
{
  // delete [] childInfo_ ;
}

//! TableMappingUDF::copyTopNode method
RelExpr * TableMappingUDF::copyTopNode(RelExpr *derivedNode,
                                CollHeap* outHeap)

{
   TableMappingUDF *result;

   if (derivedNode == NULL)
   {
     result = new (outHeap) TableMappingUDF(getArity(),
                                            NULL,
                                            outHeap);
   }
   else
     result = (TableMappingUDF *) derivedNode;

  for(CollIndex i = 0; i < childInfo_.entries(); i++)
  {
    TableMappingUDFChildInfo * ci = new (outHeap)
	TableMappingUDFChildInfo(*(childInfo_[i]));
      result->childInfo_.insert(ci);
  } 
  result->selectivityFactor_ = selectivityFactor_;
  result->cardinalityHint_ = cardinalityHint_;
  result->scalarInputParams_ = scalarInputParams_;
  result->outputParams_ = outputParams_;
  result->dllInteraction_ = dllInteraction_;
  result->invocationInfo_ = invocationInfo_;     // shallow copies for these
  result->routineHandle_ = routineHandle_;       // items are ok, they are
  result->constParamBuffer_ = constParamBuffer_; // shared for this invocation
  result->constParamBufferLen_ = constParamBufferLen_;
  result->predsEvaluatedByUDF_ = predsEvaluatedByUDF_;
  result->udfOutputToChildInputMap_ = udfOutputToChildInputMap_;
  result->isNormalized_ = isNormalized_;
  return TableValuedFunction::copyTopNode(result, outHeap);
}

TableMappingUDF *TableMappingUDF::castToTableMappingUDF()
{
  return this;
}

//! TableMappingUDF::getText method
const NAString TableMappingUDF::getText() const
{
 NAString op(CmpCommon::statementHeap());
 op = "tmudf ";
 return op + getUserTableName().getTextWithSpecialType();
}

PredefinedTableMappingFunction * TableMappingUDF::castToPredefinedTableMappingFunction()
{
  return NULL;
}

void TableMappingUDF::addLocalExpr(LIST(ExprNode *) &xlist,
                            LIST(NAString) &llist) const
{
  if (!predsEvaluatedByUDF_.isEmpty())
    {
      xlist.insert(predsEvaluatedByUDF_.rebuildExprTree());
      llist.insert("preds_evaluated_by_udf");
    }

  for(CollIndex i = 0; i < childInfo_.entries(); i++)
  {
    if (NOT childInfo_[i]->partitionBy_.isEmpty())
    {
      xlist.insert(childInfo_[i]->partitionBy_.rebuildExprTree());
      llist.insert("child_part_by");
    }
    if (NOT childInfo_[i]->orderBy_.isEmpty())
    {
      xlist.insert(childInfo_[i]->orderBy_.rebuildExprTree());
      llist.insert("child_order_by");
    }
    if (NOT childInfo_[i]->outputs_.isEmpty())
    {
      xlist.insert(childInfo_[i]->outputs_.rebuildExprTree());
      llist.insert("child_outputs");
    }
  } 
  RelRoutine::addLocalExpr(xlist,llist);
}

void TableMappingUDF::transformNode(NormWA & normWARef,
    ExprGroupId & locationOfPointerToMe) 
{
  RelExpr::transformNode(normWARef, locationOfPointerToMe);
}

void TableMappingUDF::rewriteNode(NormWA & normWARef)
{
  for(Int32 i = 0; i < getArity(); i++)
  {
    childInfo_[i]->partitionBy_.normalizeNode(normWARef);
    childInfo_[i]->orderBy_.normalizeNode(normWARef);
    childInfo_[i]->outputs_.normalizeNode(normWARef);
  }
  udfOutputToChildInputMap_.normalizeNode(normWARef);
  // rewrite group attributes and selection pred
  RelExpr::rewriteNode(normWARef);
}

void TableMappingUDF::primeGroupAnalysis()
{
  RelExpr::primeGroupAnalysis();
};


void TableMappingUDF::getPotentialOutputValues(ValueIdSet & vs) const 
{
  vs.clear();
  vs.insertList(getProcOutputParamsVids());
};
void TableMappingUDF::getPotentialOutputValuesAsVEGs(ValueIdSet& outputs) const
{
  CMPASSERT(0);
};
void TableMappingUDF::pullUpPreds()
{
   // A TMUDF never pulls up predicates from its children.
   for (Int32 i = 0; i < getArity(); i++) 
    child(i)->recomputeOuterReferences();
};
void TableMappingUDF::recomputeOuterReferences()
{
  // ---------------------------------------------------------------------
  // Delete all those input values that are no longer referenced on
  // this operator because the predicates that reference them have 
  // been pulled up.
  // ---------------------------------------------------------------------
  ValueIdSet outerRefs = getGroupAttr()->getCharacteristicInputs(); 

  // Remove from outerRefs those valueIds that are not needed
  // by my selection predicate
  GroupAttributes emptyGA;
  ValueIdSet leafExprSet, emptySet;
  ValueIdSet exprSet(getProcInputParamsVids());

  exprSet.getLeafValuesForCoverTest(leafExprSet, emptyGA, emptySet); 
  leafExprSet += getSelectionPred();

  // Also add any values mentioned in the select list, order by or
  // partition by of the child queries. Those may contain expressions
  // that are not stored anywhere else and may not be evaluated in the
  // child. For example, if the child query is "select a, current_date..."
  // then the child may only produce a, but not current_date.
  for (CollIndex c=0; c<getArity(); c++)
    {
      leafExprSet += childInfo_[c]->getPartitionBy();
      leafExprSet.insertList(childInfo_[c]->getOrderBy());
      leafExprSet.insertList(childInfo_[c]->getOutputs());
    }

  leafExprSet.weedOutUnreferenced(outerRefs);

  // Add to outerRefs those that my children need.
  Int32 arity = getArity();
  for (Int32 i = 0; i < arity; i++)
    {
      outerRefs += child(i).getPtr()->getGroupAttr()->getCharacteristicInputs();
    }

  // set my Character Inputs to this new minimal set.
  getGroupAttr()->setCharacteristicInputs(outerRefs);
};

void TableMappingUDF::pushdownCoveredExpr(
     const ValueIdSet & outputExprOnOperator,
     const ValueIdSet & newExternalInputs,
     ValueIdSet& predOnOperator,
     const ValueIdSet *nonPredNonOutputExprOnOperator,
     Lng32 childId)
{
  if (!isNormalized_)
    {
      ValueIdSet exprOnParent;
      ValueIdSet predsToPushDown;
      // At this point, we have determined the characteristic outputs
      // of the TableMappingUDF and a set of selection predicates to
      // be evaluated on the result of the UDF.

      // Call the UDF code to determine which child outputs we should
      // require as child characteristic outputs and what to do with the
      // selection predicates

      // The logic below only works if we push preds to all children
      // at the same time.
      CMPASSERT(childId == -MAX_REL_ARITY);

      // interact with the UDF
      NABoolean status = dllInteraction_->describeDataflow(
           this,
           exprOnParent,
           selectionPred(),
           predsEvaluatedByUDF_,
           predsToPushDown);
      // no good way to return failure, error will be detected
      // at the end of the normalization phase

      // rewrite the predicates to be pushed down in terms
      // of the values produced by the table-valued inputs
      ValueIdSet childPredsToPushDown;
      udfOutputToChildInputMap_.rewriteValueIdSetDown(
           predsToPushDown, childPredsToPushDown);

      // remaining selection predicates stay with the parent
      exprOnParent += selectionPred();
      if(nonPredNonOutputExprOnOperator)
        exprOnParent += *nonPredNonOutputExprOnOperator;

      RelExpr::pushdownCoveredExpr(outputExprOnOperator,
                                   newExternalInputs,
                                   childPredsToPushDown,
                                   &exprOnParent,
                                   childId);

      // apply any leftover predicates back to the parent, but need
      // to rewrite them in terms of the parent first
      if (!childPredsToPushDown.isEmpty())
        {
          predsToPushDown.clear();
          // Map the leftovers back to the language of out outputs.
          // Note that since we rewrote these values on the way down,
          // a simple mapping will suffice when going back up, as they
          // are recorded already in the map table.
          udfOutputToChildInputMap_.mapValueIdSetUp(predsToPushDown,
                                                    childPredsToPushDown);
          selectionPred() += predsToPushDown;
        }
      // indicate that we did this step and recorded needed columns
      // and pushed predicate in the InvocationInfo, don't change this
      // information from now on (unless recording such changes in
      // UDRPlanInfo)
      isNormalized_ = TRUE;
    }
  // else
  // If this is past the normalizer UDF interface call,
  // pushdownCoveredExpr() has already been called in the
  // normalizer. We cannot push down predicates and/or eliminate
  // columns in this phase, because the UDR has already been told
  // which columns and predicates we need. Also, this situation could
  // apply only to one plan alternative and the UDRInvocationInfo
  // object that records the predicates and columns is shared among
  // all the alternatives. If we want to do such pushdown in the
  // future (and this would be very desirable, something like a
  // "routine join"), then we'll have to record the pushed down
  // predicates and eliminated columns in the UDRPlanInfo object and
  // we'll have to add another compiler interface method for the UDR
  // writer.
};


void TableMappingUDF::synthLogProp(NormWA * normWAPtr)
{
  // avoid multiple calls
  if (getGroupAttr()->existsLogExprForSynthesis())
    return;

  RelExpr::synthLogProp(normWAPtr);
  // +1 on the TMUDFs
  getGroupAttr()->setNumTMUDFs(getGroupAttr()->getNumTMUDFs()+1);

  NABoolean status = dllInteraction_->describeConstraints(this);
  // rely on diags area to communicate failure
};

void TableMappingUDF::finishSynthEstLogProp()
{
  RelExpr::finishSynthEstLogProp();
};


void TableMappingUDF::synthEstLogProp(const EstLogPropSharedPtr& inputEstLogProp)
{
  if (getGroupAttr()->isPropSynthesized(inputEstLogProp)) return;

  CostScalar inputFromParentCard = inputEstLogProp->getResultCardinality();

  // create an empty result
  EstLogPropSharedPtr myEstProps(new (HISTHEAP) EstLogProp(*inputEstLogProp));

  // call the compiler UDF interaction, this may produce row counts and UECs
  // for the output columns of the UDF, if specified by the UDF writer
  NABoolean status = dllInteraction_->describeStatistics(this, inputEstLogProp);

  CostScalar udfCard = dllInteraction_->getResultCardinality(this);
  NABoolean udfSpecifiedCard = (udfCard >= 0);
  int arity = getArity();

  // Set tmUdf output cardinality, unless specified by UDF writer
  if (!udfSpecifiedCard)
    {
      // 1. no children: children histograms will have cardinality of 1
      if(arity < 1)
        {
          // CQD is used for default cardinality of a leaf TMUDF
          udfCard = 
            ActiveSchemaDB()->getDefaults().getAsDouble(TMUDF_LEAF_CARDINALITY);
        }
      else
        {
          // use information about the function type (e.g. mapper, reducer) to
          // estimate the row count
          CostScalar udfCardFactor =
            dllInteraction_->getCardinalityScaleFactorFromFunctionType(this);

          // if the function type does not help, use a CQD
          if (udfCardFactor < 0)
            udfCardFactor =
              ActiveSchemaDB()->getDefaults().getAsDouble(TMUDF_CARDINALITY_FACTOR);

          // base the result cardinality of the child with the highest cardinality
          for (CollIndex c=0; c<getArity(); c++)
            {
              EstLogPropSharedPtr childrenInputEstLogProp = child(c).outputLogProp(inputEstLogProp);
              CostScalar childCard = child(c).outputLogProp(inputEstLogProp)->getResultCardinality();

              myEstProps->unresolvedPreds() += childrenInputEstLogProp->getUnresolvedPreds();

              if (childCard > udfCard)
                udfCard = childCard;
            }

          udfCard = udfCard * udfCardFactor;
        }
    }

  myEstProps->setResultCardinality(udfCard);

  // use child(ren) histograms to figure out output column uecs
  ValueIdList &tmudfOutputs = getProcOutputParamsVids();
  ColStatDescList udfColStatDescList(CmpCommon::statementHeap());

  for(CollIndex c=0; c<tmudfOutputs.entries(); c++)
  {
    ValueId udfOutputCol = tmudfOutputs[c];
    NABoolean inputHistFound = FALSE;
    ValueId inputValId;
    ColStatsSharedPtr inputColStats;
    // initialize the uec with the value specified by the UDF, or -1
    CostScalar colUec = dllInteraction_->getOutputColumnUEC(this, c);
    
    if (arity > 0)
      {
        udfOutputToChildInputMap_.mapValueIdDown(udfOutputCol, inputValId);

        if(inputValId == udfOutputCol)
          // udfOutputCol is not passed through from a child
          inputValId = NULL_VALUE_ID;

        if(inputValId != NULL_VALUE_ID)
          {
            for (CollIndex c=0; c<arity && !inputHistFound; c++)
              {
                // try to get child histogram from this child
                inputColStats =
                  child(c).outputLogProp(inputEstLogProp)->
                  getColStats().getColStatsPtrForColumn(inputValId);

                if(inputColStats != NULL)
                  inputHistFound = TRUE;
              }
          }
      }

    if(!inputHistFound)
    {
      // if the UDF didn't specify a UEC and we have no histogram, use a CQD
      if (colUec < 1)
        colUec = udfCard.getValue() * 
          ActiveSchemaDB()->getDefaults().getAsDouble(USTAT_MODIFY_DEFAULT_UEC);

      // create a fake histogram with the specified cardinality and UEC
      udfColStatDescList.addColStatDescForVirtualCol(colUec,
                                                     udfCard, 
                                                     udfOutputCol,
                                                     udfOutputCol,
                                                     udfOutputCol,
                                                     NULL,
                                                     TRUE);
    }
    else
    {
      ColStatDescSharedPtr outputColStatDescSharedPtr(
        new(HISTHEAP) ColStatDesc(inputColStats,udfOutputCol, HISTHEAP),HISTHEAP);

      if (colUec >= 1)
        {
          // We have information from two sources: The UDF specified a column UEC
          // and we also have a histogram from the corresponding child column.
          // Try to consolidate these two pieces of information by scaling the
          // UECs in the histogram to match those specified by the UDF.
          outputColStatDescSharedPtr->getColStats()->setRowsAndUec(udfCard, colUec);
        }

      udfColStatDescList.insert(outputColStatDescSharedPtr);
    }
  }

  const ValueIdSet & inputValues = getGroupAttr()->getCharacteristicInputs();
  ValueIdSet outerReferences;
  CollIndex outerRefCount;
  ValueIdSet predsEvaluatedForStats(getSelectionPred());

  if (inputValues.entries() > 0)
    inputValues.getOuterReferences(outerReferences);
  outerRefCount = outerReferences.entries();

  if (!udfSpecifiedCard)
    // The UDF writer did not specify a cardinality, use our conventional
    // methods to estimate the effect of predicates evaluated in the
    // UDF. Note that if the UDF did specify a result cardinality, we
    // assume that it is the cardinality after evaluating those predicates.
    predsEvaluatedForStats += predsEvaluatedByUDF_;
  
  // synchronize output colum rowcounts
  udfColStatDescList.synchronizeStats(udfCard,udfColStatDescList.entries());
  
  // apply predicates
  udfCard = udfColStatDescList.estimateCardinality(
         udfCard,                /*in*/
         predsEvaluatedForStats, /*in*/
         outerReferences,        /*in*/
         NULL,                   /* no join */
         NULL,                   /* for selectivity hint, which can only be given for scan */
         NULL,                   /* for cardinality hint, which can only be given for scan */
         outerRefCount,          /*in/out*/
         myEstProps->unresolvedPreds(), /*in/out*/
         INNER_JOIN_MERGE,       /*in*/
         ITM_FIRST_ITEM_OP,      /*no-op*/
         NULL);                  /* no max. cardinality */

  // This is the number of rows we think we will return
  myEstProps->setResultCardinality(udfCard);

  // From the given ColStatDescList, populate columnStats with column
  // descriptors that are useful based on the characteristic outputs
  // for the group. 
  myEstProps->pickOutputs(udfColStatDescList,
                          inputEstLogProp, 
                          getGroupAttr()->getCharacteristicOutputs(),
                          predsEvaluatedForStats);

  // attach histograms to group attributes
  getGroupAttr()->addInputOutputLogProp (inputEstLogProp, myEstProps);
};

  ///////////////////////////////////////////////////////////

NABoolean TableMappingUDF::pilotAnalysis(QueryAnalysis* qa)
{
  return RelExpr::pilotAnalysis(qa);
};
void TableMappingUDF::jbbAnalysis(QueryAnalysis* qa)
{
  RelExpr::jbbAnalysis(qa);
};
void TableMappingUDF::jbbJoinDependencyAnalysis(ValueIdSet & predsWithDependencies)
{
  RelExpr::jbbJoinDependencyAnalysis(predsWithDependencies);
};
void TableMappingUDF::predAnalysis(QueryAnalysis* qa)
{
  RelExpr::predAnalysis(qa);
};
RelExpr* TableMappingUDF::convertToMultiJoinSubtree(QueryAnalysis* qa)
{
  return RelExpr::convertToMultiJoinSubtree(qa);
};
RelExpr* TableMappingUDF::expandMultiJoinSubtree()
{
 return RelExpr::expandMultiJoinSubtree();
};
void TableMappingUDF::analyzeInitialPlan()
{
  RelExpr::analyzeInitialPlan();
};

  ///////////////////////////////////////////////////////////

  // ---------------------------------------------------------------------
  // comparison, hash, and copy methods
  // ---------------------------------------------------------------------

SimpleHashValue TableMappingUDF::hash()
{
  return RelExpr::hash(); 
}; // from ExprNode
HashValue TableMappingUDF::topHash()
{
  HashValue result = RelRoutine::topHash();
  for (Int32 i=0; i<getArity(); i++)
  {
    result ^= (childInfo_[i]->getPartitionBy());
    result ^= (childInfo_[i]->getOrderBy());
  }
  return result;
};
NABoolean TableMappingUDF::patternMatch(const RelExpr & other) const
{
  // will need additional code for CQS
  return (RelExpr::patternMatch(other) &&
    getArity() == other.getArity());
};
NABoolean TableMappingUDF::duplicateMatch(const RelExpr & other) const
{
  if (!TableValuedFunction::duplicateMatch(other))
    return FALSE;

  TableMappingUDF &o = (TableMappingUDF &) other;

  for (Int32 i=0; i<getArity(); i++)
  {
    if (NOT ((childInfo_[i]->getPartitionBy()) == (o.childInfo_[i]->getPartitionBy()))) 
      return FALSE;
    if (NOT ((childInfo_[i]->getOrderBy()) == (o.childInfo_[i]->getOrderBy()))) 
      return FALSE;
  }

  return TRUE;
};


NABoolean TableMappingUDF::isLogical() const { return TRUE; }
NABoolean TableMappingUDF::isPhysical() const { return FALSE; }

void TableMappingUDF::checkAndCoerceScalarInputParamTypes(BindWA* bindWA)
{
  if (getProcInputParamsVids().entries() != getScalarInputParamCount())
  {
    *CmpCommon::diags() << DgSqlCode(-4452)
                        << DgString0(getUserTableName().getCorrNameAsString())
                        << DgInt0((Lng32) getScalarInputParamCount())
                        << DgInt1((Lng32) getProcInputParamsVids().entries());
    
    bindWA->setErrStatus();
    return ;
  }

  for(Int32 i =0; i < getScalarInputParamCount(); i++)
  {
    const NAType &paramType = *(getScalarInputParams()[i]->getType());
    ValueId inputTypeId = getProcInputParamsVids()[i];

    // If function argument is character type, get detailed info.
    if (inputTypeId.getType().getTypeQualifier() == NA_CHARACTER_TYPE)
    {
      const CharType* stringLiteral = (CharType*)&(inputTypeId.getType());

      if(CmpCommon::wantCharSetInference())
      {
	const CharType* desiredType =
	CharType::findPushDownCharType(((CharType&)paramType).getCharSet(),
								stringLiteral, 0);
	if ( desiredType )
	inputTypeId.coerceType((NAType&)*desiredType, NA_CHARACTER_TYPE);
      }
    }
    // Get final type of function argument.
    const NAType &inputType = inputTypeId.getType();


    // Do type checking,
    // If it is not a compatible type report an error
    if (!( NA_UNKNOWN_TYPE == inputType.getTypeQualifier() ||
	   paramType.isCompatible(inputType) ||
	   inputTypeId.getItemExpr()->getOperatorType() == ITM_DYN_PARAM))
    {
      // Error, data types dont match
      // Create error for user-defined function.
      *CmpCommon::diags() << DgSqlCode(-4455)
                          << DgInt0((Lng32) i+1)
                          << DgString0(getUserTableName().getCorrNameAsString())
                          << DgString1(inputType.getTypeSQLname(TRUE))
                          << DgString2(paramType.getTypeSQLname(TRUE));

      bindWA->setErrStatus();
      return;
    } // if NOT isCompatible

    if ( ! ( paramType == inputType) )
    {
      // Create a Cast node to cast the argument from the function call
      // to the type specified by the metadata (if the two are compatible.)
      Cast *castExpr = new (bindWA->wHeap()) 
	      Cast(inputTypeId.getItemExpr(), &paramType, ITM_CAST, TRUE);
      ItemExpr *boundCast = castExpr->bindNode(bindWA);
      if (bindWA->errStatus()) return;

      // Add to input vid list.
      getProcInputParamsVids().removeAt(i);
      getProcInputParamsVids().insertAt(i,boundCast->getValueId());
    } 
  }
}

void TableMappingUDF::createOutputVids(BindWA* bindWA)
{

  // RETDesc has already been allocated
  RETDesc *resultTable = getRETDesc();
  if (!resultTable)
  {
    bindWA->setErrStatus();
    return;
  }
  for(Int32 i =0; i < getOutputParamCount(); i++)
  {
    NAColumn &naColumn = *(getOutputParams()[i]);
    const NAType &paramType = *(naColumn.getType());
    // use a NamedTypeToItem, so EXPLAIN and other
    // tools show a name instead of just the type
    NamedTypeToItem *paramTypeItem =
      new (bindWA->wHeap()) NamedTypeToItem(
           naColumn.getColName().data(),
           naColumn.mutateType(),
           bindWA->wHeap());
    ItemExpr *outputExprToBind = NULL;
    outputExprToBind = paramTypeItem->bindNode (bindWA);
    if ( bindWA->errStatus()) return;

    // Fill the ValueIdList for the output params
    addProcOutputParamsVid(outputExprToBind->getValueId());

    const NAString &formalParamName = naColumn.getColName();
    const NAString *colParamName = &formalParamName;
    ColRefName *columnName = 
        new (bindWA->wHeap())
            ColRefName(*colParamName, bindWA->wHeap());
    resultTable->addColumn(bindWA, *columnName, outputExprToBind->getValueId());
  }
  return ;
}
	
NARoutine * TableMappingUDF::getRoutineMetadata(
     QualifiedName &routineName,
     CorrName &tmfuncName,
     BindWA *bindWA)
{
  NARoutine *result = NULL;
  CmpSeabaseDDL cmpSBD((NAHeap *)bindWA->wHeap());

  TrafDesc *tmudfMetadata =
    cmpSBD.getSeabaseRoutineDesc(
         routineName.getCatalogName(),
         routineName.getSchemaName(),
         routineName.getObjectName());

  // IS req 5: If function name not found, output binder error.
  if (NULL == tmudfMetadata)
  {
    *CmpCommon::diags() << DgSqlCode(-4450)
			<< DgString0(tmfuncName.getQualifiedNameAsString());
    bindWA->setErrStatus();
    return NULL;
  }

  ComRoutineType udfType ;

  udfType = tmudfMetadata->routineDesc()->UDRType ;

  // IS req 6: Check ROUTINE_TYPE column of ROUTINES table.
  // Emit error if invalid type.
  if (udfType != COM_TABLE_UDF_TYPE)
  {
    *CmpCommon::diags() << DgSqlCode(-4457)
			<< DgString0(tmfuncName.getQualifiedNameAsString())
			<< DgString1("Only table-valued functions are supported here");
    bindWA->setErrStatus();
    return NULL;
  } 

  // IS req 3, 7.3. Instantiate NARoutine object.  
  // NARoutine data members will be assigned from udfMetadata.
  Int32 errors=0;
  result = new (bindWA->wHeap())
    NARoutine(tmfuncName.getQualifiedNameObj(),
	      tmudfMetadata, 
	      bindWA,
	      errors,
	      bindWA->wHeap());
  if ( NULL == result || errors != 0)
  {
    bindWA->setErrStatus();
    return NULL;
  }

  return result;
}



// -----------------------------------------------------------------------
// methods for class PredefinedTableMappingFunction
// -----------------------------------------------------------------------

PredefinedTableMappingFunction::PredefinedTableMappingFunction(
       int arity,
       const CorrName &name,
       ItemExpr *params,
       OperatorTypeEnum otype,
       CollHeap *oHeap) :
     TableMappingUDF(name, params, arity, otype, oHeap)
{}

PredefinedTableMappingFunction::~PredefinedTableMappingFunction()
{}

// static method to find out whether a given name is a
// built-in table-mapping function - returns operator type
// of predefined function if so, REL_ANY_TABLE_MAPPING_UDF otherwise
OperatorTypeEnum PredefinedTableMappingFunction::nameIsAPredefinedTMF(const CorrName &name)
{
  // Predefined functions don't reside in a schema, they are referenced with an unqualified name
  const QualifiedName &qualName = name.getQualifiedNameObj();
  const NAString &funcName = qualName.getObjectName();

  if (! qualName.getSchemaName().isNull())
    return REL_ANY_TABLE_MAPPING_UDF;

  if (funcName == "EVENT_LOG_READER")
    return REL_TABLE_MAPPING_BUILTIN_LOG_READER;
  else if (funcName == "TIMESERIES")
    return REL_TABLE_MAPPING_BUILTIN_TIMESERIES;
  else if (funcName == "SERIES")
    return REL_TABLE_MAPPING_BUILTIN_SERIES;
  else if (funcName == "JDBC")
    return REL_TABLE_MAPPING_BUILTIN_JDBC;
  else
    // none of the built-in names matched, so it must be a UDF
    return REL_ANY_TABLE_MAPPING_UDF;
}

const NAString PredefinedTableMappingFunction::getText() const
{
  switch (getOperatorType())
    {
    case REL_TABLE_MAPPING_BUILTIN_LOG_READER:
      return "event_log_reader";
    case REL_TABLE_MAPPING_BUILTIN_TIMESERIES:
      return "timeseries";
    case REL_TABLE_MAPPING_BUILTIN_SERIES:
      return "series";
    case REL_TABLE_MAPPING_BUILTIN_JDBC:
      return "jdbc_udf";

    default:
      CMPASSERT(0);
      return "predefined_tmf_with_invalid_operator_type";
    }
}

PredefinedTableMappingFunction * PredefinedTableMappingFunction::castToPredefinedTableMappingFunction()
{
  return this;
}

// a virtual function used to copy most of a Node
RelExpr * PredefinedTableMappingFunction::copyTopNode(RelExpr *derivedNode,
                                                      CollHeap* outHeap)
{
  RelExpr *result;

  if (derivedNode == NULL)
    result = new(outHeap) PredefinedTableMappingFunction(
         getArity(),
         getUserTableName(),
         NULL, // params get copied by parent classes
         getOperatorType(),
         outHeap);
  else
    result = derivedNode;

  return TableMappingUDF::copyTopNode(derivedNode, outHeap);
}

NARoutine * PredefinedTableMappingFunction::getRoutineMetadata(
     QualifiedName &routineName,
     CorrName &tmfuncName,
     BindWA *bindWA)
{
  NARoutine *result = NULL;
  ComRoutineLanguage lang = COM_LANGUAGE_CPP;
  ComRoutineParamStyle paramStyle = COM_STYLE_CPP_OBJ;
  const char *externalName = NULL;
  // By default, predefined UDRs share a DLL.
  const char *libraryFileName = "libudr_predef.so";
  NAString libraryPath;

  // the libraries for predefined UDRs are in the regular
  // library directory $TRAF_HOME/export/lib${SQ_MBTYPE}
  libraryPath += getenv("TRAF_HOME");
  libraryPath += "/export/lib";

  switch (getOperatorType())
    {
    case REL_TABLE_MAPPING_BUILTIN_LOG_READER:
      externalName = "TRAF_CPP_EVENT_LOG_READER";
      libraryPath += getenv("SQ_MBTYPE");
      break;

    case REL_TABLE_MAPPING_BUILTIN_SERIES:
      externalName = "SERIES";
      libraryPath += getenv("SQ_MBTYPE");
      break;

    case REL_TABLE_MAPPING_BUILTIN_TIMESERIES:
      externalName = "TRAF_CPP_TIMESERIES";
      libraryPath += getenv("SQ_MBTYPE");
      break;

    case REL_TABLE_MAPPING_BUILTIN_JDBC:
      lang = COM_LANGUAGE_JAVA;
      paramStyle = COM_STYLE_JAVA_OBJ;
      externalName = "org.trafodion.sql.udr.predef.JDBCUDR";
      libraryPath += "/trafodion-sql-";
      libraryPath += getenv("TRAFODION_VER");
      libraryPath += ".jar";
      break;

    default:
      *CmpCommon::diags() << DgSqlCode(-4457)
                          << DgString0(routineName.getQualifiedNameAsString())
                          << DgString1("Failed to get metadata for predefined UDF");
      bindWA->setErrStatus();
      return NULL;
    }
 
  // Produce a very simple NARoutine, most of the
  // error checking and determination of output
  // columns is done by the compiler interface of
  // this predefined table mapping function.

  result = new(bindWA->wHeap()) NARoutine(routineName,
                                          bindWA->wHeap());
  result->setExternalName(externalName);
  result->setLanguage(lang);
  result->setRoutineType(COM_TABLE_UDF_TYPE);
  result->setParamStyle(paramStyle);
  result->setFile(libraryFileName);
  result->setExternalPath(libraryPath);

  return result;
}


// -----------------------------------------------------------------------
// methods for class PhysicalTableMappingUDF
// -----------------------------------------------------------------------
double PhysicalTableMappingUDF::getEstimatedRunTimeMemoryUsage(Generator *generator, ComTdb * tdb) {return 0;}

RelExpr * PhysicalTableMappingUDF::copyTopNode(RelExpr *derivedNode,
                                               CollHeap* outHeap)
{
  PhysicalTableMappingUDF *result;

  if (derivedNode == NULL)
    result = new(outHeap) PhysicalTableMappingUDF(getArity(), outHeap);
  else
    result = (PhysicalTableMappingUDF *) derivedNode;

  result->planInfo_ = planInfo_;

  return TableMappingUDF::copyTopNode(result, outHeap);
}

//! PhysicalTableMappingUDF::getText method
const NAString PhysicalTableMappingUDF::getText() const
{
	return TableMappingUDF::getText();
}

// -----------------------------------------------------------------------
// methods for class BuiltinTableValuedFunction
// -----------------------------------------------------------------------

//! BuiltinTableValuedFunction::~BuiltinTableValuedFunction Destructor 
BuiltinTableValuedFunction::~BuiltinTableValuedFunction()
{
}

//! BuiltinTableValuedFunction::getText method 
const NAString BuiltinTableValuedFunction::getText() const
{
  return "BuiltinTableValuedFunction";
}

// -----------------------------------------------------------------------
// methods for class TableValuedUDF
// -----------------------------------------------------------------------

//! TableValuedUDF::~TableValuedUDF Destructor 
TableValuedUDF::~TableValuedUDF()
{
}



//! TableValuedUDF::copyTopNode method 
RelExpr * TableValuedUDF::copyTopNode(RelExpr *derivedNode,
                                      CollHeap* outHeap)
{
   TableValuedUDF      *result;

   if (derivedNode == NULL)
   {
     result  = new (outHeap) TableValuedUDF(NULL,
                               getOperatorType(),
                               outHeap);
   }
   else
     result = (TableValuedUDF *) derivedNode;


   return TableValuedFunction::copyTopNode(result, outHeap);

}

//! TableValuedUDF::getText method 
const NAString TableValuedUDF::getText() const
{
  return "TableValuedUDF";
}



// -----------------------------------------------------------------------
// methods for class IsolatedNonTableUDR
// -----------------------------------------------------------------------

//! IsolatedNonTableUDR::~IsolatedNonTableUDR Destructor 
IsolatedNonTableUDR::~IsolatedNonTableUDR()
{
}

//! IsolatedNonTableUDR::getText method 
const NAString IsolatedNonTableUDR::getText() const
{
  return "IsolatedNonTableUDR";
}

//! IsolatedNonTableUDR::copyTopNode method 
RelExpr *IsolatedNonTableUDR::copyTopNode(RelExpr *derivedNode, CollHeap *outHeap)
{
  IsolatedNonTableUDR *result;
  if (derivedNode == NULL)
    result = new (outHeap) IsolatedNonTableUDR(getRoutineName(), outHeap);
  else
    result = (IsolatedNonTableUDR *) derivedNode;

  result->neededValueIds_ = neededValueIds_;

  return RelRoutine::copyTopNode(result, outHeap);
}

// -----------------------------------------------------------------------
// methods for class IsolatedScalarUDF
// -----------------------------------------------------------------------

//! IsolatedScalarUDF::~IsolatedScalarUDF Destructor 
IsolatedScalarUDF::~IsolatedScalarUDF()
{
}

//! IsolatedScalarUDF::getText method 
const NAString IsolatedScalarUDF::getText() const
{

  NAString name("Isolated_Scalar_UDF ");
  name += getRoutineName().getQualifiedNameAsAnsiString();
  if (getRoutineDesc() && getRoutineDesc()->isUUDFRoutine() == TRUE &&
      getRoutineDesc()->getActionNARoutine() && 
      getRoutineDesc()->getActionNARoutine()->getActionName())
  {
     name += ":";
     name += *(getRoutineDesc()->getActionNARoutine()->getActionName());
  }
  return name;
}

//! IsolatedScalarUDF::copyTopMethod method 
RelExpr *IsolatedScalarUDF::copyTopNode(RelExpr *derivedNode, CollHeap *outHeap)
{
  IsolatedScalarUDF *result;

  if (derivedNode == NULL)
  {
    result = new (outHeap) IsolatedScalarUDF(getRoutineName(),
                                       outHeap);
  }
  else
  {
    result = (IsolatedScalarUDF *) derivedNode;
  }


  return super::copyTopNode(result, outHeap);
}

//! IsolatedScalarUDF::addLocalExpr method
void IsolatedScalarUDF::addLocalExpr(LIST(ExprNode *) &xlist,
                                     LIST(NAString) &llist) const
{

  RelRoutine::addLocalExpr(xlist,llist);
}

//! IsolatedScalarUDF::getPotentialOutputValues method 
void IsolatedScalarUDF::getPotentialOutputValues(ValueIdSet &vs) const
{
  vs.clear();
  vs.insertList(getProcOutParams());
}


// -----------------------------------------------------------------------
// methods for class PhysicalIsolatedScalarUDF
// -----------------------------------------------------------------------
//! PhysicalIsolatedScalarUDF::PhysicalIsolatedScalarUDF Constructor 
PhysicalIsolatedScalarUDF::PhysicalIsolatedScalarUDF(CollHeap *heap)
  : IsolatedScalarUDF(NULL, heap)
{
}

// -----------------------------------------------------------------------
// methods for class ExplainFunc
// -----------------------------------------------------------------------

//! ExplainFunc::~ExplainFunc Destructor 
ExplainFunc::~ExplainFunc()
{
}

//! ExplainFunc::copyTopNode method 
RelExpr * ExplainFunc::copyTopNode(RelExpr *derivedNode, CollHeap* outHeap)
{
  ExplainFunc *result;

  if (derivedNode == NULL)
    result = new (outHeap) ExplainFunc(NULL,outHeap);
  else
    result = (ExplainFunc *) derivedNode;

  return BuiltinTableValuedFunction::copyTopNode(result, outHeap);
}


//! ExplainFunc::getText method 
const NAString ExplainFunc::getText() const
{
  return "explain";
}

// -----------------------------------------------------------------------
// methods for class HiveMDaccessFunc
// -----------------------------------------------------------------------

HiveMDaccessFunc::HiveMDaccessFunc(NAString *mdt,
                                   NAString* schName,
                                   NAString* objName,
                                   CollHeap *oHeap)
  : BuiltinTableValuedFunction(NULL,REL_HIVEMD_ACCESS,oHeap)
{
  if (mdt)
    mdType_ = *mdt;
  if (schName)
    schemaName_ = *schName;
  if (objName)
    objectName_ = *objName;
}

//! HiveMDaccessFunc::~HiveMDaccessFunc Destructor 
HiveMDaccessFunc::~HiveMDaccessFunc()
{
}

//! HiveMDaccessFunc::copyTopNode method 
RelExpr * HiveMDaccessFunc::copyTopNode(RelExpr *derivedNode, CollHeap* outHeap)
{
  HiveMDaccessFunc *result;

  if (derivedNode == NULL)
    result = new (outHeap) HiveMDaccessFunc(NULL,NULL,NULL,outHeap);
  else
    result = (HiveMDaccessFunc *) derivedNode;

  result->mdType_ = mdType_;
  result->schemaName_ = schemaName_;
  result->objectName_ = objectName_;

  return BuiltinTableValuedFunction::copyTopNode(result, outHeap);
}

RelExpr *HiveMDaccessFunc::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
    {
      bindWA->getCurrentScope()->setRETDesc(getRETDesc());
      return this;
    }

  RelExpr * re = BuiltinTableValuedFunction::bindNode(bindWA);
  if (bindWA->errStatus())
    return this;

  return re;
}


//! HiveMDaccessFunc::getText method 
const NAString HiveMDaccessFunc::getText() const
{
  return "hiveMD";
}

void
HiveMDaccessFunc::synthEstLogProp(const EstLogPropSharedPtr& inputEstLogProp)
{
  if (getGroupAttr()->isPropSynthesized(inputEstLogProp))
    return;

  // Create a new Output Log Property with cardinality of 10 for now.
  EstLogPropSharedPtr myEstProps(new (HISTHEAP) EstLogProp(10));

  getGroupAttr()->addInputOutputLogProp(inputEstLogProp, myEstProps);

} // HiveMDaccessFunc::synthEstLogProp

void
HiveMDaccessFunc::synthLogProp(NormWA * normWAPtr)
{
  // Check to see whether this GA has already been associated
  // with a logExpr for synthesis.  If so, no need to resynthesize
  //  for this equivalent log. expression.
  if (getGroupAttr()->existsLogExprForSynthesis()) return;

  RelExpr::synthLogProp(normWAPtr);

} // HiveMDaccessFunc::synthLogProp()

//<pb>
//==============================================================================
//  Synthesize physical properties for HiveMD operator's current plan
// extracted from a spcified context.
//
// Input:
//  myContext  -- specified context containing this operator's current plan.
//
//  planNumber -- plan's number within the plan workspace.  Used optionally for
//                 synthesizing partitioning functions but unused in this
//                 derived version of synthPhysicalProperty().
//
// Output:
//  none
//
// Return:
//  Pointer to this operator's synthesized physical properties.
//
//==============================================================================
PhysicalProperty*
HiveMDaccessFunc::synthPhysicalProperty(const Context* myContext,
                                        const Lng32     planNumber,
                                        PlanWorkSpace  *pws)
{

  //----------------------------------------------------------
  // Create a node map with a single, active, wild-card entry.
  //----------------------------------------------------------
  NodeMap* myNodeMap = new(CmpCommon::statementHeap())
                        NodeMap(CmpCommon::statementHeap(),
                                1,
                                NodeMapEntry::ACTIVE);

  //------------------------------------------------------------
  // Synthesize a partitioning function with a single partition.
  //------------------------------------------------------------
  PartitioningFunction* myPartFunc =
    new(CmpCommon::statementHeap())
    SinglePartitionPartitioningFunction(myNodeMap);

  PhysicalProperty * sppForMe =
    new(CmpCommon::statementHeap())
    PhysicalProperty(myPartFunc,
                     EXECUTE_IN_MASTER,
                     SOURCE_VIRTUAL_TABLE);

  // remove anything that's not covered by the group attributes
  sppForMe->enforceCoverageByGroupAttributes (getGroupAttr()) ;

  return sppForMe ;

} // HiveMDaccessFunc::synthPhysicalProperty()


// -----------------------------------------------------------------------
// methods for class StatisticsFunc
// -----------------------------------------------------------------------
//! StatisticsFunc::copyTopNode method 
RelExpr * StatisticsFunc::copyTopNode(RelExpr *derivedNode, CollHeap* outHeap)
{
  StatisticsFunc *result;

  if (derivedNode == NULL)
    result = new (outHeap) StatisticsFunc(NULL,outHeap);
  else
    result = (StatisticsFunc *) derivedNode;

  return BuiltinTableValuedFunction::copyTopNode(result, outHeap);
}

//! StatisticsFunc::getText method 
const NAString StatisticsFunc::getText() const
{
  return "statistics";
}

// -----------------------------------------------------------------------
// methods for class ProxyFunc
// -----------------------------------------------------------------------

//! ProxyFunc::ProxyFunc Constructor 
ProxyFunc::ProxyFunc(OperatorTypeEnum otype,
                     ElemDDLNode *columnsFromParser,
                     CollHeap *heap)
  : BuiltinTableValuedFunction(NULL, otype, heap),
    columnListFromParser_(columnsFromParser),
    virtualTableName_("", heap)
{
}

//! ProxyFunc::ProxyFunc Copy Constructor 
ProxyFunc::ProxyFunc(const ProxyFunc &other, CollHeap *h)
  : BuiltinTableValuedFunction(other, h),
    columnListFromParser_(other.columnListFromParser_),
    virtualTableName_(other.virtualTableName_, h)
{
}


//! ProxyFunc::~ProxyFunc Destructor 
ProxyFunc::~ProxyFunc()
{
}

//! ProxyFunc::getVirtualTableName method 
const char *ProxyFunc::getVirtualTableName()
{
  return virtualTableName_.data();
}

//! ProxyFunc::getNumColumns method 
ComUInt32 ProxyFunc::getNumColumns() const
{
  ComUInt32 result = 0;
  if (columnListFromParser_)
    result = columnListFromParser_->entries();
  return result;
}

//! ProxyFunc::getColumn method 
const ElemProxyColDef &ProxyFunc::getColumn(ComUInt32 i) const
{
  CMPASSERT(i < getNumColumns());
  ElemProxyColDef *result =
    (*columnListFromParser_)[i]->castToElemProxyColDef();
  CMPASSERT(result);
  return *result;
}

//! ProxyFunc::getColumnType method 
const NAType &ProxyFunc::getColumnType(ComUInt32 i) const
{
  const ElemProxyColDef &c = getColumn(i);
  const NAType *t = c.getColumnDataType();
  CMPASSERT(t);
  return *t;
}

//! ProxyFunc::getColumnNameForDescriptor method 
const NAString *ProxyFunc::getColumnNameForDescriptor(ComUInt32 i) const
{
  const ElemProxyColDef &c = getColumn(i);
  const NAString &s = c.getColumnName();
  return &s;
}

//! ProxyFunc::getTableNameForDescriptor method 
const QualifiedName *ProxyFunc::getTableNameForDescriptor(ComUInt32 i) const
{
  const ElemProxyColDef &c = getColumn(i);
  const QualifiedName *qn = c.getTableName();
  return qn;
}

//! ProxyFunc::getColumnHeading method 
const NAString *ProxyFunc::getColumnHeading(ComUInt32 i) const
{
  const ElemProxyColDef &c = getColumn(i);
  if (c.getIsHeadingSpecified())
  {
    const NAString &s = c.getHeading();
    return &s;
  }
  return NULL;
}

//! ProxyFunc::populateColumnDesc method 
void ProxyFunc::populateColumnDesc(char *tableNam,
                                   TrafDesc *&colDescs,
                                   Lng32 &reclen) const
{
    ElemDDLColDefArray colArray;
    ComObjectName tableName(tableNam);
    ComUInt32 numCols = getNumColumns();

  
    for (ComUInt32 colNum = 0; colNum < numCols; colNum++)
    {
      ElemProxyColDef *result =
        (*columnListFromParser_)[colNum]->castToElemProxyColDef();

      colArray.insert(result);
    }

   CmpSeabaseDDL cmpSBD(CmpCommon::statementHeap());

   ComTdbVirtTableColumnInfo * colInfoArray = (ComTdbVirtTableColumnInfo*)
                      new(STMTHEAP) char[numCols * sizeof(ComTdbVirtTableColumnInfo)];

   cmpSBD.buildColInfoArray(COM_USER_DEFINED_ROUTINE_OBJECT,
                            FALSE,
                            &colArray, 
                            colInfoArray, 
                            FALSE, FALSE, NULL, NULL, NULL, NULL,
                            CmpCommon::statementHeap());

   for (size_t colNum = 0; colNum < colArray.entries(); colNum++)
   {
     char buf[128];
     str_sprintf(buf, "C%d", (Int32) colNum + 1);
     const char *colName = &buf[0];
     char * col_name = new(STMTHEAP) char[strlen(colName) + 1];
     strcpy(col_name, (char*)colName);
     colInfoArray[colNum].colName = col_name;
   }

   colDescs = cmpSBD.convertVirtTableColumnInfoArrayToDescStructs(&tableName,
                                                                  colInfoArray,
                                                                  numCols) ;

  // calculate the record length 
  TrafDesc *tempDescs = colDescs;
  for (ComUInt32 colNum = 0; colNum < numCols; colNum++)
  { 
    NAType *naType = getColumn(colNum).getColumnDataType();
    Int32 fsType = naType->getFSDatatype();

    if (tempDescs->columnsDesc()->isNullable())
      reclen += SQL_NULL_HDR_SIZE;
    if (DFS2REC::isSQLVarChar(fsType))
      reclen += SQL_VARCHAR_HDR_SIZE;

    reclen += tempDescs->columnsDesc()->length;
    tempDescs = tempDescs->next;
  }
}


//! ProxyFunc::copyTopNode method 
RelExpr *ProxyFunc::copyTopNode(RelExpr *derivedNode, CollHeap *outHeap)
{
  ProxyFunc *result;
  if (derivedNode == NULL)
    result = new (outHeap) ProxyFunc(*this);
  else
    result = (ProxyFunc *) derivedNode;
 
    // make a shallow copy of the parse tree struct. This was originally 
    // instantiated as a shallow copy from the parser too.
    // assumption is that is is read only and that it does not get freed...
  result->columnListFromParser_ = columnListFromParser_;
  result->virtualTableName_ = virtualTableName_;

  return TableValuedFunction::copyTopNode(result, outHeap);
}

//! ProxyFunc::topHash method 
HashValue ProxyFunc::topHash()
{
  HashValue result = BuiltinTableValuedFunction::topHash();
  result ^= columnListFromParser_;
  result ^= virtualTableName_.hash();
  return result;
}

//! ProxyFunc::duplicateMatch method 
NABoolean ProxyFunc::duplicateMatch(const RelExpr & other) const
{
  if (!BuiltinTableValuedFunction::duplicateMatch(other))
    return FALSE;
  ProxyFunc &o = (ProxyFunc &) other;
  if (columnListFromParser_ != o.columnListFromParser_)
    return FALSE;
  if (virtualTableName_ != o.virtualTableName_)
    return FALSE;
  return TRUE;
}

// -----------------------------------------------------------------------
// methods for class SPProxyFunc
// -----------------------------------------------------------------------
//! SPProxyFunc::SPProxyFunc Constructor 
SPProxyFunc::SPProxyFunc(ElemDDLNode *columnsFromParser,
                         ItemExprList *optionalStrings,
                         CollHeap *heap)
  : ProxyFunc(REL_SP_PROXY, columnsFromParser, heap),
    optionalStrings_(optionalStrings)
{
}

//! SPProxyFunc::SPProxyFunc Constructor 
SPProxyFunc::SPProxyFunc(CollHeap *heap)
  : ProxyFunc(REL_SP_PROXY, NULL, heap),
    optionalStrings_(NULL)
{
}

//! SPProxyFunc::SPProxyFunc Copy Constructor 
SPProxyFunc::SPProxyFunc(const SPProxyFunc &other, CollHeap *h)
  : ProxyFunc(other,h),
    optionalStrings_(other.optionalStrings_)
{
}

//! SPProxyFunc::~SPProxyFunc Destructor 
SPProxyFunc::~SPProxyFunc()
{
}

//! SPProxyFunc::getNumOptionalStrings method 
ComUInt32 SPProxyFunc::getNumOptionalStrings() const
{
  ComUInt32 result = 0;
  if (optionalStrings_)
    result = optionalStrings_->entries();
  return result;
}

//! SPProxyFunc::getOptionalString method 
const char *SPProxyFunc::getOptionalString(ComUInt32 i) const
{
  const char *result = NULL;
  const ItemExpr *e = NULL;
  const ConstValue *cv = NULL;
  const NAString *s = NULL;
  NABoolean dummyNegate = FALSE;

  if (i < getNumOptionalStrings())
    e = (*optionalStrings_)[i];

  if (e)
    cv = ((ItemExpr *) e)->castToConstValue(dummyNegate);

  if (cv)
    s = cv->getRawText();

  if (s)
    result = s->data();

  return result;
}

//! SPProxyFunc::copyTopNode method 
RelExpr *SPProxyFunc::copyTopNode(RelExpr *derivedNode, CollHeap *outHeap)
{
  SPProxyFunc *result;
  if (derivedNode == NULL)
    result = new (outHeap) SPProxyFunc(*this);
  else
    result = (SPProxyFunc *) derivedNode;

  // Make a shallow copy of the pointer.
  result->optionalStrings_ = optionalStrings_;

  return ProxyFunc::copyTopNode(result, outHeap);
}

//! SPProxyFunc::getText method 
const NAString SPProxyFunc::getText() const
{
  return "sp_result_set";
}

//! SPProxyFunc::topHash method 
HashValue SPProxyFunc::topHash()
{
  HashValue result = ProxyFunc::topHash();
  result ^= optionalStrings_;
  return result;
}

//! SPProxyFunc::duplicateMatch method 
NABoolean SPProxyFunc::duplicateMatch(const RelExpr & other) const
{
  if (!ProxyFunc::duplicateMatch(other))
    return FALSE;
  SPProxyFunc &o = (SPProxyFunc &) other;
  if (optionalStrings_ != o.optionalStrings_)
    return FALSE;
  return TRUE;
}

// -----------------------------------------------------------------------
// methods for class CallSP
// -----------------------------------------------------------------------

// Raj P - 12/2000
//! CallSP::copyTopNode method 
// virtual copy constructor for the CallSP class
RelExpr *CallSP::copyTopNode(RelExpr *derivedNode, CollHeap *outHeap)
{
  CallSP *result;
  if (derivedNode == NULL)
    result = new (outHeap) CallSP(getRoutineName(), outHeap);
  else
    result = (CallSP *) derivedNode;

  result->duplicateVars_ = duplicateVars_;
  result->outDupVars_ = outDupVars_;
  result->hasUDF_ = hasUDF_;

  return super::copyTopNode(result, outHeap);
}


//! CallSP::getPotentialOutputValues method 
void CallSP::getPotentialOutputValues(ValueIdSet &vs) const
{
  vs.clear();
  vs.insertList(getProcOutputParamsVids());
}

//! CallSP::getText method 
const NAString CallSP::getText() const
{
  NAString result("call ", CmpCommon::statementHeap ());
  result += getRoutineName().getQualifiedNameAsString();
  if (nodeIsBound())
  {
    getProcAllParamsVids().unparse(result);
  }
  else
  {
    result += "(";
    if (getProcAllParamsTree() != NULL)
    {
      getProcAllParamsTree()->unparse(result);
    }
    result += ")";
  }
  return result;
}

//! CallSP::pushdownCoveredExpr method 
void CallSP::pushdownCoveredExpr(const ValueIdSet &outputExprOnOperator,
			    const ValueIdSet &newExternalInputs,
			    ValueIdSet &predicatesOnOperator,
			    const ValueIdSet *nonPredNonOutputExprOnOperator,
			    Lng32 childIndex
			   )
{

  // We use an emptySet for the outputs for the call to 
  // Relexpr::pushdowCoveredExpr because our child is a tuple with a
  // subquery in it and that subquery is an input to the Routine, so none
  // of the CallSPs output pertains to the child. 
  ValueIdSet emptySet;  

  RelExpr::pushdownCoveredExpr( emptySet,
				newExternalInputs,
				predicatesOnOperator,
				&getNeededValueIds());
}

// -----------------------------------------------------------------------
// methods for class ExtractSource
// -----------------------------------------------------------------------
//! ExtractSource::ExtractSource Constructor
ExtractSource::ExtractSource(ElemDDLNode *columnsFromParser,
                             NAString &espPhandle,
                             NAString &securityKey,
                             CollHeap *heap)
  : ProxyFunc(REL_EXTRACT_SOURCE, columnsFromParser, heap),
    espPhandle_(espPhandle, heap),
    securityKey_(securityKey, heap)
{
}

//! ExtractSource::ExtractSource Constructor
ExtractSource::ExtractSource(CollHeap *heap)
  : ProxyFunc(REL_EXTRACT_SOURCE, NULL, heap),
    espPhandle_("", heap),
    securityKey_("", heap)
{
}
//! ExtractSource::ExtractSource Copy Constructor
ExtractSource::ExtractSource(const ExtractSource &other, CollHeap *h)
  : ProxyFunc(other,h),
    espPhandle_(other.espPhandle_),
    securityKey_(other.securityKey_)
{
}


//! ExtractSource::~ExtractSource Destructor
ExtractSource::~ExtractSource()
{
}

//! ExtractSource::copyTopNode method
RelExpr *ExtractSource::copyTopNode(RelExpr *derivedNode, CollHeap *outHeap)
{
  ExtractSource *result;
  if (derivedNode == NULL)
    result = new (outHeap) ExtractSource(*this, outHeap);
  else
    result = (ExtractSource *) derivedNode;

  result->espPhandle_ = espPhandle_;
  result->securityKey_ = securityKey_;

  return ProxyFunc::copyTopNode(result, outHeap);
}

//! ExtractSource::getText method
const NAString ExtractSource::getText() const
{
  return "extract_source";
}

//! ExtractSource::topHash method
HashValue ExtractSource::topHash()
{
  HashValue result = ProxyFunc::topHash();
  result ^= espPhandle_.hash();
  result ^= securityKey_.hash();
  return result;
}

//! ExtractSource::duplicateMatch method
NABoolean ExtractSource::duplicateMatch(const RelExpr & other) const
{
  if (!ProxyFunc::duplicateMatch(other))
    return FALSE;
  ExtractSource &o = (ExtractSource &) other;
  if (espPhandle_ != o.espPhandle_)
    return FALSE;
  if (securityKey_ != o.securityKey_)
    return FALSE;
  return TRUE;
}
