You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafodion.apache.org by rm...@apache.org on 2016/10/14 19:53:34 UTC

[3/5] incubator-trafodion git commit: [TRAFODION-2167]: Invalid query invalidation keys not working properly

[TRAFODION-2167]: Invalid query invalidation keys not working properly

When a user is revoked from a role, invalidation keys are not being
processed correctly. Therefore, users can still run queries even though
privileges have been removed.  Query invalidation is complicated when
table descriptors are stored in metadata.

Changes:

--> The list of priv_descs created (and stored) was changed to include an entry
    for each user and each role accumulated across all grantors. (Today, each
    priv_desc entry includes the users' direct grants plus grants on their
    active roles.)
--> When an object is loaded into NATable or NARoutine cache, the priv_desc is
    accessed and the privilege bitmap is now generated by combining the users'
    privileges with privileges of their active roles. Correct invalidation keys
    are now being created and stored with the object. In the first code drop,
    the users' active roles are read from the role_usage table. In the next
    code drop, the active roles will be stored and maintained in executor
    globals.
--> When a plan is compiled, the correct invalidation keys for users, roles,
    and the public authorization are added to the plan.
--> Changes in the compiler were required to handle the invalidation keys for
    revoke role and revoke privilege from "PUBLIC".
--> Cleaned up the code that manages invalidation keys in privilege manager.
--> Included the correct create and redef times (if available) in the stored
    object descriptor - today they are always set to 0.
--> Added new regression test to test all the revoke options.


Project: http://git-wip-us.apache.org/repos/asf/incubator-trafodion/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafodion/commit/3b437720
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafodion/tree/3b437720
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafodion/diff/3b437720

Branch: refs/heads/master
Commit: 3b437720a54de88b6a04e44e0257fac0448f0762
Parents: 12f602c
Author: Roberta Marton <rm...@edev07.esgyn.local>
Authored: Wed Oct 12 01:48:22 2016 +0000
Committer: Roberta Marton <rm...@edev07.esgyn.local>
Committed: Wed Oct 12 01:48:22 2016 +0000

----------------------------------------------------------------------
 core/sql/common/ComDistribution.cpp      |    3 +-
 core/sql/common/ComSecurityKey.cpp       |  156 +-
 core/sql/common/ComSecurityKey.h         |    9 +-
 core/sql/optimizer/BindRelExpr.cpp       |  106 +-
 core/sql/optimizer/NARoutine.cpp         |   67 +-
 core/sql/optimizer/NATable.cpp           | 4559 +++++++++++++------------
 core/sql/sqlcomp/CmpSeabaseDDLcommon.cpp |   21 +
 core/sql/sqlcomp/PrivMgrCommands.cpp     |  194 +-
 core/sql/sqlcomp/PrivMgrCommands.h       |   22 +-
 core/sql/sqlcomp/PrivMgrDesc.h           |   84 +-
 core/sql/sqlcomp/PrivMgrPrivileges.cpp   |  594 +---
 core/sql/sqlcomp/PrivMgrPrivileges.h     |   38 +-
 core/sql/sqlcomp/PrivMgrRoles.cpp        |   22 +-
 core/sql/sqlcomp/QCache.cpp              |   19 +-
 14 files changed, 2869 insertions(+), 3025 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/3b437720/core/sql/common/ComDistribution.cpp
----------------------------------------------------------------------
diff --git a/core/sql/common/ComDistribution.cpp b/core/sql/common/ComDistribution.cpp
index 5a3382b..82fdb83 100644
--- a/core/sql/common/ComDistribution.cpp
+++ b/core/sql/common/ComDistribution.cpp
@@ -314,7 +314,8 @@ const literalAndEnumStruct qiTypeConversionTable [] =
   {COM_QI_SCHEMA_REFERENCES, COM_QI_SCHEMA_REFERENCES_LIT},
   {COM_QI_OBJECT_EXECUTE, COM_QI_OBJECT_EXECUTE_LIT},
   {COM_QI_SCHEMA_EXECUTE, COM_QI_SCHEMA_EXECUTE_LIT},
-  {COM_QI_OBJECT_REDEF, COM_QI_OBJECT_REDEF_LIT}
+  {COM_QI_OBJECT_REDEF, COM_QI_OBJECT_REDEF_LIT},
+  {COM_QI_USER_GRANT_SPECIAL_ROLE, COM_QI_USER_GRANT_SPECIAL_ROLE_LIT}
 };
 
 //----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/3b437720/core/sql/common/ComSecurityKey.cpp
----------------------------------------------------------------------
diff --git a/core/sql/common/ComSecurityKey.cpp b/core/sql/common/ComSecurityKey.cpp
index fa3415c..978a257 100644
--- a/core/sql/common/ComSecurityKey.cpp
+++ b/core/sql/common/ComSecurityKey.cpp
@@ -34,7 +34,18 @@
 #include "exp_function.h"
 #include "ComDistribution.h"
 #include "ComUser.h"
+#include "PrivMgrDefs.h"
 
+// ****************************************************************************
+// function: qiCheckForInvalidObject
+//
+// This function compares the list of query invalidate keys that changed to
+// the list of invalidation keys associated with the object.
+//
+// If the changed invalidation key matches one of the keys for the object,
+// return TRUE.  TRUE indicates that the object should be reloaded to pick up
+// DDL or privilege changes.
+// ****************************************************************************
 NABoolean qiCheckForInvalidObject (const Int32 numInvalidationKeys,
                                    const SQL_QIKEY* invalidationKeys,
                                    const Int64 objectUID,
@@ -48,27 +59,48 @@ NABoolean qiCheckForInvalidObject (const Int32 numInvalidationKeys,
   for ( Int32 i = 0; i < numInvalidationKeys && !found; i++ )
   {
     invalidationKeyType = ComQIActionTypeLiteralToEnum( invalidationKeys[i].operation );
+    Int32 numObjectKeys = objectKeys.entries();
 
-    // if the object redef time changed and this is the object, remove entry
-    if (invalidationKeyType == COM_QI_OBJECT_REDEF &&
-        invalidationKeys[i].ddlObjectUID == objectUID)
-      found = TRUE;
-    else
+    switch (invalidationKeyType)
     {
-      // Scan the passed-in object keys to find any that match the 
-      // invalidation key 
-      Int32 numObjectKeys = objectKeys.entries();
-      for (Int32 j = 0; j < numObjectKeys && !found; j++ )
+      // Indicates that the DDL of the object has changed. 
+      case COM_QI_OBJECT_REDEF:
       {
-        ComSecurityKey keyValue = objectKeys[j];
-        if ( ( invalidationKeys[i].revokeKey.subject ==
-                 keyValue.getSubjectHashValue() ) &&
-           ( invalidationKeys[i].revokeKey.object ==
-                 keyValue.getObjectHashValue() )  &&
-           ( invalidationKeyType ==
-                 keyValue.getSecurityKeyType() ) ) 
+        if (invalidationKeys[i].ddlObjectUID == objectUID)
           found = TRUE;
+        break;
       }
+
+      // Scan the passed-in object keys to find any that match the subject, 
+      // object, and key type. That is, the subject has the privilege
+      // (invalidation key type) on the object or a column of the object.
+      case COM_QI_OBJECT_SELECT:
+      case COM_QI_OBJECT_INSERT:
+      case COM_QI_OBJECT_DELETE:
+      case COM_QI_OBJECT_UPDATE:
+      case COM_QI_OBJECT_USAGE:
+      case COM_QI_OBJECT_REFERENCES: 
+      case COM_QI_OBJECT_EXECUTE:
+      case COM_QI_USER_GRANT_SPECIAL_ROLE:
+      case COM_QI_USER_GRANT_ROLE:
+      {
+        for (Int32 j = 0; j < numObjectKeys && !found; j++ )
+        {
+          ComSecurityKey keyValue = objectKeys[j];
+          if ( ( invalidationKeys[i].revokeKey.subject ==
+                   keyValue.getSubjectHashValue() ) &&
+               ( invalidationKeys[i].revokeKey.object ==
+                   keyValue.getObjectHashValue() )  &&
+               ( invalidationKeyType ==
+                   keyValue.getSecurityKeyType() ) )
+            found = TRUE;
+        }
+        break;
+      }
+
+      default:
+        found = TRUE;
+        break;
     }
   }
   return found;
@@ -77,53 +109,61 @@ NABoolean qiCheckForInvalidObject (const Int32 numInvalidationKeys,
 // ****************************************************************************
 // Function that builds query invalidation keys for privileges. A separate
 // invalidation key is added for each granted DML privilege. 
+//
+// Types of keys available for privs:
+//   OBJECT_IS_SCHEMA - not supported until we support schema level privs
+//   OBJECT_IS_OBJECT - supported for granting privs to user
+//   OBJECT_IS_COLUMN - not supported at this time
+//   OBJECT_IS_SPECIAL_ROLE - key for PUBLIC authorization ID
+//   SUBJECT_IS_USER - support for granting roles to user
+//   SUBJECT_IS_ROLE - not supported until we grant roles to roles
+//
 // ****************************************************************************
-bool buildSecurityKeySet(PrivMgrUserPrivs *privInfo,
-                         Int64 objectUID,
-                         ComSecurityKeySet &secKeySet)
+bool buildSecurityKeys( const int32_t granteeID,
+                        const int32_t roleID,
+                        const int64_t objectUID,
+                        const PrivMgrCoreDesc &privs,
+                        ComSecurityKeySet &secKeySet )
 {
-  Int32 granteeID = ComUser::getCurrentUser();
+  if (privs.isNull())
+    return STATUS_GOOD;
 
-  // Build security keys for object privileges
-  for ( Int32 i = FIRST_DML_PRIV; i <= LAST_DML_PRIV; i++ )
+  // Only need to generate keys for DML privileges
+  for ( size_t i = FIRST_DML_PRIV; i <= LAST_DML_PRIV; i++ )
   {
-    if ( privInfo->hasObjectPriv((PrivType)i) )
+    if ( privs.getPriv(PrivType(i)))
+    {
+      if (roleID != NA_UserIdDefault && ComUser::isPublicUserID(roleID))
+      {
+        ComSecurityKey key(granteeID, ComSecurityKey::OBJECT_IS_SPECIAL_ROLE);
+        if (key.isValid())
+          secKeySet.insert(key);
+        else
+          false;
+      }
+          
+      else if (roleID != NA_UserIdDefault && PrivMgr::isRoleID(roleID))
+      {
+        ComSecurityKey key (granteeID, roleID, ComSecurityKey::SUBJECT_IS_USER);
+        if (key.isValid())
+         secKeySet.insert(key);
+        else
+          false;
+      }
+
+      else
       {
-        ComSecurityKey key(granteeID,
-                           objectUID,
-                           PrivType(i),
-                           ComSecurityKey::OBJECT_IS_OBJECT);
-        if (!key.isValid())
-          return false;
-        secKeySet.insert(key);
+        ComSecurityKey key (granteeID, objectUID, PrivType(i), 
+                            ComSecurityKey::OBJECT_IS_OBJECT);
+        if (key.isValid())
+         secKeySet.insert(key);
+        else
+          false;
       }
+    }
   }
-  // Build security key for column privileges
-  PrivColumnBitmap privBitmap;
-
-  // Optimizer currently does not support OBJECT_IS_COLUMN, so we "or"
-  // all column-level privileges into one priv bitmap.  We create a key for
-  // each priv type where at least one column has that priv.
-  // The security key set is a list of sets, do duplicates are handled by c++
-  for (PrivColIterator columnIterator = privInfo->getColPrivList().begin();
-       columnIterator != privInfo->getColPrivList().end(); ++columnIterator)
-    privBitmap |= columnIterator->second;
-
-  // Now create a security key on the final bitmap
-  for (Int32 j = FIRST_DML_COL_PRIV; j <= LAST_DML_COL_PRIV; j++ )
-    {
-      if (!privBitmap.test(PrivType((PrivType)j)))
-         continue;
-
-      ComSecurityKey key(granteeID,
-                         objectUID,
-                         PrivType(j),
-                         ComSecurityKey::OBJECT_IS_OBJECT);
-      if (!key.isValid())
-        return false;
-      secKeySet.insert(key);
-   }
-   return true;
+
+  return true;
 }
 
 
@@ -195,7 +235,7 @@ ComSecurityKey::ComSecurityKey(
     if (typeOfObject == OBJECT_IS_SPECIAL_ROLE)
     {
       actionType_ = COM_QI_USER_GRANT_SPECIAL_ROLE;
-      subjectHash_ = generateHash(subjectUserID);
+      subjectHash_ = SPECIAL_SUBJECT_HASH;
       objectHash_ = SPECIAL_OBJECT_HASH;
     }
   }
@@ -336,7 +376,7 @@ void ComSecurityKey::getSecurityKeyTypeAsLit (std::string &actionString) const
       actionString = COM_QI_SCHEMA_EXECUTE_LIT;
       break;
     case COM_QI_USER_GRANT_SPECIAL_ROLE:
-      actionString = COM_QI_USER_GRANT_SPECIAL_ROLE;
+      actionString = COM_QI_USER_GRANT_SPECIAL_ROLE_LIT;
       break;
     default:
       actionString = COM_QI_INVALID_ACTIONTYPE_LIT;

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/3b437720/core/sql/common/ComSecurityKey.h
----------------------------------------------------------------------
diff --git a/core/sql/common/ComSecurityKey.h b/core/sql/common/ComSecurityKey.h
index ed1f78e..fbf60f3 100644
--- a/core/sql/common/ComSecurityKey.h
+++ b/core/sql/common/ComSecurityKey.h
@@ -29,6 +29,7 @@
 #include "Collections.h"
 #include "sqlcli.h"
 #include "PrivMgrCommands.h"
+#include "PrivMgrDesc.h"
 
 class PrivMgrUserPrivs;
 
@@ -41,9 +42,11 @@ NABoolean qiCheckForInvalidObject (const Int32 numInvalidationKeys,
                                    const Int64 objectUID,
                                    const ComSecurityKeySet objectKeys);
 
-bool buildSecurityKeySet(PrivMgrUserPrivs *privInfo,
-                         Int64 objectUID,
-                         ComSecurityKeySet &secKeySet);
+bool buildSecurityKeys( const int32_t granteeID,
+                        const int32_t roleID,
+                        const int64_t objectUID,
+                        const PrivMgrCoreDesc &privs,
+                        ComSecurityKeySet &secKeySet);
 
 
 // ****************************************************************************

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/3b437720/core/sql/optimizer/BindRelExpr.cpp
----------------------------------------------------------------------
diff --git a/core/sql/optimizer/BindRelExpr.cpp b/core/sql/optimizer/BindRelExpr.cpp
index 71f3b0b..6f1e4d7 100644
--- a/core/sql/optimizer/BindRelExpr.cpp
+++ b/core/sql/optimizer/BindRelExpr.cpp
@@ -6816,78 +6816,96 @@ NABoolean RelRoot::checkPrivileges(BindWA* bindWA)
   return !bindWA->failedForPrivileges() ;
 }
 
+// ****************************************************************************
+// method: findKeyAndInsertInOutputList
+//
+// This method searches through the list of security keys associated with the
+// object to find the best candidate to save in the plan based on the
+// privilege required.  If it finds a candidate, it inserts the best candidate 
+// into securityKeySet_ member of the RelRoot class.
+//
+// Security key types currently include:
+//   COM_QI_OBJECT_<priv>:   privileges granted directly to the user
+//   COM_QI_USER_GRANT_ROLE: privileges granted to the user via a role 
+//   COM_QI_USER_GRANT_SPECIAL_ROLE: privileges granted to PUBLIC
+//
+// COM_QI_OBJECT_<priv> types are preferred over COM_QI_USER_GRANT_ROLE.
+// ****************************************************************************
 void RelRoot::findKeyAndInsertInOutputList( ComSecurityKeySet KeysForTab
                                           , const uint32_t userHashValue
                                           , const PrivType which
                                           )
 {
-   ComSecurityKey  dummyKey;
+   // If no keys associated with object, just return
+   if (KeysForTab.entries() == 0)
+     return;
 
-   ComQIActionType objectActionType =
-                   dummyKey.convertBitmapToQIActionType ( which, ComSecurityKey::OBJECT_IS_OBJECT );
-
-   ComSecurityKey * UserSchemaKey = NULL;
    ComSecurityKey * UserObjectKey = NULL;
-   ComSecurityKey * RoleSchemaKey = NULL;
    ComSecurityKey * RoleObjectKey = NULL;
-   ComSecurityKey * BestKey = NULL;
+   ComSecurityKey * UserObjectPublicKey = NULL;
+   
+   // These may be implemented at a later time
+   ComSecurityKey * UserSchemaKey = NULL; //privs granted at schema level to user
+   ComSecurityKey * RoleSchemaKey = NULL; //privs granted at schema level to role
 
-   ComSecurityKey * thisKey = &(KeysForTab[0]);
+   // Get action type for UserObjectKey based on the privilege (which)
+   // so if (which) is SELECT, then the objectActionType is COM_QI_OBJECT_SELECT
+   ComSecurityKey  dummyKey;
+   ComQIActionType objectActionType =
+                   dummyKey.convertBitmapToQIActionType ( which, ComSecurityKey::OBJECT_IS_OBJECT );
 
-   uint32_t hashValueOfPublic = 0;
+   ComSecurityKey * thisKey = NULL;
 
    // NOTE: hashValueOfPublic will be the same for all keys, so we generate it only once.
-   if ( KeysForTab.entries() > 0 )
-      hashValueOfPublic = thisKey->generateHash(PUBLIC_USER);
+   uint32_t hashValueOfPublic = ComSecurityKey::SPECIAL_OBJECT_HASH;
 
    // Traverse List looking for ANY appropriate ComSecurityKey 
    for ( Int32 ii = 0; ii < (Int32)(KeysForTab.entries()); ii++ )
    {
       thisKey = &(KeysForTab[ii]);
+  
+      // See if the key is object related
       if ( thisKey->getSecurityKeyType() == objectActionType )
       {
-         if ( thisKey->getSubjectHashValue() == hashValueOfPublic ||
-              thisKey->getSubjectHashValue() == userHashValue )
+         if ( thisKey->getSubjectHashValue() == userHashValue )
          {
-              if ( ! UserObjectKey ) UserObjectKey = thisKey;
+            // Found a security key for the objectActionType
+            if ( ! UserObjectKey ) 
+               UserObjectKey = thisKey;
+         }
+      }
+     
+      // See if the security key is role related
+      else if (thisKey->getSecurityKeyType() == COM_QI_USER_GRANT_ROLE) 
+      {
+         if ( thisKey->getSubjectHashValue() == userHashValue )
+         {
+            if (! RoleObjectKey ) 
+               RoleObjectKey = thisKey;
          }
-         else if ( ! RoleObjectKey ) RoleObjectKey = thisKey;
       }
-      else {;} // Not right action type, just continue traversing.
-   }
-
-   if ( UserObjectKey ) BestKey = UserObjectKey ;
-   else if ( RoleObjectKey ) BestKey = RoleObjectKey ;
-   if ( BestKey == NULL)
-     return;  // Sometimes there aren't any security keys
-   securityKeySet_.insert(*BestKey);
-
-   uint32_t SubjHashValue = BestKey->getSubjectHashValue();
-   hashValueOfPublic = BestKey->generateHash(PUBLIC_USER);
 
-   // Check whether this privilege was granted to PUBLIC.  If so, nothing more to check.
-   if ( SubjHashValue == hashValueOfPublic )
-      return;
-   while ( SubjHashValue != userHashValue ) //While we see a ComSecurityKey for a Role
-   {
-      NABoolean found = FALSE;
-      for ( Int32 ii = 0; ii < (Int32)(KeysForTab.entries()); ii++ )
+      else if (thisKey->getSecurityKeyType() == COM_QI_USER_GRANT_SPECIAL_ROLE)
       {
-         // If this ComSecurityKey is a GRANT type and the grantee (the object)
-         // is the Role specified by SubjHashValue, then break out of inner loop.
-         ComSecurityKey * thisKey = &(KeysForTab[ii]);
-         if ( (   thisKey->getObjectHashValue() == SubjHashValue ) &&
-              (  (thisKey->getSecurityKeyType() == COM_QI_USER_GRANT_ROLE ) ) )
+         if (thisKey->getObjectHashValue() == hashValueOfPublic )
          {
-            securityKeySet_.insert(*thisKey); // Insert this GRANT type ComSecurityKey into the Plan
-            found = TRUE;
-            SubjHashValue = thisKey->getSubjectHashValue();
-            break; // We found the user or Role which granted the user the privilege
+            if (! UserObjectPublicKey )
+               UserObjectPublicKey = thisKey;
          }
       }
-      // found should never be FALSE
-      CMPASSERT(found)
+
+      else {;} // Not right action type, just continue traversing.
    }
+
+   // Determine best key, UserObjectKeys are better than RoleObjectKeys
+   ComSecurityKey * BestKey = (UserObjectKey) ? UserObjectKey : RoleObjectKey;
+
+   if ( BestKey != NULL)
+      securityKeySet_.insert(*BestKey);
+
+   // Add public if it exists
+   if ( UserObjectPublicKey != NULL )
+     securityKeySet_.insert(*UserObjectPublicKey); 
 }
 
 

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/3b437720/core/sql/optimizer/NARoutine.cpp
----------------------------------------------------------------------
diff --git a/core/sql/optimizer/NARoutine.cpp b/core/sql/optimizer/NARoutine.cpp
index e46f6b7..096e2bc 100644
--- a/core/sql/optimizer/NARoutine.cpp
+++ b/core/sql/optimizer/NARoutine.cpp
@@ -656,24 +656,73 @@ void NARoutine::getPrivileges(TrafDesc *priv_desc)
     return;
   }
 
+  NAString privMDLoc = CmpSeabaseDDL::getSystemCatalogStatic();
+  privMDLoc += ".\"";
+  privMDLoc += SEABASE_PRIVMGR_SCHEMA;
+  privMDLoc += "\"";
+  PrivMgrCommands privInterface(privMDLoc.data(), CmpCommon::diags(),PrivMgr::PRIV_INITIALIZED);
+
   if (priv_desc == NULL)
   {
-    *CmpCommon::diags() << DgSqlCode(-1034);
-     return;
-  }
+    privInfo_ = new(heap_) PrivMgrUserPrivs;
 
-  // create privInfo_ from priv_desc
-  privInfo_ = new(heap_) PrivMgrUserPrivs(priv_desc, ComUser::getCurrentUser());
+    CmpSeabaseDDL cmpSBD(STMTHEAP);
+    if (cmpSBD.switchCompiler(CmpContextInfo::CMPCONTEXT_TYPE_META))
+    {
+      if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
+        *CmpCommon::diags() << DgSqlCode( -4400 );
 
-  // buildSecurityKeySet uses privInfo_ member to set up the security keys
-  bool rslt = buildSecurityKeySet(privInfo_, objectUID_, routineSecKeySet_);
-  if (!rslt)
+      return;
+    }
+
+    ComObjectType objectType = (UDRType_ == COM_PROCEDURE_TYPE ?
+                                COM_STORED_PROCEDURE_OBJECT :
+                                COM_USER_DEFINED_ROUTINE_OBJECT);
+
+    std::vector <ComSecurityKey *>* secKeyVec = new(heap_) std::vector<ComSecurityKey *>;
+    if (privInterface.getPrivileges(objectUID_, objectType,
+                                    ComUser::getCurrentUser(), 
+                                   *privInfo_, secKeyVec) != STATUS_GOOD)
     {
       NADELETE(privInfo_, PrivMgrUserPrivs, heap_);
       privInfo_ = NULL;
-      *CmpCommon::diags() << DgSqlCode( -4400 );
+    }
+
+    cmpSBD.switchBackCompiler();
+
+    if (privInfo_)
+    {
+      for (std::vector<ComSecurityKey*>::iterator iter = secKeyVec->begin();
+           iter != secKeyVec->end();
+           iter++)
+      {
+        // Insertion of the dereferenced pointer results in NASet making
+        // a copy of the object, and then we delete the original.
+        routineSecKeySet_.insert(**iter);
+          delete *iter;
+      }
+    }
+  }
+  else
+  {
+    // getActive roles
+    std::vector<int32_t> roleIDs;
+    CmpSeabaseDDL cmpSBD(STMTHEAP);
+    if (cmpSBD.switchCompiler(CmpContextInfo::CMPCONTEXT_TYPE_META))
+    { 
+      if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
+        *CmpCommon::diags() << DgSqlCode( -4400 );
       return;
     }
+
+    PrivStatus retcode = privInterface.getRoles( ComUser::getCurrentUser(), roleIDs);
+    cmpSBD.switchBackCompiler();
+    if (retcode == STATUS_ERROR)
+      return;
+
+    privInfo_ = new (heap_) PrivMgrUserPrivs;
+    privInfo_->initUserPrivs(roleIDs, priv_desc, ComUser::getCurrentUser(),objectUID_, routineSecKeySet_);
+  }
 }
 
 ULng32 NARoutineDBKey::hash() const