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;
}
NATraceList
ElemDDLConstraintUnique::getDetailInfo() const
{
  NATraceList detailTextList = ElemDDLConstraint::getDetailInfo();

  if (getKeyColumnArray().entries() EQU 0)
  {
    detailTextList.append("No key column list.");
  }
  else
  {
    NAString detailText;

    detailText = "Key Column List [";
    detailText += LongToNAString((Lng32)getKeyColumnArray().entries());
    detailText += " element(s)]:";
    detailTextList.append(detailText);
    
    for (CollIndex i = 0; i < getKeyColumnArray().entries(); i++)
    {
      detailText = "[column ";
      detailText += LongToNAString((Lng32)i);
      detailText += "]";
      detailTextList.append(detailText);
      
      detailTextList.append("    ", getKeyColumnArray()[i]->getDetailInfo());
    }
  }

  return detailTextList;

} // ElemDDLConstraintUnique::getDetailInfo()
NATraceList
StmtDDLSchGrant::getDetailInfo() const
{
    NAString        detailText;
    NATraceList detailTextList;

    //
    // object name
    //

    detailTextList.append(displayLabel1());   // object name

    //
    // privileges
    //

    StmtDDLSchGrant * localThis = (StmtDDLSchGrant *)this;

    detailTextList.append(localThis->getChild(INDEX_PRIVILEGES)
                          ->castToElemDDLNode()
                          ->castToElemDDLPrivileges()
                          ->getDetailInfo());

    //
    // grantee list
    //

    const ElemDDLGranteeArray & granteeArray = getGranteeArray();

    detailText = "Grantee list [";
    detailText += LongToNAString((Lng32)granteeArray.entries());
    detailText += " element(s)]";
    detailTextList.append(detailText);

    for (CollIndex i = 0; i < granteeArray.entries(); i++)
    {
        detailText = "[grantee ";
        detailText += LongToNAString((Lng32)i);
        detailText += "]";
        detailTextList.append(detailText);

        ComASSERT(granteeArray[i] NEQ NULL AND
                  granteeArray[i]->castToElemDDLGrantee() NEQ NULL);
        detailTextList.append("    ", granteeArray[i]->castToElemDDLGrantee()
                              ->getDetailInfo());
    }

    //
    // with grant option
    //

    detailText = "is with grant option? ";
    detailText += YesNo(localThis->getChild(INDEX_WITH_GRANT_OPTION) NEQ NULL);
    detailTextList.append(detailText);

    return detailTextList;

} // StmtDDLGrant::getDetailInfo
NATraceList
ElemDDLPartitionRange::getDetailInfo() const
{
  //
  // Note that class ElemDDLPartitionRange is derived
  // from class ElemDDLPartitionSystem.
  //
  NAString        detailText;
  NATraceList detailTextList = ElemDDLPartitionSystem::getDetailInfo();

  const ItemConstValueArray & keyValues = getKeyValueArray();

  if (keyValues.entries() NEQ 0)
  {
    detailText = "Key value list [";
    detailText += LongToNAString((Lng32)keyValues.entries());
    detailText += " key value(s)]:";
    detailTextList.append(detailText);
  }
  else
  {
    //
    // only primary (range) partition node is
    // allowed not to contain a list of key values.
    //
    detailText = "Key value not specified.";
    detailTextList.append(detailText);
  }
  for (CollIndex j = 0; j < keyValues.entries(); j++)
  {
    ConstValue * keyVal = keyValues[j];
    
    detailText = "  [key value ";
    detailText += LongToNAString((Lng32)j);
    detailText += "]";
    detailTextList.append(detailText);
    
    detailText = "    Key value:      ";
    detailText += keyVal->getText();
    detailTextList.append(detailText);
    
    detailText = "    Key value type: ";
    detailText += keyVal->getType()->getTypeSQLname();
    detailTextList.append(detailText);
  }

  return detailTextList;

} // ElemDDLPartitionRange::getDetailInfo()
NATraceList StmtDDLRevokeComponentPrivilege::getDetailInfo() const
{
    NAString        detailText;
    NATraceList detailTextList;

    //
    // component name
    //

    detailTextList.append(displayLabel1());   // component name

    //
    // user role name
    //

    detailTextList.append(displayLabel2());   // user role name

    //
    // component privilege name list
    //

    const ConstStringList & privs = getComponentPrivilegeNameList();

    detailText = "Component Privilege Name List [";
    detailText += LongToNAString((Lng32)privs.entries());
    detailText += " element(s)]";
    detailTextList.append(detailText);

    for (CollIndex i = 0; i < privs.entries(); i++)
    {
        detailText = "[";
        detailText += LongToNAString((Lng32)i);
        detailText += "] ";
        detailText += *privs[i];
        detailTextList.append(detailText);
    }

    //
    // with revoke option
    //

    detailText = "is Grant Option For clause specified? ";
    detailText += YesNo(isGrantOptionForSpecified());
    detailTextList.append(detailText);

    return detailTextList;

} // StmtDDLRevokeComponentPrivilege::getDetailInfo
// --------------------------------------------------------------------------- 
// readPair: read content of entry 
// --------------------------------------------------------------------------- 
Int32 UdrCfgParser::readPair( FILE *is, char *buf, Int32 bufSize
                           , NAString &errorText )
{                                    
   char lineBuf[BUFFMAX+2];
   char *p, *cur;
   Int32  len = -1;
   NABoolean quote = FALSE;

   while( fgets( lineBuf, sizeof(lineBuf), is ) ) 
   {
      len = -1;

      remEOL(lineBuf);
      if( isTitleLine( lineBuf ) )       // section is ended 
         break;

      p=lineBuf;

      if (quote == FALSE)
         stripComment( p );

      rtrim(p);

      if ((len = (Int32)strlen(p)) == 0)
         continue;

       if( bufSize-1 < len ) 
       {
         errorText += 
          "*** ERROR: UdrCfgParser():fgets read line longer than BUFFMAX of ";
         errorText += LongToNAString((Lng32) BUFFMAX);
         errorText += " in config file ";
         errorText += cfgFileName;
         errorText += ".\n";

         return -1;
       }

       cur  = buf;
       *cur = '\0';
 
       strncpy( cur, p, len );
       cur[len] = 0;

       break;
   }

   if (ferror(is)) {
      errorText += "*** ERROR: UdrCfgParser(): fgets failed on config file ";
      errorText += cfgFileName;
      errorText += " due to an I/O error: ";
      errorText += strerror(errno);
      errorText += ".\n";
   }

   return len;
}
//----------------------------------------------------------------------------
// method for building text
//virtual 
NAString ElemDDLFileAttrBlockSize::getSyntax() const
{
  NAString syntax = "BLOCKSIZE ";
    
#pragma nowarn(1506)   // warning elimination 
  syntax += LongToNAString(blockSizeInBytes_);
#pragma warn(1506)  // warning elimination 

  return syntax;
} // getSyntax() 
// method for building text
// virtual 
NAString ElemDDLFileAttrMVCommitEach::getSyntax() const
{
  NAString syntax = "COMMIT REFRESH EACH ";
#pragma nowarn(1506)   // warning elimination 
  syntax += LongToNAString(nrows_);
#pragma warn(1506)  // warning elimination 

  return syntax;


}
NATraceList
ElemDDLPartitionByColumnList::getDetailInfo() const
{
  NAString        detailText;
  NATraceList detailTextList;
  ElemDDLNode   * pPartitionKeyColumnList = getPartitionKeyColumnList();

  //
  // kind of store option
  //

  detailTextList.append(displayLabel1());

  //
  // column name list
  //

  if (pPartitionKeyColumnList EQU NULL)
  {
    detailTextList.append("No column name list.");
    return detailTextList;
  }

  detailText = "Column Name List [";
  detailText += LongToNAString((Lng32)pPartitionKeyColumnList->entries());
  detailText += " element(s)]:";
  detailTextList.append(detailText);

  for (CollIndex i = 0; i < pPartitionKeyColumnList->entries(); i++)
  {
    detailText = "[column ";
    detailText += LongToNAString((Lng32)i);
    detailText += "]";
    detailTextList.append(detailText);

    detailTextList.append("    ", (*pPartitionKeyColumnList)[i]
                                                         ->getDetailInfo());
  }
  return detailTextList;
}
NATraceList
ElemDDLUdrMaxResults::getDetailInfo() const
{
  NAString        detailText;
  NATraceList detailTextList;

  detailText = "MaxResults: ";
#pragma nowarn(1506)   // warning elimination 
  detailText += LongToNAString(getMaxResults());
#pragma warn(1506)  // warning elimination 
  detailTextList.append(detailText);

  return detailTextList;

}
NATraceList
ElemDDLUdfStateAreaSize::getDetailInfo() const
{
  NAString        detailText;
  NATraceList detailTextList;

  detailText = "StateAreaSize: ";
#pragma nowarn(1506)   // warning elimination
  detailText += LongToNAString(getStateAreaSize());
#pragma warn(1506)  // warning elimination
  detailTextList.append(detailText);

  return detailTextList;

}
// method for building text
//virtual 
NAString ElemDDLFileAttrMaxSize::getSyntax() const
{
  NAString syntax = "MAXSIZE ";

  if (TRUE == isUnbounded_)
  {
    syntax += "UNBOUNDED";
  }
  else
  {
#pragma nowarn(1506)   // warning elimination 
    syntax += LongToNAString(maxSize_);
#pragma warn(1506)  // warning elimination 
    syntax += " ";
    
    switch(maxSizeUnit_)
    {

    case COM_BYTES:
      syntax += "";
      break;
    case COM_KBYTES:
      syntax += "K";
      break;
    case COM_MBYTES:
      syntax += "M";
      break;
    case COM_GBYTES:
      syntax += "G";
      break;
    default:
      ComASSERT(FALSE);
      break;

    }
  }

  return syntax;

} // getSyntax
NATraceList
ElemDDLPartitionSystem::getDetailInfo() const
{
  NAString        detailText;
  NATraceList detailTextList;

  detailTextList.append(displayLabel1());  // add or drop
  detailTextList.append(displayLabel2());  // location name
  detailTextList.append(displayLabel3());  // location name type

  //
  // file attributes for this partition
  //

  detailTextList.append("File attributes:");

  detailText = "    max size spec? ";
  detailText += YesNo(isMaxSizeSpecified());
  detailTextList.append(detailText);

  detailText = "    maxsizunbound? ";
  detailText += YesNo(isMaxSizeUnbounded());
  detailTextList.append(detailText);

  detailText = "    max size:      ";
  detailText += LongToNAString((Lng32)getMaxSize());
  detailTextList.append(detailText);

#pragma nowarn(1506)   // warning elimination 
  ElemDDLFileAttrMaxSize maxSizeFileAttr(getMaxSize(), 
                                         getMaxSizeUnit());
#pragma warn(1506)  // warning elimination

  detailText = "    max size unit: ";
  detailText += maxSizeFileAttr.getMaxSizeUnitAsNAString();;
  detailTextList.append(detailText);

  return detailTextList;
}
Beispiel #14
0
//
// This is the LmUtility.nativeUtils method. It takes one string as
// input and produces one string as output. The output string gets
// written to the first element of the String[] array object passed in
// as the jobjectArray parameter.
//
// Although we do not document this method for customers, there is
// nothing preventing customer code from calling this method. So don't
// put anything in the method that you wouldn't want customers
// doing. Currently this function just serves as an entry point to
// various systems calls such as TMF operations and getting/setting
// environment variables. There is nothing here that customers could
// not do on their own if they wanted to.
//
JNIEXPORT void JNICALL Java_org_trafodion_sql_udr_LmUtility_nativeUtils
(JNIEnv * env, jclass jc, jstring js, jobjectArray joa)
{
  const char *input = env->GetStringUTFChars(js, NULL);
  if (input == NULL)
  {
    // OutOfMemory error already thrown
    return;
  }

  NAString action(input);
  TrimNAStringSpace(action);

  short error;
  NAString result("OK");

  static MXStatement staticStmt;

// LCOV_EXCL_START
  if (action.compareTo("GetTxName", NAString::ignoreCase) == 0)
  {
    Int64 transid;
    error = GETTRANSID((short *) &transid);
    if (error)
    {
      if (error == 75)
      {
        result = "No active transaction";
      }
      else
      {
        result = "GETTRANSID returned ";
        result += LongToNAString((Lng32) error);
      }
      Throw(env, result.data());
    }
    else
    {
      short actualLen;
      char text[256];
      error = TRANSIDTOTEXT(transid, text, 255, &actualLen);
      if (error)
      {
        result = "TRANSIDTOTEXT returned ";
        result += LongToNAString((Lng32) error);
        Throw(env, result);
      }
      else
      {
        text[actualLen] = 0;
        result = text;
      }
    }
  } // GetTxName

  else if (action.compareTo("BeginTx", NAString::ignoreCase) == 0)
  {
    Int32 tag;
    error = BEGINTRANSACTION(&tag);
    if (error)
    {
      result = "BEGINTRANSACTION returned ";
      result += LongToNAString((Lng32) error);
      Throw(env, result);
    }
  } // BeginTx

  else if (action.compareTo("CommitTx", NAString::ignoreCase) == 0)
  {
    error = ENDTRANSACTION();
    if (error)
    {
      if (error == 75)
      {
        result = "No active transaction";
      }
      else
      {
        result = "ENDTRANSACTION returned ";
        result += LongToNAString((Lng32) error);
      }
      Throw(env, result);
    }
  } // CommitTx

  else if (action.compareTo("RollbackTx", NAString::ignoreCase) == 0)
  {
    error = ABORTTRANSACTION();
    if (error)
    {
      if (error == 75)
      {
        result = "No active transaction";
      }
      else
      {
        result = "ABORTTRANSACTION returned ";
        result += LongToNAString((Lng32) error);
      }
      Throw(env, result);
    }
  } // RollbackTx

  else if (action.compareTo("GetProcessId", NAString::ignoreCase) == 0)
  {
    Lng32 pid = GETPID();
    result = LongToNAString(pid);
  } // GetProcessId

  else if (action.index("GetEnv ", 0, NAString::ignoreCase) == 0)
  {
    NAString name = action;
    name.remove(0, str_len("GetEnv "));
    TrimNAStringSpace(name);
    char *value = getenv(name.data());
    if (value != NULL)
    {
      result = value;
    }
    else
    {
      result = "";
    }
  } // GetEnv

  else if (action.index("PutEnv ", 0, NAString::ignoreCase) == 0)
  {
    NAString nameAndValue = action;
    nameAndValue.remove(0, str_len("PutEnv "));
    TrimNAStringSpace(nameAndValue);
    Int32 retcode = putenv((char *) nameAndValue.data());
    if (retcode != 0)
    {
      result = "putenv returned ";
      result += LongToNAString((Lng32) retcode);
      Throw(env, result);
    }
  } // PutEnv

  else if (action.index("LmDebug ", 0, NAString::ignoreCase) == 0)
  {
    NAString name = action;
    name.remove(0, str_len("LmDebug "));
    LM_DEBUG0(name.data());
  } // LmDebug

  else if (action.index("ExecSql ", 0, NAString::ignoreCase) == 0)
  {
    NAString stmtText = action.remove(0, str_len("ExecSql "));

    MXStatement s;
    const char *status = "OK";
    Lng32 retcode = 0;

    retcode = s.init(status);
  
    if (retcode == 0)
    {
      retcode = s.prepare(stmtText.data());
      if (retcode != 0)
      {
        status = "PREPARE failed";
      }
    }
  
    if (retcode == 0)
    {
      retcode = s.execute();
      if (retcode != 0)
      {
        status = "EXECUTE failed";
      }
    }
  
    if (retcode == 0)
    {
      retcode = s.fetchEOD();
      if (retcode != 0)
      {
        status = "FETCH failed";
      }
    }
  
    if (retcode == 0)
    {
      retcode = s.close();
      if (retcode != 0)
      {
        status = "CLOSE failed";
      }
    }

    if (retcode != 0)
    {
      char msg[256];
      sprintf(msg, "[UdrSqlException %d] %s", retcode, status);
      Throw(env, msg);
    }
  
  } // ExecSql

  else if (action.index("FetchSql ", 0, NAString::ignoreCase) == 0)
  {
    // The incoming string is SQL statement text. The code below will
    // prepare and execute the statement then fetch only the first
    // row. It will build one long multi-line string containing all
    // column values, one on each line. The multi-line string can be
    // split by the Java caller into an array of Strings with the
    // split("\n") method.

    Lng32 i;
    NAString stmtText = action.remove(0, str_len("FetchSql "));

    MXStatement s;
    const char *status = "OK";
    Lng32 retcode = 0;

    retcode = s.init(status);
  
    if (!retcode)
    {
      retcode = s.prepare(stmtText.data());
      if (retcode)
        status = "PREPARE failed";
    }
  
    if (!retcode)
    {
      retcode = s.execute();
      if (retcode)
        status = "EXECUTE failed";
    }

    Lng32 numOutColumns = s.getNumOutColumns();
    NABoolean stringsAllocated = FALSE;
    char **argv = NULL;

    if (!retcode && numOutColumns > 0)
    {
      argv = new char *[numOutColumns];
      Lng32 bufLen = 1000;
      for (i = 0; i < numOutColumns; i++)
        argv[i] = new char[bufLen + 1];

      stringsAllocated = TRUE;

      retcode = s.fetchStrings(argv, bufLen);
      if (retcode)
        status = "FETCH STRINGS failed";

      if (!retcode)
      {
        result = argv[0];
        for (i = 1; i < numOutColumns; i++)
        {
          result += "\n";
          result += argv[i];
        }
      }
    }
  
    if (!retcode)
    {
      retcode = s.fetchEOD();
      if (retcode)
        status = "FETCH EOD failed";
    }
  
    if (!retcode)
    {
      retcode = s.close();
      if (retcode)
        status = "CLOSE failed";
    }

    if (stringsAllocated)
    {
      for (i = 0; i < numOutColumns; i++)
        delete [] argv[i];
      delete [] argv;
    }

    if (retcode)
    {
      char msg[256];
      sprintf(msg, "[UdrSqlException %d] %s", retcode, status);
      Throw(env, msg);
    }
  
  } // FetchSql

  else if (action.index("Prepare ", 0, NAString::ignoreCase) == 0)
  {
    NAString stmtText = action.remove(0, str_len("Prepare "));

    const char *status = "OK";
    Lng32 retcode = 0;

    retcode = staticStmt.init(status);
  
    if (retcode == 0)
    {
      retcode = staticStmt.prepare(stmtText.data());
      if (retcode != 0)
      {
        status = "PREPARE failed";
      }
    }
  
    if (retcode)
    {
      char msg[256];
      sprintf(msg, "[UdrSqlException %d] %s", retcode, status);
      Throw(env, msg);
    }

  } // Prepare
  
  else if (action.index("ExecUsingString ", 0, NAString::ignoreCase) == 0)
  {
    NAString data = action.remove(0, str_len("ExecUsingString "));

    const char *status = "OK";
    Lng32 retcode = 0;

    if (retcode == 0)
    {
      retcode = staticStmt.executeUsingString(data.data(),
                                              (Lng32) data.length());
      if (retcode != 0)
      {
        status = "EXECUTE failed";
      }
    }
  
    if (retcode == 0)
    {
      retcode = staticStmt.fetchEOD();
      if (retcode != 0)
      {
        status = "FETCH failed";
      }
    }
  
    if (retcode == 0)
    {
      retcode = staticStmt.close();
      if (retcode != 0)
      {
        status = "CLOSE failed";
      }
    }

    if (retcode != 0)
    {
      char msg[256];
      sprintf(msg, "[UdrSqlException %d] %s", retcode, status);
      Throw(env, msg);
    }
  
  } // ExecUsingString

  else if (action.index("FetchUsingString ", 0, NAString::ignoreCase) == 0)
  {
    NAString data = action.remove(0, str_len("FetchUsingString "));
    const char *status = "OK";
    Lng32 retcode = 0;
    Int32 i = 0;

    if (!retcode)
    {
      retcode = staticStmt.executeUsingString(data.data(),
                                              (Lng32) data.length());
      if (retcode)
        status = "EXECUTE failed";
    }

    Lng32 numOutColumns = staticStmt.getNumOutColumns();
    NABoolean stringsAllocated = FALSE;
    char **argv = NULL;

    if (!retcode && numOutColumns > 0)
    {
      argv = new char *[numOutColumns];
      Lng32 bufLen = 1000;
      for (i = 0; i < numOutColumns; i++)
        argv[i] = new char[bufLen + 1];

      stringsAllocated = TRUE;

      retcode = staticStmt.fetchStrings(argv, bufLen);
      if (retcode)
        status = "FETCH STRINGS failed";

      if (!retcode)
      {
        result = argv[0];
        for (i = 1; i < numOutColumns; i++)
        {
          result += "\n";
          result += argv[i];
        }
      }
    }
  
    if (!retcode)
    {
      retcode = staticStmt.fetchEOD();
      if (retcode)
        status = "FETCH EOD failed";
    }
  
    if (!retcode)
    {
      retcode = staticStmt.close();
      if (retcode)
        status = "CLOSE failed";
    }

    if (stringsAllocated)
    {
      for (i = 0; i < numOutColumns; i++)
        delete [] argv[i];
      delete [] argv;
    }

    if (retcode)
    {
      char msg[256];
      sprintf(msg, "[UdrSqlException %d] %s", retcode, status);
      Throw(env, msg);
    }
  
  } // FetchUsingString

  else
  {
    //
    // Over time other operations can be supported
    //
    result = "Invalid action: ";
    result += action;
    Throw(env, result);
  }
// LCOV_EXCL_STOP

  //
  // Create the Java output string
  //
  if (env->ExceptionCheck() == JNI_FALSE)
  {
    jobject j = env->NewStringUTF(result.data());
    env->SetObjectArrayElement(joa, 0, j);
  }

}
NATraceList
ElemDDLConstraintRI::getDetailInfo() const
{
  //
  // constraint name and related information
  //

  NAString        detailText;
  NATraceList detailTextList = ElemDDLConstraint::getDetailInfo();

  //
  // match type
  //

  if (getMatchType() EQU COM_NONE_MATCH_OPTION)
  {
    detailTextList.append("Match type not specified.");
  }
  else
  {
    detailText = "Match type: ";
    detailText += getMatchTypeAsNAString();
    detailTextList.append(detailText);
  }

  //
  // delete rule
  //

  switch (getDeleteRule())
  {
  case COM_UNKNOWN_DELETE_RULE :
    if (isDeleteRuleSpecified())
    {
      ABORT("internal logic error");
    }
    detailTextList.append("Delete Rule not specified.");
    break;

  case COM_CASCADE_DELETE_RULE :
    detailTextList.append("Delete rule: Cascade");
    break;

  case COM_NO_ACTION_DELETE_RULE :
    detailTextList.append("Delete rule: No Action");
    break;

  case COM_SET_DEFAULT_DELETE_RULE :
    detailTextList.append("Delete rule: Set Default");
    break;

  case COM_SET_NULL_DELETE_RULE :
    detailTextList.append("Delete rule: Set Null");
    break;

  default :
    ABORT("internal logic error");
    break;
  }

  //
  // update rule
  //

  switch (getUpdateRule())
  {
  case COM_UNKNOWN_UPDATE_RULE :
    if (isUpdateRuleSpecified())
    {
      ABORT("internal logic error");
    }
    detailTextList.append("Update Rule not specified.");
    break;

  case COM_CASCADE_UPDATE_RULE :
    detailTextList.append("Update rule: Cascade");
    break;

  case COM_NO_ACTION_UPDATE_RULE :
    detailTextList.append("Update rule: No Action");
    break;

  case COM_SET_DEFAULT_UPDATE_RULE :
    detailTextList.append("Update rule: Set Default");
    break;

  case COM_SET_NULL_UPDATE_RULE :
    detailTextList.append("Update rule: Set Null");
    break;

  default :
    ABORT("internal logic error");
    break;
  }

  //
  // referencing information
  //

  CollIndex nbrRefCols;
  const ElemDDLColNameArray & cols = getReferencingColumns();

  nbrRefCols = cols.entries();

  if (nbrRefCols EQU 0)
  {
    detailTextList.append("Referencing column list is empty.");
  }
  else
  {
    detailText = "Referencing column list [";
    detailText += LongToNAString((Lng32)nbrRefCols);
    detailText += " element(s)]:";
    detailTextList.append(detailText);
  
    for (CollIndex i = 0; i < nbrRefCols; i++)
    {
      detailText = "[referencing column ";
      detailText +=  LongToNAString((Lng32)i);
      detailText += "]";
      detailTextList.append(detailText);
  
      detailTextList.append("    ", cols[i]->getDetailInfo());
    }
  }

  //
  // referenced information
  //

  ElemDDLReferences * pRefd = children_[INDEX_REFERENCED_TABLE_AND_COLUMNS]
        ->castToElemDDLReferences();
  
  detailTextList.append(pRefd->getDetailInfo());

  return detailTextList;
}
NATraceList
ElemDDLColDef::getDetailInfo() const
{
  NAString        detailText;
  NATraceList detailTextList;

  detailTextList.append(displayLabel1());  // column name
  detailTextList.append(displayLabel2());  // column data type

  //
  // default value for column
  //
  
  if (getDefaultValueExpr() NEQ NULL)
  {
    detailText = "Default value: ";
    detailText += getDefaultValueExpr()->getText();
    detailTextList.append(detailText);
  }
  else
  {
    detailTextList.append("No default value.");
  }

  //
  // heading information for column
  //

  if (NOT getHeading().isNull())
  {
    detailText = "Heading: ";
    detailText += getHeading();
    detailTextList.append(detailText);
  }
  else
  {
    detailTextList.append("No heading.");
  }

  //
  // not null (column) constraint information
  //

  detailText = "notnull? ";
  detailText += YesNo(getIsConstraintNotNullSpecified());
  detailTextList.append(detailText);

  //
  // primary key column constraint information
  //

  detailText = "prikey?  ";
  detailText += YesNo(getIsConstraintPKSpecified());
  detailTextList.append(detailText);
  
  //
  // information about other column constraint definitions
  //

  const ElemDDLConstraintArray & consList = getConstraintArray();
  CollIndex nbrConstraints = consList.entries();

  if (nbrConstraints EQU 0)
  {
    detailTextList.append("No column constraints.");
  }
  else
  {
    detailText = "Column Constraints list [";
    detailText += LongToNAString((Lng32)nbrConstraints);
    detailText += " element(s)]:";
    detailTextList.append(detailText);

    for (CollIndex i = 0; i < nbrConstraints; i++)
    {
      ElemDDLConstraint * cons = consList[i];

      detailText = "[column constraint ";
      detailText += LongToNAString((Lng32)i);
      detailText += "]";
      detailTextList.append(detailText);

      NATraceList constraintDetailTextList = cons->getDetailInfo();

      for (CollIndex j = 0; j <  constraintDetailTextList.entries(); j++)
      {
        detailTextList.append(NAString("    ") + constraintDetailTextList[j]);
      }
    }
  }

  return detailTextList;

} // ElemDDLColDef::getDetailInfo()
NATraceList
StmtDDLSchRevoke::getDetailInfo() const
{
    NAString        detailText;
    NATraceList detailTextList;

    //
    // object name
    //

    detailTextList.append(displayLabel1());   // object name

    //
    // privileges
    //

    StmtDDLSchRevoke * localThis = (StmtDDLSchRevoke *)this;

    detailTextList.append(localThis->getChild(INDEX_PRIVILEGES)
                          ->castToElemDDLNode()
                          ->castToElemDDLPrivileges()
                          ->getDetailInfo());

    //
    // grantee list
    //

    const ElemDDLGranteeArray & granteeArray = getGranteeArray();

    detailText = "Grantee list [";
    detailText += LongToNAString((Lng32)granteeArray.entries());
    detailText += " element(s)]";
    detailTextList.append(detailText);

    for (CollIndex i = 0; i < granteeArray.entries(); i++)
    {
        detailText = "[grantee ";
        detailText += LongToNAString((Lng32)i);
        detailText += "]";
        detailTextList.append(detailText);

        ComASSERT(granteeArray[i] NEQ NULL AND
                  granteeArray[i]->castToElemDDLGrantee() NEQ NULL);
        detailTextList.append("    ", granteeArray[i]->castToElemDDLGrantee()
                              ->getDetailInfo());
    }

    //
    // grant option for
    //

    detailText = "is grant option for? ";
    detailText += YesNo(isGrantOptionForSpecified());
    detailTextList.append(detailText);

    //
    // drop behavior
    //

    detailTextList.append(displayLabel2());   // drop behavior


    return detailTextList;

} // StmtDDLSchRevoke::getDetailInfo
Lng32 AddKeyGroups()
  {
  HSGlobalsClass *hs_globals = GetHSContext();
    if (HSGlobalsClass::isHiveCat(hs_globals->objDef->getCatName()))
      {
        // HSHiveTableDef::getKeyList()/getIndexArray() not yet implemented.
        *CmpCommon::diags() << DgSqlCode(-UERR_NO_ONEVERYKEY) << DgString0("hive");
        return -1;
      }

    Lng32 retcode = 0;
    Lng32 numColsInGroup = 0;
    HSColumnStruct col;
    NAString tempColList = "";
    NAString tempCol;
    NAString autoGroup;
    ULng32 numKeys;
    ULng32 i, j;
    NATable* naTbl = hs_globals->objDef->getNATable();
    HSLogMan *LM = HSLogMan::Instance();

    // ----------------------------------------------------------
    // Generate histograms for KEY
    // ----------------------------------------------------------
    // The clustering index is included in the list of indices returned by
    // NATable::getIndexList(), so we store its pointer so we can skip it
    // when the other indexes are processed below.
    NAFileSet* clusteringIndex = naTbl->getClusteringIndex();
    const NAColumnArray& keyCols = clusteringIndex->getIndexKeyColumns();
    Lng32 colPos;
    numKeys = keyCols.entries();

    if (numKeys == 1)     // SINGLE-COLUMN KEY
      {
        colPos = keyCols[0]->getPosition();
        if (LM->LogNeeded())
          {
            sprintf(LM->msg, "\t\tKEY:\t\t(%s)", hs_globals->objDef->getColName(colPos));
            LM->Log(LM->msg);
          }

        if (ColumnExists(colPos)) // avoid duplicates
          {
            LM->Log("\t\t** duplicate column group has been ignored.");
          }
        else                                 // add to single-column group list
          {
            retcode = AddSingleColumn(colPos);
          }
      }
    else if (numKeys > 1) // MULTI-COLUMN KEY
      {  
        // Create multiple MC group(s) if numkeys > 1.  Subset MC groups will
        // also be created if numkeys > 2,  E.g. If numkeys = 5, then
        // MC groups with 5, 4, 3, and 2 columns will be created using
        // the key columns.  Note that if numkeys is larger than CQD 
        // USTAT_NUM_MC_GROUPS_FOR_KEYS (default = 5), then the number
        // of groups created will be limited by this value.  So, e.g. if
        // numkeys = 10, then MC groups with 5, 4, 3, and 2 columns will
        // be created (that is, 5 groups will be created - incl the single).

        ULng32 minMCGroupSz = 2;
        ULng32 maxMCGroups  = (ULng32)
          CmpCommon::getDefaultNumeric(USTAT_NUM_MC_GROUPS_FOR_KEYS);

        // Generate no MCs with more cols than specified by the cqd.
        if (numKeys > maxMCGroups)
          numKeys = maxMCGroups;

        // For salted table, generate only the longest MC for the key (subject
        // to max cols determined above) unless a cqd is set to gen all MCs of
        // allowable sizes.
        if (CmpCommon::getDefault(USTAT_ADD_SALTED_KEY_PREFIXES_FOR_MC) == DF_OFF &&
            hs_globals->objDef->getColNum("_SALT_", FALSE) >= 0)
          minMCGroupSz = numKeys;

        while (numKeys >= minMCGroupSz)  // Create only MC groups not single cols
          {
            HSColSet colSet;

            autoGroup = "(";
            for (j = 0; j < numKeys; j++)
              {
                colPos = keyCols[j]->getPosition();
                col = hs_globals->objDef->getColInfo(colPos);
                col.colnum = colPos;
                colSet.insert(col);
                autoGroup += col.colname->data();
                autoGroup += ",";
              }

            if (LM->LogNeeded())
              {
                autoGroup.replace(autoGroup.length()-1,1,")");    // replace comma with close parenthesis
                sprintf(LM->msg, "\t\tKEY:\t\t%s", autoGroup.data());
                LM->Log(LM->msg);
              }

            if (retcode = AddColumnSet(colSet))
              {
                HSHandleError(retcode);
              }
            numKeys--;
          }
      }
  
    // ----------------------------------------------------------
    // Generate histograms for all INDEXES
    // ----------------------------------------------------------
    const NAFileSetList& indexes = naTbl->getIndexList();
    NAFileSet* index;
    for (i = 0; i < indexes.entries(); i++ )
      {
        index = indexes[i];
        if (index == clusteringIndex)
          continue;  // clustering index processed above already
        const NAColumnArray& keyCols = index->getIndexKeyColumns();
        numKeys = keyCols.entries();
        if (numKeys == 1)                            // SINGLE-COLUMN INDEX
          {
            colPos = keyCols[0]->getPosition();
            if (LM->LogNeeded())
              {
                sprintf(LM->msg, "\t\tINDEX[%d]\t(%s)", i, 
                        hs_globals->objDef->getColName(colPos));
                LM->Log(LM->msg);
              }
            if (ColumnExists(colPos)) // avoid duplicates
              {
                LM->Log("\t\t*** duplicate column group has been ignored.");
              }
            else                                 // add to single-column group list
              {
                retcode = AddSingleColumn(colPos);
              }
          }
        else // MULTI-COLUMN INDEX
          {  
            // Create multiple MC group(s) if numkeys > 1.  Subset MC groups will
            // also be created if numkeys > 2,  E.g. If numkeys = 5, then
            // MC groups with 5, 4, 3, and 2 columns will be created using
            // the key columns.  Note that if numkeys is larger than CQD 
            // USTAT_NUM_MC_GROUPS_FOR_KEYS (default = 5), then the number
            // of groups created will be limited by this value.  So, e.g. if
            // numkeys = 10, then MC groups with 10, 9, 8, 7, 6 columns will
            // be created (that is, 5 groups will be created).

            ULng32 minMCGroupSz = 2;
            ULng32 maxMCGroups  = (ULng32)
              CmpCommon::getDefaultNumeric(USTAT_NUM_MC_GROUPS_FOR_KEYS);
            if (numKeys > maxMCGroups) 
              minMCGroupSz = numKeys - maxMCGroups + 1;
            while (numKeys >= minMCGroupSz)  // MinMCGroupSz is greater than 1.
              {
              HSColSet colSet;

              tempColList = "";
              autoGroup = "(";
              for (j = 0; j < numKeys; j++)
                {
                  colPos = keyCols[j]->getPosition();
                  tempCol = ".";
                  tempCol += LongToNAString(colPos);
                  tempCol += ".";

                  // Eliminate duplicate columns in the index;
                  // They may have been introduced by appending the key to the specified index.
                  if (!tempColList.contains(tempCol))
                    {
                      col = hs_globals->objDef->getColInfo(colPos);
                      col.colnum = colPos;
                      colSet.insert((const struct HSColumnStruct) col);

                      tempColList += tempCol.data();
                      numColsInGroup++;
                      autoGroup += col.colname->data();
                      autoGroup += ",";
                    }
                }

              if (colSet.entries())
                {
                  if (numColsInGroup > 1)
                    {
                      if (LM->LogNeeded())
                        {
                          autoGroup.replace(autoGroup.length()-1,1,")");    // replace comma with close parenthesis
                          sprintf(LM->msg, "\t\tINDEX[%d]\t%s", i, autoGroup.data());
                          LM->Log(LM->msg);
                        }

                      if (retcode = AddColumnSet(colSet))
                        {
                          HSHandleError(retcode);
                        }
                    }
                  numColsInGroup = 0;
                }
              numKeys--;
              }
          }
      }

    return retcode;
  }