NATraceList
ElemDDLUdfOptimizationHint::getDetailInfo() const
{
  NAString        detailText;
  NATraceList detailTextList;

  detailText = "optimization hint = ";
  detailText +=  LongToNAString((Lng32)getOptimizationKind());
  if (getOptimizationKind() NEQ COM_UDF_NUMBER_OF_UNIQUE_OUTPUT_VALUES)
  {
    detailText +=  " - cost = ";
    detailText +=  LongToNAString((Lng32)getCost());
  }
  else
  {
    detailText += " - number of unique output values = ( ";
    const NAList<ComSInt64> values = getUniqueOutputValues();
    for (CollIndex i = 0; i < values.entries(); i++)
    {
      if (i > 0) detailText += " , ";
      detailText += Int64ToNAString((Int64)values[i]);
    }
    detailText += " )";
  }
  detailTextList.append(detailText);

  return detailTextList;
}
NABoolean NAList<T>::operator== (const NAList<T> &other) const
{
  if (this->entries() != other.entries())
    return FALSE;

  for (CollIndex i = 0; i < this->entries(); i++)
    {
      if (NOT (at(i) == other.at(i)))
	return FALSE;
    }

  return TRUE;
}
// ****************************************************************************
// method: getListOfReferencedTables
//
// Returns a list of all tables that are being referenced by the passed in 
// view UID
//
// Parameters:
//    cliInterface - used to get the list of object usages
//    objectUID - the UID being processed
//    tableList - a list of objectRefdByMe structures describing each usage
//
// returns:
//    0 - successful
//   -1 - unexpected error occurred
// ****************************************************************************
short CmpSeabaseDDL::getListOfReferencedTables( 
   ExeCliInterface * cliInterface,
   const Int64 objectUID,
   NAList<objectRefdByMe> &tablesList )
{
  Lng32 retcode = 0;

  NAList <objectRefdByMe> tempRefdList;
  retcode = getListOfDirectlyReferencedObjects (cliInterface, objectUID, tempRefdList);
  
  // If unexpected error - return
  if (retcode < 0)
    {
      if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
        SEABASEDDL_INTERNAL_ERROR("getting list of referenced tables");
      return -1;
    }
   

  // For each view in the list, call getReferencedTables recursively
  for (CollIndex i = 0; i < tempRefdList.entries(); i++)
    {
      objectRefdByMe objectRefd = tempRefdList[i];

      // views should only be referencing tables, other views, or functions
      CMPASSERT(objectRefd.objectType == COM_BASE_TABLE_OBJECT_LIT ||
                objectRefd.objectType == COM_USER_DEFINED_ROUTINE_OBJECT_LIT ||
                objectRefd.objectType == COM_SEQUENCE_GENERATOR_OBJECT_LIT ||
                objectRefd.objectType == COM_VIEW_OBJECT_LIT);

      // found a table, add to list
      if (objectRefd.objectType == COM_BASE_TABLE_OBJECT_LIT)
        {  
          // First make sure it has not already been added to the list
          NABoolean foundEntry = FALSE;
          for (CollIndex j = 0; j < tablesList.entries(); j++)
            {
               if (tablesList[j].objectUID == objectRefd.objectUID)
                 foundEntry = TRUE;
            }
        if (!foundEntry)             
          tablesList.insert(objectRefd);  
      } 

      // found a view, get objects associated with the view
      if (objectRefd.objectType == COM_VIEW_OBJECT_LIT)
        getListOfReferencedTables(cliInterface, objectRefd.objectUID, tablesList);
    }

  return 0;
}
// This native method is called by the LmT2Driver Java class
// whenever a java.sql.Connection object of type default connection 
// is created. The default connection's object reference is passed 
// as input to this method.
//
// This method creates a global reference of the provided connection
// object and adds it to 'lmUtilityConnList'.
//
JNIEXPORT void JNICALL Java_com_tandem_sqlmx_LmT2Driver_addConnection
(JNIEnv * env, jclass jc, jobject conn)
{
  LM_ASSERT( conn != NULL );
  jobject newConn = env->NewGlobalRef( conn );
  lmUtilityConnList.insert(newConn);
}
void NAList<T>::insert(const NAList<T> &other)
{
  CollIndex count = other.entries();
  for (CollIndex i = 0; i < count; i++)
    {
      insert(other[i]);
    } // for loop for iterating over members of the set
} // insert(LIST(T))
// If there are any Java connection objects present in 
// 'lmUtilityConnList' then the following actions are taken:
// - Calls the 'close()' method on the connection
// - Deletes the object reference
// - Removes the connection entry from 'lmUtilityConnList'
// 
// The method expects the following as input:
// - Pointer to the JNIEnv interface
// - JNI method ID of java.sql.Connection.close() method
//
void lmUtilityInitConnList( JNIEnv *jni, jmethodID connCloseId )
{
  while( lmUtilityConnList.entries() )
  {
    jobject conn = lmUtilityConnList[0];

    if( conn )
    {
      jni->CallVoidMethod( conn,
                           connCloseId );
      jni->ExceptionClear();
    }

    jni->DeleteGlobalRef( conn );
    lmUtilityConnList.removeAt(0);
  }

  lmUtilityConnList.clear();
}
// ****************************************************************************
// method: getListOfDirectlyReferencedObjects
//
// Returns a list of objects that are being directly referenced by the passed 
// in objectUID
//
// Parameters:
//    cliInterface - used to get the list of object usages
//    objectUID - the UID being processed
//    objectList - a list of objectRefdByMe structures describing each usage
//
// returns:
//    0 - successful
//   -1 - unexpected error occurred
// ****************************************************************************
short CmpSeabaseDDL::getListOfDirectlyReferencedObjects (
  ExeCliInterface *cliInterface,
  const Int64 objectUID,
  NAList<objectRefdByMe> &objectsList)
{
  // Select all the rows from views_usage associated with the passed in
  // objectUID
  Lng32 cliRC = 0;
  char buf[4000];
  str_sprintf(buf, "select object_type, object_uid, catalog_name," 
                   "schema_name, object_name from %s.\"%s\".%s T, %s.\"%s\".%s VU " 
                   "where VU.using_view_uid = %Ld "
                   "and T.object_uid = VU.used_object_uid",
              getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
              getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_VIEWS_USAGE,
              objectUID);

  Queue * usingObjectsQueue = NULL;
  cliRC = cliInterface->fetchAllRows(usingObjectsQueue, buf, 0, FALSE, FALSE, TRUE);
  if (cliRC < 0)
    {
      cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
      return -1;
    }

  // set up an objectRefdByMe struct for each returned row
  usingObjectsQueue->position();
  for (int idx = 0; idx < usingObjectsQueue->numEntries(); idx++)
    {
      OutputInfo * oi = (OutputInfo*)usingObjectsQueue->getNext();
      objectRefdByMe objectInfo;
      objectInfo.objectType = NAString(oi->get(0));
      objectInfo.objectUID = *(Int64*)oi->get(1);
      objectInfo.catalogName = NAString(oi->get(2));
      objectInfo.schemaName = NAString(oi->get(3));
      objectInfo.objectName = NAString(oi->get(4));
      objectsList.insert(objectInfo);
    }

  return 0;
}
void CmpSeabaseDDL::dropSeabaseView(
				    StmtDDLDropView * dropViewNode,
				    NAString &currCatName, NAString &currSchName)
{
  Lng32 cliRC = 0;
  Lng32 retcode = 0;

  const NAString &tabName = dropViewNode->getViewName();

  ComObjectName viewName(tabName);
  ComAnsiNamePart currCatAnsiName(currCatName);
  ComAnsiNamePart currSchAnsiName(currSchName);
  viewName.applyDefaults(currCatAnsiName, currSchAnsiName);

  const NAString catalogNamePart = viewName.getCatalogNamePartAsAnsiString();
  const NAString schemaNamePart = viewName.getSchemaNamePartAsAnsiString(TRUE);
  const NAString objectNamePart = viewName.getObjectNamePartAsAnsiString(TRUE);
  const NAString extViewName = viewName.getExternalName(TRUE);

  ExeCliInterface cliInterface(STMTHEAP, NULL, NULL, 
  CmpCommon::context()->sqlSession()->getParentQid());

  ExpHbaseInterface * ehi = allocEHI();
  if (ehi == NULL)
    return;

  if ((isSeabaseReservedSchema(viewName)) &&
      (!Get_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL)))
    {
      *CmpCommon::diags() << DgSqlCode(-1119)
			  << DgTableName(extViewName);
      deallocEHI(ehi); 

      processReturn();

      return;
    }

  retcode = existsInSeabaseMDTable(&cliInterface, 
				   catalogNamePart, schemaNamePart, objectNamePart,
				   COM_VIEW_OBJECT, TRUE, FALSE);
  if (retcode < 0)
    {
      deallocEHI(ehi); 

      processReturn();

      return;
    }

  if (retcode == 0) // does not exist
    {
      *CmpCommon::diags() << DgSqlCode(-1389)
			  << DgString0(extViewName);

      deallocEHI(ehi); 

      processReturn();
      
      return;
    }

  Int32 objectOwnerID = 0;
  Int32 schemaOwnerID = 0;
  Int64 objUID = getObjectUIDandOwners(&cliInterface,
			              catalogNamePart.data(), schemaNamePart.data(), 
			              objectNamePart.data(),
			              COM_VIEW_OBJECT,
                                      objectOwnerID,schemaOwnerID);

  if (objUID < 0 || objectOwnerID == 0)
    {
      if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
        SEABASEDDL_INTERNAL_ERROR("getting object UID and owner for drop view");

      deallocEHI(ehi); 

      processReturn();

      return;
    }

  // Verify user can perform operation
  if (!isDDLOperationAuthorized(SQLOperation::DROP_VIEW,objectOwnerID,schemaOwnerID))
  {
     *CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
     deallocEHI(ehi);
     processReturn ();
     return;
  }
 
  Queue * usingViewsQueue = NULL;
  if (dropViewNode->getDropBehavior() == COM_RESTRICT_DROP_BEHAVIOR)
    {
      NAString usingObjName;
      cliRC = getUsingObject(&cliInterface, objUID, usingObjName);
      if (cliRC < 0)
	{
	  deallocEHI(ehi); 

	  processReturn();
	  
	  return;
	}

      if (cliRC != 100) // found an object
	{
	  *CmpCommon::diags() << DgSqlCode(-1047)
			      << DgTableName(usingObjName);

	  deallocEHI(ehi); 

	  processReturn();

	  return;
	}
    }
  else if (dropViewNode->getDropBehavior() == COM_CASCADE_DROP_BEHAVIOR)
    {
      cliRC = getUsingViews(&cliInterface, objUID, usingViewsQueue);
      if (cliRC < 0)
	{
	  deallocEHI(ehi); 

	  processReturn();
	  
	  return;
	}
    }

  // get the list of all tables referenced by the view.  Save this list so 
  // referenced tables can be removed from cache later
  NAList<objectRefdByMe> tablesRefdList;
  short status = getListOfReferencedTables(&cliInterface, objUID, tablesRefdList);

  if (usingViewsQueue)
    {
      usingViewsQueue->position();
      for (int idx = 0; idx < usingViewsQueue->numEntries(); idx++)
	{
	  OutputInfo * vi = (OutputInfo*)usingViewsQueue->getNext(); 
	  
	  char * viewName = vi->get(0);
	  
	  if (dropSeabaseObject(ehi, viewName,
				 currCatName, currSchName, COM_VIEW_OBJECT))
	    {
	      deallocEHI(ehi); 

	      processReturn();
	      
	      return;
	    }
	}
    }

  if (dropSeabaseObject(ehi, tabName,
			 currCatName, currSchName, COM_VIEW_OBJECT))
    {
      deallocEHI(ehi); 

      processReturn();

      return;
    }

  // clear view definition from my cache only. 
  CorrName cn(objectNamePart, STMTHEAP, schemaNamePart, catalogNamePart);
  ActiveSchemaDB()->getNATableDB()->removeNATable(cn,
    NATableDB::REMOVE_MINE_ONLY, COM_VIEW_OBJECT);

  // clear view from all other caches here. This compensates for a 
  // scenario where the object UID is not available in removeNATable, 
  // and the look up failed too.  Solution is just to use the objectUID 
  // here.
  SQL_QIKEY qiKey;
  qiKey.operation[0] = 'O';
  qiKey.operation[1] = 'R';
  qiKey.ddlObjectUID = objUID;
  SQL_EXEC_SetSecInvalidKeys(1, &qiKey);

  // Now remove referenced tables from cache.
  // When a query that references a view is compiled, all views are converted
  // to the underlying base tables.  Query plans are generated to access the
  // tables, and the views are no longer relevant.
  // When dropping a view, query plans that reference the dropped view will
  // continue to work if the plans are cached.  This code removes the 
  // referenced tables from caches to force recompilations so dropped views
  // are noticed.
  for (CollIndex i = 0; i < tablesRefdList.entries(); i++)
    {
      CorrName cn(tablesRefdList[i].objectName,
                  STMTHEAP,
                  tablesRefdList[i].schemaName,
                  tablesRefdList[i].catalogName);
      ActiveSchemaDB()->getNATableDB()->removeNATable(cn,
        NATableDB::REMOVE_FROM_ALL_USERS, COM_BASE_TABLE_OBJECT);
    }

  deallocEHI(ehi); 
      
  processReturn();

  return;
}