//////////////////////////////////////////////////////////////////////////////
// Does this base table have a supporting index on the MAV GroupBy columns?
// (Supporting index means that the MAV GroupBy columns must be a prefix
// of the index columns).
//////////////////////////////////////////////////////////////////////////////
NABoolean Refresh::doesBaseTableHaveSupportingIndex(BindWA *bindWA,
        MVInfoForDML *mvInfo) const
{
    CollIndex i;
    LIST (MVUsedObjectInfo*)& UsedObjList = mvInfo->getUsedObjectsList();
    MVUsedObjectInfo* pUsedTable = UsedObjList[0];

    // Extract GroupBy columns
    const MVColumns& pMvInfoColumnList =
        mvInfo->getMVColumns();
    LIST (MVColumnInfo *) mvGroupByColumns(bindWA->wHeap());
    for (	i = 0 ; i < pMvInfoColumnList.entries() ; i++)
    {
#pragma nowarn(1506)   // warning elimination 
        MVColumnInfo *currentMvColInfo = pMvInfoColumnList[i];
#pragma warn(1506)  // warning elimination 
        if (COM_MVCOL_GROUPBY == currentMvColInfo->getColType())
        {
            mvGroupByColumns.insert(currentMvColInfo);
        }
    }

    // If the MAV does not have any group by columns - than there is
    // no supporting index.
    if (mvGroupByColumns.entries() == 0)
        return FALSE;

    // Get the NATable
    QualifiedName underlyingTableName = pUsedTable->getObjectName();
    CorrName corrTableName(underlyingTableName);
    NATable * pNaTable = bindWA->getNATable(corrTableName, FALSE);

    // Construct table GroupBy
    NAColumnArray tableGroupByArray;
    const NAColumnArray & columnArray = pNaTable->getNAColumnArray();
    for ( i = 0 ; i < mvGroupByColumns.entries() ; i++)
    {
        Int32 tableColNum = (mvGroupByColumns)[i]->getOrigColNumber();
        NAColumn * pColumn = columnArray.getColumn(tableColNum);
        tableGroupByArray.insert(pColumn);
    }

    // Check the clustering Index.
    const NAFileSet *pClusteringIndexFileSet = pNaTable->getClusteringIndex();
    const NAColumnArray& ciColumns =
        pClusteringIndexFileSet->getIndexKeyColumns();

    if (TRUE == areGroupByColsAnIndexPrefix(tableGroupByArray, ciColumns))
    {
        return TRUE;
    }

    // Check any secondary indices.
    const NAFileSetList & indexFileSetList = pNaTable->getIndexList();
    for ( i = 0 ; i < indexFileSetList.entries() ; i++)
    {
        const NAFileSet *pSecondaryIndexFileSet = indexFileSetList[i];
        const NAColumnArray& siColumns =
            pSecondaryIndexFileSet->getIndexKeyColumns();

        if (TRUE == areGroupByColsAnIndexPrefix(tableGroupByArray, siColumns))
        {
            return TRUE;
        }
    }

    return FALSE;
}
// *****************************************************************************
// *                                                                           *
// * 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;

}