/**********************************************************************
//
// @@@ 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:         UdfDllInteraction.cpp
* Description:  Methods for a udf RelExpr to interact with a dll
* Created:      3/01/10
* Language:     C++
*
*************************************************************************
*/

#include "UdfDllInteraction.h"
#include "NumericType.h"
#include "CharType.h"
#include "DatetimeType.h"
#include "MiscType.h"
#include "ItemLog.h"
#include "ItemOther.h"
#include "NARoutine.h"
#include "SchemaDB.h"
#include "GroupAttr.h"
#include "exp_attrs.h"
#include "LmError.h"
#include "ComUser.h"


// -----------------------------------------------------------------------
// methods for class TMUDFDllInteraction
// -----------------------------------------------------------------------

TMUDFDllInteraction::TMUDFDllInteraction() :
     cliInterface_(CmpCommon::statementHeap(),
                   0,
                   NULL, 
                   CmpCommon::context()->sqlSession()->getParentQid())
{
}

NABoolean TMUDFDllInteraction::describeParamsAndMaxOutputs(
                                TableMappingUDF * tmudfNode,
                                BindWA * bindWA)
{
  // convert the compiler structures into something we can pass
  // to the UDF writer, to describe input parameters and input tables
  char *constParamBuffer = NULL;
  int constParamBufferLen = 0;
  tmudr::UDRInvocationInfo *invocationInfo =
    TMUDFInternalSetup::createInvocationInfoFromRelExpr(tmudfNode,
                                                        constParamBuffer,
                                                        constParamBufferLen,
                                                        CmpCommon::diags());
  if (!invocationInfo)
    {
      bindWA->setErrStatus();
      return FALSE;
    }

  tmudfNode->setInvocationInfo(invocationInfo);
  tmudfNode->setConstParamBuffer(constParamBuffer,
                                 constParamBufferLen);

  // set up variables to serialize UDRInvocationInfo
  char iiBuf[20000];
  char *serializedUDRInvocationInfo = iiBuf;
  int iiLen;
  int iiAllocatedLen = sizeof(iiBuf);

  try
    {
      iiLen = invocationInfo->serializedLength();

      if (iiLen > iiAllocatedLen)
        serializedUDRInvocationInfo = new(CmpCommon::statementHeap()) char[iiLen];

      invocationInfo->serializeObj(serializedUDRInvocationInfo, iiLen);
    }
  catch (tmudr::UDRException e)
    {
      *CmpCommon::diags() << DgSqlCode(-LME_OBJECT_INTERFACE_ERROR)
                          << DgString0(invocationInfo->getUDRName().c_str())
                          << DgString1(tmudr::UDRInvocationInfo::callPhaseToString(
                                            tmudr::UDRInvocationInfo::GET_ROUTINE_CALL))
                          << DgString2("describeParams")
                          << DgString3(e.getMessage().data());
      bindWA->setErrStatus();
      return FALSE;
    }
  catch (...)
    {
      *CmpCommon::diags() << DgSqlCode(-LME_OBJECT_INTERFACE_ERROR)
                          << DgString0(invocationInfo->getUDRName().c_str())
                          << DgString1(tmudr::UDRInvocationInfo::callPhaseToString(
                                            tmudr::UDRInvocationInfo::GET_ROUTINE_CALL))
                          << DgString2("describeParams")
                          << DgString3("General exception");
      bindWA->setErrStatus();
      return FALSE;
    }

  // Get a routine handle from the CLI, this goes through the language
  // manager and may load a DLL or jar file if this is the first call
  // in this process for a given library.
  const NARoutine *routine = tmudfNode->getNARoutine();
  CliRoutineHandle routineHandle = NullCliRoutineHandle;
  const char *containerName = routine->getFile();

  if (routine->getParamStyle() != COM_STYLE_JAVA_OBJ &&
      routine->getParamStyle() != COM_STYLE_CPP_OBJ)
    {
      // other parameter styles are no longer supported.
      *CmpCommon::diags() << DgSqlCode(-3286);
      bindWA->setErrStatus();
      return FALSE;
    }

  Int32 cliRC = cliInterface_.getRoutine(
       serializedUDRInvocationInfo,
       iiLen,
       NULL, // no plan info at this stage
       0,
       routine->getLanguage(),
       routine->getParamStyle(),
       routine->getMethodName(),
       // for C/C++ the container that gets loaded is the library file
       // name, for Java it's the class name
       routine->getContainerName(),
       routine->getExternalPath(),
       routine->getLibrarySqlName().getExternalName(),
       &routineHandle,
       CmpCommon::diags());
  if (cliRC < 0)
    {
      bindWA->setErrStatus();
      return FALSE;
    }

  CMPASSERT(routineHandle != NullCliRoutineHandle);
  // register routine handle for later release when compilation is done
  CmpCommon::context()->addRoutineHandle(routineHandle);
  tmudfNode->setRoutineHandle(routineHandle);

  // call the UDR compiler interface
  if (!invokeRoutine(tmudr::UDRInvocationInfo::COMPILER_INITIAL_CALL,
                     tmudfNode))
    {
      bindWA->setErrStatus();
      return FALSE;
    }

  // copy the formal parameter list back into the RelExpr
  NAHeap *outHeap = CmpCommon::statementHeap();
  NAColumnArray * modifiedParameterArray =
    new(outHeap) NAColumnArray(outHeap);

  for (int p=0; p<invocationInfo->getFormalParameters().getNumColumns(); p++)
    {
      NAColumn *newParam = 
        TMUDFInternalSetup::createNAColumnFromColumnInfo(
             invocationInfo->getFormalParameters().getColumn(p),
             p,
             outHeap,
             CmpCommon::diags());
      if (newParam == NULL)
        {
          bindWA->setErrStatus();
          return FALSE;
        }
      modifiedParameterArray->insert(newParam);
    }

  tmudfNode->setScalarInputParams(modifiedParameterArray);

  // copy the output columns back into the RelExpr
  NAColumnArray * outColArray =
    TMUDFInternalSetup::createColumnArrayFromTableInfo(
         invocationInfo->out(),
         tmudfNode,
         outHeap,
         CmpCommon::diags());
  if (outColArray == NULL)
    {
      bindWA->setErrStatus();
      return FALSE;
    }
  if (outColArray->entries() == 0)
    {
      *(CmpCommon::diags()) << DgSqlCode(-11155);
      bindWA->setErrStatus();
      return FALSE;
    }

  tmudfNode->setOutputParams(outColArray);

  // copy the query partition by and order by back into childInfo
  for (int c=0; c<tmudfNode->getArity(); c++)
    {
      TableMappingUDFChildInfo *childInfo = tmudfNode->getChildInfo(c);
      const ValueIdList &childCols = childInfo->getOutputs();
      const tmudr::PartitionInfo &childPartInfo = invocationInfo->in(c).getQueryPartitioning();
      const tmudr::OrderInfo &childOrderInfo = invocationInfo->in(c).getQueryOrdering();
      TMUDFInputPartReq childPartType = NO_PARTITIONING; 
      ValueIdSet childPartKey;
      ValueIdList childOrderBy;

      switch (childPartInfo.getType())
        {
        case tmudr::PartitionInfo::ANY:
          childPartType = ANY_PARTITIONING;
          break;

        case tmudr::PartitionInfo::SERIAL:
          childPartType = NO_PARTITIONING;
          break;

        case tmudr::PartitionInfo::PARTITION:
          {
            childPartType = SPECIFIED_PARTITIONING;
            // convert column numbers back to ValueIds
            for (int p=0; p<childPartInfo.getNumEntries(); p++)
              {
                int colNum = childPartInfo.getColumnNum(p);

                if (colNum < childCols.entries() && colNum >= 0)
                  {
                    childPartKey += childCols[colNum];
                  }
                else
                  processReturnStatus(
                       tmudr::UDRException(
                            38900,
                            "Invalid child column number %d used in partition by key of child table %d with %d columns",
                            colNum, c, childCols.entries()),
                       tmudfNode);
                            
                            
              }
          }
          break;

        case tmudr::PartitionInfo::REPLICATE:
          childPartType = REPLICATE_PARTITIONING;
          break;

        default:
          processReturnStatus(
               tmudr::UDRException(
                    38900,
                    "Invalid partitioning type %d used in partition by key of child table %d",
                    static_cast<int>(childPartInfo.getType()), c),
               tmudfNode);
          break;
        }

      for (int oc=0; oc<childOrderInfo.getNumEntries(); oc++)
        {
          int colNum = childOrderInfo.getColumnNum(oc);

          if (colNum < childCols.entries() && colNum >= 0)
            {
              if (childOrderInfo.getOrderType(oc) == tmudr::OrderInfo::DESCENDING)
                {
                  ItemExpr *inv = new(CmpCommon::statementHeap())
                    InverseOrder(childCols[colNum].getItemExpr());
                  inv->synthTypeAndValueId();
                  childOrderBy.insert(inv->getValueId());
                }
              childOrderBy.insert(childCols[colNum]);
            }
          else
            processReturnStatus(
                 tmudr::UDRException(
                      38900,
                      "Invalid child column number %d used in order by key of child table %d with %d columns",
                      colNum, c, childCols.entries()),
                 tmudfNode);
        }

      // now transfer all this info into childInfo
      childInfo->setPartitionType(childPartType);
      childInfo->setPartitionBy(childPartKey);
      childInfo->setOrderBy(childOrderBy);
    }

  return TRUE;
}

NABoolean TMUDFDllInteraction::createOutputInputColumnMap(
     TableMappingUDF * tmudfNode,
     ValueIdMap &result)
{
  tmudr::UDRInvocationInfo * invocationInfo = tmudfNode->getInvocationInfo();
  tmudr::TableInfo & outputTableInfo = invocationInfo->out();
  int numOutputColumns = outputTableInfo.getNumColumns();

  for (int oc=0; oc<numOutputColumns; oc++)
    {
      const tmudr::ProvenanceInfo &p =
        outputTableInfo.getColumn(oc).getProvenance();

      if (p.isFromInputTable())
        {
          result.addMapEntry(
               tmudfNode->getProcOutputParamsVids()[oc],
               tmudfNode->getChildInfo(p.getInputTableNum())->
                             getOutputs()[p.getInputColumnNum()]);
        }
    }

  return TRUE;
}

NABoolean TMUDFDllInteraction::describeDataflow(
     TableMappingUDF * tmudfNode,        // in
     ValueIdSet &valuesRequiredByParent, // out: values the parent needs to
                                         //      require from its children
     ValueIdSet &selectionPreds,         // in:  predicates that could
                                         //      potentially be pushed down
                                         // out: predicates that need to be
                                         //      evaluated on the UDF result
     ValueIdSet &predsEvaluatedByUDF,    // out: predicates evaluated by the
                                         //      UDF (in user-written code)
     ValueIdSet &predsToPushDown)        // out: predicates to be pushed down
                                         //      to the children (expressed
                                         //      in terms of child value ids)
{
  tmudr::UDRInvocationInfo * invocationInfo = tmudfNode->getInvocationInfo();
  tmudr::TableInfo & outputTableInfo = invocationInfo->out();
  int numOutputColumns = outputTableInfo.getNumColumns();
  ValueIdList &udfOutputCols = tmudfNode->getProcOutputParamsVids();
  ValueIdSet udfOutputColSet(udfOutputCols);
  const ValueIdSet &udfCharOutputs =
    tmudfNode->getGroupAttr()->getCharacteristicOutputs();
  ValueIdSet usedOutputColumns(udfCharOutputs);
  ValueIdSet exprsOnOutputColumns(udfCharOutputs);
  ValueIdList predsOfferedToUDF;
  NABitVector usedColPositions;

  // don't clear valuesRequiredByParent, we just add to this set
  // clear remaining output parameters
  predsEvaluatedByUDF.clear();
  predsToPushDown.clear();

  // start with those characteristic outputs that are output columns
  // of the UDF
  usedOutputColumns.intersectSet(udfOutputColSet);

  // next, look into more complex expressions that reference output columns
  exprsOnOutputColumns -= udfOutputColSet;

  // find out which of the UDF outputs are referenced by these
  // more complex expressions
  ValueIdSet temp(udfOutputColSet);
  exprsOnOutputColumns.weedOutUnreferenced(temp);
  usedOutputColumns += temp;

  // loop over the characteristic outputs and translate them into ordinals
  for (ValueId udfOutputCol=usedOutputColumns.init(); 
       usedOutputColumns.next(udfOutputCol);
       usedOutputColumns.advance(udfOutputCol))
    {
      CollIndex ordinal =
        tmudfNode->getProcOutputParamsVids().index(udfOutputCol);

      CMPASSERT(ordinal != NULL_COLL_INDEX)
      usedColPositions += ordinal;
    }

  // set up predicate information from the selection predicates
  if (!TMUDFInternalSetup::setPredicateInfoFromValueIdSet(
           invocationInfo,
           udfOutputCols,
           tmudfNode->selectionPred(),
           predsOfferedToUDF,
           usedColPositions))
    return FALSE;

  // initialize usage info for all columns
  for (int c=0; c<numOutputColumns; c++)
    outputTableInfo.getColumn(c).setUsage(
         (usedColPositions.contains(c) ?
          tmudr::ColumnInfo::USED :
          tmudr::ColumnInfo::NOT_USED));

  // call the UDR compiler interface
  if (!invokeRoutine(tmudr::UDRInvocationInfo::COMPILER_DATAFLOW_CALL,
                     tmudfNode))
    return FALSE;
                     
  // Remove any unused output columns. Also, just as a sanity check,
  // make sure the UDF didn't change any of the output columns' usage
  for (int x=udfOutputCols.entries()-1; x>=0; x--)
    {
      tmudr::ColumnInfo::ColumnUseCode usage =
        invocationInfo->out().getColumn(x).getUsage();

      if (usedColPositions.contains(x))
        {
          if (usage != tmudr::ColumnInfo::USED)
            {
              processReturnStatus(
                   tmudr::UDRException(
                        38900,
                        "UDF output column %d changed from used to not used.",
                        x),
                   tmudfNode);
              return FALSE;
            }
        }
      else
        {
          if (usage == tmudr::ColumnInfo::USED)
            {
              processReturnStatus(
                   tmudr::UDRException(
                        38900,
                        "UDF output column %d changed from not used to used",
                        x),
                   tmudfNode);
            }
          else if (usage == tmudr::ColumnInfo::NOT_PRODUCED)
            // remove this column from the list
            // of output columns, the UDF allowed it by
            // setting the usage code to NOT_PRODUCED
            tmudfNode->removeOutputParam(x);
        }
    }

  // For each child column marked as "used" by the UDF, treat it as an
  // expression required by the parent.
  // For each predicate marked as pushable to a child, rewrite it in terms of
  // child value ids and use it as a selection predicate for
  // pushdownCoveredExprs. For every predicate marked as evaluated by the
  // UDF, remove it from the selection predicates.

  for (int i=0; i<tmudfNode->getArity(); i++)
    {
      const tmudr::TableInfo &ti = invocationInfo->in(i);
      const tmudr::PartitionInfo &pi = ti.getQueryPartitioning();
      const tmudr::OrderInfo &oi = ti.getQueryOrdering();
      ValueIdList &childOutputs = tmudfNode->getChildInfo(i)->getOutputIds();
      int numInputCols = ti.getNumColumns();
      int numPartCols  = pi.getNumEntries();
      int numOrderCols = oi.getNumEntries();

      // mark all columns used by PARTITION BY or ORDER BY as used,
      // in case the UDF didn't
      for (int pc=0; pc<numPartCols; pc++)
        invocationInfo->setChildColumnUsage(i,
                                            pi.getColumnNum(pc),
                                            tmudr::ColumnInfo::USED);
      for (int oc=0; oc<numOrderCols; oc++)
        invocationInfo->setChildColumnUsage(i,
                                            oi.getColumnNum(oc),
                                            tmudr::ColumnInfo::USED);

      // go backwards, so we can remove by position from
      // a ValueIdList below
      for (int c=numInputCols-1; c>=0; c--)
        switch (ti.getColumn(c).getUsage())
          {
          case tmudr::ColumnInfo::UNKNOWN:
            // the UDF didn't set any usage info, assume USED
            invocationInfo->setChildColumnUsage(
                 i, c, tmudr::ColumnInfo::USED);
            // fall through to next case
          case tmudr::ColumnInfo::USED:
            // This column is needed, treat it as an expression needed by
            // the parent.
            valuesRequiredByParent += childOutputs[c];
            break;

          case tmudr::ColumnInfo::NOT_PRODUCED:
          case tmudr::ColumnInfo::NOT_USED:
            // Remove the column from the NAColumnArray and ValueIdList
            // describing the child table. We don't distinguish NOT_USED
            // and NOT_PRODUCED on children, since both are set by the UDF.
            tmudfNode->getChildInfo(i)->removeColumn(c);
            break;

          default:
            processReturnStatus(
                 tmudr::UDRException(
                      38900,
                      "Invalid usage code %d for column %d of child %d",
                      ti.getColumn(c).getUsage(), c, i),
                 tmudfNode);
            return FALSE;
          }
    }

  // walk through predicates and handle the evaluation codes assigned to them
  for (int p=0; p<predsOfferedToUDF.entries(); p++)
    {
      int evalCode = static_cast<int>(
           invocationInfo->getPredicate(p).getEvaluationCode());

      // evaluate the predicate on the UDF result if the evaluation
      // code was not set at all or if the EVALUATE_ON_RESULT flag
      // is set
      if (!(evalCode == tmudr::PredicateInfo::UNKNOWN_EVAL ||
            evalCode & tmudr::PredicateInfo::EVALUATE_ON_RESULT))
        selectionPreds -= predsOfferedToUDF[p];

      if (evalCode & tmudr::PredicateInfo::EVALUATE_IN_UDF)
        predsEvaluatedByUDF += predsOfferedToUDF[p];

      if (evalCode & tmudr::PredicateInfo::EVALUATE_IN_CHILD)
        predsToPushDown += predsOfferedToUDF[p];
    }

  // We have removed unused columns from our ValueIdLists.
  // Remove columns that are not used or not produced in
  // the UDRInvocationInfo as well and
  // trim down the predicate list in the UDRInvocationInfo
  // to contain just those predicates that are evaluated in
  // the UDF itself.
  return TMUDFInternalSetup::removeUnusedColumnsAndPredicates(
       invocationInfo);
}

NABoolean TMUDFDllInteraction::describeConstraints(
     TableMappingUDF * tmudfNode)
{
  tmudr::UDRInvocationInfo *invocationInfo = tmudfNode->getInvocationInfo();

  // set up constraint info for child tables
  if (!TMUDFInternalSetup::createConstraintInfoFromRelExpr(tmudfNode))
    return FALSE;

  // call the UDR compiler interface
  if (!invokeRoutine(tmudr::UDRInvocationInfo::COMPILER_CONSTRAINTS_CALL,
                     tmudfNode))
    return FALSE;

  // translate resulting constraints on result table back into
  // ItemExprs
  if (!TMUDFInternalSetup::createConstraintsFromConstraintInfo(
           invocationInfo->out(),
           tmudfNode,
           CmpCommon::statementHeap()))
    return FALSE;

  return TRUE;
}

NABoolean TMUDFDllInteraction::describeStatistics(
     TableMappingUDF * tmudfNode,
     const EstLogPropSharedPtr& inputLP)
{
  // set the child output stats, so the UDF can synthesize its own stats
  if (!TMUDFInternalSetup::setChildOutputStats(
           tmudfNode->getInvocationInfo(),
           tmudfNode,
           inputLP))
    return FALSE;

  // call the UDR compiler interface
  if (!invokeRoutine(tmudr::UDRInvocationInfo::COMPILER_STATISTICS_CALL,
                     tmudfNode))
    return FALSE;

  return TRUE;
}

NABoolean TMUDFDllInteraction::degreeOfParallelism(
     TableMappingUDF * tmudfNode,
     TMUDFPlanWorkSpace * pws,
     int &dop)
{ 
  tmudr::UDRInvocationInfo *invocationInfo = tmudfNode->getInvocationInfo();
  tmudr::UDRPlanInfo *udrPlanInfo = pws->getUDRPlanInfo();

  if (udrPlanInfo == NULL)
    {
      // make a UDRPlanInfo for this PWS
      udrPlanInfo = TMUDFInternalSetup::createUDRPlanInfo(invocationInfo,
                                                          tmudfNode->getNextPlanInfoNum());
      pws->setUDRPlanInfo(udrPlanInfo);
    }

  // call the UDR compiler interface
  if (!invokeRoutine(tmudr::UDRInvocationInfo::COMPILER_DOP_CALL,
                     tmudfNode,
                     udrPlanInfo))
    return FALSE;

  dop = udrPlanInfo->getDesiredDegreeOfParallelism();
  
  return TRUE;
}

NABoolean TMUDFDllInteraction::finalizePlan(
     TableMappingUDF * tmudfNode,
     tmudr::UDRPlanInfo *planInfo)
{ 
  tmudr::UDRInvocationInfo *invocationInfo = tmudfNode->getInvocationInfo();

  // call the UDR compiler interface
  if (!invokeRoutine(tmudr::UDRInvocationInfo::COMPILER_COMPLETION_CALL,
                     tmudfNode,
                     planInfo))
    return FALSE;

  return TRUE;
}

CostScalar TMUDFDllInteraction::getResultCardinality(TableMappingUDF *tmudfNode)
{
  return tmudfNode->getInvocationInfo()->out().getEstimatedNumRows();
}

CostScalar TMUDFDllInteraction::getCardinalityScaleFactorFromFunctionType(
     TableMappingUDF *tmudfNode)
{
  switch (tmudfNode->getInvocationInfo()->getFuncType())
    {
    case tmudr::UDRInvocationInfo::MAPPER:
      // for mappers, we assume that the UDF returns one output row per input row
      return 1;

    case tmudr::UDRInvocationInfo::REDUCER:
      // for reducers, we assume that the UDF returns one output row per partition
      // of the input rows of the partitioned child with the most rows
      {
        double ratio = 1; // fallback, return the same value as for a maper
        long childNumRows = 0;
        tmudr::UDRInvocationInfo *ii = tmudfNode->getInvocationInfo();

        // try to find the partitioned child with the most rows and
        // compute its ratio of partitions / row
        for (int c=0; c<ii->getNumTableInputs(); c++)
          {
            long estNumRows    = ii->in(c).getEstimatedNumRows();
            long estPartitions = ii->in(c).getEstimatedNumPartitions();

            if (estNumRows > childNumRows &&
                estPartitions > 0 &&
                estPartitions < estNumRows)
              {
                ratio = estPartitions / estNumRows;
                childNumRows = estNumRows;
              }
          }

        return ratio;
      }

    default:
      // we don't have a clue
      return -1;
    }
}

CostScalar TMUDFDllInteraction::getOutputColumnUEC(TableMappingUDF *tmudfNode,
                                                   int colNum)
{
  return tmudfNode->getInvocationInfo()->
    out().getColumn(colNum).getEstimatedUniqueEntries();
}

NABoolean TMUDFDllInteraction::invokeRoutine(tmudr::UDRInvocationInfo::CallPhase cp,
                                             TableMappingUDF * tmudfNode,
                                             tmudr::UDRPlanInfo *planInfo,
                                             ComDiagsArea *diags)
{
  tmudr::UDRInvocationInfo *invocationInfo = tmudfNode->getInvocationInfo();
  CliRoutineHandle routineHandle = tmudfNode->getRoutineHandle();
  Int32 cliRC;

  if (diags == NULL)
    diags = CmpCommon::diags();

  // set up variables to serialize/deserialize UDRInvocationInfo
  char iiBuf[20000];
  char *serializedUDRInvocationInfo = iiBuf;
  int iiLen = 0;
  int iiAllocatedLen = sizeof(iiBuf);
  Int32 iiReturnedLen = -1;
  int iiCheckLen = -1;

  // set up variables to serialize/deserialize UDRPlanInfo
  char piBuf[10000];
  char *serializedUDRPlanInfo = piBuf;
  int piLen = 0;
  int piAllocatedLen = sizeof(piBuf);
  Int32 piReturnedLen = -1;
  int piCheckLen = -1;
  int planNum = -1;

  try
    {
      if (invocationInfo && cp != tmudr::UDRInvocationInfo::COMPILER_INITIAL_CALL)
        {
          // Note: We don't send the invocationInfo in the initial call, because
          //       we already sent it as part of the GetRoutine call and it did
          //       not change in the meantime.

          iiLen = invocationInfo->serializedLength();
          if (iiLen > iiAllocatedLen)
            {
              // leave some room for growth for the returned data
              // after the call
              iiAllocatedLen = 2*iiLen + 4000;
              serializedUDRInvocationInfo =
                new(CmpCommon::statementHeap()) char[iiAllocatedLen];
            }

          invocationInfo->serializeObj(serializedUDRInvocationInfo, iiLen);
        }

      if (planInfo)
        {
          planNum = planInfo->getPlanNum();
          piLen = planInfo->serializedLength();
          if (piLen > piAllocatedLen)
            {
              // leave some room for growth for the returned data
              // after the call
              piAllocatedLen = 2*piLen + 2000;
              serializedUDRPlanInfo =
                new(CmpCommon::statementHeap()) char[piAllocatedLen];
            }

          planInfo->serializeObj(serializedUDRPlanInfo, piLen);
        }
    }
  catch (tmudr::UDRException e)
    {
      *diags << DgSqlCode(-LME_OBJECT_INTERFACE_ERROR)
             << DgString0(invocationInfo->getUDRName().c_str())
             << DgString1(tmudr::UDRInvocationInfo::callPhaseToString(cp))
             << DgString2("serialize")
             << DgString3(e.getMessage().data());
      return FALSE;
    }
  catch (...)
    {
      *diags << DgSqlCode(-LME_OBJECT_INTERFACE_ERROR)
             << DgString0(invocationInfo->getUDRName().c_str())
             << DgString1(tmudr::UDRInvocationInfo::callPhaseToString(cp))
             << DgString2("serialize")
             << DgString3("General exception");
      return FALSE;
    }

  cliRC = cliInterface_.invokeRoutine(
       routineHandle,
       static_cast<Int32>(cp),
       serializedUDRInvocationInfo,
       iiLen,
       &iiReturnedLen,
       serializedUDRPlanInfo,
       piLen,
       planNum,
       &piReturnedLen,
       tmudfNode->getConstParamBuffer(),
       tmudfNode->getConstParamBufferLen(),
       NULL, // no output row
       0,
       diags);

  if (cliRC < 0)
    return FALSE;

  // The previous call gave us the length to expect for the updated
  // invocation and plan infos. Now make sure we have big enough buffers
  // and then retrieve these objects.
  if (iiReturnedLen > iiAllocatedLen)
    {
      // resize the buffer to be able to hold the returned info
      iiAllocatedLen = iiReturnedLen;
      if (serializedUDRInvocationInfo != iiBuf)
        NADELETEBASIC(serializedUDRInvocationInfo, CmpCommon::statementHeap());
      serializedUDRInvocationInfo =
        new(CmpCommon::statementHeap()) char[iiAllocatedLen];
    }

  if (piReturnedLen > piAllocatedLen)
    {
      // resize the buffer to be able to hold the returned info
      piAllocatedLen = piReturnedLen;
      if (serializedUDRPlanInfo != piBuf)
        NADELETEBASIC(serializedUDRPlanInfo, CmpCommon::statementHeap());
      serializedUDRPlanInfo =
        new(CmpCommon::statementHeap()) char[piAllocatedLen];
    }

  cliRC = cliInterface_.getRoutineInvocationInfo(
       routineHandle,
       serializedUDRInvocationInfo,
       iiAllocatedLen,
       &iiCheckLen,
       serializedUDRPlanInfo,
       piAllocatedLen,
       planNum,
       &piCheckLen,
       diags);

  if (cliRC < 0 ||
      iiCheckLen != iiReturnedLen ||
      piCheckLen != piReturnedLen)
    {
      // make sure we report an error
      if (diags->mainSQLCODE() >= 0)
        *diags << DgSqlCode(-LME_OBJECT_INTERFACE_ERROR)
               << DgString0(invocationInfo->getUDRName().c_str())
               << DgString1(tmudr::UDRInvocationInfo::callPhaseToString(cp))
               << DgString2("GetRoutineInvocationInfo")
               << DgString3("CLI failed without diags");
      return FALSE;
    }

  try
    {
      // if updated objects were returned, deserialize them, so that
      // we can process the updated information in the caller
      if (invocationInfo && iiReturnedLen > 0)
        invocationInfo->deserializeObj(serializedUDRInvocationInfo,
                                       iiCheckLen);

      if (planInfo && piReturnedLen > 0)
        planInfo->deserializeObj(serializedUDRPlanInfo,
                                 piCheckLen);
    }
  catch (tmudr::UDRException e)
    {
      *diags << DgSqlCode(-LME_OBJECT_INTERFACE_ERROR)
             << DgString0(invocationInfo->getUDRName().c_str())
             << DgString1(tmudr::UDRInvocationInfo::callPhaseToString(cp))
             << DgString2("deserialize")
             << DgString3(e.getMessage().data());
      return FALSE;
    }
  catch (...)
    {
      *diags << DgSqlCode(-LME_OBJECT_INTERFACE_ERROR)
             << DgString0(invocationInfo->getUDRName().c_str())
             << DgString1(tmudr::UDRInvocationInfo::callPhaseToString(cp))
             << DgString2("deserialize")
             << DgString3("General exception");
      return FALSE;
    }

  return TRUE;
}

void TMUDFDllInteraction::processReturnStatus(const tmudr::UDRException &e, 
                                              TableMappingUDF *tmudfNode)
{
  // this method is just a shortcut to the more verbose form
  processReturnStatus(
       e,
       tmudfNode->getUserTableName().getExposedNameAsAnsiString().data());
}

void TMUDFDllInteraction::processReturnStatus(const tmudr::UDRException &e, 
                                              const char * routineName,
                                              ComDiagsArea *diags)
{
  const char *sqlState = e.getSQLState();
  NABoolean validSQLState = (strncmp(sqlState, "38", 2) == 0);

  if (diags == NULL)
    diags = CmpCommon::diags();

  if (validSQLState)
    for (int pos=2; pos<5; pos++)
      {
        char ch = sqlState[pos];

        // See ISO/ANSI SQL, subclause 23.1 SQLSTATE
        // - Class 38: External routine exception (see above)
        // - Only digits and simple Latin upper case letters
        //   are allowed in SQLSTATE.
        if (!(ch >= '0' && ch <= '9' ||
              ch >= 'A' && ch <= 'Z'))
          validSQLState = FALSE;
      }
                          
  if (validSQLState)
    {
      // valid SQLSTATE for UDRs, class 38 as defined
      // in the ANSI SQL standard
      *diags << DgSqlCode(-LME_CUSTOM_ERROR)
             << DgString0(e.getMessage().data())
             << DgString1(sqlState);
      *diags << DgCustomSQLState(sqlState);
    }
  else
    {
      *diags << DgSqlCode(-LME_UDF_ERROR)
             << DgString0(routineName)
             << DgString1(sqlState)
             << DgString2(e.getMessage().data());
    }
}

tmudr::UDRInvocationInfo *TMUDFInternalSetup::createInvocationInfoFromRelExpr(
     TableMappingUDF * tmudfNode,
     char *&constBuffer,
     int &constBufferLength,
     ComDiagsArea *diags)
{
  tmudr::UDRInvocationInfo *result = new tmudr::UDRInvocationInfo();
  NABoolean success = TRUE;

  // register this object with the context, so it will be cleaned
  // up after compilation
  CmpCommon::context()->addInvocationInfo(result);

  result->name_ = tmudfNode->getRoutineName().getQualifiedNameAsAnsiString().data();
  result->numTableInputs_ = tmudfNode->getArity();

  result->debugFlags_ = static_cast<int>(ActiveSchemaDB()->getDefaults().getAsLong(UDR_DEBUG_FLAGS));
  // initialize the function type with the most general
  // type there is, SETFUNC
  result->funcType_ = tmudr::UDRInvocationInfo::GENERIC;

  // set user ids
  result->currentUser_ = ComUser::getCurrentUsername();

  if (ComUser::getSessionUser() ==
      ComUser::getCurrentUser())
    result->sessionUser_ = result->currentUser_;
  else
    {
      // session user is different, look it up
      char sessionUsername[MAX_USERNAME_LEN + 1];
      Int32 sessionUserLen;

      if (ComUser::getUserNameFromUserID(
               ComUser::getSessionUser(),
               sessionUsername,
               sizeof(sessionUsername),
               sessionUserLen) == FEOK)
        result->sessionUser_ = sessionUsername;
    }

  // set info for the formal scalar input parameters
  const NAColumnArray &formalParams = tmudfNode->getNARoutine()->getInParams();
  for (CollIndex c=0; c<formalParams.entries(); c++)
    {
      tmudr::ColumnInfo *pi =
        TMUDFInternalSetup::createColumnInfoFromNAColumn(
             formalParams[c],
             diags);
      if (!pi)
        return NULL;

      result->addFormalParameter(*pi);
    }

  // set info for the actual scalar input parameters
  const ValueIdList &actualParamVids = tmudfNode->getProcInputParamsVids();
  constBuffer = NULL;
  constBufferLength = 0;
  int nextOffset = 0;

  for (CollIndex j=0; j < actualParamVids.entries(); j++)
    {
      NABoolean negate;
      ConstValue *constVal = actualParamVids[j].getItemExpr()->castToConstValue(negate);

      if (constVal)
        {
          constBufferLength += constVal->getType()->getTotalSize();
          // round up to the next multiple of 8
          // do this the same way as with nextOffset below
          constBufferLength = ((constBufferLength + 7) / 8) * 8;
        }
    }

  // Allocate a buffer to hold the constant values in binary form.
  // This gets allocated from the statement heap and will not be
  // changed or deallocated. Therefore, we won't need to copy
  // this buffer again, e.g. in TableMappingUDF::copyTopNode().
  if (constBufferLength > 0)
    constBuffer = new(CmpCommon::statementHeap()) char[constBufferLength];
  // record length for compile-time parameters
  result->nonConstActualParameters().setRecordLength(constBufferLength);

  for (CollIndex i=0; i < actualParamVids.entries(); i++)
    {
      NABoolean success = TRUE;
      NABoolean negate;
      ConstValue *constVal = actualParamVids[i].getItemExpr()->castToConstValue(negate);
      const NAType &paramType = (constVal ? constVal->getValueId().getType()
                                          : actualParamVids[i].getType());
      NABuiltInTypeEnum typeClass = paramType.getTypeQualifier();
      std::string paramName;
      char paramNum[10];

      if (i < result->getFormalParameters().getNumColumns())
        paramName = result->getFormalParameters().getColumn(i).getColName();

      tmudr::TypeInfo ti;
      success = TMUDFInternalSetup::setTypeInfoFromNAType(
           ti,
           &paramType,
           diags);
      if (!success)
        return NULL;

      tmudr::ColumnInfo pi = tmudr::ColumnInfo(
           paramName.data(),
           ti);

      result->nonConstActualParameters().addColumn(pi);
      
      // if the actual parameter is a constant value, pass its data
      // to the UDF
      if (constVal)
        {
          int totalSize     = constVal->getType()->getTotalSize();
          int nullIndOffset = -1;
          int vcLenOffset   = -1;
          int dataOffset    = -1;

          memcpy(constBuffer + nextOffset, constVal->getConstValue(), totalSize);

          constVal->getOffsetsInBuffer(nullIndOffset, vcLenOffset, dataOffset);
          result->nonConstActualParameters().getColumn(i).getType().setOffsets(
               (nullIndOffset >= 0 ? nextOffset + nullIndOffset : -1),
               (vcLenOffset   >= 0 ? nextOffset + vcLenOffset   : -1),
               nextOffset + dataOffset);

          nextOffset += totalSize;
          // round up to the next multiple of 8
          // do this the same way as with constBufferLength above
          nextOffset = ((nextOffset + 7) / 8) * 8;

        }
    }
  CMPASSERT(nextOffset == constBufferLength);

  // set up info for the input (child) tables
  for (int c=0; c<result->numTableInputs_; c++)
    {
      TableMappingUDFChildInfo *childInfo = tmudfNode->getChildInfo(c);
      const NAColumnArray &childColArray = childInfo->getInputTabCols();
      const ValueIdList &childOrderBy = childInfo-> getOrderBy();

      success = TMUDFInternalSetup::setTableInfoFromNAColumnArray(
           result->inputTableInfo_[c],
           &childColArray,
           diags);
      if (!success)
        return NULL;

      // add child PARTITION BY syntax
      tmudr::PartitionInfo pi;

      switch (childInfo->getPartitionType())
        {
        case ANY_PARTITIONING:
          pi.setType(tmudr::PartitionInfo::ANY);
          break;

        case SPECIFIED_PARTITIONING:
          {
            const ValueIdSet &childPartBy = childInfo->getPartitionBy();
            const ValueIdList &childCols  = childInfo->getOutputs();

            pi.setType(tmudr::PartitionInfo::PARTITION);

            // translate the value ids into ordinal column numbers
            for (ValueId p=childPartBy.init();
                 childPartBy.next(p);
                 childPartBy.advance(p))
              {
                CollIndex ordinal = childCols.index(p);

                CMPASSERT(ordinal != NULL_COLL_INDEX);
                pi.addEntry(ordinal);
              }
          }
          break;

        case REPLICATE_PARTITIONING:
          pi.setType(tmudr::PartitionInfo::REPLICATE);
          break;

        case NO_PARTITIONING:
          pi.setType(tmudr::PartitionInfo::SERIAL);
          break;

        default:
          // leave pi uninitialized
          break;
        }

      result->setChildPartitioning(c, pi);

      if (childOrderBy.entries() > 0)
        {
          // add child ORDER BY syntax
          const ValueIdList &childCols  = childInfo->getOutputs();
          tmudr::OrderInfo orderInfo;

          for (int obc=0; obc<childOrderBy.entries(); obc++)
            {
              // translate the value id into an ordinal column number
              CollIndex ordinal = NULL_COLL_INDEX;
              tmudr::OrderInfo::OrderTypeCode orderCode = tmudr::OrderInfo::ASCENDING;

              if (childOrderBy[obc].getItemExpr()->getOperatorType() == ITM_INVERSE)
                {
                  orderCode = tmudr::OrderInfo::DESCENDING;
                  ordinal = childCols.index(
                       childOrderBy[obc].getItemExpr()->child(0).getValueId());
                }
              else
                ordinal = childCols.index(childOrderBy[obc]);

              CMPASSERT(ordinal != NULL_COLL_INDEX);
              orderInfo.addEntry(ordinal, orderCode);
            }

          result->setChildOrdering(c, orderInfo);
        }
    }

  // initialize output columns with the columns declared in the metadata
  // UDF compiler interface can change this
  success = TMUDFInternalSetup::setTableInfoFromNAColumnArray(
       result->outputTableInfo_,
       &(tmudfNode->getNARoutine()->getOutParams()),
       diags);
  if (!success)
    return NULL;

  // predicates_ is initially empty, nothing to do

  return result;
}

NABoolean TMUDFInternalSetup::setTypeInfoFromNAType(
     tmudr::TypeInfo &tgt,
     const NAType *src,
     ComDiagsArea *diags)
{
  // follows code in TMUDFDllInteraction::setParamInfo() - approximately
  NABoolean result = TRUE;

  tmudr::TypeInfo::SQLTypeCode sqlType = tmudr::TypeInfo::UNDEFINED_SQL_TYPE;
  int length    = src->getNominalSize();
  bool nullable = src->supportsSQLnull();
  int scale     = 0;
  tmudr::TypeInfo::SQLCharsetCode charset = tmudr::TypeInfo::CHARSET_UTF8;
  tmudr::TypeInfo::SQLIntervalCode intervalCode =
    tmudr::TypeInfo::UNDEFINED_INTERVAL_CODE;
  int precision = 0;
  tmudr::TypeInfo::SQLCollationCode collation =
    tmudr::TypeInfo::SYSTEM_COLLATION;

  // sqlType_, cType_, scale_, charset_, intervalCode_, precision_, collation_
  // are somewhat dependent on each other and are set in the following
  switch (src->getTypeQualifier())
    {
    case NA_NUMERIC_TYPE:
      {
        const NumericType *numType = static_cast<const NumericType *>(src);
        NABoolean isUnsigned = numType->isUnsigned();
        NABoolean isDecimal = numType->isDecimal();
        NABoolean isDecimalPrecision = numType->decimalPrecision();
        NABoolean isExact = numType->isExact();

        scale = src->getScale();

        if (isDecimalPrecision)
          {
            if (isUnsigned)
              sqlType = tmudr::TypeInfo::NUMERIC_UNSIGNED;
            else
              sqlType = tmudr::TypeInfo::NUMERIC;
            // decimal precision is used for SQL type NUMERIC
            precision = src->getPrecision();
          }

        if (isDecimal)
          {
            // decimals are represented as strings in the UDF
            if (isUnsigned)
              sqlType = tmudr::TypeInfo::DECIMAL_UNSIGNED;
            else
              sqlType = tmudr::TypeInfo::DECIMAL_LSE;
            // decimal precision is used for range checks
            precision = src->getPrecision();
          }
        else if (isExact)
          switch (length)
            {
              // TINYINT, SMALLINT, INT, LARGEINT, NUMERIC, signed and unsigned
            case 1:
              if (isUnsigned)
                {
                  if (!isDecimalPrecision)
                    sqlType = tmudr::TypeInfo::TINYINT_UNSIGNED;
                }
              else
                {
                  if (!isDecimalPrecision)
                    sqlType = tmudr::TypeInfo::TINYINT;
                }
              break;

            case 2:
              if (isUnsigned)
                {
                  if (!isDecimalPrecision)
                    sqlType = tmudr::TypeInfo::SMALLINT_UNSIGNED;
                }
              else
                {
                  if (!isDecimalPrecision)
                    sqlType = tmudr::TypeInfo::SMALLINT;
                }
              break;
              
            case 4:
              if (isUnsigned)
                {
                  if (!isDecimalPrecision)
                    sqlType = tmudr::TypeInfo::INT_UNSIGNED;
                }
              else
                {
                  if (!isDecimalPrecision)
                    sqlType = tmudr::TypeInfo::INT;
                }
              break;

            case 8:
              CMPASSERT(!isUnsigned);
              if (!isDecimalPrecision)
                sqlType = tmudr::TypeInfo::LARGEINT;
              break;

            default:
              *diags << DgSqlCode(-11151)
                     << DgString0("type")
                     << DgString1(src->getTypeSQLname())
                     << DgString2("unsupported length");
              result = FALSE;
            }
        else // inexact numeric
          if (length == 4)
            {
              sqlType = tmudr::TypeInfo::REAL;
            }
          else
            {
              // note that there is no SQL FLOAT in UDFs, SQL FLOAT
              // gets mapped to REAL or DOUBLE PRECISION
              CMPASSERT(length == 8);
              sqlType = tmudr::TypeInfo::DOUBLE_PRECISION;
            }
      }
      break;

    case NA_CHARACTER_TYPE:
      {
        CharInfo::CharSet cs = (CharInfo::CharSet) src->getScaleOrCharset();

        if (src->isVaryingLen())
          sqlType = tmudr::TypeInfo::VARCHAR;
        else
          sqlType = tmudr::TypeInfo::CHAR;

        // character set
        switch (cs)
          {
          case CharInfo::ISO88591:
            charset = tmudr::TypeInfo::CHARSET_ISO88591;
            break;

          case CharInfo::UTF8:
            charset = tmudr::TypeInfo::CHARSET_UTF8;
            break;

          case CharInfo::UCS2:
            charset = tmudr::TypeInfo::CHARSET_UCS2;
            break;

          default:
            *diags << DgSqlCode(-11151)
                   << DgString0("character set")
                   << DgString1(CharInfo::getCharSetName(
                                     (CharInfo::CharSet) src->getScaleOrCharset()))
                   << DgString2("unsupported character set");
            result = FALSE;
          }

        // length is specified in characters for this constructor,
        // divide the nominal size by the min. character width
        length /= CharInfo::minBytesPerChar(cs);
        // collation stays at 0 for now
      }
      break;

    case NA_DATETIME_TYPE:
      {
        const DatetimeType *dType = static_cast<const DatetimeType *>(src);

        // fraction precision for time/timestamp, which is really
        // the scale of the second part
        scale = dType->getFractionPrecision();

        switch (dType->getSubtype())
          {
          case DatetimeType::SUBTYPE_SQLDate:
            sqlType = tmudr::TypeInfo::DATE;
            break;
          case DatetimeType::SUBTYPE_SQLTime:
            sqlType = tmudr::TypeInfo::TIME;
            break;
          case DatetimeType::SUBTYPE_SQLTimestamp:
            sqlType = tmudr::TypeInfo::TIMESTAMP;
            break;
          default:
            *diags << DgSqlCode(-11151)
                   << DgString0("type")
                   << DgString1(src->getTypeSQLname())
                   << DgString2("unsupported datetime subtype");
            result = FALSE;
          }
      }
      break;

    case NA_INTERVAL_TYPE:
      {
        const IntervalType *iType = static_cast<const IntervalType *>(src);

        sqlType   = tmudr::TypeInfo::INTERVAL;
        precision = iType->getLeadingPrecision();
        scale     = iType->getFractionPrecision();

        switch (src->getFSDatatype())
          {
          case REC_INT_YEAR:
            intervalCode = tmudr::TypeInfo::INTERVAL_YEAR;
            break;
          case REC_INT_MONTH:
            intervalCode = tmudr::TypeInfo::INTERVAL_MONTH;
            break;
          case REC_INT_YEAR_MONTH:
            intervalCode = tmudr::TypeInfo::INTERVAL_YEAR_MONTH;
            break;
          case REC_INT_DAY:
            intervalCode = tmudr::TypeInfo::INTERVAL_DAY;
            break;
          case REC_INT_HOUR:
            intervalCode = tmudr::TypeInfo::INTERVAL_HOUR;
            break;
          case REC_INT_DAY_HOUR:
            intervalCode = tmudr::TypeInfo::INTERVAL_DAY_HOUR;
            break;
          case REC_INT_MINUTE:
            intervalCode = tmudr::TypeInfo::INTERVAL_MINUTE;
            break;
          case REC_INT_HOUR_MINUTE:
            intervalCode = tmudr::TypeInfo::INTERVAL_HOUR_MINUTE;
            break;
          case REC_INT_DAY_MINUTE:
            intervalCode = tmudr::TypeInfo::INTERVAL_DAY_MINUTE;
            break;
          case REC_INT_SECOND:
            intervalCode = tmudr::TypeInfo::INTERVAL_SECOND;
            break;
          case REC_INT_MINUTE_SECOND:
            intervalCode = tmudr::TypeInfo::INTERVAL_MINUTE_SECOND;
            break;
          case REC_INT_HOUR_SECOND:
            intervalCode = tmudr::TypeInfo::INTERVAL_HOUR_SECOND;
            break;
          case REC_INT_DAY_SECOND:
            intervalCode = tmudr::TypeInfo::INTERVAL_DAY_SECOND;
            break;
          default:
            *diags << DgSqlCode(-11151)
                   << DgString0("type")
                   << DgString1("interval")
                   << DgString2("unsupported interval subtype");
            result = FALSE;
          }
      }
      break;

    case NA_BOOLEAN_TYPE:
      {
        sqlType = tmudr::TypeInfo::BOOLEAN;
        if (length != 1)
          {
            *diags << DgSqlCode(-11151)
                   << DgString0("type")
                   << DgString1(src->getTypeSQLname())
                   << DgString2("unsupported 4 byte boolean");
            result = FALSE;
          }
      }
      break;

    default:
      *diags << DgSqlCode(-11151)
             << DgString0("type")
             << DgString1(src->getTypeSQLname())
             << DgString2("unsupported type class");
      result = FALSE;
    }

  // call the constructor and use that logic to set all the individual values
  tgt = tmudr::TypeInfo(
       sqlType,
       length,
       nullable,
       scale,
       charset,
       intervalCode,
       precision,
       collation);

  return result;
}

tmudr::ColumnInfo * TMUDFInternalSetup::createColumnInfoFromNAColumn(
     const NAColumn *src,
     ComDiagsArea *diags)
{
  tmudr::TypeInfo ti;

  if (!TMUDFInternalSetup::setTypeInfoFromNAType(
       ti,
       src->getType(),
       diags))
    return NULL;

  return new tmudr::ColumnInfo(
       src->getColName(),
       ti);
}

NABoolean TMUDFInternalSetup::setTableInfoFromNAColumnArray(
     tmudr::TableInfo &tgt,
     const NAColumnArray *src,
     ComDiagsArea *diags)
{
  for (CollIndex c=0; c<src->entries(); c++)
    {
      const NAColumn *nac = (*src)[c];
      tmudr::ColumnInfo *ci =
        TMUDFInternalSetup::createColumnInfoFromNAColumn(
             nac,
             diags);
      if (ci == NULL)
        return FALSE;

      tgt.columns_.push_back(ci);
    }

  return TRUE;
}

NABoolean TMUDFInternalSetup::setPredicateInfoFromValueIdSet(
     tmudr::UDRInvocationInfo *tgt,
     const ValueIdList &udfOutputColumns,
     const ValueIdSet &predicates,
     ValueIdList &convertedPredicates,
     NABitVector &usedColPositions)
{
  tmudr::TableInfo & outputTableInfo = tgt->out();
  int numOutputColumns = outputTableInfo.getNumColumns();
  tmudr::ComparisonPredicateInfo *pi;

  // loop over predicates
  for (ValueId pred=predicates.init(); 
       predicates.next(pred);
       predicates.advance(pred))
    {
      pi = NULL;

      // logic specific to the item expression
      switch (pred.getItemExpr()->getOperatorType())
        {
        case ITM_EQUAL:
        case ITM_LESS:
        case ITM_LESS_EQ:
        case ITM_GREATER:
        case ITM_GREATER_EQ:
          {
            // TBD: Do we need to check for "const op col" as well or
            // has this already been normalized?
            BiRelat *comp = static_cast<BiRelat *>(pred.getItemExpr());
            int columnNum = udfOutputColumns.index(comp->child(0).getValueId());
            NABoolean dummy;
            ConstValue *val = comp->child(1)->castToConstValue(dummy);

            if (val != NULL && columnNum != NULL_COLL_INDEX)
              {
                tmudr::PredicateInfo::PredOperator predOp = tmudr::PredicateInfo::UNKNOWN_OP;

                pi = new tmudr::ComparisonPredicateInfo;

                switch (pred.getItemExpr()->getOperatorType())
                  {
                  case ITM_EQUAL:
                    predOp = tmudr::PredicateInfo::EQUAL;
                    break;
                  case ITM_LESS:
                    predOp = tmudr::PredicateInfo::LESS;
                    break;
                  case ITM_LESS_EQ:
                    predOp = tmudr::PredicateInfo::LESS_EQUAL;
                    break;
                  case ITM_GREATER:
                    predOp = tmudr::PredicateInfo::GREATER;
                    break;
                  case ITM_GREATER_EQ:
                    predOp = tmudr::PredicateInfo::GREATER_EQUAL;
                    break;
                  }
                pi->setOperator(predOp);
                pi->setColumnNumber(columnNum);
                pi->setValue(val->getConstStr().data());
                // mark column used in predicate as used
                usedColPositions += columnNum;
              }
          }
          break;

        case ITM_VEG_PREDICATE:
          {
            VEGPredicate *vegPred = static_cast<VEGPredicate *>(pred.getItemExpr());
            VEG *veg = vegPred->getVEG();
            ValueId constValId = veg->getAConstant();
            ValueIdSet udfOutputColsInVEG(udfOutputColumns);
            ValueId colReferencedInVEG;

            udfOutputColsInVEG.intersectSet(veg->getAllValues());
            udfOutputColsInVEG.getFirst(colReferencedInVEG);

            if (constValId != NULL_VALUE_ID &&
                colReferencedInVEG != NULL_VALUE_ID)
              {
                int colNum = udfOutputColumns.index(colReferencedInVEG);

                // we found a VEG that has a constant member and also
                // one of the TMUDF output columns as a member, add
                // an equals predicate between the two
                CMPASSERT(colNum != NULL_COLL_INDEX);
                pi = new tmudr::ComparisonPredicateInfo;
                pi->setOperator(tmudr::PredicateInfo::EQUAL);
                pi->setColumnNumber(colNum);
                pi->setValue(
                     static_cast<ConstValue *>(constValId.getItemExpr())->
                     getConstStr().data());
                // mark column used in predicate as used
                usedColPositions += colNum;
              }
          }
          break;

        default:
          break;

        } // switch

      if (pi)
        {
          // add this predicate to the invocation info
          tgt->predicates_.push_back(pi);
          // also remember its number, so we can later
          // translate it back
          convertedPredicates.insert(pred);
        }
    } // loop over predicates

  return TRUE;
}

NABoolean TMUDFInternalSetup::removeUnusedColumnsAndPredicates(
     tmudr::UDRInvocationInfo *tgt)
{
  // remove unused output columns

  tmudr::TableInfo &outInfo = tgt->out();
  std::vector<int> outputColMap;
  int numDeletedOutCols = 0;

  // Make a map of current output column numbers to the new state
  // with output columns that are NOT_PRODUCED removed. Note that we
  // keep the columns marked as NOT_USED by the normalizer, since
  // the UDF did not indicate that it is ok to drop such columns.
  for (int c=0; c<outInfo.getNumColumns(); c++)
    if (outInfo.getColumn(c).getUsage() == tmudr::ColumnInfo::NOT_PRODUCED)
      {
        outputColMap.push_back(-1);
        numDeletedOutCols++;
      }
    else
      outputColMap.push_back(c-numDeletedOutCols);

  // remove unused predicates and adjust column numbers of remaining ones
  // to reflect deleted output columns
  std::vector<tmudr::PredicateInfo *>::iterator it = tgt->predicates_.begin();

  while (it != tgt->predicates_.end())
    if ((*it)->getEvaluationCode() == tmudr::PredicateInfo::EVALUATE_IN_UDF)
      {
        // keep this predicate, adjust its column numbers and 
        // move on to the next
        (*it)->mapColumnNumbers(outputColMap);
        it++;
      }
    else
      {
        // delete this predicate, set the iterator to the element following it
        tmudr::PredicateInfo *pi = *it;

        it = tgt->predicates_.erase(it);
        delete pi;
      }

  // remove unused output columns (go backwards)
  for (int oc=outInfo.getNumColumns()-1; oc>=0; oc--)
    if (outInfo.getColumn(oc).getUsage() == tmudr::ColumnInfo::NOT_PRODUCED)
      outInfo.deleteColumn(oc);

  // remove unused columns from the table-valued inputs
  for (int i=0; i<tgt->getNumTableInputs(); i++)
    {
      tmudr::TableInfo &inInfo = tgt->inputTableInfo_[i];
      std::vector<int> childOutputColMap;
      int numDeletedCols = 0;

      // first, make a map of current column numbers of this
      // table-valued input to the new state with unused columns
      // removed
      for (int cc=0; cc<inInfo.getNumColumns(); cc++)
        if (inInfo.getColumn(cc).getUsage() == tmudr::ColumnInfo::USED)
          childOutputColMap.push_back(cc-numDeletedCols);
        else
          {
            childOutputColMap.push_back(-1);
            numDeletedCols++;
          }

      if (numDeletedCols > 0)
        {
          tmudr::PartitionInfo newPartInfo;
          tmudr::OrderInfo newOrderInfo;

          // loop in reverse order and remove unused columns
          for (int ic=inInfo.getNumColumns()-1; ic>=0; ic--)
            if (inInfo.getColumn(ic).getUsage() != tmudr::ColumnInfo::USED)
              inInfo.deleteColumn(ic);

          // adjust column numbers in ORDER BY and PARTITION BY lists,
          // if necessary
          inInfo.getQueryPartitioning().mapColumnNumbers(childOutputColMap);
          inInfo.getQueryOrdering().mapColumnNumbers(childOutputColMap);

          // adjust the column numbers in the provenance info of the outputs
          // for removal of unused columns in the table-valued inputs
          for (int oc=0; oc<outInfo.getNumColumns(); oc++)
            {
              tmudr::ColumnInfo &colInfo = outInfo.getColumn(oc);
              const tmudr::ProvenanceInfo &prov = colInfo.getProvenance();

              if (prov.isFromInputTable(i))
                {
                  int oldColNum = prov.getInputColumnNum();

                  if (childOutputColMap[oldColNum] != oldColNum)
                    // column number is going to change, update provenance
                    colInfo.setProvenance(
                         tmudr::ProvenanceInfo(i, childOutputColMap[oldColNum]));
                }            
            }
        } // numDeletedCols > 0
    } // loop over table-valued inputs

  return TRUE;
}

NABoolean TMUDFInternalSetup::createConstraintInfoFromRelExpr(
     TableMappingUDF * tmudfNode)
{
  tmudr::UDRInvocationInfo *tgt = tmudfNode->getInvocationInfo();

  for (int i=0; i<tmudfNode->getArity(); i++)
    {
      const ValueIdSet &childConstraints =
        tmudfNode->child(i)->getGroupAttr()->getConstraints();

      for (ValueId v=childConstraints.init();
           childConstraints.next(v);
           childConstraints.advance(v))
        {
          switch (v.getItemExpr()->getOperatorType())
            {
            case ITM_CARD_CONSTRAINT:
              {
                long minRows, maxRows;
                CardConstraint *cc =
                  static_cast<CardConstraint *>(v.getItemExpr());

                minRows = cc->getLowerBound();
                maxRows = cc->getUpperBound();
                tgt->inputTableInfo_[i].addCardinalityConstraint(
                     tmudr::CardinalityConstraintInfo(minRows, maxRows));
              }
              break;

            case ITM_UNIQUE_OPT_CONSTRAINT:
              {
                // set of unique columns
                const ValueIdSet &uniqueCols =
                  static_cast<UniqueOptConstraint *>(
                       v.getItemExpr())->uniqueCols();
                // outputs produced by child i
                const ValueIdList &childColList =
                  tmudfNode->getChildInfo(i)->getOutputs();
                ValueIdSet childOutputSet = childColList;

                // cross-check the two
                childOutputSet.intersectSet(uniqueCols);

                if (uniqueCols == childOutputSet)
                  {
                    // we found all the unique columns in the child
                    // outputs (should be the common case), continue

                    tmudr::UniqueConstraintInfo ucInfo;

                    // translate ValueIdSet into a set of ordinal numbers
                    for (ValueId u=uniqueCols.init();
                         uniqueCols.next(u);
                         uniqueCols.advance(u))
                      ucInfo.addColumn(childColList.index(u));

                    tgt->inputTableInfo_[i].addUniquenessConstraint(ucInfo);
                  }
              }
              break;

            default:
              // skip this constraint, it's not handled yet
              break;
            }
        }
    }

  return TRUE;
}

NABoolean TMUDFInternalSetup::setChildOutputStats(
     tmudr::UDRInvocationInfo *tgt,
     TableMappingUDF * tmudfNode,
     const EstLogPropSharedPtr& inputLP)
{
  // set estimated # of rows, # of partitions, UECs for child
  // tables of the UDF in the UDRInvocationInfo
  for (CollIndex i=0; i<tmudfNode->getArity(); i++)
    {
      tmudr::TableInfo &ti = tgt->inputTableInfo_[i];
      const tmudr::PartitionInfo &pi = ti.getQueryPartitioning();
      ValueIdList &childOutputs = tmudfNode->getChildInfo(i)->getOutputIds();
      int numInputCols = ti.getNumColumns();
      int numPartCols  = pi.getNumEntries();
      EstLogPropSharedPtr childEstLogProps = 
        tmudfNode->child(i).outputLogProp(inputLP);
      const ColStatDescList &childColStatList =
        childEstLogProps->getColStats();


      // set overall estimated row count
      ti.setEstimatedNumRows(childEstLogProps->getResultCardinality().toLong());

      if (numPartCols > 0)
        {
          // set estimated # of partitions, if available
          ValueIdSet partCols;

          for (CollIndex p=0; p<numPartCols; p++)
            partCols += childOutputs[pi.getColumnNum(p)];

          // As a friend we can set this directly. Conveniently, both
          // estimatedNumPartitions_ and getAggregateUec() use -1
          // to represent an unknown value
          ti.estimatedNumPartitions_ =
            childColStatList.getAggregateUec(partCols).toLong();
        }

      // set UEC for each column, if available
      for (CollIndex c=0; c<numInputCols; c++)
        {
          long uec = -1;
          CollIndex index;

          if (childColStatList.getColStatDescIndexForColumn(
                   index,
                   childOutputs[c]))
            {
              uec = childColStatList[index]->getColStats()->getTotalUec().toLong();
              if (uec < 1)
                uec = 1;
            }

          ti.getColumn(c).setEstimatedUniqueEntries(uec);
        }
    }

  return TRUE;
}

NAType *TMUDFInternalSetup::createNATypeFromTypeInfo(
     const tmudr::TypeInfo &src,
     int colNumForDiags,
     NAHeap *heap,
     ComDiagsArea *diags)
{
  NAType *result = NULL;
  tmudr::TypeInfo::SQLTypeCode typeCode = src.getSQLType();

  switch (typeCode)
    {
    case tmudr::TypeInfo::TINYINT:
    case tmudr::TypeInfo::TINYINT_UNSIGNED:
      result = new(heap)
        SQLTiny(heap, (typeCode == tmudr::TypeInfo::TINYINT),
                src.getIsNullable());
      break;

    case tmudr::TypeInfo::SMALLINT:
    case tmudr::TypeInfo::SMALLINT_UNSIGNED:
      result = new(heap)
        SQLSmall(heap, (typeCode == tmudr::TypeInfo::SMALLINT),
                 src.getIsNullable());
      break;

    case tmudr::TypeInfo::INT:
    case tmudr::TypeInfo::INT_UNSIGNED:
      result = new(heap)
        SQLInt(heap, (typeCode == tmudr::TypeInfo::INT),
               src.getIsNullable());
      break;

    case tmudr::TypeInfo::LARGEINT:
      result = new(heap) SQLLargeInt(heap, TRUE,
                                     src.getIsNullable());
      break;

    case tmudr::TypeInfo::NUMERIC:
    case tmudr::TypeInfo::NUMERIC_UNSIGNED:
      {
        int storageSize = getBinaryStorageSize(src.getPrecision());
        // if the storage size is specified, it must match
        if (src.getByteLength() > 0 &&
            src.getByteLength() != storageSize)
          {
            *diags << DgSqlCode(-11152)
                   << DgInt0(typeCode)
                   << DgInt1(colNumForDiags)
                   << DgString0("Incorrect storage size");
          }
        else
          result = new(heap) 
            SQLNumeric(heap, storageSize,
                       src.getPrecision(),
                       src.getScale(),
                       (typeCode == tmudr::TypeInfo::NUMERIC),
                       src.getIsNullable());
      }
      break;

    case tmudr::TypeInfo::DECIMAL_LSE:
    case tmudr::TypeInfo::DECIMAL_UNSIGNED:
      result = new(heap)
        SQLDecimal(heap, src.getPrecision(),
                   src.getScale(),
                   (typeCode == tmudr::TypeInfo::DECIMAL_LSE),
                   src.getIsNullable());
      break;

    case tmudr::TypeInfo::REAL:
      result = new(heap) SQLReal(heap, src.getIsNullable());
      break;

    case tmudr::TypeInfo::DOUBLE_PRECISION:
      result = new(heap) SQLDoublePrecision(heap, src.getIsNullable());
      break;

    case tmudr::TypeInfo::CHAR:
    case tmudr::TypeInfo::VARCHAR:
      {
        CharInfo::CharSet cs = CharInfo::UnknownCharSet;

        switch (src.getCharset())
          {
          case tmudr::TypeInfo::CHARSET_ISO88591:
            cs = CharInfo::ISO88591;
            break;
          case tmudr::TypeInfo::CHARSET_UTF8:
            cs = CharInfo::UTF8;
            break;
          case tmudr::TypeInfo::CHARSET_UCS2:
            cs = CharInfo::UCS2;
            break;
          default:
            *diags << DgSqlCode(-11152)
                   << DgInt0(src.getSQLType())
                   << DgInt1(colNumForDiags)
                   << DgString0("Invalid charset");
          }

        if (cs != CharInfo::UnknownCharSet)
          {
            // assume that any UTF8 strings are
            // limited by their byte length, not
            // the number of UTF8 characters
            CharLenInfo lenInfo(0,src.getByteLength());

            if (typeCode == tmudr::TypeInfo::CHAR)
              result = new(heap)
                SQLChar(heap, lenInfo,
                        src.getIsNullable(),
                        FALSE,
                        FALSE,
                        FALSE,
                        cs);
            else
              result = new(heap)
                SQLVarChar(heap, lenInfo,
                           src.getIsNullable(),
                           FALSE,
                           FALSE,
                           cs);
          }
      }
      break;

    case tmudr::TypeInfo::DATE:
      result = new(heap) SQLDate(heap, src.getIsNullable());
      break;

    case tmudr::TypeInfo::TIME:
      result = new(heap) SQLTime(heap, src.getIsNullable(),
                                 src.getScale());
      break;

    case tmudr::TypeInfo::TIMESTAMP:
      result = new(heap) SQLTimestamp(heap, src.getIsNullable(),
                                      src.getScale());
      break;

    case tmudr::TypeInfo::INTERVAL:
      {
        rec_datetime_field startField = REC_DATE_UNKNOWN;
        rec_datetime_field endField = REC_DATE_UNKNOWN;

        switch (src.getIntervalCode())
          {
          case tmudr::TypeInfo::INTERVAL_YEAR:
            startField =
              endField = REC_DATE_YEAR;
            break;

          case tmudr::TypeInfo::INTERVAL_MONTH:
            startField =
              endField = REC_DATE_MONTH;
            break;

          case tmudr::TypeInfo::INTERVAL_DAY:
            startField =
              endField = REC_DATE_DAY;
            break;

          case tmudr::TypeInfo::INTERVAL_HOUR:
            startField =
              endField = REC_DATE_HOUR;
            break;

          case tmudr::TypeInfo::INTERVAL_MINUTE:
            startField =
              endField = REC_DATE_MINUTE;
            break;

          case tmudr::TypeInfo::INTERVAL_SECOND:
            startField =
              endField = REC_DATE_SECOND;
            break;

          case tmudr::TypeInfo::INTERVAL_YEAR_MONTH:
            startField = REC_DATE_YEAR;
            endField = REC_DATE_MONTH;
            break;

          case tmudr::TypeInfo::INTERVAL_DAY_HOUR:
            startField = REC_DATE_DAY;
            endField = REC_DATE_HOUR;
            break;

          case tmudr::TypeInfo::INTERVAL_DAY_MINUTE:
            startField = REC_DATE_DAY;
            endField = REC_DATE_MINUTE;
            break;

          case tmudr::TypeInfo::INTERVAL_DAY_SECOND:
            startField = REC_DATE_DAY;
            endField = REC_DATE_SECOND;
            break;

          case tmudr::TypeInfo::INTERVAL_HOUR_MINUTE:
            startField = REC_DATE_HOUR;
            endField = REC_DATE_MINUTE;
            break;

          case tmudr::TypeInfo::INTERVAL_HOUR_SECOND:
            startField = REC_DATE_HOUR;
            endField = REC_DATE_SECOND;
            break;

          case tmudr::TypeInfo::INTERVAL_MINUTE_SECOND:
            startField = REC_DATE_MINUTE;
            endField = REC_DATE_SECOND;
            break;

          default:
            *diags << DgSqlCode(-11152)
                   << DgInt0(src.getSQLType())
                   << DgInt1(colNumForDiags)
                   << DgString0("Invalid interval start/end fields");
          }

        if (startField != REC_DATE_UNKNOWN)
          {
            result = new(heap) SQLInterval(heap, src.getIsNullable(),
                                           startField,
                                           src.getPrecision(),
                                           endField,
                                           src.getScale());
            if (!static_cast<SQLInterval *>(result)->checkValid(diags))
              {
                *diags << DgSqlCode(-11152)
                       << DgInt0(src.getSQLType())
                       << DgInt1(colNumForDiags)
                       << DgString0("See previous error");
                result = NULL;
              }
          }
      }
      break;

    case tmudr::TypeInfo::BOOLEAN:
      result = new(heap) SQLBooleanNative(heap, src.getIsNullable());
      break;

    default:
      *diags << DgSqlCode(-11152)
             << DgInt0(src.getSQLType())
             << DgInt1(colNumForDiags)
             << DgString0("Invalid SQL Type code");
      break;
    }

  return result;
}

NAColumn *TMUDFInternalSetup::createNAColumnFromColumnInfo(
     const tmudr::ColumnInfo &src,
     int position,
     NAHeap *heap,
     ComDiagsArea *diags)
{
  NAType *newColType = createNATypeFromTypeInfo(src.getType(),
                                                position,
                                                heap,
                                                diags);
  if (newColType == NULL)
    return NULL;

  return new(heap) NAColumn(
       src.getColName().data(),
       position,
       newColType,
       heap);
}

NAColumnArray * TMUDFInternalSetup::createColumnArrayFromTableInfo(
     const tmudr::TableInfo &tableInfo,
     TableMappingUDF * tmudfNode,
     NAHeap *heap,
     ComDiagsArea *diags)
{
  NAColumnArray *result = new(heap) NAColumnArray(heap);
  int numColumns = tableInfo.getNumColumns();

  for (int i=0; i<numColumns; i++)
    {
      const tmudr::ColumnInfo &colInfo = tableInfo.getColumn(i);
      NAColumn *newCol = NULL;
      const tmudr::ProvenanceInfo &provenance = colInfo.getProvenance();

      if (provenance.isFromInputTable())
        {
          // the output column is passed through from an input
          // column

          const NAColumn *ic =
            tmudfNode->getChildInfo(
                 provenance.getInputTableNum())->getInputTabCols().getColumn(
                      provenance.getInputColumnNum());
          const char *newColName = colInfo.getColName().data();

          // unless specified, use the input column name
          if (!newColName || strlen(newColName) == 0)
            newColName = ic->getColName();

          // use type and heading from the input column when
          // creating the descriptor of the output column
          newCol = new(heap) NAColumn(
               newColName,
               i,
               ic->getType()->newCopy(heap),
               heap,
               NULL,
               USER_COLUMN,
               COM_NO_DEFAULT,
               NULL,
               const_cast<char *>(ic->getHeading()));
        }
      else
        {
          char defaultName[30];
          const char *usedColName;
          NAType *newColType = createNATypeFromTypeInfo(colInfo.getType(),
                                                        i,
                                                        heap,
                                                        diags);

          if (newColType == NULL)
            return NULL;

          usedColName = colInfo.getColName().data();

          if (usedColName[0] == 0)
            {
              // no name specified by UDF writer, make one up
              snprintf(defaultName, 30, "output_%d", i);
              usedColName = defaultName;
            }

          newCol = new(heap) NAColumn(
               usedColName,
               i,
               newColType,
               heap);
        }

      result->insert(newCol);
    }

  return result;
}

NABoolean TMUDFInternalSetup::createConstraintsFromConstraintInfo(
     const tmudr::TableInfo &tableInfo,
     TableMappingUDF * tmudfNode,
     NAHeap *heap)
{
  int numConstraints = tableInfo.getNumConstraints();

  for (int c=0; c<tableInfo.getNumConstraints(); c++)
    switch(tableInfo.getConstraint(c).getType())
      {
      case tmudr::ConstraintInfo::CARDINALITY:
        {
          const tmudr::CardinalityConstraintInfo &cc =
            static_cast<const tmudr::CardinalityConstraintInfo &>(
                 tableInfo.getConstraint(c));
          CardConstraint *ccItem = new(heap)
            CardConstraint(cc.getMinNumRows(),
                           cc.getMaxNumRows());

          // attach it to the group attributes
          tmudfNode->getGroupAttr()->addConstraint(ccItem);
        }
        break;

      case tmudr::ConstraintInfo::UNIQUE:
        {
          const tmudr::UniqueConstraintInfo &uc =
            static_cast<const tmudr::UniqueConstraintInfo &>(
                 tableInfo.getConstraint(c));
          const ValueIdList &udfOutputCols =
            tmudfNode->getProcOutputParamsVids();
          ValueIdSet uniqueValSet;
          int numUniqueCols = uc.getNumUniqueColumns();

          // translate the ordinals of the unique cols into ValueIds
          for (int c=0; c<numUniqueCols; c++)
            uniqueValSet += udfOutputCols[uc.getUniqueColumn(c)];

          // make a new ItemExpr constraint expression from the ValueIdSet
          UniqueOptConstraint *ucItem = new(heap)
            UniqueOptConstraint(uniqueValSet);


          // attach it to the group attributes
          tmudfNode->getGroupAttr()->addConstraint(ucItem);
        }
        break;

      default:
        TMUDFDllInteraction::processReturnStatus(
             tmudr::UDRException(
                  38900,
                  "Encountered invalid constraint type after describeConstraints(): %d",
                  static_cast<int>(tableInfo.getConstraint(c).getType())),
             tmudfNode);
        return FALSE;
      }

  return TRUE;
}

tmudr::UDRPlanInfo *TMUDFInternalSetup::createUDRPlanInfo(
     tmudr::UDRInvocationInfo *invocationInfo,
     int planNum)
{
  tmudr::UDRPlanInfo *result = new tmudr::UDRPlanInfo(invocationInfo, planNum);

  // register the object for later deletion, whether this plan got
  // selected or not and whether we had an error or not
  CmpCommon::context()->addPlanInfo(result);

  return result;
}

void TMUDFInternalSetup::setOffsets(tmudr::UDRInvocationInfo *invocationInfo,
                                    ExpTupleDesc *paramTupleDesc,
                                    ExpTupleDesc *outputTupleDesc,
                                    ExpTupleDesc **inputTupleDescs)
{
  if (paramTupleDesc)
    {
      CMPASSERT(invocationInfo->getFormalParameters().getNumColumns() ==
                paramTupleDesc->numAttrs());
      // set record length, note that formal params will be copied
      // to actual parameters below
      invocationInfo->nonConstActualParameters().setRecordLength(
           paramTupleDesc->tupleDataLength());
      for (int p=0; p<invocationInfo->getFormalParameters().getNumColumns(); p++)
        {
          Attributes *attr = paramTupleDesc->getAttr(p);

          invocationInfo->nonConstFormalParameters().getColumn(p).getType().setOffsets(
               attr->getNullIndOffset(),
               attr->getVCLenIndOffset(),
               attr->getOffset());
        }
    }
  else
    {
      CMPASSERT(invocationInfo->getFormalParameters().getNumColumns() == 0);
      invocationInfo->nonConstActualParameters().setRecordLength(0);
    }

  // As we move from compile time to runtime, replace the actual
  // parameter list with the formal parameter list, since we
  // can expect the actual parameters at runtime to have the
  // types of the formal parameters. We should not access
  // formal parameters at runtime.

  while (invocationInfo->par().getNumColumns() > 0)
    invocationInfo->nonConstActualParameters().deleteColumn(0);

  while (invocationInfo->getFormalParameters().getNumColumns() > 0)
    {
      invocationInfo->nonConstActualParameters().addColumn(
           invocationInfo->nonConstFormalParameters().getColumn(0));
      invocationInfo->nonConstFormalParameters().deleteColumn(0);
    }

  tmudr::TableInfo &ot = invocationInfo->out();

  if (outputTupleDesc)
    {
      CMPASSERT((outputTupleDesc == NULL &&
                 ot.getNumColumns() == 0) ||
                (ot.getNumColumns() == outputTupleDesc->numAttrs()));
      ot.setRecordLength(outputTupleDesc->tupleDataLength());
      for (int oc=0; oc<ot.getNumColumns(); oc++)
        {
          tmudr::ColumnInfo &colInfo = ot.getColumn(oc);
          Attributes *attr = outputTupleDesc->getAttr(oc);

          colInfo.getType().setOffsets(attr->getNullIndOffset(),
                                       attr->getVCLenIndOffset(),
                                       attr->getOffset());
        }
    }
  else
    {
      CMPASSERT(ot.getNumColumns() == 0);
      ot.setRecordLength(0);
    }

  for (int i=0; i<invocationInfo->getNumTableInputs(); i++)
    {
      tmudr::TableInfo &it = invocationInfo->inputTableInfo_[i];
      ExpTupleDesc *inputTupleDesc = inputTupleDescs[i];

      if (inputTupleDesc)
        {
          CMPASSERT(it.getNumColumns() == inputTupleDesc->numAttrs());
          it.setRecordLength(inputTupleDesc->tupleDataLength());
          for (int ic=0; ic<it.getNumColumns(); ic++)
            {
              tmudr::ColumnInfo &colInfo = it.getColumn(ic);
              Attributes *attr = inputTupleDesc->getAttr(ic);

              colInfo.getType().setOffsets(attr->getNullIndOffset(),
                                           attr->getVCLenIndOffset(),
                                           attr->getOffset());
            }
        }
      else
        {
          CMPASSERT(it.getNumColumns() == 0);
          it.setRecordLength(0);
        }
    }
}


void TMUDFInternalSetup::deleteUDRInvocationInfo(tmudr::UDRInvocationInfo *toDelete)
{
  // sorry, I'm your friend, but I'll have to terminate you now
  delete toDelete;
}

void TMUDFInternalSetup::deleteUDRPlanInfo(tmudr::UDRPlanInfo *toDelete)
{
  // sorry, I'm your friend, but I'll have to terminate you now
  delete toDelete;
}

// also source in the methods defined in sqludr.cpp
#include "sqludr.cpp"
