@@ -840,11 +840,12 @@ PrivStatus PrivMgrComponentPrivileges::grantPrivilege(
       // more items in the list fail and in cases of "ALL".                                             
       if (!componentOperations.nameExists(componentUID,operationName))
       {
-         *pDiags_ << DgSqlCode(-CAT_TABLE_DOES_NOT_EXIST_ERROR)
-                  << DgTableName(operationName.c_str());
+         *pDiags_ << DgSqlCode(-CAT_INVALID_COMPONENT_PRIVILEGE)
+                  << DgString0(operationName.c_str())
+                  << DgString1(componentName.c_str());
          return STATUS_ERROR;
       }
-      
+
       std::string operationCode;
       bool isSystemOperation = FALSE;
       std::string operationDescription;
//*****************************************************************************
// @@@ 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 @@@
//*****************************************************************************
#include "PrivMgrComponentPrivileges.h"

#include "PrivMgrDefs.h"  
#include "PrivMgrMD.h"
#include "PrivMgrMDTable.h"
#include "PrivMgrComponents.h"
#include "PrivMgrComponentOperations.h"
#include "PrivMgrRoles.h"

#include <string>
#include <cstdio>
#include <algorithm>
#include <vector>
#include "ComSmallDefs.h"

// sqlcli.h included because ExExeUtilCli.h needs it (and does not include it!)
#include "sqlcli.h"
#include "ExExeUtilCli.h"
#include "ComQueue.h"
#include "ComDiags.h"
#include "ComQueue.h"
// CmpCommon.h contains STMTHEAP declaration
#include "CmpCommon.h"
#include "CmpDDLCatErrorCodes.h"
#include "ComUser.h"

static bool isSQLDMLPriv(
   const int64_t componentUID,
   const std::string operationCode);

namespace ComponentPrivileges 
{

class DMLPrivData
{
public:
   int32_t                granteeID_;
   std::vector<int32_t>   roleIDs_;
   PrivObjectBitmap       DMLBitmap_;
   bool                   managePrivileges_;
};

// *****************************************************************************
// * Class:        MyRow
// * Description:  This class represents a row in the COMPONENT_PRIVILEGES table.
// *****************************************************************************
class MyRow : public PrivMgrMDRow
{
public:
// -------------------------------------------------------------------
// Constructors and destructors:
// -------------------------------------------------------------------
   MyRow(std::string tableName)
   : PrivMgrMDRow(tableName, COMPONENT_PRIVILEGES_ENUM),
     componentUID_(0),
     visited_(false)
   { };
   MyRow(const MyRow &other)
   : PrivMgrMDRow(other),
     visited_(false)
   {
      componentUID_ = other.componentUID_;              
      operationCode_ = other.operationCode_;
      granteeID_ = other.granteeID_;
      granteeName_ = other.granteeName_;
      grantorID_ = other.grantorID_;
      grantorName_ = other.grantorName_;
      grantDepth_ = other.grantDepth_;
   };
   virtual ~MyRow() {};

   bool operator==(const MyRow & other) const
   {
      return ( ( componentUID_ == other.componentUID_ ) &&
               ( operationCode_  == other.operationCode_ ) &&
               ( granteeID_  == other.granteeID_ ) &&
               ( grantorID_  == other.grantorID_ ) );
   }

   inline void clear() {componentUID_ = 0;};
    
   void describeGrant(
      const std::string &operationName,
      const std::string &componentName, 
      std::vector<std::string> & outlines); 

// -------------------------------------------------------------------
// Data Members:
// -------------------------------------------------------------------

//  From COMPONENT_PRIVILEGES
    int64_t            componentUID_;
    std::string        operationCode_;
    int32_t            granteeID_;
    std::string        granteeName_;
    int32_t            grantorID_;
    std::string        grantorName_;
    int32_t            grantDepth_;
    bool               visited_;
    
private: 
   MyRow();
  
};

// *****************************************************************************
// * Class:        MyTable
// * Description:  This class represents the COMPONENT_PRIVILEGES table.
// *                
// *****************************************************************************
class MyTable : public PrivMgrMDTable
{
public:
   MyTable(
      const std::string & tableName,
      ComDiagsArea * pDiags = NULL) 
   : PrivMgrMDTable(tableName,COMPONENT_PRIVILEGES_ENUM, pDiags),
     lastRowRead_(tableName)
    {};
    
   inline void clear() { lastRowRead_.clear(); };
      
   PrivStatus fetchDMLPrivInfo(
      const int32_t                granteeID,
      const std::vector<int32_t> & roleIDs,
      PrivObjectBitmap           & DMLBitmap,
      bool                       & hasManagePrivileges);
      
   PrivStatus fetchOwner(
      const int64_t componentUID,
      const std::string & operationCode,
      int32_t & grantee);    
   
   void getRowsForGrantee(
      const MyRow &baseRow,
      std::vector<MyRow> &masterRowList,
      std::set<size_t> &rowsToDelete);

   virtual PrivStatus insert(const PrivMgrMDRow & row);
   
   PrivStatus selectAllWhere(
      const std::string & whereClause,
      const std::string & orderByClause,
      std::vector<MyRow> & rows);
      
   virtual PrivStatus selectWhereUnique(
      const std::string & whereClause,
      PrivMgrMDRow & row);
      
   PrivStatus selectWhere(
      const std::string & whereClause,  
      std::vector<MyRow *> &rowList);
      
   void setRow(
      OutputInfo & cliInterface,
      PrivMgrMDRow & rowOut);
      
   void describeGrantTree(
      const int32_t grantorID,
      const std::string &operationName,
      const std::string &componentName,
      const std::vector<MyRow> &rows,
      std::vector<std::string> & outlines);

   int32_t findGrantor(
      int32_t currentRowID,
      const int32_t grantorID,
      const std::vector<MyRow> rows);

private:   
   MyTable();
   
   MyRow lastRowRead_;
   DMLPrivData userDMLPrivs_;
};
}//End namespace ComponentPrivileges
using namespace ComponentPrivileges;

// *****************************************************************************
//    PrivMgrComponentPrivileges methods
// *****************************************************************************
// -----------------------------------------------------------------------
// Construct a PrivMgrComponentPrivileges object for a new component operation.
// -----------------------------------------------------------------------
PrivMgrComponentPrivileges::PrivMgrComponentPrivileges(
   const std::string & metadataLocation,
   ComDiagsArea * pDiags)
: PrivMgr(metadataLocation,pDiags),
  fullTableName_(metadataLocation_ + "." + PRIVMGR_COMPONENT_PRIVILEGES),
  myTable_(*new MyTable(fullTableName_,pDiags)) 
{ };

// -----------------------------------------------------------------------
// Copy constructor
// -----------------------------------------------------------------------
PrivMgrComponentPrivileges::PrivMgrComponentPrivileges(const PrivMgrComponentPrivileges &other)
: PrivMgr(other),
  myTable_(*new MyTable(fullTableName_,pDiags_))
{
   fullTableName_ = other.fullTableName_;
}

// -----------------------------------------------------------------------
// Destructor.
// -----------------------------------------------------------------------
PrivMgrComponentPrivileges::~PrivMgrComponentPrivileges() 
{ 

   delete &myTable_;

}

// *****************************************************************************
// *                                                                           *
// * Function: PrivMgrComponentPrivileges::clear                               *
// *                                                                           *
// *    This function clears any cache associated with this object.            *
// *                                                                           *
// *****************************************************************************
void PrivMgrComponentPrivileges::clear()

{

MyTable &myTable = static_cast<MyTable &>(myTable_);

   myTable.clear();
   
}
//****************** End of PrivMgrComponentPrivileges::clear ******************


  
// *****************************************************************************
// *                                                                           *
// * Function: PrivMgrComponentPrivileges::describeComponentPrivileges         *
// *  calls selectAllWhere to get the list of privileges for the operation.    *
// *  Once list is generated, starts at the root (system grant to owner) and   *
// *  generates grant statements by traversing each branch based on grantor    *
// *  -> grantee relationship.                                                 *
// *                                                                           *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  componentUIDString               const std::string &                  In *
// *    used with operationCode to find wanted component privileges.           *
// *                                                                           *
// *  componentName                    const std::string &                  In *
// *    used for generate grant statement on the component.                    *
// *                                                                           *
// *  operationCode                    const std::string &                  In *
// *    used with componentUIDString to find wanted component privileges.      *
// *                                                                           *
// *  operationName                    const std::string &                  In *
// *     used for generate grant statement as granted operation.               *
// *                                                                           *
// *  outlines                         std::vector<std::string> &           Out*
// *      output generated GRANT statements to this array.                     *
// *****************************************************************************
// *                                                                           *
// * Returns: PrivStatus                                                       *
// *                                                                           *
// * STATUS_GOOD: Component privilege(s) were revoked                          *
// *           *: One or more component privileges were not revoked.           *
// *              A CLI error is put into the diags area.                      *
// *                                                                           *
// *****************************************************************************
PrivStatus PrivMgrComponentPrivileges::describeComponentPrivileges(
   const std::string & componentUIDString,
   const std::string & componentName,
   const std::string & operationCode, 
   const std::string & operationName,
   std::vector<std::string> & outlines) 
{
   // Get the list of all privileges granted to the component and component
   // operation
   std::string whereClause (" WHERE COMPONENT_UID = ");
   whereClause += componentUIDString;
   whereClause += " AND OPERATION_CODE = '";
   whereClause += operationCode;
   whereClause += "'";

   std::string orderByClause= "ORDER BY GRANTOR_ID, GRANTEE_ID, GRANT_DEPTH";

   std::vector<MyRow> rows;
   MyTable &myTable = static_cast<MyTable &>(myTable_);

   PrivStatus privStatus = myTable.selectAllWhere(whereClause,orderByClause,rows);

   // We should get at least 1 row back - the grant from the system to the 
   // component operation owner
   int32_t rowIndex = 0;
   if ((privStatus == STATUS_NOTFOUND) || 
        (rows.size() == 0) ||
        (rowIndex = myTable.findGrantor(0, SYSTEM_USER, rows) == -1))
   {
      std::string errorText("Unable to find any grants for operation ");
      errorText += operationName;
      errorText += " on component ";
      errorText += componentName;
      PRIVMGR_INTERNAL_ERROR(errorText.c_str());
      return STATUS_ERROR;
   }
     
   // Add the initial grant (system grant -> owner) to text (outlines)
   // There is only one system grant -> owner per component operation
   MyRow row = rows[rowIndex];
   row.describeGrant(operationName, componentName, outlines);

   // Traverse the base branch that starts with the owner and proceeds
   // outward.  In otherwords, describe grants where the grantee is the grantor.
   int32_t newGrantor = row.granteeID_;
   myTable.describeGrantTree(newGrantor, operationName, componentName, rows, outlines);   

   return STATUS_GOOD;
}
  
//****** End of PrivMgrComponentPrivileges::describeComponentPrivileges ********


// *****************************************************************************
// *                                                                           *
// * Function: PrivMgrComponentPrivileges::dropAll                             *
// *                                                                           *
// *    This function drops all component privileges.                          *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: PrivStatus                                                       *
// *                                                                           *
// *  STATUS_GOOD: All rows were deleted.                                      *
// * STATUS_ERROR: Execution failed. A CLI error is put into the diags area.   *
// *                                                                           *
// *****************************************************************************
PrivStatus PrivMgrComponentPrivileges::dropAll()

{

MyTable &myTable = static_cast<MyTable &>(myTable_);

std::string whereClause(" ");

   return myTable.deleteWhere(whereClause);

}
//**************** End of PrivMgrComponentPrivileges::dropAll ******************



// *****************************************************************************
// *                                                                           *
// * Function: PrivMgrComponentPrivileges::dropAllForComponent                 *
// *                                                                           *
// *    This function drops all component privileges associated with the       *
// *  specified component.                                                     *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <componentUIDString>            const std::string &             In       *
// *    is a string representation of the unique ID associated with the        *
// *    component.                                                             *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: PrivStatus                                                       *
// *                                                                           *
// *  STATUS_GOOD: All rows associated with the component were deleted.        *
// * STATUS_ERROR: Execution failed. A CLI error is put into the diags area.   *
// *                                                                           *
// *****************************************************************************
PrivStatus PrivMgrComponentPrivileges::dropAllForComponent(const std::string & componentUIDString)

{

MyTable &myTable = static_cast<MyTable &>(myTable_);

std::string whereClause("WHERE ");

   whereClause += "COMPONENT_UID = ";
   whereClause += componentUIDString.c_str();
   
   return myTable.deleteWhere(whereClause);

}
//*********** End of PrivMgrComponentPrivileges::dropAllForComponent ***********

// *****************************************************************************
// *                                                                           *
// * Function: PrivMgrComponentPrivileges::dropAllForOperation                 *
// *                                                                           *
// *    This function drops all component privileges associated with the       *
// *  specified component and operation.                                       *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <componentUIDString>            const std::string &             In       *
// *    is a string representation of the unique ID associated with the        *
// *    component.                                                             *
// *                                                                           *
// *  <operationCode>                 const std::string &             In       *
// *    is the two character code associated with the component operation.     *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: PrivStatus                                                       *
// *                                                                           *
// *  STATUS_GOOD: All rows associated with the component and operation        *
// *               were deleted.                                               *
// * STATUS_ERROR: Execution failed. A CLI error is put into the diags area.   *
// *                                                                           *
// *****************************************************************************
PrivStatus PrivMgrComponentPrivileges::dropAllForOperation(
   const std::string & componentUIDString,
   const std::string & operationCode) 
   
{

MyTable &myTable = static_cast<MyTable &>(myTable_);

std::string whereClause("WHERE ");

   whereClause += "COMPONENT_UID = ";
   whereClause += componentUIDString.c_str();
   whereClause += " AND OPERATION_CODE = '";
   whereClause += operationCode.c_str();
   whereClause += "'";
   
   return myTable.deleteWhere(whereClause);

}
//*********** End of PrivMgrComponentPrivileges::dropAllForOperation ***********



// *****************************************************************************
// *                                                                           *
// * Function: PrivMgrComponentPrivileges::dropAllForGrantee                   *
// *                                                                           *
// *    This function drops all component privileges that have been granted    *
// *  to the user specified as "granteeID".  If the grantee had the WGO then   *
// *  the branch of privileges started by granteeID are removed.               *
// *                                                                           *
// *  This code assumes that all roles have been revoked from the granteeID    *
// *  prior to being called.                                                   *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <granteeID>                     const int32_t                   In       *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: bool                                                             *
// *                                                                           *
// *  true:  grantees were dropped                                             *
// * false:  unexpected error occurred. Error is put into the diags area.      *
// *                                                                           *
// *****************************************************************************
bool PrivMgrComponentPrivileges::dropAllForGrantee(
  const int32_t granteeID)
{
   // Get the list of all privileges from component_privileges table
   // Skip rows granted by the system (-2)
   std::string whereClause (" WHERE GRANTOR_ID > 0");
   std::string orderByClause= " ORDER BY COMPONENT_UID, GRANTOR_ID, GRANTEE_ID, OPERATION_CODE, GRANT_DEPTH";

   MyTable &myTable = static_cast<MyTable &>(myTable_);
   std::vector<MyRow> masterRowList;

   PrivStatus privStatus = myTable.selectAllWhere(whereClause,orderByClause,masterRowList);
   if (privStatus == STATUS_ERROR)
     return false;

   // Create a list of indexes into the masterRowList where the granteeID is 
   // the target of one or more privileges
   std::vector<size_t> granteeRowList;
   for (size_t i = 0; i < masterRowList.size(); i++)
   {
      if (masterRowList[i].granteeID_ == granteeID)
         granteeRowList.push_back(i);
   }
   
   // if the granteeID has not been granted any privileges, we are done
   if (granteeRowList.size() == 0)
     return true;

   // Add the rows from granteeRowList to rowsToDelete list
   // If any privileges were granted WGO, also remove the branch.
   std::set<size_t> rowsToDelete;
   for (size_t i = 0; i < granteeRowList.size(); i++)
   {
      size_t baseIdx = granteeRowList[i];
      MyRow baseRow = masterRowList[baseIdx];

      // If grantDepth < 0, then WGO was specified, remove branch
      if (baseRow.grantDepth_ < 0)
        myTable.getRowsForGrantee(baseRow, masterRowList, rowsToDelete);
      masterRowList[baseIdx].visited_ = true;
      rowsToDelete.insert(baseIdx);
   }
   
   // delete all the rows in affected list into statements of 10 rows 
   if (rowsToDelete.size() > 0)
   {
      whereClause = "WHERE ";
      bool isFirst = true;
      size_t count = 0;
      for (std::set<size_t>::iterator it = rowsToDelete.begin(); it!= rowsToDelete.end(); ++it)
      {
         if (count > 20)
         {
            privStatus ==  myTable.deleteWhere(whereClause);
            if (privStatus == STATUS_ERROR)
              return false;
            whereClause = "WHERE ";
            isFirst = true;
            count = 0;
         }
         if (isFirst)
           isFirst = false;
         else
           whereClause += " OR ";
         size_t masterIdx = *it;
         MyRow row = masterRowList[masterIdx];

         const std::string componentUIDString = to_string((long long int)row.componentUID_);
         whereClause += "(component_uid = ";
         whereClause += componentUIDString.c_str();
         whereClause += " AND grantor_name = '";
         whereClause += row.grantorName_;
         whereClause += "' AND grantee_name = '";
         whereClause += row.granteeName_;
         whereClause += "' AND operation_code = '";
         whereClause += row.operationCode_;
         whereClause += "')";
         count++;
      }
      privStatus ==  myTable.deleteWhere(whereClause);
      if (privStatus == STATUS_ERROR)
        return false;
   }

   return true;
}





// *****************************************************************************
// *                                                                           *
// * Function: PrivMgrComponentPrivileges::getCount                            *
// *                                                                           *
// *    Returns the number of grants of component privileges.                  *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: int64_t                                                          *
// *                                                                           *
// *    Returns the number of grants of component privileges.                  *
// *                                                                           *
// *****************************************************************************
int64_t PrivMgrComponentPrivileges::getCount()
   
{
                                   
std::string whereClause(" ");   

int64_t rowCount = 0;   
MyTable &myTable = static_cast<MyTable &>(myTable_);

// set pointer in diags area
int32_t diagsMark = pDiags_->mark();

PrivStatus privStatus = myTable.selectCountWhere(whereClause,rowCount);

   if (privStatus != STATUS_GOOD)
      pDiags_->rewind(diagsMark);

      
   return rowCount;

}
//***************** End of PrivMgrComponentPrivileges::getCount ****************


// *****************************************************************************
// *                                                                           *
// * Function: PrivMgrComponentPrivileges::getSQLDMLPrivileges                 *
// *                                                                           *
// *    Returns the SQL_OPERATION privileges associated with DML privileges    *
// * for the specified authorization ID.                                       *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <granteeID>                     const int32_t                   In       *
// *    is the authorization ID of the grantee.                                *
// *                                                                           *
// *  <roleIDs>                       const std::vector<int32_t> &    In       *
// *    is a list of roleIDs granted to the grantee.                           *
// *                                                                           *
// *  <DMLBitmap>                     PrivObjectBitmap &              In       *
// *    passes back the system-level DML privileges granted to the grantee.    *
// *                                                                           *
// *  <hasManagePrivileges>           bool &                          In       *
// *    passes back if the user has MANAGE_PRIVILEGES authority.               *
// *                                                                           *
// *****************************************************************************
void PrivMgrComponentPrivileges::getSQLDMLPrivileges(
   const int32_t                granteeID,
   const std::vector<int32_t> & roleIDs,
   PrivObjectBitmap           & DMLBitmap,
   bool                       & hasManagePrivileges)

{
                                   
MyTable &myTable = static_cast<MyTable &>(myTable_);

// set pointer in diags area
int32_t diagsMark = pDiags_->mark();

PrivStatus privStatus = myTable.fetchDMLPrivInfo(granteeID,roleIDs,DMLBitmap,
                                                 hasManagePrivileges);

   if (privStatus != STATUS_GOOD)
      pDiags_->rewind(diagsMark);

}
//************ End of PrivMgrComponentPrivileges::getSQLDMLPrivileges **********


   
// *****************************************************************************
// *                                                                           *
// * Function: PrivMgrComponentPrivileges::grantExists                         *
// *                                                                           *
// *    Determines if a specific authorization ID (granteee) has been granted  *
// * a component privilege by a specific authorization ID (grantor).           *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <componentUIDString>            const std::string &             In       *
// *    is the component unique ID.                                            *
// *                                                                           *
// *  <operationCode>                 const std::string &             In       *
// *    is the two character code associated with the component operation.     *
// *                                                                           *
// *  <grantorID>                     const int32_t                   In       *
// *    is the authorization ID of the grantor.                                *
// *                                                                           *
// *  <granteeID>                     const int32_t                   In       *
// *    is the authorization ID of the grantee.                                *
// *                                                                           *
// *  <grantDepth>                    int32_t &                       In       *
// *    passes back the grant depth if the component privilege grant exists.   *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: bool                                                             *
// *                                                                           *
// * true: Component privilege has been granted to grantee by grantor.         *
// * false: Component privilege has not been granted to grantee by grantor,    *
// * or there was an error trying to read from the COMPONENT_PRIVILEGES table. *
// *                                                                           *
// *****************************************************************************
bool PrivMgrComponentPrivileges::grantExists(
   const std::string componentUIDString,
   const std::string operationCode,
   const int32_t grantorID,
   const int32_t granteeID,
   int32_t & grantDepth) 

{

MyTable &myTable = static_cast<MyTable &>(myTable_);

// Not found in cache, look for the component name in metadata.
std::string whereClause("WHERE COMPONENT_UID = ");

   whereClause += componentUIDString;
   whereClause += " AND OPERATION_CODE = '";
   whereClause += operationCode; 
   whereClause += "' AND GRANTOR_ID = ";          
   whereClause += authIDToString(grantorID); 
   whereClause += " AND GRANTEE_ID = ";          
   whereClause += authIDToString(granteeID); 
   
MyRow row(fullTableName_);
   
// set pointer in diags area
int32_t diagsMark = pDiags_->mark();

PrivStatus privStatus = myTable.selectWhereUnique(whereClause,row);

   if (privStatus == STATUS_GOOD || privStatus == STATUS_WARNING) 
   {
      grantDepth = row.grantDepth_;
      return true;
   }
      
   pDiags_->rewind(diagsMark);

   return false;

}
//*************** End of PrivMgrComponentPrivileges::grantExists ***************


// *****************************************************************************
// *                                                                           *
// * Function: PrivMgrComponentPrivileges::grantPrivilege                      *
// *                                                                           *
// *    Grants the authority to perform one or more operations on a            *
// *  component to an authID; a row is added to the COMPONENT_PRIVILEGES       *
// *  table for each grant.                                                    *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <componentName>                 const std::string &              In      *
// *    is the component name.                                                 *
// *                                                                           *
// *  <operations>                    const std::vector<std::string> & In      *
// *    is a list of component operations to be granted.                       *
// *                                                                           *
// *  <grantorIDIn>                   const int32_t                    In      *
// *    is the auth ID granting the privilege.                                 *
// *                                                                           *
// *  <grantorName>                   const std::string &              In      *
// *    is the name of the authID granting the privilege.                      *
// *                                                                           *
// *  <granteeID>                     const int32_t                    In      *
// *    is the the authID being granted the privilege.                         *
// *                                                                           *
// *  <granteeName>                   const std::string &              In      *
// *    is the name of the authID being granted the privilege.                 *
// *                                                                           *
// *  <grantDepth>                    const int32_t                    In      *
// *    is the number of levels this privilege may be granted by the grantee.  *
// *  Initially this is either 0 or -1.                                        *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: PrivStatus                                                       *
// *                                                                           *
// * STATUS_GOOD: Component privilege(s) were granted                          *
// *           *: One or more component privileges were not granted.           *
// *              A CLI error is put into the diags area.                      *
// *                                                                           *
// *****************************************************************************
PrivStatus PrivMgrComponentPrivileges::grantPrivilege(
   const std::string & componentName,
   const std::vector<std::string> & operations,
   const int32_t grantorIDIn,
   const std::string & grantorName,
   const int32_t granteeID,
   const std::string & granteeName,
   const int32_t grantDepth)
  
{

   // Determine if the component exists.
   PrivMgrComponents component(metadataLocation_,pDiags_);

   if (!component.exists(componentName))
   {
      *pDiags_ << DgSqlCode(-CAT_TABLE_DOES_NOT_EXIST_ERROR)
               << DgTableName(componentName.c_str());
      return STATUS_ERROR;
   }
 
   std::string componentUIDString;
   int64_t componentUID;
   bool isSystemComponent;
   std::string tempStr;
   PrivStatus privStatus = STATUS_GOOD;

   component.fetchByName(componentName,
                         componentUIDString,
                         componentUID,
                         isSystemComponent,
                         tempStr);
                         
   // OK, the component is defined, what about the operations?
   MyTable &myTable = static_cast<MyTable &>(myTable_);
   PrivMgrComponentOperations componentOperations(metadataLocation_,pDiags_);
   std::vector<std::string> operationCodes;
   int32_t grantorID = grantorIDIn;

   for (size_t i = 0; i < operations.size(); i ++)
   {
      std::string operationName = operations[i];

      // For the moment we are disabling DML_* privileges. We might remove
      // them in the future. Note that it will still be possible to revoke 
      // them. (Note: sizeof counts null terminator, hence the -1.)
      if (strncmp(operationName.c_str(),"DML_",sizeof("DML_")-1) == 0)
      {
         *pDiags_ << DgSqlCode(-CAT_UNSUPPORTED_COMMAND_ERROR);
         return STATUS_ERROR;
      }
      
      //TODO: 
      // If we can't find an operation in the list, we give up.  No warnings or 
      // transactions currently.  Need to revisit this when we have 
      // transactions and warnings.  Also need to consider adding a general
      // mechanism to return what was done.  Useful with lists when one or 
      // more items in the list fail and in cases of "ALL".                                             
      if (!componentOperations.nameExists(componentUID,operationName))
      {
         *pDiags_ << DgSqlCode(-CAT_TABLE_DOES_NOT_EXIST_ERROR)
                  << DgTableName(operationName.c_str());
         return STATUS_ERROR;
      }
      
      std::string operationCode;
      bool isSystemOperation = FALSE;
      std::string operationDescription;
      
      componentOperations.fetchByName(componentUIDString,
                                      operationName,
                                      operationCode,
                                      isSystemOperation,
                                      operationDescription);
     
      // Component and this operation both exist.
      
      // If grantorID is DB__ROOT, then we use the "owner" of the 
      // operation, which is the user granted the privilege by _SYSTEM.
      // Read COMPONENT_PRIVILEGES to get grantorID.
      if (grantorIDIn == ComUser::getRootUserID())
      {
         privStatus = myTable.fetchOwner(componentUID,operationCode,
                                         grantorID);
         // If component operation is defined, there should be a grant to the
         // owner from the system. Just in case...                                
         if (privStatus != STATUS_GOOD) 
         {
            *pDiags_ << DgSqlCode(-CAT_INVALID_PRIVILEGE_FOR_GRANT_OR_REVOKE);
            return STATUS_ERROR;
         }
      }
      else
         grantorID = grantorIDIn;
      
      if (!hasWGO(grantorID,componentUIDString,operationCode))
      {
         *pDiags_ << DgSqlCode(-CAT_NOT_AUTHORIZED);
         return STATUS_ERROR;
      }

      operationCodes.push_back(operationCode);
   }
   
   //
   // Operations are valid, add or update each entry.
   //

   MyRow row(fullTableName_);

   row.componentUID_ = componentUID;
   row.grantDepth_ = grantDepth;
   row.granteeID_ = granteeID;
   row.granteeName_ = granteeName;
   row.grantorID_ = grantorID;
   row.grantorName_ = grantorName;
   
   std::string whereClauseHeader(" WHERE COMPONENT_UID = ");

   whereClauseHeader += componentUIDString;
   whereClauseHeader += " AND GRANTEE_ID = ";          
   whereClauseHeader += authIDToString(granteeID); 
   whereClauseHeader += " AND GRANTOR_ID = ";          
   whereClauseHeader += authIDToString(grantorID); 
   whereClauseHeader += " AND OPERATION_CODE = '";
   
   for (size_t oc = 0; oc < operationCodes.size(); oc++)
   {
      int32_t thisGrantDepth;
      
      // If privilege is already granted, just move on to the next entry.
      // Note, if adding WITH GRANT OPTION, perform an update.
      if (grantExists(componentUIDString,operationCodes[oc],grantorID,granteeID,
                      thisGrantDepth))  
      {
         if (grantDepth == thisGrantDepth || grantDepth == 0)
            continue;
      
         std::string whereClause = whereClauseHeader + operationCodes[oc] + "'";
         
         // Set new grant depth
         std::string setClause(" SET GRANT_DEPTH = ");
         
         char grantDepthString[20];
         
         sprintf(grantDepthString,"%d",grantDepth);
         setClause += grantDepthString + whereClause;
         
         privStatus = myTable.update(setClause);
      }
      else
      {
         row.operationCode_ = operationCodes[oc];
         privStatus = myTable.insert(row);
      }
      
      if (privStatus != STATUS_GOOD)
         return privStatus;
   }
   
   return STATUS_GOOD;

}  
//************* End of PrivMgrComponentPrivileges::grantPrivilege **************

// *****************************************************************************
// *                                                                           *
// * Function: PrivMgrComponentPrivileges::grantPrivilegeInternal              *
// *                                                                           *
// *    Internal function to grant one or more component privileges.           *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <componentUID>                  const int64_t                   In       *
// *    is the unique ID associated with the component.                        *
// *                                                                           *
// *  <operationCodes>                const std::vector<std::string> & In      *
// *    is a list of component operation codes for the operation to be granted.*
// *                                                                           *
// *  <grantorID>                     const int32_t                    In      *
// *    is the auth ID granting the privilege.                                 *
// *                                                                           *
// *  <grantorName>                   const std::string &              In      *
// *    is the name of the authID granting the privilege.                      *
// *                                                                           *
// *  <granteeID>                     const int32_t                    In      *
// *    is the the authID being granted the privilege.                         *
// *                                                                           *
// *  <granteeName>                   const std::string &              In      *
// *    is the name of the authID being granted the privilege.                 *
// *                                                                           *
// *  <grantDepth>                    const int32_t                    In      *
// *    is the number of levels this privilege may be granted by the grantee.  *
// *  Initially this is either 0 or -1.                                        *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: PrivStatus                                                       *
// *                                                                           *
// * STATUS_GOOD: Component privilege(s) were granted                          *
// *           *: One or more component privileges were not granted.           *
// *              A CLI error is put into the diags area.                      *
// *                                                                           *
// *****************************************************************************
PrivStatus PrivMgrComponentPrivileges::grantPrivilegeInternal(
   const int64_t componentUID,
   const std::vector<std::string> & operationCodes,
   const int32_t grantorID,
   const std::string & grantorName,
   const int32_t granteeID,
   const std::string & granteeName,
   const int32_t grantDepth,
   const bool checkExistence)
  
{

   MyTable &myTable = static_cast<MyTable &>(myTable_);
   MyRow row(fullTableName_);

   row.componentUID_ = componentUID;
   row.grantDepth_ = grantDepth;
   row.granteeID_ = granteeID;
   row.granteeName_ = granteeName;
   row.grantorID_ = grantorID;
   row.grantorName_ = grantorName;
   
   const std::string componentUIDString = to_string((long long int)componentUID);

   for (size_t oc = 0; oc < operationCodes.size(); oc++)
   {
      row.operationCode_ = operationCodes[oc];

      if (checkExistence &&
          grantExists(componentUIDString, row.operationCode_, row.grantorID_,
                      row.granteeID_, row.grantDepth_))
         continue;

      PrivStatus privStatus = myTable.insert(row);
      
      if (privStatus != STATUS_GOOD)
         return privStatus;
   }
   
   return STATUS_GOOD;

}  
//********* End of PrivMgrComponentPrivileges::grantPrivilegeInternal **********

// *****************************************************************************
// *                                                                           *
// * Function: PrivMgrComponentPrivileges::grantPrivilegeToCreator             *
// *                                                                           *
// *    Grants privilege on operation to creator from _SYSTEM.                 *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <componentUID>                  const int64_t                   In       *
// *    is the unique ID associated with the component.                        *
// *                                                                           *
// *  <operationCode>                 const std::string &             In       *
// *    is the two character code associated with the component operation.     *
// *                                                                           *
// *  <granteeID>                    const int32_t                    In       *
// *    is the auth ID of the creator of the component operation.              *
// *                                                                           *
// *  <granteeName>                   const std::string &             In       *
// *    is the name of the creator of the component operation.                 *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: PrivStatus                                                       *
// *                                                                           *
// * STATUS_GOOD: Component operation was granted to the auth ID by _SYSTEM.   *
// *           *: Component operation was not granted due to I/O error.        *
// *              A CLI error is put into the diags area.                      *
// *                                                                           *
// *****************************************************************************
PrivStatus PrivMgrComponentPrivileges::grantPrivilegeToCreator(
   const int64_t componentUID,
   const std::string & operationCode,
   const int32_t granteeID,
   const std::string & granteeName)
     
{

MyTable &myTable = static_cast<MyTable &>(myTable_);

MyRow row(fullTableName_);

   row.componentUID_ = componentUID;
   row.operationCode_ = operationCode;
   row.granteeID_ = granteeID;
   row.granteeName_ = granteeName;
   row.grantorID_ = SYSTEM_USER;
   row.grantorName_ = SYSTEM_AUTH_NAME;
   row.grantDepth_ = -1;
   
   return myTable.insert(row);

}  
//************** End of PrivMgrRoles::grantPrivilegeToCreator ******************

// *****************************************************************************
// *                                                                           *
// * Function: PrivMgrComponentPrivileges::hasPriv                             *
// *                                                                           *
// *    Determines if an authID has been granted the privilege on the          *
// * specified component operation.                                            *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <authID>                        const int32_t                   In       *
// *    is the authorization ID.                                               *
// *                                                                           *
// *  <componentName>                 const std::string &             In       *
// *    is the name of the component.                                          *
// *                                                                           *
// *  <operationName>                 const std::string &             In       *
// *    is the name of the operation.                                          *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: bool                                                             *
// *                                                                           *
// * true: This authorization ID has the component privilege.                  *
// * false: This authorization ID does not have the component privilege, or    *
// *   there was an error trying to read from the COMPONENT_PRIVILEGES table.  *
// *                                                                           *
// *****************************************************************************
bool PrivMgrComponentPrivileges::hasPriv(
   const int32_t authID,
   const std::string & componentName,
   const std::string & operationName)
   
{

// Determine if the component exists.

PrivMgrComponents component(metadataLocation_,pDiags_);

   if (!component.exists(componentName))
   {
      *pDiags_ << DgSqlCode(-CAT_TABLE_DOES_NOT_EXIST_ERROR)
               << DgTableName(componentName.c_str());
      return STATUS_ERROR;
   }
 
std::string componentUIDString;
int64_t componentUID;
bool isSystemComponent;
std::string tempStr;

   component.fetchByName(componentName,
                         componentUIDString,
                         componentUID,
                         isSystemComponent,
                         tempStr);
    
// OK, the component is defined, what about the operation?

PrivMgrComponentOperations componentOperations(metadataLocation_,pDiags_);

   if (!componentOperations.nameExists(componentUID,operationName))
   {
      *pDiags_ << DgSqlCode(-CAT_TABLE_DOES_NOT_EXIST_ERROR)
               << DgTableName(operationName.c_str());
      return STATUS_ERROR;
   }
   
std::string operationCode;
bool isSystemOperation = FALSE;
std::string operationDescription;
   
   componentOperations.fetchByName(componentUIDString,
                                   operationName,
                                   operationCode,
                                   isSystemOperation,
                                   operationDescription);
                                   
std::string whereClause(" WHERE COMPONENT_UID = ");   

   whereClause += componentUIDString;
   whereClause += " AND OPERATION_CODE = '";
   whereClause += operationCode;
   whereClause += "' AND GRANTEE_ID = ";
   whereClause += authIDToString(authID); 
   
int64_t rowCount = 0;   
MyTable &myTable = static_cast<MyTable &>(myTable_);

// set pointer in diags area
int32_t diagsMark = pDiags_->mark();

PrivStatus privStatus = myTable.selectCountWhere(whereClause,rowCount);

   if ((privStatus == STATUS_GOOD || privStatus == STATUS_WARNING) &&
        rowCount > 0)
      return true;
      
   pDiags_->rewind(diagsMark);

   return false;

}
//***************** End of PrivMgrComponentPrivileges::hasPriv *****************


// *****************************************************************************
// *                                                                           *
// * Function: PrivMgrComponentPrivileges::hasSQLPriv                          *
// *                                                                           *
// *    Determines if an authID has been granted the privilege on the          *
// * SQL_OPERATIONS component operation.                                       *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <authID>                        const int32_t                   In       *
// *    is the authorization ID.                                               *
// *                                                                           *
// *  <operation>                     const SQLOperation              In       *
// *    is the enum for the SQL operation.                                     *
// *                                                                           *
// *  <includeRoles>                  const bool                      In       *
// *    if true, indicates privileges granted to roles granted to the          *
// * authorization ID should be included.                                      *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: bool                                                             *
// *                                                                           *
// * true: This authorization ID has the component privilege.                  *
// * false: This authorization ID does not have the component privilege, or    *
// *   there was an error trying to read from the COMPONENT_PRIVILEGES table.  *
// *                                                                           *
// *****************************************************************************
bool PrivMgrComponentPrivileges::hasSQLPriv(
   const int32_t authID,
   const SQLOperation operation,
   const bool includeRoles)
   
{

  if (authID == ComUser::getRootUserID())
     return true;

const std::string & operationCode = PrivMgr::getSQLOperationCode(operation);

std::string whereClause(" WHERE COMPONENT_UID = 1 AND (OPERATION_CODE = '");   

   whereClause += operationCode;
   
   if (PrivMgr::isSQLCreateOperation(operation))
   {
      whereClause += "' OR OPERATION_CODE = '";
      whereClause += PrivMgr::getSQLOperationCode(SQLOperation::CREATE);
   }
   else 
      if (PrivMgr::isSQLDropOperation(operation))
      {
         whereClause += "' OR OPERATION_CODE = '";
         whereClause += PrivMgr::getSQLOperationCode(SQLOperation::DROP);
      }
      else
         if (PrivMgr::isSQLAlterOperation(operation))
         {
            whereClause += "' OR OPERATION_CODE = '";
            whereClause += PrivMgr::getSQLOperationCode(SQLOperation::ALTER);
         }
         else
            if (PrivMgr::isSQLManageOperation(operation))
            {
               whereClause += "' OR OPERATION_CODE = '";
               whereClause += PrivMgr::getSQLOperationCode(SQLOperation::MANAGE);
            }

   
   whereClause += "') AND (GRANTEE_ID = -1 OR GRANTEE_ID = ";
   whereClause += authIDToString(authID);
    
// *****************************************************************************
// *                                                                           *
// *   If component privileges granted to roles granted to the authorization   *
// * ID should be considered, get the list of roles granted to the auth ID     *
// * and add each one as a potential grantee.                                  *
// *                                                                           *
// *****************************************************************************
   
   if (includeRoles)
   {
      std::vector<std::string> roleNames;
      std::vector<int32_t> roleIDs;
      std::vector<int32_t> grantDepths;
      
      PrivMgrRoles roles(" ",metadataLocation_,pDiags_);
      
      PrivStatus privStatus = roles.fetchRolesForUser(authID,roleNames,
                                                      roleIDs,grantDepths);
      
      for (size_t r = 0; r < roleIDs.size(); r++)
      {
         whereClause += " OR GRANTEE_ID = ";
         whereClause += authIDToString(roleIDs[r]);
      }
   }
   
   whereClause += ")"; 
   
int64_t rowCount = 0;   
MyTable &myTable = static_cast<MyTable &>(myTable_);

// set pointer in diags area
int32_t diagsMark = (pDiags_ != NULL ? pDiags_->mark() : -1);

PrivStatus privStatus = myTable.selectCountWhere(whereClause,rowCount);

   if ((privStatus == STATUS_GOOD || privStatus == STATUS_WARNING) &&
        rowCount > 0)
      return true;
      
   if (diagsMark != -1)
      pDiags_->rewind(diagsMark);

   return false;

}
//*************** End of PrivMgrComponentPrivileges::hasSQLPriv ****************





// *****************************************************************************
// *                                                                           *
// * Function: PrivMgrComponentPrivileges::hasWGO                              *
// *                                                                           *
// *    Determines if an authID has been granted the ability to grant a        *
// * specific component operation.                                             *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <authID>                        const int32_t                   In       *
// *    is the authorization ID.                                               *
// *                                                                           *
// *  <componentUIDString>            const std::string &             In       *
// *    is the unique ID of the component in string format.                    *
// *                                                                           *
// *  <operationCode>                 const std::string &             In       *
// *    is the two character code for the component operation.                 *
// *                                                                           *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: bool                                                             *
// *                                                                           *
// * true: This authorization ID has with grant option.                        *
// * false: This authorization ID does not have with grant option, or there    *
// *        was an error trying to read from the ROLE_USAGE table.             *
// *                                                                           *
// *****************************************************************************
bool PrivMgrComponentPrivileges::hasWGO(
   int32_t authID,
   const std::string & componentUIDString,
   const std::string & operationCode)
   
{

   // get roles granted to authID
   std::vector<std::string> roleNames;
   std::vector<int32_t> roleIDs;
   std::vector<int32_t> grantDepths;

   PrivMgrRoles roles(" ",metadataLocation_,pDiags_);

   if (roles.fetchRolesForUser(authID,roleNames,
                               roleIDs,grantDepths) == STATUS_ERROR)
      return false;

   MyTable &myTable = static_cast<MyTable &>(myTable_);

   std::string granteeList;
   granteeList += authIDToString(authID);
   for (size_t i = 0; i < roleIDs.size(); i++)
   {
      granteeList += ", ";
      granteeList += authIDToString(roleIDs[i]);
   }

   // DB__ROOTROLE is a special role.  If the authID has been granted this role 
   // then they have WGO privileges. 
   if (std::find(roleIDs.begin(), roleIDs.end(), ROOT_ROLE_ID) != roleIDs.end())
      return true;

   std::string whereClause (" WHERE GRANTEE_ID IN (");
   whereClause += granteeList;
   whereClause += ") AND COMPONENT_UID = ";          
   whereClause += componentUIDString;
   whereClause += " AND OPERATION_CODE = '";          
   whereClause += operationCode;
   whereClause += "' AND GRANT_DEPTH <> 0";
   
   int64_t rowCount = 0;

   // set pointer in diags area
   int32_t diagsMark = pDiags_->mark();

   PrivStatus privStatus = myTable.selectCountWhere(whereClause,rowCount);

   if ((privStatus == STATUS_GOOD || privStatus == STATUS_WARNING) &&
        rowCount > 0)
      return true;
      
   pDiags_->rewind(diagsMark);

   return false;
   
}
//***************** End of PrivMgrComponentPrivileges::hasWGO ******************

// *****************************************************************************
// *                                                                           *
// * Function: PrivMgrComponentPrivileges::isAuthIDGrantedPrivs                *
// *                                                                           *
// *    Determines if the specified authorization ID has been granted one or   *
// * more component privileges.                                                *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <authID>                        const int32_t                   In       *
// *    is the authorization ID.                                               *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: bool                                                             *
// *                                                                           *
// * true: Authorization ID has been granted one or more component privileges. *
// * false: Authorization ID has not been granted any component privileges.    *
// *                                                                           *
// *****************************************************************************
bool PrivMgrComponentPrivileges::isAuthIDGrantedPrivs(const int32_t authID)

{

std::string whereClause(" WHERE GRANTEE_ID =  ");   

   whereClause += authIDToString(authID); 

int64_t rowCount = 0;   
MyTable &myTable = static_cast<MyTable &>(myTable_);

// set pointer in diags area
int32_t diagsMark = pDiags_->mark();

PrivStatus privStatus = myTable.selectCountWhere(whereClause,rowCount);

   if ((privStatus == STATUS_GOOD || privStatus == STATUS_WARNING) &&
        rowCount > 0)
      return true;
      
   pDiags_->rewind(diagsMark);

   return false;

}
//*********** End of PrivMgrComponentPrivileges::isAuthIDGrantedPrivs **********



// *****************************************************************************
// *                                                                           *
// * Function: PrivMgrComponentPrivileges::isGranted                           *
// *                                                                           *
// *    Determines if a component operation has been granted, i.e., if it      *
// * is used in the COMPONENT_PRIVILEGES table.                                *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <componentUIDString>            const std::string &             In       *
// *    is the component unique ID.                                            *
// *                                                                           *
// *  <operationCode>                 const std::string &             In       *
// *    is the two character code associated with the component operation.     *
// *                                                                           *
// *  <shouldExcludeGrantsBySystem>   const bool                      [In]     *
// *    if true, don't consider the system grant to the creator.               *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: bool                                                             *
// *                                                                           *
// * true: Component operation has been granted to one or more authIDs.        *
// * false: Component operation has not been granted, or there was an error    *
// * trying to read from the COMPONENT_PRIVILEGES table.                       *
// *                                                                           *
// *****************************************************************************
bool PrivMgrComponentPrivileges::isGranted(
  const std::string & componentUIDString,
  const std::string & operationCode,
  const bool shouldExcludeGrantsBySystem)
  
{

MyRow row(fullTableName_);
MyTable &myTable = static_cast<MyTable &>(myTable_);

std::string whereClause("WHERE COMPONENT_UID = ");

   whereClause += componentUIDString;
   whereClause += " AND OPERATION_CODE = '";
   whereClause += operationCode;
   whereClause += "'";
   if (shouldExcludeGrantsBySystem)
      whereClause += " AND GRANTOR_ID <> -2";
   
// set pointer in diags area
int32_t diagsMark = pDiags_->mark();

PrivStatus privStatus = myTable.selectWhereUnique(whereClause,row);

   if (privStatus == STATUS_GOOD || privStatus == STATUS_WARNING)
      return true;
      
   pDiags_->rewind(diagsMark);

   return false;
    
}      
//**************** End of PrivMgrComponentPrivileges::isGranted ****************





// *****************************************************************************
// * Function: PrivMgrComponentPrivileges::revokeAllForGrantor                 *
// *                                                                           *
// *    Revokes grants from a specified grantor.                               *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Parameters:                                                               *
// *                                                                           *
// *  <grantorID>                     const int32_t                    In      *
// *    is the unique ID of the authID whose grants are to be revoked.         *
// *                                                                           *
// *  <roleID>                        const int32_t                    In      *
// *    is the ID of the role to be revoked.                                   *
// *                                                                           *
// *  <isGOFSpecified>             const bool                          In      *
// *    is true if admin rights are being revoked.                             *
// *                                                                           *
// *  <newGrantDepth>              const int32_t                       In      *
// *    is the number of levels this privilege may be granted by the grantee.  *
// *  Initially this is always 0 when revoking.                                *
// *                                                                           *
// *  <dropBehavior>                  PrivDropBehavior                 In      *
// *    indicates whether restrict or cascade behavior is requested.           *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: PrivStatus                                                       *
// *                                                                           *
// * STATUS_GOOD: All grants of the role by this grantor were revoked (or      *
// *              there were none).                                            *
// *           *: Could not revoke grants.  A CLI error is put into            *
// *              the diags area.                                              *
// *                                                                           *
// *****************************************************************************
PrivStatus PrivMgrComponentPrivileges::revokeAllForGrantor(
   const int32_t grantorID,
   const std::string componentName,
   const std::string componentUIDString,
   const std::string operationName,
   const std::string operationCode,
   const bool isGOFSpecified,
   const int32_t newGrantDepth,
   PrivDropBehavior dropBehavior) 
   
{

// *****************************************************************************
// *                                                                           *
// *  First, get all the rows where the grantor has granted this operation     *
// * to any authorization ID.                                                  *
// *                                                                           *
// *****************************************************************************

std::string whereClause("WHERE COMPONENT_UID = ");

   whereClause += componentUIDString;
   whereClause += " AND OPERATION_CODE = '";
   whereClause += operationCode;
   whereClause += "' AND GRANTOR_ID = ";
   whereClause += authIDToString(grantorID);
   
std::string orderByClause;
   
std::vector<MyRow> rows;
MyTable &myTable = static_cast<MyTable &>(myTable_);

PrivStatus privStatus = myTable.selectAllWhere(whereClause,orderByClause,rows);

// *****************************************************************************
// *                                                                           *
// *   If the grantor has no active grants for this operation, we are done.    *
// *                                                                           *
// *****************************************************************************

   if (privStatus == STATUS_NOTFOUND)
      return STATUS_GOOD;

// *****************************************************************************
// *                                                                           *
// *   Unexpected problem, let the caller deal with it.                        *
// *                                                                           *
// *****************************************************************************

   if (privStatus != STATUS_GOOD && privStatus != STATUS_WARNING)
      return privStatus;
      
// *****************************************************************************
// *                                                                           *
// *   Expected NOTFOUND, but if empty list returned, return no error.         *
// *                                                                           *
// *****************************************************************************

   if (rows.size() == 0)
      return STATUS_GOOD;

// *****************************************************************************
// *                                                                           *
// *   If there are grants and drop behavior is RESTRICT, return an error.     *
// *                                                                           *
// *****************************************************************************

   if (dropBehavior == PrivDropBehavior::RESTRICT)
   { 
      //TODO: Need better error message. 
      *pDiags_ << DgSqlCode(-CAT_DEPENDENT_OBJECTS_EXIST);
      return STATUS_ERROR; 
      return STATUS_ERROR;
   }
      
// *****************************************************************************
// *                                                                           *
// *   There are one more grants from the grantor of this operation.  Create a *
// * vector for the operationCode and call revokePrivilege.                    *
// *                                                                           *
// *****************************************************************************
      
std::vector<std::string> operationNames;  

   operationNames.push_back(operationName);  
   
   for (size_t r = 0; r < rows.size(); r++) 
   {
      privStatus = revokePrivilege(componentName,operationNames,grantorID,
                                   rows[r].granteeID_,isGOFSpecified,
                                   newGrantDepth,dropBehavior); 
      if (privStatus != STATUS_GOOD)
         return privStatus;
   }
   
   return STATUS_GOOD;

}
//****************** End of PrivMgrRoles::revokeAllForGrantor ******************



// *****************************************************************************
// *                                                                           *
// * Function: PrivMgrComponentPrivileges::revokePrivilege                     *
// *                                                                           *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <componentName>                 const std::string &              In      *
// *    is the component name.                                                 *
// *                                                                           *
// *  <operations>                    const std::vector<std::string> & In      *
// *    is a list of component operations to be revoked.                       *
// *                                                                           *
// *  <grantorID>                     const int32_t                    In      *
// *    is the authID revoking the privilege.                                  *
// *                                                                           *
// *  <granteeID>                     const int32_t                    In      *
// *    is the authID the privilege is being revoked from.                     *
// *                                                                           *
// *  <isGOFSpecified>             const bool                          In      *
// *    is true if admin rights are being revoked.                             *
// *                                                                           *
// *  <newGrantDepth>              const int32_t                       In      *
// *    is the number of levels this privilege may be granted by the grantee.  *
// *  Initially this is always 0 when revoking.                                *
// *                                                                           *
// *  <dropBehavior>                  PrivDropBehavior                 In      *
// *    indicates whether restrict or cascade behavior is requested.           *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: PrivStatus                                                       *
// *                                                                           *
// * STATUS_GOOD: Component privilege(s) were revoked                          *
// *           *: One or more component privileges were not revoked.           *
// *              A CLI error is put into the diags area.                      *
// *                                                                           *
// *****************************************************************************
PrivStatus PrivMgrComponentPrivileges::revokePrivilege(
   const std::string & componentName,
   const std::vector<std::string> & operations,
   const int32_t grantorID,
   const int32_t granteeID, 
   const bool isGOFSpecified,
   const int32_t newGrantDepth,
   PrivDropBehavior dropBehavior) 
  
{
// Determine if the component exists.

PrivMgrComponents component(metadataLocation_,pDiags_);

   if (!component.exists(componentName))
   {
      *pDiags_ << DgSqlCode(-CAT_TABLE_DOES_NOT_EXIST_ERROR)
               << DgTableName(componentName.c_str());
      return STATUS_ERROR;
   }
 
std::string componentUIDString;
int64_t componentUID;
bool isSystemComponent;
std::string tempStr;

   component.fetchByName(componentName,
                         componentUIDString,
                         componentUID,
                         isSystemComponent,
                         tempStr);
    
// OK, the component is defined, what about the operations?

PrivMgrComponentOperations componentOperations(metadataLocation_,pDiags_);
std::vector<std::string> operationCodes;

   for (size_t i = 0; i < operations.size(); i++)
   {
      std::string operationName = operations[i];
      //TODO: We stop if one on the list is not found.  See comment in
      // grantPrivilege() for more details.                                             
      if (!componentOperations.nameExists(componentUID,operationName))
      {
         *pDiags_ << DgSqlCode(-CAT_TABLE_DOES_NOT_EXIST_ERROR)
                  << DgTableName(operationName.c_str());
         return STATUS_ERROR;
      }
      
      std::string operationCode;
      bool isSystemOperation = FALSE;
      std::string operationDescription;
      
      componentOperations.fetchByName(componentUIDString,
                                      operationName,
                                      operationCode,
                                      isSystemOperation,
                                      operationDescription);
   
      // Component and this operation both exist. Save operation code.
      operationCodes.push_back(operationCode);
   }
   
PrivStatus privStatus = STATUS_GOOD;
   
   for (size_t oc = 0; oc < operationCodes.size(); oc++)
   {
   
      int32_t grantDepth;
       
      if (!grantExists(componentUIDString,operationCodes[oc],grantorID,
                       granteeID,grantDepth))
      {
         int32_t length;
         char grantorName[MAX_DBUSERNAME_LEN + 1];
                  
         Int16 retCode = ComUser::getAuthNameFromAuthID(grantorID,
                                                        grantorName,
                                                        sizeof(grantorName),
                                                        length);
         // Should not fail, grantor ID was derived from name provided by user.
         if (retCode != 0)
         {
            std::string errorText("Unable to look up grantor name for ID ");
            
            errorText += authIDToString(grantorID);
            PRIVMGR_INTERNAL_ERROR(errorText.c_str());
            return STATUS_ERROR;
         }
      
         char granteeName[MAX_DBUSERNAME_LEN + 1];
                  
         retCode = ComUser::getAuthNameFromAuthID(granteeID,
                                                  granteeName,
                                                  sizeof(granteeName),
                                                  length);
         // Should not fail, grantee ID was derived from name provided by user.
         if (retCode != 0)
         {
            std::string errorText("Unable to look up grantee name for ID ");
            
            errorText += authIDToString(granteeID);
            PRIVMGR_INTERNAL_ERROR(errorText.c_str());
            return STATUS_ERROR;
         }
         
         std::string operationOnComponent(operations[oc]);
         
         operationOnComponent += " on component ";
         operationOnComponent += componentName;
      
         *pDiags_ << DgSqlCode(-CAT_GRANT_NOT_FOUND) 
                  << DgString0(operationOnComponent.c_str()) 
                  << DgString1(grantorName) 
                  << DgString2(granteeName);
         return STATUS_ERROR;
      }
   
      if (!hasWGO(granteeID,componentUIDString,operationCodes[oc]))
         continue;

      privStatus = revokeAllForGrantor(granteeID,
                                       componentName,
                                       componentUIDString,
                                       operations[oc],
                                       operationCodes[oc],
                                       isGOFSpecified,
                                       newGrantDepth,
                                       dropBehavior); 
      if (privStatus != STATUS_GOOD)
      {
         return STATUS_ERROR;
      }
      if (isSQLDMLPriv(componentUID,operations[oc]))
      {   //TODO: QI only supports revoke from objects and users (roles)
         // Notify QI
      }
   }
    
MyTable &myTable = static_cast<MyTable &>(myTable_);

std::string whereClauseHeader("WHERE COMPONENT_UID = ");

   whereClauseHeader += componentUIDString;
   whereClauseHeader += " AND GRANTOR_ID = ";
   whereClauseHeader += authIDToString(grantorID);;
   whereClauseHeader += " AND GRANTEE_ID = ";
   whereClauseHeader += authIDToString(granteeID);;
   whereClauseHeader += " AND OPERATION_CODE = '";
   
std::string setClause("SET GRANT_DEPTH = ");

   if (isGOFSpecified)
   {
      char grantDepthString[20];
      
      sprintf(grantDepthString,"%d",newGrantDepth);
      setClause += grantDepthString;
   }
   
bool someNotRevoked = false;
  
   for (size_t c = 0; c < operationCodes.size(); c++)
   {
      std::string whereClause(whereClauseHeader);

      whereClause += operationCodes[c];
      whereClause += "'";
      
      if (isGOFSpecified)
      {
         std::string updateClause = setClause + whereClause;
         
         privStatus = myTable.update(updateClause);
      }
      else
         privStatus = myTable.deleteWhere(whereClause);
      
      if (privStatus == STATUS_NOTFOUND)
      {
         someNotRevoked = true;
         continue;
      }
      
      if (privStatus != STATUS_GOOD)
         return privStatus;
   }
   
   if (someNotRevoked)
   {
      *pDiags_ << DgSqlCode(CAT_NOT_ALL_PRIVILEGES_REVOKED);
      return STATUS_WARNING;
   }
   
   return STATUS_GOOD;
  
}  
//************* End of PrivMgrComponentPrivileges::revokePrivilege *************

// *****************************************************************************
//    Private functions
// *****************************************************************************

// *****************************************************************************
// *                                                                           *
// * Function: PrivMgrComponentPrivileges::isSQLDMLPriv                        *
// *                                                                           *
// *     This function determines if a component-level privilege is a DML      *
// *  privilege in the SQL_OPERATIONS component.                               *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <componentUID>                  const int64_t                   In       *
// *    is the unique ID associated with the component.                        *
// *                                                                           *
// *  <operationCode>                 const std::string &             In       *
// *    is the two character code associated with the component operation.     *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: bool                                                             *
// *                                                                           *
// * true: This is a SQL_OPERATION DML privilege.                              *
// * false: This is NOT a SQL_OPERATION DML privilege.                         *
// *                                                                           *
// *****************************************************************************
static bool isSQLDMLPriv(
   const int64_t componentUID,
   const std::string operationCode)

{

   if (componentUID != SQL_OPERATIONS_COMPONENT_UID)
      return false;
      
   for (SQLOperation operation = SQLOperation::FIRST_DML_PRIV;
        static_cast<int>(operation) <= static_cast<int>(SQLOperation::LAST_DML_PRIV); 
        operation = static_cast<SQLOperation>(static_cast<int>(operation) + 1))
   {
      if (PrivMgr::getSQLOperationCode(operation) == operationCode)
         return true;
   }

   return false;

}  
//***************************** End of isSQLDMLPriv ****************************



// *****************************************************************************
//    MyTable methods
// *****************************************************************************

// *****************************************************************************
// *                                                                           *
// * Function: MyTable::describeGrantTree                                      *
// *                                                                           *
// *    Describes grants for the specified grantor                             *
// *    Recursively calls itself to describe the grants for each grantee       *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  grantorID                        const int32_t                        In *
// *    all grants granted by the grantorID are described.                     *
// *                                                                           *
// *  operationName                    const std::string &                  In *
// *     used for generate grant statement as granted operation.               *
// *                                                                           *
// *  componentName                    const std::string &                  In *
// *    used for generate grant statement on the component.                    *
// *                                                                           *
// *  rows                             const std::vector<MyRow> &           In *
// *    all the rows that represent grants for the component operation.        *
// *                                                                           *
// *  outlines                         std::vector<std::string> &           Out*
// *      output generated GRANT statements to this array.                     *
// *                                                                           *
// *****************************************************************************
void MyTable::describeGrantTree(
  const int32_t grantorID,
  const std::string &operationName,
  const std::string &componentName,
  const std::vector<MyRow> &rows,
  std::vector<std::string> & outlines)
{
   // Starts at the beginning of the list searching for grants attributed to 
   // the grantorID
   int32_t nextRowID = 0;
   while (nextRowID >= 0 && nextRowID < rows.size())
   {
     int32_t rowID = findGrantor(nextRowID, grantorID, rows);

     // If this grantor did not grant any requests, -1 is returned and we are
     // done traversing this branch
     if (rowID == -1)
       return;

     nextRowID = rowID;
     MyRow row = rows[rowID];

     // We found a grant, describe the grant
     row.describeGrant(operationName, componentName, outlines);

     // Traverser any grants that may have been performed by the grantee.
     // If grantDepth is 0, then the grantee does not have the WITH GRANT 
     // OPTION so no reason to traverse this potential branch - there is none.
     if (row.grantDepth_ != 0)
       describeGrantTree(row.granteeID_, operationName, componentName, rows, outlines);

     // get next grant for this grantorID
     nextRowID++;
  }
}

//******************* End of MyTable::describeGrantTree ************************

// *****************************************************************************
// *                                                                           *
// * Function: MyTable::fetchDMLPrivInfo                                       *
// *                                                                           *
// *    Reads from the COMPONENT_PRIVILEGES table and returns the              * 
// *    SQL_OPERATIONS privileges associated with DML privileges.              *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <granteeID>                     int32_t &                       In       *
// *    is the authID whose system-level DML privileges are being fetched.     *
// *                                                                           *
// *  <roleIDs>                       const std::vector<int32_t> &    In       *
// *    is a list of roleIDs granted to the grantee.                           *
// *                                                                           *
// *  <DMLBitmap>                     PrivObjectBitmap &              In       *
// *    passes back the system-level DML privileges granted to the grantee.    *
// *                                                                           *
// *  <hasManagePrivileges>           bool &                          In       *
// *    passes back if the user has MANAGE_PRIVILEGES authority.               *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: PrivStatus                                                       *
// *                                                                           *
// * STATUS_GOOD: Data returned.                                               *
// *           *: Error encountered.                                           *
// *                                                                           *
// *****************************************************************************
PrivStatus MyTable::fetchDMLPrivInfo(
   const int32_t                granteeID,
   const std::vector<int32_t> & roleIDs,
   PrivObjectBitmap           & DMLBitmap,
   bool                       & hasManagePrivileges)
   
{

// Check the last grantee data read before reading metadata.

   if (userDMLPrivs_.granteeID_ == granteeID && 
       userDMLPrivs_.roleIDs_ == roleIDs)
   {
      DMLBitmap = userDMLPrivs_.DMLBitmap_;
      hasManagePrivileges = userDMLPrivs_.managePrivileges_;
      return STATUS_GOOD;
   } 
      
// Not found in cache, look for the priv info in metadata.
// ??? - is the component_uid for SQL_OPERATIONS always going to be 1?
std::string whereClause("WHERE COMPONENT_UID = 1 AND OPERATION_CODE IN ('");

   for (SQLOperation operation = SQLOperation::FIRST_DML_PRIV;
        static_cast<int>(operation) <= static_cast<int>(SQLOperation::LAST_DML_PRIV); 
        operation = static_cast<SQLOperation>(static_cast<int>(operation) + 1))
   {
      whereClause += PrivMgr::getSQLOperationCode(operation);
      whereClause += "','";
   }

   whereClause += PrivMgr::getSQLOperationCode(SQLOperation::MANAGE_PRIVILEGES);
   whereClause += "') AND GRANTEE_ID IN (";
   whereClause += PrivMgr::authIDToString(granteeID);
   whereClause += ",";
   for (size_t ri = 0; ri < roleIDs.size(); ri++)
   {
      whereClause += PrivMgr::authIDToString(roleIDs[ri]);
      whereClause += ",";
   }
   whereClause += PrivMgr::authIDToString(PUBLIC_USER);
   whereClause += ")";
   
std::string orderByClause;
   
std::vector<MyRow> rows;

PrivStatus privStatus = selectAllWhere(whereClause,orderByClause,rows);

   if (privStatus != STATUS_GOOD && privStatus != STATUS_WARNING)
      return privStatus;
   
// Initialize cache.
   userDMLPrivs_.granteeID_ = granteeID;
   userDMLPrivs_.roleIDs_ = roleIDs;
   userDMLPrivs_.managePrivileges_ = false;
   userDMLPrivs_.DMLBitmap_.reset();  
    
   for (size_t r = 0; r < rows.size(); r++)
   {
      MyRow &row = rows[r];
      
      if (row.operationCode_ == PrivMgr::getSQLOperationCode(SQLOperation::MANAGE_PRIVILEGES))
      {
         userDMLPrivs_.managePrivileges_ = true;
         continue;
      }   
      
      if (row.operationCode_ == PrivMgr::getSQLOperationCode(SQLOperation::DML_DELETE))
      {
         userDMLPrivs_.DMLBitmap_.set(DELETE_PRIV);
         continue;
      }   
      
      if (row.operationCode_ == PrivMgr::getSQLOperationCode(SQLOperation::DML_INSERT))
      {
         userDMLPrivs_.DMLBitmap_.set(INSERT_PRIV);
         continue;
      }   
      
      if (row.operationCode_ == PrivMgr::getSQLOperationCode(SQLOperation::DML_REFERENCES))
      {
         userDMLPrivs_.DMLBitmap_.set(REFERENCES_PRIV);
         continue;
      }   
      
      if (row.operationCode_ == PrivMgr::getSQLOperationCode(SQLOperation::DML_SELECT))
      {
         userDMLPrivs_.DMLBitmap_.set(SELECT_PRIV);
         continue;
      }   
      
      if (row.operationCode_ == PrivMgr::getSQLOperationCode(SQLOperation::DML_UPDATE))
      {
         userDMLPrivs_.DMLBitmap_.set(UPDATE_PRIV);
         continue;
      }   
      
      if (row.operationCode_ == PrivMgr::getSQLOperationCode(SQLOperation::DML_USAGE))
      {
         userDMLPrivs_.DMLBitmap_.set(USAGE_PRIV);
         continue;
      }   
   }
   
   hasManagePrivileges = userDMLPrivs_.managePrivileges_;
   DMLBitmap = userDMLPrivs_.DMLBitmap_;   
   
   return STATUS_GOOD;

}   
//******************* End of MyTable::fetchDMLPrivInfo *************************

// *****************************************************************************
// *                                                                           *
// * Function: MyTable::findGrantor                                            *
// *                                                                           *
// *    Search the list of grants for the component operation looking for the  *
// *    next row for the grantor.                                              *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  currentRowID                           int32_t                        In *
// *    where to start searching for the next row for the grantor.             *
// *                                                                           *
// *  grantorID                        const int32_t                        In *
// *    the grantor to search for.                                             *
// *                                                                           *
// *  rows                             const std::vector<MyRow> &           In *
// *    all the rows that represent grants for the component operation.        *
// *                                                                           *
// *                                                                           *
// * Returns                                                                   *
// *   >= 0 -- the index into rows where the next row for grantor is described *
// *     -1 -- no more row, done                                               *
// *                                                                           *
// *****************************************************************************
int32_t MyTable::findGrantor(
  int32_t currentRowID,
  const int32_t grantorID,
  const std::vector<MyRow> rows)
{
   for (size_t i = currentRowID; i < rows.size(); i++)
   {
      if (rows[i].grantorID_ == grantorID)
        return i;

      // rows are sorted in grantorID order, so once the grantorID stored in
      // rows is greater than the requested grantorID, we are done.
      if (rows[i].grantorID_ > grantorID)
        return -1;
   }
   return -1;
}

//******************* End of MyTable::findGrantor ******************************

// *****************************************************************************
// *                                                                           *
// * Function: MyTable::fetchOwner                                             *
// *                                                                           *
// *    Reads from the COMPONENT_PRIVILEGES table and returns the authID       *
// *  granted the specified privilege by the system.                           *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <componentUID>                  const int64_t                   In       *
// *    is the unique ID associated with the component.                        *
// *                                                                           *
// *  <operationCode>                 const std::string &             In       *
// *    is the two digit code for the operation.                               *
// *                                                                           *
// *  <granteeID>                     int32_t &                       Out      *
// *    passes back the authID granted the privilege by the system.            *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: PrivStatus                                                       *
// *                                                                           *
// * STATUS_GOOD: Found row with system grantor, grantee returned.             *
// *           *: Row not found or error encountered.                          *
// *                                                                           *
// *****************************************************************************
PrivStatus MyTable::fetchOwner(
   const int64_t componentUID,
   const std::string & operationCode,
   int32_t & granteeID)
   
{

// Check the last row read before reading metadata.

   if (lastRowRead_.grantorID_ == SYSTEM_USER &&
       lastRowRead_.componentUID_ == componentUID &&
       lastRowRead_.operationCode_ == operationCode)
   {
      granteeID = lastRowRead_.granteeID_;
      return STATUS_GOOD;
   }    
       
// Not found in cache, look for the system grantor in metadata.
std::string whereClause("WHERE COMPONENT_UID = ");

   whereClause += PrivMgr::UIDToString(componentUID);
   whereClause += " AND OPERATION_CODE = '";
   whereClause += operationCode;
   whereClause += "' AND GRANTOR_ID = -2";
   
MyRow row(tableName_);

PrivStatus privStatus = selectWhereUnique(whereClause,row);
   
   switch (privStatus)
   {
      // Return status to caller to handle
      case STATUS_NOTFOUND:
      case STATUS_ERROR:
         return privStatus;
         break;

      // Object exists 
      case STATUS_GOOD:
      case STATUS_WARNING:
         granteeID = row.granteeID_;
         return STATUS_GOOD;
         break;

      // Should not occur, internal error
      default:
         PRIVMGR_INTERNAL_ERROR("Switch statement in PrivMgrComponentPrivileges::MyTable::fetchOwner()");
         return STATUS_ERROR;
         break;
   }
   
   return STATUS_GOOD;

}   
//*********************** End of MyTable::fetchOwner ***************************




// *****************************************************************************
// *                                                                           *
// * Function: MyTable::getRowsForGrantee                                      *
// *                                                                           *
// *    Finds the list of rows (branch) that need to be removed if the         *
// *  grantee no longer has WGO.                                               *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <baseRow>                       const MyRow &                   In       *
// *    contains the starting point for the branch                             *
// *                                                                           *
// *  <masterRowList>                       std::vector<MyRow> &      In/Out   *
// *    contains the master list of privileges                                 *
// *    this list is updated to set the "visited_" flag for performance        *
// *                                                                           *
// *  <rowsToDelete>                        std::set<size_t> &        Out      *
// *    returns the list of privileges to be removed                           *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: No errors are generated                                          *
// *                                                                           *
// *****************************************************************************
void MyTable::getRowsForGrantee(
   const MyRow &baseRow,
   std::vector<MyRow> &masterRowList,
   std::set<size_t> &rowsToDelete)
{
   for (size_t i = 0; i < masterRowList.size(); i++)
   {
      // master list is ordered by component ID, grantorID, granteeID and operationCode
      // If done checking rows for the grantorID_ from the baseRow, just return
      if ((masterRowList[i].componentUID_ == baseRow.componentUID_) &&
          (masterRowList[i].grantorID_ > baseRow.granteeID_))
        break;
 
      // If we have already processed the row or it is a row we are not 
      // interested in - continue
      if (masterRowList[i].visited_ || (masterRowList[i].grantorID_ < baseRow.granteeID_))
        continue;

      // If this is a row we are interested in, add to rowsToDelete
      if ((masterRowList[i].componentUID_ == baseRow.componentUID_) &&
          (masterRowList[i].grantorID_ == baseRow.granteeID_) &&
          (masterRowList[i].operationCode_ == baseRow.operationCode_))
      {
         // no more leaves, done with the branch
         if (masterRowList[i].grantDepth_ == 0)
         {
            masterRowList[i].visited_ = true;
            rowsToDelete.insert(i);
            continue;
         }

         // Privilege was granted WITH GRANT OPTION, see if there is anything 
         // left on the branch to remove. If there are more leaves, check to 
         // see if grantee gets the priv from other grantors (WGO). If so, then 
         // no need to remove rest of branch
         std::vector<size_t> grantList;
         for (size_t g = 0; g < masterRowList.size(); g++)
         {
            // see if this is a row we are interested in
            if ((masterRowList[g].visited_  == false) &&
                (masterRowList[g].componentUID_ == baseRow.componentUID_) &&
                (masterRowList[g].granteeID_ == baseRow.granteeID_) &&
                (masterRowList[g].operationCode_ == baseRow.operationCode_))
            {
              // If this is the base row, skip
              if (masterRowList[g] == baseRow)
                continue;

              // we are interested, save it
              grantList.push_back(g);
            }
         }

         // See if privilege has been granted by another grantor
         if (grantList.size() > 0)
         {
            for (size_t j = 0; j < grantList.size(); j++)
            {
               size_t grantNdx = grantList[j];
               if (masterRowList[grantNdx].grantDepth_ < 0)
               {
                  // this authID has been granted WGO privilege from another user
                  // no need to remove branch
                  masterRowList[i].visited_ = true;
                  break;
               }
            }
         }

         // Check the next branch of privileges
         getRowsForGrantee(masterRowList[i], masterRowList, rowsToDelete);

         // found a leaf to remove
         masterRowList[i].visited_;
         rowsToDelete.insert(i);
      }
   }
}


// *****************************************************************************
// *                                                                           *
// * Function: MyTable::insert                                                 *
// *                                                                           *
// *    Inserts a row into the COMPONENT_PRIVILEGES table.                     *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <rowIn>                         const PrivMgrMDRow &            In       *
// *    is a MyRow to be inserted.                                             *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: PrivStatus                                                       *
// *                                                                           *
// * STATUS_GOOD: Row inserted.                                                *
// *           *: Insert failed. A CLI error is put into the diags area.       *
// *                                                                           *
// *****************************************************************************
PrivStatus MyTable::insert(const PrivMgrMDRow & rowIn)
{

char insertStatement[1000];

const MyRow & row = static_cast<const MyRow &>(rowIn);

   sprintf(insertStatement, "insert into %s values (%d, %d, %ld, '%s', '%s', '%s', %d)",     
           tableName_.c_str(),
           row.granteeID_,
           row.grantorID_,
           row.componentUID_,
           row.operationCode_.c_str(),
           row.granteeName_.c_str(),
           row.grantorName_.c_str(),
           row.grantDepth_);

   return CLIImmediate(insertStatement);

}
//************************** End of MyTable::insert ****************************


// *****************************************************************************
// *                                                                           *
// * Function: MyTable::selectAllWhere                                         *
// *                                                                           *
// *    Selects rows from the COMPONENT_PRIVILEGES table based on the          *
// *  specified WHERE clause and sorted per an optional ORDER BY clause.       *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <whereClause>                   const std::string &             In       *
// *    is the WHERE clause specifying a unique row.                           *
// *                                                                           *
// *  <orderByClause>                 const std::string &             In       *
// *    is an optional ORDER BY clause.                                        *
// *                                                                           *
// *  <rowOut>                        PrivMgrMDRow &                  Out      *
// *    passes back a MyRow.                                                   *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: PrivStatus                                                       *
// *                                                                           *
// * STATUS_GOOD: Row returned.                                                *
// *           *: Select failed. A CLI error is put into the diags area.       *
// *                                                                           *
// *****************************************************************************
PrivStatus MyTable::selectAllWhere(
   const std::string & whereClause,
   const std::string & orderByClause,
   std::vector<MyRow> & rows)
   
{

std::string selectStmt ("SELECT COMPONENT_UID, OPERATION_CODE, GRANTEE_ID, GRANTOR_ID, GRANTEE_NAME, GRANTOR_NAME, GRANT_DEPTH FROM ");  
   selectStmt += tableName_;
   selectStmt += " ";
   selectStmt += whereClause;
   selectStmt += " ";
   selectStmt += orderByClause;
  
Queue * tableQueue = NULL;

PrivStatus privStatus = executeFetchAll(selectStmt,tableQueue);

   if (privStatus == STATUS_ERROR)
      return privStatus;

   tableQueue->position();
   for (int idx = 0; idx < tableQueue->numEntries(); idx++)
   {
      OutputInfo * pCliRow = (OutputInfo*)tableQueue->getNext();
      MyRow row(tableName_);
      setRow(*pCliRow,row);   
      rows.push_back(row);
   }    

  return STATUS_GOOD;

}
//********************** End of MyTable::selectAllWhere ************************



// *****************************************************************************
// *                                                                           *
// * Function: MyTable::selectWhereUnique                                      *
// *                                                                           *
// *    Selects a row from the COMPONENT_PRIVILEGES table based on the         *
// *  specified WHERE clause.                                                  *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <whereClause>                   const std::string &             In       *
// *    is the WHERE clause specifying a unique row.                           *
// *                                                                           *
// *  <rowOut>                        PrivMgrMDRow &                  Out      *
// *    passes back a MyRow.                                                   *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: PrivStatus                                                       *
// *                                                                           *
// * STATUS_GOOD: Row returned.                                                *
// *           *: Select failed. A CLI error is put into the diags area.       *
// *                                                                           *
// *****************************************************************************
PrivStatus MyTable::selectWhereUnique(
   const std::string & whereClause,
   PrivMgrMDRow & rowOut)
   
{

// Generate the select statement
std::string selectStmt ("SELECT COMPONENT_UID, OPERATION_CODE, GRANTEE_ID, GRANTOR_ID, GRANTEE_NAME, GRANTOR_NAME, GRANT_DEPTH FROM ");  
selectStmt += tableName_;
selectStmt += " ";
selectStmt += whereClause;

ExeCliInterface cliInterface(STMTHEAP);

PrivStatus privStatus = CLIFetch(cliInterface,selectStmt);   
   
   if (privStatus != STATUS_GOOD && privStatus != STATUS_WARNING)
      return privStatus;   

char * ptr = NULL;
Lng32 len = 0;
char value[500];
  
MyRow & row = static_cast<MyRow &>(rowOut);
  
   // column 1:  component_uid
   cliInterface.getPtrAndLen(1,ptr,len);
   row.componentUID_ = *(reinterpret_cast<int64_t*>(ptr));

   // column 2:  operation_code
   cliInterface.getPtrAndLen(2,ptr,len);
   strncpy(value,ptr,len);
   value[len] = 0;
   row.operationCode_ = value;

   // column 3:  granteeID
   cliInterface.getPtrAndLen(3,ptr,len);
   row.granteeID_ = *(reinterpret_cast<int32_t*>(ptr));

   // column 4:  grantorID
   cliInterface.getPtrAndLen(4,ptr,len);
   row.grantorID_ = *(reinterpret_cast<int32_t*>(ptr));

   // column 5:  grantee_name
   cliInterface.getPtrAndLen(5,ptr,len);
   strncpy(value,ptr,len);
   value[len] = 0;
   row.granteeName_ = value;

   // column 6:  grantor_name
   cliInterface.getPtrAndLen(6,ptr,len);
   strncpy(value,ptr,len);
   value[len] = 0;
   row.grantorName_ = value;

   // column 7:  grant_depth
   cliInterface.getPtrAndLen(7,ptr,len);
   row.grantDepth_ = *(reinterpret_cast<int32_t*>(ptr));
   
   lastRowRead_ = row;

   return STATUS_GOOD;
   
}
//************************ End of MyTable::selectWhere *************************


// *****************************************************************************
// *                                                                           *
// * Function: MyTable::setRow                                                 *
// *                                                                           *
// *    Sets the fields of a row.                                              *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <cliInterface>                  OutputInfo &                    In       *
// *    is a reference to CLI interface to the row data that was read.         *
// *                                                                           *
// *  <rowOut>                        PrivMgrMDRow &                  Out      *
// *    passes back a MyRow.                                                   *
// *                                                                           *
// *****************************************************************************
void MyTable::setRow(
   OutputInfo & cliInterface,
   PrivMgrMDRow & rowOut)
   
{

MyRow & row = static_cast<MyRow &>(rowOut);
char * ptr = NULL;
int32_t length = 0;
char value[500];
std::string selectStmt ("SELECT COMPONENT_UID, OPERATION_CODE, GRANTEE_ID, GRANTOR_ID, GRANTEE_NAME, GRANTOR_NAME, GRANT_DEPTH FROM ");  
  
   // column 1:  component_uid
   cliInterface.get(0,ptr,length);
   row.componentUID_ = *(reinterpret_cast<int64_t*>(ptr));

   // column 2:  operation_code
   cliInterface.get(1,ptr,length);
   strncpy(value,ptr,length);
   value[length] = 0;
   row.operationCode_ = value;

   // column 3:  grantee_ID
   cliInterface.get(2,ptr,length);
   row.granteeID_ = *(reinterpret_cast<int32_t*>(ptr));

   // column 4:  grantor_ID
   cliInterface.get(3,ptr,length);
   row.grantorID_ = *(reinterpret_cast<int32_t*>(ptr));

   // column 5:  grantee_name
   cliInterface.get(4,ptr,length);
   strncpy(value,ptr,length);
   value[length] = 0;
   row.granteeName_ = value;

   // column 6:  grantor_name
   cliInterface.get(5,ptr,length);
   strncpy(value,ptr,length);
   value[length] = 0;
   row.grantorName_ = value;

   // column 7:  grant_depth
   cliInterface.get(6,ptr,length);
   row.grantDepth_ = *(reinterpret_cast<int32_t*>(ptr));
   
   lastRowRead_ = row;

}
//************************** End of MyTable::setRow ****************************

// *****************************************************************************
//    MyRow methods
// *****************************************************************************

// *****************************************************************************
// *                                                                           *
// * Function: MyRow::describeGrant                                            *
// *                                                                           *
// *    Generates text for the grant based on the row, operationName, and      *
// *    componentName                                                          *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  operationName                    const std::string &                  In *
// *     used for generate grant statement as granted operation.               *
// *                                                                           *
// *  componentName                    const std::string &                  In *
// *    used for generate grant statement on the component.                    *
// *                                                                           *
// *  outlines                         std::vector<std::string> &           Out*
// *      output generated GRANT statements to this array.                     *
// *                                                                           *
// *****************************************************************************
void MyRow::describeGrant(
  const std::string &operationName,
  const std::string &componentName,
  std::vector<std::string> & outlines)
{
   //generate grant statement
   std::string grantText;
   if (grantorID_ == SYSTEM_USER)
      grantText += "-- ";
   grantText += "GRANT COMPONENT PRIVILEGE \"";
   grantText += operationName;
   grantText += "\" ON \"";
   grantText += componentName;
   grantText += "\" TO \"";
   if(granteeID_ == -1)
     grantText += PUBLIC_AUTH_NAME;
   else
     grantText += granteeName_;
   grantText += '"';
   if(grantDepth_ != 0){
     grantText += " WITH GRANT OPTION";
   }
   grantText += ";";
   outlines.push_back(grantText);
}


//************************** End of MyRow::describeGrant ***********************

Looks like we were using the wrong error message before? Thanks for fixing this.