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:32 UTC

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

Repository: incubator-trafodion
Updated Branches:
  refs/heads/master ca00ea231 -> b12b45eca


http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/3b437720/core/sql/sqlcomp/CmpSeabaseDDLcommon.cpp
----------------------------------------------------------------------
diff --git a/core/sql/sqlcomp/CmpSeabaseDDLcommon.cpp b/core/sql/sqlcomp/CmpSeabaseDDLcommon.cpp
index 4ef16c5..d9b1423 100644
--- a/core/sql/sqlcomp/CmpSeabaseDDLcommon.cpp
+++ b/core/sql/sqlcomp/CmpSeabaseDDLcommon.cpp
@@ -10356,6 +10356,27 @@ std::string commandString;
       SEABASEDDL_INTERNAL_ERROR(commandString.c_str());
    }
    
+   // update the redef timestamp for the role in auths table
+   char buf[(roleIDs.size()*12) + 500];
+   Int64 redefTime = NA_JulianTimestamp();
+   std::string roleList;
+   for (size_t i = 0; i < roleIDs.size(); i++)
+   {
+     if (i > 0)
+       roleList += ", ";
+     roleList += to_string((long long int)roleIDs[i]);
+   }
+
+   str_sprintf(buf, "update %s.\"%s\".%s set auth_redef_time = %Ld "
+                    "where auth_id in (%s)",
+              systemCatalog.c_str(), SEABASE_MD_SCHEMA, SEABASE_AUTHS,
+              redefTime, roleList.c_str());
+ 
+   ExeCliInterface cliInterface(STMTHEAP);
+   Int32 cliRC = cliInterface.executeImmediate(buf);
+   if (cliRC < 0)
+      cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
+
 }
 //********************** End of grantRevokeSeabaseRole *************************
 

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/3b437720/core/sql/sqlcomp/PrivMgrCommands.cpp
----------------------------------------------------------------------
diff --git a/core/sql/sqlcomp/PrivMgrCommands.cpp b/core/sql/sqlcomp/PrivMgrCommands.cpp
index 550ac64..6faf70b 100644
--- a/core/sql/sqlcomp/PrivMgrCommands.cpp
+++ b/core/sql/sqlcomp/PrivMgrCommands.cpp
@@ -67,96 +67,138 @@ PrivMgrObjectInfo::PrivMgrObjectInfo(
 // ****************************************************************************
 // Class: PrivMgrUserPrivs
 // ****************************************************************************
-PrivMgrUserPrivs::PrivMgrUserPrivs(
+bool PrivMgrUserPrivs::initUserPrivs(
+  const std::vector<int32_t> & roleIDs,
   const TrafDesc *priv_desc,
-  const int32_t userID)
+  const int32_t userID,
+  const int64_t objectUID,
+  ComSecurityKeySet & secKeySet)
 {
-  assert (priv_desc);
+  hasPublicPriv_ = false;
 
   // generate PrivMgrUserPrivs from the priv_desc structure
   TrafDesc *priv_grantees_desc = priv_desc->privDesc()->privGrantees;
-  TrafDesc *priv_grantee_desc = NULL;
-  TrafDesc *priv_public_desc = NULL;
+  NAList<PrivMgrDesc> descList;
 
-  // Find relevant desc for the user
+  // Find relevant descs for the user
   while (priv_grantees_desc)
   {
     Int32 grantee = priv_grantees_desc->privGranteeDesc()->grantee;
+    bool addDesc = false;
     if (grantee == userID)
-      priv_grantee_desc = priv_grantees_desc->privGranteeDesc();
+      addDesc = true;
+
+    if (PrivMgr::isRoleID(grantee))
+    {
+      if ((std::find(roleIDs.begin(), roleIDs.end(), grantee)) != roleIDs.end())
+        addDesc = true;
+    }
 
     if (ComUser::isPublicUserID(grantee))
-      priv_public_desc = priv_grantees_desc->privGranteeDesc();
+    {
+      addDesc = true;
+      hasPublicPriv_ = true;
+    }
 
-    priv_grantees_desc = priv_grantees_desc->next;
-  }
+    // Create a list of PrivMgrDesc contain privileges for user, user's roles,
+    // and public
+    if (addDesc)
+    {
+      TrafDesc *objectPrivs = priv_grantees_desc->privGranteeDesc()->objectBitmap;
 
-  // If the user has a privilege in the priv_grantees_desc list, use it to
-  // create the PrivMgrUserPrivs class.
-  if (priv_grantee_desc)
-  {
+      PrivMgrCoreDesc objectDesc(objectPrivs->privBitmapDesc()->privBitmap,
+                                 objectPrivs->privBitmapDesc()->privWGOBitmap);
+      
+      TrafDesc *priv_grantee_desc = priv_grantees_desc->privGranteeDesc();
+      TrafDesc *columnPrivs = priv_grantee_desc->privGranteeDesc()->columnBitmaps;
+      NAList<PrivMgrCoreDesc> columnDescs;
+      while (columnPrivs)
+      {
+        PrivMgrCoreDesc columnDesc(columnPrivs->privBitmapDesc()->privBitmap,
+                                   columnPrivs->privBitmapDesc()->privWGOBitmap,
+                                   columnPrivs->privBitmapDesc()->columnOrdinal);
+        columnDescs.insert(columnDesc);
+        columnPrivs = columnPrivs->next;
+      }
 
-    // Set up object level privileges
-    TrafDesc *objectPrivs = priv_grantee_desc->privGranteeDesc()->objectBitmap;
-    objectBitmap_ = objectPrivs->privBitmapDesc()->privBitmap;
-    grantableBitmap_ = objectPrivs->privBitmapDesc()->privWGOBitmap;
+      PrivMgrDesc privs(priv_grantees_desc->privGranteeDesc()->grantee);
+      privs.setTablePrivs(objectDesc);
+      privs.setColumnPrivs(columnDescs);
+      privs.setHasPublicPriv(hasPublicPriv_);
 
-    // Set up column level privileges
-    // The PrivColList is a key <=> value pair structure, the key is the
-    // column ordinal (number) and the value is the associated bitmap.
-    TrafDesc *columnPrivs = priv_grantee_desc->privGranteeDesc()->columnBitmaps;
-    PrivColList colPrivsList;
-    PrivColList colGrantableList;
-    while (columnPrivs)
-    {
-      Int32 columnOrdinal = columnPrivs->privBitmapDesc()->columnOrdinal;
-      colPrivsList[columnOrdinal] = columnPrivs->privBitmapDesc()->privBitmap;
-      colGrantableList[columnOrdinal] = columnPrivs->privBitmapDesc()->privWGOBitmap;
-      columnPrivs = columnPrivs->next;
+      descList.insert(privs);
     }
-    colPrivsList_= colPrivsList;
-    colGrantableList_ = colGrantableList;
+    priv_grantees_desc = priv_grantees_desc->next;
   }
 
-  // See if there are privileges assigned to public.  If so, "or" the public
-  // list to the user to the current bitmaps. Initially all the bitmap are
-  // set to 0.
-  if (priv_public_desc)
+  // Union privileges from all grantees together to create a single set of
+  // bitmaps.  Create security invalidation keys
+  for (int i = 0; i < descList.entries(); i++)
   {
+    PrivMgrDesc privs = descList[i];
+
     // Set up object level privileges
-    TrafDesc *objectPrivs = priv_public_desc->privGranteeDesc()->objectBitmap;
-    objectBitmap_ |= objectPrivs->privBitmapDesc()->privBitmap;
-    grantableBitmap_ |= objectPrivs->privBitmapDesc()->privWGOBitmap;
+    objectBitmap_ |= privs.getTablePrivs().getPrivBitmap();
+    grantableBitmap_ |= privs.getTablePrivs().getWgoBitmap();
 
     // Set up column level privileges
-    // The PrivColList is a key <=> value pair structure, the key is the
-    // column ordinal (number) and the value is the associated bitmap.
-    TrafDesc *columnPrivs = priv_public_desc->privGranteeDesc()->columnBitmaps;
-    PrivColList colPrivsList;
-    PrivColList colGrantableList;
-    std::map<size_t,PrivColumnBitmap>::iterator it; 
-    while (columnPrivs)
+    NAList<PrivMgrCoreDesc> columnPrivs = privs.getColumnPrivs();
+    std::map<size_t,PrivColumnBitmap>::iterator it;
+    for (int j = 0; j < columnPrivs.entries(); j++)
     {
-      Int32 columnOrdinal = columnPrivs->privBitmapDesc()->columnOrdinal;
+      PrivMgrCoreDesc colDesc = columnPrivs[j];
+      Int32 columnOrdinal = colDesc.getColumnOrdinal();
       it = colPrivsList_.find(columnOrdinal);
       if (it == colPrivsList_.end())
       {
-        colPrivsList_[columnOrdinal] = columnPrivs->privBitmapDesc()->privBitmap;
-        colGrantableList[columnOrdinal] = columnPrivs->privBitmapDesc()->privWGOBitmap;
+        colPrivsList_[columnOrdinal] = colDesc.getPrivBitmap();
+        colGrantableList_[columnOrdinal] = colDesc.getWgoBitmap();
       }
       else
       {
-        colPrivsList_[columnOrdinal] |= columnPrivs->privBitmapDesc()->privBitmap;
-        colGrantableList[columnOrdinal] |= columnPrivs->privBitmapDesc()->privWGOBitmap;
+        colPrivsList_[columnOrdinal] |= colDesc.getPrivBitmap();
+        colGrantableList_[columnOrdinal] |= colDesc.getWgoBitmap();
       }
+    }
+
+    // set up security invalidation keys
+    Int32 grantee = privs.getGrantee();
+    Int32 role = (ComUser::isPublicUserID(grantee) || PrivMgr::isRoleID(grantee)) 
+        ? grantee : NA_UserIdDefault;
 
-      columnPrivs = columnPrivs->next;
+    if (!buildSecurityKeys(userID, role, objectUID, privs.getTablePrivs(), secKeySet))
+      return false;
+
+    for (int k = 0; k < colPrivsList_.size(); k++)
+    {
+      PrivMgrCoreDesc colDesc(colPrivsList_[k], colGrantableList_[k]);
+      if (!buildSecurityKeys(userID, role, objectUID, colDesc, secKeySet))
+        return false;
     }
   }
 
   // TBD - add schema privilege bitmaps
+  return true;
 }
 
+// ----------------------------------------------------------------------------
+// method: initUserPrivs
+//
+// Creates a PrivMgrUserPrivs object from a PrivMgrDesc object
+// ----------------------------------------------------------------------------
+void PrivMgrUserPrivs::initUserPrivs(PrivMgrDesc &privsOfTheUser)
+{
+  objectBitmap_ = privsOfTheUser.getTablePrivs().getPrivBitmap();
+  grantableBitmap_ = privsOfTheUser.getTablePrivs().getWgoBitmap();
+
+  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();
+  }
+  hasPublicPriv_ = privsOfTheUser.getHasPublicPriv();
+}
 
 // ****************************************************************************
 // Class: PrivMgrCommands
@@ -546,10 +588,7 @@ PrivStatus PrivMgrCommands::getPrivileges(
   PrivMgrUserPrivs &userPrivs,
   std::vector <ComSecurityKey *>* secKeySet)
 {
-  PrivMgrBitmap objPrivs;
-  PrivMgrBitmap grantablePrivs;
-  PrivColList colPrivsList;
-  PrivColList colGrantableList;
+  PrivMgrDesc privsOfTheUser;
 
   // If authorization is enabled, go get privilege bitmaps from metadata
   if (authorizationEnabled())
@@ -558,10 +597,7 @@ PrivStatus PrivMgrCommands::getPrivileges(
     PrivStatus retcode = objectPrivs.getPrivsOnObjectForUser(objectUID,
                                                              objectType, 
                                                              userID, 
-                                                             objPrivs, 
-                                                             grantablePrivs,
-                                                             colPrivsList,
-                                                             colGrantableList,
+                                                             privsOfTheUser, 
                                                              secKeySet);
     if (retcode != STATUS_GOOD)
       return retcode;
@@ -570,20 +606,42 @@ PrivStatus PrivMgrCommands::getPrivileges(
   // authorization is not enabled, return bitmaps with all bits set
   // With all bits set, privilege checks will always succeed
   else
-  {
-    objPrivs.set();
-    grantablePrivs.set();
-  }
+    privsOfTheUser.getTablePrivs().setAllPrivAndWgo(true);
 
-  userPrivs.setObjectBitmap(objPrivs);
-  userPrivs.setGrantableBitmap(grantablePrivs);
-  userPrivs.setColPrivList(colPrivsList);
-  userPrivs.setColGrantableList(colGrantableList);
+  userPrivs.initUserPrivs(privsOfTheUser);
     
   return STATUS_GOOD;
 }
 
 
+// ----------------------------------------------------------------------------
+// method: getRoles
+//
+// Returns roleIDs for the grantee.
+//                                                                       
+//  <granteeID> the authorization ID to obtain roles for
+//  <roleIDs> is the returned list of roles
+//                                                                  
+// Returns: PrivStatus                                               
+//                                                                  
+//   STATUS_GOOD: role list was built
+//             *: unexpected error occurred, see diags.     
+// ----------------------------------------------------------------------------
+PrivStatus PrivMgrCommands::getRoles(
+  const int32_t granteeID,
+  std::vector <int32_t > &roleIDs)
+{
+  // If authorization is not enabled, return
+  if (!authorizationEnabled())
+    return STATUS_GOOD;
+  
+  PrivMgrRoles roles(" ",metadataLocation_,pDiags_);
+  std::vector<std::string> roleNames;
+  std::vector<int32_t> roleDepths;
+
+  return  roles.fetchRolesForUser(granteeID,roleNames,roleIDs,roleDepths);
+}
+
 // *****************************************************************************
 // *                                                                           *
 // * Function: PrivMgrCommands::getPrivRowsForObject                           *

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/3b437720/core/sql/sqlcomp/PrivMgrCommands.h
----------------------------------------------------------------------
diff --git a/core/sql/sqlcomp/PrivMgrCommands.h b/core/sql/sqlcomp/PrivMgrCommands.h
index cf281e8..74849c3 100644
--- a/core/sql/sqlcomp/PrivMgrCommands.h
+++ b/core/sql/sqlcomp/PrivMgrCommands.h
@@ -31,6 +31,7 @@
 #include "PrivMgrMD.h"
 #include "PrivMgrDefs.h"
 #include "TrafDDLdesc.h"
+#include "ComSecurityKey.h"
 
 class ComDiagsArea;
 class ComSecurityKey;
@@ -130,10 +131,9 @@ class PrivMgrUserPrivs
 {
   public:
 
-  PrivMgrUserPrivs(const int32_t nbrCols = 0){};
-  PrivMgrUserPrivs(
-    const TrafDesc *priv_desc,
-    const int32_t userID);
+  PrivMgrUserPrivs()
+  : hasPublicPriv_(false)
+  {}
 
   static std::string convertPrivTypeToLiteral(PrivType which)
   {
@@ -392,6 +392,14 @@ class PrivMgrUserPrivs
   void setSchemaGrantableBitmap (PrivSchemaBitmap schemaGrantableBitmap)
      {schemaGrantableBitmap_ = schemaGrantableBitmap;}
 
+  bool getHasPublicPriv() { return hasPublicPriv_; }
+  void setHasPublicPriv(bool hasPublicPriv) {hasPublicPriv_ = hasPublicPriv;}
+  void initUserPrivs (PrivMgrDesc &privsOfTheGrantor);
+  bool initUserPrivs ( const std::vector<int32_t> &roleIDs,
+                       const TrafDesc *priv_desc,
+                       const int32_t userID,
+                       const int64_t objectUID,
+                       NASet<ComSecurityKey> & secKeySet);
 
  private:
    PrivObjectBitmap objectBitmap_;
@@ -401,8 +409,10 @@ class PrivMgrUserPrivs
    PrivSchemaBitmap schemaPrivBitmap_;
    PrivSchemaBitmap schemaGrantableBitmap_;
    PrivColumnBitmap emptyBitmap_;
+   bool hasPublicPriv_;
 };
 
+
 // *****************************************************************************
 // *
 // * Class:        PrivMgrCommands
@@ -479,6 +489,10 @@ public:
       const int64_t objectUID,
       std::vector<ObjectPrivsRow> & objectPrivsRows);
       
+   PrivStatus getRoles(
+      const int32_t grantee,
+      std::vector<int32_t> &roleIDs);
+
    PrivStatus givePrivForObjects(
          const int32_t currentOwnerID,
          const int32_t newOwnerID,

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/3b437720/core/sql/sqlcomp/PrivMgrDesc.h
----------------------------------------------------------------------
diff --git a/core/sql/sqlcomp/PrivMgrDesc.h b/core/sql/sqlcomp/PrivMgrDesc.h
index 832255b..dc72474 100644
--- a/core/sql/sqlcomp/PrivMgrDesc.h
+++ b/core/sql/sqlcomp/PrivMgrDesc.h
@@ -382,7 +382,8 @@ public:
    PrivMgrDesc(const PrivMgrDesc&other)           // copy constructor
    : tableLevel_(other.tableLevel_),
      columnLevel_(other.columnLevel_),
-     grantee_(other.grantee_)
+     grantee_(other.grantee_),
+     hasPublicPriv_(other.hasPublicPriv_)
    {}
 
    PrivMgrDesc(const int32_t grantee,
@@ -390,20 +391,23 @@ public:
               )
    : tableLevel_(),
      columnLevel_(),
-     grantee_(grantee)
+     grantee_(grantee),
+     hasPublicPriv_(false)
   {}
 
    PrivMgrDesc(const PrivMgrDesc &privs,            // preset constructor
                const int32_t grantee)
    : tableLevel_(privs.tableLevel_),
      columnLevel_(privs.columnLevel_),
-     grantee_(privs.grantee_)
+     grantee_(privs.grantee_),
+     hasPublicPriv_(privs.hasPublicPriv_)
    {}
 
    PrivMgrDesc(void)
    : tableLevel_(),
      columnLevel_(),
-     grantee_(0)
+     grantee_(0),
+     hasPublicPriv_(false)
    {}
 
    virtual ~PrivMgrDesc()                 // destructor
@@ -419,6 +423,7 @@ public:
       tableLevel_  = other.tableLevel_;
       columnLevel_ = other.columnLevel_;
       grantee_ = other.grantee_;
+      hasPublicPriv_ = other.hasPublicPriv_;
 
       return *this;
    }
@@ -431,6 +436,7 @@ public:
       if ( this == &other )
          return TRUE;
 
+      // Not checking all members, should be okay
       return ( 
                ( columnLevel_ == other.columnLevel_ ) &&
                ( tableLevel_  == other.tableLevel_  ) &&
@@ -519,27 +525,6 @@ public:
    void resetTablePrivs() { tableLevel_.setAllPrivAndWgo(0); }
    void setColumnPrivs(const NAList<PrivMgrCoreDesc> &privs) { columnLevel_ = privs; }
 
-#if 0
-   void setColumnPriv(const PrivType which,
-                      const bool value,
-                      const int32_t ordinal
-                      );
-   void setColumnWgo(const PrivType which,
-                     const bool value,
-                     const int32_t ordinal
-                     );
-
-   void setOneColOrdPriv(const PrivMgrCoreDesc& privs,
-                         const int32_t ordinal
-                         );
-  void setAllColsPriv(const PrivType which,
-                       const bool value
-                      );
-   void setAllColsWgo(const PrivType which,
-                      const bool value
-                      );
-#endif
-
    // This will replace setAllDMLGrantPrivileges for the table level.  This function
    // is also used to set a view's privileges as well.
    void setAllTableGrantPrivileges(const bool wgo)
@@ -582,68 +567,27 @@ public:
    void setAllUdrRevokePrivileges(const bool grantOption);
    void setAllSequenceRevokePrivileges(const bool grantOption);
 
-
-    /* 
-     *  These six functions are called by CatAccessPrivs to perform GRANT/REVOKEs on the actual
-     *  PrivMgrCoreDesc members of the PrivMgrDesc.  Previously, these members were accessed directly
-     *  via friend declarations.
-     */
+   bool getHasPublicPriv() { return hasPublicPriv_; }
+   void setHasPublicPriv(bool hasPublicPriv) { hasPublicPriv_ = hasPublicPriv; }
 
    PrivMgrCoreDesc::PrivResult grantTablePrivs(PrivMgrCoreDesc& priv)
    { return tableLevel_.grantPrivs(priv); }
    //PrivMgrCoreDesc::PrivResult grantColumnPrivs(PrivMgrCoreDesc& priv, const int32_t ordinal);
-   
+
    PrivMgrCoreDesc::PrivResult revokeTablePrivs(PrivMgrCoreDesc& priv)
    { return tableLevel_.revokePrivs(priv); }
    //PrivMgrCoreDesc::PrivResult revokeColumnPrivs(PrivMgrCoreDesc& priv, const int32_t ordinal);
 
 
-#if 0
-   /* 
-    *  Apply the privileges in this descriptor to a target object,
-    *  as grants from the specified Grantor.
-    *  Modify the privilege settings in the descriptor to carry only the
-    *  privileges newly granted.
-    *  Return ALL/SOME/NONE, according to how many specified privileges
-    *  were actually granted.
-    */
-CatPrivs::PrivResult applyTableGrants(const int64_t objectUID,
-                                      const int32_t& theGrantor
-                                      );
-   /* 
-    *  Apply the privileges in this descriptor to a target object,
-    *  as revokes from the specified Grantor.
-    *  Modify the privilege settings in the descriptor to carry only the
-    *  privileges newly granted.
-    *  Return ALL/SOME/NONE, according to how many specified privileges
-    *  were actually granted.
-    */
-
-
-   /* 
-    *  Apply the privileges in this descriptor to a target object,
-    *  as revokes from the specified Grantor.
-    *  Modify the privilege settings in the descriptor to carry only the
-    *  privileges newly granted.
-    *  Return ALL/SOME/NONE, according to how many specified privileges
-    *  were actually granted.
-    */
-
-
-   PrivMgrCoreDesc::PrivResult applyTableRevokes(CatRWTableValued* targetObjectP,
-                                          const int32_t& theGrantor
-                                          );
-
    void pTrace() const;   // Debug trace
 
-#endif
 
    // Data members
 private:
-
    PrivMgrCoreDesc                 tableLevel_;
    NAList<PrivMgrCoreDesc>         columnLevel_;
    int32_t                         grantee_;
+   bool                            hasPublicPriv_;
 };
 
 

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/3b437720/core/sql/sqlcomp/PrivMgrPrivileges.cpp
----------------------------------------------------------------------
diff --git a/core/sql/sqlcomp/PrivMgrPrivileges.cpp b/core/sql/sqlcomp/PrivMgrPrivileges.cpp
index 0dbb45b..f18dacc 100644
--- a/core/sql/sqlcomp/PrivMgrPrivileges.cpp
+++ b/core/sql/sqlcomp/PrivMgrPrivileges.cpp
@@ -337,17 +337,6 @@ void static buildGrantText(
    const int32_t ownerID,
    std::string & grantText);
 
-static PrivStatus buildColumnSecurityKeys(
-   const int64_t objectUID,
-   const PrivColList & colPrivsList,
-   const int32_t userID, 
-   std::vector<ComSecurityKey *> & secKeySet);
-
-static PrivStatus buildUserSecurityKeys(
-   const std::vector<int32_t> & roleIDs,
-   const int32_t userID, 
-   std::vector <ComSecurityKey *> & secKeySet);
-   
 void static closeColumnList(std::string & columnList);   
 
 static void deleteRowList(std::vector<PrivMgrMDRow *> & rowList);
@@ -356,13 +345,6 @@ static PrivMgrCoreDesc * findColumnEntry(
    NAList<PrivMgrCoreDesc> & colPrivsToGrant,
    const int32_t columnsOrdinal);
    
-static PrivStatus getColRowsForGrantee(
-   const std::vector <PrivMgrMDRow *> &columnRowList,
-   const int32_t granteeID,
-   const std::vector<int32_t> & roleIDs,
-   std::vector<ColumnPrivsMDRow> &rowList,
-   std::vector <ComSecurityKey *>* secKeySet);   
-
 static void getColRowsForGranteeGrantor(
    const std::vector <PrivMgrMDRow *> & columnRowList,
    const int32_t granteeID,
@@ -498,20 +480,31 @@ PrivMgrPrivileges::~PrivMgrPrivileges()
 // *                                                               
 // *****************************************************************************
 PrivStatus PrivMgrPrivileges::buildSecurityKeys(
-   const int32_t granteeID, 
-   const PrivMgrCoreDesc &privs,
-   std::vector <ComSecurityKey *> & secKeySet)
-  
+  const int32_t granteeID,
+  const int32_t roleID,
+  const PrivMgrCoreDesc &privs,
+  std::vector <ComSecurityKey *> & secKeySet)
 {
+  if (privs.isNull())
+    return STATUS_GOOD;
+
   // Only need to generate keys for DML privileges
   for ( size_t i = FIRST_DML_PRIV; i <= LAST_DML_PRIV; i++ )
   {
     if ( privs.getPriv(PrivType(i)))
     {
-      ComSecurityKey *key = new ComSecurityKey(granteeID, 
-                                               objectUID_,
-                                               PrivType(i),
-                                               ComSecurityKey::OBJECT_IS_OBJECT);
+      ComSecurityKey *key = NULL;
+      if (roleID != NA_UserIdDefault && ComUser::isPublicUserID(roleID))
+        key = new ComSecurityKey(granteeID, 
+                                 ComSecurityKey::OBJECT_IS_SPECIAL_ROLE);
+      else if (roleID != NA_UserIdDefault && isRoleID(roleID))
+        key = new ComSecurityKey(granteeID, roleID,
+                                 ComSecurityKey::SUBJECT_IS_USER);
+      else
+        key = new ComSecurityKey(granteeID, 
+                                 objectUID_,
+                                 PrivType(i),
+                                 ComSecurityKey::OBJECT_IS_OBJECT);
       if (key->isValid())
          secKeySet.push_back(key);
       else
@@ -562,95 +555,57 @@ PrivStatus PrivMgrPrivileges::getPrivsOnObject (
   if (generateColumnRowList() == STATUS_ERROR)
     return STATUS_ERROR;
   
-  // Gets all the grantees (userIDs) from the object and column lists
-  // The public auth ID is also included in this list
+  // Gets all the user grantees (userIDs) for the object and column lists
+  // Gets all the role grantees (roleIDs) for the object and column lists
+  // The public auth ID is included in the userIDs list
   std::vector<int32_t> userIDs;
-  if (getDistinctUserIDs(objectRowList_, columnRowList_, userIDs) == STATUS_ERROR)
+  std::vector<int32_t> roleIDs;
+  if (getDistinctIDs(objectRowList_, columnRowList_, userIDs, roleIDs) == STATUS_ERROR)
     return STATUS_ERROR;
 
+  // Gather privilege descriptors for each user
   for (size_t i = 0; i < userIDs.size(); i++)
   {
     int32_t userID = userIDs[i];
 
     PrivMgrDesc privsOfTheUser(userID);
     bool hasManagePrivileges = false;
-    std::vector <int32_t> roleIDs;
+    std::vector <int32_t> emptyRoleIDs;
  
-    // Public is not granted roles, skip to avoid extra I/O
-    if (!ComUser::isPublicUserID(userID))
-    {
-      if (getRoleIDsForUserID(userID,roleIDs) == STATUS_ERROR)
-        return STATUS_ERROR;
-    }
-
+    // getUserPrivs returns object and column privileges summarized across all
+    // grantors.  Just get direct grants to the user (role list is empty) 
+    if (getUserPrivs(objectType, userID, emptyRoleIDs, privsOfTheUser,
+                     hasManagePrivileges, NULL ) != STATUS_GOOD)
+      return STATUS_ERROR;
+    
+    if (!privsOfTheUser.isNull())
+      privDescs.push_back(privsOfTheUser);
+  }
+  
+  // Attach roles to priv lists
+  for (size_t i = 0; i < roleIDs.size(); i++)
+  {
+    int32_t grantee = roleIDs[i];
+    
+    PrivMgrDesc privsOfTheUser(grantee);
+    bool hasManagePrivileges = false;
+    std::vector <int32_t> emptyRoleIDs;
+    
     // getUserPrivs returns object and column privileges summarized across
     // all grantors. 
-    if (getUserPrivs(objectType, userID, roleIDs, privsOfTheUser,
+    if (getUserPrivs(objectType, grantee, emptyRoleIDs, privsOfTheUser,
                      hasManagePrivileges, NULL ) != STATUS_GOOD)
       return STATUS_ERROR;
     
-    privDescs.push_back(privsOfTheUser);
+    if (!privsOfTheUser.isNull())
+      privDescs.push_back(privsOfTheUser);
   }
+
   return STATUS_GOOD;
 }
 
 
 // *****************************************************************************
-// * Method: getColPrivsForUser                                
-// *                                                       
-// *    Returns the column privileges a user has been granted on the object.
-// *                                                       
-// *  Parameters:    
-// *                                                                       
-// *  <granteeID> is the unique identifier for the grantee
-// *  <roleIDs> specifies a list of roles granted to the grantee
-// *  <colPrivsList> passes back the list of privs granted
-// *  <colGrantableList> passes back the list the user has WGO for
-// *  <secKeySet> if not NULL, returns a set of keys for user
-// *                                                                     
-// * Returns: PrivStatus                                               
-// *                                                                  
-// * STATUS_GOOD: Privileges were returned
-// *           *: Unable to lookup privileges, see diags.     
-// *                                                               
-// *****************************************************************************
-PrivStatus PrivMgrPrivileges::getColPrivsForUser(
-   const int32_t granteeID,
-   const std::vector<int32_t> & roleIDs,
-   PrivColList & colPrivsList,
-   PrivColList & colGrantableList,
-   std::vector <ComSecurityKey *>* secKeySet) 
-
-{
-
-   std::vector<ColumnPrivsMDRow> rowList;
-
-   // Get the privileges for the columns of the object granted to the grantee
-   PrivStatus privStatus = getColRowsForGrantee(columnRowList_,granteeID,roleIDs,
-                                                rowList,secKeySet);
-                                             
-   if (privStatus == STATUS_ERROR)
-      return privStatus; 
-     
-   for (int32_t i = 0; i < rowList.size();++i)
-   {
-      const int32_t columnOrdinal = rowList[i].columnOrdinal_;
-      colPrivsList[columnOrdinal] = rowList[i].privsBitmap_;
-      colGrantableList[columnOrdinal] = rowList[i].grantableBitmap_;
-      
-      if (secKeySet != NULL)
-      {
-         privStatus = buildColumnSecurityKeys(objectUID_,colPrivsList,
-                                             rowList[i].granteeID_,*secKeySet);
-         if (privStatus != STATUS_GOOD)
-            return privStatus;    
-      }
-   }
-
-   return STATUS_GOOD;
-}  
-
-// *****************************************************************************
 // Function: getColRowsForGranteeOrdinal                                     
 //                                                                           
 //    Returns the list of column privileges granted for the object that have 
@@ -691,22 +646,20 @@ void PrivMgrPrivileges::getColRowsForGranteeOrdinal(
 }
 
 // *****************************************************************************
-// * Method: getDistinctUserIDs                                
+// * Method: getDistinctIDs                                
+// *
+// * Finds all the userIDs that have been granted at least one privilege on
+// * object. This list includes the public authorization ID
 // *
-// * Finds all the usersIDs that have been granted at least one privilege on
-// * object.  These userIDs include direct grants: 
-// *   grant <privilege> on <object> to <user>  <== user added to list
-// * Or indirect grants through role:
-// *   grant <privilege> on <object> to <role>
-// *   grant <role> to <user>  <== user added to list
-// * Includes public in the returned list
-// *****************************************************************************
-PrivStatus PrivMgrPrivileges::getDistinctUserIDs(
+// * Finds all the roleIDs that have been granted at least one privilege on
+// * object
+// *****************************************************************************
+PrivStatus PrivMgrPrivileges::getDistinctIDs(
   const std::vector <PrivMgrMDRow *> &objectRowList,
   const std::vector <PrivMgrMDRow *> &columnRowList,
-  std::vector<int32_t> &userIDs)
+  std::vector<int32_t> &userIDs,
+  std::vector<int32_t> &roleIDs)
 {
-  std::vector<int32_t> roleIDs;
   int32_t authID;
 
   // DB__ROOTROLE is a special role.  If the current user has been granted 
@@ -715,15 +668,13 @@ PrivStatus PrivMgrPrivileges::getDistinctUserIDs(
   roleIDs.push_back(ROOT_ROLE_ID);
 
   // The direct object grants are stored in memory (objectRowList) so no I/O
-  // Save grants to roles for further processing
   for (size_t i = 0; i < objectRowList.size(); i++)
   {
     ObjectPrivsMDRow &row = static_cast<ObjectPrivsMDRow &> (*objectRowList[i]);
     authID = row.granteeID_;
 
     // insert authID into correct list, if not already present
-    if (ComUser::isPublicUserID(authID) || 
-        CmpSeabaseDDLauth::isUserID(authID)) 
+    if (ComUser::isPublicUserID(authID) || CmpSeabaseDDLauth::isUserID(authID)) 
     {
        if (std::find(userIDs.begin(), userIDs.end(), authID) == userIDs.end())
          userIDs.insert( std::upper_bound( userIDs.begin(), userIDs.end(), authID ), authID);
@@ -756,22 +707,6 @@ PrivStatus PrivMgrPrivileges::getDistinctUserIDs(
     }
   }
 
-  // Get the list of users that have been granted one or more of the roles in
-  // the role list.  A query that retrieves all userIDs granted to the list of
-  // roles (roleIDs) is performed. 
-  if (roleIDs.size() > 0)
-  {
-    std::vector<int32_t> userIDsForRoleIDs;
-    if (getUserIDsForRoleIDs(roleIDs, userIDsForRoleIDs) == STATUS_ERROR)
-      return STATUS_ERROR;
-
-    for (size_t i = 0; i < userIDsForRoleIDs.size(); i++)
-    {
-      authID = userIDsForRoleIDs[i];
-      if (std::find(userIDs.begin(), userIDs.end(), authID) == userIDs.end())
-         userIDs.insert( std::upper_bound( userIDs.begin(), userIDs.end(), authID ), authID);
-    }
-  }
   return STATUS_GOOD;
 }
   
@@ -3270,29 +3205,6 @@ PrivStatus PrivMgrPrivileges::revokeColumnPriv(
       rowRevoked = true;
    } 
    
-   // Send revoked privs to RMS
-   SQL_QIKEY siKeyList[NBR_DML_COL_PRIVS];
-   size_t siIndex = 0;
-
-   for (size_t i = FIRST_DML_COL_PRIV; i <= LAST_DML_COL_PRIV; i++ )
-   {
-      if (!revokedPrivs.test(PrivType(i)))
-         continue;
-         
-      ComSecurityKey secKey(granteeID,objectUID_,PrivType(i),
-                            ComSecurityKey::OBJECT_IS_OBJECT);
-      
-      siKeyList[siIndex].revokeKey.subject = secKey.getSubjectHashValue();
-      siKeyList[siIndex].revokeKey.object = secKey.getObjectHashValue();
-      std::string actionString;
-      secKey.getSecurityKeyTypeAsLit(actionString);
-      strncpy(siKeyList[siIndex].operation,actionString.c_str(),2);
-      siIndex++;                          
-   }      
-   
-   if (siIndex > 0)   
-      SQL_EXEC_SetSecInvalidKeys(siIndex,siKeyList);
-      
    // if (!rowRevoked)
    //   Warning
       
@@ -3377,6 +3289,11 @@ PrivStatus PrivMgrPrivileges::revokeObjectPriv (const ComObjectType objectType,
   // If only column-level privileges were specified, no problem.  
   if (privsToRevoke.getTablePrivs().isNull())
   {
+    // Send a message to the Trafodion RMS process about the revoke operation.
+    // RMS will contact all master executors and ask that cached privilege 
+    // information be re-calculated
+    retcode = sendSecurityKeysToRMS(granteeID, privsToRevoke);
+
     // report any privs not granted
     if (warnNotAll)
       reportPrivWarnings(origPrivsToRevoke,
@@ -4005,7 +3922,7 @@ void PrivMgrPrivileges::scanColumnPublic(
 // input:
 //    granteeID - the UID of the user losing privileges
 //       the granteeID is stored in the PrivMgrDesc class - extra?
-//    listOfRevokePrivileges - the list of privileges that were revoked
+//    revokedPrivs - the list of privileges that were revoked
 //
 // Returns: PrivStatus                                               
 //                                                                  
@@ -4014,43 +3931,39 @@ void PrivMgrPrivileges::scanColumnPublic(
 // ****************************************************************************
 PrivStatus PrivMgrPrivileges::sendSecurityKeysToRMS(
   const int32_t granteeID, 
-  const PrivMgrDesc &listOfRevokedPrivileges)
+  const PrivMgrDesc &revokedPrivs)
 {
   // Go through the list of table privileges and generate SQL_QIKEYs
-#if 0
-  // Only need to generate keys for SELECT, INSERT, UPDATE, and DELETE
   std::vector<ComSecurityKey *> keyList;
-  PrivMgrCoreDesc privs = listOfRevokedPrivileges.getTablePrivs();
-  for ( size_t i = 0; i < NBR_OF_PRIVS; i++ )
+  int32_t roleID = (ComUser::isPublicUserID(granteeID)) ? PUBLIC_USER : NA_UserIdDefault;
+  const PrivMgrCoreDesc &privs = revokedPrivs.getTablePrivs();
+  PrivStatus privStatus = buildSecurityKeys(granteeID,
+                                            roleID,
+                                            revokedPrivs.getTablePrivs(),
+                                            keyList);
+  if (privStatus != STATUS_GOOD)
   {
-    PrivType pType = PrivType(i);
-    if (pType == SELECT_PRIV || pType == INSERT_PRIV || 
-        pType == UPDATE_PRIV || pType == DELETE_PRIV)
+    for(size_t k = 0; k < keyList.size(); k++)
+     delete keyList[k]; 
+    keyList.clear();
+    return privStatus;
+  }
+
+  for (int i = 0; i < revokedPrivs.getColumnPrivs().entries(); i++)
+  {
+    const NAList<PrivMgrCoreDesc> &columnPrivs = revokedPrivs.getColumnPrivs();
+    privStatus = buildSecurityKeys(granteeID,
+                                   roleID,
+                                   columnPrivs[i],
+                                   keyList);
+    if (privStatus != STATUS_GOOD)
     {
-      if (privs.getPriv(pType))
-      {
-        ComSecurityKey *key = new ComSecurityKey(granteeID, 
-                                                 objectUID_,
-                                                 pType, 
-                                                 ComSecurityKey::OBJECT_IS_OBJECT);
-        if (key->isValid())
-          keyList.push_back(key);
-        else
-        {
-           // Probably should report a different error.  Is an error possible?
-          *pDiags_ << DgSqlCode (-CAT_NOT_AUTHORIZED);
-          return STATUS_ERROR;
-        }
-      }
+      for(size_t k = 0; k < keyList.size(); k++)
+       delete keyList[k]; 
+      keyList.clear();
+      return privStatus;
     }
   }
-#endif
-  std::vector<ComSecurityKey *> keyList;
-  PrivMgrCoreDesc privs = listOfRevokedPrivileges.getTablePrivs();
-  PrivStatus privStatus = buildSecurityKeys(granteeID,privs,keyList);
-  if (privStatus != STATUS_GOOD)
-     return privStatus;
-  // TDB: add column privileges
   
   // Create an array of SQL_QIKEYs
   int32_t numKeys = keyList.size();
@@ -4216,10 +4129,7 @@ PrivStatus PrivMgrPrivileges::getPrivTextForObject(
 // *                                                                       
 // *  <objectUID> identifies the object
 // *  <userID> identifies the user
-// *  <userPrivs> the list of privileges is returned
-// *  <grantablePrivs> the list of grantable privileges is returned
-// *  <colPrivsList> the list of column-level privileges is returned
-// *  <colGrantableList> the list of grantable column-level privileges is returned
+// *  <privsOfTheUser> the list of privileges is returned
 // *                                                                     
 // * Returns: PrivStatus                                               
 // *                                                                  
@@ -4231,10 +4141,7 @@ PrivStatus PrivMgrPrivileges::getPrivsOnObjectForUser(
   const int64_t objectUID,
   ComObjectType objectType,
   const int32_t userID,
-  PrivObjectBitmap &userPrivs,
-  PrivObjectBitmap &grantablePrivs,
-  PrivColList & colPrivsList,
-  PrivColList & colGrantableList,
+  PrivMgrDesc &privsOfTheUser,
   std::vector <ComSecurityKey *>* secKeySet)
 {
   PrivStatus retcode = STATUS_GOOD;
@@ -4253,41 +4160,19 @@ PrivStatus PrivMgrPrivileges::getPrivsOnObjectForUser(
   // generate the list of column-level privileges granted to the object and store in class
   if (generateColumnRowList() == STATUS_ERROR)
     return STATUS_ERROR;
+  
+  // generate the list of roles for the user
+  std::vector<int32_t> roleIDs;
+  if (getRoleIDsForUserID(userID,roleIDs) == STATUS_ERROR)
+    return STATUS_ERROR;
 
-  objectUID_ = objectUID;
-  PrivMgrDesc privsOfTheUser(userID);
+  // generate the list of privileges for the user
+  privsOfTheUser.setGrantee(userID);
   bool hasManagePrivileges = false;
-  std::vector<int32_t> roleIDs;
   
-  retcode = getRoleIDsForUserID(userID,roleIDs);
-  if (retcode == STATUS_ERROR)
-    return retcode;
-
   retcode = getUserPrivs(objectType, userID, roleIDs, privsOfTheUser, 
                          hasManagePrivileges, secKeySet);
-  if (retcode != STATUS_GOOD)
-    return retcode;
- 
-  if (hasManagePrivileges && hasAllDMLPrivs(objectType,privsOfTheUser.getTablePrivs().getPrivBitmap()))
-  {
-    userPrivs = privsOfTheUser.getTablePrivs().getPrivBitmap();
-    grantablePrivs = userPrivs;
-    return STATUS_GOOD; 
-  }
-    
-  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;
 }
 
@@ -4406,7 +4291,7 @@ PrivStatus PrivMgrPrivileges::getUserPrivs(
 
    summarizedPrivs = temp;
 
-   // TBD - set all column granted if the table level privilege is set
+
   return retcode;
 }
 
@@ -4443,6 +4328,7 @@ PrivStatus PrivMgrPrivileges::getPrivsFromAllGrantors(
 {
   PrivStatus retcode = STATUS_GOOD;
   hasManagePrivileges = false;
+  bool hasPublicGrantee = false;
   
   // Check to see if the granteeID is the system user
   // if so, the system user has all privileges.  Set up appropriately
@@ -4482,15 +4368,20 @@ PrivStatus PrivMgrPrivileges::getPrivsFromAllGrantors(
     {
       ObjectPrivsMDRow &row = static_cast<ObjectPrivsMDRow &> (*rowList[i]);
     
-      if (secKeySet != NULL)
+      if (ComUser::isPublicUserID(row.granteeID_))
+        hasPublicGrantee = true;
+
+      PrivMgrCoreDesc temp (row.privsBitmap_, row.grantableBitmap_);
+      if (secKeySet)
       {
-        PrivMgrCoreDesc privs(row.privsBitmap_,0);
-        retcode = buildSecurityKeys(row.granteeID_,privs,*secKeySet);
-        if (retcode != STATUS_GOOD)
-          return retcode;    
+        retcode = buildSecurityKeys(granteeID,
+                                    row.granteeID_,
+                                    temp,
+                                    *secKeySet);
+        if (retcode == STATUS_ERROR)
+          return retcode;
       }
 
-      PrivMgrCoreDesc temp (row.privsBitmap_, row.grantableBitmap_);
       coreTablePrivs.unionOfPrivs(temp);
     }
   
@@ -4516,26 +4407,31 @@ PrivStatus PrivMgrPrivileges::getPrivsFromAllGrantors(
   {
     ColumnPrivsMDRow &row = static_cast<ColumnPrivsMDRow &> (*rowList[i]);
 
+    if (ComUser::isPublicUserID(row.granteeID_))
+      hasPublicGrantee = true;
+
+
     // See if the ordinal has already been specified
     PrivMgrCoreDesc temp (row.privsBitmap_, row.grantableBitmap_, row.columnOrdinal_);
+    if (secKeySet)
+    {
+      retcode = buildSecurityKeys(granteeID,
+                                  row.granteeID_,
+                                  temp,
+                                  *secKeySet);
+      if (retcode == STATUS_ERROR)
+        return retcode;
+    }
+
     PrivMgrCoreDesc *coreColumnPriv = findColumnEntry(coreColumnPrivs, row.columnOrdinal_);
     if (coreColumnPriv)
       coreColumnPriv->unionOfPrivs(temp);
     else
       coreColumnPrivs.insert(temp);
-    
-    // set up security keys, if required
-    if (secKeySet != NULL)
-    {
-      PrivColList privColList;
-      privColList[row.columnOrdinal_] = row.privsBitmap_;
-      retcode = buildColumnSecurityKeys(objectUID_,privColList, row.granteeID_,*secKeySet);
-      if (retcode != STATUS_GOOD)
-        return retcode;
-    }
   } 
 
   summarizedPrivs.setColumnPrivs(coreColumnPrivs);
+  summarizedPrivs.setHasPublicPriv(hasPublicGrantee);
 
   return STATUS_GOOD;
 }
@@ -4572,26 +4468,6 @@ PrivStatus PrivMgrPrivileges::getRowsForGrantee(
 {
   PrivStatus retcode = STATUS_GOOD;
 
-#if 0
-  if (isObjectTable)
-  {
-    if (objectRowList_.size() == 0)
-    {
-      PRIVMGR_INTERNAL_ERROR("privilege list for object has not been created");
-      return STATUS_ERROR;
-    }
-  }
-
-  else // isColumnTable
-  {
-    if (columnRowList_.size() == 0)
-    {
-      PRIVMGR_INTERNAL_ERROR("privilege list for columns have not been created");
-      return STATUS_ERROR;
-    }
-  }
-#endif
-
   // create the list of row pointers 
   std::vector<int32_t> authIDs = roleIDs;
   authIDs.push_back(granteeID);
@@ -4628,16 +4504,6 @@ PrivStatus PrivMgrPrivileges::getRowsForGrantee(
        rowList.push_back(privRowList[i]);
   }
   
-  if (rowList.size() > 0 && secKeySet != NULL)
-  {
-    retcode = buildUserSecurityKeys(roleIDs,granteeID,*secKeySet);   
-    if (retcode == STATUS_ERROR)
-    {
-      PRIVMGR_INTERNAL_ERROR("Unable to build user security key");
-      return STATUS_ERROR;   
-    }
-  }
-
   return STATUS_GOOD;
 }
 
@@ -5432,132 +5298,6 @@ void static buildGrantText(
 }
 //*************************** End of buildGrantText ****************************
 
-// *****************************************************************************
-// * Function: buildColumnSecurityKeys                                         *
-// *                                                                           *
-// *    Builds security keys for privileges granted on one or more columns of  *
-// * an object.                                                                *
-// *                                                                           *
-// *                                                                           *
-// *****************************************************************************
-// *                                                                           *
-// *  Parameters:                                                              *
-// *                                                                           *
-// *                                                                           *
-// *  <objectUID>                  const int64_t                      In       *
-// *    is the unique ID of the object.                                        *
-// *                                                                           *
-// *  <roleIDs>                    const PrivColList & colPrivsList   In       *
-// *    is a list of the column privileges granted on this object to the       *
-// * specified grantee.                                                        *
-// *                                                                           *
-// *  <granteeID>                  const int32_t                      In       *
-// *    is the ID of the user granted the column privilege(s).                 *
-// *                                                                           *
-// *  <secKeySet>                  std::vector <ComSecurityKey *> &   Out      *
-// *    passes back a list of SUBJECT_IS_OBJECT security keys for each of the  *
-// *  privileges granted on the object to the grantee.                         *
-// *                                                                           *
-// *****************************************************************************
-// *                                                                           *
-// * Returns: PrivStatus                                                       *
-// *                                                                           *
-// * STATUS_GOOD: Security keys were built                                     *
-// *           *: Security keys were not built, see diags.                     *
-// *                                                                           *
-// *****************************************************************************
-static PrivStatus buildColumnSecurityKeys(
-   const int64_t objectUID,
-   const PrivColList & colPrivsList,
-   const int32_t granteeID, 
-   std::vector<ComSecurityKey *> & secKeySet)
-  
-{
-
-// *****************************************************************************
-// *                                                                           *
-// *   Optimizer currently does not support OBJECT_IS_COLUMN, so we combine    *
-// * all column-level privileges to one priv bitmap and create a key for       *
-// * each priv type the grantee has on the object.                             *
-// *                                                                           *
-// *****************************************************************************
-
-PrivColumnBitmap privBitmap;
-
-   for (PrivColIterator columnIterator = colPrivsList.begin();
-        columnIterator != colPrivsList.end(); ++columnIterator)
-      privBitmap |= columnIterator->second;
-      
-   for (size_t i = FIRST_DML_COL_PRIV; i <= LAST_DML_COL_PRIV; i++ )
-   {
-      if (!privBitmap.test(PrivType(i)))
-         continue;
-   
-      ComSecurityKey *key = new ComSecurityKey(granteeID, 
-                                               objectUID,
-                                               PrivType(i),
-                                               ComSecurityKey::OBJECT_IS_OBJECT);
-      if (!key->isValid())
-         return STATUS_ERROR;
-         
-      secKeySet.push_back(key);
-   }
-   
-   return STATUS_GOOD;
-   
-}
-//********************** End of buildColumnSecurityKeys ************************
-
-// *****************************************************************************
-// * Function: buildUserSecurityKeys                                           *
-// *                                                                           *
-// *    Builds security keys for a user and the roles granted to the user.     *
-// *                                                                           *
-// *****************************************************************************
-// *                                                                           *
-// *  Parameters:                                                              *
-// *                                                                           *
-// *                                                                           *
-// *  <roleIDs>                    const std::vector<int32_t> &       In       *
-// *    is a reference to a vector of roleIDs that have been granted to the    *
-// *  user.                                                                    *
-// *                                                                           *
-// *                                                                           *
-// *  <userID>                     const int32_t                      In       *
-// *    is the ID of the user granted the role(s).                             *
-// *                                                                           *
-// *  <secKeySet>                  std::vector <ComSecurityKey *> &   Out      *
-// *    passes back a list of SUBJECT_IS_USER security keys for each of the    *
-// *  roles granted to the user.                                               *
-// *                                                                           *
-// *****************************************************************************
-// *                                                                           *
-// * Returns: PrivStatus                                                       *
-// *                                                                           *
-// * STATUS_GOOD: Security keys were built                                     *
-// *           *: Security keys were not built, see diags.                     *
-// *                                                                           *
-// *****************************************************************************
-static PrivStatus buildUserSecurityKeys(
-   const std::vector<int32_t> & roleIDs,
-   const int32_t userID, 
-   std::vector<ComSecurityKey *> & secKeySet)
-  
-{
-
-   for ( size_t i = 0; i < roleIDs.size(); i++ )
-   {
-      ComSecurityKey *key = new ComSecurityKey(userID,roleIDs[i],
-                                               ComSecurityKey::SUBJECT_IS_USER);
-      if (key->isValid())
-         secKeySet.push_back(key);
-      else
-         return STATUS_ERROR;
-   }
-   
-   return STATUS_GOOD;
-}
-//*********************** End of buildUserSecurityKeys *************************
 
 // *****************************************************************************
 // * Function: closeColumnList                                                 *
@@ -5658,77 +5398,6 @@ static PrivMgrCoreDesc * findColumnEntry(
 //************************** End of findColumnEntry ****************************
 
 
-
-// *****************************************************************************
-// * Function: getColRowsForGrantee                                            *
-// *                                                                           *
-// *    Returns the list of column privileges granted for the object that have *
-// *    been granted to the granteeID.                                         *
-// *                                                                           *
-// *****************************************************************************
-// *                                                                           *
-// *  Parameters:                                                              *
-// *                                                                           *
-// *  <columnRowList>              std::vector<PrivMgrMDRow *> &      In       *
-// *    is the list of column privileges granted on the object.                *
-// *                                                                           *
-// *  <granteeID>                  const int32_t                      In       *
-// *    is the authID granted the privileges.                                  *
-// *                                                                           *
-// *  <roleIDs>                    const std::vector<int32_t> &       In       *
-// *    is a list of roles granted to the grantee.                             *
-// *                                                                           *
-// *  <rowList>                    std::vector<PrivMgrMDRow *> &      Out      *
-// *    passes back a list rows representing the privileges granted.           *
-// *                                                                           *
-// *  <secKeySet>                  std::vector <ComSecurityKey *> &   Out      *
-// *    passes back a list of SUBJECT_IS_USER security keys for each of the    *
-// *  roles granted to the grantee.                                            *
-// *                                                                           *
-// *****************************************************************************
-// * Returns: PrivStatus                                                       * 
-// *                                                                           *  
-// * STATUS_GOOD: Row returned.                                                *
-// * STATUS_NOTFOUND: No matching rows were found                              *
-// *****************************************************************************
-static PrivStatus getColRowsForGrantee(
-   const std::vector <PrivMgrMDRow *> &columnRowList,
-   const int32_t granteeID,
-   const std::vector<int32_t> & roleIDs,
-   std::vector<ColumnPrivsMDRow> & rowList,
-   std::vector <ComSecurityKey *>* secKeySet)
-    
-{
-
-  std::vector<int32_t> authIDs = roleIDs;
-  authIDs.push_back(granteeID);
-  authIDs.push_back(PUBLIC_USER);
-  std::vector<int32_t>::iterator it;
-
-  std::vector<PrivMgrMDRow *> privRowList;
-
-   // returns the list of rows for the grantee, roles that the grantee has been
-   // granted, and PUBLIC
-   for (size_t i = 0; i < columnRowList.size(); i++)
-   {
-      ColumnPrivsMDRow &row = static_cast<ColumnPrivsMDRow &> (*columnRowList[i]);
-      it = std::find(authIDs.begin(), authIDs.end(), row.granteeID_);
-      if (it != authIDs.end())
-         rowList.push_back(row);
-   }
-
-   if (rowList.empty())
-     return STATUS_NOTFOUND;
-
-   if (secKeySet != NULL)
-      return buildUserSecurityKeys(roleIDs,granteeID,*secKeySet);   
-
-   return STATUS_GOOD;
-   
-}
-//*********************** End of getColRowsForGrantee **************************
-
-
 // *****************************************************************************
 // * Function: getColRowsForGranteeGrantor                                     *
 // *                                                                           *
@@ -5869,6 +5538,7 @@ static bool isDelimited( const std::string &strToScan)
 //*********************** End of isDelimited ***********************************
    
 
+
 // *****************************************************************************
 // method: reportPrivWarnings
 //
@@ -5940,8 +5610,6 @@ void PrivMgrPrivileges::reportPrivWarnings(
   }
 }
 
-
-
 // *****************************************************************************
 //    ObjectPrivsMDRow methods
 // *****************************************************************************

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/3b437720/core/sql/sqlcomp/PrivMgrPrivileges.h
----------------------------------------------------------------------
diff --git a/core/sql/sqlcomp/PrivMgrPrivileges.h b/core/sql/sqlcomp/PrivMgrPrivileges.h
index a3a132c..285f6e1 100644
--- a/core/sql/sqlcomp/PrivMgrPrivileges.h
+++ b/core/sql/sqlcomp/PrivMgrPrivileges.h
@@ -112,20 +112,10 @@ public:
   // -------------------------------------------------------------------
    PrivStatus buildSecurityKeys(
       const int32_t granteeID, 
+      const int32_t roleID,
       const PrivMgrCoreDesc &privs,
       std::vector <ComSecurityKey *> & secKeySet);
       
-   PrivStatus getPrivsOnObject (
-      const ComObjectType objectType,
-      std::vector<PrivMgrDesc> & privDescs );
- 
-   PrivStatus getColPrivsForUser(
-      const int32_t granteeID,
-      const std::vector<int32_t> & roleIDs,
-      PrivColList & colPrivsList,
-      PrivColList & colGrantableList,
-      std::vector <ComSecurityKey *>* secKeySet);
-       
    PrivStatus getGrantorDetailsForObject(
       const bool isGrantedBySpecified,
       const std::string grantedByName,
@@ -138,6 +128,17 @@ public:
       const std::string & orderByClause,
       std::vector<PrivObjectBitmap> & privBitmaps);
       
+   PrivStatus getPrivsOnObject (
+      const ComObjectType objectType,
+      std::vector<PrivMgrDesc> & privDescs );
+ 
+   PrivStatus getPrivsOnObjectForUser(
+      const int64_t objectUID,
+      ComObjectType objectType,
+      const int32_t userID,
+      PrivMgrDesc &privsForTheUser,
+      std::vector <ComSecurityKey *>* secKeySet);
+
    PrivStatus getPrivRowsForObject(
       const int64_t objectUID,
       std::vector<ObjectPrivsRow> & objectPrivsRows);
@@ -146,16 +147,6 @@ public:
       const PrivMgrObjectInfo &objectInfo,
       std::string &privilegeText);
 
-   PrivStatus getPrivsOnObjectForUser(
-      const int64_t objectUID,
-      ComObjectType objectType,
-      const int32_t userID,
-      PrivObjectBitmap &userPrivs,
-      PrivObjectBitmap &grantablePrivs,
-      PrivColList & colPrivsList,
-      PrivColList & colGrantableList,
-      std::vector <ComSecurityKey *>* secKeySet);
-
    PrivStatus givePrivForObjects(
       const int32_t currentOwnerID,
       const int32_t newOwnerID,
@@ -334,10 +325,11 @@ private:
     const int64_t objectUID,
     std::vector<PrivMgrMDRow *> &columnRows);
 
-  PrivStatus getDistinctUserIDs(
+  PrivStatus getDistinctIDs(
     const std::vector <PrivMgrMDRow *> &objectRowList,
     const std::vector <PrivMgrMDRow *> &columnRowList,
-    std::vector<int32_t> &userIDs);
+    std::vector<int32_t> &userIDs,
+    std::vector<int32_t> &roleIDs);
 
   PrivStatus getGrantedPrivs(
     const int32_t granteeID,

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/3b437720/core/sql/sqlcomp/PrivMgrRoles.cpp
----------------------------------------------------------------------
diff --git a/core/sql/sqlcomp/PrivMgrRoles.cpp b/core/sql/sqlcomp/PrivMgrRoles.cpp
index 12861fd..4419c85 100644
--- a/core/sql/sqlcomp/PrivMgrRoles.cpp
+++ b/core/sql/sqlcomp/PrivMgrRoles.cpp
@@ -1664,7 +1664,7 @@ PrivStatus PrivMgrRoles::revokeRole(
    const std::vector<int32_t> & grantorIDs,
    const bool isGOFSpecified,
    const int32_t newGrantDepth,
-   PrivDropBehavior dropBehavior) 
+   PrivDropBehavior dropBehavior)
   
 {
 
@@ -1676,7 +1676,7 @@ PrivStatus PrivMgrRoles::revokeRole(
       return STATUS_ERROR;
    }
    
-PrivStatus privStatus = STATUS_GOOD;
+   PrivStatus privStatus = STATUS_GOOD;
 
    for (size_t r = 0; r < roleIDs.size(); r++)
    {
@@ -1758,10 +1758,10 @@ PrivStatus privStatus = STATUS_GOOD;
       }
    }
 
-// All checks completed, all dependent grants revoked, and when CASCADE is
-// supported, all dependent objects dropped. It's now safe to revoke the roles.
+   // All checks completed, all dependent grants revoked, and when CASCADE is
+   // supported, all dependent objects dropped. It's now safe to revoke the roles.
 
-std::string setClause("SET GRANT_DEPTH = ");
+   std::string setClause("SET GRANT_DEPTH = ");
 
    if (isGOFSpecified)
    {
@@ -1771,9 +1771,9 @@ std::string setClause("SET GRANT_DEPTH = ");
       setClause += grantDepthString;
    }
    
-int32_t numKeys = roleIDs.size() * granteeIDs.size();
-SQL_QIKEY siKeyList[numKeys];
-size_t siIndex = 0;
+   int32_t numKeys = roleIDs.size() * granteeIDs.size();
+   SQL_QIKEY siKeyList[numKeys];
+   size_t siIndex = 0;
 
    for (size_t r2 = 0; r2 < roleIDs.size(); r2++)
    {
@@ -1808,9 +1808,9 @@ size_t siIndex = 0;
             return STATUS_ERROR;
          }
          
-         ComSecurityKey secKey(granteeIDs[g2],roleIDs[r2], 
+         ComSecurityKey secKey(granteeIDs[g2],roleIDs[r2],
                                ComSecurityKey::SUBJECT_IS_USER);
-                               
+
          siKeyList[siIndex].revokeKey.subject = secKey.getSubjectHashValue();
          siKeyList[siIndex].revokeKey.object = secKey.getObjectHashValue();
          std::string actionString;
@@ -1820,7 +1820,7 @@ size_t siIndex = 0;
       }
    }  
     
-// Call the CLI to send details to RMS
+   // Call the CLI to send details to RMS
    SQL_EXEC_SetSecInvalidKeys(siIndex,siKeyList);
       
    return STATUS_GOOD;

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/3b437720/core/sql/sqlcomp/QCache.cpp
----------------------------------------------------------------------
diff --git a/core/sql/sqlcomp/QCache.cpp b/core/sql/sqlcomp/QCache.cpp
index 2478922..90a1593 100644
--- a/core/sql/sqlcomp/QCache.cpp
+++ b/core/sql/sqlcomp/QCache.cpp
@@ -2643,15 +2643,18 @@ void QCache::free_entries_with_QI_keys( Int32 pNumKeys, SQL_QIKEY * pSiKeyEntry
         {
           // this key passed in as a param is for REVOKE so look
           // thru the plan's revoke keys.
-          for ( CollIndex ii = 0; ii < numPlanSecKeys &&
-                                  !found; ii ++ )
+          for ( CollIndex ii = 0; ii < numPlanSecKeys && !found; ii ++ )
           {
-            if ( ( (pSiKeyEntry[jj]).revokeKey.subject == 
-                      planSet[ii].getSubjectHashValue() ) &&
-                 ( (pSiKeyEntry[jj]).revokeKey.object ==
-                      planSet[ii].getObjectHashValue() ) &&
-                 ( siKeyType == planSet[ii].getSecurityKeyType() ) )
-            found = TRUE;
+            // If user ID's (subjects match)
+            if ( (pSiKeyEntry[jj]).revokeKey.subject ==
+                    planSet[ii].getSubjectHashValue() ) 
+            {
+               // Remove all plans for user
+               if ( ( pSiKeyEntry[jj]).revokeKey.object ==
+                       planSet[ii].getObjectHashValue() &&
+                    ( siKeyType == planSet[ii].getSecurityKeyType() ) )
+              found = TRUE;
+            }
           }
         }
      } // end loop thru the keys passed as params


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

Posted by rm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/3b437720/core/sql/optimizer/NATable.cpp
----------------------------------------------------------------------
diff --git a/core/sql/optimizer/NATable.cpp b/core/sql/optimizer/NATable.cpp
index d8d4b2e..24cfbf3 100644
--- a/core/sql/optimizer/NATable.cpp
+++ b/core/sql/optimizer/NATable.cpp
@@ -84,6 +84,7 @@
 #include "ComSmallDefs.h"
 #include "CmpMain.h"
 #include "TrafDDLdesc.h"
+#include "CmpSeabaseDDL.h"
 
 #define MAX_NODE_NAME 9
 #define MAX_PRECISION_ALLOWED  18
@@ -5319,17 +5320,17 @@ NABoolean createNAFileSets(TrafDesc * table_desc       /*IN*/,
   if (table_desc->tableDesc()->all_col_fams)
     {
       // Space delimited col families.
-      
-      string buf; // Have a buffer string
-      stringstream ss(table_desc->tableDesc()->all_col_fams); // Insert the string into a stream
-      
-      while (ss >> buf)
-        {
-          allColFams_.insert(buf.c_str());
-        }
+
+	    string buf; // Have a buffer string
+	    stringstream ss(table_desc->tableDesc()->all_col_fams); // Insert the string into a stream
+
+	    while (ss >> buf)
+	    {
+		    allColFams_.insert(buf.c_str());
+	    }
     }
   else
-    allColFams_.insert(defaultColFam_);
+	  allColFams_.insert(defaultColFam_);
 
   TrafDesc * files_desc = table_desc->tableDesc()->files_desc;
 
@@ -5337,132 +5338,132 @@ NABoolean createNAFileSets(TrafDesc * table_desc       /*IN*/,
   // Therefore, only setup the partnsDesc_ if this is a partitionable object
   if (files_desc)
   {
-     if (files_desc->filesDesc()->partns_desc)
-       partnsDesc_ = files_desc->filesDesc()->partns_desc;
+	  if (files_desc->filesDesc()->partns_desc)
+		  partnsDesc_ = files_desc->filesDesc()->partns_desc;
   }
   else
-     partnsDesc_ = NULL;
+	  partnsDesc_ = NULL;
 
   //
   // Insert a NAColumn in the colArray_ for this NATable for each
   // columns_desc from the ARK SMD. Returns TRUE if error creating NAColumns.
   //
   if (createNAColumns(table_desc->tableDesc()->columns_desc,
-		      this,
-		      colArray_ /*OUT*/,
-		      heap_))
-    //coverity[leaked_storage]
-    return; // colcount_ == 0 indicates an error
+			  this,
+			  colArray_ /*OUT*/,
+			  heap_))
+	  //coverity[leaked_storage]
+	  return; // colcount_ == 0 indicates an error
 
   //
   // Add view information, if this is a view
   //
   TrafDesc *view_desc = table_desc->tableDesc()->views_desc;
   if (view_desc)
-    {
-      viewText_ = new (heap_) char[strlen(view_desc->viewDesc()->viewtext) + 2];
-      strcpy(viewText_, view_desc->viewDesc()->viewtext);
-      strcat(viewText_, ";");
-
-      viewTextCharSet_ = (CharInfo::CharSet)view_desc->viewDesc()->viewtextcharset;
-
-      viewCheck_    = NULL; //initialize
-      if(view_desc->viewDesc()->viewchecktext){
-        UInt32 viewCheckLength = str_len(view_desc->viewDesc()->viewchecktext)+1;
-        viewCheck_ = new (heap_) char[ viewCheckLength];
-        memcpy(viewCheck_, view_desc->viewDesc()->viewchecktext,
-               viewCheckLength);
-      }
+  {
+	  viewText_ = new (heap_) char[strlen(view_desc->viewDesc()->viewtext) + 2];
+	  strcpy(viewText_, view_desc->viewDesc()->viewtext);
+	  strcat(viewText_, ";");
+
+	  viewTextCharSet_ = (CharInfo::CharSet)view_desc->viewDesc()->viewtextcharset;
+
+	  viewCheck_    = NULL; //initialize
+	  if(view_desc->viewDesc()->viewchecktext){
+		  UInt32 viewCheckLength = str_len(view_desc->viewDesc()->viewchecktext)+1;
+		  viewCheck_ = new (heap_) char[ viewCheckLength];
+		  memcpy(viewCheck_, view_desc->viewDesc()->viewchecktext,
+				  viewCheckLength);
+	  }
 
-      viewColUsages_ = NULL;
-      if(view_desc->viewDesc()->viewcolusages){
-        viewColUsages_ = new (heap_) NAList<ComViewColUsage *>; //initialize empty list
-        char * beginStr (view_desc->viewDesc()->viewcolusages);
-        char * endStr = strchr(beginStr, ';');
-        while (endStr != NULL) {
-          ComViewColUsage *colUsage = new (heap_) ComViewColUsage;
-          NAString currentUsage(beginStr, endStr - beginStr + 1); 
-          colUsage->unpackUsage (currentUsage.data());
-          viewColUsages_->insert(colUsage);
-          beginStr = endStr+1;
-          endStr = strchr(beginStr, ';');
-        }
-      }
+	  viewColUsages_ = NULL;
+	  if(view_desc->viewDesc()->viewcolusages){
+		  viewColUsages_ = new (heap_) NAList<ComViewColUsage *>; //initialize empty list
+		  char * beginStr (view_desc->viewDesc()->viewcolusages);
+		  char * endStr = strchr(beginStr, ';');
+		  while (endStr != NULL) {
+			  ComViewColUsage *colUsage = new (heap_) ComViewColUsage;
+			  NAString currentUsage(beginStr, endStr - beginStr + 1); 
+			  colUsage->unpackUsage (currentUsage.data());
+			  viewColUsages_->insert(colUsage);
+			  beginStr = endStr+1;
+			  endStr = strchr(beginStr, ';');
+		  }
+	  }
 
-      setUpdatable(view_desc->viewDesc()->isUpdatable());
-      setInsertable(view_desc->viewDesc()->isInsertable());
+	  setUpdatable(view_desc->viewDesc()->isUpdatable());
+	  setInsertable(view_desc->viewDesc()->isInsertable());
 
-      //
-      // The updatable flag is false for an MP view only if it is NOT a
-      // protection view. Therefore updatable == FALSE iff it is a
-      // shorthand view. See ReadTableDef.cpp, l. 3379.
-      //
+	  //
+	  // The updatable flag is false for an MP view only if it is NOT a
+	  // protection view. Therefore updatable == FALSE iff it is a
+	  // shorthand view. See ReadTableDef.cpp, l. 3379.
+	  //
 
-      viewFileName_ = NULL;
-      CMPASSERT(view_desc->viewDesc()->viewfilename);
-      UInt32 viewFileNameLength = str_len(view_desc->viewDesc()->viewfilename) + 1;
-      viewFileName_ = new (heap_) char[viewFileNameLength];
-      memcpy(viewFileName_, view_desc->viewDesc()->viewfilename,
-	     viewFileNameLength);
-    }
+	  viewFileName_ = NULL;
+	  CMPASSERT(view_desc->viewDesc()->viewfilename);
+	  UInt32 viewFileNameLength = str_len(view_desc->viewDesc()->viewfilename) + 1;
+	  viewFileName_ = new (heap_) char[viewFileNameLength];
+	  memcpy(viewFileName_, view_desc->viewDesc()->viewfilename,
+			  viewFileNameLength);
+  }
   else
-    {
-      //keep track of memory used by NAFileSets
-      Lng32 preCreateNAFileSetsMemSize = heap_->getAllocSize();
+  {
+	  //keep track of memory used by NAFileSets
+	  Lng32 preCreateNAFileSetsMemSize = heap_->getAllocSize();
 
-      //
-      // Process indexes and vertical partitions for this table.
-      //
-      if (createNAFileSets(table_desc       /*IN*/,
-                           this             /*IN*/,
-                           colArray_        /*IN*/,
-                           indexes_         /*OUT*/,
-                           vertParts_       /*OUT*/,
-                           clusteringIndex_ /*OUT*/,
-			   tableIdList_     /*OUT*/,
-                           heap_,
-                           bindWA,
-                           newColumns_,     /*OUT*/
-			   maxIndexLevelsPtr)) {
-        return; // colcount_ == 0 indicates an error
-      }
+	  //
+	  // Process indexes and vertical partitions for this table.
+	  //
+	  if (createNAFileSets(table_desc       /*IN*/,
+				  this             /*IN*/,
+				  colArray_        /*IN*/,
+				  indexes_         /*OUT*/,
+				  vertParts_       /*OUT*/,
+				  clusteringIndex_ /*OUT*/,
+				  tableIdList_     /*OUT*/,
+				  heap_,
+				  bindWA,
+				  newColumns_,     /*OUT*/
+				  maxIndexLevelsPtr)) {
+		  return; // colcount_ == 0 indicates an error
+	  }
 
-      // Add constraint info.
-      //
-      // This call to createConstraintInfo, calls the parser on
-      // the constraint name
-      //
-      
-      NABoolean  errorOccurred =
-        createConstraintInfo(table_desc        /*IN*/,
-                             getTableName()    /*IN*/,
-                             getNAColumnArray()/*IN (some columns updated)*/,
-                             checkConstraints_ /*OUT*/,
-                             uniqueConstraints_/*OUT*/,
-                             refConstraints_   /*OUT*/,
-                             heap_,
-                             bindWA);
-      
-      if (errorOccurred) {
-        // return before setting colcount_, indicating that there
-        // was an error in constructing this NATable.
-        //
-        return;
-      }
-      
-      //
-      // FetchHistograms call used to be here -- moved to getStatistics().
-      //
-    }
-  
-    // change partFunc for base table if PARTITION clause has been used
-    // to limit the number of partitions that will be accessed.
-    if ((qualifiedName_.isPartitionNameSpecified()) ||
-	(qualifiedName_.isPartitionRangeSpecified())) {
-      if (filterUnusedPartitions(corrName.getPartnClause())) {
-	return ;
-      }
-    }
+	  // Add constraint info.
+	  //
+	  // This call to createConstraintInfo, calls the parser on
+	  // the constraint name
+	  //
+
+	  NABoolean  errorOccurred =
+		  createConstraintInfo(table_desc        /*IN*/,
+				  getTableName()    /*IN*/,
+				  getNAColumnArray()/*IN (some columns updated)*/,
+				  checkConstraints_ /*OUT*/,
+				  uniqueConstraints_/*OUT*/,
+				  refConstraints_   /*OUT*/,
+				  heap_,
+				  bindWA);
+
+	  if (errorOccurred) {
+		  // return before setting colcount_, indicating that there
+		  // was an error in constructing this NATable.
+		  //
+		  return;
+	  }
+
+	  //
+	  // FetchHistograms call used to be here -- moved to getStatistics().
+	  //
+  }
+
+  // change partFunc for base table if PARTITION clause has been used
+  // to limit the number of partitions that will be accessed.
+  if ((qualifiedName_.isPartitionNameSpecified()) ||
+		  (qualifiedName_.isPartitionRangeSpecified())) {
+	  if (filterUnusedPartitions(corrName.getPartnClause())) {
+		  return ;
+	  }
+  }
 
   //
   // Set colcount_ after all possible errors (Binder uses nonzero colcount
@@ -5484,17 +5485,17 @@ NABoolean createNAFileSets(TrafDesc * table_desc       /*IN*/,
   mvAttributeBitmap_.initBitmap(table_desc->tableDesc()->mvAttributesBitmap);
 
   TrafDesc *mvs_desc = NULL; // using mvs not set or returned for traf tables
-// Memory Leak
+  // Memory Leak
   while (mvs_desc)
   {
-    TrafUsingMvDesc* mv = mvs_desc->usingMvDesc();
+	  TrafUsingMvDesc* mv = mvs_desc->usingMvDesc();
 
-    UsingMvInfo *usingMv = new(heap_)
-      UsingMvInfo(mv->mvName, mv->refreshType(), mv->rewriteEnabled,
-                    mv->isInitialized, heap_);
-    mvsUsingMe_.insert(usingMv);
+	  UsingMvInfo *usingMv = new(heap_)
+		  UsingMvInfo(mv->mvName, mv->refreshType(), mv->rewriteEnabled,
+				  mv->isInitialized, heap_);
+	  mvsUsingMe_.insert(usingMv);
 
-    mvs_desc = mvs_desc->next;
+	  mvs_desc = mvs_desc->next;
   }
 
   // ++MV
@@ -5510,18 +5511,18 @@ NABoolean createNAFileSets(TrafDesc * table_desc       /*IN*/,
 
   if (isAnMV_)
   {
-    switch(qualifiedName_.getSpecialType())
-    {
-    case ExtendedQualName::GHOST_TABLE:
-      qualifiedName_.setSpecialType(ExtendedQualName::GHOST_MV_TABLE);
-      break;
-    case ExtendedQualName::GHOST_MV_TABLE:
-      // Do not change it
-      break;
-    default:
-      qualifiedName_.setSpecialType(ExtendedQualName::MV_TABLE);
-      break;
-    }
+	  switch(qualifiedName_.getSpecialType())
+	  {
+		  case ExtendedQualName::GHOST_TABLE:
+			  qualifiedName_.setSpecialType(ExtendedQualName::GHOST_MV_TABLE);
+			  break;
+		  case ExtendedQualName::GHOST_MV_TABLE:
+			  // Do not change it
+			  break;
+		  default:
+			  qualifiedName_.setSpecialType(ExtendedQualName::MV_TABLE);
+			  break;
+	  }
   }
 
   // --MV
@@ -5529,508 +5530,510 @@ NABoolean createNAFileSets(TrafDesc * table_desc       /*IN*/,
   // Initialize the sequence generator fields
   TrafDesc *sequence_desc = table_desc->tableDesc()->sequence_generator_desc;
   if (sequence_desc != NULL) {
-    TrafSequenceGeneratorDesc *sg_desc = sequence_desc->sequenceGeneratorDesc();
-    
-    if (sg_desc != NULL)
-      {
-	sgAttributes_ = 
-	  new(heap_) SequenceGeneratorAttributes(
-						 sg_desc->startValue,
-						 sg_desc->increment,
-						 sg_desc->maxValue,
-						 sg_desc->minValue,
-						 sg_desc->sgType(),
-						 (ComSQLDataType)sg_desc->sqlDataType,
-						 (ComFSDataType)sg_desc->fsDataType,
-						 sg_desc->cycleOption,
-                                                 FALSE,
-						 sg_desc->objectUID,
-						 sg_desc->cache,
-						 sg_desc->nextValue,
-                                                 0,
-                                                 sg_desc->redefTime);
-      }
+	  TrafSequenceGeneratorDesc *sg_desc = sequence_desc->sequenceGeneratorDesc();
+
+	  if (sg_desc != NULL)
+	  {
+		  sgAttributes_ = 
+			  new(heap_) SequenceGeneratorAttributes(
+					  sg_desc->startValue,
+					  sg_desc->increment,
+					  sg_desc->maxValue,
+					  sg_desc->minValue,
+					  sg_desc->sgType(),
+					  (ComSQLDataType)sg_desc->sqlDataType,
+					  (ComFSDataType)sg_desc->fsDataType,
+					  sg_desc->cycleOption,
+					  FALSE,
+					  sg_desc->objectUID,
+					  sg_desc->cache,
+					  sg_desc->nextValue,
+					  0,
+					  sg_desc->redefTime);
+	  }
   }
 #ifndef NDEBUG
   if (getenv("NATABLE_DEBUG"))
-    {
-      cout << "NATable " << (void*)this << " "
-	   << qualifiedName_.getQualifiedNameObj().getQualifiedNameAsAnsiString() << " "
-	   << (Int32)qualifiedName_.getSpecialType() << endl;
-      colArray_.print();
-      }
-  #endif
-      //this guy is cacheable
+  {
+	  cout << "NATable " << (void*)this << " "
+		  << qualifiedName_.getQualifiedNameObj().getQualifiedNameAsAnsiString() << " "
+		  << (Int32)qualifiedName_.getSpecialType() << endl;
+	  colArray_.print();
+  }
+#endif
+  //this guy is cacheable
   if((qualifiedName_.isCacheable())&&
-     (NOT (isHbaseTable())) && 
-      //this object is not on the statement heap (i.e. it is being cached)
-     ((heap_ != CmpCommon::statementHeap())||
-      (OSIM_runningInCaptureMode())))
+		  (NOT (isHbaseTable())) && 
+		  //this object is not on the statement heap (i.e. it is being cached)
+		  ((heap_ != CmpCommon::statementHeap())||
+		   (OSIM_runningInCaptureMode())))
   {
-    char * nodeName = NULL;
-    char * catStr = NULL;
-    char * schemaStr = NULL;
-    char * fileStr = NULL;
-    short nodeNameLen = 0;
-    Int32 catStrLen = 0;
-    Int32 schemaStrLen = 0;
-    Int32 fileStrLen = 0;
+	  char * nodeName = NULL;
+	  char * catStr = NULL;
+	  char * schemaStr = NULL;
+	  char * fileStr = NULL;
+	  short nodeNameLen = 0;
+	  Int32 catStrLen = 0;
+	  Int32 schemaStrLen = 0;
+	  Int32 fileStrLen = 0;
 #ifdef NA_64BIT
-    // dg64 - match signature
-    int_32 primaryNodeNum=0;
+	  // dg64 - match signature
+	  int_32 primaryNodeNum=0;
 #else
-    Int32 primaryNodeNum=0;
+	  Int32 primaryNodeNum=0;
 #endif
-    short error = 0;
-
-    //clusteringIndex has physical filename that can be used to check
-    //if a catalog operation has been performed on a table.
-    //Views don't have clusteringIndex, so we get physical filename
-    //from the viewFileName_ datamember.
-    if(viewText_)
-    {
-      //view filename starts with node name
-      //filename is in format \<node_name>.$<volume>.<subvolume>.<file>
-      //catStr => <volume>
-      //schemaStr => <subvolume>
-      //fileStr => <file>
-      nodeName = viewFileName_;
-      catStr = nodeName;
-
-      //skip over node name
-      //measure node name length
-      //get to begining of volume name
-      //Measure length of node name
-      //skip over node name i.e. \MAYA, \AZTEC, etc
-      //and get to volume name
-      while((nodeName[nodeNameLen]!='.')&&
-            (nodeNameLen < 8)){
-	catStr++;
-        nodeNameLen++;
-      };
-
-      //skip over '.' and the '$' in volume name
-      catStr=&nodeName[nodeNameLen+2];
-      schemaStr=catStr;
-
-      //skip over the volume/catalog name
-      //while measuring catalog name length
-      while((catStr[catStrLen]!='.')&&
-            (catStrLen < 8))
-      {
-	schemaStr++;
-	catStrLen++;
-      }
-
-      //skip over the '.'
-      schemaStr++;
-      fileStr=schemaStr;
-
-      //skip over the subvolume/schema name
-      //while measuring schema name length
-      while((schemaStr[schemaStrLen]!='.')&&
-            (schemaStrLen < 8))
-      {
-	fileStr++;
-        schemaStrLen++;
-      }
-
-      //skip over the '.'
-      fileStr++;
-      fileStrLen = str_len(fileStr);
-
-      //figure out the node number for the node
-      //which has the primary partition.
-      primaryNodeNum=0;
+	  short error = 0;
 
-      if(!OSIM_runningSimulation())        
-          primaryNodeNum = gpClusterInfo->mapNodeNameToNodeNum(NAString(nodeName));
-    }
-    else{
-      //get qualified name of the clustering index which should
-      //be the actual physical file name of the table
-      const QualifiedName fileNameObj = getClusteringIndex()->
-        getRandomPartition();
-      const NAString fileName = fileNameObj.getObjectName();
-
-      //get schemaName object
-      const SchemaName schemaNameObj = fileNameObj.getSchemaName();
-      const NAString schemaName = schemaNameObj.getSchemaName();
-
-      //get catalogName object
-      //this contains a string in the form \<node_name>.$volume
-      const CatalogName catalogNameObj = fileNameObj.getCatalogName();
-      const NAString catalogName = catalogNameObj.getCatalogName();
-      nodeName = (char*) catalogName.data();
-      catStr = nodeName;
-
-      //Measure length of node name
-      //skip over node name i.e. \MAYA, \AZTEC, etc
-      //and get to volume name
-      while((nodeName[nodeNameLen]!='.')&&
-            (nodeNameLen < 8)){
-        catStr++;
-        nodeNameLen++;
-      };
-
-      //get volume/catalog name
-      //skip ".$"
-      catStr=&nodeName[nodeNameLen+2];
+	  //clusteringIndex has physical filename that can be used to check
+	  //if a catalog operation has been performed on a table.
+	  //Views don't have clusteringIndex, so we get physical filename
+	  //from the viewFileName_ datamember.
+	  if(viewText_)
+	  {
+		  //view filename starts with node name
+		  //filename is in format \<node_name>.$<volume>.<subvolume>.<file>
+		  //catStr => <volume>
+		  //schemaStr => <subvolume>
+		  //fileStr => <file>
+		  nodeName = viewFileName_;
+		  catStr = nodeName;
+
+		  //skip over node name
+		  //measure node name length
+		  //get to begining of volume name
+		  //Measure length of node name
+		  //skip over node name i.e. \MAYA, \AZTEC, etc
+		  //and get to volume name
+		  while((nodeName[nodeNameLen]!='.')&&
+				  (nodeNameLen < 8)){
+			  catStr++;
+			  nodeNameLen++;
+		  };
+
+		  //skip over '.' and the '$' in volume name
+		  catStr=&nodeName[nodeNameLen+2];
+		  schemaStr=catStr;
+
+		  //skip over the volume/catalog name
+		  //while measuring catalog name length
+		  while((catStr[catStrLen]!='.')&&
+				  (catStrLen < 8))
+		  {
+			  schemaStr++;
+			  catStrLen++;
+		  }
+
+		  //skip over the '.'
+		  schemaStr++;
+		  fileStr=schemaStr;
+
+		  //skip over the subvolume/schema name
+		  //while measuring schema name length
+		  while((schemaStr[schemaStrLen]!='.')&&
+				  (schemaStrLen < 8))
+		  {
+			  fileStr++;
+			  schemaStrLen++;
+		  }
+
+		  //skip over the '.'
+		  fileStr++;
+		  fileStrLen = str_len(fileStr);
+
+		  //figure out the node number for the node
+		  //which has the primary partition.
+		  primaryNodeNum=0;
+
+		  if(!OSIM_runningSimulation())        
+			  primaryNodeNum = gpClusterInfo->mapNodeNameToNodeNum(NAString(nodeName));
+	  }
+	  else{
+		  //get qualified name of the clustering index which should
+		  //be the actual physical file name of the table
+		  const QualifiedName fileNameObj = getClusteringIndex()->
+			  getRandomPartition();
+		  const NAString fileName = fileNameObj.getObjectName();
+
+		  //get schemaName object
+		  const SchemaName schemaNameObj = fileNameObj.getSchemaName();
+		  const NAString schemaName = schemaNameObj.getSchemaName();
+
+		  //get catalogName object
+		  //this contains a string in the form \<node_name>.$volume
+		  const CatalogName catalogNameObj = fileNameObj.getCatalogName();
+		  const NAString catalogName = catalogNameObj.getCatalogName();
+		  nodeName = (char*) catalogName.data();
+		  catStr = nodeName;
+
+		  //Measure length of node name
+		  //skip over node name i.e. \MAYA, \AZTEC, etc
+		  //and get to volume name
+		  while((nodeName[nodeNameLen]!='.')&&
+				  (nodeNameLen < 8)){
+			  catStr++;
+			  nodeNameLen++;
+		  };
+
+		  //get volume/catalog name
+		  //skip ".$"
+		  catStr=&nodeName[nodeNameLen+2];
 #pragma nowarn(1506)   // warning elimination
-      catStrLen = catalogName.length() - (nodeNameLen+2);
+		  catStrLen = catalogName.length() - (nodeNameLen+2);
 #pragma warn(1506)  // warning elimination
 
-      //get subvolume/schema name
-      schemaStr = (char *) schemaName.data();
+		  //get subvolume/schema name
+		  schemaStr = (char *) schemaName.data();
 #pragma nowarn(1506)   // warning elimination
-      schemaStrLen = schemaName.length();
+		  schemaStrLen = schemaName.length();
 #pragma warn(1506)  // warning elimination
 
-      //get file name
-      fileStr = (char *) fileName.data();
+		  //get file name
+		  fileStr = (char *) fileName.data();
 #pragma nowarn(1506)   // warning elimination
-      fileStrLen = fileName.length();
+		  fileStrLen = fileName.length();
 #pragma warn(1506)  // warning elimination
 
-      //figure out the node number for the node
-      //which has the primary partition.
-      primaryNodeNum=0;
+		  //figure out the node number for the node
+		  //which has the primary partition.
+		  primaryNodeNum=0;
 
-      primaryNodeNum = gpClusterInfo->mapNodeNameToNodeNum(NAString(nodeName));
-      
-    }
+		  primaryNodeNum = gpClusterInfo->mapNodeNameToNodeNum(NAString(nodeName));
+
+	  }
   }
 
   Lng32 postCreateNATableWarnings = CmpCommon::diags()->getNumber(DgSqlCode::WARNING_);
 
   if(postCreateNATableWarnings != preCreateNATableWarnings)
-    tableConstructionHadWarnings_=TRUE;
+	  tableConstructionHadWarnings_=TRUE;
   const char *lobHdfsServer = CmpCommon::getDefaultString(LOB_HDFS_SERVER);
   Int32 lobHdfsPort = (Lng32)CmpCommon::getDefaultNumeric(LOB_HDFS_PORT);
   if (hasLobColumn())
-    {
-      // read lob related information from lob metadata
-      short *lobNumList = new (heap_) short[getColumnCount()];
-      short *lobTypList = new (heap_) short[getColumnCount()];
-      char  **lobLocList = new (heap_) char*[getColumnCount()];
-      
-      const NAColumnArray &colArray = getNAColumnArray();
-      NAColumn *nac = NULL;
-      
-      Lng32 j = 0;
-      for (CollIndex i = 0; i < getColumnCount(); i++)
-	{
-	  nac = colArray.getColumn(i);
-	  
-	  if (nac->getType()->getTypeQualifier() == NA_LOB_TYPE)
+  {
+	  // read lob related information from lob metadata
+	  //     setFromStoredDesc(TRUE);
+      //
+	    short *lobNumList = new (heap_) short[getColumnCount()];
+	    short *lobTypList = new (heap_) short[getColumnCount()];
+	    char  **lobLocList = new (heap_) char*[getColumnCount()];
+
+	    const NAColumnArray &colArray = getNAColumnArray();
+	    NAColumn *nac = NULL;
+
+	    Lng32 j = 0;
+	    for (CollIndex i = 0; i < getColumnCount(); i++)
 	    {
-	      lobLocList[j] = new (heap_) char[1024];
-	      j++;
-	    }
-	}      
-      
-      NAString schNam;
-      schNam = "\"";
-      schNam += getTableName().getCatalogName();
-      schNam += "\".\"";
-      schNam += getTableName().getSchemaName();
-      schNam += "\"";
-      
-      Lng32 numLobs = 0;
-      Lng32 cliRC = SQL_EXEC_LOBddlInterface
-	(
-	 (char*)schNam.data(),
-	 schNam.length(),
-	 objectUid().castToInt64(),
-	 numLobs,
-	 LOB_CLI_SELECT_CURSOR,
-	 lobNumList,
-	 lobTypList,
-	 lobLocList,(char *)lobHdfsServer,lobHdfsPort,0,FALSE);
-      
-      if (cliRC == 0)
-	{
-	  for (Lng32 i = 0; i < numLobs; i++)
+		    nac = colArray.getColumn(i);
+
+		    if (nac->getType()->getTypeQualifier() == NA_LOB_TYPE)
+		    {
+			    lobLocList[j] = new (heap_) char[1024];
+			    j++;
+		    }
+	    }      
+
+	    NAString schNam;
+	    schNam = "\"";
+	    schNam += getTableName().getCatalogName();
+	    schNam += "\".\"";
+	    schNam += getTableName().getSchemaName();
+	    schNam += "\"";
+
+	    Lng32 numLobs = 0;
+	    Lng32 cliRC = SQL_EXEC_LOBddlInterface
+		    (
+		     (char*)schNam.data(),
+		     schNam.length(),
+		     objectUid().castToInt64(),
+		     numLobs,
+		     LOB_CLI_SELECT_CURSOR,
+		     lobNumList,
+		     lobTypList,
+		     lobLocList,(char *)lobHdfsServer,lobHdfsPort,0,FALSE);
+
+	    if (cliRC == 0)
 	    {
-	      nac = colArray.getColumn(lobNumList[i]);
-	      
-	      nac->lobNum() = lobNumList[i];
-	      nac->lobStorageType() = (LobsStorage)lobTypList[i];
-	      nac->lobStorageLocation() = lobLocList[i];
-	    }
-	} // if
+		    for (Lng32 i = 0; i < numLobs; i++)
+		    {
+			    nac = colArray.getColumn(lobNumList[i]);
+
+			    nac->lobNum() = lobNumList[i];
+			    nac->lobStorageType() = (LobsStorage)lobTypList[i];
+			    nac->lobStorageLocation() = lobLocList[i];
+		    }
+	    } // if
     } // if
-  
-// LCOV_EXCL_STOP
+
+  // LCOV_EXCL_STOP
   initialSize_ = heap_->getAllocSize();
   MonitorMemoryUsage_Exit((char*)mmPhase.data(), heap_, NULL, TRUE);
-} // NATable()
+ } // NATable()
 #pragma warn(770)  // warning elimination
 
 
 // Constructor for a Hive table
 NATable::NATable(BindWA *bindWA,
-                 const CorrName& corrName,
-		 NAMemory *heap,
-		 struct hive_tbl_desc* htbl)
-  //
-  // The NATable heap ( i.e. heap_ ) used to come from ContextHeap
-  // (i.e. heap) but it creates high memory usage/leakage in Context
-  // Heap. Although the NATables are deleted at the end of each statement,
-  // the heap_ is returned to heap (i.e. context heap) which caused
-  // context heap containing a lot of not used chunk of memory. So it is
-  // changed to be from whatever heap is passed in at the call in
-  // NATableDB.getNATable.
-  //
-  // Now NATable objects can be cached.If an object is to be cached (persisted
-  // across statements) a NATable heap is allocated for the object
-  // and is passed in (this is done in NATableDB::get(CorrName& corrName...).
-  // Otherwise a reference to the Statement heap is passed in. When a cached
-  // object is to be deleted the object's heap is deleted which wipes out the
-  // NATable object all its related stuff. NATable objects that are not cached
-  // are wiped out at the end of the statement when the statement heap is deleted.
-  //
-  : heap_(heap),
-    referenceCount_(0),
-    refsIncompatibleDP2Halloween_(FALSE),
-    isHalloweenTable_(FALSE),
-    qualifiedName_(corrName.getExtendedQualNameObj(),heap),
-    synonymReferenceName_(heap),
-    fileSetName_(corrName.getQualifiedNameObj(),heap),   // for now, set equal
-    clusteringIndex_(NULL),
-    colcount_(0),
-    colArray_(heap),
-    recordLength_(0),
-    indexes_(heap),
-    vertParts_(heap),
-    colStats_(NULL),
-    statsFetched_(FALSE),
-    viewFileName_(NULL),
-    viewText_(NULL),
-    viewTextInNAWchars_(heap),
-    viewTextCharSet_(CharInfo::UnknownCharSet),
-    viewCheck_(NULL),
-    viewColUsages_(NULL),
-    flags_(IS_INSERTABLE | IS_UPDATABLE),
-    insertMode_(COM_REGULAR_TABLE_INSERT_MODE),
-    isSynonymTranslationDone_(FALSE),
-    checkConstraints_(heap),
-    createTime_(htbl->creationTS_),
-    redefTime_(htbl->redeftime()),
-    cacheTime_(0),
-    statsTime_(0),
-    catalogUID_(0),
-    schemaUID_(0),
-    objectUID_(0),
-    objectType_(COM_UNKNOWN_OBJECT),
-    partitioningScheme_(COM_UNKNOWN_PARTITIONING),
-    uniqueConstraints_(heap),
-    refConstraints_(heap),
-    isAnMV_(FALSE),
-    isAnMVMetaData_(FALSE),
-    mvsUsingMe_(heap),
-    mvInfo_(NULL),
-    accessedInCurrentStatement_(TRUE),
-    setupForStatement_(FALSE),
-    resetAfterStatement_(FALSE),
-    hitCount_(0),
-    replacementCounter_(2),
-    sizeInCache_(0),
-    recentlyUsed_(TRUE),
-    tableConstructionHadWarnings_(FALSE),
-    isAnMPTableWithAnsiName_(FALSE),
-    isUMDTable_(FALSE),
-    isSMDTable_(FALSE),
-    isMVUMDTable_(FALSE),
-
-    // For virtual tables, we set the object schema version
-    // to be the current schema version
-    osv_(COM_VERS_CURR_SCHEMA),
-    ofv_(COM_VERS_CURR_SCHEMA),
-    partnsDesc_(NULL),
-    colsWithMissingStats_(NULL),
-    originalCardinality_(-1.0),
-    tableIdList_(heap),
-    rcb_(NULL),
-    rcbLen_(0),
-    keyLength_(0),
-    parentTableName_(NULL),
-    sgAttributes_(NULL),
-    isHive_(TRUE),
-    isHbase_(FALSE),
-    isHbaseCell_(FALSE),
-    isHbaseRow_(FALSE),
-    isSeabase_(FALSE),
-    isSeabaseMD_(FALSE),
-    isSeabasePrivSchemaTable_(FALSE),
-    isUserUpdatableSeabaseMD_(FALSE),
-    resetHDFSStatsAfterStmt_(FALSE),
-    hiveDefaultStringLen_(0),
-    hiveTableId_(htbl->tblID_),
-    tableDesc_(NULL),
-    secKeySet_(heap),
-    privInfo_(NULL),
-    newColumns_(heap),
-    snapshotName_(NULL)
+		const CorrName& corrName,
+		NAMemory *heap,
+		struct hive_tbl_desc* htbl)
+	//
+	// The NATable heap ( i.e. heap_ ) used to come from ContextHeap
+	// (i.e. heap) but it creates high memory usage/leakage in Context
+	// Heap. Although the NATables are deleted at the end of each statement,
+	// the heap_ is returned to heap (i.e. context heap) which caused
+	// context heap containing a lot of not used chunk of memory. So it is
+	// changed to be from whatever heap is passed in at the call in
+	// NATableDB.getNATable.
+	//
+	// Now NATable objects can be cached.If an object is to be cached (persisted
+	// across statements) a NATable heap is allocated for the object
+	// and is passed in (this is done in NATableDB::get(CorrName& corrName...).
+	// Otherwise a reference to the Statement heap is passed in. When a cached
+	// object is to be deleted the object's heap is deleted which wipes out the
+	// NATable object all its related stuff. NATable objects that are not cached
+	// are wiped out at the end of the statement when the statement heap is deleted.
+	//
+	: heap_(heap),
+	referenceCount_(0),
+	refsIncompatibleDP2Halloween_(FALSE),
+	isHalloweenTable_(FALSE),
+	qualifiedName_(corrName.getExtendedQualNameObj(),heap),
+	synonymReferenceName_(heap),
+	fileSetName_(corrName.getQualifiedNameObj(),heap),   // for now, set equal
+	clusteringIndex_(NULL),
+	colcount_(0),
+	colArray_(heap),
+	recordLength_(0),
+	indexes_(heap),
+	vertParts_(heap),
+	colStats_(NULL),
+	statsFetched_(FALSE),
+	viewFileName_(NULL),
+	viewText_(NULL),
+	viewTextInNAWchars_(heap),
+	viewTextCharSet_(CharInfo::UnknownCharSet),
+	viewCheck_(NULL),
+	viewColUsages_(NULL),
+	flags_(IS_INSERTABLE | IS_UPDATABLE),
+	insertMode_(COM_REGULAR_TABLE_INSERT_MODE),
+	isSynonymTranslationDone_(FALSE),
+	checkConstraints_(heap),
+	createTime_(htbl->creationTS_),
+	redefTime_(htbl->redeftime()),
+	cacheTime_(0),
+	statsTime_(0),
+	catalogUID_(0),
+	schemaUID_(0),
+	objectUID_(0),
+	objectType_(COM_UNKNOWN_OBJECT),
+	partitioningScheme_(COM_UNKNOWN_PARTITIONING),
+	uniqueConstraints_(heap),
+	refConstraints_(heap),
+	isAnMV_(FALSE),
+	isAnMVMetaData_(FALSE),
+	mvsUsingMe_(heap),
+	mvInfo_(NULL),
+	accessedInCurrentStatement_(TRUE),
+	setupForStatement_(FALSE),
+	resetAfterStatement_(FALSE),
+	hitCount_(0),
+	replacementCounter_(2),
+	sizeInCache_(0),
+	recentlyUsed_(TRUE),
+	tableConstructionHadWarnings_(FALSE),
+	isAnMPTableWithAnsiName_(FALSE),
+	isUMDTable_(FALSE),
+	isSMDTable_(FALSE),
+	isMVUMDTable_(FALSE),
+
+	// For virtual tables, we set the object schema version
+	// to be the current schema version
+	osv_(COM_VERS_CURR_SCHEMA),
+	ofv_(COM_VERS_CURR_SCHEMA),
+	partnsDesc_(NULL),
+	colsWithMissingStats_(NULL),
+	originalCardinality_(-1.0),
+	tableIdList_(heap),
+	rcb_(NULL),
+	rcbLen_(0),
+	keyLength_(0),
+	parentTableName_(NULL),
+	sgAttributes_(NULL),
+	isHive_(TRUE),
+	isHbase_(FALSE),
+	isHbaseCell_(FALSE),
+	isHbaseRow_(FALSE),
+	isSeabase_(FALSE),
+	isSeabaseMD_(FALSE),
+	isSeabasePrivSchemaTable_(FALSE),
+	isUserUpdatableSeabaseMD_(FALSE),
+	resetHDFSStatsAfterStmt_(FALSE),
+	hiveDefaultStringLen_(0),
+	hiveTableId_(htbl->tblID_),
+	tableDesc_(NULL),
+	secKeySet_(heap),
+	privInfo_(NULL),
+	newColumns_(heap),
+	snapshotName_(NULL)
 {
 
-  NAString tblName = qualifiedName_.getQualifiedNameObj().getQualifiedNameAsString();
-  NAString mmPhase;
-
-  Lng32 preCreateNATableWarnings = CmpCommon::diags()->getNumber(DgSqlCode::WARNING_);
-
-  //set heap type
-  if(heap_ == CmpCommon::statementHeap()){
-    heapType_ = STATEMENT;
-    mmPhase = "NATable Init (Stmt) - " + tblName;
-  }else if (heap_ == CmpCommon::contextHeap()){
-    heapType_ = CONTEXT;
-    mmPhase = "NATable Init (Cnxt) - " + tblName;
-  }else {
-    heapType_ = OTHER;
-    mmPhase = "NATable Init (Other) - " + tblName;
-  }
+	NAString tblName = qualifiedName_.getQualifiedNameObj().getQualifiedNameAsString();
+	NAString mmPhase;
+
+	Lng32 preCreateNATableWarnings = CmpCommon::diags()->getNumber(DgSqlCode::WARNING_);
+
+	//set heap type
+	if(heap_ == CmpCommon::statementHeap()){
+		heapType_ = STATEMENT;
+		mmPhase = "NATable Init (Stmt) - " + tblName;
+	}else if (heap_ == CmpCommon::contextHeap()){
+		heapType_ = CONTEXT;
+		mmPhase = "NATable Init (Cnxt) - " + tblName;
+	}else {
+		heapType_ = OTHER;
+		mmPhase = "NATable Init (Other) - " + tblName;
+	}
 
-  MonitorMemoryUsage_Enter((char*)mmPhase.data(), heap_, TRUE);
+	MonitorMemoryUsage_Enter((char*)mmPhase.data(), heap_, TRUE);
 
 
-  isTrigTempTable_ = FALSE;
+	isTrigTempTable_ = FALSE;
 
 
-  insertMode_ = 
-     COM_MULTISET_TABLE_INSERT_MODE; // allow dup, to check
-     //ComInsertMode::COM_MULTISET_TABLE_INSERT_MODE; // allow dup, to check
+	insertMode_ = 
+		COM_MULTISET_TABLE_INSERT_MODE; // allow dup, to check
+	//ComInsertMode::COM_MULTISET_TABLE_INSERT_MODE; // allow dup, to check
 
-  //
-  // Add timestamp information.
-  //
+	//
+	// Add timestamp information.
+	//
 
-  // To get from Hive
-/*
-  createTime_ = longArrayToInt64(table_desc->tableDesc()->createtime);
-  redefTime_  = longArrayToInt64(table_desc->tableDesc()->redeftime);
-  cacheTime_  = longArrayToInt64(table_desc->tableDesc()->cachetime);
-*/
+	// To get from Hive
+	/*
+	   createTime_ = longArrayToInt64(table_desc->tableDesc()->createtime);
+	   redefTime_  = longArrayToInt64(table_desc->tableDesc()->redeftime);
+	   cacheTime_  = longArrayToInt64(table_desc->tableDesc()->cachetime);
+	   */
 
-  // NATable has a schemaUID column, probably should propogate it.
-  // for now, set to 0.
-  schemaUID_ = 0;
+	// NATable has a schemaUID column, probably should propogate it.
+	// for now, set to 0.
+	schemaUID_ = 0;
 
-  // Set the objectUID_
-  // If the HIVE table has been registered in Trafodion, get the objectUID
-  // from Trafodion, otherwise, set it to 0.
-  // TBD - does getQualifiedNameObj handle delimited names correctly?
-  if ( !fetchObjectUIDForNativeTable(corrName) )
-     return;
+	// Set the objectUID_
+	// If the HIVE table has been registered in Trafodion, get the objectUID
+	// from Trafodion, otherwise, set it to 0.
+	// TBD - does getQualifiedNameObj handle delimited names correctly?
+	if ( !fetchObjectUIDForNativeTable(corrName) )
+		return;
 
-  if ( objectUID_ > 0 )
-    setHasExternalTable(TRUE);
+	if ( objectUID_ > 0 )
+		setHasExternalTable(TRUE);
 
-  // for HIVE objects, the schema owner and table owner is HIVE_ROLE_ID
-  if (CmpCommon::context()->isAuthorizationEnabled())
-  {
-    owner_ = HIVE_ROLE_ID;
-    schemaOwner_ = HIVE_ROLE_ID;
-  }
-  else
-  {
-     owner_ = SUPER_USER;
-     schemaOwner_ = SUPER_USER;
-  }
+	// for HIVE objects, the schema owner and table owner is HIVE_ROLE_ID
+	if (CmpCommon::context()->isAuthorizationEnabled())
+	{
+		owner_ = HIVE_ROLE_ID;
+		schemaOwner_ = HIVE_ROLE_ID;
+	}
+	else
+	{
+		owner_ = SUPER_USER;
+		schemaOwner_ = SUPER_USER;
+	}
 
-  if (hasExternalTable())
-    getPrivileges(NULL); 
+	if (hasExternalTable())
+		getPrivileges(NULL); 
 
-  // TBD - if authorization is enabled and there is no external table to store
-  // privileges, go get privilege information from HIVE metadata ...
-  
-  // TBD - add a check to verify that the column list coming from HIVE matches
-  // the column list stored in the external table.  Maybe some common method
-  // that can be used to compare other things as well...
- 
-  objectType_ = COM_BASE_TABLE_OBJECT;
+	// TBD - if authorization is enabled and there is no external table to store
+	// privileges, go get privilege information from HIVE metadata ...
 
-// to check
-  partitioningScheme_ = COM_UNKNOWN_PARTITIONING;
+	// TBD - add a check to verify that the column list coming from HIVE matches
+	// the column list stored in the external table.  Maybe some common method
+	// that can be used to compare other things as well...
 
-// to check
-  rcb_ = 0;
-  rcbLen_ = 0;
-  keyLength_ = 0;
+	objectType_ = COM_BASE_TABLE_OBJECT;
 
-  partnsDesc_ = NULL;
+	// to check
+	partitioningScheme_ = COM_UNKNOWN_PARTITIONING;
 
-  //
-  // Insert a NAColumn in the colArray_ for this NATable for each
-  // columns_desc from the ARK SMD. Returns TRUE if error creating NAColumns.
-  //
+	// to check
+	rcb_ = 0;
+	rcbLen_ = 0;
+	keyLength_ = 0;
 
-  if (createNAColumns(htbl->getColumns(),
-		      this,
-		      colArray_ /*OUT*/,
-		      heap_))
-    //coverity[leaked_storage]
-    return;
+	partnsDesc_ = NULL;
 
+	//
+	// Insert a NAColumn in the colArray_ for this NATable for each
+	// columns_desc from the ARK SMD. Returns TRUE if error creating NAColumns.
+	//
 
-  //
-  // Set colcount_ after all possible errors (Binder uses nonzero colcount
-  // as an indicator of valid table definition).
-  //
+	if (createNAColumns(htbl->getColumns(),
+				this,
+				colArray_ /*OUT*/,
+				heap_))
+		//coverity[leaked_storage]
+		return;
 
-  // To set it via the new createNAColumns()
-  colcount_ = colArray_.entries();
 
-  // compute record length from colArray
+	//
+	// Set colcount_ after all possible errors (Binder uses nonzero colcount
+	// as an indicator of valid table definition).
+	//
 
-  Int32 recLen = 0;
-  for ( CollIndex i=0; i<colcount_; i++ ) {
-    recLen += colArray_[i]->getType()->getNominalSize();
-  } 
+	// To set it via the new createNAColumns()
+	colcount_ = colArray_.entries();
 
-  setRecordLength(recLen);
-
-  if (createNAFileSets(htbl             /*IN*/,
-                       this             /*IN*/,
-                       colArray_        /*IN*/,
-                           indexes_         /*OUT*/,
-                           vertParts_       /*OUT*/,
-                           clusteringIndex_ /*OUT*/,
-                           tableIdList_     /*OUT*/,
-                           heap_,
-                           bindWA
-                           )) {
-    colcount_ = 0; // indicates failure
-    return;
-  }
+	// compute record length from colArray
 
-  // HIVE-TBD ignore constraint info creation for now
+	Int32 recLen = 0;
+	for ( CollIndex i=0; i<colcount_; i++ ) {
+		recLen += colArray_[i]->getType()->getNominalSize();
+	} 
 
+	setRecordLength(recLen);
 
-  // If there is a host variable associated with this table, store it
-  // for use by the generator to generate late-name resolution information.
-  //
-  HostVar *hv = corrName.getPrototype();
-  prototype_ = hv ? new (heap_) HostVar(*hv) : NULL;
+	if (createNAFileSets(htbl             /*IN*/,
+				this             /*IN*/,
+				colArray_        /*IN*/,
+				indexes_         /*OUT*/,
+				vertParts_       /*OUT*/,
+				clusteringIndex_ /*OUT*/,
+				tableIdList_     /*OUT*/,
+				heap_,
+				bindWA
+			    )) {
+		colcount_ = 0; // indicates failure
+		return;
+	}
 
-  // MV
-  // Initialize the MV support data members
-  isAnMV_           = FALSE;
-  isAnMVMetaData_   = FALSE;
+	// HIVE-TBD ignore constraint info creation for now
 
-  Lng32 postCreateNATableWarnings = CmpCommon::diags()->getNumber(DgSqlCode::WARNING_);
 
-  if(postCreateNATableWarnings != preCreateNATableWarnings)
-    tableConstructionHadWarnings_=TRUE;
+	// If there is a host variable associated with this table, store it
+	// for use by the generator to generate late-name resolution information.
+	//
+	HostVar *hv = corrName.getPrototype();
+	prototype_ = hv ? new (heap_) HostVar(*hv) : NULL;
 
-  hiveDefaultStringLen_ = CmpCommon::getDefaultLong(HIVE_MAX_STRING_LENGTH);
-  Int32 hiveDefaultStringLenInBytes = CmpCommon::getDefaultLong(HIVE_MAX_STRING_LENGTH_IN_BYTES);
-  if( hiveDefaultStringLenInBytes != 32000 ) 
-      hiveDefaultStringLen_ = hiveDefaultStringLenInBytes;
+	// MV
+	// Initialize the MV support data members
+	isAnMV_           = FALSE;
+	isAnMVMetaData_   = FALSE;
 
-// LCOV_EXCL_STOP
-  initialSize_ = heap_->getAllocSize();
-  MonitorMemoryUsage_Exit((char*)mmPhase.data(), heap_, NULL, TRUE);
+	Lng32 postCreateNATableWarnings = CmpCommon::diags()->getNumber(DgSqlCode::WARNING_);
+
+	if(postCreateNATableWarnings != preCreateNATableWarnings)
+		tableConstructionHadWarnings_=TRUE;
+
+	hiveDefaultStringLen_ = CmpCommon::getDefaultLong(HIVE_MAX_STRING_LENGTH);
+	Int32 hiveDefaultStringLenInBytes = CmpCommon::getDefaultLong(HIVE_MAX_STRING_LENGTH_IN_BYTES);
+	if( hiveDefaultStringLenInBytes != 32000 ) 
+		hiveDefaultStringLen_ = hiveDefaultStringLenInBytes;
+
+	// LCOV_EXCL_STOP
+	initialSize_ = heap_->getAllocSize();
+	MonitorMemoryUsage_Exit((char*)mmPhase.data(), heap_, NULL, TRUE);
 } // NATable()
 #pragma warn(770)  // warning elimination
 
@@ -6039,20 +6042,20 @@ NATable::NATable(BindWA *bindWA,
 
 NABoolean NATable::doesMissingStatsWarningExist(CollIndexSet & colsSet) const
 {
-  return colsWithMissingStats_->contains(&colsSet);
+	return colsWithMissingStats_->contains(&colsSet);
 }
 
 NABoolean NATable::insertMissingStatsWarning(CollIndexSet colsSet) const
 {
-  CollIndexSet * setOfColsWithMissingStats = new (STMTHEAP) CollIndexSet (colsSet);
+	CollIndexSet * setOfColsWithMissingStats = new (STMTHEAP) CollIndexSet (colsSet);
 
-  Int32 someVar = 1;
-  CollIndexSet * result = colsWithMissingStats_->insert(setOfColsWithMissingStats, &someVar);
+	Int32 someVar = 1;
+	CollIndexSet * result = colsWithMissingStats_->insert(setOfColsWithMissingStats, &someVar);
 
-  if (result == NULL)
-    return FALSE;
-  else
-    return TRUE;
+	if (result == NULL)
+		return FALSE;
+	else
+		return TRUE;
 }
 
 // This gets called in the Optimizer phase -- the Binder phase will already have
@@ -6060,523 +6063,523 @@ NABoolean NATable::insertMissingStatsWarning(CollIndexSet colsSet) const
 // below can decide which histograms and histints to leave in the stats list
 // and which to remove.
 //
-StatsList &
+	StatsList &
 NATable::getStatistics()
 {
-    if (!statsFetched_)
-    {
-      // mark the kind of histograms needed for this table's columns
-      markColumnsForHistograms();
-
-      NAString tblName = qualifiedName_.getQualifiedNameObj().getQualifiedNameAsString();
-      NAString mmPhase = "NATable getStats - " + tblName;
-      MonitorMemoryUsage_Enter((char*)mmPhase.data(), NULL, TRUE);
-
-      //trying to get statistics for a new statement allocate colStats_
-      colStats_ = new (CmpCommon::statementHeap()) StatsList(CmpCommon::statementHeap());
+	if (!statsFetched_)
+	{
+		// mark the kind of histograms needed for this table's columns
+		markColumnsForHistograms();
+
+		NAString tblName = qualifiedName_.getQualifiedNameObj().getQualifiedNameAsString();
+		NAString mmPhase = "NATable getStats - " + tblName;
+		MonitorMemoryUsage_Enter((char*)mmPhase.data(), NULL, TRUE);
+
+		//trying to get statistics for a new statement allocate colStats_
+		colStats_ = new (CmpCommon::statementHeap()) StatsList(CmpCommon::statementHeap());
+
+		// Do not create statistics on the fly for the following tables
+		if (isAnMV() || isUMDTable() ||
+				isSMDTable() || isMVUMDTable() ||
+				isTrigTempTable() )
+			CURRSTMT_OPTDEFAULTS->setHistDefaultSampleSize(0);
+
+		CURRCONTEXT_HISTCACHE->getHistograms(*this);
+
+		if ((*colStats_).entries() > 0)
+			originalCardinality_ = (*colStats_)[0]->getRowcount();
+		else
+			originalCardinality_ = ActiveSchemaDB()->getDefaults().getAsDouble(HIST_NO_STATS_ROWCOUNT);
+
+		// -----------------------------------------------------------------------
+		// So now we have read in the contents of the HISTOGRM & HISTINTS
+		// tables from the system catalog.  Before we can use them, we need
+		// to massage them into a format we can use.  In particular, we need
+		// to make sure that what we read in (which the user may have mucked
+		// about with) matches the histogram classes' internal semantic
+		// requirements.  Also, we need to generate the MultiColumnUecList.
+		//  ----------------------------------------------------------------------
+
+		// what did the user set as the max number of intervals?
+		NADefaults &defs = ActiveSchemaDB()->getDefaults();
+		CollIndex maxIntervalCount = defs.getAsLong(HIST_MAX_NUMBER_OF_INTERVALS);
+
+		//-----------------------------------------------------------------------------------
+		// Need to flag the MC colStatsDesc so it is only used for the range partitioning task
+		// and not any cardinality calculations tasks. Flagging it also makes the logic
+		// to check fo the presence for this MC easier (at the time we need to create
+		// the range partitioning function)
+		//-----------------------------------------------------------------------------------
+
+		if (CmpCommon::getDefault(HBASE_RANGE_PARTITIONING_MC_SPLIT) == DF_ON && 
+				!(*colStats_).allFakeStats())
+		{
+			CollIndex currentMaxsize = 1;
+			Int32 posMCtoUse = -1;
 
-      // Do not create statistics on the fly for the following tables
-      if (isAnMV() || isUMDTable() ||
-          isSMDTable() || isMVUMDTable() ||
-          isTrigTempTable() )
-        CURRSTMT_OPTDEFAULTS->setHistDefaultSampleSize(0);
+			NAColumnArray partCols;
 
-      CURRCONTEXT_HISTCACHE->getHistograms(*this);
+			if (getClusteringIndex()->getPartitioningKeyColumns().entries() > 0)
+				partCols = getClusteringIndex()->getPartitioningKeyColumns();
+			else
+				partCols = getClusteringIndex()->getIndexKeyColumns();
 
-      if ((*colStats_).entries() > 0)
-        originalCardinality_ = (*colStats_)[0]->getRowcount();
-      else
-        originalCardinality_ = ActiveSchemaDB()->getDefaults().getAsDouble(HIST_NO_STATS_ROWCOUNT);
-
-      // -----------------------------------------------------------------------
-      // So now we have read in the contents of the HISTOGRM & HISTINTS
-      // tables from the system catalog.  Before we can use them, we need
-      // to massage them into a format we can use.  In particular, we need
-      // to make sure that what we read in (which the user may have mucked
-      // about with) matches the histogram classes' internal semantic
-      // requirements.  Also, we need to generate the MultiColumnUecList.
-      //  ----------------------------------------------------------------------
-
-      // what did the user set as the max number of intervals?
-      NADefaults &defs = ActiveSchemaDB()->getDefaults();
-      CollIndex maxIntervalCount = defs.getAsLong(HIST_MAX_NUMBER_OF_INTERVALS);
-
-      //-----------------------------------------------------------------------------------
-      // Need to flag the MC colStatsDesc so it is only used for the range partitioning task
-      // and not any cardinality calculations tasks. Flagging it also makes the logic
-      // to check fo the presence for this MC easier (at the time we need to create
-      // the range partitioning function)
-      //-----------------------------------------------------------------------------------
-
-      if (CmpCommon::getDefault(HBASE_RANGE_PARTITIONING_MC_SPLIT) == DF_ON && 
-          !(*colStats_).allFakeStats())
-      {
-         CollIndex currentMaxsize = 1;
-         Int32 posMCtoUse = -1;
+			CollIndex partColNum = partCols.entries();
 
-         NAColumnArray partCols;
+			// look for MC histograms that have multiple intervals and whose columns are a prefix for the
+			// paritition column list. If multiple pick the one with the most matching columns
+			for (Int32 i=0; i < (*colStats_).entries(); i++)
+			{
+				NAColumnArray statsCols = (*colStats_)[i]->getStatColumns();
+				CollIndex colNum = statsCols.entries();
+
+				CollIndex j = 0;
+
+				NABoolean potentialMatch = TRUE;
+				if ((colNum > currentMaxsize) && 
+						(!(*colStats_)[i]->isSingleIntHist()) && // no SIH -- number of histograms is large enough to do splitting
+						(colNum <= partColNum))
+				{
+					while ((j < colNum) && potentialMatch)
+					{
+						j++;
+						NAColumn * col = partCols[j-1];
+						if (statsCols[j-1]->getPosition() != partCols[j-1]->getPosition())
+						{
+							potentialMatch = FALSE;
+							break;
+						}   
+					}
+				}
+				else
+				{
+					potentialMatch = FALSE;
+				}
+
+				if (potentialMatch)
+				{
+					currentMaxsize = j;
+					posMCtoUse = i;
+				}
+
+				// we got what we need, just return
+				if (potentialMatch && (currentMaxsize == partColNum))
+				{
+					break;
+				}
+			}
+
+			if (posMCtoUse >= 0)
+			{
+				(*colStats_)[posMCtoUse]->setMCforHbasePartitioning (TRUE);
+			}
+		}
 
-         if (getClusteringIndex()->getPartitioningKeyColumns().entries() > 0)
-             partCols = getClusteringIndex()->getPartitioningKeyColumns();
-         else
-             partCols = getClusteringIndex()->getIndexKeyColumns();
+		// *************************************************************************
+		// FIRST: Generate the stats necessary to later create the
+		// MultiColumnUecList; then filter out the multi-column histograms
+		// because later code doesn't know how to handle them
+		// In the same loop, also mark another flag for originally fake histogram
+		// This is to differentiate the cases when the histogram is fake because
+		// it has no statistics and the case where the histogram has been termed
+		// fake by the optimizer because its statistics is no longer reliable.
+		// *************************************************************************
+		CollIndex i ;
+		for ( i = 0 ; i < (*colStats_).entries() ; /* no automatic increment */ )
+		{
+			// the StatsList has two lists which it uses to store the information we
+			// need to fill the MultiColumnUecList with <table-col-list,uec value> pairs:
+			//
+			// LIST(NAColumnArray) groupUecColumns_
+			// LIST(CostScalar)    groupUecValues_
+			//
+			// ==> insert the NAColumnArray & uec total values for each
+			// entry in colStats_
+
+			// don't bother storing multicolumnuec info for fake histograms
+			// but do set the originallly fake histogram flag to TRUE
+			if ( (*colStats_)[i]->isFakeHistogram() )
+				(*colStats_)[i]->setOrigFakeHist(TRUE);
+			else
+			{
+				NAColumnArray cols = (*colStats_)[i]->getStatColumns() ;
+				(*colStats_).groupUecColumns_.insert(cols) ;
+
+				CostScalar uecs = (*colStats_)[i]->getTotalUec() ;
+				(*colStats_).groupUecValues_.insert(uecs) ;
+
+				if (CmpCommon::getDefault(USTAT_COLLECT_MC_SKEW_VALUES) == DF_ON)
+				{
+					MCSkewedValueList mcSkewedValueList = (*colStats_)[i]->getMCSkewedValueList() ;
+					(*colStats_).groupMCSkewedValueLists_.insert(mcSkewedValueList) ;
+				}
+			}
+
+			// MCH:
+			// once we've stored the column/uec information, filter out the
+			// multi-column histograms, since our synthesis code doesn't
+			// handle them
+			if (( (*colStats_)[i]->getStatColumns().entries() != 1) &&
+					(!(*colStats_)[i]->isMCforHbasePartitioning()))
+			{
+				(*colStats_).removeAt(i) ;
+			}
+			else
+			{
+				i++ ; // in-place removal from a list is a bother!
+			}
+		}
 
-         CollIndex partColNum = partCols.entries();
+		// *************************************************************************
+		// SECOND: do some fixup work to make sure the histograms maintain
+		// the semantics we later expect (& enforce)
+		// *************************************************************************
+
+		// -------------------------------------------------------------------------
+		// HISTINT fixup-code : char-string histograms
+		// -------------------------------------------------------------------------
+		// problem arises with HISTINTs that are for char* columns
+		// here's what we can get:
+		//
+		// Rows    Uec    Value
+		// ----    ---    -----
+		//    0      0    "value"
+		//   10      5    "value"
+		//
+		// this is not good!  The problem is our (lousy) encoding of
+		// char strings into EncodedValue's
+		//
+		// After much deliberation, here's our current fix:
+		//
+		// Rows    Uec    Value
+		// ----    ---    -----
+		//    0      0    "valu" <-- reduce the min value of 1st interval
+		//   10      5    "value"    by a little bit
+		//
+		// When we find two intervals like this where they aren't the
+		// first intervals in the histogram, we simply merge them into
+		// one interval (adding row/uec information) and continue; note
+		// that in this case, we haven't actually lost any information;
+		// we've merely made sense out of (the garbage) what we've got
+		//
+		// -------------------------------------------------------------------------
+		// additional HISTINT fixup-code
+		// -------------------------------------------------------------------------
+		// 1. If there are zero or one HISTINTs, then set the HISTINTs to match
+		// the max/min information contained in the COLSTATS object.
+		//
+		// 2. If there are any HISTINTs whose boundary values are out-of-order,
+		// we abort with an an ERROR message.
+		//
+		// 3. If there is a NULL HISTINT at the end of the Histogram, then we
+		// need to make sure there are *TWO* NULL HISTINTS, to preserve correct
+		// histogram semantics for single-valued intervals.
+		// -------------------------------------------------------------------------
+
+		CollIndex j ;
+		for ( i = 0 ; i < (*colStats_).entries() ; i++ )
+		{
+			// we only worry about histograms on char string columns
+			// correction: it turns out that these semantically-deranged
+			// ----------  histograms were being formed for other, non-char string
+			//             columns, so we commented out the code below
+			// if ( colStats_[i]->getStatColumns()[0]->getType()->getTypeQualifier() !=
+			//     NA_CHARACTER_TYPE)
+			//   continue ; // not a string, skip to next
+
+			ColStatsSharedPtr stats = (*colStats_)[i] ;
+
+			HistogramSharedPtr hist = stats->getHistogramToModify() ;
+			// histograms for key columns of a table that are not
+			// referenced in the query are read in with zero intervals
+			// (to conserve memory); however, internal
+			// histogram-semantic checking code assumes that any
+			// histogram which has zero intervals is FAKE; however
+			// however, MDAM will not be chosen in the case where one of
+			// the histograms for a key column is FAKE.  Thus -- we will
+			// avoid this entire issue by creating a single interval for
+			// any Histograms that we read in that are empty.
+			if ( hist->entries() < 2 )
+			{
+				if(stats->getMinValue() > stats->getMaxValue())
+				{
+					*CmpCommon::diags() << DgSqlCode(CATALOG_HISTOGRM_HISTINTS_TABLES_CONTAIN_BAD_VALUE)
+						<< DgString0("")
+						<< DgString1(stats->getStatColumns()[0]->getFullColRefNameAsAnsiString().data() );
+
+					stats->createFakeHist();
+					continue;
+				}
+
+				stats->setToSingleInterval ( stats->getMinValue(),
+						stats->getMaxValue(),
+						stats->getRowcount(),
+						stats->getTotalUec() ) ;
+				// now we have to undo some of the automatic flag-setting
+				// of ColStats::setToSingleInterval()
+				stats->setMinSetByPred (FALSE) ;
+				stats->setMaxSetByPred (FALSE) ;
+				stats->setShapeChanged (FALSE) ;
+				continue ; // skip to next ColStats
+			}
+
+			// NB: we'll handle the first Interval last
+			for ( j = 1 ; j < hist->entries()-1 ; /* no automatic increment */ )
+			{
 
-         // look for MC histograms that have multiple intervals and whose columns are a prefix for the
-         // paritition column list. If multiple pick the one with the most matching columns
-         for (Int32 i=0; i < (*colStats_).entries(); i++)
-         {
-            NAColumnArray statsCols = (*colStats_)[i]->getStatColumns();
-            CollIndex colNum = statsCols.entries();
-   
-            CollIndex j = 0;
-                
-            NABoolean potentialMatch = TRUE;
-            if ((colNum > currentMaxsize) && 
-                (!(*colStats_)[i]->isSingleIntHist()) && // no SIH -- number of histograms is large enough to do splitting
-                (colNum <= partColNum))
-            {
-                while ((j < colNum) && potentialMatch)
-                {
-                   j++;
-                   NAColumn * col = partCols[j-1];
-                   if (statsCols[j-1]->getPosition() != partCols[j-1]->getPosition())
-                   {
-                      potentialMatch = FALSE;
-                      break;
-                   }   
-                }
-            }
-            else
-            {
-               potentialMatch = FALSE;
-            }
-         
-            if (potentialMatch)
-            {
-               currentMaxsize = j;
-               posMCtoUse = i;
-            }
-   
-            // we got what we need, just return
-            if (potentialMatch && (currentMaxsize == partColNum))
-            {
-                break;
-            }
-         }
+				if ( (*hist)[j].getUec() == 0 || (*hist)[j].getCardinality() == 0 )
+				{
+					hist->removeAt(j) ;
+					continue ; // don't increment, loop again
+				}
+
+				// intervals must be in order!
+				if ( (*hist)[j].getBoundary() > (*hist)[j+1].getBoundary() )
+				{
+					*CmpCommon::diags() <<
+						DgSqlCode(CATALOG_HISTINTS_TABLES_CONTAIN_BAD_VALUES)
+						<< DgInt0(j)
+						<< DgInt1(j+1)
+						<< DgString1(stats->getStatColumns()[0]->getFullColRefNameAsAnsiString().data() );
+
+					stats->createFakeHist();
+					break ; // skip to next ColStats
+				}
+
+				if ( (*hist)[j].getBoundary() == (*hist)[j+1].getBoundary() )
+				{
+					// merge Intervals, if the two consecutive intervals have same 
+					// boundaries and these are not single valued (UEC > 1)
+					// If there are more two single valued intervals, then merge
+					// all except the last one.
+					NABoolean mergeIntervals = FALSE;
+
+					if (CmpCommon::getDefault(COMP_BOOL_79) == DF_ON)
+					{
+						mergeIntervals = TRUE;
+
+						if( (j < (hist->entries() - 2)) && ((*hist)[j+1].getUec() == 1) &&
+								((*hist)[j+1].getBoundary() != (*hist)[j+2].getBoundary())
+								||
+								(j == (hist->entries() - 2)) && ((*hist)[j+1].getUec() == 1) )
+							mergeIntervals = FALSE;
+					}
+					else
+					{
+						if ( (*hist)[j+1].getUec() > 1)
+							mergeIntervals = TRUE;
+					}
+
+					if ( mergeIntervals ) 
+					{
+						// if the intervals with same boundary are not SVI, just merge them 
+						// together.
+						// Also do the merge, if there are more than one SVIs with same 
+						// encoded interval boundary. Example, we want to avoid intervals
+						// such as
+						//   boundary   inclusive_flag  UEC
+						//   12345.00    <               1
+						//   12345.00    <               1
+						//   12345.00    <=              1
+						// These would be changed to 
+						//   12345.00    <               2
+						//   12345.00    <=              1
+						CostScalar combinedRows = (*hist)[ j ].getCardinality() +
+							(*hist)[j+1].getCardinality() ;
+						CostScalar combinedUec  = (*hist)[ j ].getUec() +
+							(*hist)[j+1].getUec() ;
+						(*hist)[j].setCardAndUec (combinedRows, combinedUec) ;
+						stats->setIsColWithBndryConflict(TRUE);
+						hist->removeAt(j+1) ;
+					}
+					else
+					{
+						// for some reason, some SVI's aren't being
+						// generated correctly!
+						(*hist)[j].setBoundIncl(FALSE) ;
+						(*hist)[j+1].setBoundIncl(TRUE) ;
+						j++;
+					}
+				}
+				else
+					j++ ; // in-place removal from a list is a bother!
+			} // loop over intervals
+
+			// ----------------------------------------------------------------------
+			// now we handle the first interval
+			//
+			// first, it must be in order w.r.t. the second interval!
+			if ( (*hist)[0].getBoundary() > (*hist)[1].getBoundary() )
+			{
+				*CmpCommon::diags() <<
+					DgSqlCode(CATALOG_HISTINTS_TABLES_CONTAIN_BAD_VALUES)
+					<< DgInt0(0)
+					<< DgInt1(1)
+					<< DgString1(stats->getStatColumns()[0]->getFullColRefNameAsAnsiString().data() );
+
+				stats->createFakeHist();
+				continue ; // skip to next ColStats
+			}
+
+			// second, handle the case where first and second interval are the same
+			if ( hist->entries() > 1 && // avoid the exception! might just be a single NULL
+					//                     // interval after the loop above
+					(*hist)[0].getBoundary() == (*hist)[1].getBoundary() &&
+					(*hist)[1].getUec() > 1 )
+			{
+				const double KLUDGE_VALUE = 0.0001 ;
+				const double oldVal = (*hist)[0].getBoundary().getDblValue() ;
+				const EncodedValue newVal =
+					EncodedValue(oldVal - (_ABSOLUTE_VALUE_(oldVal) * KLUDGE_VALUE)) ; // kludge alert!
+				//Absolute of oldval due to CR 10-010426-2457
+				(*hist)[0].setBoundary( newVal ) ;
+				(*hist)[0].setBoundIncl( FALSE ) ; // no longer a real boundary!
+				(*colStats_)[i]->setMinValue( newVal ) ; // set aggr info also
+			}
+			// done with first interval
+			// ----------------------------------------------------------------------
+
+			//
+			// NULL values must only be stored in single-valued intervals
+			// in the histograms ; so, just in case we're only getting
+			// *one* HistInt for the NULL interval, insert a 2nd one
+			//
+			// 0   1   2
+			// |   |   |
+			// |   |   |    entries() == 3
+			//         NULL
+			//
+			// 0   1   2   3
+			// |   |   |   |
+			// |   |   |   |    entries() == 4
+			//        new  NULL
+			//        NULL
+			//
+			if ( hist->lastHistInt().isNull() )
+			{
+				CollIndex count = hist->entries() ;
+				if ( !(*hist)[count-2].isNull() )
+				{
+					// insert a 2nd NULL HISTINT, with boundaryIncl value FALSE
+					HistInt secondLast (hist->lastHistInt().getBoundary(), FALSE) ;
+					hist->insertAt(count-1,secondLast) ;
+					// new HISTINT by default has row/uec of 0, which is what we want
+				}
+			}
+
+			//
+			// Now, reduce the total number of intervals to be the number
+			// that the user wants.  This is used to test the tradeoffs
+			// between compile time & rowcount estimation.
+			//
+			(*colStats_)[i]->setMaxIntervalCount (maxIntervalCount) ;
+			(*colStats_)[i]->reduceToMaxIntervalCount () ;
+
+			if ((*colStats_)[i]->getRowcount() == (*colStats_)[i]->getTotalUec() )
+				(*colStats_)[i]->setAlmostUnique(TRUE);
+
+		} // outer for loop -- done with this COLSTATS, continue with next one
+		// ***********************************************************************
+
+		statsFetched_ = TRUE;
+		MonitorMemoryUsage_Exit((char*)mmPhase.data(), NULL, NULL, TRUE);
+	} // !statsFetched_
+
+	return (*colStats_);
+}
 
-         if (posMCtoUse >= 0)
-         {
-            (*colStats_)[posMCtoUse]->setMCforHbasePartitioning (TRUE);
-         }
-      }
+	StatsList &
+NATable::generateFakeStats()
+{
+	if (colStats_ == NULL)
+	{
+		//trying to get statistics for a new statement allocate colStats_
+		colStats_ = new (CmpCommon::statementHeap()) StatsList(CmpCommon::statementHeap());
+	}
 
-      // *************************************************************************
-      // FIRST: Generate the stats necessary to later create the
-      // MultiColumnUecList; then filter out the multi-column histograms
-      // because later code doesn't know how to handle them
-      // In the same loop, also mark another flag for originally fake histogram
-      // This is to differentiate the cases when the histogram is fake because
-      // it has no statistics and the case where the histogram has been termed
-      // fake by the optimizer because its statistics is no longer reliable.
-      // *************************************************************************
-      CollIndex i ;
-      for ( i = 0 ; i < (*colStats_).entries() ; /* no automatic increment */ )
-        {
-          // the StatsList has two lists which it uses to store the information we
-          // need to fill the MultiColumnUecList with <table-col-list,uec value> pairs:
-          //
-          // LIST(NAColumnArray) groupUecColumns_
-          // LIST(CostScalar)    groupUecValues_
-          //
-          // ==> insert the NAColumnArray & uec total values for each
-          // entry in colStats_
+	if (colStats_->entries() > 0)
+		return (*colStats_);
 
-          // don't bother storing multicolumnuec info for fake histograms
-	  // but do set the originallly fake histogram flag to TRUE
-          if ( (*colStats_)[i]->isFakeHistogram() )
-	    (*colStats_)[i]->setOrigFakeHist(TRUE);
-	  else
-            {
-              NAColumnArray cols = (*colStats_)[i]->getStatColumns() ;
-              (*colStats_).groupUecColumns_.insert(cols) ;
+	NAColumnArray colList = getNAColumnArray() ;
+	double defaultFakeRowCount = (ActiveSchemaDB()->getDefaults()).getAsDouble(HIST_NO_STATS_ROWCOUNT);
+	double defaultFakeUec = (ActiveSchemaDB()->getDefaults()).getAsDouble(HIST_NO_STATS_UEC);
 
-              CostScalar uecs = (*colStats_)[i]->getTotalUec() ;
-              (*colStats_).groupUecValues_.insert(uecs) ;
+	if ( isHiveTable() ) {
+		defaultFakeRowCount = getOriginalRowCount().value();
+	}
 
-              if (CmpCommon::getDefault(USTAT_COLLECT_MC_SKEW_VALUES) == DF_ON)
-              {
-                 MCSkewedValueList mcSkewedValueList = (*colStats_)[i]->getMCSkewedValueList() ;
-                 (*colStats_).groupMCSkewedValueLists_.insert(mcSkewedValueList) ;
-              }
+	/*  if ( isHbaseTable() ) {
+	    defaultFakeRowCount = getOriginalRowCount().value();
 	    }
+	    */
 
-          // MCH:
-          // once we've stored the column/uec information, filter out the
-          // multi-column histograms, since our synthesis code doesn't
-          // handle them
-          if (( (*colStats_)[i]->getStatColumns().entries() != 1) &&
-              (!(*colStats_)[i]->isMCforHbasePartitioning()))
-          {
-            (*colStats_).removeAt(i) ;
-          }
-          else
-          {
-            i++ ; // in-place removal from a list is a bother!
-          }
-        }
+	for (CollIndex i = 0; i < colList.entries(); i++ )
+	{
+		NAColumn * col = colList[i];
 
-      // *************************************************************************
-      // SECOND: do some fixup work to make sure the histograms maintain
-      // the semantics we later expect (& enforce)
-      // *************************************************************************
+		if (col->isUnique() )
+			defaultFakeUec = defaultFakeRowCount;
+		else
+			defaultFakeUec = MINOF(defaultFakeUec, defaultFakeRowCount);
 
-      // -------------------------------------------------------------------------
-      // HISTINT fixup-code : char-string histograms
-      // -------------------------------------------------------------------------
-      // problem arises with HISTINTs that are for char* columns
-      // here's what we can get:
-      //
-      // Rows    Uec    Value
-      // ----    ---    -----
-      //    0      0    "value"
-      //   10      5    "value"
-      //
-      // this is not good!  The problem is our (lousy) encoding of
-      // char strings into EncodedValue's
-      //
-      // After much deliberation, here's our current fix:
-      //
-      // Rows    Uec    Value
-      // ----    ---    -----
-      //    0      0    "valu" <-- reduce the min value of 1st interval
-      //   10      5    "value"    by a little bit
-      //
-      // When we find two intervals like this where they aren't the
-      // first intervals in the histogram, we simply merge them into
-      // one interval (adding row/uec information) and continue; note
-      // that in this case, we haven't actually lost any information;
-      // we've merely made sense out of (the garbage) what we've got
-      //
-      // -------------------------------------------------------------------------
-      // additional HISTINT fixup-code
-      // -------------------------------------------------------------------------
-      // 1. If there are zero or one HISTINTs, then set the HISTINTs to match
-      // the max/min information contained in the COLSTATS object.
-      //
-      // 2. If there are any HISTINTs whose boundary values are out-of-order,
-      // we abort with an an ERROR message.
-      //
-      // 3. If there is a NULL HISTINT at the end of the Histogram, then we
-      // need to make sure there are *TWO* NULL HISTINTS, to preserve correct
-      // histogram semantics for single-valued intervals.
-      // -------------------------------------------------------------------------
+		EncodedValue dummyVal(0.0);
 
-      CollIndex j ;
-      for ( i = 0 ; i < (*colStats_).entries() ; i++ )
-        {
-          // we only worry about histograms on char string columns
-          // correction: it turns out that these semantically-deranged
-          // ----------  histograms were being formed for other, non-char string
-          //             columns, so we commented out the code below
-          // if ( colStats_[i]->getStatColumns()[0]->getType()->getTypeQualifier() !=
-          //     NA_CHARACTER_TYPE)
-          //   continue ; // not a string, skip to next
-
-          ColStatsSharedPtr stats = (*colStats_)[i] ;
-
-          HistogramSharedPtr hist = stats->getHistogramToModify() ;
-          // histograms for key columns of a table that are not
-          // referenced in the query are read in with zero intervals
-          // (to conserve memory); however, internal
-          // histogram-semantic checking code assumes that any
-          // histogram which has zero intervals is FAKE; however
-          // however, MDAM will not be chosen in the case where one of
-          // the histograms for a key column is FAKE.  Thus -- we will
-          // avoid this entire issue by creating a single interval for
-          // any Histograms that we read in that are empty.
-          if ( hist->entries() < 2 )
-            {
-              if(stats->getMinValue() > stats->getMaxValue())
-	      {
-	      *CmpCommon::diags() << DgSqlCode(CATALOG_HISTOGRM_HISTINTS_TABLES_CONTAIN_BAD_VALUE)
-		     << DgString0("")
-		     << DgString1(stats->getStatColumns()[0]->getFullColRefNameAsAnsiString().data() );
+		EncodedValue lowBound = dummyVal.minMaxValue(col->getType(), TRUE);
+		EncodedValue highBound = dummyVal.minMaxValue(col->getType(), FALSE);
 
-		stats->createFakeHist();
-		continue;
-	      }
+		HistogramSharedPtr emptyHist(new (HISTHEAP) Histogram(HISTHEAP));
 
-              stats->setToSingleInterval ( stats->getMinValue(),
-                                           stats->getMaxValue(),
-                                           stats->getRowcount(),
-                                           stats->getTotalUec() ) ;
-              // now we have to undo some of the automatic flag-setting
-              // of ColStats::setToSingleInterval()
-              stats->setMinSetByPred (FALSE) ;
-              stats->setMaxSetByPred (FALSE) ;
-              stats->setShapeChanged (FALSE) ;
-              continue ; // skip to next ColStats
-            }
+		HistInt newFirstHistInt(lowBound, FALSE);
 
-          // NB: we'll handle the first Interval last
-          for ( j = 1 ; j < hist->entries()-1 ; /* no automatic increment */ )
-            {
+		HistInt newSecondHistInt(highBound, TRUE);
 
-              if ( (*hist)[j].getUec() == 0 || (*hist)[j].getCardinality() == 0 )
-                {
-                  hist->removeAt(j) ;
-                  continue ; // don't increment, loop again
-                }
+		newSecondHistInt.setCardAndUec(defaultFakeRowCount,
+				defaultFakeUec);
 
-              // intervals must be in order!
-              if ( (*hist)[j].getBoundary() > (*hist)[j+1].getBoundary() )
-                {
-		  *CmpCommon::diags() <<
-                    DgSqlCode(CATALOG_HISTINTS_TABLES_CONTAIN_BAD_VALUES)
-		    << DgInt0(j)
-		    << DgInt1(j+1)
-		    << DgString1(stats->getStatColumns()[0]->getFullColRefNameAsAnsiString().data() );
-
-		    stats->createFakeHist();
-		    break ; // skip to next ColStats
-                }
+		emptyHist->insert(newFirstHistInt);
+		emptyHist->insert(newSecondHistInt);
 
-              if ( (*hist)[j].getBoundary() == (*hist)[j+1].getBoundary() )
-                {
-                  // merge Intervals, if the two consecutive intervals have same 
-                  // boundaries and these are not single valued (UEC > 1)
-                  // If there are more two single valued intervals, then merge
-                  // all except the last one.
-                  NABoolean mergeIntervals = FALSE;
+		ComUID histid(NA_JulianTimestamp());
+		ColStatsSharedPtr fakeColStats(
+				new (HISTHEAP) ColStats(histid,
+					defaultFakeUec,
+					defaultFakeRowCount,
+					defaultFakeRowCount,
+					col->isUnique(),
+					FALSE,
+					emptyHist,
+					FALSE,
+					1.0,
+					1.0,
+					-1, // avg varchar size
+					HISTHEAP));
 
-                  if (CmpCommon::getDefault(COMP_BOOL_79) == DF_ON)
-                  {
-                    mergeIntervals = TRUE;
+		fakeColStats->setFakeHistogram(TRUE);
+		fakeColStats->setOrigFakeHist(TRUE);
+		fakeColStats->setMinValue(lowBound);
+		fakeColStats->setMaxValue(highBound);
+		fakeColStats->statColumns().insert(col);
 
-                    if( (j < (hist->entries() - 2)) && ((*hist)[j+1].getUec() == 1) &&
-                        ((*hist)[j+1].getBoundary() != (*hist)[j+2].getBoundary())
-                        ||
-                        (j == (hist->entries() - 2)) && ((*hist)[j+1].getUec() == 1) )
-                      mergeIntervals = FALSE;
-                  }
-                  else
-                  {
-                    if ( (*hist)[j+1].getUec() > 1)
-                      mergeIntervals = TRUE;
-                  }
+		colStats_->insert(fakeColStats);
+	}
+	setStatsFetched(TRUE);
+	setOriginalRowCount(defaultFakeRowCount);
 
-                  if ( mergeIntervals ) 
-                  {
-                    // if the intervals with same boundary are not SVI, just merge them 
-                    // together.
-                    // Also do the merge, if there are more than one SVIs with same 
-                    // encoded interval boundary. Example, we want to avoid intervals
-                    // such as
-                    //   boundary   inclusive_flag  UEC
-                    //   12345.00    <               1
-                    //   12345.00    <               1
-                    //   12345.00    <=              1
-                    // These would be changed to 
-                    //   12345.00    <               2
-                    //   12345.00    <=              1
-                    CostScalar combinedRows = (*hist)[ j ].getCardinality() +
-                                              (*hist)[j+1].getCardinality() ;
-                    CostScalar combinedUec  = (*hist)[ j ].getUec() +
-                                              (*hist)[j+1].getUec() ;
-                    (*hist)[j].setCardAndUec (combinedRows, combinedUec) ;
-                    stats->setIsColWithBndryConflict(TRUE);
-                     hist->removeAt(j+1) ;
-                    }
-                  else
-                    {
-                      // for some reason, some SVI's aren't being
-                      // generated correctly!
-                      (*hist)[j].setBoundIncl(FALSE) ;
-                      (*hist)[j+1].setBoundIncl(TRUE) ;
-                      j++;
-                    }
-                }
-              else
-                j++ ; // in-place removal from a list is a bother!
-            } // loop over intervals
-
-          // ----------------------------------------------------------------------
-          // now we handle the first interval
-          //
-          // first, it must be in order w.r.t. the second interval!
-          if ( (*hist)[0].getBoundary() > (*hist)[1].getBoundary() )
-            {
-              *CmpCommon::diags() <<
-                DgSqlCode(CATALOG_HISTINTS_TABLES_CONTAIN_BAD_VALUES)
-		<< DgInt0(0)
-		<< DgInt1(1)
- 		<< DgString1(stats->getStatColumns()[0]->getFullColRefNameAsAnsiString().data() );
-
-		  stats->createFakeHist();
-		  continue ; // skip to next ColStats
-            }
-
-          // second, handle the case where first and second interval are the same
-          if ( hist->entries() > 1 && // avoid the exception! might just be a single NULL
-               //                     // interval after the loop above
-               (*hist)[0].getBoundary() == (*hist)[1].getBoundary() &&
-               (*hist)[1].getUec() > 1 )
-            {
-               const double KLUDGE_VALUE = 0.0001 ;
-               const double oldVal = (*hist)[0].getBoundary().getDblValue() ;
-               const EncodedValue newVal =
-                 EncodedValue(oldVal - (_ABSOLUTE_VALUE_(oldVal) * KLUDGE_VALUE)) ; // kludge alert!
-										//Absolute of oldval due to CR 10-010426-2457
-               (*hist)[0].setBoundary( newVal ) ;
-               (*hist)[0].setBoundIncl( FALSE ) ; // no longer a real boundary!
-               (*colStats_)[i]->setMinValue( newVal ) ; // set aggr info also
-             }
-          // done with first interval
-          // ----------------------------------------------------------------------
-
-          //
-          // NULL values must only be stored in single-valued intervals
-          // in the histograms ; so, just in case we're only getting
-          // *one* HistInt for the NULL interval, insert a 2nd one
-          //
-          // 0   1   2
-          // |   |   |
-          // |   |   |    entries() == 3
-          //         NULL
-          //
-          // 0   1   2   3
-          // |   |   |   |
-          // |   |   |   |    entries() == 4
-          //        new  NULL
-          //        NULL
-          //
-          if ( hist->lastHistInt().isNull() )
-            {
-              CollIndex count = hist->entries() ;
-              if ( !(*hist)[count-2].isNull() )
-              {
-                // insert a 2nd NULL HISTINT, with boundaryIncl value FALSE
-                HistInt secondLast (hist->lastHistInt().getBoundary(), FALSE) ;
-                hist->insertAt(count-1,secondLast) ;
-                // new HISTINT by default has row/uec of 0, which is what we want
-              }
-            }
-
-          //
-          // Now, reduce the total number of intervals to be the number
-          // that the user wants.  This is used to test the tradeoffs
-          // between compile time & rowcount estimation.
-          //
-          (*colStats_)[i]->setMaxIntervalCount (maxIntervalCount) ;
-          (*colStats_)[i]->reduceToMaxIntervalCount () ;
-
-	  if ((*colStats_)[i]->getRowcount() == (*colStats_)[i]->getTotalUec() )
-		(*colStats_)[i]->setAlmostUnique(TRUE);
-
-        } // outer for loop -- done with this COLSTATS, continue with next one
-      // ***********************************************************************
-
-      statsFetched_ = TRUE;
-      MonitorMemoryUsage_Exit((char*)mmPhase.data(), NULL, NULL, TRUE);
-    } // !statsFetched_
-
-    return (*colStats_);
-}
-
-StatsList &
-NATable::generateFakeStats()
-{
-  if (colStats_ == NULL)
-  {
-    //trying to get statistics for a new statement allocate colStats_
-    colStats_ = new (CmpCommon::statementHeap()) StatsList(CmpCommon::statementHeap());
-  }
-
-  if (colStats_->entries() > 0)
-    return (*colStats_);
-
-  NAColumnArray colList = getNAColumnArray() ;
-  double defaultFakeRowCount = (ActiveSchemaDB()->getDefaults()).getAsDouble(HIST_NO_STATS_ROWCOUNT);
-  double defaultFakeUec = (ActiveSchemaDB()->getDefaults()).getAsDouble(HIST_NO_STATS_UEC);
-
-  if ( isHiveTable() ) {
-      defaultFakeRowCount = getOriginalRowCount().value();
-  }
-
-  /*  if ( isHbaseTable() ) {
-      defaultFakeRowCount = getOriginalRowCount().value();
-  }
-  */
-
-  for (CollIndex i = 0; i < colList.entries(); i++ )
-  {
-    NAColumn * col = colList[i];
-
-    if (col->isUnique() )
-      defaultFakeUec = defaultFakeRowCount;
-    else
-      defaultFakeUec = MINOF(defaultFakeUec, defaultFakeRowCount);
-
-    EncodedValue dummyVal(0.0);
-
-    EncodedValue lowBound = dummyVal.minMaxValue(col->getType(), TRUE);
-    EncodedValue highBound = dummyVal.minMaxValue(col->getType(), FALSE);
-
-    HistogramSharedPtr emptyHist(new (HISTHEAP) Histogram(HISTHEAP));
-
-    HistInt newFirstHistInt(lowBound, FALSE);
-
-    HistInt newSecondHistInt(highBound, TRUE);
-
-    newSecondHistInt.setCardAndUec(defaultFakeRowCount,
-                                   defaultFakeUec);
-
-    emptyHist->insert(newFirstHistInt);
-    emptyHist->insert(newSecondHistInt);
-
-    ComUID histid(NA_JulianTimestamp());
-    ColStatsSharedPtr fakeColStats(
-                    new (HISTHEAP) ColStats(histid,
-                    defaultFakeUec,
-                    defaultFakeRowCount,
-                    defaultFakeRowCount,
-                    col->isUnique(),
-                    FALSE,
-                    emptyHist,
-                    FALSE,
-                    1.0,
-                    1.0,
-                    -1, // avg varchar size
-                    HISTHEAP));
-
-    fakeColStats->setFakeHistogram(TRUE);
-    fakeColStats->setOrigFakeHist(TRUE);
-    fakeColStats->setMinValue(lowBound);
-    fakeColStats->setMaxValue(highBound);
-    fakeColStats->statColumns().insert(col);
-
-    colStats_->insert(fakeColStats);
-  }
-  setStatsFetched(TRUE);
-  setOriginalRowCount(defaultFakeRowCount);
-
-  return (*colStats_);
-}
+	return (*colStats_);
+}
 
 NABoolean NATable::rowsArePacked() const
 {
-  // If one fileset is packed, they all are
-  return (getVerticalPartitionList().entries() &&
-          getVerticalPartitionList()[0]->isPacked());
+	// If one fileset is packed, they all are
+	return (getVerticalPartitionList().entries() &&
+			getVerticalPartitionList()[0]->isPacked());
 }
 
 // MV
 // Read materialized view information from the catalog manager.
 MVInfoForDML *NATable::getMVInfo(BindWA *bindWA)
 {
-  return mvInfo_;
+	return mvInfo_;
 }
 
 // MV
@@ -6584,43 +6587,43 @@ MVInfoForDML *NATable::getMVInfo(BindWA *bindWA)
 // If not initialized, keep a list and report error at runtime.
 NABoolean NATable::verifyMvIsInitializedAndAvailable(BindWA *bindWA) const
 {
-  CMPASSERT(isAnMV());
-  const ComMvAttributeBitmap& bitmap = getMvAttributeBitmap();
+	CMPASSERT(isAnMV());
+	const ComMvAttributeBitmap& bitmap = getMvAttributeBitmap();
 
-  // First check if the table is Unavailable.
-  NAString value;
-  if (bitmap.getIsMvUnAvailable())
-  {
+	// First check if the table is Unavailable.
+	NAString value;
+	if (bitmap.getIsMvUnAvailable())
+	{
 
-    // 12312 Materialized View $0~TableName is unavailable.
-    *CmpCommon::diags() << DgSqlCode(-12312)
-	  << DgTableName(getTableName().getQualifiedNameAsString());
-    bindWA->setErrStatus();
+		// 12312 Materialized View $0~TableName is unavailable.
+		*CmpCommon::diags() << DgSqlCode(-12312)
+			<< DgTableName(getTableName().getQualifiedNameAsString());
+		bindWA->setErrStatus();
 
-    return TRUE;
-  }
+		return TRUE;
+	}
 
-  // if the mv is uninitialized,
-  // add it to the uninitializedMvList in the BindWA
-  if (bitmap.getIsMvUnInitialized())
-  {
-    
-    // get physical and ansi names
-    NAString fileName(
-	 getClusteringIndex()->getFileSetName().getQualifiedNameAsString(),
-	 bindWA->wHeap() );
-    
-    NAString ansiName( getTableName().getQualifiedNameAsAnsiString(),
-		       bindWA->wHeap() );
-    
-    // get physical and ansi name
-    bindWA->addUninitializedMv(
-	 convertNAString( fileName, bindWA->wHeap() ),
-	 convertNAString( ansiName, bindWA->wHeap() ) );
-  }
+	// if the mv is uninitialized,
+	// add it to the uninitializedMvList in the BindWA
+	if (bitmap.getIsMvUnInitialized())
+	{
 
+		// get physical and ansi names
+		NAString fileName(
+				getClusteringIndex()->getFileSetName().getQualifiedNameAsString(),
+				bindWA->wHeap() );
 
-  return FALSE;
+		NAString ansiName( getTableName().getQualifiedNameAsAnsiString(),
+				bindWA->wHeap() );
+
+		// get physical and ansi name
+		bindWA->addUninitializedMv(
+				convertNAString( fileName, bindWA->wHeap() ),
+				convertNAString( ansiName, bindWA->wHeap() ) );
+	}
+
+
+	return FALSE;
 }
 
 // Return value: TRUE, found an index or constr. FALSE, not found.
@@ -6636,275 +6639,287 @@ NABoolean NATable::verifyMvIsInitializedAndAvailable(BindWA *bindWA) const
 //                            FALSE, accept any index that has the
 //                            same columns, in any sequence.
 NABoolean NATable::getCorrespondingIndex(NAList<NAString> &inputCols,
-					 NABoolean lookForExplicitIndex,
-					 NABoolean lookForUniqueIndex,
-					 NABoolean lookForPrimaryKey,
-					 NABoolean lookForAnyIndexOrPkey,
-                                         NABoolean lookForSameSequenceOfCols,
-                                         NABoolean excludeAlwaysComputedSystemCols,
-					 NAString *indexName)
+		NABoolean lookForExplicitIndex,
+		NABoolean lookForUniqueIndex,
+		NABoolean lookForPrimaryKey,
+		NABoolean lookForAnyIndexOrPkey,
+		NABoolean lookForSameSequenceOfCols,
+		NABoolean excludeAlwaysComputedSystemCols,
+		NAString *indexName)
 {
-  NABoolean indexFound = FALSE;
-  CollIndex numInputCols = inputCols.entries();
-
-  if (numInputCols == 0)
-    {
-      lookForPrimaryKey = TRUE;
-      lookForUniqueIndex = FALSE;
-      lookForAnyIndexOrPkey = FALSE;
-    }
-
-  Lng32 numBTpkeys = getClusteringIndex()->getIndexKeyColumns().entries();
-
-  const NAFileSetList &indexList = getIndexList();
-  for (Int32 i = 0; (NOT indexFound && (i < indexList.entries())); i++)
-    {
-      NABoolean isPrimaryKey = FALSE;
-      NABoolean isUniqueIndex = FALSE;
+	NABoolean indexFound = FALSE;
+	CollIndex numInputCols = inputCols.entries();
 
-      const NAFileSet * naf = indexList[i];
-      if (naf->getKeytag() == 0)
-	isPrimaryKey = TRUE;
-      else if (naf->uniqueIndex())
-	isUniqueIndex = TRUE;
-
-      if ((NOT lookForPrimaryKey) && (isPrimaryKey))
-	continue;
-
-      NABoolean found = FALSE;
-      if (lookForAnyIndexOrPkey)
-	found = TRUE;
-      else if (lookForPrimaryKey && isPrimaryKey)
-	found = TRUE;
-      else if (lookForUniqueIndex && isUniqueIndex)
-	found = TRUE;
-
-      if (found)
+	if (numInputCols == 0)
 	{
-	  if (lookForExplicitIndex)  // need an explicit index to match.
-	    {
-	      if ((naf->isCreatedExplicitly()) ||
-		  (isPrimaryKey))
-		found = TRUE;
-	      else
-		found = FALSE;
-	    }
+		lookForPrimaryKey = TRUE;
+		lookForUniqueIndex = FALSE;
+		lookForAnyIndexOrPkey = FALSE;
 	}
 
-      if (NOT found)
-	continue;
-
-      Int32 numMatchedCols = 0;
-      NABoolean allColsMatched = TRUE;
-
-      if (numInputCols > 0)
-        {
-          const NAColumnArray &nacArr = naf->getIndexKeyColumns();
-
-          Lng32 numKeyCols = naf->getCountOfColumns(
-               TRUE,           // exclude non-key cols
-               !isPrimaryKey,  // exclude cols other than user-specified index cols
-               FALSE,          // don't exclude all system cols like SYSKEY
-               excludeAlwaysComputedSystemCols);
+	Lng32 numBTpkeys = getClusteringIndex()->getIndexKeyColumns().entries();
 
-          // compare # of columns first and disqualify the index
-          // if it doesn't have the right number of columns
-          if (numInputCols != numKeyCols)
-            continue;
+	const NAFileSetList &indexList = getIndexList();
+	for (Int32 i = 0; (NOT indexFound && (i < indexList.entries())); i++)
+	{
+		NABoolean isPrimaryKey = FALSE;
+		NABoolean isUniqueIndex = FALSE;
+
+		const NAFileSet * naf = indexList[i];
+		if (naf->getKeytag() == 0)
+			isPrimaryKey = TRUE;
+		else if (naf->uniqueIndex())
+			isUniqueIndex = TRUE;
+
+		if ((NOT lookForPrimaryKey) && (isPrimaryKey))
+			continue;
+
+		NABoolean found = FALSE;
+		if (lookForAnyIndexOrPkey)
+			found = TRUE;
+		else if (lookForPrimaryKey && isPrimaryKey)
+			found = TRUE;
+		else if (lookForUniqueIndex && isUniqueIndex)
+			found = TRUE;
+
+		if (found)
+		{
+			if (lookForExplicitIndex)  // need an explicit index to match.
+			{
+				if ((naf->isCreatedExplicitly()) ||
+						(isPrimaryKey))
+					found = TRUE;
+				else
+					found = FALSE;
+			}
+		}
 
-          // compare individual key columns with the provided input columns
-          for (Int32 j = 0; j < nacArr.entries() && allColsMatched; j++)
-            {
-              NAColumn *nac = nacArr[j];
+		if (NOT found)
+			continue;
 
-              // exclude the same types of columns that we excluded in
-              // the call to naf->getCountOfColumns() above
-              if (!isPrimaryKey &&
-                  nac->getIndexColName() == nac->getColName())
-                conti

<TRUNCATED>


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

Posted by rm...@apache.org.
[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


[4/5] incubator-trafodion git commit: Merge branch 'master' into trafodion-2189

Posted by rm...@apache.org.
Merge branch 'master' into trafodion-2189

Conflicts:
	core/sql/optimizer/NATable.cpp
	core/sql/sqlcomp/PrivMgrDesc.h


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

Branch: refs/heads/master
Commit: b10bc1b0b03e3c13354fadcfb6fea56a6aab1f3f
Parents: 3b43772 66bc826
Author: Roberta Marton <rm...@edev07.esgyn.local>
Authored: Wed Oct 12 23:18:05 2016 +0000
Committer: Roberta Marton <rm...@edev07.esgyn.local>
Committed: Wed Oct 12 23:18:05 2016 +0000

----------------------------------------------------------------------
 .../SqlCompilerDebugger/ItemExpressionView.cpp  |   4 +-
 core/sql/arkcmp/CmpContext.cpp                  |   7 +-
 core/sql/arkcmp/CmpStatement.cpp                |   2 +
 core/sql/arkcmp/CmpStoredProc.cpp               |   2 +-
 core/sql/arkcmp/cmpargs.cpp                     |   2 +-
 core/sql/bin/SqlciErrors.txt                    |   2 +-
 core/sql/cli/CliExtern.cpp                      |  16 +-
 core/sql/cli/Context.cpp                        |  21 +-
 core/sql/cli/Globals.cpp                        |  17 +-
 core/sql/comexe/ComTdbSort.h                    |  10 +-
 core/sql/common/BloomFilter.cpp                 |   2 +-
 core/sql/common/ColIndList.h                    |   4 +-
 core/sql/common/Collections.cpp                 |   1 -
 core/sql/common/Collections.h                   |  47 ++-
 core/sql/common/ComExeTrace.cpp                 |   1 +
 core/sql/common/Ipc.h                           |   4 +-
 core/sql/common/NAMemory.cpp                    |   2 +-
 core/sql/common/NATestpoint.cpp                 |   3 +-
 core/sql/common/NATraceList.h                   |   2 +-
 core/sql/executor/ExHbaseAccess.cpp             |   1 +
 core/sql/executor/ExHbaseDDL.cpp                |   2 +-
 core/sql/executor/ex_sort.cpp                   |  16 +-
 core/sql/exp/ExpLOB.h                           |   4 +-
 core/sql/exp/ExpPCodeOptimizations.cpp          |   2 +-
 core/sql/exp/ExpPCodeOptsBulk.cpp               |   4 +-
 core/sql/exp/ExpPCodeOptsNativeExpr.cpp         |   2 +-
 core/sql/exp/exp_tuple_desc.cpp                 |  17 +-
 core/sql/export/ComDiags.cpp                    |   4 +-
 core/sql/generator/GenExplain.cpp               |   2 +-
 core/sql/generator/GenKey.cpp                   |   2 +-
 core/sql/generator/GenRelGrby.cpp               |   2 +-
 core/sql/generator/GenRelJoin.cpp               |   2 +-
 core/sql/generator/GenRelMisc.cpp               |   3 +-
 core/sql/generator/GenRelScan.cpp               |   2 +-
 core/sql/generator/GenRelUpdate.cpp             |  12 +-
 core/sql/generator/GenResources.cpp             |   2 +-
 core/sql/generator/Generator.cpp                |  16 +-
 core/sql/langman/LmRoutineJava.cpp              |   3 +-
 core/sql/langman/LmUtility.cpp                  |   2 +-
 core/sql/nskgmake/sort/Makefile                 |   3 +-
 core/sql/optimizer/Analyzer.cpp                 |  15 +-
 core/sql/optimizer/Analyzer.h                   |   5 +
 core/sql/optimizer/BindItemExpr.cpp             |   6 +-
 core/sql/optimizer/BindRI.cpp                   |   2 +-
 core/sql/optimizer/BindRelExpr.cpp              |  11 +-
 core/sql/optimizer/BindWA.cpp                   |   1 +
 core/sql/optimizer/BindWA.h                     |   2 +-
 core/sql/optimizer/CacheWA.cpp                  |   3 +
 core/sql/optimizer/ColStatDesc.cpp              |  20 +-
 core/sql/optimizer/ControlDB.cpp                |   8 +-
 core/sql/optimizer/EncodedValue.cpp             |   3 +-
 core/sql/optimizer/HDFSHook.cpp                 |   2 +-
 core/sql/optimizer/HbaseSearchSpec.h            |  52 +--
 core/sql/optimizer/ItemFuncUDF.h                |  11 +-
 core/sql/optimizer/ItemOther.h                  |   2 +-
 core/sql/optimizer/LargeScopeRules.cpp          |   4 +-
 core/sql/optimizer/MJVIndexBuilder.cpp          |  12 +-
 core/sql/optimizer/MVCandidates.cpp             |  10 +-
 core/sql/optimizer/MVInfo.cpp                   |  13 +-
 core/sql/optimizer/MVJoinGraph.cpp              |   5 +-
 core/sql/optimizer/MjvBuilder.cpp               |   2 +-
 core/sql/optimizer/MultiJoin.cpp                |   2 +-
 core/sql/optimizer/MvRefreshBuilder.cpp         |   4 +-
 core/sql/optimizer/NAClusterInfo.cpp            |   2 +-
 core/sql/optimizer/NATable.cpp                  | 215 ++++++-------
 core/sql/optimizer/NATable.h                    |   9 +-
 core/sql/optimizer/NodeMap.cpp                  |   2 +-
 core/sql/optimizer/NormRelExpr.cpp              |   8 +-
 core/sql/optimizer/NormWA.cpp                   |   4 +-
 core/sql/optimizer/NormWA.h                     |   8 +
 core/sql/optimizer/OptItemExpr.cpp              |   2 +-
 core/sql/optimizer/OptLogRelExpr.cpp            |   2 +-
 core/sql/optimizer/OptRange.cpp                 |   4 +-
 core/sql/optimizer/QRDescGenerator.cpp          |   2 +-
 core/sql/optimizer/QRDescGenerator.h            |   5 +-
 core/sql/optimizer/RETDesc.cpp                  |  10 +-
 core/sql/optimizer/Refresh.cpp                  |   2 +-
 core/sql/optimizer/RelExeUtil.h                 |   3 +-
 core/sql/optimizer/RelExpr.cpp                  |  29 +-
 core/sql/optimizer/RelPackedRows.cpp            |   2 +-
 core/sql/optimizer/RelRoutine.cpp               |   2 +-
 core/sql/optimizer/RelScan.h                    |   7 +-
 core/sql/optimizer/Rule.cpp                     |   4 +-
 core/sql/optimizer/ScanOptimizer.cpp            |   4 +-
 core/sql/optimizer/SchemaDB.cpp                 |   2 +-
 core/sql/optimizer/SearchKey.cpp                |   6 +-
 core/sql/optimizer/Stats.cpp                    |   3 +-
 core/sql/optimizer/Stats.h                      |  12 +-
 core/sql/optimizer/TableNameMap.h               |   3 +-
 core/sql/optimizer/TransRule.cpp                |   2 +-
 core/sql/optimizer/VEGTable.cpp                 |   6 +-
 core/sql/optimizer/ValueDesc.cpp                |   2 +-
 core/sql/optimizer/memo.cpp                     |   2 +-
 core/sql/parser/ElemDDLHbaseOptions.h           |   3 +-
 core/sql/parser/SqlParserAux.cpp                |   6 +-
 core/sql/parser/StmtDDLCreate.cpp               |   6 +-
 core/sql/parser/sqlparser.y                     |  36 +--
 core/sql/qmscommon/QRLogger.cpp                 |   6 +
 core/sql/qmscommon/Range.cpp                    |   3 +-
 core/sql/qmscommon/Range.h                      |   3 +-
 core/sql/regress/compGeneral/DIFF042.KNOWN      |  36 +--
 core/sql/regress/compGeneral/EXPECTED001.SB     |   2 +-
 core/sql/runtimestats/ssmpipc.cpp               |   5 +-
 core/sql/sort/Qsort.h                           |   5 +-
 core/sql/sort/Record.cpp                        |  14 +-
 core/sql/sort/Record.h                          |   8 +
 core/sql/sort/SortTopN.cpp                      | 318 +++++++++++++++++++
 core/sql/sort/SortTopN.h                        |  89 ++++++
 core/sql/sort/SortUtil.cpp                      |  78 +++--
 core/sql/sort/SortUtil.h                        |   2 +-
 core/sql/sort/SortUtilCfg.cpp                   |  43 +--
 core/sql/sort/SortUtilCfg.h                     |  11 +-
 core/sql/sqlcomp/CmpDescribe.cpp                |   4 +-
 core/sql/sqlcomp/CmpSeabaseDDLcommon.cpp        |  10 +-
 core/sql/sqlcomp/CmpSeabaseDDLindex.cpp         |   8 +-
 core/sql/sqlcomp/CmpSeabaseDDLrepos.cpp         |   4 +-
 core/sql/sqlcomp/CmpSeabaseDDLtable.cpp         |  36 +--
 core/sql/sqlcomp/CmpSeabaseDDLview.cpp          |   4 +-
 core/sql/sqlcomp/DefaultConstants.h             |   1 +
 core/sql/sqlcomp/PrivMgrCommands.cpp            |   4 +-
 core/sql/sqlcomp/PrivMgrDesc.h                  |   6 +-
 core/sql/sqlcomp/PrivMgrPrivileges.cpp          |   8 +-
 core/sql/sqlcomp/QCache.cpp                     |   2 +-
 core/sql/sqlcomp/QCache.h                       |   1 +
 core/sql/sqlcomp/nadefaults.cpp                 |   2 +
 core/sql/sqlcomp/parser.cpp                     |   5 +-
 core/sql/sqlmsg/GetErrorMessage.cpp             |   2 +-
 core/sql/sqlmxevents/logmxevent_traf.cpp        |   2 +-
 .../java/org/trafodion/sql/HBaseClient.java     |  13 +-
 core/sql/udrserv/spinfo.cpp                     |   3 +-
 core/sql/ustat/hs_cli.cpp                       |   2 +-
 core/sql/ustat/hs_parser.cpp                    |   4 +-
 .../src/asciidoc/_chapters/binder_msgs.adoc     | 102 +++---
 docs/messages_guide/src/asciidoc/index.adoc     |   1 +
 install/installer/traf_sqconfig                 |   5 +-
 135 files changed, 1125 insertions(+), 589 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/b10bc1b0/core/sql/optimizer/BindRelExpr.cpp
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/b10bc1b0/core/sql/optimizer/NATable.cpp
----------------------------------------------------------------------
diff --cc core/sql/optimizer/NATable.cpp
index 24cfbf3,b240f17..67ebadd
--- a/core/sql/optimizer/NATable.cpp
+++ b/core/sql/optimizer/NATable.cpp
@@@ -5360,110 -5360,110 +5361,109 @@@ NABoolean createNAFileSets(TrafDesc * t
    //
    TrafDesc *view_desc = table_desc->tableDesc()->views_desc;
    if (view_desc)
 -    {
 -      viewText_ = new (heap_) char[strlen(view_desc->viewDesc()->viewtext) + 2];
 -      strcpy(viewText_, view_desc->viewDesc()->viewtext);
 -      strcat(viewText_, ";");
 -
 -      viewTextCharSet_ = (CharInfo::CharSet)view_desc->viewDesc()->viewtextcharset;
 -
 -      viewCheck_    = NULL; //initialize
 -      if(view_desc->viewDesc()->viewchecktext){
 -        UInt32 viewCheckLength = str_len(view_desc->viewDesc()->viewchecktext)+1;
 -        viewCheck_ = new (heap_) char[ viewCheckLength];
 -        memcpy(viewCheck_, view_desc->viewDesc()->viewchecktext,
 -               viewCheckLength);
 -      }
 -
 -      viewColUsages_ = NULL;
 -      if(view_desc->viewDesc()->viewcolusages){
 -        viewColUsages_ = new (heap_) NAList<ComViewColUsage *>(heap_); //initialize empty list
 -        char * beginStr (view_desc->viewDesc()->viewcolusages);
 -        char * endStr = strchr(beginStr, ';');
 -        while (endStr != NULL) {
 -          ComViewColUsage *colUsage = new (heap_) ComViewColUsage;
 -          NAString currentUsage(beginStr, endStr - beginStr + 1); 
 -          colUsage->unpackUsage (currentUsage.data());
 -          viewColUsages_->insert(colUsage);
 -          beginStr = endStr+1;
 -          endStr = strchr(beginStr, ';');
 -        }
 -      }
 +  {
 +	  viewText_ = new (heap_) char[strlen(view_desc->viewDesc()->viewtext) + 2];
 +	  strcpy(viewText_, view_desc->viewDesc()->viewtext);
 +	  strcat(viewText_, ";");
 +
 +	  viewTextCharSet_ = (CharInfo::CharSet)view_desc->viewDesc()->viewtextcharset;
 +
 +	  viewCheck_    = NULL; //initialize
 +	  if(view_desc->viewDesc()->viewchecktext){
 +		  UInt32 viewCheckLength = str_len(view_desc->viewDesc()->viewchecktext)+1;
 +		  viewCheck_ = new (heap_) char[ viewCheckLength];
 +		  memcpy(viewCheck_, view_desc->viewDesc()->viewchecktext,
 +				  viewCheckLength);
 +	  }
  
 -      setUpdatable(view_desc->viewDesc()->isUpdatable());
 -      setInsertable(view_desc->viewDesc()->isInsertable());
 +	  viewColUsages_ = NULL;
 +	  if(view_desc->viewDesc()->viewcolusages){
- 		  viewColUsages_ = new (heap_) NAList<ComViewColUsage *>; //initialize empty list
++		  viewColUsages_ = new (heap_) NAList<ComViewColUsage *>(heap_); //initialize empty list
 +		  char * beginStr (view_desc->viewDesc()->viewcolusages);
 +		  char * endStr = strchr(beginStr, ';');
 +		  while (endStr != NULL) {
 +			  ComViewColUsage *colUsage = new (heap_) ComViewColUsage;
 +			  NAString currentUsage(beginStr, endStr - beginStr + 1); 
 +			  colUsage->unpackUsage (currentUsage.data());
 +			  viewColUsages_->insert(colUsage);
 +			  beginStr = endStr+1;
 +			  endStr = strchr(beginStr, ';');
 +		  }
 +	  }
- 
 +	  setUpdatable(view_desc->viewDesc()->isUpdatable());
 +	  setInsertable(view_desc->viewDesc()->isInsertable());
  
 -      //
 -      // The updatable flag is false for an MP view only if it is NOT a
 -      // protection view. Therefore updatable == FALSE iff it is a
 -      // shorthand view. See ReadTableDef.cpp, l. 3379.
 -      //
 +	  //
 +	  // The updatable flag is false for an MP view only if it is NOT a
 +	  // protection view. Therefore updatable == FALSE iff it is a
 +	  // shorthand view. See ReadTableDef.cpp, l. 3379.
 +	  //
  
 -      viewFileName_ = NULL;
 -      CMPASSERT(view_desc->viewDesc()->viewfilename);
 -      UInt32 viewFileNameLength = str_len(view_desc->viewDesc()->viewfilename) + 1;
 -      viewFileName_ = new (heap_) char[viewFileNameLength];
 -      memcpy(viewFileName_, view_desc->viewDesc()->viewfilename,
 -	     viewFileNameLength);
 -    }
 +	  viewFileName_ = NULL;
 +	  CMPASSERT(view_desc->viewDesc()->viewfilename);
 +	  UInt32 viewFileNameLength = str_len(view_desc->viewDesc()->viewfilename) + 1;
 +	  viewFileName_ = new (heap_) char[viewFileNameLength];
 +	  memcpy(viewFileName_, view_desc->viewDesc()->viewfilename,
 +			  viewFileNameLength);
 +  }
    else
 -    {
 -      //keep track of memory used by NAFileSets
 -      Lng32 preCreateNAFileSetsMemSize = heap_->getAllocSize();
 +  {
 +	  //keep track of memory used by NAFileSets
 +	  Lng32 preCreateNAFileSetsMemSize = heap_->getAllocSize();
  
 -      //
 -      // Process indexes and vertical partitions for this table.
 -      //
 -      if (createNAFileSets(table_desc       /*IN*/,
 -                           this             /*IN*/,
 -                           colArray_        /*IN*/,
 -                           indexes_         /*OUT*/,
 -                           vertParts_       /*OUT*/,
 -                           clusteringIndex_ /*OUT*/,
 -			   tableIdList_     /*OUT*/,
 -                           heap_,
 -                           bindWA,
 -                           newColumns_,     /*OUT*/
 -			   maxIndexLevelsPtr)) {
 -        return; // colcount_ == 0 indicates an error
 -      }
 +	  //
 +	  // Process indexes and vertical partitions for this table.
 +	  //
 +	  if (createNAFileSets(table_desc       /*IN*/,
 +				  this             /*IN*/,
 +				  colArray_        /*IN*/,
 +				  indexes_         /*OUT*/,
 +				  vertParts_       /*OUT*/,
 +				  clusteringIndex_ /*OUT*/,
 +				  tableIdList_     /*OUT*/,
 +				  heap_,
 +				  bindWA,
 +				  newColumns_,     /*OUT*/
 +				  maxIndexLevelsPtr)) {
 +		  return; // colcount_ == 0 indicates an error
 +	  }
  
 -      // Add constraint info.
 -      //
 -      // This call to createConstraintInfo, calls the parser on
 -      // the constraint name
 -      //
 -      
 -      NABoolean  errorOccurred =
 -        createConstraintInfo(table_desc        /*IN*/,
 -                             getTableName()    /*IN*/,
 -                             getNAColumnArray()/*IN (some columns updated)*/,
 -                             checkConstraints_ /*OUT*/,
 -                             uniqueConstraints_/*OUT*/,
 -                             refConstraints_   /*OUT*/,
 -                             heap_,
 -                             bindWA);
 -      
 -      if (errorOccurred) {
 -        // return before setting colcount_, indicating that there
 -        // was an error in constructing this NATable.
 -        //
 -        return;
 -      }
 -      
 -      //
 -      // FetchHistograms call used to be here -- moved to getStatistics().
 -      //
 -    }
 -  
 -    // change partFunc for base table if PARTITION clause has been used
 -    // to limit the number of partitions that will be accessed.
 -    if ((qualifiedName_.isPartitionNameSpecified()) ||
 -	(qualifiedName_.isPartitionRangeSpecified())) {
 -      if (filterUnusedPartitions(corrName.getPartnClause())) {
 -	return ;
 -      }
 -    }
 +	  // Add constraint info.
 +	  //
 +	  // This call to createConstraintInfo, calls the parser on
 +	  // the constraint name
 +	  //
 +
 +	  NABoolean  errorOccurred =
 +		  createConstraintInfo(table_desc        /*IN*/,
 +				  getTableName()    /*IN*/,
 +				  getNAColumnArray()/*IN (some columns updated)*/,
 +				  checkConstraints_ /*OUT*/,
 +				  uniqueConstraints_/*OUT*/,
 +				  refConstraints_   /*OUT*/,
 +				  heap_,
 +				  bindWA);
 +
 +	  if (errorOccurred) {
 +		  // return before setting colcount_, indicating that there
 +		  // was an error in constructing this NATable.
 +		  //
 +		  return;
 +	  }
 +
 +	  //
 +	  // FetchHistograms call used to be here -- moved to getStatistics().
 +	  //
 +  }
 +
 +  // change partFunc for base table if PARTITION clause has been used
 +  // to limit the number of partitions that will be accessed.
 +  if ((qualifiedName_.isPartitionNameSpecified()) ||
 +		  (qualifiedName_.isPartitionRangeSpecified())) {
 +	  if (filterUnusedPartitions(corrName.getPartnClause())) {
 +		  return ;
 +	  }
 +  }
  
    //
    // Set colcount_ after all possible errors (Binder uses nonzero colcount
@@@ -5773,267 -5771,268 +5773,268 @@@
  
  // Constructor for a Hive table
  NATable::NATable(BindWA *bindWA,
- 		const CorrName& corrName,
- 		NAMemory *heap,
- 		struct hive_tbl_desc* htbl)
- 	//
- 	// The NATable heap ( i.e. heap_ ) used to come from ContextHeap
- 	// (i.e. heap) but it creates high memory usage/leakage in Context
- 	// Heap. Although the NATables are deleted at the end of each statement,
- 	// the heap_ is returned to heap (i.e. context heap) which caused
- 	// context heap containing a lot of not used chunk of memory. So it is
- 	// changed to be from whatever heap is passed in at the call in
- 	// NATableDB.getNATable.
- 	//
- 	// Now NATable objects can be cached.If an object is to be cached (persisted
- 	// across statements) a NATable heap is allocated for the object
- 	// and is passed in (this is done in NATableDB::get(CorrName& corrName...).
- 	// Otherwise a reference to the Statement heap is passed in. When a cached
- 	// object is to be deleted the object's heap is deleted which wipes out the
- 	// NATable object all its related stuff. NATable objects that are not cached
- 	// are wiped out at the end of the statement when the statement heap is deleted.
- 	//
- 	: heap_(heap),
- 	referenceCount_(0),
- 	refsIncompatibleDP2Halloween_(FALSE),
- 	isHalloweenTable_(FALSE),
- 	qualifiedName_(corrName.getExtendedQualNameObj(),heap),
- 	synonymReferenceName_(heap),
- 	fileSetName_(corrName.getQualifiedNameObj(),heap),   // for now, set equal
- 	clusteringIndex_(NULL),
- 	colcount_(0),
- 	colArray_(heap),
- 	recordLength_(0),
- 	indexes_(heap),
- 	vertParts_(heap),
- 	colStats_(NULL),
- 	statsFetched_(FALSE),
- 	viewFileName_(NULL),
- 	viewText_(NULL),
- 	viewTextInNAWchars_(heap),
- 	viewTextCharSet_(CharInfo::UnknownCharSet),
- 	viewCheck_(NULL),
- 	viewColUsages_(NULL),
- 	flags_(IS_INSERTABLE | IS_UPDATABLE),
- 	insertMode_(COM_REGULAR_TABLE_INSERT_MODE),
- 	isSynonymTranslationDone_(FALSE),
- 	checkConstraints_(heap),
- 	createTime_(htbl->creationTS_),
- 	redefTime_(htbl->redeftime()),
- 	cacheTime_(0),
- 	statsTime_(0),
- 	catalogUID_(0),
- 	schemaUID_(0),
- 	objectUID_(0),
- 	objectType_(COM_UNKNOWN_OBJECT),
- 	partitioningScheme_(COM_UNKNOWN_PARTITIONING),
- 	uniqueConstraints_(heap),
- 	refConstraints_(heap),
- 	isAnMV_(FALSE),
- 	isAnMVMetaData_(FALSE),
- 	mvsUsingMe_(heap),
- 	mvInfo_(NULL),
- 	accessedInCurrentStatement_(TRUE),
- 	setupForStatement_(FALSE),
- 	resetAfterStatement_(FALSE),
- 	hitCount_(0),
- 	replacementCounter_(2),
- 	sizeInCache_(0),
- 	recentlyUsed_(TRUE),
- 	tableConstructionHadWarnings_(FALSE),
- 	isAnMPTableWithAnsiName_(FALSE),
- 	isUMDTable_(FALSE),
- 	isSMDTable_(FALSE),
- 	isMVUMDTable_(FALSE),
- 
- 	// For virtual tables, we set the object schema version
- 	// to be the current schema version
- 	osv_(COM_VERS_CURR_SCHEMA),
- 	ofv_(COM_VERS_CURR_SCHEMA),
- 	partnsDesc_(NULL),
- 	colsWithMissingStats_(NULL),
- 	originalCardinality_(-1.0),
- 	tableIdList_(heap),
- 	rcb_(NULL),
- 	rcbLen_(0),
- 	keyLength_(0),
- 	parentTableName_(NULL),
- 	sgAttributes_(NULL),
- 	isHive_(TRUE),
- 	isHbase_(FALSE),
- 	isHbaseCell_(FALSE),
- 	isHbaseRow_(FALSE),
- 	isSeabase_(FALSE),
- 	isSeabaseMD_(FALSE),
- 	isSeabasePrivSchemaTable_(FALSE),
- 	isUserUpdatableSeabaseMD_(FALSE),
- 	resetHDFSStatsAfterStmt_(FALSE),
- 	hiveDefaultStringLen_(0),
- 	hiveTableId_(htbl->tblID_),
- 	tableDesc_(NULL),
- 	secKeySet_(heap),
- 	privInfo_(NULL),
- 	newColumns_(heap),
- 	snapshotName_(NULL)
+                  const CorrName& corrName,
+ 		 NAMemory *heap,
+ 		 struct hive_tbl_desc* htbl)
+   //
+   // The NATable heap ( i.e. heap_ ) used to come from ContextHeap
+   // (i.e. heap) but it creates high memory usage/leakage in Context
+   // Heap. Although the NATables are deleted at the end of each statement,
+   // the heap_ is returned to heap (i.e. context heap) which caused
+   // context heap containing a lot of not used chunk of memory. So it is
+   // changed to be from whatever heap is passed in at the call in
+   // NATableDB.getNATable.
+   //
+   // Now NATable objects can be cached.If an object is to be cached (persisted
+   // across statements) a NATable heap is allocated for the object
+   // and is passed in (this is done in NATableDB::get(CorrName& corrName...).
+   // Otherwise a reference to the Statement heap is passed in. When a cached
+   // object is to be deleted the object's heap is deleted which wipes out the
+   // NATable object all its related stuff. NATable objects that are not cached
+   // are wiped out at the end of the statement when the statement heap is deleted.
+   //
+   : heap_(heap),
+     referenceCount_(0),
+     refsIncompatibleDP2Halloween_(FALSE),
+     isHalloweenTable_(FALSE),
+     qualifiedName_(corrName.getExtendedQualNameObj(),heap),
+     synonymReferenceName_(heap),
+     fileSetName_(corrName.getQualifiedNameObj(),heap),   // for now, set equal
+     clusteringIndex_(NULL),
+     colcount_(0),
+     colArray_(heap),
+     recordLength_(0),
+     indexes_(heap),
+     vertParts_(heap),
+     colStats_(NULL),
+     statsFetched_(FALSE),
+     viewFileName_(NULL),
+     viewText_(NULL),
+     viewTextInNAWchars_(heap),
+     viewTextCharSet_(CharInfo::UnknownCharSet),
+     viewCheck_(NULL),
+     viewColUsages_(NULL),
+     flags_(IS_INSERTABLE | IS_UPDATABLE),
+     insertMode_(COM_REGULAR_TABLE_INSERT_MODE),
+     isSynonymTranslationDone_(FALSE),
+     checkConstraints_(heap),
+     createTime_(htbl->creationTS_),
+     redefTime_(htbl->redeftime()),
+     cacheTime_(0),
+     statsTime_(0),
+     catalogUID_(0),
+     schemaUID_(0),
+     objectUID_(0),
+     objectType_(COM_UNKNOWN_OBJECT),
+     partitioningScheme_(COM_UNKNOWN_PARTITIONING),
+     uniqueConstraints_(heap),
+     refConstraints_(heap),
+     isAnMV_(FALSE),
+     isAnMVMetaData_(FALSE),
+     mvsUsingMe_(heap),
+     mvInfo_(NULL),
+     accessedInCurrentStatement_(TRUE),
+     setupForStatement_(FALSE),
+     resetAfterStatement_(FALSE),
+     hitCount_(0),
+     replacementCounter_(2),
+     sizeInCache_(0),
+     recentlyUsed_(TRUE),
+     tableConstructionHadWarnings_(FALSE),
+     isAnMPTableWithAnsiName_(FALSE),
+     isUMDTable_(FALSE),
+     isSMDTable_(FALSE),
+     isMVUMDTable_(FALSE),
+ 
+     // For virtual tables, we set the object schema version
+     // to be the current schema version
+     osv_(COM_VERS_CURR_SCHEMA),
+     ofv_(COM_VERS_CURR_SCHEMA),
+     partnsDesc_(NULL),
+     colsWithMissingStats_(NULL),
+     originalCardinality_(-1.0),
+     tableIdList_(heap),
+     rcb_(NULL),
+     rcbLen_(0),
+     keyLength_(0),
+     parentTableName_(NULL),
+     sgAttributes_(NULL),
+     isHive_(TRUE),
+     isHbase_(FALSE),
+     isHbaseCell_(FALSE),
+     isHbaseRow_(FALSE),
+     isSeabase_(FALSE),
+     isSeabaseMD_(FALSE),
+     isSeabasePrivSchemaTable_(FALSE),
+     isUserUpdatableSeabaseMD_(FALSE),
+     resetHDFSStatsAfterStmt_(FALSE),
+     hiveDefaultStringLen_(0),
+     hiveTableId_(htbl->tblID_),
+     tableDesc_(NULL),
+     secKeySet_(heap),
+     privInfo_(NULL),
+     newColumns_(heap),
+     snapshotName_(NULL),
+     allColFams_(heap)
  {
  
 -  NAString tblName = qualifiedName_.getQualifiedNameObj().getQualifiedNameAsString();
 -  NAString mmPhase;
 -
 -  Lng32 preCreateNATableWarnings = CmpCommon::diags()->getNumber(DgSqlCode::WARNING_);
 -
 -  //set heap type
 -  if(heap_ == CmpCommon::statementHeap()){
 -    heapType_ = STATEMENT;
 -    mmPhase = "NATable Init (Stmt) - " + tblName;
 -  }else if (heap_ == CmpCommon::contextHeap()){
 -    heapType_ = CONTEXT;
 -    mmPhase = "NATable Init (Cnxt) - " + tblName;
 -  }else {
 -    heapType_ = OTHER;
 -    mmPhase = "NATable Init (Other) - " + tblName;
 -  }
 +	NAString tblName = qualifiedName_.getQualifiedNameObj().getQualifiedNameAsString();
 +	NAString mmPhase;
 +
 +	Lng32 preCreateNATableWarnings = CmpCommon::diags()->getNumber(DgSqlCode::WARNING_);
 +
 +	//set heap type
 +	if(heap_ == CmpCommon::statementHeap()){
 +		heapType_ = STATEMENT;
 +		mmPhase = "NATable Init (Stmt) - " + tblName;
 +	}else if (heap_ == CmpCommon::contextHeap()){
 +		heapType_ = CONTEXT;
 +		mmPhase = "NATable Init (Cnxt) - " + tblName;
 +	}else {
 +		heapType_ = OTHER;
 +		mmPhase = "NATable Init (Other) - " + tblName;
 +	}
  
 -  MonitorMemoryUsage_Enter((char*)mmPhase.data(), heap_, TRUE);
 +	MonitorMemoryUsage_Enter((char*)mmPhase.data(), heap_, TRUE);
  
  
 -  isTrigTempTable_ = FALSE;
 +	isTrigTempTable_ = FALSE;
  
  
 -  insertMode_ = 
 -     COM_MULTISET_TABLE_INSERT_MODE; // allow dup, to check
 -     //ComInsertMode::COM_MULTISET_TABLE_INSERT_MODE; // allow dup, to check
 +	insertMode_ = 
 +		COM_MULTISET_TABLE_INSERT_MODE; // allow dup, to check
 +	//ComInsertMode::COM_MULTISET_TABLE_INSERT_MODE; // allow dup, to check
  
 -  //
 -  // Add timestamp information.
 -  //
 +	//
 +	// Add timestamp information.
 +	//
  
 -  // To get from Hive
 -/*
 -  createTime_ = longArrayToInt64(table_desc->tableDesc()->createtime);
 -  redefTime_  = longArrayToInt64(table_desc->tableDesc()->redeftime);
 -  cacheTime_  = longArrayToInt64(table_desc->tableDesc()->cachetime);
 -*/
 +	// To get from Hive
 +	/*
 +	   createTime_ = longArrayToInt64(table_desc->tableDesc()->createtime);
 +	   redefTime_  = longArrayToInt64(table_desc->tableDesc()->redeftime);
 +	   cacheTime_  = longArrayToInt64(table_desc->tableDesc()->cachetime);
 +	   */
  
 -  // NATable has a schemaUID column, probably should propogate it.
 -  // for now, set to 0.
 -  schemaUID_ = 0;
 +	// NATable has a schemaUID column, probably should propogate it.
 +	// for now, set to 0.
 +	schemaUID_ = 0;
  
 -  // Set the objectUID_
 -  // If the HIVE table has been registered in Trafodion, get the objectUID
 -  // from Trafodion, otherwise, set it to 0.
 -  // TBD - does getQualifiedNameObj handle delimited names correctly?
 -  if ( !fetchObjectUIDForNativeTable(corrName) )
 -     return;
 +	// Set the objectUID_
 +	// If the HIVE table has been registered in Trafodion, get the objectUID
 +	// from Trafodion, otherwise, set it to 0.
 +	// TBD - does getQualifiedNameObj handle delimited names correctly?
 +	if ( !fetchObjectUIDForNativeTable(corrName) )
 +		return;
  
 -  if ( objectUID_ > 0 )
 -    setHasExternalTable(TRUE);
 +	if ( objectUID_ > 0 )
 +		setHasExternalTable(TRUE);
  
 -  // for HIVE objects, the schema owner and table owner is HIVE_ROLE_ID
 -  if (CmpCommon::context()->isAuthorizationEnabled())
 -  {
 -    owner_ = HIVE_ROLE_ID;
 -    schemaOwner_ = HIVE_ROLE_ID;
 -  }
 -  else
 -  {
 -     owner_ = SUPER_USER;
 -     schemaOwner_ = SUPER_USER;
 -  }
 +	// for HIVE objects, the schema owner and table owner is HIVE_ROLE_ID
 +	if (CmpCommon::context()->isAuthorizationEnabled())
 +	{
 +		owner_ = HIVE_ROLE_ID;
 +		schemaOwner_ = HIVE_ROLE_ID;
 +	}
 +	else
 +	{
 +		owner_ = SUPER_USER;
 +		schemaOwner_ = SUPER_USER;
 +	}
  
 -  if (hasExternalTable())
 -    getPrivileges(NULL); 
 +	if (hasExternalTable())
 +		getPrivileges(NULL); 
  
 -  // TBD - if authorization is enabled and there is no external table to store
 -  // privileges, go get privilege information from HIVE metadata ...
 -  
 -  // TBD - add a check to verify that the column list coming from HIVE matches
 -  // the column list stored in the external table.  Maybe some common method
 -  // that can be used to compare other things as well...
 - 
 -  objectType_ = COM_BASE_TABLE_OBJECT;
 +	// TBD - if authorization is enabled and there is no external table to store
 +	// privileges, go get privilege information from HIVE metadata ...
  
 -// to check
 -  partitioningScheme_ = COM_UNKNOWN_PARTITIONING;
 +	// TBD - add a check to verify that the column list coming from HIVE matches
 +	// the column list stored in the external table.  Maybe some common method
 +	// that can be used to compare other things as well...
  
 -// to check
 -  rcb_ = 0;
 -  rcbLen_ = 0;
 -  keyLength_ = 0;
 +	objectType_ = COM_BASE_TABLE_OBJECT;
  
 -  partnsDesc_ = NULL;
 +	// to check
 +	partitioningScheme_ = COM_UNKNOWN_PARTITIONING;
  
 -  //
 -  // Insert a NAColumn in the colArray_ for this NATable for each
 -  // columns_desc from the ARK SMD. Returns TRUE if error creating NAColumns.
 -  //
 +	// to check
 +	rcb_ = 0;
 +	rcbLen_ = 0;
 +	keyLength_ = 0;
  
 -  if (createNAColumns(htbl->getColumns(),
 -		      this,
 -		      colArray_ /*OUT*/,
 -		      heap_))
 -    //coverity[leaked_storage]
 -    return;
 +	partnsDesc_ = NULL;
  
 +	//
 +	// Insert a NAColumn in the colArray_ for this NATable for each
 +	// columns_desc from the ARK SMD. Returns TRUE if error creating NAColumns.
 +	//
  
 -  //
 -  // Set colcount_ after all possible errors (Binder uses nonzero colcount
 -  // as an indicator of valid table definition).
 -  //
 +	if (createNAColumns(htbl->getColumns(),
 +				this,
 +				colArray_ /*OUT*/,
 +				heap_))
 +		//coverity[leaked_storage]
 +		return;
  
 -  // To set it via the new createNAColumns()
 -  colcount_ = colArray_.entries();
  
 -  // compute record length from colArray
 +	//
 +	// Set colcount_ after all possible errors (Binder uses nonzero colcount
 +	// as an indicator of valid table definition).
 +	//
  
 -  Int32 recLen = 0;
 -  for ( CollIndex i=0; i<colcount_; i++ ) {
 -    recLen += colArray_[i]->getType()->getNominalSize();
 -  } 
 +	// To set it via the new createNAColumns()
 +	colcount_ = colArray_.entries();
  
 -  setRecordLength(recLen);
 -
 -  if (createNAFileSets(htbl             /*IN*/,
 -                       this             /*IN*/,
 -                       colArray_        /*IN*/,
 -                           indexes_         /*OUT*/,
 -                           vertParts_       /*OUT*/,
 -                           clusteringIndex_ /*OUT*/,
 -                           tableIdList_     /*OUT*/,
 -                           heap_,
 -                           bindWA
 -                           )) {
 -    colcount_ = 0; // indicates failure
 -    return;
 -  }
 +	// compute record length from colArray
  
 -  // HIVE-TBD ignore constraint info creation for now
 +	Int32 recLen = 0;
 +	for ( CollIndex i=0; i<colcount_; i++ ) {
 +		recLen += colArray_[i]->getType()->getNominalSize();
 +	} 
  
 +	setRecordLength(recLen);
  
 -  // If there is a host variable associated with this table, store it
 -  // for use by the generator to generate late-name resolution information.
 -  //
 -  HostVar *hv = corrName.getPrototype();
 -  prototype_ = hv ? new (heap_) HostVar(*hv) : NULL;
 +	if (createNAFileSets(htbl             /*IN*/,
 +				this             /*IN*/,
 +				colArray_        /*IN*/,
 +				indexes_         /*OUT*/,
 +				vertParts_       /*OUT*/,
 +				clusteringIndex_ /*OUT*/,
 +				tableIdList_     /*OUT*/,
 +				heap_,
 +				bindWA
 +			    )) {
 +		colcount_ = 0; // indicates failure
 +		return;
 +	}
  
 -  // MV
 -  // Initialize the MV support data members
 -  isAnMV_           = FALSE;
 -  isAnMVMetaData_   = FALSE;
 +	// HIVE-TBD ignore constraint info creation for now
  
 -  Lng32 postCreateNATableWarnings = CmpCommon::diags()->getNumber(DgSqlCode::WARNING_);
  
 -  if(postCreateNATableWarnings != preCreateNATableWarnings)
 -    tableConstructionHadWarnings_=TRUE;
 +	// If there is a host variable associated with this table, store it
 +	// for use by the generator to generate late-name resolution information.
 +	//
 +	HostVar *hv = corrName.getPrototype();
 +	prototype_ = hv ? new (heap_) HostVar(*hv) : NULL;
  
 -  hiveDefaultStringLen_ = CmpCommon::getDefaultLong(HIVE_MAX_STRING_LENGTH);
 -  Int32 hiveDefaultStringLenInBytes = CmpCommon::getDefaultLong(HIVE_MAX_STRING_LENGTH_IN_BYTES);
 -  if( hiveDefaultStringLenInBytes != 32000 ) 
 -      hiveDefaultStringLen_ = hiveDefaultStringLenInBytes;
 +	// MV
 +	// Initialize the MV support data members
 +	isAnMV_           = FALSE;
 +	isAnMVMetaData_   = FALSE;
  
 -// LCOV_EXCL_STOP
 -  initialSize_ = heap_->getAllocSize();
 -  MonitorMemoryUsage_Exit((char*)mmPhase.data(), heap_, NULL, TRUE);
 +	Lng32 postCreateNATableWarnings = CmpCommon::diags()->getNumber(DgSqlCode::WARNING_);
 +
 +	if(postCreateNATableWarnings != preCreateNATableWarnings)
 +		tableConstructionHadWarnings_=TRUE;
 +
 +	hiveDefaultStringLen_ = CmpCommon::getDefaultLong(HIVE_MAX_STRING_LENGTH);
 +	Int32 hiveDefaultStringLenInBytes = CmpCommon::getDefaultLong(HIVE_MAX_STRING_LENGTH_IN_BYTES);
 +	if( hiveDefaultStringLenInBytes != 32000 ) 
 +		hiveDefaultStringLen_ = hiveDefaultStringLenInBytes;
 +
 +	// LCOV_EXCL_STOP
 +	initialSize_ = heap_->getAllocSize();
 +	MonitorMemoryUsage_Exit((char*)mmPhase.data(), heap_, NULL, TRUE);
  } // NATable()
  #pragma warn(770)  // warning elimination
  
@@@ -6890,36 -6885,28 +6891,36 @@@ void NATable::getPrivileges(TrafDesc * 
    if (CmpSeabaseDDL::isSeabasePrivMgrMD
         (qualifiedName_.getQualifiedNameObj().getCatalogName(),
          qualifiedName_.getQualifiedNameObj().getSchemaName()))
 +
 +  {
      isSeabasePrivSchemaTable_ = TRUE;
-     return;
++   return;
 +  }
  
 -  if ((!isSeabaseTable() && !isHiveTable()) ||
 -      !CmpCommon::context()->isAuthorizationEnabled() ||
 -      isVolatileTable() ||
 -      ComUser::isRootUserID()||
 -      ComUser::getCurrentUser() == owner_)
 -    {
 -      privInfo_ = new(heap_) PrivMgrUserPrivs;
 -      privInfo_->setOwnerDefaultPrivs();
 -      return;
 -    }
 -  
 -  // priv_desc could be NULL if NATable is being created for an MD or hive
 -  // table. 
 -  // For hive tables, go ahead and read the privilege manager metadata to 
 -  // extract privs
 -  // Much of the time, MD is read by the compiler/DDL on behalf of the user so 
 +  // Most of the time, MD is read by the compiler/DDL on behalf of the user so 
    // privilege checks are skipped.  Instead of performing the I/O to get 
    // privilege information at this time, set privInfo_ to NULL and rely on 
    // RelRoot::checkPrivileges to look up privileges. checkPrivileges is 
    // optimized to lookup privileges only when needed.
 +  if (CmpSeabaseDDL::isSeabaseReservedSchema
 +       (qualifiedName_.getQualifiedNameObj().getCatalogName(),
 +        qualifiedName_.getQualifiedNameObj().getSchemaName()))
 +    return;
 +
 +  // If current user is root, object owner, or this is a volatile table
 +  // automatically have owner default privileges.
 +  if ((!isSeabaseTable() && !isHiveTable()) ||
 +       !CmpCommon::context()->isAuthorizationEnabled() ||
 +       isVolatileTable() ||
 +       ComUser::isRootUserID()||
 +       ComUser::getCurrentUser() == owner_)
 +  {
 +    privInfo_ = new(heap_) PrivMgrUserPrivs;
 +    privInfo_->setOwnerDefaultPrivs();
 +    return;
 +  }
 +
-   ComSecurityKeySet secKeyVec;
++  ComSecurityKeySet secKeyVec(heap_);
    if (priv_desc == NULL)
      {
        if (isHiveTable())

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/b10bc1b0/core/sql/sqlcomp/CmpSeabaseDDLcommon.cpp
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/b10bc1b0/core/sql/sqlcomp/PrivMgrCommands.cpp
----------------------------------------------------------------------
diff --cc core/sql/sqlcomp/PrivMgrCommands.cpp
index 6faf70b,550ac64..30b6eea
--- a/core/sql/sqlcomp/PrivMgrCommands.cpp
+++ b/core/sql/sqlcomp/PrivMgrCommands.cpp
@@@ -78,76 -75,69 +78,76 @@@ bool PrivMgrUserPrivs::initUserPrivs
  
    // generate PrivMgrUserPrivs from the priv_desc structure
    TrafDesc *priv_grantees_desc = priv_desc->privDesc()->privGrantees;
-   NAList<PrivMgrDesc> descList;
 -  TrafDesc *priv_grantee_desc = NULL;
 -  TrafDesc *priv_public_desc = NULL;
++  NAList<PrivMgrDesc> descList(NULL);
  
 -  // Find relevant desc for the user
 +  // Find relevant descs for the user
    while (priv_grantees_desc)
    {
      Int32 grantee = priv_grantees_desc->privGranteeDesc()->grantee;
 +    bool addDesc = false;
      if (grantee == userID)
 -      priv_grantee_desc = priv_grantees_desc->privGranteeDesc();
 +      addDesc = true;
 +
 +    if (PrivMgr::isRoleID(grantee))
 +    {
 +      if ((std::find(roleIDs.begin(), roleIDs.end(), grantee)) != roleIDs.end())
 +        addDesc = true;
 +    }
  
      if (ComUser::isPublicUserID(grantee))
 -      priv_public_desc = priv_grantees_desc->privGranteeDesc();
 +    {
 +      addDesc = true;
 +      hasPublicPriv_ = true;
 +    }
  
 -    priv_grantees_desc = priv_grantees_desc->next;
 -  }
 +    // Create a list of PrivMgrDesc contain privileges for user, user's roles,
 +    // and public
 +    if (addDesc)
 +    {
 +      TrafDesc *objectPrivs = priv_grantees_desc->privGranteeDesc()->objectBitmap;
  
 -  // If the user has a privilege in the priv_grantees_desc list, use it to
 -  // create the PrivMgrUserPrivs class.
 -  if (priv_grantee_desc)
 -  {
 +      PrivMgrCoreDesc objectDesc(objectPrivs->privBitmapDesc()->privBitmap,
 +                                 objectPrivs->privBitmapDesc()->privWGOBitmap);
 +      
 +      TrafDesc *priv_grantee_desc = priv_grantees_desc->privGranteeDesc();
 +      TrafDesc *columnPrivs = priv_grantee_desc->privGranteeDesc()->columnBitmaps;
-       NAList<PrivMgrCoreDesc> columnDescs;
++      NAList<PrivMgrCoreDesc> columnDescs(NULL);
 +      while (columnPrivs)
 +      {
 +        PrivMgrCoreDesc columnDesc(columnPrivs->privBitmapDesc()->privBitmap,
 +                                   columnPrivs->privBitmapDesc()->privWGOBitmap,
 +                                   columnPrivs->privBitmapDesc()->columnOrdinal);
 +        columnDescs.insert(columnDesc);
 +        columnPrivs = columnPrivs->next;
 +      }
  
 -    // Set up object level privileges
 -    TrafDesc *objectPrivs = priv_grantee_desc->privGranteeDesc()->objectBitmap;
 -    objectBitmap_ = objectPrivs->privBitmapDesc()->privBitmap;
 -    grantableBitmap_ = objectPrivs->privBitmapDesc()->privWGOBitmap;
 +      PrivMgrDesc privs(priv_grantees_desc->privGranteeDesc()->grantee);
 +      privs.setTablePrivs(objectDesc);
 +      privs.setColumnPrivs(columnDescs);
 +      privs.setHasPublicPriv(hasPublicPriv_);
  
 -    // Set up column level privileges
 -    // The PrivColList is a key <=> value pair structure, the key is the
 -    // column ordinal (number) and the value is the associated bitmap.
 -    TrafDesc *columnPrivs = priv_grantee_desc->privGranteeDesc()->columnBitmaps;
 -    PrivColList colPrivsList;
 -    PrivColList colGrantableList;
 -    while (columnPrivs)
 -    {
 -      Int32 columnOrdinal = columnPrivs->privBitmapDesc()->columnOrdinal;
 -      colPrivsList[columnOrdinal] = columnPrivs->privBitmapDesc()->privBitmap;
 -      colGrantableList[columnOrdinal] = columnPrivs->privBitmapDesc()->privWGOBitmap;
 -      columnPrivs = columnPrivs->next;
 +      descList.insert(privs);
      }
 -    colPrivsList_= colPrivsList;
 -    colGrantableList_ = colGrantableList;
 +    priv_grantees_desc = priv_grantees_desc->next;
    }
  
 -  // See if there are privileges assigned to public.  If so, "or" the public
 -  // list to the user to the current bitmaps. Initially all the bitmap are
 -  // set to 0.
 -  if (priv_public_desc)
 +  // Union privileges from all grantees together to create a single set of
 +  // bitmaps.  Create security invalidation keys
 +  for (int i = 0; i < descList.entries(); i++)
    {
 +    PrivMgrDesc privs = descList[i];
 +
      // Set up object level privileges
 -    TrafDesc *objectPrivs = priv_public_desc->privGranteeDesc()->objectBitmap;
 -    objectBitmap_ |= objectPrivs->privBitmapDesc()->privBitmap;
 -    grantableBitmap_ |= objectPrivs->privBitmapDesc()->privWGOBitmap;
 +    objectBitmap_ |= privs.getTablePrivs().getPrivBitmap();
 +    grantableBitmap_ |= privs.getTablePrivs().getWgoBitmap();
  
      // Set up column level privileges
 -    // The PrivColList is a key <=> value pair structure, the key is the
 -    // column ordinal (number) and the value is the associated bitmap.
 -    TrafDesc *columnPrivs = priv_public_desc->privGranteeDesc()->columnBitmaps;
 -    PrivColList colPrivsList;
 -    PrivColList colGrantableList;
 -    std::map<size_t,PrivColumnBitmap>::iterator it; 
 -    while (columnPrivs)
 +    NAList<PrivMgrCoreDesc> columnPrivs = privs.getColumnPrivs();
 +    std::map<size_t,PrivColumnBitmap>::iterator it;
 +    for (int j = 0; j < columnPrivs.entries(); j++)
      {
 -      Int32 columnOrdinal = columnPrivs->privBitmapDesc()->columnOrdinal;
 +      PrivMgrCoreDesc colDesc = columnPrivs[j];
 +      Int32 columnOrdinal = colDesc.getColumnOrdinal();
        it = colPrivsList_.find(columnOrdinal);
        if (it == colPrivsList_.end())
        {

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/b10bc1b0/core/sql/sqlcomp/PrivMgrDesc.h
----------------------------------------------------------------------
diff --cc core/sql/sqlcomp/PrivMgrDesc.h
index dc72474,1ebc8ce..13e83a2
--- a/core/sql/sqlcomp/PrivMgrDesc.h
+++ b/core/sql/sqlcomp/PrivMgrDesc.h
@@@ -390,24 -389,21 +390,24 @@@ public
                 const int32_t nbrCols = 0    // preset constructor
                )
     : tableLevel_(),
-      columnLevel_(),
+      columnLevel_(NULL),
 -     grantee_(grantee)
 +     grantee_(grantee),
 +     hasPublicPriv_(false)
    {}
  
     PrivMgrDesc(const PrivMgrDesc &privs,            // preset constructor
                 const int32_t grantee)
     : tableLevel_(privs.tableLevel_),
-      columnLevel_(privs.columnLevel_),
 -    columnLevel_(privs.columnLevel_, NULL),
 -     grantee_(privs.grantee_)
++     columnLevel_(privs.columnLevel_,NULL),
 +     grantee_(privs.grantee_),
 +     hasPublicPriv_(privs.hasPublicPriv_)
     {}
  
     PrivMgrDesc(void)
     : tableLevel_(),
-      columnLevel_(),
+      columnLevel_(NULL),
 -     grantee_(0)
 +     grantee_(0),
 +     hasPublicPriv_(false)
     {}
  
     virtual ~PrivMgrDesc()                 // destructor

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/b10bc1b0/core/sql/sqlcomp/PrivMgrPrivileges.cpp
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/b10bc1b0/core/sql/sqlcomp/QCache.cpp
----------------------------------------------------------------------



[5/5] incubator-trafodion git commit: Merge [TRAFODION-2167] pr 757 Invalid Query Invalidation Keys not working properly

Posted by rm...@apache.org.
Merge [TRAFODION-2167] pr 757 Invalid Query Invalidation Keys not working properly


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

Branch: refs/heads/master
Commit: b12b45eca0e1eed6df11d0cf00e0b7344a9689ff
Parents: ca00ea2 b10bc1b
Author: Roberta Marton <ro...@apache.org>
Authored: Fri Oct 14 19:53:09 2016 +0000
Committer: Roberta Marton <ro...@apache.org>
Committed: Fri Oct 14 19:53:09 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           | 4356 +++++++++++++------------
 core/sql/sqlcomp/CmpSeabaseDDLcommon.cpp |   21 +
 core/sql/sqlcomp/PrivMgrCommands.cpp     |  194 +-
 core/sql/sqlcomp/PrivMgrCommands.h       |   22 +-
 core/sql/sqlcomp/PrivMgrDesc.h           |   88 +-
 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, 2769 insertions(+), 2926 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/b12b45ec/core/sql/optimizer/BindRelExpr.cpp
----------------------------------------------------------------------