// 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; }
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; }