//**********************************************************************
// @@@ 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:         NAroutine.cpp
* Description:  SQL compiler representation of  SP routine metadata
* Created:      5/3/2000
* Language:     C++
*
*
**************************************************************************
*/
#include "BaseTypes.h"
#include "TrafDDLdesc.h"
#include "BindWA.h"
#include "NAType.h"
#include "NumericType.h"
#include "CharType.h"
#include "DatetimeType.h" 
#include "ComSmallDefs.h"
#include "CmpCommon.h"
#include "UdrErrors.h"
#include "NARoutineDB.h"
#include "NARoutine.h"
#include "SchemaDB.h"
#include "str.h"
#include "hs_util.h"
#include "LmJavaSignature.h"
#include "CmUtil.h"
#include "NATableSt.h"
#include "CmpMain.h"
#include "Globals.h"
#include "Context.h"
#include "ComUser.h"
#include "CmpSeabaseDDL.h"

// -----------------------------------------------------------------------
// Copy a string.  A null terminated buffer is returned.
// -----------------------------------------------------------------------
char *UDRCopyString ( const ComString &sourceString, CollHeap *heap )
{
  char *string = new(heap)char [sourceString.length()+1];
  str_cpy_all ( string
		, sourceString.data()
		, sourceString.length()+1
	      );
  return string;
} // UDRCopyString



NARoutine::NARoutine (CollHeap *heap) 
    : name_                   ("", heap)
    , extRoutineName_         (NULL) // ExtendedQualName *
    , extActionName_          (NULL) // ExtendedQualName * - Empty if not an action.
    , intActionName_          (NULL) // ComObjectName * - Empty if not an action.
    , language_               (COM_UNKNOWN_ROUTINE_LANGUAGE)
    , UDRType_                (COM_UNKNOWN_ROUTINE_TYPE)
    , sqlAccess_              (COM_UNKNOWN_ROUTINE_SQL_ACCESS)
    , transactionAttributes_  (COM_UNKNOWN_ROUTINE_TRANSACTION_ATTRIBUTE)
    , maxResults_             (0)
    , stateAreaSize_          (0)
    , externalFile_           ("", heap)
    , externalPath_           ("", heap)
    , externalName_           ("", heap)
    , librarySqlName_         (NULL)
    , signature_              ("", heap)
    , paramStyle_             (COM_UNKNOWN_ROUTINE_PARAM_STYLE)
    , paramStyleVersion_      (1)
    , isDeterministic_        (FALSE)
    , isCallOnNull_           (TRUE)
    , isIsolate_              (TRUE)
    , externalSecurity_       (COM_ROUTINE_EXTERNAL_SECURITY_INVOKER)
    , isExtraCall_            (FALSE)
    , hasOutParams_           (FALSE)
    , redefTime_              (0)
    , lastUsedTime_           (0)
    , routineSecKeySet_       (heap)
    , passThruDataNumEntries_ (0)
    , passThruData_           (NULL)
    , passThruDataSize_       (NULL)
    , udfFanOut_              (1)
    , uecValues_              (heap, 0)
    , isUniversal_            (FALSE)
    , actionPosition_         (-1)
    , executionMode_          (COM_ROUTINE_SAFE_EXECUTION)
    , objectUID_              (0)
    , dllName_                ("", heap)
    , dllEntryPoint_          ("", heap)
    , comRoutineParallelism_  ("NO", heap)
    , sasFormatWidth_         ("", heap)
    , systemName_             ("", heap)
    , dataSource_             ("", heap)
    , fileSuffix_             ("", heap)
    , schemaVersionOfRoutine_ (COM_VERS_UNKNOWN)
    , objectOwner_            (0)
    , schemaOwner_            (0)
    , privInfo_               (NULL)
    , heap_                   (heap)
{
}


// This is an empty constructor, with only the name specified
// It is meant for use with TMUDF code where we want to fake the
// presence of a TMUDF in metadata, for example with predefined
// table mapping functions, where the metadata is all determined
// by the compiler interface.

NARoutine::NARoutine (  const QualifiedName &name
		      , CollHeap            *heap
                     ) 	
    : name_                   (name, heap)
    , hashKey_                (name, heap) 
    , language_               (COM_LANGUAGE_C)
    , UDRType_                (COM_TABLE_UDF_TYPE)
    , sqlAccess_              (COM_NO_SQL)
    , transactionAttributes_  (COM_UNKNOWN_ROUTINE_TRANSACTION_ATTRIBUTE)
    , maxResults_             (0)
    , stateAreaSize_          (0)
    , externalFile_           ("", heap)
    , externalPath_           ("", heap)
    , externalName_           ("", heap)
    , librarySqlName_         (NULL)
    , signature_              ("", heap)
    , paramStyle_             (COM_STYLE_SQLROW)
    , paramStyleVersion_      (COM_ROUTINE_PARAM_STYLE_VERSION_1)
    , isDeterministic_        (1)
    , isCallOnNull_           (1)
    , isIsolate_              (0) // Trusted UDR like FastExtract
    , externalSecurity_       (COM_ROUTINE_EXTERNAL_SECURITY_INVOKER)
    , isExtraCall_            (1)
    , hasOutParams_           (FALSE)
    , redefTime_              (0)
    , lastUsedTime_           (0)
    , routineSecKeySet_       (heap)
    , passThruDataNumEntries_ (0)
    , passThruData_           (NULL)
    , passThruDataSize_       (NULL)
    , udfFanOut_              (1)
    , uecValues_              (heap,0)
    , isUniversal_            (0)
    , actionPosition_         (-1)
    , executionMode_          (COM_ROUTINE_SAFE_EXECUTION)
    , objectUID_              (0)
    , dllName_                ("", heap)
    , dllEntryPoint_          ("", heap)
    , comRoutineParallelism_  ("", heap)
    , sasFormatWidth_         ("", heap)
    , systemName_             ("", heap)
    , dataSource_             ("", heap)
    , fileSuffix_             ("", heap)
    , schemaVersionOfRoutine_ (COM_VERS_2500)
    , objectOwner_            (0)
    , schemaOwner_            (0)
    , privInfo_               (NULL)
    , heap_(heap)
{
  CollIndex colCount = 0;
  NAColumn *newCol = NULL;
  NAType   *newColType = NULL;
  extRoutineName_ = new (heap) ExtendedQualName( name_, heap );
  extActionName_  = new (heap) NAString(heap);
  intActionName_  = new (heap) ComObjectName(heap);
  params_         = new (heap) NAColumnArray(heap);
  inParams_       = new (heap) NAColumnArray(heap);
  outParams_      = new (heap) NAColumnArray(heap);

  // Construct the CostVectors
  // CQDs are checked at Bind time.
  Int32 initCpuCost = -1;
  Int32 initIOCost = -1;
  Int32 initMsgCost = -1;

  CostScalar initialCpuCost( initCpuCost);
  CostScalar initialIOCost( initIOCost);
  CostScalar initialMsgCost( initMsgCost);

  initialRowCost_.setCPUTime( initCpuCost < 0 ? csMinusOne : initialCpuCost);
  initialRowCost_.setIOTime( initIOCost < 0 ? csMinusOne : initialIOCost);
  initialRowCost_.setMSGTime( initMsgCost < 0 ? csMinusOne : initialMsgCost);

  Int32 normCpuCost = -1;
  Int32 normIOCost = -1;
  Int32 normMsgCost = -1;

  CostScalar normalCpuCost( normCpuCost);
  CostScalar normalIOCost( normIOCost);
  CostScalar normalMsgCost( normMsgCost);

  normalRowCost_.setCPUTime( normCpuCost < 0 ? csMinusOne  : normalCpuCost);
  normalRowCost_.setIOTime( normIOCost < 0 ? csMinusOne  : normalIOCost);
  normalRowCost_.setMSGTime( normMsgCost < 0 ? csMinusOne  : normalMsgCost);

  // this is for prototyping only
  for (CollIndex currentCol=0; currentCol<colCount; currentCol++)
  {
     // Create the new NAType.
    newColType = new (heap) SQLVarChar (heap, 255
                                        , 1
                                        , FALSE
					, FALSE /*not caseinsensitive, for now*/
                                        , CharInfo::ISO88591
                                        , CharInfo::DefaultCollation
                                        , CharInfo::COERCIBLE
                                        , CharInfo::ISO88591
                                      );

    ComColumnDirection colDirection = COM_INPUT_COLUMN;

    NAString nameStr("pattern");
    NAString empStr(" ");
    
    // Create the new NAColumn and insert it into the NAColumnArray
    newCol = new (heap) NAColumn ( (char *)nameStr.data()
				   , currentCol +1
				   , newColType
				   , heap
				   , NULL   // NATable *
				   , USER_COLUMN
				   , COM_NO_DEFAULT
				   , NULL   // default value
				   , NULL
				   , FALSE
				   , FALSE // addedColumn
				   , colDirection
				   , FALSE
				   , NULL// (char *) ucol->routineParamType
				 );
	
   
      inParams_->insert (newCol);
      params_->insert (newCol );
  } // for

  passThruDataNumEntries_ = 0;
  passThruData_ = NULL;
  passThruDataSize_ = NULL;

  // Copy privilege information
  heapSize_ = (heap ? heap->getTotalSize() : 0);
} // NARoutine

NARoutine::NARoutine (const NARoutine &old, CollHeap *h)
    : name_                   (old.name_, h)
    , hashKey_                (old.hashKey_, h)
    , language_               (old.language_)
    , UDRType_                (old.UDRType_)
    , sqlAccess_              (old.sqlAccess_)
    , transactionAttributes_  (old.transactionAttributes_)
    , maxResults_             (old.maxResults_)
    , externalFile_           (old.externalFile_, h)
    , externalPath_           (old.externalPath_, h)
    , externalName_           (old.externalName_, h)
    , signature_              (old.signature_, h)
    , librarySqlName_         (old.librarySqlName_, h)
    , paramStyle_             (old.paramStyle_)
    , paramStyleVersion_      (old.paramStyleVersion_)
    , isDeterministic_        (old.isDeterministic_)
    , isCallOnNull_           (old.isCallOnNull_)
    , isIsolate_              (old.isIsolate_)
    , externalSecurity_       (old.externalSecurity_)
    , isExtraCall_            (old.isExtraCall_)
    , hasOutParams_           (old.hasOutParams_)
    , redefTime_              (old.redefTime_)
    , lastUsedTime_           (old.lastUsedTime_)
    , routineSecKeySet_       (h)
    , isUniversal_            (old.isUniversal_)
    , executionMode_          (old.getExecutionMode())
    , objectUID_              (old.objectUID_)
    , stateAreaSize_          (old.stateAreaSize_)
    , dllName_                (old.dllName_, h)
    , dllEntryPoint_          (old.dllEntryPoint_, h)
    , comRoutineParallelism_  (old.comRoutineParallelism_)
    , sasFormatWidth_         (old.sasFormatWidth_, h)
    , systemName_             (old.systemName_, h)
    , dataSource_             (old.dataSource_, h)
    , fileSuffix_             (old.fileSuffix_, h)
    , initialRowCost_	      (old.initialRowCost_)
    , normalRowCost_	      (old.normalRowCost_)
    , udfFanOut_              (old.udfFanOut_)
    , passThruDataNumEntries_ (old.passThruDataNumEntries_)
    , uecValues_              (old.uecValues_, h)
    , actionPosition_         (old.actionPosition_)
    , schemaVersionOfRoutine_ (old.schemaVersionOfRoutine_)
    , objectOwner_            (0)
    , schemaOwner_            (0) 
    , privInfo_               (NULL)
    , heap_                   (h)
{
  extRoutineName_ = new (h) ExtendedQualName(*old.extRoutineName_, h);
  extActionName_  = new (h) NAString(*old.extActionName_, h);
  intActionName_  = new (h) ComObjectName(*old.intActionName_, h);
  inParams_       = new (h) NAColumnArray(*old.inParams_, h);
  outParams_      = new (h) NAColumnArray(*old.outParams_, h);
  params_         = new (h) NAColumnArray(*old.params_, h);

  if (old.passThruDataNumEntries_ EQU 0)
  {
    passThruDataNumEntries_ = 0;
    passThruData_           = NULL;
    passThruDataSize_       = NULL;
  }
  else
  {
    passThruData_ = new (h) char*[(UInt32) passThruDataNumEntries_];
    passThruDataSize_ = new (h) Int64[(UInt32) passThruDataNumEntries_];
    for (Int32 i=0; i<passThruDataNumEntries_; i++)
    {
      passThruDataSize_[i]=old.passThruDataSize_[i];
      passThruData_[i] = new (h) char[(UInt32)passThruDataSize_[i]+1];
      memcpy(passThruData_[i], old.passThruData_[i], (size_t)passThruDataSize_[i]);
      passThruData_[i][(size_t)passThruDataSize_[i]]=0;  // make sure to Null terminate the string
    }
  }

  routineSecKeySet_ = old.routineSecKeySet_;

  heapSize_ = (h ? h->getTotalSize() : 0);
}

NARoutine::NARoutine(const QualifiedName   &name,
           const TrafDesc    *routine_desc,
           BindWA                *bindWA,
           Int32                 &errorOccurred,
           NAMemory              *heap)
    : name_                   (name, heap)
    , hashKey_                (name, heap) 
    , language_               (routine_desc->routineDesc()->language)
    , UDRType_                (routine_desc->routineDesc()->UDRType)
    , sqlAccess_              (routine_desc->routineDesc()->sqlAccess)
    , transactionAttributes_  (routine_desc->routineDesc()->transactionAttributes)
    , maxResults_             (routine_desc->routineDesc()->maxResults)
    , stateAreaSize_          (routine_desc->routineDesc()->stateAreaSize)
    , externalFile_           ("", heap)
    , externalPath_           (routine_desc->routineDesc()->libraryFileName, heap)
    , externalName_           ("", heap)
    , librarySqlName_         (routine_desc->routineDesc()->librarySqlName, COM_UNKNOWN_NAME, FALSE, heap) //TODO
    , signature_              (routine_desc->routineDesc()->signature, heap)
    , paramStyle_             (routine_desc->routineDesc()->paramStyle)
    , paramStyleVersion_      (COM_ROUTINE_PARAM_STYLE_VERSION_1)
    , isDeterministic_        (routine_desc->routineDesc()->isDeterministic)
    , isCallOnNull_           (routine_desc->routineDesc()->isCallOnNull )
    , isIsolate_              (routine_desc->routineDesc()->isIsolate)
    , externalSecurity_       (routine_desc->routineDesc()->externalSecurity)
    , isExtraCall_            (FALSE) //TODO
    , hasOutParams_           (FALSE)
    , redefTime_              (0)  //TODO
    , lastUsedTime_           (0)
    , routineSecKeySet_       (heap)
    , passThruDataNumEntries_ (0)
    , passThruData_           (NULL)
    , passThruDataSize_       (0)
    , udfFanOut_              (1) // TODO
    , uecValues_              (heap,0)
    , isUniversal_            (0) // TODO
    , actionPosition_         (0) // TODO
    , executionMode_          (COM_ROUTINE_SAFE_EXECUTION)
    , objectUID_              (routine_desc->routineDesc()->objectUID)
    , dllName_                (routine_desc->routineDesc()->libraryFileName, heap)
    , dllEntryPoint_          (routine_desc->routineDesc()->externalName, heap)
    , sasFormatWidth_         ("", heap) //TODO
    , systemName_             ("", heap) // TODO
    , dataSource_             ("", heap) // TODO
    , fileSuffix_             ("", heap) // TODO
    , schemaVersionOfRoutine_ ((COM_VERSION)0) // TODO
    , objectOwner_            (routine_desc->routineDesc()->owner)
    , schemaOwner_            (routine_desc->routineDesc()->schemaOwner)
    , privInfo_               (NULL)
    , heap_(heap)
{
  char parallelism[5];
  CmGetComRoutineParallelismAsLit(routine_desc->routineDesc()->parallelism, parallelism);
  comRoutineParallelism_ = ((char *)parallelism);

  if (paramStyle_ == COM_STYLE_JAVA_CALL)
  {
    NAString extName(routine_desc->routineDesc()->externalName);
    size_t pos=extName.last('.');
    externalName_ = extName(pos+1, (extName.length()-pos-1)); // method_name
    externalFile_ = extName.remove (pos); // package_name.class_name 
  }
  else
  {
    externalName_ = routine_desc->routineDesc()->externalName;
    if (language_ == COM_LANGUAGE_C ||
        language_ == COM_LANGUAGE_CPP)
      {
        // Split the fully-qualified DLL name into a directory name and
        // simple file name
        ComUInt32 len = dllName_.length();
        if (len > 0)
          {
            size_t lastSlash = dllName_.last('/');
            if (lastSlash == NA_NPOS)
              {
                // No slash was found
                externalPath_ = ".";
                externalFile_ = dllName_;
              }
            else
              {
                // A slash was found. EXTERNAL PATH is everything before the
                // slash. EXTERNAL FILE is everything after.
                externalPath_ = dllName_;
                externalPath_.remove(lastSlash, len - lastSlash);
                externalFile_ = dllName_;
                externalFile_.remove(0, lastSlash + 1);
              }
          }
      } // if (len > 0)
  }

  ComSInt32 colCount = routine_desc->routineDesc()->paramsCount;
  NAColumn *newCol = NULL;
  NAType   *newColType = NULL;
  extRoutineName_ = new (heap) ExtendedQualName( name_, heap );
  extActionName_  = new (heap) NAString(heap);
  intActionName_  = new (heap) ComObjectName(heap);
  params_         = new (heap) NAColumnArray(heap);
  inParams_       = new (heap) NAColumnArray(heap);
  outParams_      = new (heap) NAColumnArray(heap);

  // to compute java signature
  ComFSDataType *paramType = new STMTHEAP ComFSDataType[colCount];
  ComUInt32     *subType   = new STMTHEAP ComUInt32    [colCount];
  ComColumnDirection *direction = new STMTHEAP ComColumnDirection[colCount] ;
  //
  // Construct the CostVectors
  // CQDs are checked at Bind time.
  Int32 initCpuCost = -1;
  Int32 initIOCost = -1;
  Int32 initMsgCost = -1;

  CostScalar initialCpuCost( initCpuCost);
  CostScalar initialIOCost( initIOCost);
  CostScalar initialMsgCost( initMsgCost);

  initialRowCost_.setCPUTime( initCpuCost < 0 ? csMinusOne : initialCpuCost);
  initialRowCost_.setIOTime( initIOCost < 0 ? csMinusOne : initialIOCost);
  initialRowCost_.setMSGTime( initMsgCost < 0 ? csMinusOne : initialMsgCost);

  Int32 normCpuCost = -1;
  Int32 normIOCost = -1;
  Int32 normMsgCost = -1;

  CostScalar normalCpuCost( normCpuCost);
  CostScalar normalIOCost( normIOCost);
  CostScalar normalMsgCost( normMsgCost);

  normalRowCost_.setCPUTime( normCpuCost < 0 ? csMinusOne  : normalCpuCost);
  normalRowCost_.setIOTime( normIOCost < 0 ? csMinusOne  : normalIOCost);
  normalRowCost_.setMSGTime( normMsgCost < 0 ? csMinusOne  : normalMsgCost);

  TrafDesc *params_desc_list  = routine_desc->routineDesc()->params;
  TrafColumnsDesc *param_desc;

  int i = 0;
  while (params_desc_list)
  {
    param_desc = params_desc_list->columnsDesc();

    // Create the new NAType.
    if (NAColumn::createNAType(param_desc->columnsDesc(), (const NATable *)NULL, newColType, heap_))
      {
      errorOccurred = TRUE;
      return;
    }
    if (param_desc->colname && strncmp(param_desc->colname, "#:", 2) == 0)
    {
      memset(param_desc->colname, 0, 2);
    }

    ComParamDirection colDirection = param_desc->paramDirection();
    
    // Create the new NAColumn and insert it into the NAColumnArray
    newCol = new (heap) NAColumn(
         (const char *)UDRCopyString (param_desc->colname, heap)
         , param_desc->colnumber
         , newColType
         , heap
         , NULL   // NATable *
         , USER_COLUMN
         , COM_NO_DEFAULT
         , NULL   // default value
         , UDRCopyString("", heap) // TODO:heading can it have some value
         , param_desc->isUpshifted()
         , FALSE // addedColumn
         , (ComColumnDirection) colDirection
         , param_desc->isOptional()
         , (char *) COM_NORMAL_PARAM_TYPE_LIT
				 );
	
    // We have to check for INOUT in both the
    // if's below
    if ( COM_OUTPUT_PARAM == colDirection ||
	 COM_INOUT_PARAM == colDirection )
    {
      hasOutParams_ = TRUE;
      outParams_->insert (newCol);
      params_->insert (newCol );
    }

    if ( COM_INPUT_PARAM == colDirection ||
	 COM_INOUT_PARAM == colDirection )
    {
      inParams_->insert (newCol);
      if ( COM_INOUT_PARAM != colDirection )
      {
	params_->insert (newCol );
      }    // if not INOUT
    } // if IN or INOUT

    // Gather the param attributes for LM from the paramDefArray previously
    // populated and from the routineparamList generated from paramDefArray.
    paramType[i] = (ComFSDataType)newColType->getFSDatatype();
    subType[i] = 0;  // default

    // Set subType for special cases detected by LM
    switch ( paramType[i] )
    {
      case COM_SIGNED_BIN16_FSDT :
      case COM_SIGNED_BIN32_FSDT :
      case COM_SIGNED_BIN64_FSDT :
      case COM_UNSIGNED_BIN16_FSDT :
      case COM_UNSIGNED_BIN32_FSDT :
      case COM_UNSIGNED_BPINT_FSDT :
        {
          subType[i] = newColType->getPrecision();
          break;
        }

      case COM_DATETIME_FSDT :
      {
        switch ( ((DatetimeType *)newColType)->getSubtype() )
        {
        case DatetimeType::SUBTYPE_SQLDate : subType[i] = 1;      break;
        case DatetimeType::SUBTYPE_SQLTime : subType[i] = 2;      break;
        case DatetimeType::SUBTYPE_SQLTimestamp : subType[i] = 3; break;
        }
      }
    } // end switch paramType[i]

    direction[i] = (ComColumnDirection) colDirection;
    
    params_desc_list = params_desc_list->next;
    i++;
  } // for

  passThruDataNumEntries_ = 0;
  passThruData_ = NULL;
  passThruDataSize_ = NULL;

#define MAX_SIGNATURE_LENGTH 8193
  if ((language_ == COM_LANGUAGE_JAVA)&&(signature_.length() < 2))
    {
      // Allocate buffer for generated signature
      char sigBuf[MAX_SIGNATURE_LENGTH];
      sigBuf[0] = '\0';

      // If the syntax specified a signature, pass that to LanguageManager.
      char* optionalSig = NULL;
      ComBoolean isJavaMain =
        ((str_cmp_ne(externalName_.data(), "main") == 0) ? TRUE : FALSE);

      LmResult createSigResult;
      LmJavaSignature *lmSignature =  new (STMTHEAP) LmJavaSignature(NULL,
                                                                     STMTHEAP);
      createSigResult = lmSignature->createSig(paramType, subType, direction,
                                               colCount, COM_UNKNOWN_FSDT, 0,
                                               maxResults_, optionalSig, 
                                               isJavaMain, sigBuf,
                                               MAX_SIGNATURE_LENGTH,
                                               CmpCommon::diags());
      NADELETE(lmSignature, LmJavaSignature, STMTHEAP);


      // Lm returned error. Lm fills diags area
      if (createSigResult != LM_ERR)
        signature_ = sigBuf;
    }
    
     
  getPrivileges(routine_desc->routineDesc()->priv_desc);

  heapSize_ = (heap ? heap->getTotalSize() : 0);
}

NARoutine::~NARoutine()
{
  // Call deepDelete() on NAColumnArray's.  
  // The destructor does not do this.
  inParams_->deepDelete();
  outParams_->deepDelete();
  delete inParams_;
  delete outParams_;
  delete params_;    // Do not do a deepDelete() on params_ the
                     // elements are shared with in|outParams_.
  delete extRoutineName_;
  delete extActionName_;
  delete intActionName_;
  uecValues_.clear(); // delete all its elements.  
  if (passThruData_ NEQ NULL)
  {
    for (Int32 i = 0; i < passThruDataNumEntries_; i++)
      NADELETEBASIC(passThruData_[i], heap_); // Can't use NADELETEARRAY on C types.
    NADELETEBASIC(passThruData_, heap_);      // Can't use NADELETEARRAY on C types.
  }
  if (passThruDataSize_ NEQ NULL) // Use NADELETEARRAY for any 'new(heap)<class>[<size>]'
    NADELETEARRAY(passThruDataSize_, (UInt32)passThruDataNumEntries_, Int64, heap_);

  if (privInfo_)
   NADELETE(privInfo_, PrivMgrUserPrivs, heap_);
}

void NARoutine::setSasFormatWidth(NAString &width)
{
  sasFormatWidth_ = width;
}

// ----------------------------------------------------------------------------
// method: getPrivileges
//
// If authorization is enabled, set privs based on the passed in priv_desc
// and set up query invalidation (security) keys for the routine.
// ----------------------------------------------------------------------------
void NARoutine::getPrivileges(TrafDesc *priv_desc)
{
  if ( !CmpCommon::context()->isAuthorizationEnabled() || ComUser::isRootUserID())
  {
    privInfo_ = new(heap_) PrivMgrUserPrivs;
    privInfo_->setOwnerDefaultPrivs();
    return;
  }

  NAString privMDLoc = CmpSeabaseDDL::getSystemCatalogStatic();
  privMDLoc += ".\"";
  privMDLoc += SEABASE_PRIVMGR_SCHEMA;
  privMDLoc += "\"";
  PrivMgrCommands privInterface(privMDLoc.data(), CmpCommon::diags(),PrivMgr::PRIV_INITIALIZED);

  if (priv_desc == NULL)
  {
    privInfo_ = new(heap_) PrivMgrUserPrivs;

    CmpSeabaseDDL cmpSBD(STMTHEAP);
    if (cmpSBD.switchCompiler(CmpContextInfo::CMPCONTEXT_TYPE_META))
    {
      if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
        *CmpCommon::diags() << DgSqlCode( -4400 );

      return;
    }

    ComObjectType objectType = (UDRType_ == COM_PROCEDURE_TYPE ?
                                COM_STORED_PROCEDURE_OBJECT :
                                COM_USER_DEFINED_ROUTINE_OBJECT);

    std::vector <ComSecurityKey *>* secKeyVec = new(heap_) std::vector<ComSecurityKey *>;
    if (privInterface.getPrivileges(objectUID_, objectType,
                                    ComUser::getCurrentUser(), 
                                   *privInfo_, secKeyVec) != STATUS_GOOD)
    {
      NADELETE(privInfo_, PrivMgrUserPrivs, heap_);
      privInfo_ = NULL;
    }

    cmpSBD.switchBackCompiler();

    if (privInfo_)
    {
      for (std::vector<ComSecurityKey*>::iterator iter = secKeyVec->begin();
           iter != secKeyVec->end();
           iter++)
      {
        // Insertion of the dereferenced pointer results in NASet making
        // a copy of the object, and then we delete the original.
        routineSecKeySet_.insert(**iter);
          delete *iter;
      }
    }
  }
  else
  {
    // get roles granted to current user 
    // SQL_EXEC_GetRoleList returns the list of roles from the CliContext
    std::vector<int32_t> myRoles;
    Int32 numRoles = 0;
    Int32 *roleIDs = NULL;
    if (SQL_EXEC_GetRoleList(numRoles, roleIDs) < 0)
    {
      *CmpCommon::diags() << DgSqlCode(-1034);
      return;
    }

    // At this time we should have at least one entry in roleIDs (PUBLIC_USER)
    CMPASSERT (roleIDs && numRoles > 0);

    for (Int32 i = 0; i < numRoles; i++)
      myRoles.push_back(roleIDs[i]);

    privInfo_ = new (heap_) PrivMgrUserPrivs;
    privInfo_->initUserPrivs(myRoles, priv_desc, ComUser::getCurrentUser(),objectUID_, routineSecKeySet_);
  }
}

ULng32 NARoutineDBKey::hash() const
{ 
  return routine_.hash() ^ action_.hash(); 
}

ULng32 hashKey(const NARoutineDBKey &key)
{
  return key.hash();
}
// NARoutineDB member functions (NARoutine caching)
#define DEFAULT_ROUTINEDB_CACHE_SZ 20 // in MB

// NARoutineDB public member functions.
// ======================================
// Constructor
NARoutineDB::NARoutineDB(NAMemory *h) :
    heap_(h),
    routinesToDeleteAfterStatement_(h),
    cacheMetaData_(TRUE),
    metadata(""),
    currentCacheSize_(0),
    refreshCacheInThisStatement_(FALSE),                                
    entries_(0),
    highWatermarkCache_(0),                                      
    totalLookupsCount_(0),        
    totalCacheHits_(0),
    NAKeyLookup<NARoutineDBKey, NARoutine> (NARoutineDB_INIT_SIZE,
                                            NAKeyLookupEnums::KEY_INSIDE_VALUE,
                                            h)
{
  // Initial size.  Cannot use CQDs, since NARoutineDB is constructed as 
  // part of SchemaDB object.
  defaultCacheSize_ = DEFAULT_ROUTINEDB_CACHE_SZ*1024*1024; 
  maxCacheSize_ = defaultCacheSize_;
}

NABoolean NARoutineDB::cachingMetaData() 
{ 
  maxCacheSize_ = CmpCommon::getDefaultLong(ROUTINE_CACHE_SIZE);
  return cacheMetaData_ && maxCacheSize_; 
}

// ----------------------------------------------------------------------------
// method: moveRoutineToDeleteList
//
// This method removes the routine from the primary cache and adds it to the
// list of routines to delete after statement execution completes.
//
// cachedNARoutine is a pointer to an NARoutine entry
// key is a pointer to the routine key
// ----------------------------------------------------------------------------
void NARoutineDB::moveRoutineToDeleteList(NARoutine *cachedNARoutine, const NARoutineDBKey *key)
{  
  // routine is not cached, just return
  if (cachedNARoutine == NULL || !cachingMetaData())
    return;

  // Add pointer to the routine to the list that will  be deleted after the 
  // statement completes (to avoid affecting compile time)
  routinesToDeleteAfterStatement_.insert(cachedNARoutine);

  // The NARoutine in cache is dirty and needs to be removed.
  // Remove entry that the key is pointing to
  remove(key);

  // Adjust cache size
  if ((ULng32)cachedNARoutine->getSize() <= currentCacheSize_)
  {
    currentCacheSize_ -= cachedNARoutine->getSize();
    if (entries_>0) entries_--;
  }
  else
  {
    currentCacheSize_ = 0;
    entries_ = 0;
  }
}

// Cleanup NARoutine cache after the statement completes.  Remove entries 
// using LRU policy, if the cache has grown too large.  The approach here is 
// somewhat different from NATableDB caching, which deletes entries from the 
// NATable cache if the statement was DDL that may have affected the table 
// definition.   NATable caching also deletes tables from the cache at this 
// time for performance reasons.
void NARoutineDB::resetAfterStatement()
{
  // Delete 'dirty' NARoutine objects that were not deleted earlier 
  // to save compile-time performance.
  if (routinesToDeleteAfterStatement_.entries())
  {
    // Clear the list of tables to delete after statement
    routinesToDeleteAfterStatement_.clear();
  }

  if (entries())
  {
    // Reduce size of cache if it has grown too large.
    if (!enforceMemorySpaceConstraints())
      cacheMetaData_ = FALSE; // Disable cache if there is a problem.

    // Reset statement level flags
    refreshCacheInThisStatement_=FALSE;

    // Clear 'accessed in current statement' flag for all cached NARoutines.
    NAHashDictionaryIterator<NARoutineDBKey,NARoutine> iter (*this); 
    NARoutineDBKey *key;
    NARoutine      *routine;
    iter.getNext(key,routine);
    while(key) {
      routine->getAccessedInCurStmt() = FALSE; 
      iter.getNext(key,routine);
    }
  }
}

// ----------------------------------------------------------------------------
// method: free_entries_with_QI_key
//
// This method is sent a list of query invalidation keys.
// It looks through the list of routines to see if any of them need to be
// removed from cache because their definitions are no longer valid.
//
// numKeys - number of existing invalidation keys
// qiKeyArray - actual keys
// ----------------------------------------------------------------------------
void NARoutineDB::free_entries_with_QI_key(Int32 numKeys, SQL_QIKEY* qiKeyArray)
{
  NAHashDictionaryIterator<NARoutineDBKey,NARoutine> iter (*this);
  NARoutineDBKey *key;
  NARoutine *routine;
  iter.getNext(key,routine);
  while(key && routine)
  {
    // See if item should be removed
    if (qiCheckForInvalidObject(numKeys, qiKeyArray,
                                routine->getRoutineID(),
                                routine->getSecKeySet()))
      moveRoutineToDeleteList(routine, key);
    iter.getNext(key,routine);
  }
}

// ----------------------------------------------------------------------------
// method: removeNARoutine
//
// The method is called when DDL is performed against a routine making its 
// definition incorrect.
// It has a side affect of generating query invalidation keys that are 
// propagate to all the other processes that could have the routine stored 
// in cache.
// ----------------------------------------------------------------------------
void NARoutineDB::removeNARoutine2(QualifiedName &routineName, 
                                   ComQiScope qiScope, 
                                   Int64 objUID)
{

  NAHashDictionaryIterator<NARoutineDBKey,NARoutine> iter (*this); 
  NARoutineDBKey *key = NULL;
  NARoutine *cachedNARoutine = NULL;

  NASet<Int64> objectUIDs(CmpCommon::statementHeap(), 1);

  // If there are no items in cache, skip
  if (entries() > 0)
  {
    NASet<Int64> objectUIDs(CmpCommon::statementHeap(), 1);

    // iterate over all entries and remove the ones that match the name
    iter.reset();
    iter.getNext(key,cachedNARoutine);

    while(key && cachedNARoutine)
    {
      if (cachedNARoutine->getSqlName() == routineName)
      {
        objectUIDs.insert(cachedNARoutine->getRoutineID());
        moveRoutineToDeleteList(cachedNARoutine,key);
      }
      iter.getNext(key,cachedNARoutine);
    }
  }

  // clear out the other users' caches too.
  if (qiScope == REMOVE_FROM_ALL_USERS) 
  {
    // There are some scenarios where the affected object does not have an 
    // NARoutine cache entry.  However, other processes may have this routine
    // in their caches.  Go ahead and create an invalidation key 
    if (0 == objectUIDs.entries())
        objectUIDs.insert(objUID);

    Int32 numKeys = objectUIDs.entries();
    SQL_QIKEY qiKeys[numKeys];
    for (CollIndex i = 0; i < numKeys; i++)
    {
      qiKeys[i].ddlObjectUID = objectUIDs[i];
      qiKeys[i].operation[0] = 'O';
      qiKeys[i].operation[1] = 'R';
    }
    long retcode = SQL_EXEC_SetSecInvalidKeys(numKeys, qiKeys);
  }
}

// This method follows the same semantics as NATableDB::removeNATable
void NARoutineDB::removeNARoutine(QualifiedName &routineName, 
                                  ComQiScope qiScope, 
                                  Int64 objUID,
                                  NABoolean ddlXns, NABoolean atCommit)

{
  if ((ddlXns) &&
      (NOT atCommit))
    {
      CmpContext::DDLObjInfo ddlObj;
      ddlObj.ddlObjName = routineName.getQualifiedNameAsString();
      ddlObj.qiScope = qiScope;
      ddlObj.ot = COM_USER_DEFINED_ROUTINE_OBJECT;
      ddlObj.objUID = objUID;

      NABoolean found = FALSE;
      for (Lng32 i = 0;
           ((NOT found) && (i <  CmpCommon::context()->ddlObjsList().entries()));
           i++)
        {
          CmpContext::DDLObjInfo &ddlObjInList = 
            CmpCommon::context()->ddlObjsList()[i];
          if (ddlObj.ddlObjName == ddlObjInList.ddlObjName)
            found = TRUE;
        }

      removeNARoutine2(routineName, qiScope, objUID);

      if (NOT found)
        CmpCommon::context()->ddlObjsList().insert(ddlObj);
 
      return;
    }

  removeNARoutine2(routineName, qiScope, objUID);
}

// Find the NARoutine entry in the cache for 'key' or create it if not found.
// 1. Check for entry in cache.  
// 2. If it doesn't exist, return.
// 3. If it does exist, check to see if this is first time entry accessed.
// 4. If so, check to see if entry is dirty (obsolete).
// 5. If dirty, remove key and add to list to remove entry after statement 
//    completes.
// Note that BindWA is needed to be passed to this function so that we can
// use it with getRedefTime() is necessary.
NARoutine *NARoutineDB::get(BindWA *bindWA, const NARoutineDBKey *key)
{
  // Check cache to see if a cached NARoutine object exists
  NARoutine *cachedNARoutine =
    NAKeyLookup<NARoutineDBKey,NARoutine>::get(key);                    /* 1 */

  totalLookupsCount_++; // Statistics counter: number of lookups

  if (!cachedNARoutine || !cacheMetaData_) return NULL;                 /* 2 */

  totalCacheHits_++;    // Statistics counter: number of cache hits.

  // Record time that this NARoutine was obtained from cache for LRU.
  cachedNARoutine->setLastUsedTime(hs_getEpochTime());

  cachedNARoutine->getAccessedInCurStmt() = TRUE; 

  return cachedNARoutine;
}

// Insert NARoutine in NARoutineDB cache and update size.
void NARoutineDB::put(NARoutine *routine)
{
  if (cacheMetaData_ && maxCacheSize_)
  {
    routine->setLastUsedTime(hs_getEpochTime());
    insert(routine);  // This function returns void.

    entries_++;
    currentCacheSize_ += routine->getSize();
    if (currentCacheSize_ > highWatermarkCache_)
      highWatermarkCache_ = currentCacheSize_; // statistics counter
  }
}


// NARoutineDB private member functions.
// ======================================
// Check if cache size is within maximum allowed cache size.  If not,
// then remove entries in the cache based on the replacement policy,
// until the cache size drops below the allowed size.
// DO NOT CALL THIS ROUTINE IN THE MIDDLE OF A STATEMENT.
NABoolean NARoutineDB::enforceMemorySpaceConstraints()
{
  NABoolean retval = TRUE;

  // Set cache size to CQD setting.
  maxCacheSize_ = CmpCommon::getDefaultLong(ROUTINE_CACHE_SIZE)
                  * 1024 * 1024;

  // Check if cache size is within memory constraints
  if (currentCacheSize_ <= maxCacheSize_)
    return retval;

  // Need to reduce cache size

  // Loop through the list and attempt to remove the entries
  // that are least recently used (that is, that have the oldest
  // timestamps of when they were last used).  Do not allow the
  // number of times looped to exceed the number of entries in
  // cache.
  Lng32 loopCnt = 0, entries = this->entries();
  while (currentCacheSize_ > maxCacheSize_ && loopCnt++ < entries){
    // Find least recently used NARoutine in cache.
    NAHashDictionaryIterator<NARoutineDBKey,NARoutine> iter (*this); 
    NARoutineDBKey *key=0, *oldestKey=0;
    NARoutine      *routine=0, *oldestRoutine=0;
    Int64           oldestTime;

    iter.reset();
    iter.getNext(key,routine);
    if (key && routine) // This should always be true.
    {
      oldestTime = routine->getLastUsedTime();
      while(key)
      {
        // Check routine for last used time.  Save oldest.  Must use
        // '<=' so that oldestKey will get set first time through loop.
        if (routine && routine->getLastUsedTime() <= oldestTime)
        {
          oldestTime    = routine->getLastUsedTime();
          oldestKey     = key;
          oldestRoutine = routine;
        }
        iter.getNext(key, routine);
      }
      remove(oldestKey);
      currentCacheSize_ -= oldestRoutine->getSize();
      if (entries_>0) entries_--;
      delete oldestRoutine;
    }
    if ((ULng32) oldestRoutine->getSize() <= currentCacheSize_)
    {
      currentCacheSize_ -= oldestRoutine->getSize();
      if (entries_>0) entries_--;
    }
    else
    {
      currentCacheSize_ = 0;
      entries_ = 0;
    }
  }

  //return true indicating cache size is below maximum memory allowance.
  if (currentCacheSize_ > maxCacheSize_) retval = FALSE;
  return retval;
}

void NARoutineDB::flushCache()
{

  //if something is cached
  if(cacheMetaData_)
  {
    //set the flag to indicate cache is clear
    cacheMetaData_ = FALSE;

    NAHashDictionaryIterator<NARoutineDBKey,NARoutine> iter (*this); 
    NARoutineDBKey *key;
    NARoutine *routine;
    iter.getNext(key,routine);
    while(key && routine) 
    {
      remove(key);
      delete routine ;
      iter.getNext(key,routine);
    }

    routinesToDeleteAfterStatement_.clear();

    //set cache size to 0 to indicate nothing in cache
    currentCacheSize_ = 0;
    entries_ = 0;
    highWatermarkCache_ = 0;   // High watermark of currentCacheSize_  
    totalLookupsCount_ = 0;    // reset NARoutine entries lookup counter
    totalCacheHits_ = 0;       // reset cache hit counter
    replacementCursor_ = 0;
  }


}

void NARoutineDB::getCacheStats(NARoutineCacheStats & stats)
{
  stats.numLookups = totalLookupsCount_;
  stats.numCacheHits = totalCacheHits_;
  stats.currentCacheSize = currentCacheSize_;
  stats.highWaterMark = highWatermarkCache_;
  stats.maxCacheSize = maxCacheSize_;
  stats.numEntries =  entries_;    
}

//-----------------------------------------------------------------------
// NARoutineCacheStoredProcedure is a class that contains functions used by
// the NARoutineCache virtual table, whose purpose is to serve as an interface
// to the SQL/MX NARoutine cache statistics. This table is implemented as
// an internal stored procedure.
//-----------------------------------------------------------------------

SP_STATUS NARoutineCacheStatStoredProcedure::sp_InputFormat(SP_FIELDDESC_STRUCT *inputFieldFormat,
                                                            Lng32 numFields,
                                                            SP_COMPILE_HANDLE spCompileObj,
                                                            SP_HANDLE spObj,
                                                            SP_ERROR_STRUCT *error)
{
  if ( numFields != 2 )
    {
      //accepts 2 input columns
      error->error = arkcmpErrorISPWrongInputNum;
      strcpy(error->optionalString[0], "NARoutineCache");
      error->optionalInteger[0] = 2;
      return SP_FAIL;
    }
  
  //column as input parameter for ISP, specifiy cache of metadata or user context
  strcpy(&((inputFieldFormat++)->COLUMN_DEF[0]), "instance char(16)  not null");
  strcpy(&((inputFieldFormat++)->COLUMN_DEF[0]), "location char(16)  not null"); 
  return SP_SUCCESS;
}

SP_STATUS NARoutineCacheStatStoredProcedure::sp_NumOutputFields(
  Lng32 *numFields,
  SP_COMPILE_HANDLE spCompileObj,
  SP_HANDLE spObj,
  SP_ERROR_STRUCT *error)
{
  const Lng32 NUM_OF_OUTPUT = 6;

  *numFields = NUM_OF_OUTPUT;
  return SP_SUCCESS;
}

SP_STATUS NARoutineCacheStatStoredProcedure::sp_OutputFormat(
  SP_FIELDDESC_STRUCT *format,
  SP_KEYDESC_STRUCT keyFields[],
  Lng32 *numKeyFields,
  SP_HANDLE spCompileObj,
  SP_HANDLE spObj,
  SP_ERROR_STRUCT *error)
{
  strcpy(&((format++)->COLUMN_DEF[0]), "Num_lookups      INT UNSIGNED");
  strcpy(&((format++)->COLUMN_DEF[0]), "Num_cache_hits   INT UNSIGNED");
  strcpy(&((format++)->COLUMN_DEF[0]), "Num_entries      INT UNSIGNED");
  strcpy(&((format++)->COLUMN_DEF[0]), "Current_cache_size   INT UNSIGNED");
  strcpy(&((format++)->COLUMN_DEF[0]), "High_watermark   INT UNSIGNED");
  strcpy(&((format++)->COLUMN_DEF[0]), "Max_cache_size   INT UNSIGNED");

  return SP_SUCCESS;
}

SP_STATUS NARoutineCacheStatStoredProcedure::sp_ProcessRoutine(
  SP_PROCESS_ACTION action,
  SP_ROW_DATA inputData,
  SP_EXTRACT_FUNCPTR eFunc,
  SP_ROW_DATA outputData,
  SP_FORMAT_FUNCPTR fFunc,
  SP_KEY_VALUE keys,
  SP_KEYVALUE_FUNCPTR kFunc,
  SP_PROCESS_HANDLE *spProcHandle,
  SP_HANDLE spObj,
  SP_ERROR_STRUCT *error)
{
  if (action == SP_PROC_OPEN) {
    NARoutineCacheStatsISPIterator * it = new (GetCliGlobals()->exCollHeap()) 
      NARoutineCacheStatsISPIterator(inputData, eFunc, error,
                                     GetCliGlobals()->currContext()->getCmpContextInfo(), 
                                     GetCliGlobals()->exCollHeap());
    *spProcHandle = it;
    return SP_SUCCESS;
  }

  if (action == SP_PROC_FETCH) {
    NARoutineCacheStatsISPIterator* it = (NARoutineCacheStatsISPIterator *)(*spProcHandle);
    if (!it) {
      return SP_FAIL;
    }
    NARoutineCacheStats stats;
    if(!it->getNext(stats))
       return SP_SUCCESS;
    fFunc(0, outputData, sizeof(ULng32), &(stats.numLookups), 0);
    fFunc(1, outputData, sizeof(ULng32), &(stats.numCacheHits), 0);
    fFunc(2, outputData, sizeof(ULng32), &(stats.numEntries), 0);
    fFunc(3, outputData, sizeof(ULng32), &(stats.currentCacheSize), 0);
    fFunc(4, outputData, sizeof(ULng32), &(stats.highWaterMark), 0);
    fFunc(5, outputData, sizeof(ULng32), &(stats.maxCacheSize), 0);
    return SP_MOREDATA;
  }
  
  if (action == SP_PROC_CLOSE) {
    if (*spProcHandle)
      NADELETEBASIC((NARoutineCacheStatsISPIterator *)(*spProcHandle), GetCliGlobals()->exCollHeap());
    return SP_SUCCESS;
  }
  return SP_SUCCESS;
}

SP_STATUS NARoutineCacheStatStoredProcedure::sp_ProcessAction(
  SP_PROCESS_ACTION action,
  SP_ROW_DATA inputData,
  SP_EXTRACT_FUNCPTR eFunc,
  SP_ROW_DATA outputData,
  SP_FORMAT_FUNCPTR fFunc,
  SP_KEY_VALUE keys,
  SP_KEYVALUE_FUNCPTR kFunc,
  SP_PROCESS_HANDLE *spProcHandle,
  SP_HANDLE spObj,
  SP_ERROR_STRUCT *error)
{
  struct InfoStruct
  {
    ULng32 counter;
  };

  SP_STATUS status = SP_SUCCESS;
  InfoStruct *is = NULL;

  NARoutineDB * tableDB = ActiveSchemaDB()->getNARoutineActionDB();

  switch (action)
  {
  case SP_PROC_OPEN:
    is = new InfoStruct;
    is->counter = 0;
    *spProcHandle = is;
    break;

  case SP_PROC_FETCH:
    is = (InfoStruct*)(*spProcHandle);
    if (is == NULL )
    {
      status = SP_FAIL;
      break;
    }

    if (is->counter > 0) break;
    is->counter++;
    fFunc(0, outputData, sizeof(ULng32), &(tableDB->totalLookupsCount_), 0);
    fFunc(1, outputData, sizeof(ULng32), &(tableDB->totalCacheHits_), 0);
    fFunc(2, outputData, sizeof(ULng32), &(tableDB->entries_), 0);
    fFunc(3, outputData, sizeof(ULng32), &(tableDB->currentCacheSize_), 0);
    fFunc(4, outputData, sizeof(ULng32), &(tableDB->highWatermarkCache_), 0);
    fFunc(5, outputData, sizeof(ULng32), &(tableDB->maxCacheSize_), 0);
    status = SP_MOREDATA;
    break;

  case SP_PROC_CLOSE:
    delete (InfoStruct*) (*spProcHandle);
    break;
  }
  return status;
}

void NARoutineCacheStatStoredProcedure::Initialize(SP_REGISTER_FUNCPTR regFunc)
{
  regFunc("NAROUTINECACHE",
          sp_Compile,
          sp_InputFormat,
          0,
          sp_NumOutputFields,
          sp_OutputFormat,
          sp_ProcessRoutine,
          0,
	  CMPISPVERSION);
  regFunc("NAROUTINEACTIONCACHE",
          sp_Compile,
          sp_InputFormat,
          0,
          sp_NumOutputFields,
          sp_OutputFormat,
          sp_ProcessAction,
          0,
	  CMPISPVERSION);
}

//-----------------------------------------------------------------------
// NARoutineCacheDeleteStoredProcedure is a class that contains functions used
// to delete the contents of the  NARoutineCache virtual table. The delete 
// function is implemented as an internal stored procedure.
//-----------------------------------------------------------------------


SP_STATUS NARoutineCacheDeleteStoredProcedure::sp_Process(
  SP_PROCESS_ACTION action,
  SP_ROW_DATA inputData,
  SP_EXTRACT_FUNCPTR eFunc,
  SP_ROW_DATA outputData,
  SP_FORMAT_FUNCPTR fFunc,
  SP_KEY_VALUE keys,
  SP_KEYVALUE_FUNCPTR kFunc,
  SP_PROCESS_HANDLE *spProcHandle,
  SP_HANDLE spObj,
  SP_ERROR_STRUCT *error)
{
  struct InfoStruct
  {
    ULng32 counter;
  };

  SP_STATUS status = SP_SUCCESS;
  InfoStruct *is = NULL;
  NARoutineDB * routineDB = NULL;
  NARoutineDB * actionDB = NULL;

  switch (action)
  {
  case SP_PROC_OPEN:
    // No inputs to process
    is = new InfoStruct;
    is->counter = 0;
    *spProcHandle = is;
    break;

  case SP_PROC_FETCH:
    is = (InfoStruct*)(*spProcHandle);
    if (is == NULL )
    {
      status = SP_FAIL;
      break;
    }

    routineDB = ActiveSchemaDB()->getNARoutineDB();
    actionDB = ActiveSchemaDB()->getNARoutineActionDB();

    //clear out NARoutineCache
    if (routineDB)
    {
      routineDB->setCachingOFF();
      routineDB->setCachingON();
    }
    if (actionDB)
    {
      actionDB->setCachingOFF();
      actionDB->setCachingON();
    }
    break;

  case SP_PROC_CLOSE:
    delete (InfoStruct*) (*spProcHandle);
    break;
  }
  return status;
}

void NARoutineCacheDeleteStoredProcedure::Initialize(SP_REGISTER_FUNCPTR regFunc)
{
  regFunc("NAROUTINECACHEDELETE",
          sp_Compile,
          sp_InputFormat,
          0,
          sp_NumOutputFields,
          sp_OutputFormat,
          sp_Process,
          0,
	  CMPISPVERSION);
}

NARoutineCacheStatsISPIterator::NARoutineCacheStatsISPIterator(
     SP_ROW_DATA  inputData, SP_EXTRACT_FUNCPTR  eFunc, 
     SP_ERROR_STRUCT* error, const NAArray<CmpContextInfo*> & ctxs, 
     CollHeap * h)
: ISPIterator(ctxs, h)
{
  initializeISPCaches(inputData, eFunc, error, ctxs, 
                      contextName_, currCacheIndex_);
}


NABoolean NARoutineCacheStatsISPIterator::getNext(NARoutineCacheStats & stats)
{
   //Only for remote tdm_arkcmp with 0 context
   if(currCacheIndex_ == -1)
   {
     ActiveSchemaDB()->getNARoutineDB()->getCacheStats(stats);
     currCacheIndex_ = -2;
     return TRUE;
   }
   
   //fetch QueryCaches of all CmpContexts with name equal to contextName_
   if(currCacheIndex_ > -1 && currCacheIndex_ < ctxInfos_.entries())
   {
      if( !ctxInfos_[currCacheIndex_]->isSameClass(contextName_.data()) //current context name is not equal to contextName_
       && contextName_.compareTo("ALL", NAString::exact)!=0) //and contextName_ is not "ALL"
      {// go to next context in ctxInfos_
          currCacheIndex_++;
          return getNext(stats);
      }
      ctxInfos_[currCacheIndex_++]->getCmpContext()->getSchemaDB()->getNARoutineDB()->getCacheStats(stats);
      return TRUE;
   }
   //all entries of all caches are fetched, we are done!
   return FALSE;
}




