// The return value is computed as follows:
//   If no privs were specified in this on input, return Neutral.
//   Otherwise :
//     Return All if each T specified in input 'this'
//       remains T in output 'this';
//     Return None if each T specified in input 'this'
//       becomes F on output 'this';
//     Return Some for other combinations.
// ----------------------------------------------------------------------------
PrivMgrCoreDesc::PrivResult PrivMgrCoreDesc::grantPrivs(PrivMgrCoreDesc& param)
{
   if ( this->isNull() )
      return NEUTRAL;   // Do nothing.  No privs to be granted.

   std::bitset<NBR_OF_PRIVS> beforePriv (param.priv_);  // save input values
   std::bitset<NBR_OF_PRIVS> beforeWgo  (param.wgo_);
   std::bitset<NBR_OF_PRIVS> inPriv (priv_);
   std::bitset<NBR_OF_PRIVS> inWgo  (wgo_);

   param.priv_ |= priv_;    // param(out) gets param(in) OR this(in).
   param.wgo_  |= wgo_;

   priv_ &= ( beforePriv.flip() );  // this(out) gets this(in)
   wgo_  &= ( beforeWgo.flip() );   //     AND NOT  param(in)

   PrivResult result(NEUTRAL);

   // Look at each privilege type
   for ( size_t i = 0; i < NBR_OF_PRIVS; i++ )
   {
      PrivType pType = PrivType(i);
      PrivMgrCoreDesc::interpretChanges(inPriv.test(pType),
                                     priv_.test(pType),
                                     result);
      PrivMgrCoreDesc::interpretChanges(inWgo.test(pType),
                                     wgo_.test(pType),
                                     result);
   }

   return result;
}
//     this object|passed param|passed param|this object
//      on input: |  on input: | on output: | on output:
//     priv_ wgo_ | priv_ wgo_ | priv_ wgo_ | priv_ wgo_
//      ---  ---  |  ---  ---  |  ---  ---  |  ---  --- 
//       T    T  ->   T    T  =>   F    F       T    T 
//                    T    F       F    F       T    F 
//                    F    F       F    F       F    F 
//       F    T  ->   T    T  =>   T    F       F    T
//                    T    F       T    F       F    F
//                    F    F       F    F       F    F  
//       F    F  ->   x    y  =>   x    y       F    F 
//       T    F (does not occur -- cannot revoke priv without revoking wgo)
// 
// The algorithm is:
//   Output param = input param AND NOT input this;
//   Output this = input this AND input param.
//   Return value is computed as described in grantPrivs.
// ---------------------------------------------------------------------------- 
PrivMgrCoreDesc::PrivResult PrivMgrCoreDesc::revokePrivs(PrivMgrCoreDesc& param)
{
   if ( this->isNull() )
      return NEUTRAL;   // Do nothing.  No privs to be revoked.

   std::bitset<NBR_OF_PRIVS> beforePriv  = param.priv_;  // save input values.
   std::bitset<NBR_OF_PRIVS> beforeWgo =  param.wgo_;
   std::bitset<NBR_OF_PRIVS> inPriv (priv_);
   std::bitset<NBR_OF_PRIVS> inWgo  (wgo_);

   param.priv_ &= ( priv_.flip() );   // param(out) gets param(in) 
   //param.priv_ &= ( priv_ );   // param(out) gets param(in) 
   param.wgo_  &= ( wgo_.flip());     //   AND NOT( this(in) ).
   //param.wgo_  &= ( wgo_);     //   AND NOT( this(in) ).
   param.wgo_  &= param.priv_;  // Assure valid new setting.

   priv_ &= beforePriv;       // this(out) gets this(in)
   wgo_  &= beforeWgo;        //     AND param(in).

   PrivResult result(NEUTRAL);
   // Look at each privilege type
   for ( size_t i = 0; i < NBR_OF_PRIVS; i++ )
   {
      PrivType pType = PrivType(i);
      PrivMgrCoreDesc::interpretChanges(inPriv.test(pType),
                                     priv_.test(pType),
                                     result);
      PrivMgrCoreDesc::interpretChanges(inWgo.test(pType),
                                     wgo_.test(pType),
                                     result);
   }

   return result;
}
// *****************************************************************************
// *                                                                           *
// * Function: checkAccessPrivileges                                           *
// *                                                                           *
// *   This function determines if a user has the requesite privileges to      *
// * access the referenced objects that comprise the view.                     *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <vtul>                   const ParTableUsageList &              In       *
// *    is a reference to a list of objects used by the view.                  *
// *                                                                           *
// *  <vctcul>                 const ParViewColTableColsUsageList &   In       *
// *    is a reference to the list of columns used by the view.                *
// *                                                                           *
// *  <privilegesBitmap>       PrivMgrBitmap &                        Out      *
// *    passes back the union of privileges the user has on the referenced     *
// *    objects.                                                               *
// *                                                                           *
// *  <grantableBitmap>        PrivMgrBitmap &                        Out      *
// *    passes back the union of the with grant option authority the user has  *
// *    on the referenced objects.                                             *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: bool                                                             *
// *                                                                           *
// *  true: User has requisite privileges; bitmap unions returned.             *
// * false: Could not retrieve privileges or user does not have requesite      *
// *        privileges; see diags area for error details.                      *
// *                                                                           *
// *****************************************************************************
static bool checkAccessPrivileges(
   const ParTableUsageList & vtul,
   const ParViewColTableColsUsageList & vctcul,
   PrivMgrBitmap & privilegesBitmap,
   PrivMgrBitmap & grantableBitmap)
   
{

BindWA bindWA(ActiveSchemaDB(),CmpCommon::context(),FALSE/*inDDL*/);
bool missingPrivilege = false;
NAString extUsedObjName;

// generate the lists of privileges and grantable privileges
// a side effect is to return an error if basic privileges are not granted
   for (CollIndex i = 0; i < vtul.entries(); i++)
   {
      if (vtul[i].getSpecialType() == ExtendedQualName::SG_TABLE)
         continue;
         
      ComObjectName usedObjName(vtul[i].getQualifiedNameObj().getQualifiedNameAsAnsiString(),
                                vtul[i].getAnsiNameSpace());
      
      const NAString catalogNamePart = usedObjName.getCatalogNamePartAsAnsiString();
      const NAString schemaNamePart = usedObjName.getSchemaNamePartAsAnsiString(TRUE);
      const NAString objectNamePart = usedObjName.getObjectNamePartAsAnsiString(TRUE);
      const NAString extUsedObjName = usedObjName.getExternalName(TRUE);
      CorrName cn(objectNamePart,STMTHEAP, schemaNamePart,catalogNamePart);
 
      NATable *naTable = bindWA.getNATable(cn);
      if (naTable == NULL)
      {
         SEABASEDDL_INTERNAL_ERROR("Bad NATable pointer in checkAccessPrivileges");
         return false; 
      }
      // Grab privileges from the NATable structure
      PrivMgrUserPrivs *privs = naTable->getPrivInfo();
      if (privs == NULL) 
      {         
         *CmpCommon::diags() << DgSqlCode(-CAT_UNABLE_TO_RETRIEVE_PRIVS);
         return false;
      }

      // Requester must have at least select privilege
      if ( !privs->hasSelectPriv() )
         missingPrivilege = true;

     // Summarize privileges
      privilegesBitmap &= privs->getObjectBitmap();
      grantableBitmap &= privs->getGrantableBitmap();
   }
   
   if (!missingPrivilege)
      return true;
   
   missingPrivilege = false;   
      
PrivColumnBitmap colPrivBitmap;
PrivColumnBitmap colGrantableBitmap;

   PrivMgrPrivileges::setColumnPrivs(colPrivBitmap);
   PrivMgrPrivileges::setColumnPrivs(colGrantableBitmap);

   for (size_t i = 0; i < vctcul.entries(); i++)
   {
      const ParViewColTableColsUsage &vctcu = vctcul[i];
      int32_t usingColNum = vctcu.getUsingViewColumnNumber();
      const ColRefName &usedColRef = vctcu.getUsedObjectColumnName();
      
      ComObjectName usedObjName;

      usedObjName = usedColRef.getCorrNameObj().getQualifiedNameObj().
                    getQualifiedNameAsAnsiString();

      const NAString catalogNamePart = usedObjName.getCatalogNamePartAsAnsiString();
      const NAString schemaNamePart = usedObjName.getSchemaNamePartAsAnsiString(TRUE);
      const NAString objectNamePart = usedObjName.getObjectNamePartAsAnsiString(TRUE);
      extUsedObjName = usedObjName.getExternalName(TRUE);
      CorrName cn(objectNamePart,STMTHEAP,schemaNamePart,catalogNamePart);

      NATable *naTable = bindWA.getNATable(cn);
      if (naTable == NULL)
      {
         SEABASEDDL_INTERNAL_ERROR("Bad NATable pointer in checkAccessPrivileges");
         return -1; 
      }

      const NAColumnArray &nacolArr = naTable->getNAColumnArray();
      ComString usedObjColName(usedColRef.getColName());
      const NAColumn * naCol = nacolArr.getColumn(usedObjColName);
      if (naCol == NULL)
      {
         *CmpCommon::diags() << DgSqlCode(-CAT_COLUMN_DOES_NOT_EXIST_ERROR)
                             << DgColumnName(usedObjColName);
         return false;
      }
      int32_t usedColNumber = naCol->getPosition();
     
      // Grab privileges from the NATable structure
      PrivMgrUserPrivs *privs = naTable->getPrivInfo();
      if (privs == NULL) 
      {         
         *CmpCommon::diags() << DgSqlCode(-CAT_UNABLE_TO_RETRIEVE_PRIVS);
         return false;
      }
      // If the user is missing SELECT on at least one column-level privilege,
      // view cannot be created.  No need to proceed.
      if (!privs->hasColSelectPriv(usedColNumber))
      {
         missingPrivilege = true;
         break;
      }        
      
      colPrivBitmap &= privs->getColumnPrivBitmap(usedColNumber);
      colGrantableBitmap &= privs->getColumnGrantableBitmap(usedColNumber);
   }
  
   if (missingPrivilege || vctcul.entries() == 0)
   {
      *CmpCommon::diags() << DgSqlCode(-4481)
                          << DgString0("SELECT")
                          << DgString1(extUsedObjName.data());
      return false;
   }
  
   for (size_t i = FIRST_DML_COL_PRIV; i <= LAST_DML_COL_PRIV; i++ )
   {
      if (colPrivBitmap.test(PrivType(i)))
         privilegesBitmap.set(PrivType(i));   
 
      if (colGrantableBitmap.test(PrivType(i)))
         grantableBitmap.set(PrivType(i));   
   }
   
   return true;

}