Repository: incubator-trafodion
Updated Branches:
  refs/heads/master 71b1f8cb8 -> addb9b18d


http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/877a8e8a/core/sql/sqlcomp/PrivMgrPrivileges.cpp
----------------------------------------------------------------------
diff --git a/core/sql/sqlcomp/PrivMgrPrivileges.cpp 
b/core/sql/sqlcomp/PrivMgrPrivileges.cpp
index 7b96792..0dbb45b 100644
--- a/core/sql/sqlcomp/PrivMgrPrivileges.cpp
+++ b/core/sql/sqlcomp/PrivMgrPrivileges.cpp
@@ -44,13 +44,11 @@
 #include "ComQueue.h"
 #include "CmpCommon.h"
 #include "CmpContext.h"
-#include "CmpDDLCatErrorCodes.h"
 #include "ComSecurityKey.h"
 #include "NAUserId.h"
 #include "ComUser.h"
 #include "CmpSeabaseDDLutil.h"
 #include "logmxevent_traf.h"
-class ColPrivEntry;
 class ColPrivGrant;
 class ColumnPrivsMDTable;
  
@@ -239,7 +237,7 @@ public:
    void clearVisited() 
    { 
      visited_.setColumnOrdinal(columnOrdinal_);
-     visited_.getPrivDesc().setAllPrivAndWgo(false);
+     visited_.setAllPrivAndWgo(false);
    }
 
 // sets the current entry to match the original privileges
@@ -248,14 +246,14 @@ public:
    { 
      current_.setColumnOrdinal(columnOrdinal_);
      current_.setPrivBitmap(privsBitmap_);
-     current_.setGrantableBitmap(grantableBitmap_);
+     current_.setWgoBitmap(grantableBitmap_);
    }
  
 // compares the current privileges with the visited grant tree to
 // see if there are any broken branches
    NABoolean anyNotVisited() 
    {return current_.getPrivBitmap() != visited_.getPrivBitmap() || 
-           current_.getGrantableBitmap() != visited_.getGrantableBitmap();}
+           current_.getWgoBitmap() != visited_.getWgoBitmap();}
 
 
 // -------------------------------------------------------------------
@@ -272,8 +270,8 @@ public:
    PrivColumnBitmap   privsBitmap_;
    PrivColumnBitmap   grantableBitmap_;
    
-   ColPrivEntry       visited_;
-   ColPrivEntry       current_;
+   PrivMgrCoreDesc    visited_;
+   PrivMgrCoreDesc    current_;
 
 };
 
@@ -354,8 +352,8 @@ void static closeColumnList(std::string & columnList);
 
 static void deleteRowList(std::vector<PrivMgrMDRow *> & rowList);
 
-static ColPrivEntry * findColumnEntry(
-   std::vector<ColPrivEntry> & colPrivsToGrant,
+static PrivMgrCoreDesc * findColumnEntry(
+   NAList<PrivMgrCoreDesc> & colPrivsToGrant,
    const int32_t columnsOrdinal);
    
 static PrivStatus getColRowsForGrantee(
@@ -369,41 +367,14 @@ static void getColRowsForGranteeGrantor(
    const std::vector <PrivMgrMDRow *> & columnRowList,
    const int32_t granteeID,
    const int32_t grantorID,
-   std::vector<ColPrivEntry> &colPrivGrants);
+   NAList<PrivMgrCoreDesc> &colPrivGrants);
    
 static bool hasAllDMLPrivs(
    ComObjectType objectType,
    PrivObjectBitmap privBitmap);   
    
-static bool hasGrantedColumnPriv(
-   const std::vector <PrivMgrMDRow *> & columnRowList,
-   int32_t grantorID,
-   int32_t granteeID,
-   const std::vector<ColPrivSpec> & colPrivsArray,
-   PrivStatus & privStatus,
-   std::string & privilege,
-   std::vector<ColPrivEntry> & grantedColPrivs);   
-  
 static bool isDelimited( const std::string &identifier);
 
-// 
*****************************************************************************
-//    ColPrivEntry constructors
-// 
*****************************************************************************
-ColPrivEntry::ColPrivEntry ( const PrivMgrMDRow &row )
-{
-  PrivMgrMDRow theRow = row;
-  ColumnPrivsMDRow &columnRow = static_cast<ColumnPrivsMDRow &> (theRow);
-  privDesc_.setColumnOrdinal(columnRow.columnOrdinal_);
-  privDesc_.setPrivBitmap(columnRow.privsBitmap_);
-  privDesc_.setWgoBitmap(columnRow.grantableBitmap_);
-  isUpdate_ = false;
-}
-  
-ColPrivEntry::ColPrivEntry ( const ColPrivEntry &other)
-{
-   privDesc_ = other.privDesc_;
-   isUpdate_ = other.isUpdate_;
-}
 
 // 
*****************************************************************************
 //    PrivMgrPrivileges methods
@@ -591,9 +562,8 @@ PrivStatus PrivMgrPrivileges::getPrivsOnObject (
   if (generateColumnRowList() == STATUS_ERROR)
     return STATUS_ERROR;
   
-  // Gets all the grantees from the object and column lists
-  // This list is affected userIDs.  The public auth ID is also included if any
-  // privs were granted. 
+  // Gets all the grantees (userIDs) from the object and column lists
+  // The public auth ID is also included in this list
   std::vector<int32_t> userIDs;
   if (getDistinctUserIDs(objectRowList_, columnRowList_, userIDs) == 
STATUS_ERROR)
     return STATUS_ERROR;
@@ -613,26 +583,13 @@ PrivStatus PrivMgrPrivileges::getPrivsOnObject (
         return STATUS_ERROR;
     }
 
+    // getUserPrivs returns object and column privileges summarized across
+    // all grantors. 
     if (getUserPrivs(objectType, userID, roleIDs, privsOfTheUser,
                      hasManagePrivileges, NULL ) != STATUS_GOOD)
       return STATUS_ERROR;
-
-    PrivColList colPrivsList;
-    PrivColList colGrantableList;
-    if (getColPrivsForUser(userID,roleIDs,colPrivsList,colGrantableList,NULL) 
!= STATUS_GOOD)
-      return STATUS_ERROR;
-
-    // the returned list are in column ordinal order, if no privileges have
-    // been granted on the column, then the bitmap is all zeroes
-    NAList<PrivMgrCoreDesc> colPrivs;
-    for (size_t j = 0; j < colPrivsList.size(); j++)
-    {
-      PrivMgrCoreDesc colPriv(colPrivsList[j], colGrantableList[j], j);
-      colPrivs.insert(colPriv);
-    }
-    privsOfTheUser.setColumnPrivs(colPrivs);
-
-    privDescs.push_back(privsOfTheUser);  
+    
+    privDescs.push_back(privsOfTheUser);
   }
   return STATUS_GOOD;
 }
@@ -718,7 +675,7 @@ void PrivMgrPrivileges::getColRowsForGranteeOrdinal(
   for (size_t i = 0; i < columnRowList.size(); ++i)
   {
     ColumnPrivsMDRow &row = static_cast<ColumnPrivsMDRow &> 
(*columnRowList[i]);
-    ColPrivEntry colPrivGrant;
+    PrivMgrCoreDesc colPrivGrant;
 
     if (row.columnOrdinal_ == columnOrdinal)
     {
@@ -1189,7 +1146,7 @@ char whereClause[1000];
 
 
 // 
*****************************************************************************
-// * Method: grantColumnPrivileges                                
+// * Method: grantColumnPriv                                
 // *                                                       
 // *    Adds or updates a row in the COLUMN_PRIVILEGES table.
 // *                                                       
@@ -1209,93 +1166,22 @@ char whereClause[1000];
 // *           *: Unable to grant privileges, see diags.     
 // *                                                               
 // 
*****************************************************************************
-PrivStatus PrivMgrPrivileges::grantColumnPrivileges(
+PrivStatus PrivMgrPrivileges::grantColumnPriv(
    const ComObjectType objectType,
    const int32_t granteeID,
    const std::string &granteeName,
    const std::string &grantorName,
-   const std::vector<ColPrivSpec> & colPrivsArrayIn,
+   const PrivMgrDesc &privsToGrant,
    const bool isWGOSpecified)
 {
 
   std::string traceMsg;
 
   PrivStatus privStatus = STATUS_GOOD;
-  std::vector<ColPrivSpec> &colPrivsArray = 
-   const_cast<std::vector<ColPrivSpec> &>(colPrivsArrayIn); 
   
   log (__FILE__, "Checking column privileges", -1);
 
-  // get roleIDs for the grantor
-  std::vector<int_32> roleIDs;
-  privStatus = getRoleIDsForUserID(grantorID_,roleIDs);
-  if (privStatus == STATUS_ERROR)
-    return privStatus;
-
-  // Grantor may have WGO from two sources, object-level grants on the object,
-  // and column-level grants.  hasColumnWGO checks both
-  if (!hasColumnWGO(colPrivsArrayIn,roleIDs,privStatus))
-  {
-    if (privStatus == STATUS_NOTFOUND)
-      *pDiags_ << DgSqlCode(-CAT_PRIVILEGE_NOT_GRANTED);
-    else
-      PRIVMGR_INTERNAL_ERROR("Cannot fetch privileges");
-    return STATUS_ERROR;   
-  }
-
-  // Grantor has authority to grant all privileges requested.  See if some of
-  // the grants are already present. (may be adding WGO)
-   
-  // Note, object level grants goes ahead and grants privileges on those object
-  // that the grantor has WGO.  Column level grants return an error if the
-  // grantor does not have WGO on all columns - this is different behavior and
-  // should confer with ANSI SQL standard for which is correct.
-
-  // Object level grants check for a circular dependency.  Should column level
-  // grants to the same? Or should the check be removed from object grants.
-
-  // Get existing column grants from grantor to the specified grantee.
-  std::vector<ColPrivEntry> grantedColPrivs;
-  getColRowsForGranteeGrantor(columnRowList_,
-                              granteeID,grantorID_,
-                              grantedColPrivs);
-                                                 
-  // Merge the column-privilege-to-grant entries (colPrivArray) into one entry 
-  // per column ordinal.
-  //
-  // Example: Given a commands such as 
-  //
-  // GRANT SELECT(COL4),INSERT(COL2,COL4) ON TAB TO USER;
-  // 
-  // three entries are generated by the parser, but only two rows are written; 
 
-  // one for column 2 (insert) and one for column 4 (insert and select).  
-  //
-  // Input may have same column ordinal in multiple entries, but the input is 
-  // guaranteed not to contain same ordinal and privType more than once.
-  std::vector<ColPrivEntry> colPrivsToGrant;
-  for (size_t i = 0; i < colPrivsArray.size(); i++)
-  {
-    const ColPrivSpec &colPrivSpec = colPrivsArray[i];
-      
-    ColPrivEntry *existingEntry = findColumnEntry(colPrivsToGrant,
-                                                  colPrivSpec.columnOrdinal);
-    if (existingEntry != NULL)
-    {
-      existingEntry->setPriv(colPrivSpec.privType, true);
-      if (isWGOSpecified)
-        existingEntry->setGrantable(colPrivSpec.privType, true);
-    }
-    else
-    {
-      ColPrivEntry colPrivToGrant;
-      colPrivToGrant.setColumnOrdinal(colPrivSpec.columnOrdinal);
-      colPrivToGrant.setPriv(colPrivSpec.privType, true);
-      if (isWGOSpecified)
-        colPrivToGrant.setGrantable(colPrivSpec.privType, true);
-            
-      colPrivsToGrant.push_back(colPrivToGrant);
-    }
-  }
+  NAList<PrivMgrCoreDesc> colPrivsToGrant = privsToGrant.getColumnPrivs();
 
   // Verify that view-col <=> referenced_col relationship exists
   if (objectType == COM_VIEW_OBJECT)
@@ -1313,8 +1199,6 @@ PrivStatus PrivMgrPrivileges::grantColumnPrivileges(
     }
   }
 
-  // Walk the list of column privileges to grant, and either insert a new
-  // row in the COLUMN_PRIVILEGES table or update an existing row.  
 
   bool rowWritten = false;
 
@@ -1329,23 +1213,41 @@ PrivStatus PrivMgrPrivileges::grantColumnPrivileges(
     
   ColumnPrivsMDTable columnPrivsTable(columnTableName_,pDiags_);
 
-  // Get privileges on the object - needed for checks later
+  // Get privileges on the object for grantor/grantee
   ObjectPrivsMDRow objRow;
+  PrivObjectBitmap objPrivsBitmap;
+  PrivObjectBitmap objGrantableBitmap;
   privStatus = getGrantedPrivs(granteeID, objRow);
- if (privStatus == STATUS_ERROR)
-    return privStatus;
 
-  for (size_t i = 0; i < colPrivsToGrant.size(); i++)
+  // getGrantedPrivs returns STATUS_GOOD or STATUS_NOTFOUND
+  // if STATUS_NOTFOUND, bitmaps are empty (as initialized above)
+  // if STATUS_GOOD, set current bitmaps
+  if (privStatus == STATUS_GOOD)
   {
-    ColPrivEntry &colPrivToGrant = colPrivsToGrant[i];
+    objPrivsBitmap = objRow.privsBitmap_;
+    objGrantableBitmap = objRow.grantableBitmap_;
+  }
 
-    colPrivToGrant.describe(traceMsg);
-    log (__FILE__, traceMsg, i);
+  // Get existing column grants from grantor to the specified grantee.
+  NAList<PrivMgrCoreDesc> grantedColPrivs;
+  getColRowsForGranteeGrantor(columnRowList_,
+                              granteeID,grantorID_,
+                              grantedColPrivs);
+
+
+  // Walk the list of column privileges to grant, and either insert a new
+  // row in the COLUMN_PRIVILEGES table or update an existing row.  
+  for (size_t i = 0; i < colPrivsToGrant.entries(); i++)
+  {
+    PrivMgrCoreDesc &colPrivToGrant = colPrivsToGrant[i];
+
+    // TBD - add a describe function to PrivMgrCoreDesc and PrivMgrDesc so
+    // information can ge logged.
 
     bool updateOperation = false;
     bool skipOperation = false; 
 
-    ColPrivEntry *grantedColPriv = findColumnEntry(grantedColPrivs, 
colPrivToGrant.getColumnOrdinal());
+    PrivMgrCoreDesc *grantedColPriv = findColumnEntry(grantedColPrivs, 
colPrivToGrant.getColumnOrdinal());
     if (grantedColPriv)
     {
       // An existing row with the same column has been found, it is one of 
four cases:
@@ -1359,7 +1261,7 @@ PrivStatus PrivMgrPrivileges::grantColumnPrivileges(
       // WGO bit set in grantedColPriv is not set in colPrivToGrant - can this 
       // really occur?
       if (colPrivToGrant.getPrivBitmap() == grantedColPriv->getPrivBitmap() &&
-          
grantedColPriv->getPrivDesc().anyNotSet(colPrivToGrant.getPrivDesc()))
+          grantedColPriv->anyNotSet(colPrivToGrant))
       {
          PRIVMGR_INTERNAL_ERROR("trying to remove WGO during grant");
          return STATUS_ERROR;
@@ -1369,20 +1271,19 @@ PrivStatus PrivMgrPrivileges::grantColumnPrivileges(
       // This is an update operation
       if (colPrivToGrant.getPrivBitmap() != grantedColPriv->getPrivBitmap())
       {
-        updateOperation = true;  // Case #1
-        
colPrivToGrant.getPrivDesc().unionOfPrivs(grantedColPriv->getPrivDesc());
+        updateOperation = true; 
+        colPrivToGrant.unionOfPrivs(*grantedColPriv);
       }
          
-      // Privilege bitmaps are the same
       else 
         // Case 3: the privileges match, see if there are any additional WGO 
privs 
         // to set and mark updatable 
         // anyNotSet returns true iff any WGO bit set in colPrivToGrant is not 
set in 
         // grantedColPriv, this means more WGO bits need to be set.
-        if 
(colPrivToGrant.getPrivDesc().anyNotSet(grantedColPriv->getPrivDesc()))
+        if (colPrivToGrant.anyNotSet(*grantedColPriv))
         {
           updateOperation = true; 
-          
colPrivToGrant.getPrivDesc().unionOfPrivs(grantedColPriv->getPrivDesc());
+          colPrivToGrant.unionOfPrivs(*grantedColPriv);
         }
         // Case 4: no changes to priv or WGO bits -  no updates required - skip
         else
@@ -1402,26 +1303,26 @@ PrivStatus PrivMgrPrivileges::grantColumnPrivileges(
     objectUsage.objectType = objectType;
 
     PrivMgrCoreDesc currentPrivs; // creates an empty descriptor
-    PrivMgrCoreDesc tempPrivs(objRow.privsBitmap_, objRow.grantableBitmap_);
+    PrivMgrCoreDesc tempPrivs(objPrivsBitmap, objGrantableBitmap);
     objectUsage.originalPrivs.setTablePrivs(tempPrivs);
     objectUsage.updatedPrivs.setTablePrivs(tempPrivs); 
 
     // Create list of ColumnReferences
     objectUsage.columnReferences = new std::vector<ColumnReference *>;
-    for (size_t i = 0; i < colPrivsToGrant.size(); i++)
+    for (size_t i = 0; i < colPrivsToGrant.entries(); i++)
     {
-       ColPrivEntry &colPrivToGrant = colPrivsToGrant[i];
-       ColPrivEntry *grantedColPriv = findColumnEntry(grantedColPrivs, 
colPrivToGrant.getColumnOrdinal());
+       PrivMgrCoreDesc &colPrivToGrant = colPrivsToGrant[i];
+       PrivMgrCoreDesc *grantedColPriv = findColumnEntry(grantedColPrivs, 
colPrivToGrant.getColumnOrdinal());
 
        ColumnReference *adjustedCol = new ColumnReference;
        adjustedCol->columnOrdinal = colPrivToGrant.getColumnOrdinal();
 
        PrivMgrCoreDesc adjustedPrivs;
        if (grantedColPriv)
-          adjustedPrivs = grantedColPriv->getPrivDesc();
+          adjustedPrivs = *grantedColPriv;
 
        adjustedCol->originalPrivs = adjustedPrivs;
-       adjustedPrivs.unionOfPrivs(colPrivToGrant.getPrivDesc());
+       adjustedPrivs.unionOfPrivs(colPrivToGrant);
        adjustedCol->updatedPrivs = adjustedPrivs;
        objectUsage.columnReferences->push_back(adjustedCol);
     }
@@ -1441,7 +1342,7 @@ PrivStatus PrivMgrPrivileges::grantColumnPrivileges(
     row.grantorID_ = grantorID_; 
     row.grantorName_ = grantorName;
     row.privsBitmap_ = colPrivToGrant.getPrivBitmap();
-    row.grantableBitmap_ = colPrivToGrant.getGrantableBitmap();
+    row.grantableBitmap_ = colPrivToGrant.getWgoBitmap();
     row.columnOrdinal_ = colPrivToGrant.getColumnOrdinal();
 
     if (updateOperation)
@@ -1455,16 +1356,10 @@ PrivStatus PrivMgrPrivileges::grantColumnPrivileges(
     rowWritten = true;
   } 
 
-//TODO: Could issue a warning if no privileges were granted; means all 
-// requested grants already exist.
-   
-// if (!rowWritten)
-      // Report Warning;
-      
-   return STATUS_GOOD;
+  return STATUS_GOOD;
   
 }
-//************* End of PrivMgrPrivileges::grantColumnPrivileges 
****************
+//************* End of PrivMgrPrivileges::grantColumnPriv ****************
 
 
 
@@ -1507,12 +1402,6 @@ PrivStatus PrivMgrPrivileges::grantObjectPriv(
   std::string traceMsg;
   log (__FILE__, "****** GRANT operation begins ******", -1);
 
-  if (objectUID_ == 0)
-  {
-    PRIVMGR_INTERNAL_ERROR("objectUID is 0 for grant command");
-    return STATUS_ERROR;
-  }
-
   // If this grant request is called during the creation of the 
OBJECT_PRIVILEGES
   // table, just return okay.  Fixes a chicken and egg problem.
   char theQuote = '"';
@@ -1538,51 +1427,62 @@ PrivStatus PrivMgrPrivileges::grantObjectPriv(
     return STATUS_ERROR;
   }
 
-  // generate the list of privileges granted to the object and store in class
-  if (generateObjectRowList() == STATUS_ERROR)
-    return STATUS_ERROR;
-
-  // generate the list of privileges granted to columns and store in class
-  if (generateColumnRowList() == STATUS_ERROR)
-    return STATUS_ERROR;
-
-  // get roleIDs for the grantor
+  PrivMgrDesc privsToGrant(granteeID);
+  PrivMgrDesc privsOfTheGrantor(grantorID_);
   std::vector<int_32> roleIDs;
-  retcode = getRoleIDsForUserID(grantorID_,roleIDs);
-  if (retcode == STATUS_ERROR)
+  retcode = initGrantRevoke(objectType, granteeID,
+                            privsList, colPrivsArray,
+                            isAllSpecified, isWGOSpecified, true,
+                            privsToGrant, privsOfTheGrantor, roleIDs);
+  if (retcode != STATUS_GOOD)
     return retcode;
 
-  if (!colPrivsArray.empty())
+  // Make sure the grantor can grant at least one of the requested privileges
+  // SQL Ansi states that privileges that can be granted should be done so
+  // even if some requested privilege are not grantable.
+  // Remove any privsToGrant which are not held GRANTABLE by the Grantor.
+  bool warnNotAll = false;
+  PrivMgrDesc origPrivsToGrant = privsToGrant;
+
+  // if limitToGrantable true ==> some specified privs were not grantable.
+  if ( privsToGrant.limitToGrantable( privsOfTheGrantor ) )
+    warnNotAll = true;
+
+  // If nothing left to grant, we are done.
+  if ( privsToGrant.isNull() )
+  {
+    *pDiags_ << DgSqlCode (-CAT_PRIVILEGE_NOT_GRANTED);
+    return STATUS_ERROR;
+  }
+
+  // grant any column level privileges
+  if ( !privsToGrant.isColumnLevelNull() )
   {
-    retcode = 
grantColumnPrivileges(objectType,granteeID,granteeName,grantorName,
-                                    colPrivsArray,isWGOSpecified);
+    retcode = grantColumnPriv(objectType,granteeID,granteeName,grantorName,
+                              privsToGrant,isWGOSpecified); 
     if (retcode != STATUS_GOOD)
       return retcode;
-    // If only column-level privileges were specified, no problem.  
-    if (privsList.empty())
-    {
-      log (__FILE__, "****** GRANT operation succeeded ******", -1);
-      return STATUS_GOOD;
-    }
   }
-  
-  // verify the privileges list and create a desc to contain them
-  PrivMgrDesc privsToGrant(granteeID);
-  retcode = convertPrivsToDesc(objectType, 
-                               isAllSpecified, 
-                               isWGOSpecified, 
-                               false,
-                               privsList, 
-                               privsToGrant); 
-  if (retcode != STATUS_GOOD)
-    return retcode;
+    
+  // If only column-level privileges were specified, no problem.  
+  if (privsToGrant.getTablePrivs().isNull())
+  {
+    // report any privs not granted
+    if (warnNotAll)
+      reportPrivWarnings(origPrivsToGrant,
+                         privsToGrant,
+                         CAT_NOT_ALL_PRIVILEGES_GRANTED);
 
+    log (__FILE__, "****** GRANT operation succeeded ******", -1);
+    return STATUS_GOOD;
+  }
+  
   // check for circular dependency.  If USERX grants to USERY WGO, then USERY 
   // cannot grant back to USERX. Theoretically, USERX can grant select, update 
   // to USERY and USERY can grant delete, insert to USERX but for simplicity, 
   // we will reject the request independent on the set of privileges involved.
   std::set<int32_t> listOfGrantors;
-  getTreeOfGrantors(grantorID_, listOfGrantors); 
+  getTreeOfGrantors(grantorID_, listOfGrantors);
 
   // If we find the grantee in the list of grantors, return an error
   if (listOfGrantors.find(granteeID) != listOfGrantors.end())
@@ -1593,46 +1493,6 @@ PrivStatus PrivMgrPrivileges::grantObjectPriv(
     return STATUS_ERROR;
   }
 
-  // get privileges for the grantor and make sure the grantor can grant
-  // at least one of the requested privileges
-  //
-  // SQL Ansi states that privileges that can be granted should be done so
-  // even if some requested privilege are not grantable.
-  PrivMgrDesc privsOfTheGrantor(grantorID_);
-  bool hasManagePrivileges;
-  retcode = getUserPrivs(objectType, grantorID_, roleIDs, privsOfTheGrantor, 
-                         hasManagePrivileges, NULL ); 
-  if (retcode != STATUS_GOOD)
-    return retcode;
-  
-  // If null, the grantor has no privileges
-  if ( privsOfTheGrantor.isNull() )
-  {
-     *pDiags_ << DgSqlCode (-CAT_PRIVILEGE_NOT_GRANTED);
-     return STATUS_ERROR;
-   }
-
-  // Remove any privsToGrant which are not held GRANTABLE by the Grantor.
-  // TBD: if not all privileges are grantable, should at least report
-  //      which ones were not granted.
-  bool warnNotAll = false;
-  if ( privsToGrant.limitToGrantable( privsOfTheGrantor ) )
-  {
-    // limitToGrantable true ==> some specified privs were not grantable.
-    if ( isAllSpecified )
-    {
-      // This is ok.  Can specify ALL without having ALL.
-    }
-    else
-      warnNotAll = true;  // Not all the specified privs are grantable.
-  }
-
-  // If nothing left to grant, we are done.
-  if ( privsToGrant.isNull() )
-  {
-    *pDiags_ << DgSqlCode (-CAT_PRIVILEGE_NOT_GRANTED);
-    return STATUS_ERROR;
-  }
 
   // See if grantor has previously granted privileges to the grantee
   bool foundRow = false;
@@ -1663,7 +1523,13 @@ PrivStatus PrivMgrPrivileges::grantObjectPriv(
 
   // nothing to grant - everything is already granted
   if ( result == PrivMgrCoreDesc::NONE )
-    return STATUS_GOOD;
+  {
+    if (warnNotAll)
+      reportPrivWarnings(origPrivsToGrant,
+                         privsToGrant,
+                         CAT_NOT_ALL_PRIVILEGES_GRANTED);
+      return STATUS_GOOD;
+  }
 
   // Internal consistency check.  We should have granted something.
   assert( result != PrivMgrCoreDesc::NEUTRAL );
@@ -1736,6 +1602,11 @@ PrivStatus PrivMgrPrivileges::grantObjectPriv(
     retcode = objectPrivsTable.insert(row);
   }
 
+  if (warnNotAll)
+    reportPrivWarnings(origPrivsToGrant, 
+                       privsToGrant, 
+                       CAT_NOT_ALL_PRIVILEGES_GRANTED);
+
   log (__FILE__, "****** GRANT operation succeeded ******", -1);
 
   return retcode;
@@ -1890,6 +1761,79 @@ PrivStatus privStatus = objectPrivsTable.insert(row);
 }
 
 // 
*****************************************************************************
+// method: initGrantRevoke
+//
+// This method initializes structures needed to complete grant and revoke 
+// operations.
+//
+// It returns:
+//    privsToApply - the list of requested privileges to grant/revoke 
+//    privsOfTheGrantor - privileges of the grantor to be used in later checks
+//
+// It also reads privileges for the object at table and column level from the
+// metadata and stores the results in the class
+// 
*****************************************************************************
+PrivStatus PrivMgrPrivileges::initGrantRevoke(
+    const ComObjectType objectType,
+    const int32_t granteeID,
+    const std::vector<PrivType> &privList,
+    const std::vector<ColPrivSpec> & colPrivsArray,
+    const bool isAllSpecified,
+    const bool isGOSpecified,
+    const bool isGrant,
+    PrivMgrDesc &privsToApply,
+    PrivMgrDesc &privsOfTheGrantor,
+    std::vector<int32_t> & roleIDs)
+{
+  if (objectUID_ == 0)
+  {
+    PRIVMGR_INTERNAL_ERROR("objectUID is 0 for grant or revoke command");
+    return STATUS_ERROR;
+  }
+
+  // Generate the list of privilege descriptors that were requested 
+  PrivStatus retcode = convertPrivsToDesc(objectType,
+                               isAllSpecified,
+                               (isGrant) ? isGOSpecified : true, // WGO
+                               (isGrant) ? false : isGOSpecified, // GOF
+                               privList,
+                               colPrivsArray,
+                               privsToApply);
+  if (retcode != STATUS_GOOD)
+    return retcode;
+
+ // generate the list of privileges granted to the object and store in class
+  if (generateObjectRowList() == STATUS_ERROR)
+    return STATUS_ERROR;
+    
+  // generate the list of privileges granted to object columns and store in 
class
+  if (generateColumnRowList() == STATUS_ERROR)
+    return STATUS_ERROR; 
+    
+  // get roleIDs for the grantor
+  retcode = getRoleIDsForUserID(grantorID_,roleIDs);
+  if (retcode == STATUS_ERROR)
+    return retcode;
+
+  // get column and object privileges across all grantors 
+  bool hasManagePrivileges;
+  retcode = getUserPrivs(objectType, grantorID_, roleIDs, privsOfTheGrantor,
+                         hasManagePrivileges, NULL );
+  if (retcode != STATUS_GOOD)
+    return retcode;
+
+  // If null, the grantor has no privileges
+  if ( privsOfTheGrantor.isNull() )
+  {
+    *pDiags_ << DgSqlCode ((isGrant) ? -CAT_PRIVILEGE_NOT_GRANTED : 
-CAT_PRIVILEGE_NOT_REVOKED);
+    return STATUS_ERROR;
+  }
+
+  return STATUS_GOOD;
+}
+
+
+// 
*****************************************************************************
 // * Method: insertPrivRowsForObject                                
 // *                                                       
 // *    writes rows that add grants of privileges for an object.
@@ -2833,7 +2777,7 @@ PrivStatus PrivMgrPrivileges::getAffectedObjects(
 // ----------------------------------------------------------------------------
 // method: getGrantedPrivs
 //
-// This method reads the metadata to get privilege information for the
+// This method searches the list of object privs to get information for the
 // object, grantor, and grantee.
 //
 // input:  granteeID
@@ -3048,7 +2992,7 @@ PrivMgrRoles 
roles(trafMetadataLocation_,metadataLocation_,pDiags_);
 }
 
 // 
*****************************************************************************
-// * Method: revokeColumnPrivileges                                
+// * Method: revokeColumnPriv                                
 // *                                                       
 // *    Adds or updates a row in the COLUMN_PRIVILEGES table.
 // *                                                       
@@ -3068,12 +3012,12 @@ PrivMgrRoles 
roles(trafMetadataLocation_,metadataLocation_,pDiags_);
 // *           *: Unable to revoke privileges, see diags.     
 // *                                                               
 // 
*****************************************************************************
-PrivStatus PrivMgrPrivileges::revokeColumnPrivileges(
+PrivStatus PrivMgrPrivileges::revokeColumnPriv(
    const ComObjectType objectType,
    const int32_t granteeID,
    const std::string & granteeName,
    const std::string & grantorName,
-   const std::vector<ColPrivSpec> & colPrivsArrayIn,
+   const PrivMgrDesc & privsToRevoke,
    const bool isWGOSpecified)
 {
 
@@ -3081,99 +3025,15 @@ PrivStatus PrivMgrPrivileges::revokeColumnPrivileges(
 
   log (__FILE__, "checking column privileges", -1);
 
-  std::vector<ColPrivSpec> &colPrivsArray = 
-    const_cast<std::vector<ColPrivSpec> &>(colPrivsArrayIn); 
-  ColumnPrivsMDTable columnPrivsTable(columnTableName_,pDiags_);
-  std::string privilege;
-  std::vector<ColPrivEntry> grantedColPrivs;
-
-  // get the list of object privileges for the object
-  if (generateObjectRowList() == STATUS_ERROR)
-    return STATUS_ERROR;
-
-  // get the list of column privileges for the object
-  if (generateColumnRowList() == STATUS_ERROR)
-    return STATUS_ERROR;
-
-  // First verify the grantor has granted all the privileges they wish to 
revoke.
-  // If not, report the first privilege that cannot be revoked.
-   if (!hasGrantedColumnPriv(columnRowList_,grantorID_,granteeID,
-                             
colPrivsArrayIn,privStatus,privilege,grantedColPrivs))
-   {
-      if (privStatus == STATUS_NOTFOUND)
-      {
-         std::string privOnObject(privilege + " on ");
-         
-         privOnObject += objectName_;
-         
-         *pDiags_ << DgSqlCode(-CAT_GRANT_NOT_FOUND) 
-                  << DgString0(privOnObject.c_str()) 
-                  << DgString1(grantorName.c_str()) 
-                  << DgString2(granteeName.c_str());
-         return STATUS_ERROR;
-      }
-   
-      return privStatus;
-   }
-   
-   // Create a privsToRevoke array using the passed in revoke entries and the
-   // list of currently granted column privileges.  Combine multiple 
privileges 
-   // for the same column into one entry.
-
-   std::vector<ColPrivEntry> colPrivsToRevoke;
-
-   for (size_t i = 0; i < colPrivsArray.size(); i++)
-   {
-      const ColPrivSpec &colPrivSpec = colPrivsArray[i];
-      PrivType privType = colPrivSpec.privType;
-      int32_t columnOrdinal = colPrivSpec.columnOrdinal;
-      
-      // Find the priv details from metadata
-      ColPrivEntry *metadataEntry = findColumnEntry(grantedColPrivs,
-                                                    columnOrdinal);
-      if (metadataEntry == NULL)
-      { 
-         PRIVMGR_INTERNAL_ERROR("Privilege to revoke not found");
-         return STATUS_ERROR;
-      }
-
-      // See if privilege entry has already been created
-      ColPrivEntry *existingEntry = findColumnEntry(colPrivsToRevoke,
-                                                    columnOrdinal);
-      if (existingEntry != NULL)
-      {
-         existingEntry->setPriv(privType, true);
-
-         // if revoking a privilege and auth ID has WGO, then revoke 
-         // the WGO bit also
-         PrivColumnBitmap grantableBitmap = 
metadataEntry->getGrantableBitmap();
-         existingEntry->setGrantable(privType, grantableBitmap.test(privType));
-      }
-      else
-      {
-         ColPrivEntry colPrivToRevoke;
-         
-         colPrivToRevoke.setColumnOrdinal(columnOrdinal);   
-         if (isWGOSpecified)
-         {
-           colPrivToRevoke.setPriv(privType,false);
-           colPrivToRevoke.setGrantable(privType, true);
-         }
-         else
-         {
-           colPrivToRevoke.setPriv(privType,true);
-           // if revoking a privilege and auth ID has WGO, then revoke 
-           // the WGO bit also
-           colPrivToRevoke.setGrantable(privType, 
metadataEntry->getGrantableBitmap().test(privType));
-         }
+  NAList<PrivMgrCoreDesc> colPrivsToRevoke = privsToRevoke.getColumnPrivs();
 
-         colPrivsToRevoke.push_back(colPrivToRevoke);
-      }
-   }
+  // Get existing column grants from grantor to the specified grantee.
+  NAList<PrivMgrCoreDesc> grantedColPrivs;
+  getColRowsForGranteeGrantor(columnRowList_,
+                              granteeID,grantorID_,
+                              grantedColPrivs);
 
-   // checks to see if can revoke if there are referenced items when
-   // revoke cascade is supported, this returns the list of referenced
-   // items that need to change. 
+   // set up the object usage 
    ObjectUsage objectUsage;
    objectUsage.objectUID = objectUID_;
    objectUsage.granteeID = granteeID;
@@ -3182,34 +3042,107 @@ PrivStatus PrivMgrPrivileges::revokeColumnPrivileges(
 
    // Create list of ColumnReferences
    objectUsage.columnReferences = new std::vector<ColumnReference *>;
-   for (size_t i = 0; i < colPrivsToRevoke.size(); i++)
+   for (size_t i = 0; i < colPrivsToRevoke.entries(); i++)
    {
-      ColPrivEntry &colPrivToRevoke = colPrivsToRevoke[i];
-      ColPrivEntry *grantedColPriv = findColumnEntry(grantedColPrivs, 
colPrivToRevoke.getColumnOrdinal());
+      PrivMgrCoreDesc &colPrivToRevoke = colPrivsToRevoke[i];
+      PrivMgrCoreDesc *grantedColPriv = findColumnEntry(grantedColPrivs, 
colPrivToRevoke.getColumnOrdinal());
       if (grantedColPriv)
       {
-         ColumnReference *adjustedCol = new ColumnReference;
-         adjustedCol->columnOrdinal = colPrivToRevoke.getColumnOrdinal();
-         adjustedCol->originalPrivs = grantedColPriv->getPrivDesc();     
-         PrivMgrCoreDesc adjustedPrivs = grantedColPriv->getPrivDesc();
-         adjustedPrivs.AndNot(colPrivToRevoke.getPrivDesc());
-         adjustedCol->updatedPrivs = adjustedPrivs;
-         objectUsage.columnReferences->push_back(adjustedCol);
-      }
-   }
+        if (colPrivToRevoke.anyNotSet(*grantedColPriv))
+        {
+          // sanity check -> verify that privileges to revoke actually are set
+          // in the granted list 
+          for (size_t p = FIRST_DML_COL_PRIV; p <= LAST_DML_COL_PRIV; p++ )
+          {
+            PrivType type = (PrivType)p;
+
+            // If trying to revoke a privilege that is not granted or 
+            // if trying to revoke grant option that is not granted, report it
+            //if ((colPrivToRevoke.getPriv(type) && 
!grantedColPriv->getPriv(type)) ||
+            //    (!colPrivToRevoke.getPriv(type) && 
colPrivToRevoke.getWgo(type) && !grantedColPriv->getWgo(type)))
+            bool printWarning = false;
+            bool printWgo = false;
+            if (colPrivToRevoke.getPriv(type))
+            {
+              if ( !grantedColPriv->getPriv(type))
+                printWarning = true;
+            }
+            else
+            {
+              if (colPrivToRevoke.getWgo(type) && 
!grantedColPriv->getWgo(type))
+              {
+                printWarning = true;
+                printWgo = true;
+              }
+            }
 
-   // get privileges for the object, if they exist
-   ObjectPrivsMDRow row;
-   privStatus = getGrantedPrivs(granteeID, row);
-   if (privStatus == STATUS_GOOD)
-   {
-     PrivMgrCoreDesc coreDesc(row.privsBitmap_, row.grantableBitmap_);
-     objectUsage.originalPrivs.setTablePrivs(coreDesc);
-     objectUsage.updatedPrivs.setTablePrivs(coreDesc); 
-   }
-   
-   if ( updateDependentObjects(objectUsage, 
PrivCommand::REVOKE_COLUMN_RESTRICT) == STATUS_ERROR)
-     return STATUS_ERROR;
+            if (printWarning)
+            {
+              char buf[1000];
+              sprintf(buf, "%s %s (columm number %d) on %s",
+                            
PrivMgrUserPrivs::convertPrivTypeToLiteral(type).c_str(),
+                            (colPrivToRevoke.getWgo(type)) ? "WITH GRANT 
OPTION" : "",
+                            colPrivToRevoke.getColumnOrdinal(), 
objectName_.c_str());
+              *pDiags_ << DgSqlCode(CAT_GRANT_NOT_FOUND)
+                       << DgString0(buf)
+                       << DgString1(grantorName.c_str())
+                       << DgString2(granteeName.c_str());
+            }
+          }
+        }
+        ColumnReference *adjustedCol = new ColumnReference;
+        adjustedCol->columnOrdinal = colPrivToRevoke.getColumnOrdinal();
+        adjustedCol->originalPrivs = *grantedColPriv;     
+        PrivMgrCoreDesc adjustedPrivs = *grantedColPriv;
+        adjustedPrivs.AndNot(colPrivToRevoke);
+        adjustedCol->updatedPrivs = adjustedPrivs;
+        objectUsage.columnReferences->push_back(adjustedCol);
+      }
+      else
+      {
+        // report errors for any missing grants
+        for (size_t p = FIRST_DML_COL_PRIV; p <= LAST_DML_COL_PRIV; p++ )
+        {
+          // If trying to revoke a privilege that is not granted or 
+          // if trying to revoke grant option that is not granted, report it
+          if (colPrivToRevoke.getPriv((PrivType)p) || 
colPrivToRevoke.getWgo((PrivType)p))
+          {
+            char buf[1000];
+            sprintf(buf, "%s %s (columm number %d) on %s",
+                          
PrivMgrUserPrivs::convertPrivTypeToLiteral((PrivType)p).c_str(),
+                          (colPrivToRevoke.getWgo((PrivType)p)) ? "WITH GRANT 
OPTION" : "",
+                          colPrivToRevoke.getColumnOrdinal(), 
objectName_.c_str());
+            *pDiags_ << DgSqlCode(CAT_GRANT_NOT_FOUND)
+                     << DgString0(buf)
+                     << DgString1(grantorName.c_str())
+                     << DgString2(granteeName.c_str());
+          }
+        }
+      }
+   }
+
+   if (objectUsage.columnReferences->size() == 0)
+     return STATUS_GOOD;
+
+   // Get privileges on the object for grantor/grantee
+   ObjectPrivsMDRow objRow;
+   privStatus = getGrantedPrivs(granteeID, objRow);
+
+   // getGrantedPrivs returns STATUS_GOOD or STATUS_NOTFOUND
+   // if STATUS_NOTFOUND, bitmaps are empty (as initialized above)
+   // if STATUS_GOOD, set current bitmaps
+   if (privStatus == STATUS_GOOD)
+   {
+     PrivMgrCoreDesc coreDesc(objRow.privsBitmap_, objRow.grantableBitmap_);
+     objectUsage.originalPrivs.setTablePrivs(coreDesc);
+     objectUsage.updatedPrivs.setTablePrivs(coreDesc); 
+   }
+   
+   // check to see if can revoke if there are referenced items when
+   // revoke cascade is supported, this returns the list of referenced
+   // items that need to change. 
+   if ( updateDependentObjects(objectUsage, 
PrivCommand::REVOKE_COLUMN_RESTRICT) == STATUS_ERROR)
+     return STATUS_ERROR;
    
    // At this point we have an array of privsToRevoke with column ordinal and 
    // priv bitmap.
@@ -3245,26 +3178,25 @@ PrivStatus PrivMgrPrivileges::revokeColumnPrivileges(
    whereBase += authIDToString(granteeID);
    whereBase += " AND column_number = ";
     
-   for (size_t i = 0; i < colPrivsToRevoke.size(); i++)
+   ColumnPrivsMDTable columnPrivsTable(columnTableName_,pDiags_);
+
+   for (size_t i = 0; i < colPrivsToRevoke.entries(); i++)
    {
-      ColPrivEntry &colPrivToRevoke = colPrivsToRevoke[i];
+      PrivMgrCoreDesc &colPrivToRevoke = colPrivsToRevoke[i];
       bool updateRow = false;
       bool deleteRow = false;
 
       // Look for any existing granted privileges on the column for which
       // privileges are to be granted.
-      ColPrivEntry *grantedColPriv = findColumnEntry(grantedColPrivs, 
colPrivToRevoke.getColumnOrdinal());
+      PrivMgrCoreDesc *grantedColPriv = findColumnEntry(grantedColPrivs, 
colPrivToRevoke.getColumnOrdinal());
       if (grantedColPriv)
       {
          // Found row with grant for this column.
          
-         // Verify privilege(s) being revoked was/were granted.  If not, 
internal error.
+         // Verify privilege(s) being revoked was/were granted.  If not, 
continue
          if (!isWGOSpecified && 
              ((colPrivToRevoke.getPrivBitmap() & 
grantedColPriv->getPrivBitmap()) == 0))
-         {
-            PRIVMGR_INTERNAL_ERROR("Privilege to revoke not found");
-            return STATUS_ERROR;
-         }
+            continue;
          
          // If all privileges are revoked, delete corresponding row
          if (!isWGOSpecified && 
@@ -3275,8 +3207,8 @@ PrivStatus PrivMgrPrivileges::revokeColumnPrivileges(
 
          // generate the final bitmaps to store in metadata
          // removing any privileges that already have been revoked
-         PrivMgrCoreDesc adjustedPrivs = grantedColPriv->getPrivDesc();
-         adjustedPrivs.AndNot(colPrivToRevoke.getPrivDesc());
+         PrivMgrCoreDesc adjustedPrivs = *grantedColPriv;
+         adjustedPrivs.AndNot(colPrivToRevoke);
 
          // If only removing WGO, then the privsBitmap does not change
          // Not sure if this is needed ??
@@ -3285,13 +3217,20 @@ PrivStatus PrivMgrPrivileges::revokeColumnPrivileges(
 
          // set adjusted privileges
          colPrivToRevoke.setPrivBitmap(adjustedPrivs.getPrivBitmap());
-         colPrivToRevoke.setGrantableBitmap(adjustedPrivs.getWgoBitmap());
+         colPrivToRevoke.setWgoBitmap(adjustedPrivs.getWgoBitmap());
 
          // Using the list of privs to revoke, change so adjustedPrivs contains
          // Some privileges may have been requested to revoke that aren't
          // currently granted - flip adjusted bits to final list of privs
          revokedPrivs |= adjustedPrivs.getPrivBitmap(); 
       }
+      else
+      {
+         // The row should exist in "grantedColPrivs" 
+         PRIVMGR_INTERNAL_ERROR("Column privilege not found to revoke");
+         return STATUS_ERROR;
+      }   
+
       
       if (deleteRow)
       {
@@ -3320,7 +3259,7 @@ PrivStatus PrivMgrPrivileges::revokeColumnPrivileges(
       row.grantorID_ = grantorID_; 
       row.grantorName_ = grantorName;
       row.privsBitmap_ = colPrivToRevoke.getPrivBitmap();
-      row.grantableBitmap_ = colPrivToRevoke.getGrantableBitmap();
+      row.grantableBitmap_ = colPrivToRevoke.getWgoBitmap();
       row.columnOrdinal_ = colPrivToRevoke.getColumnOrdinal();
 
       privStatus = columnPrivsTable.updateColumnRow(row,whereBase);
@@ -3360,7 +3299,7 @@ PrivStatus PrivMgrPrivileges::revokeColumnPrivileges(
    return STATUS_GOOD;
 
 }
-//************* End of PrivMgrPrivileges::revokeColumnPrivileges 
***************
+//************* End of PrivMgrPrivileges::revokeColumnPriv ***************
 
 
 // 
*****************************************************************************
@@ -3398,90 +3337,25 @@ PrivStatus PrivMgrPrivileges::revokeObjectPriv (const 
ComObjectType objectType,
   std::string traceMsg;
   log (__FILE__, "****** REVOKE operation begins ******", -1);
 
-  if (objectUID_ == 0)
-  {
-    PRIVMGR_INTERNAL_ERROR("objectUID is 0 for revoke command");
-    return STATUS_ERROR;
-  }
-
-  // get roleIDs for grantor
-  std::vector<int_32> roleIDs;
-  retcode = getRoleIDsForUserID(grantorID_,roleIDs);
-  if (retcode == STATUS_ERROR)
-    return retcode;
-
-  if (!colPrivsArray.empty())
-  {
-    retcode = revokeColumnPrivileges(objectType,granteeID,granteeName,
-                                     grantorName,colPrivsArray,isGOFSpecified);
-    if (retcode != STATUS_GOOD)
-      return retcode;
-    
-    // If only column-level privileges were specified, no problem.  
-    if (privsList.empty())
-    {
-      log (__FILE__, "****** REVOKE operation succeeded ******", -1);
-      return STATUS_GOOD;
-    }
-  }
-  
-  // Convert the privsList into a PrivMgrDesc
-  // convertPrivsToDesc sets up any errors in the diags area
-  
-  // revokeWGOWithPriv and isGOFSpecified interaction:
-  //    isGOFSpecified is true if only GRANT OPTION FOR is being revoked.
-  //       The privilege will still be available but the user can no longer
-  //       grant the privilege to others.
-  //    revokeWGOWithPriv is always set to true.  This means that both the
-  //       priv and wgo is revoked.  It does not make sense to revoke the priv
-  //       and not the WITH GRANT OPTION option.
-  bool revokeWGOWithPriv = true;
   PrivMgrDesc privsToRevoke(granteeID);
-  retcode = convertPrivsToDesc(objectType, 
-                               isAllSpecified, 
-                               revokeWGOWithPriv, 
-                               isGOFSpecified, 
-                               privsList, 
-                               privsToRevoke); 
-  if (retcode != STATUS_GOOD)
-    return retcode;
-
-
-  // get all privilege descriptors for the object
-  if (generateObjectRowList() == STATUS_ERROR)
-    return STATUS_ERROR;
-
-  // generate the list of privileges granted to columns and store in class
-  if (generateColumnRowList() == STATUS_ERROR)
-    return STATUS_ERROR;
-
-  // get privileges for the grantor and make sure the grantor can revoke
-  // at least one of the requested privileges
   PrivMgrDesc privsOfTheGrantor(grantorID_);
-  bool hasManagePrivileges;
-  retcode = getUserPrivs(objectType, grantorID_, roleIDs, privsOfTheGrantor, 
-                         hasManagePrivileges, NULL ); 
+  std::vector<int_32> roleIDs;
+  retcode = initGrantRevoke(objectType, granteeID,
+                            privsList, colPrivsArray,
+                            isAllSpecified, isGOFSpecified, false,
+                            privsToRevoke, privsOfTheGrantor, roleIDs);
   if (retcode != STATUS_GOOD)
     return retcode;
 
-  // If null, the grantor has no privileges
-  if ( privsOfTheGrantor.isNull() )
-  {
-     *pDiags_ << DgSqlCode (-CAT_PRIVILEGE_NOT_REVOKED);
-     return STATUS_ERROR;
-   }
-
   // Remove any privsToRevoke which are not held grantable by the Grantor.
   // If limitToGrantable returns true, some privs are not revokable.
   bool warnNotAll = false;
+  PrivMgrDesc origPrivsToRevoke = privsToRevoke;
   if ( privsToRevoke.limitToGrantable( privsOfTheGrantor ) )
   {
-    if ( isAllSpecified )
-    {
-      // This is ok.  Can specify ALL without having all privileges set.
-    }
-    else
-      warnNotAll = true;  // Not all the specified privs can be revoked
+     // This is ok.  Can specify ALL without having all privileges set.
+     if (!isAllSpecified )
+       warnNotAll = true;  // Not all the specified privs can be revoked
   }
 
   // If nothing left to revoke, we are done.
@@ -3491,9 +3365,33 @@ PrivStatus PrivMgrPrivileges::revokeObjectPriv (const 
ComObjectType objectType,
     return STATUS_ERROR;
   }
 
+  // revoke any column level privileges
+  if ( !privsToRevoke.isColumnLevelNull() )
+  {
+    retcode = revokeColumnPriv(objectType,granteeID,granteeName,
+                               grantorName,privsToRevoke,isGOFSpecified);
+    if (retcode != STATUS_GOOD)
+      return retcode;
+  }
+    
+  // If only column-level privileges were specified, no problem.  
+  if (privsToRevoke.getTablePrivs().isNull())
+  {
+    // report any privs not granted
+    if (warnNotAll)
+      reportPrivWarnings(origPrivsToRevoke,
+                         privsToRevoke,
+                         CAT_NOT_ALL_PRIVILEGES_REVOKED);
+    log (__FILE__, "****** REVOKE operation succeeded ******", -1);
+    return STATUS_GOOD;
+  }
+
   // See if grantor has previously granted privileges to the grantee
   ObjectPrivsMDRow row;
   retcode = getGrantedPrivs(granteeID, row);
+  if (retcode == STATUS_ERROR)
+    return retcode;
+
   if (retcode == STATUS_NOTFOUND)
   {
     // Set up parameters for the error message: privileges, grantor, & grantee
@@ -3502,7 +3400,6 @@ PrivStatus PrivMgrPrivileges::revokeObjectPriv (const 
ComObjectType objectType,
     for (size_t i = 0; i < privsList.size(); i++)
       privListStr += PrivMgrUserPrivs::convertPrivTypeToLiteral(privsList[i]) 
+ ", ";
     
-    // Remove the last ", "
     privListStr.erase(privListStr.length()-2, privListStr.length());
     if (isGOFSpecified)
       privListStr += " WITH GRANT OPTION";
@@ -3511,10 +3408,9 @@ PrivStatus PrivMgrPrivileges::revokeObjectPriv (const 
ComObjectType objectType,
              << DgString0 (privListStr.c_str())
              << DgString1 (grantorName.c_str())
              <<DgString2 (granteeName.c_str());
+  
     return STATUS_WARNING;
   }
-  if (retcode != STATUS_GOOD)
-    return retcode;
 
   // if privileges exist, set currentPrivs to existing list
   // save a copy of the original privs
@@ -3561,7 +3457,7 @@ PrivStatus PrivMgrPrivileges::revokeObjectPriv (const 
ComObjectType objectType,
     return STATUS_ERROR;
 
   ObjectPrivsMDTable objectPrivsTable (objectTableName_, pDiags_);
-  if (privsToRevoke.isNull())
+  if (privsToRevoke.getTablePrivs().isNull())
   {
     row.describeRow(traceMsg);
     traceMsg.insert(0, "deleting privilege row ");
@@ -3589,7 +3485,9 @@ PrivStatus PrivMgrPrivileges::revokeObjectPriv (const 
ComObjectType objectType,
   // even if some requested privilege are not revokable.
   // TDB:  report which privileges were not revoked
   if (warnNotAll)
-    *pDiags_ << DgSqlCode(CAT_NOT_ALL_PRIVILEGES_REVOKED);
+      reportPrivWarnings(origPrivsToRevoke,
+                         privsToRevoke,
+                         CAT_NOT_ALL_PRIVILEGES_REVOKED);
 
   log (__FILE__, "****** REVOKE operation succeeded ******", -1);
 
@@ -3856,7 +3754,7 @@ void PrivMgrPrivileges::scanPublic( const PrivType pType, 
// in
 // 
---------------------------------------------------------------------------- 
 bool PrivMgrPrivileges::checkColumnRevokeRestrict (
   int32_t granteeID,
-  const std::vector<ColPrivEntry> &colPrivsToRevoke,
+  const NAList<PrivMgrCoreDesc> &colPrivsToRevoke,
   std::vector <PrivMgrMDRow *> &rowList )
 {
   std::string traceMsg;
@@ -3877,16 +3775,17 @@ bool PrivMgrPrivileges::checkColumnRevokeRestrict (
         currentRow.granteeID_ == granteeID)
     {
       // Adjust rows that have had their privileges updated
-      for (int32_t j = 0; j < colPrivsToRevoke.size(); j++)
+      for (int32_t j = 0; j < colPrivsToRevoke.entries(); j++)
       {
-        ColPrivEntry updatedEntry = (ColPrivEntry)colPrivsToRevoke[j];
+        PrivMgrCoreDesc updatedEntry = (PrivMgrCoreDesc)colPrivsToRevoke[j];
 
         if (updatedEntry.getColumnOrdinal() == currentRow.columnOrdinal_)
         {
           PrivColumnBitmap newPrivBitmap = updatedEntry.getPrivBitmap() ^= 
currentRow.privsBitmap_;
-          PrivColumnBitmap newGrantableBitmap = 
updatedEntry.getGrantableBitmap() ^= currentRow.grantableBitmap_;
+          PrivColumnBitmap temp = updatedEntry.getWgoBitmap().flip();
+          PrivColumnBitmap newGrantableBitmap =  temp &= 
currentRow.grantableBitmap_;
           currentRow.current_.setPrivBitmap(newPrivBitmap);
-          currentRow.current_.setGrantableBitmap(newGrantableBitmap);
+          currentRow.current_.setWgoBitmap(newGrantableBitmap);
           traceMsg = "Adjusted current_ to reflect revoked privileges";
           traceMsg += ", grantor is ";
           traceMsg += to_string((long long int)currentRow.grantorID_);
@@ -3913,9 +3812,9 @@ bool PrivMgrPrivileges::checkColumnRevokeRestrict (
   // reconstruction, only look at rows that have changes.  
   // std::set does not add entries if they already exist.
   std::set<int32_t> listOfColumnOrdinals;
-  for ( size_t i = 0; i < colPrivsToRevoke.size(); i++)
+  for ( size_t i = 0; i < colPrivsToRevoke.entries(); i++)
   {
-    ColPrivEntry colPrivToRevoke = colPrivsToRevoke[i];
+    PrivMgrCoreDesc colPrivToRevoke = colPrivsToRevoke[i];
     listOfColumnOrdinals.insert(colPrivToRevoke.getColumnOrdinal());
   }
 
@@ -4009,7 +3908,7 @@ void PrivMgrPrivileges::scanColumnBranch( const PrivType 
pType,
 
       // Just look at rows that have had privileges changed
       // The listOfColumnOrdinals has this list
-      ColPrivEntry current = currentRow.current_;
+      PrivMgrCoreDesc current = currentRow.current_;
       std::set<int32_t>::iterator it;
       it = std::find(listOfColumnOrdinals.begin(), listOfColumnOrdinals.end(), 
current.getColumnOrdinal());
       if (it != listOfColumnOrdinals.end())
@@ -4019,15 +3918,15 @@ void PrivMgrPrivileges::scanColumnBranch( const 
PrivType pType,
           // This grantee has priv.  Set corresponding visited flag.
           currentRow.visited_.setPriv(pType, true);
 
-          if ( current.getGrantableBitmap().test(pType))
+          if ( current.getWgoBitmap().test(pType))
           {
             // This grantee has wgo.  
-            if ( currentRow.visited_.getGrantableBitmap().test(pType) )
+            if ( currentRow.visited_.getWgoBitmap().test(pType) )
             {   // Already processed this subtree.
             }
             else
             {
-              currentRow.visited_.setGrantable(pType, true);
+              currentRow.visited_.setWgo(pType, true);
  
               // To check:  since column level privileges do not have
               // an anchor, we choose the object owner as the root.
@@ -4075,7 +3974,7 @@ void PrivMgrPrivileges::scanColumnPublic(
 
       // Just look at rows that have had privileges changed
       // The listOfColumnOrdinals has this list
-      ColPrivEntry current = currentRow.current_;
+      PrivMgrCoreDesc current = currentRow.current_;
       std::set<int32_t>::iterator it;
       it = std::find(listOfColumnOrdinals.begin(), listOfColumnOrdinals.end(), 
current.getColumnOrdinal());
       if (it != listOfColumnOrdinals.end())
@@ -4086,8 +3985,8 @@ void PrivMgrPrivileges::scanColumnPublic(
            currentRow.visited_.setPriv(pType, true);
 
             // This grantee has wgo.  
-            if ( currentRow.visited_.getGrantableBitmap().test(pType) )
-              currentRow.visited_.setGrantable(pType, true);
+            if ( currentRow.visited_.getWgoBitmap().test(pType) )
+              currentRow.visited_.setWgo(pType, true);
         }
       }
    }  // end scan privsList over all Grantees/Grantors
@@ -4347,10 +4246,14 @@ PrivStatus PrivMgrPrivileges::getPrivsOnObjectForUser(
     return STATUS_ERROR;
   }
 
- // generate the list of privileges granted to the object and store in class
+  // generate the list of privileges granted to the object and store in class
   if (generateObjectRowList() == STATUS_ERROR)
     return STATUS_ERROR;
 
+  // generate the list of column-level privileges granted to the object and 
store in class
+  if (generateColumnRowList() == STATUS_ERROR)
+    return STATUS_ERROR;
+
   objectUID_ = objectUID;
   PrivMgrDesc privsOfTheUser(userID);
   bool hasManagePrivileges = false;
@@ -4372,20 +4275,19 @@ PrivStatus PrivMgrPrivileges::getPrivsOnObjectForUser(
     return STATUS_GOOD; 
   }
     
- // generate the list of column-level privileges granted to the object and 
store in class
-  if (generateColumnRowList() == STATUS_ERROR)
-    return STATUS_ERROR;
-
-  retcode = 
getColPrivsForUser(userID,roleIDs,colPrivsList,colGrantableList,secKeySet);
-  if (retcode != STATUS_GOOD)
-    return retcode;
-
   userPrivs = privsOfTheUser.getTablePrivs().getPrivBitmap();
   if (hasManagePrivileges)
     grantablePrivs = userPrivs;
   else
     grantablePrivs = privsOfTheUser.getTablePrivs().getWgoBitmap();
   
+  // Create the column bitmaps as stored in privsOfTheUser
+  for (int32_t i = 0; i < privsOfTheUser.getColumnPrivs().entries(); i++)
+  {
+    const int32_t columnOrdinal = 
privsOfTheUser.getColumnPrivs()[i].getColumnOrdinal();
+    colPrivsList[columnOrdinal] = 
privsOfTheUser.getColumnPrivs()[i].getPrivBitmap();
+    colGrantableList[columnOrdinal] = 
privsOfTheUser.getColumnPrivs()[i].getWgoBitmap();
+  }  
   return retcode;
 }
 
@@ -4554,6 +4456,7 @@ PrivStatus PrivMgrPrivileges::getPrivsFromAllGrantors(
     return STATUS_GOOD;
   }
   
+  std::vector<PrivMgrMDRow *> rowList;
   PrivObjectBitmap systemPrivs;
   PrivMgrComponentPrivileges componentPrivileges(metadataLocation_,pDiags_);
   
@@ -4564,41 +4467,75 @@ PrivStatus PrivMgrPrivileges::getPrivsFromAllGrantors(
   {
     PrivMgrCoreDesc coreTablePrivs(systemPrivs,systemPrivs);
     summarizedPrivs.setTablePrivs(coreTablePrivs);
-    return STATUS_GOOD; 
   }
   
-  std::vector<PrivMgrMDRow *> rowList;
-  retcode = getRowsForGrantee(objectUID, granteeID, true, roleIDs, rowList, 
secKeySet);
+  // Accumulate object level privileges
+  else
+  {
+    retcode = getRowsForGrantee(objectUID, granteeID, true, roleIDs, rowList, 
secKeySet);
+    if (retcode == STATUS_ERROR)
+      return retcode; 
+
+    // Get the privileges for the object granted to the grantee
+    PrivMgrCoreDesc coreTablePrivs;
+    for (int32_t i = 0; i < rowList.size();++i)
+    {
+      ObjectPrivsMDRow &row = static_cast<ObjectPrivsMDRow &> (*rowList[i]);
+    
+      if (secKeySet != NULL)
+      {
+        PrivMgrCoreDesc privs(row.privsBitmap_,0);
+        retcode = buildSecurityKeys(row.granteeID_,privs,*secKeySet);
+        if (retcode != STATUS_GOOD)
+          return retcode;    
+      }
+
+      PrivMgrCoreDesc temp (row.privsBitmap_, row.grantableBitmap_);
+      coreTablePrivs.unionOfPrivs(temp);
+    }
+  
+    PrivObjectBitmap grantableBitmap;
+  
+    if (hasManagePrivileges)
+       grantableBitmap = systemPrivs;
+  
+    PrivMgrCoreDesc temp2(systemPrivs,grantableBitmap);
+    coreTablePrivs.unionOfPrivs(temp2);
+  
+    summarizedPrivs.setTablePrivs(coreTablePrivs);
+  }
+
+  // Add accumulated column level privileges
+  rowList.clear();
+  retcode = getRowsForGrantee(objectUID, granteeID, false, roleIDs, rowList, 
secKeySet);
   if (retcode == STATUS_ERROR)
-    return retcode; 
+    return retcode;
 
-  // Get the privileges for the object granted to the grantee
-  PrivMgrCoreDesc coreTablePrivs;
+  NAList<PrivMgrCoreDesc> coreColumnPrivs;
   for (int32_t i = 0; i < rowList.size();++i)
   {
-    ObjectPrivsMDRow &row = static_cast<ObjectPrivsMDRow &> (*rowList[i]);
+    ColumnPrivsMDRow &row = static_cast<ColumnPrivsMDRow &> (*rowList[i]);
+
+    // See if the ordinal has already been specified
+    PrivMgrCoreDesc temp (row.privsBitmap_, row.grantableBitmap_, 
row.columnOrdinal_);
+    PrivMgrCoreDesc *coreColumnPriv = findColumnEntry(coreColumnPrivs, 
row.columnOrdinal_);
+    if (coreColumnPriv)
+      coreColumnPriv->unionOfPrivs(temp);
+    else
+      coreColumnPrivs.insert(temp);
     
+    // set up security keys, if required
     if (secKeySet != NULL)
     {
-      PrivMgrCoreDesc privs(row.privsBitmap_,0);
-      retcode = buildSecurityKeys(row.granteeID_,privs,*secKeySet);
+      PrivColList privColList;
+      privColList[row.columnOrdinal_] = row.privsBitmap_;
+      retcode = buildColumnSecurityKeys(objectUID_,privColList, 
row.granteeID_,*secKeySet);
       if (retcode != STATUS_GOOD)
-        return retcode;    
+        return retcode;
     }
+  } 
 
-    PrivMgrCoreDesc temp (row.privsBitmap_, row.grantableBitmap_);
-    coreTablePrivs.unionOfPrivs(temp);
-  }
-  
-  PrivObjectBitmap grantableBitmap;
-  
-  if (hasManagePrivileges)
-     grantableBitmap = systemPrivs;
-  
-  PrivMgrCoreDesc temp2(systemPrivs,grantableBitmap);
-  coreTablePrivs.unionOfPrivs(temp2);
-  
-  summarizedPrivs.setTablePrivs(coreTablePrivs);
+  summarizedPrivs.setColumnPrivs(coreColumnPrivs);
 
   return STATUS_GOOD;
 }
@@ -4691,7 +4628,7 @@ PrivStatus PrivMgrPrivileges::getRowsForGrantee(
        rowList.push_back(privRowList[i]);
   }
   
-  if (secKeySet != NULL)
+  if (rowList.size() > 0 && secKeySet != NULL)
   {
     retcode = buildUserSecurityKeys(roleIDs,granteeID,*secKeySet);   
     if (retcode == STATUS_ERROR)
@@ -5024,8 +4961,11 @@ bool PrivMgrPrivileges::isAuthIDGrantedPrivs(const 
int32_t authID)
 // *  <objectType> type of object
 // *  <isAllSpecified> if true then all privileges valid for the object
 // *                        type will be revoked
-// *  <isWGOSpecified> if true then remove the ability for  the grantee 
-// *                   to revoke the set of privileges to other grantees
+// *  <isWGOSpecified> for grants, include the with grant option
+// *                   for revokes (always true), if revoke the priv, also
+// *                   revoke the with grant option
+// *  <isGofSpecified> for grants - alway false (not applicable)
+// *                   for revokes - only revoke the with grant option
 // *  <privsList> is the list of privileges to check
 // *  <PrivMgrCoreDesc>  the core descriptor containing privileges
 // *                                                                     
@@ -5039,8 +4979,9 @@ PrivStatus PrivMgrPrivileges::convertPrivsToDesc(
   const ComObjectType objectType,
   const bool isAllSpecified,
   const bool isWgoSpecified,
-  const bool isGOFSpecified,
+  const bool isGofSpecified,
   const std::vector<PrivType> privsList,
+  const std::vector<ColPrivSpec> & colPrivsList,
   PrivMgrDesc &privsToProcess)
 {
 
@@ -5102,7 +5043,7 @@ PrivStatus PrivMgrPrivileges::convertPrivsToDesc(
         if (!isUdr)
           isIncompatible = true;
         else
-          
tableCorePrivs.testAndSetBit(privsList[i],isWgoSpecified,isGOFSpecified);  
+          
tableCorePrivs.testAndSetBit(privsList[i],isWgoSpecified,isGofSpecified);  
         break;
       case DELETE_PRIV:
       case INSERT_PRIV:
@@ -5111,25 +5052,24 @@ PrivStatus PrivMgrPrivileges::convertPrivsToDesc(
         if (!isObject)
           isIncompatible = true;
         else
-          
tableCorePrivs.testAndSetBit(privsList[i],isWgoSpecified,isGOFSpecified);  
+          
tableCorePrivs.testAndSetBit(privsList[i],isWgoSpecified,isGofSpecified);  
         break;
       case UPDATE_PRIV:
         if (!isObject && !isLibrary)
           isIncompatible = true;
         else
-          
tableCorePrivs.testAndSetBit(privsList[i],isWgoSpecified,isGOFSpecified);  
+          
tableCorePrivs.testAndSetBit(privsList[i],isWgoSpecified,isGofSpecified);  
         break;
       case USAGE_PRIV:
         if (!isLibrary && !isSequence)
           isIncompatible = true;
         else
-          
tableCorePrivs.testAndSetBit(privsList[i],isWgoSpecified,isGOFSpecified);  
+          
tableCorePrivs.testAndSetBit(privsList[i],isWgoSpecified,isGofSpecified);  
         break;
       case ALL_DML:
         if (!isObject)
           isIncompatible = true;
-        else
-          if (isGOFSpecified)
+          if (isGofSpecified)
             tableCorePrivs.setWgo(ALL_DML,true);
           else
           {
@@ -5154,6 +5094,40 @@ PrivStatus PrivMgrPrivileges::convertPrivsToDesc(
   } // end for
 
   privsToProcess.setTablePrivs(tableCorePrivs);
+
+  // Merge the column-privilege-to-grant entries (colPrivArray) into one entry 
+  // per column ordinal.
+  //
+  // Example: Given a commands such as 
+  //
+  // GRANT SELECT(COL4),INSERT(COL2,COL4) ON TAB TO USER;
+  // 
+  // three entries are generated by the parser, but only two rows are written; 
 
+  // one for column 2 (insert) and one for column 4 (insert and select).  
+  //
+  // Input may have same column ordinal in multiple entries, but the input is 
+  // guaranteed not to contain same ordinal and privType more than once.
+  NAList<PrivMgrCoreDesc> columnCorePrivs;
+  for (size_t i = 0; i < colPrivsList.size(); i++)
+  {
+    const ColPrivSpec &colPrivSpec = colPrivsList[i];
+
+    PrivMgrCoreDesc *existingEntry = findColumnEntry(columnCorePrivs,
+                                                     
colPrivSpec.columnOrdinal);
+    if (existingEntry != NULL)
+      
existingEntry->testAndSetBit(colPrivSpec.privType,isWgoSpecified,isGofSpecified);
+    else
+    {
+      PrivMgrCoreDesc colPrivToGrant;
+      colPrivToGrant.setColumnOrdinal(colPrivSpec.columnOrdinal);
+      
colPrivToGrant.testAndSetBit(colPrivSpec.privType,isWgoSpecified,isGofSpecified);
+
+      columnCorePrivs.insert(colPrivToGrant);
+    }
+  }
+
+  privsToProcess.setColumnPrivs(columnCorePrivs);
+
   return STATUS_GOOD;      
 }
 
@@ -5341,6 +5315,7 @@ static PrivStatus buildPrivText(
                if (!isDMLPrivType(static_cast<PrivType>(p)))
                   continue;
                  
+               // See if any WGO statement exist
                if (hasWGO[p])
                {
                   closeColumnList(WGOString[p]);
@@ -5349,15 +5324,16 @@ static PrivStatus buildPrivText(
                   
WGOString[p].assign(PrivMgrUserPrivs::convertPrivTypeToLiteral((PrivType)p) + 
"(");
                   hasWGO[p] = false;
                }
-               else
-                  if (hasPriv[p])
-                  {
-                     closeColumnList(privString[p]);
-                     withoutWGO += privString[p];
-                     // Reset to original value
-                     
privString[p].assign(PrivMgrUserPrivs::convertPrivTypeToLiteral((PrivType)p) + 
"(");
-                     hasPriv[p] = false;
-                  }
+               
+               // See if any WGO statement exist
+               if (hasPriv[p])
+               {
+                  closeColumnList(privString[p]);
+                  withoutWGO += privString[p];
+                  // Reset to original value
+                  
privString[p].assign(PrivMgrUserPrivs::convertPrivTypeToLiteral((PrivType)p) + 
"(");
+                  hasPriv[p] = false;
+               }
             }
             mergeStrings = false;
          }
@@ -5646,7 +5622,7 @@ static void deleteRowList(std::vector<PrivMgrMDRow *> & 
rowList)
 // 
*****************************************************************************
 // * Function: findColumnEntry                                                 
*
 // *                                                                           
*
-// *    This function searches a vector of ColPrivEntry for a matching         
*
+// *    This function searches a vector of PrivMgrCoreDesc for a matching      
   *
 // *  column ordinal.                                                          
*
 // *                                                                           
*
 // 
*****************************************************************************
@@ -5654,7 +5630,7 @@ static void deleteRowList(std::vector<PrivMgrMDRow *> & 
rowList)
 // *  Parameters:                                                              
*
 // *                                                                           
*
 // *                                                                           
*
-// *  <colPrivEntries>             std::vector<ColPrivEntry> &        In       
*
+// *  <colPrivEntries>             NAList<PrivMgrCoreDesc> &        In       *
 // *    is a reference to a vector of ColPrivEntry.                            
*
 // *                                                                           
*
 // *  <columnOrdinal>              const int32_t                      In       
*
@@ -5662,24 +5638,22 @@ static void deleteRowList(std::vector<PrivMgrMDRow *> & 
rowList)
 // *                                                                           
*
 // 
*****************************************************************************
 // *                                                                           
*
-// * Returns: ColPrivEntry                                                     
*
+// * Returns: PrivMgrCoreDesc                                                  
   *
 // *                                                                           
*
 // * NULL: No entry found with that column ordinal                             
*
 // *    *: Entry found with matching column ordinal                            
*
 // *                                                                           
*
 // 
*****************************************************************************
-static ColPrivEntry * findColumnEntry(
-   std::vector<ColPrivEntry> & colPrivEntries,
+static PrivMgrCoreDesc * findColumnEntry(
+   NAList<PrivMgrCoreDesc> & colPrivEntries,
    const int32_t columnOrdinal)
    
 {
-
-   for (size_t i = 0; i < colPrivEntries.size(); i++)
+   for (size_t i = 0; i < colPrivEntries.entries(); i++)
       if (colPrivEntries[i].getColumnOrdinal() == columnOrdinal)
          return & colPrivEntries[i];
          
    return NULL;
-
 }   
 //************************** End of findColumnEntry 
****************************
 
@@ -5774,7 +5748,7 @@ static PrivStatus getColRowsForGrantee(
 // *  <grantorID>                  const int32_t                      In       
*
 // *    is the authID who granted the privileges.                              
*
 // *                                                                           
*
-// *  <grantedColPrivs>            std::vector<ColPrivEntry> &        Out      
*
+// *  <grantedColPrivs>            NAList<PrivMgrCoreDesc> &        Out      *
 // *    passes back a privileges granted to <granteeID> by <grantorID>.        
*
 // *                                                                           
*
 // 
*****************************************************************************
@@ -5782,22 +5756,22 @@ static void getColRowsForGranteeGrantor(
    const std::vector <PrivMgrMDRow *> &columnRowList,
    const int32_t granteeID,
    const int32_t grantorID,
-   std::vector<ColPrivEntry> & grantedColPrivs)
+   NAList<PrivMgrCoreDesc> & grantedColPrivs)
    
 {
 
    for (size_t i = 0; i < columnRowList.size(); ++i)
    {
       ColumnPrivsMDRow &row = static_cast<ColumnPrivsMDRow &> 
(*columnRowList[i]);
-      ColPrivEntry colPrivGrant;
+      PrivMgrCoreDesc colPrivGrant;
       
       if (row.grantorID_ == grantorID && row.granteeID_ == granteeID)
       {
          colPrivGrant.setColumnOrdinal(row.columnOrdinal_);
          colPrivGrant.setPrivBitmap(row.privsBitmap_.to_ulong());
-         colPrivGrant.setGrantableBitmap(row.grantableBitmap_.to_ulong());
+         colPrivGrant.setWgoBitmap(row.grantableBitmap_.to_ulong());
       
-         grantedColPrivs.push_back(colPrivGrant);
+         grantedColPrivs.insert(colPrivGrant);
       }
    }
    
@@ -5858,245 +5832,7 @@ static bool hasAllDMLPrivs(
 
 }
 //************************** End of hasAllDMLPrivs 
*****************************
-
-
-// 
*****************************************************************************
-// * Function: hasColumnWGO                                                    
*
-// *                                                                           
*
-// *    This function determines if the grantor has the authority to grant     
*
-// * the specified privileges.                                                 
*
-// *                                                                           
*
-// 
*****************************************************************************
-// *                                                                           
*
-// *  Parameters:                                                              
*
-// *                                                                           
*
-// *  <colPrivsArrayIn>            const std::vector<ColPrivSpec> &   In       
*
-// *    is the list of privileges the grantor wants to grant.                  
*
-// *                                                                           
*
-// *  <roleIDs>                    std::vector<int_32> &              In       
*
-// *    is the list of role IDs granted to the grantor.                        
*
-// *                                                                           
*
-// *  <privStatus>                 PrivStatus &                       In       
*
-// *    passes back the PrivStatus.                                            
*
-// *                                                                           
*
-// *                                                                           
*
-// 
*****************************************************************************
-// *                                                                           
*
-// * Returns: bool                                                             
*
-// *                                                                           
*
-// *  true: Grantor has WGO.                                                   
*
-// * false: Grantor does NOT have WGO.  See privStatus.                        
*
-// *                                                                           
*
-// 
*****************************************************************************
-bool PrivMgrPrivileges::hasColumnWGO(
-   const std::vector<ColPrivSpec> & colPrivsArrayIn,
-   const std::vector<int32_t> &roleIDs,
-   PrivStatus & privStatus)
-{
-
-std::vector<ColPrivSpec> &colPrivsArray = 
-   const_cast<std::vector<ColPrivSpec> &>(colPrivsArrayIn); 
-
-   privStatus = STATUS_GOOD;
-
-   // Grantor may have column WGO from two sources, object-level grants on the 
 
-   // object and column-level grants.  First check the object-level grants. 
-  
-   std::vector<PrivMgrMDRow *> objRowList;
-
-   // Get object privileges that the grantor has been granted - that is, the 
-   // grantor becomes the grantee.  
-   privStatus = 
getRowsForGrantee(objectUID_,grantorID_,true,roleIDs,objRowList,NULL);
-   if (privStatus == STATUS_ERROR)
-     return privStatus;
-      
-   // For each privilege to grant, see if the grantor has been granted that 
-   // privilege WITH GRANT OPTION (WGO).  If so, note it in the colPrivsArray 
entry.
-   // If the grantor does not have WGO, note that we have to check column 
-   // privileges for at least one grant.
-   bool checkColumnPrivs = false;
- 
-   for (size_t i = 0; i < colPrivsArray.size(); i++)
-   {
-      ColPrivSpec &colPrivSpec = colPrivsArray[i];
-      colPrivSpec.grantorHasWGO = false;
-      for (size_t j = 0; j < objRowList.size(); j++)
-      {
-         ObjectPrivsMDRow &objectRow = static_cast<ObjectPrivsMDRow &> 
(*objRowList[j]);
-         
-         if (objectRow.grantableBitmap_.test(colPrivSpec.privType))
-         {
-            colPrivSpec.grantorHasWGO = true;
-            break;
-         }
-      }
-      if (!colPrivSpec.grantorHasWGO)
-         checkColumnPrivs = true;
-   }
    
-   // If object-level privileges are sufficient to grant the column-level 
-   // privileges, no need to read COLUMN_PRIVILEGES table.
-   if (!checkColumnPrivs)
-      return true;
-
-
-   // The grantor did not have WGO at the object level for at least one
-   // of the privileges to be granted; see if they have the column privilege 
WGO.  
-
-   // Fetch any relevant WGO rows from COLUMN_PRIVILEGES.
-   std::vector<PrivMgrMDRow *> colRowList;
-    
-   // Get object privileges that the grantor has been granted - that is, the 
-   // grantor becomes the grantee.  
-   privStatus = 
getRowsForGrantee(objectUID_,grantorID_,false,roleIDs,colRowList,NULL);
-   if (privStatus == STATUS_ERROR)
-     return privStatus;
-
-   for (size_t i = 0; i < colPrivsArray.size(); i++)
-   {
-      // If the grantor already has the authority to grant this privilege 
-      // from another source, move to the next privilege to be granted.
-      if (colPrivsArray[i].grantorHasWGO)
-         continue;
-         
-      ColPrivSpec &colPrivSpec = colPrivsArray[i];
-      
-      // See if the grantor has been granted WGO at column-level for priv.  
-      for (size_t j = 0; j < colRowList.size(); j++)
-      {
-          ColumnPrivsMDRow &columnRow = static_cast<ColumnPrivsMDRow &> 
(*colRowList[j]);
-          if (columnRow.columnOrdinal_ == colPrivSpec.columnOrdinal)
-          {
-             if (columnRow.grantableBitmap_.test(colPrivSpec.privType))
-             {
-                colPrivSpec.grantorHasWGO = true;
-                break;
-             }
-         }
-      }
-
-      // If the grantor does not have an object-level or column-level WGO
-      // for one of the privs to grant, return an error.
-      if (!colPrivSpec.grantorHasWGO)
-      {
-         privStatus = STATUS_NOTFOUND;
-         return false;
-      }
-   }
-  
-   return true;
-  
-}
-//*************************** End of hasColumnWGO 
******************************
-
-
-   
-// 
*****************************************************************************
-// *                                                                           
*
-// * Function: hasGrantedColumnPriv                                            
*
-// *                                                                           
*
-// *   This function determines if a grantor has granted the specified         
*
-// * set of privileges on the specified object to the specified grantee.       
*
-// *                                                                           
*
-// 
*****************************************************************************
-// *                                                                           
*
-// *  Parameters:                                                              
*
-// *                                                                           
*
-// *  <colRowList>                 std::vector<PrivMgrMDRow *> &      In       
*
-// *    is the list of all column privileges granted to the object.            
*
-// *                                                                           
*
-// *  <grantorID>                  const int32_t                      In       
*
-// *    is the authorization ID of the grantor.                                
*
-// *                                                                           
*
-// *  <granteeID>                  const int32_t                      In       
*
-// *    is the authorization ID of the grantee.                                
*
-// *                                                                           
*
-// *  <colPrivsArray>              const std::vector<ColPrivSpec> &   In       
*
-// *    is an array of column privilege specifications, with one entry per     
*
-// *  privilege and column.                                                    
*
-// *                                                                           
*
-// *  <privStatus>                 PrivStatus                         Out      
*
-// *    passes back the PrivStatus for last operation.                         
*
-// *                                                                           
*
-// *  <privilege>                  std::string &                      Out      
*
-// *    passes back the first privilege not granted.                           
*
-// *                                                                           
*
-// *  <grantedColPrivs>            std::vector<ColPrivEntry> &        Out      
*
-// *    passes back an array of column privilege entries, with one entry per   
*
-// *  column--privileges are combined into one bitmap.                         
*
-// *                                                                           
*
-// 
*****************************************************************************
-// *                                                                           
*
-// * Returns: bool                                                             
*
-// *                                                                           
*
-// *  true: All specified privileges have been granted.                        
*
-// * false: One or more privileges have not been granted                       
*
-// *                                                                           
*
-// 
*****************************************************************************
-static bool hasGrantedColumnPriv(
-   const std::vector<PrivMgrMDRow *> &colRowList,
-   int32_t grantorID,
-   int32_t granteeID,
-   const std::vector<ColPrivSpec> & colPrivsArray,
-   PrivStatus & privStatus,
-   std::string & privilege,
-   std::vector<ColPrivEntry> & grantedColPrivs)
-   
-{
-
-   privStatus = STATUS_GOOD;
-  
-// For each privilege to revoke, see if the grantor has granted that privilege 
-// to the grantee for the specified column.  If not, return an error.
- 
-   for (size_t i = 0; i < colPrivsArray.size(); i++)
-   {
-      const ColPrivSpec &colPrivSpec = colPrivsArray[i];
-      bool grantFound = false;
-      for (size_t j = 0; j < colRowList.size(); j++)
-      {
-         ColumnPrivsMDRow &columnRow = static_cast<ColumnPrivsMDRow &> 
(*colRowList[j]);
-
-         // Only look at rows with the requested grantor and grantee
-         if (columnRow.grantorID_ == grantorID && columnRow.granteeID_ == 
granteeID)
-         {
-            if (columnRow.columnOrdinal_ == colPrivSpec.columnOrdinal &&
-                columnRow.privsBitmap_.test(colPrivSpec.privType))
-            {
-               grantFound = true;
-               break;
-            }
-         }
-      }
-
-      if (!grantFound)
-      {
-         privilege = 
PrivMgrUserPrivs::convertPrivTypeToLiteral((PrivType)colPrivSpec.privType);
-         privStatus = STATUS_NOTFOUND;
-         return false;
-      }
-   }
-
-// Build array of granted privileges.  One entry per column granted a privilege
-// from grantor to grantee.
-   for (size_t j = 0; j < colRowList.size(); j++)
-   {
-      ColumnPrivsMDRow &columnRow = static_cast<ColumnPrivsMDRow &> 
(*colRowList[j]);
-      if (columnRow.grantorID_ == grantorID && columnRow.granteeID_ == 
granteeID)
-      {
-         ColPrivEntry grantedColPriv;
-      
-         grantedColPriv.setColumnOrdinal(columnRow.columnOrdinal_);
-         grantedColPriv.setGrantableBitmap(columnRow.grantableBitmap_);
-         grantedColPriv.setPrivBitmap(columnRow.privsBitmap_);
-         grantedColPrivs.push_back(grantedColPriv);
-      }
-   }
-
-   return true;
-  
-}
-//*********************** End of hasGrantedColumnPriv 
**************************
    
 // 
*****************************************************************************
 // *                                                                           
*
@@ -6134,6 +5870,79 @@ static bool isDelimited( const std::string &strToScan)
    
 
 // 
*****************************************************************************
+// method: reportPrivWarnings
+//
+// Ansi states that when a grant statement is executed, a set of privilege 
+// descriptors (CPD) is created based on existing privileges for the object 
and 
+// object’s columns. Each CPD contains the grantee, action (privileges), 
object, 
+// column and grantor. A similar list of privilege descriptors is created 
based 
+// on the grant/revoke statement (GPD).
+//
+// If there is an element in the GPD (what the user requested) that is not in 
+// the  CPD (what was actually granted/revoked), then a warning – privilege 
not 
+// granted/revoked is displayed.
+// 
+// This method compares the list of actual privileges granted/revoked 
+// (actualPrivs)to the list privileges requested (origPrivs).  If a privilege 
+// was requested but not granted/revoked report a warning.
+// 
*****************************************************************************
+void PrivMgrPrivileges::reportPrivWarnings(
+    const PrivMgrDesc &origPrivs,
+    const PrivMgrDesc &actualPrivs,
+    const CatErrorCode warningCode)
+{
+  PrivMgrCoreDesc objPrivsNotApplied = origPrivs.getTablePrivs();
+  objPrivsNotApplied.suppressDuplicatedPrivs(actualPrivs.getTablePrivs());
+  if (!objPrivsNotApplied.isNull())
+  {
+    for ( size_t i = FIRST_DML_PRIV; i <= LAST_DML_PRIV; i++ )
+    {
+      PrivType privType = PrivType(i);
+      if (objPrivsNotApplied.getPriv(privType))
+      {
+        *pDiags_ << DgSqlCode(warningCode)
+                 << 
DgString0(PrivMgrUserPrivs::convertPrivTypeToLiteral(privType).c_str());
+      }
+    }
+  }
+
+  NAList<PrivMgrCoreDesc> colPrivs = origPrivs.getColumnPrivs();
+  for (int i = 0; i < colPrivs.entries(); i++)
+  {
+     PrivMgrCoreDesc colPrivsNotApplied = colPrivs[i];
+
+     int index = actualPrivs.getColumnPriv(i);
+     if (index >= 0)
+     {
+       PrivMgrCoreDesc colPrivsActual = actualPrivs.getColumnPrivs()[index];
+       colPrivsNotApplied.suppressDuplicatedPrivs(colPrivsActual);
+     }
+
+     if (!colPrivsNotApplied.isNull())
+     {
+       for ( size_t j = FIRST_DML_PRIV; j <= LAST_DML_PRIV; j++ )
+       {
+         PrivType privType = PrivType(j);
+         if (colPrivsNotApplied.getPriv(privType))
+         {
+           // would be better to add column name instead of number
+           // would require an I/O to read COLUMNS to get the name
+           // associated with the number
+           char privStr[100];
+           snprintf(privStr, sizeof(privStr), "%s (column number %d) ", 
+                    
PrivMgrUserPrivs::convertPrivTypeToLiteral(privType).c_str(),
+                    colPrivsNotApplied.getColumnOrdinal());
+           *pDiags_ << DgSqlCode(warningCode)
+                    << DgString0(privStr);
+         }
+       }
+     }
+  }
+}
+
+
+
+// 
*****************************************************************************
 //    ObjectPrivsMDRow methods
 // 
*****************************************************************************
 

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/877a8e8a/core/sql/sqlcomp/PrivMgrPrivileges.h
----------------------------------------------------------------------
diff --git a/core/sql/sqlcomp/PrivMgrPrivileges.h 
b/core/sql/sqlcomp/PrivMgrPrivileges.h
index 10d2809..a3a132c 100644
--- a/core/sql/sqlcomp/PrivMgrPrivileges.h
+++ b/core/sql/sqlcomp/PrivMgrPrivileges.h
@@ -30,6 +30,7 @@
 #include "PrivMgrDesc.h"
 #include "ComSmallDefs.h"
 #include "ComViewColUsage.h"
+#include "CmpDDLCatErrorCodes.h"
 
 #include <string>
 #include <bitset>
@@ -58,50 +59,6 @@ public:
 };
 
 // 
*****************************************************************************
-// * Class:        ColPrivEntry
-// * Description:  This class represents the privileges and corresponding 
-// *               WGO (with grant option) for a column
-// 
*****************************************************************************
-class ColPrivEntry
-{
-public:
-   PrivMgrCoreDesc    privDesc_;
-   bool               isUpdate_;
-
-   ColPrivEntry()
-   : isUpdate_(false){};
-   ColPrivEntry(const PrivMgrMDRow &row);
-   ColPrivEntry(const ColPrivEntry &other);
-
-   PrivMgrCoreDesc &getPrivDesc (void) { return privDesc_; }
-
-   int32_t getColumnOrdinal (void) { return privDesc_.getColumnOrdinal(); }
-   PrivColumnBitmap getPrivBitmap (void) { return privDesc_.getPrivBitmap(); }
-   PrivColumnBitmap getGrantableBitmap (void) { return 
privDesc_.getWgoBitmap(); }
-
-   void setColumnOrdinal (int32_t columnOrdinal)
-   { privDesc_.setColumnOrdinal(columnOrdinal); }
-
-   void setPrivBitmap(PrivMgrBitmap privBitmap)
-   { privDesc_.setPrivBitmap(privBitmap); }
-   void setGrantableBitmap(PrivMgrBitmap grantableBitmap)
-   { privDesc_.setWgoBitmap(grantableBitmap);}
-
-   void setPriv (PrivType privType, bool value)
-   { privDesc_.setPriv(privType, value); }
-   void setGrantable (PrivType privType, bool value)
-   { privDesc_.setWgo(privType, value); }
-
-   void describe (std::string &details) const
-   {
-      details = "column usage - column number is ";
-      details += to_string((long long int) privDesc_.getColumnOrdinal());
-      details += ", isUpdate is ";
-      details += (isUpdate_) ? "true " : "false ";
-   }
-};
-
-// 
*****************************************************************************
 // * Class:         PrivMgrPrivileges
 // * Description:  This class represents the access rights for objects
 // 
*****************************************************************************
@@ -205,12 +162,12 @@ public:
       const std::string &newOwnerName,
       const std::vector<int64_t> &objectUIDs);
          
-   PrivStatus grantColumnPrivileges(
+   PrivStatus grantColumnPriv(
       const ComObjectType objectType,
       const int32_t granteeID,
       const std::string &granteeName,
       const std::string &grantorName,
-      const std::vector<ColPrivSpec> & colPrivsArray,
+      const PrivMgrDesc &privsToGrant,
       const bool isWGOSpecified);
   
    PrivStatus grantObjectPriv(
@@ -246,12 +203,12 @@ public:
       const std::string &objectsLocation,
       const std::string &authsLocation);
       
-   PrivStatus revokeColumnPrivileges(
+   PrivStatus revokeColumnPriv(
          const ComObjectType objectType,
          const int32_t granteeID,
          const std::string & granteeName,
          const std::string & grantorName,
-         const std::vector<ColPrivSpec> & colPrivsArrayIn,
+         const PrivMgrDesc &privsToRevoke,
          const bool isWGOSpecified);
          
    PrivStatus revokeObjectPriv(
@@ -284,7 +241,8 @@ protected:
      const bool isAllSpecified,
      const bool isWGOSpecified,
      const bool isGOFSpecified,
-     const std::vector<PrivType> privs,
+     const std::vector<PrivType> privsList,
+     const std::vector<ColPrivSpec> & colPrivsList,
      PrivMgrDesc &privsToGrant);
 
    PrivStatus getPrivsFromAllGrantors(
@@ -314,7 +272,7 @@ private:
 
   bool checkColumnRevokeRestrict (
     int32_t granteeID,
-    const std::vector<ColPrivEntry> &colPrivsToRevoke,
+    const NAList<PrivMgrCoreDesc> &colPrivsToRevoke,
     std::vector <PrivMgrMDRow *> &rowList );
 
   bool checkRevokeRestrict (
@@ -419,10 +377,22 @@ private:
      const std::string &newOwnerName,
      const int64_t objectUID);    
 
-  bool hasColumnWGO(
-   const std::vector<ColPrivSpec> & colPrivsArrayIn,
-   const std::vector<int32_t> &roleIDs,
-   PrivStatus & privStatus);
+  PrivStatus initGrantRevoke(
+    const ComObjectType objectType,
+    const int32_t granteeID,
+    const std::vector<PrivType> &privList,
+    const std::vector<ColPrivSpec> & colPrivsArray,
+    const bool isAllSpecified,
+    const bool isGOSpecified,
+    const bool isGrant,
+    PrivMgrDesc &privsToApply,
+    PrivMgrDesc &privsOfTheGrantor,
+    std::vector<int32_t> & roleIDs);
+
+  void reportPrivWarnings(
+    const PrivMgrDesc &origPrivs,
+    const PrivMgrDesc &actualPrivs,
+    const CatErrorCode warningCode);
 
   void scanColumnBranch( const PrivType pType,
     const int32_t& grantor,


Reply via email to