// For debugging only..
void showColSet(HSColSet &colSet, const char *title)
{
  HSLogMan *LM = HSLogMan::Instance();
  if (LM->LogNeeded())
    {
      UInt32 i;
      sprintf(LM->msg, title);
      LM->Log(LM->msg);
      for (i=0; i<colSet.entries(); i++)
        {
          sprintf(LM->msg, "\t\tcolSet[%d]: :%s: %d", i, colSet[i].colname->data(), colSet[i].colnum);
          LM->Log(LM->msg);
        }
    }
}
// This is called by AddSaltToIndexPrefixes() when a group (SC or MC) is found
// that coincides with the first n columns of an index (possibly excluding _SALT_),
// where n is the number of columns in the group. The function adds an MC group
// that adds _SALT_ (if missing) to the columns of the index contained in matchedGroup,
// in index order.
Lng32 AddSaltedIndexPrefix(NAFileSet* index,
                           HSColGroupStruct* matchedGroup,
                           NABoolean groupHasSalt)
{
  HSLogMan *LM = HSLogMan::Instance();
  HSGlobalsClass *hs_globals = GetHSContext();
  const NAColumnArray& inxCols = index->getIndexKeyColumns();
  HSColSet* saltedColSet = new(STMTHEAP) HSColSet(STMTHEAP);
  HSColumnStruct* colStruct;

  // If the group already contains _SALT_, there will be 1 less column of the
  // index to include.
  CollIndex lastColInxToInclude = matchedGroup->colCount;
  if (groupHasSalt)
    lastColInxToInclude--;

  // Create an MC that includes the columns of the matching MC with the columns
  // in index order, adding _SALT_ at the beginning if it wasn't present in the
  // original MC.
  for (CollIndex inxColInx=0; inxColInx<=lastColInxToInclude; inxColInx++)
    {
      colStruct = new(STMTHEAP) HSColumnStruct;
      *colStruct =  hs_globals->objDef
                              ->getColInfo(inxCols[inxColInx]->getPosition());
      colStruct->position = inxColInx;  // position in MC
      saltedColSet->insert(*colStruct);
    }

  if (!groupHasSalt && LM->LogNeeded())
    {
      snprintf(LM->msg, sizeof(LM->msg),
               "Adding an MC to duplicate index subset (%s) with \"_SALT_\" prefix added.",
               matchedGroup->colNames->data());
      LM->Log(LM->msg);
    }

  // If we formed the new, index-ordered group and had to add _SALT_, we leave
  // the original group in place. However, if the new group has the same cols
  // and only the order was changed, delete the original first, or the new one
  // will be rejected as a duplicate when we try to add it.
  if (groupHasSalt)
    hs_globals->removeGroup(matchedGroup);

  return AddColumnSet(*saltedColSet);
}
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;
  }
Lng32 AddColumnSet(HSColSet &colSet)
  {
    HSGlobalsClass *hs_globals = GetHSContext();
    Lng32 retcode = 0;
    HSColGroupStruct *newGroup  = NULL;
    Lng32 colCount = 0;
    NABoolean badColList = FALSE;
    NAString colNames = "";
    NAString temp;
    HSLogMan *LM = HSLogMan::Instance();
    Int32 numCols = colSet.entries();
    Int32 i;

    if (numCols < 2)          // Must have at least 2 columns in multi-col set.
      {
        if (LM->LogNeeded())
          {
            sprintf(LM->msg, "\t\tIgnoring Column Group with single unique entry (%s)", 
                             colSet[0].colname->data());
            LM->Log(LM->msg);
          }
        return HS_WARNING;
      }

    for (i=0; i<numCols; i++)          // update column numbers, position & NO DUPLICATES
      {
        HSColumnStruct &col = colSet[i];
        temp = " ";
        temp += ToAnsiIdentifier(col.colname->data());
          // Note: ToAnsiIdentifier() determines whether a name needs to be delimited
          // with quotes.  This function works for shift-JIS but may not work for other
          // non-ISO88591 char sets such as Korean, BIG5, GB2312, and GB18030, ...
        temp += ",";

        if (colNames.contains(temp))
          badColList = TRUE;
        else
          {
            col.colnum  = hs_globals->objDef->getColNum((char*)col.colname->data());
            if (col.colnum < 0)
              {
                retcode = -1;
                HSHandleError(retcode);
              }
            col.position = colCount;
            colCount++;
          }
        colNames += temp;
      }
    colNames.remove(0,1);    // remove first blank
    colNames.remove(colNames.length() - 1);    // remove last comma

    if (badColList)          // column list contains repeating columns
      {
        if (LM->LogNeeded())
          {
            sprintf(LM->msg, "\t\tNon-Unique Column Group (%s)", colNames.data());
            LM->Log(LM->msg);
          }
        HSFuncMergeDiags(- UERR_COLUMNLIST_NOT_UNIQUE, colNames.data());
        retcode = -1;
        HSHandleError(retcode);
      }
    else
      {
        if (GroupExists(colSet))
          {
            if (LM->LogNeeded())
              {
                sprintf(LM->msg, "\t\tDuplicate Column Group (%s) has been ignored.", colNames.data());
                LM->Log(LM->msg);
              }
            retcode = HS_WARNING;
          }
        else
          {
            newGroup  = new(STMTHEAP) HSColGroupStruct;
            newGroup->colSet = colSet;
            newGroup->colCount = colCount;
            *newGroup->colNames = colNames.data();

            if (hs_globals->multiGroup == NULL)    // first group entry
              {
                hs_globals->multiGroup = newGroup;
              }
            else                  // append to front of list
              {
                newGroup->next = hs_globals->multiGroup;
                hs_globals->multiGroup->prev = newGroup;
                hs_globals->multiGroup = newGroup;
              }

            hs_globals->groupCount++;
          }
      }

    return retcode;
  }
// -----------------------------------------------------------------------
// Construct a fully qualified table name.
// -----------------------------------------------------------------------
Lng32 AddTableName( const hs_table_type type
                 , const char *table
                 , const char *schema
                 , const char *catalog
                 )
  {
    HSGlobalsClass *hs_globals = GetHSContext();
    NAString catName, schName, objName;
    NAString extName;
    NAString defaultCat, defaultSch;
    NAString userLocation;
    Lng32 retcode = 0;

    hs_globals->tableType = type;
    HSLogMan *LM = HSLogMan::Instance();
  
    // SET MPLOC is converted to CQD (setting values for default
    // attributes MP_SYSTEM, MP_VOLUME, MP_SUBVOLUME).  It does not
    // update the global MPLOC value stored in SqlParser_MPLOC.  The
    // following updates the global MPLOC value to be consistent with
    // the default attribute values set by SET MPLOC/CQD.
    ActiveSchemaDB()->getDefaults().getSqlParser_NADefaults();

    if (type == GUARDIAN_TABLE)
      {
        if (*table == '$')
          { // Qualify with system name.
            extName  = SqlParser_MPLOC.getSystemName();
            extName += ".";
            extName += table;
          }
        else
          extName = table;
        hs_globals->tableFormat = SQLMP;
      }
    else
      {
        // When CQD DEFAULT_SCHEMA_ACCESS_ONLY is on, 
        // users cannot update stats on tables not in the default/public schemas.
        if ( schema && 
             ActiveSchemaDB()->getDefaults().getToken(DEFAULT_SCHEMA_ACCESS_ONLY)==DF_ON )
        {
          SchemaName objSchName;
          NAString curSchName(schema);
          NAString curCatName;
          objSchName.setSchemaName(curSchName);
          if (catalog)
          {
            curCatName = catalog;
            objSchName.setCatalogName(curCatName);
          }
          else
            curCatName = ActiveSchemaDB()->getDefaultSchema().getCatalogName();

          // If the schema is neither default nor public,
          // issue inaccessible error.
          if (!objSchName.matchDefaultPublicSchema())
          {
            NAString dataObj(curCatName);
            if (!dataObj.isNull()) dataObj += ".";
            dataObj += curSchName + ".";
            dataObj += table;
            HSFuncMergeDiags(-UERR_OBJECT_INACCESSIBLE, dataObj.data());
            retcode = -1;
            HSHandleError(retcode);
          }
        }

        if (catalog)
          catName = catalog;
        else
          {
            // LCOV_EXCL_START :nsk
            if (SqlParser_NAMETYPE == DF_NSK)
              {
                catName = SqlParser_MPLOC.getSysDotVol();
                hs_globals->tableType = GUARDIAN_TABLE;
                hs_globals->tableFormat = SQLMP;
              }
            else
            // LCOV_EXCL_STOP
              catName = ActiveSchemaDB()->getDefaultSchema().getCatalogName();
          }
  
        if (schema)
          schName = schema;
        else
          {
            // LCOV_EXCL_START :nsk
            if (SqlParser_NAMETYPE == DF_NSK)
              {
                schName = SqlParser_MPLOC.getSubvolName();
                hs_globals->tableFormat = SQLMP;
              }
            else
            // LCOV_EXCL_STOP
              schName = ActiveSchemaDB()->getDefaultSchema().getSchemaName();
          }
  
        objName = table;
        extName = catName + "." + schName + "." + objName;
      }
  
    // LCOV_EXCL_START :nsk
    if (hs_globals->tableFormat == SQLMP)
      {
        ComMPLoc loc(extName, ComMPLoc::FILE);
        if (loc.getFormat() == ComMPLoc::INVALID)
          {
            HSFuncMergeDiags(-UERR_OBJECT_INACCESSIBLE, extName);
            retcode = -1;
            HSHandleError(retcode);
          }
  
        catName = loc.getSysDotVol();
        schName = loc.getSubvolName();
        objName = loc.getFileName();
      }
    // LCOV_EXCL_STOP

    hs_globals->objDef = NULL;
    
    // Search in volatile schema first. If not found, search in regular cat/sch.
    if ((CmpCommon::context()->sqlSession()->volatileSchemaInUse()) &&
        (type != GUARDIAN_TABLE) &&
        (! catalog))
      {
        // search using the volatile schema name.
        NAString &volCatName = CmpCommon::context()->sqlSession()->volatileCatalogName();
        NAString &volSchName = CmpCommon::context()->sqlSession()->volatileSchemaName();
        NAString volObjName = table;
	
        
        ComObjectName volIntName(volCatName, volSchName, volObjName,
                                 COM_UNKNOWN_NAME, 
                                 ComAnsiNamePart::INTERNAL_FORMAT);
        if (NOT volIntName.isValid())
          {
            LM->Log("***[ERROR] Unable to create an ObjectClass");
            HSFuncMergeDiags(-UERR_OBJECT_INACCESSIBLE, extName);
            retcode = -1;
            HSHandleError(retcode);
          }
	
        if (LM->LogNeeded())
          {
            LM->Log("Searching in volatile schema, since catalog not specified.\n");
            sprintf(LM->msg, "Checking volatile name (volIntName) %s.%s.%s\n",
                    volIntName.getCatalogNamePart().getInternalName().data(),
                    volIntName.getSchemaNamePart().getInternalName().data(),
                    volIntName.getObjectNamePart().getInternalName().data());
            LM->Log(LM->msg);
          }

        hs_globals->objDef = HSTableDef::create(STMTHEAP,
                                                volIntName,
                                                hs_globals->tableType,
                                                hs_globals->nameSpace);
      	if (NOT hs_globals->objDef->objExists(HSTableDef::MAX_INFO))
          {
            // now look into the regular schema
            delete hs_globals->objDef;
            hs_globals->objDef = NULL;
          }
        else 
          {
            // if schema name was specified, validate that it is the
            // current username.
            if (schema)
              {
                QualifiedName qn(volObjName, schName);
                if (NOT CmpCommon::context()->sqlSession()->validateVolatileQualifiedName(qn))
                  {
                    // table was found in the volatile schema but it is
                    // not a valid volatile name.
                    // Look for it in regular schema.
                    // error info was moved to CmpCommon::diags. Clear it.
                    CmpCommon::diags()->clear();
                    delete hs_globals->objDef;
                    hs_globals->objDef = NULL;
                  }
              }
          }
      }      
    
    if (hs_globals->objDef == NULL)
      {
	ComObjectName intName(catName, schName, objName,
			      COM_UNKNOWN_NAME, 
			      ComAnsiNamePart::INTERNAL_FORMAT);
	if (NOT intName.isValid())
	  {
	    LM->Log("***[ERROR] Unable to create an ObjectClass");
	    HSFuncMergeDiags(-UERR_OBJECT_INACCESSIBLE, extName);
	    retcode = -1;
	    HSHandleError(retcode);
	  }
	

  hs_globals->objDef = HSTableDef::create(STMTHEAP,
                                          intName,
                                          hs_globals->tableType,
                                          hs_globals->nameSpace);

  // try public schema if an object is not qualified and not found
  if ((NOT schema) && 
      (NOT hs_globals->objDef->objExists(HSTableDef::MAX_INFO)))
	  {
      NAString pubSch = ActiveSchemaDB()->getDefaults().getValue(PUBLIC_SCHEMA_NAME);
      ComSchemaName pubSchema(pubSch);
      if (NOT pubSchema.getSchemaNamePart().isEmpty())
      {
        NAString pubSchName = pubSchema.getSchemaNamePart().getInternalName();
        NAString pubCatName = (pubSchema.getCatalogNamePart().isEmpty() ? 
          catName:pubSchema.getCatalogNamePart().getInternalName());
      	ComObjectName pubIntName(pubCatName, pubSchName, objName,
			                           COM_UNKNOWN_NAME, ComAnsiNamePart::INTERNAL_FORMAT);
	      if (pubIntName.isValid())
	      {
          HSTableDef *pubObjDef = HSTableDef::create(STMTHEAP,
                                                     pubIntName, 
                                                     hs_globals->tableType,
                                                     hs_globals->nameSpace);
          if (pubObjDef->objExists(HSTableDef::MAX_INFO))
          {
            hs_globals->objDef = pubObjDef;
          }
	      }
      }
	  }

	if (NOT hs_globals->objDef->objExists(HSTableDef::MAX_INFO))
	  {
	    HSFuncMergeDiags(-UERR_OBJECT_INACCESSIBLE, extName);
	    retcode = -1;
	    HSHandleError(retcode);
	  }
      }

    //10-040123-2660 We only support tables. We do not allow views.
    // Tables can be metadata tables.
    if ((hs_globals->objDef->getObjectType() != COM_BASE_TABLE_OBJECT) &&
        (hs_globals->objDef->getObjectType() != COM_MV_OBJECT)) 
      {
        HSFuncMergeDiags(-UERR_INVALID_OBJECT, extName);
        retcode = -1;
        HSHandleError(retcode);
      }
    retcode = hs_globals->objDef->getColumnNames();
    HSFuncExecQuery("CONTROL QUERY DEFAULT DISPLAY_DIVISION_BY_COLUMNS RESET");
    HSHandleError(retcode);

    hs_globals->tableFormat = hs_globals->objDef->getObjectFormat();
    *hs_globals->catSch     = hs_globals->objDef->getPrimaryLoc(HSTableDef::EXTERNAL_FORMAT);
    *hs_globals->user_table = hs_globals->objDef->getObjectFullName();
    hs_globals->tableFormat = hs_globals->objDef->getObjectFormat();
    hs_globals->isHbaseTable = HSGlobalsClass::isHbaseCat(catName);

    if (hs_globals->tableFormat == SQLMX)
      {
        // Determine the schema version for this MX table.
        if (LM->LogNeeded())
         {
            sprintf(LM->msg, "\nCHECK SCHEMA VERSION FOR TABLE: %s\n", 
              hs_globals->user_table->data());
            LM->Log(LM->msg);
         }
        HSGlobalsClass::schemaVersion = getTableSchemaVersion(hs_globals->user_table->data());
        // LCOV_EXCL_START :rfi
        if (HSGlobalsClass::schemaVersion == COM_VERS_UNKNOWN)
        {
           HSFuncMergeDiags(-UERR_INTERNAL_ERROR, "GET_SCHEMA_VERSION");
           return -1;
        }
        // LCOV_EXCL_STOP


        if (HSGlobalsClass::schemaVersion >= COM_VERS_2300) 
          HSGlobalsClass::autoInterval = CmpCommon::getDefaultLong(USTAT_AUTOMATION_INTERVAL);
        if (LM->LogNeeded())
         {
            sprintf(LM->msg, "\nUpdateStats: TABLE: %s; SCHEMA VERSION: %d; AUTOMATION INTERVAL: %d\n", 
                  hs_globals->user_table->data(), 
                  HSGlobalsClass::schemaVersion, HSGlobalsClass::autoInterval);
            LM->Log(LM->msg);
         }

        const char* period = strchr(hs_globals->catSch->data(), '.');
        NAString catName(hs_globals->catSch->data(),
                         period - hs_globals->catSch->data());
        NABoolean isHbaseOrHive = HSGlobalsClass::isHbaseCat(catName) ||
                                  HSGlobalsClass::isHiveCat(catName);

        *hs_globals->hstogram_table = 
            getHistogramsTableLocation(hs_globals->catSch->data(), FALSE);
        if (isHbaseOrHive)
          hs_globals->hstogram_table->append(".").append(HBASE_HIST_NAME);
        else
          hs_globals->hstogram_table->append(".HISTOGRAMS");

        *hs_globals->hsintval_table = 
            getHistogramsTableLocation(hs_globals->catSch->data(), FALSE);
        if (isHbaseOrHive)
          hs_globals->hsintval_table->append(".").append(HBASE_HISTINT_NAME);
        else
          hs_globals->hsintval_table->append(".HISTOGRAM_INTERVALS");
      }
    else
      {
        // LCOV_EXCL_START :nsk
        *hs_globals->hstogram_table = hs_globals->objDef->getCatalogLoc(HSTableDef::EXTERNAL_FORMAT);
        hs_globals->hstogram_table->append(".HISTOGRM");
        
        *hs_globals->hsintval_table = hs_globals->objDef->getCatalogLoc(HSTableDef::EXTERNAL_FORMAT);
        hs_globals->hsintval_table->append(".HISTINTS");        

        // RESET CQDS:
        HSFuncExecQuery("CONTROL QUERY DEFAULT DETAILED_STATISTICS RESET");
        HSFuncExecQuery("CONTROL QUERY DEFAULT ALLOW_DP2_ROW_SAMPLING RESET");
        HSFuncExecQuery("CONTROL QUERY DEFAULT POS RESET");
        HSFuncExecQuery("CONTROL QUERY DEFAULT POS_NUM_OF_PARTNS RESET");
        // LCOV_EXCL_STOP
      }
  
    return 0;
  }
// -----------------------------------------------------------------------
// Add the single-column groups from startColumn to endColumn. If these
// parameters are NULL, the function has been called for the ON EVERY COLUMN
// clause, and we will add all single column groups, as well as key groups.
// -----------------------------------------------------------------------
Lng32 AddEveryColumn(const char *startColumn, const char *endColumn)
  {
    HSGlobalsClass *hs_globals = GetHSContext();
    Lng32 colNumber, retcode;
    NAString colName;
    Lng32 start, upto;
    HSLogMan *LM = HSLogMan::Instance();
    hs_globals->parserError = HSGlobalsClass::ERROR_SEMANTICS;

    // Can't use EVERYCOL_OPT flag for this test, it may have been set on a
    // previous call (making this a redundant, or incorrect, request to ustat
    // an individual column name). startColumn will always be NULL if this fn
    // is called to add all the columns for a table.
    if (!startColumn)
      {
        HS_ASSERT(hs_globals->optFlags & EVERYCOL_OPT);
        start = 0;
        upto  = hs_globals->objDef->getNumCols() - 1;
      }
    else
      {
        start = hs_globals->objDef->getColNum(startColumn);
        // LCOV_EXCL_START :rfi
        if (start < 0)
          {
            retcode = -1;
            HSHandleError(retcode);
          }
        // LCOV_EXCL_STOP
        upto  = hs_globals->objDef->getColNum(endColumn);
        // LCOV_EXCL_START :rfi
        if (upto < 0)
          {
            retcode = -1;
            HSHandleError(retcode);
          }
        // LCOV_EXCL_STOP

        if (start > upto)
          {
            Lng32 tmp = upto;
            upto = start;
            start = tmp;
          }
      }

    for (colNumber = start; colNumber <= upto; colNumber++)
      {
        if (ColumnExists(colNumber))      // avoid duplicates
          {
            colName = hs_globals->objDef->getColName(colNumber);
            if (LM->LogNeeded())
              {
                sprintf(LM->msg, "\t\t****Duplicate Column group (%s) has been ignored", colName.data());
                LM->Log(LM->msg);
              }
          }
        else                                 // add to single-column group list
          {
            retcode = AddSingleColumn(colNumber);
          }
      }

    if (!startColumn &&  // ON EVERY COLUMN causes key groups to be added as well
        !HSGlobalsClass::isHiveCat(hs_globals->objDef->getCatName()))  // No ustat on keys yet for hive tables
      {
        retcode = AddKeyGroups();
        HSHandleError(retcode);
      }

    hs_globals->parserError = HSGlobalsClass::ERROR_SYNTAX;
    return 0;
  }
示例#7
0
Lng32 HSSqTableDef::DescribeColumnNames()
  {
    Lng32 entry, len;
    NAString query;
    char colName[ComMAX_1_PART_INTERNAL_UTF8_NAME_LEN_IN_BYTES + 2];
    HSLogMan *LM = HSLogMan::Instance();

    SQLMODULE_ID module;
    init_SQLMODULE_ID(&module);

    SQLSTMT_ID *stmt = new(STMTHEAP) SQLSTMT_ID;
    init_SQLCLI_OBJ_ID(stmt);
    stmt->module = &module;
    stmt->name_mode = stmt_handle;

    SQLDESC_ID *srcDesc = new(STMTHEAP) SQLDESC_ID;
    init_SQLCLI_OBJ_ID(srcDesc);
    srcDesc->module = &module;
    srcDesc->name_mode = desc_handle;

    SQLDESC_ID *outputDesc = new(STMTHEAP) SQLDESC_ID;
    init_SQLCLI_OBJ_ID(outputDesc);
    outputDesc->module = &module;
    outputDesc->name_mode = desc_handle;

    // Use the header information from a 'select *' to get the column names. 
    // Note that this works for SJIS and UTF8 since the names returned through
    // CLI are encoded correctly.
    retcode_ = setHasSyskeyFlag();
    HSHandleError(retcode_);
    if (hasSyskey_)
      query  = "SELECT SYSKEY, * FROM ";
    else
      query  = "SELECT * FROM ";
    if(objActualFormat_ == SQLMP)
      query += getTableName(tableName_->data(), nameSpace_);
    else
      query += getTableName(ansiName_->data(), nameSpace_);

    retcode_ = SQL_EXEC_ClearDiagnostics(stmt);
    // to prevent false alarms for statement heap memory allocation "smt"
    // coverity[leaked_storage]
    HSHandleError(retcode_);

    retcode_ = SQL_EXEC_AllocStmt(stmt, 0);
    HSHandleError(retcode_);
    retcode_ = SQL_EXEC_AllocDesc(srcDesc, 1);
    HSHandleError(retcode_);
    retcode_ = SQL_EXEC_AllocDesc(outputDesc, 4096);
    HSHandleError(retcode_);

    retcode_ = SQL_EXEC_SetDescItem(srcDesc, 1, SQLDESC_TYPE_FS,
                                    REC_BYTE_V_ANSI, 0);
    HSHandleError(retcode_);
    retcode_ = SQL_EXEC_SetDescItem(srcDesc, 1, SQLDESC_VAR_PTR,
                                    (Long)query.data(), 0);
    HSHandleError(retcode_);
    retcode_ = SQL_EXEC_SetDescItem(srcDesc, 1, SQLDESC_LENGTH,
#pragma nowarn(1506)   // warning elimination
                                    query.length() + 1, 0);
#pragma warn(1506)  // warning elimination
    HSHandleError(retcode_);
    // SQLDESC_CHAR_SET must be the last descriptor item set, otherwise
    // it may get reset by other calls to SQL_EXEC_SetDescItem().
    NAString charSet = ActiveSchemaDB()->getDefaults().getValue(ISO_MAPPING);
    NAString defCS   = ActiveSchemaDB()->getDefaults().getValue(DEFAULT_CHARSET);
    retcode_ = SQL_EXEC_SetDescItem(srcDesc, 1, SQLDESC_CHAR_SET,
                                    SQLCHARSETCODE_UTF8
                                    , 0);
    HSHandleError(retcode_);

    // ---------------------------------------------------------------------
    // Prepare the statement
    // ---------------------------------------------------------------------
    SQL_QUERY_COST_INFO query_cost_info;
    SQL_QUERY_COMPILER_STATS_INFO comp_stats_info;
   
    retcode_ = SQL_EXEC_Prepare2(stmt, srcDesc,NULL,0,NULL,&query_cost_info, &comp_stats_info,NULL,0,0);
    HSHandleError( retcode_);

    // ---------------------------------------------------------------------
    // describe the column information into the output descriptor
    // ---------------------------------------------------------------------
    retcode_ = SQL_EXEC_DescribeStmt(stmt, 0, outputDesc);
    HSHandleError(retcode_);

    retcode_ = SQL_EXEC_GetDescEntryCount(outputDesc, &numCols_);
    HSHandleError(retcode_);

    colInfo_ = new(STMTHEAP) HSColumnStruct[numCols_];
    for (Int32 i = 0; i < numCols_; i++)
      {
                                                  /*==   GET COLUMN NAME   ==*/
        entry = i + 1;
        retcode_ = SQL_EXEC_GetDescItem(outputDesc, entry,
                                        SQLDESC_NAME,
                                        0, colName, sizeof(colName), &len, 0);
        if ((retcode_ == 0) &&
            (len >= sizeof(colName) ))
          retcode_ = -1;
        HSHandleError(retcode_);
        colName[len] = '\0';
        *colInfo_[i].colname = &*colName;
                                                  /*== GET COLUMN DATATYPE ==*/
        retcode_ = SQL_EXEC_GetDescItem(outputDesc, entry,
                                        SQLDESC_TYPE_FS,
                                        &colInfo_[i].datatype,
                                        0, 0, 0, 0);
        HSHandleError(retcode_);

        retcode_ = SQL_EXEC_GetDescItem(outputDesc, entry,
                                        SQLDESC_NULLABLE,
                                        &colInfo_[i].nullflag,
                                        0, 0, 0, 0);
        HSHandleError(retcode_);
                                                  /*==  GET COLUMN LENGTH  ==*/
        retcode_ = SQL_EXEC_GetDescItem(outputDesc, entry,
                                        SQLDESC_OCTET_LENGTH,
                                        &colInfo_[i].length,
                                        0, 0, 0, 0);
        HSHandleError(retcode_);

        // If applicable, get the character set, precision and scale
        if (DFS2REC::isAnyCharacter(colInfo_[i].datatype))
          {
            retcode_ = SQL_EXEC_GetDescItem(outputDesc, entry,
                                            SQLDESC_CHAR_SET,
                                            (Lng32*)&colInfo_[i].charset, 0, 0, 0, 0);
            HSHandleError(retcode_);
            // UCS2 cols not supported in MODE_SPECIAL_1 or 2 and do not support case insensitivity.
            retcode_ = SQL_EXEC_GetDescItem(outputDesc, entry,
                                            SQLDESC_CASEINSENSITIVE,
                                            (Lng32*)&colInfo_[i].caseInsensitive, 0, 0, 0, 0);
            HSHandleError(retcode_);
            retcode_ = SQL_EXEC_GetDescItem(outputDesc, entry,
                                            SQLDESC_COLLATION,
                                            (Lng32*)&colInfo_[i].colCollation, 0, 0, 0, 0);
            HSHandleError(retcode_);
          }
        else if ((colInfo_[i].datatype >= REC_MIN_BINARY &&  // May be type NUMERIC
                  colInfo_[i].datatype <= REC_MAX_BINARY)    //    instead of INT
                     ||
                 (colInfo_[i].datatype >= REC_MIN_DECIMAL &&
                 colInfo_[i].datatype <= REC_MAX_DECIMAL))
          {
            retcode_ = SQL_EXEC_GetDescItem(outputDesc, entry,                
                                           SQLDESC_PRECISION,                  
                                           &colInfo_[i].precision, 0, 0, 0, 0);
            HSHandleError(retcode_);
            retcode_ = SQL_EXEC_GetDescItem(outputDesc, entry,                
                                           SQLDESC_SCALE,                  
                                           &colInfo_[i].scale, 0, 0, 0, 0);
            HSHandleError(retcode_);
          }
        else if (DFS2REC::isDateTime(colInfo_[i].datatype))
          {
            retcode_ = SQL_EXEC_GetDescItem(outputDesc, entry,
                                           SQLDESC_DATETIME_CODE,
                                           &colInfo_[i].precision, 0, 0, 0, 0);
            HSHandleError(retcode_);
            retcode_ = SQL_EXEC_GetDescItem(outputDesc, entry,
                                           SQLDESC_PRECISION,
                                           &colInfo_[i].scale, 0, 0, 0, 0);
            HSHandleError(retcode_);
          }
        else if (DFS2REC::isInterval(colInfo_[i].datatype))
          {
            retcode_ = SQL_EXEC_GetDescItem(outputDesc, entry,                
                                            SQLDESC_INT_LEAD_PREC,              
                                            &colInfo_[i].precision, 0, 0, 0, 0);
            HSHandleError(retcode_);                                           
            retcode_ = SQL_EXEC_GetDescItem(outputDesc, entry,                
                                            SQLDESC_PRECISION,                  
                                            &colInfo_[i].scale, 0, 0, 0, 0);
            HSHandleError(retcode_);
          }
        else
          {
            /* No additional information about column attributes needed */
          }

        if (LM->LogNeeded())
          {
            sprintf(LM->msg, "COLUMN [%s]: (%d, %d, %d, %d, %d, %d)"
                                , colInfo_[i].colname->data()
                                , colInfo_[i].datatype
                                , colInfo_[i].nullflag
                                , colInfo_[i].charset
                                , colInfo_[i].length
                                , colInfo_[i].precision
                                , colInfo_[i].scale
                   );
            LM->Log(LM->msg);
          }
      }
    retcode_ = SQL_EXEC_DeallocStmt(stmt);
    HSHandleError(retcode_);

    return 0;
  }