NAString TDBDlgExprList::ExprNodeFlagsToString(ex_expr* exprNode)
{
   NAString string;
   
   if (exprNode->getFixupConstsAndTemps())
    string += "FIXUP_CONSTS_AND_TEMPS|";

   if (exprNode->generateNoPCode())
     string += "GENERATE_NO_PCODE|";

   if (exprNode->getPCodeGenCompile())
     string += "PCODE_GEN_COMPILE|";
   
   if (exprNode->getPCodeMoveFastpath())
     string += "PCODE_MOVE_FASTPATH|";

   if (exprNode->forInsertUpdate())
     string += "FOR_INSERT_UPDATE|";

   if (exprNode->usePCodeEvalAligned())
     string += "PCODE_EVAL_ALIGNED|";

   if (exprNode->handleIndirectVC())
     string += "HANDLE_INDIRECT_VC|";

   if (exprNode-> getPCodeNative())
     string += "PCODE_EVAL_NATIVE";
   
   int len = string.length();
   string.remove(len-1);

   return string;
}
//
// data (begin or end) is in this format: 
//  <length><data> ... <length><data>
//
// a). length is 2-bytes long
// b). data is <length>-bytes long
// c). there are <n> such pairs, where <n> is determined by
//     the total length of the source and the length of each pair.
//
static NABoolean extractKeyValuePairs(const NAString& source, NAString& result) 
{
   char buf[1024];

   const char* data = source.data();
   const char* end = data + source.length();

   NABoolean hasData = ( data < end);

   while ( data < end ) {
       UInt16 len = 0;
       memcpy((char*)&len, data, sizeof(len));

       memcpy(buf, data+sizeof(len), len);
       buf[len] = NULL;

       result.append(buf);

       data += sizeof(len) + len;

       if ( data < end )
          result.append(",");
   }
   return hasData;
}
// -----------------------------------------------------------------------
// Translate ANSI SQL names from Default ANSI SQL Name character set
// to UCS-2 encoding values.  The contents of the outWcs parameter is
// clear and set to the newly computed UCS2 string
// -----------------------------------------------------------------------
void CmAnsiNameToUCS2(const NAString &inMbs, NAWString &outWcs)
{
  outWcs.remove(0); // set to an empty string
  if (inMbs.length() <= 0)
  {
    return;
  }
  NAWString * pTargetNAWString =
    charToUnicode ( (Lng32)ComGetNameInterfaceCharSet() // in - Lng32        strCharSet
                  , inMbs.data()                        // in - const char * str
                  , (Int32)inMbs.length()               // in - Int32        len
                  , (NAMemory *)STMTHEAP                // in - NAMemory *   h
                  );
  ComASSERT(pTargetNAWString != NULL AND pTargetNAWString->length() > 0 AND
             pTargetNAWString->length() <= ComMAX_ANSI_IDENTIFIER_INTERNAL_LEN/*in NAWchars*/);
  outWcs.append(pTargetNAWString->data(), pTargetNAWString->length());
  delete pTargetNAWString;
}
//LCOV_EXCL_START /* : cnu -- not used on Linux */
// -----------------------------------------------------------------------
// makeSafeFilenamePart() and
// QualifiedName::getQualifiedNameAsAnsiNTFilenameString()
//
// Genesis 10-990113-5782
// Make sure that the end result of this function results in a valid
// file name for the system -- whether NT or OSS.
//
// Convert any invalid NT filename characters to underscores.
//
// A valid NT (or OSS) filename may be up to 255 characters including spaces.
// The characters
//	\/:*?<>|"
// are not allowed in the filename at all.
// Furthermore, a POSIX shell (MKS KornShell on NT, OSS on NSK)
// treats the following specially, so they do not make good chars for filenames:
//	$%&();' and space
//
// SQL identifiers can be up to 128 characters long in regular or
// delimited format.
//
// Regular identifiers begin with A-Z or a-z and can contain digits 0-9 or
// underscores.  Regular identifiers are not case sensitive.  Reserved words
// may not be used in a regular identifier.
//
// Delimited identifiers always begin with a " character, and can contain
// both upper and lowercase Latin-1 characters, as well as
//	\/|<>*?:"
//	$%&();' and space
//	+-=[],.
//	digits 0-9 and underscore
//
// This routine will convert all non-alphanumeric chars
// to the underscore character, and result in a filename which when treated
// as an Ansi qualified name (a MODULE name), is composed only of regular
// identifiers -- no "quoting" needed.
//
// The length of a module name that might get generated
// could be a string of over 255 characters.  128 for each of the three parts.
// 2 characters for each part if delimited plus the period separators not
// counting any quotes which are embedded and doubled which might be
// singled again.
//
// There might still be problems because NT is not case sensitive but
// SQL is where delimited identifiers are concerned and that is not being
// addressed here.  We're just going to assume that we won't have two
// catalogs and schemas that are the same delimited if case is not considered
// that will cause problems in NT.  We will be replacing all characters
// that cause the name to be delimited with underscore.
//
// If we need to truncate any one of the three parts (not generally the
// user supplied portion (mainly just the module name portion), then we
// will need to verify that the truncated result does not result in a
// reserved word.  Might possibly happen depending on how we decide to
// handle the case where the length of 2 of the parts nears the 255
// character file name limit for NT and we decide to truncate one part
// down to a size that might result in a reserved word.
// -----------------------------------------------------------------------
//
static void makeSafeFilenamePart(NAString &ns, const NAString &prefix)
{
  size_t len = ns.length();
  for (size_t i=0; i<len; i++) {
    if (!isalnum(ns[i]) && ns[i] != '_')
      ns[i] = '_';
  }

  if (!len || !isalpha(ns[(size_t)0]))	// must begin with an alphabetic
    ns.prepend(prefix);
}
Beispiel #5
0
void CmpSqlSession::setSessionId(NAString &sessionID)
{
  sessionID_ = sessionID;

  if (NOT sessionID_.isNull())
    {
      volatileSchemaName_ = COM_VOLATILE_SCHEMA_PREFIX;
      volatileSchemaName_  += COM_SESSION_ID_PREFIX;
      
      char sName[200];
      Int64 cpu_l;
      Int64 pin_l;
      Int64 schemaNameCreateTime = 0;
      Int64 sessionUniqNum;
      Lng32 userNameLen = 0;
      Lng32 userSessionNameLen = 0;
      ComSqlId::extractSqlSessionIdAttrs
	((char*)sessionID.data(),
	 sessionID.length(),
	 segmentNum_,
	 cpu_l,
	 pin_l,
	 schemaNameCreateTime,
	 sessionUniqNum,
	 userNameLen, NULL,
	 userSessionNameLen, NULL);
      str_sprintf(sName, "%02d%03Ld%06Ld%018Ld%010Ld",
		  ComSqlId::SQ_SQL_ID_VERSION,
		  segmentNum_, pin_l, schemaNameCreateTime,
		  sessionUniqNum);
      volatileSchemaName_ += sName;

      volatileSchemaName_.toUpper();

      // get segment name
      segmentName_ = "NSK";

      sessionInUse_ = TRUE;
      volatileSchemaInUse_ = FALSE;
      //
      // it's a new session
      numSessions_++;
    }
  else
    {
      sessionInUse_ = FALSE;
      volatileSchemaInUse_ = FALSE;
    }
}
Beispiel #6
0
// ----------------------------------------------------------------------------
// method: isAuthNameReserved
//
// Checks to see if proposed name is reserved
//
// Input: authorization name
//
// Output:
//   true - name is reserved
//   false - name is not reserved
// ----------------------------------------------------------------------------
bool CmpSeabaseDDLauth::isAuthNameReserved (const NAString &authName)
{
  bool result;
  result = authName.length() >= strlen(RESERVED_AUTH_NAME_PREFIX)
           &&
           authName.operator()(0,strlen(RESERVED_AUTH_NAME_PREFIX)) ==
                                                   RESERVED_AUTH_NAME_PREFIX
           ||
           authName == "_SYSTEM"
           ||
           authName == "PUBLIC"
           ||
           authName == "NONE";

  return result;
}
// Retrieve the external database user ID from CLI
Int32 SqlciEnv::getExternalUserName(NAString &username)
{
  HandleCLIErrorInit();

  char buf[1024] = "";
  Int32 rc = SQL_EXEC_GetSessionAttr(SESSION_EXTERNAL_USER_NAME,
                                     NULL,
                                     buf, 1024, NULL);
  HandleCLIError(rc, this);

  if (rc >= 0)
    username = buf;

  if (username.length() == 0)
   username = "******";
  return rc;
}
Beispiel #8
0
// traverse queryExpr and put together its cacheKey
void CacheWA::generateCacheKey(RelExpr *queryExpr, const char *sText,
                               Lng32 charset, const NAString& viewsUsed)
{
  if (viewsUsed.length() > 0) {
    qryText_ += "v:";
    qryText_ += viewsUsed.data();
    useView_ = TRUE;
  }
  if (isViewJoin_) {
    // prepend view join's text into its cache key
    qryText_ += sText;
    char cs[20]; sprintf(cs, "%d", charset);
    qryText_ += cs;
  }
  // save parameterized statement text into cwa.qryText_
  queryExpr->generateCacheKey(*this);
}
NABoolean NAClusterInfo::NODE_ID_TO_NAME(Int32 nodeId, char *nodeName, short maxLen, short *actualLen)
{
    //Currently, this method behaves as same as NODENUMBER_TO_NODENAME_(),
    //which always returns "\\NSK", the only reason for doing this is to
    //avoid diff in regression test and core file dumped when exiting sqlci.(don't know why.)
    NODENUMBER_TO_NODENAME_(nodeId, nodeName, maxLen, actualLen);
    return TRUE;
    //Following code may be used in future to provide real node id to name map.
    *actualLen = 0;
    if (nodeIdToNodeNameMap_->contains(&nodeId))
    {
        NAString * value = nodeIdToNodeNameMap_->getFirstValue(&nodeId);
        *actualLen = value->length();
        strncpy(nodeName, value->data(), maxLen < (*actualLen) ? maxLen : (*actualLen));
        return TRUE;
    }
    return FALSE;
}
Beispiel #10
0
NABoolean CmpSqlSession::validateVolatileName(const char * name)
{
  ComObjectName volTabName(name);

  NAString schemaNamePart = 
    volTabName.getSchemaNamePartAsAnsiString(TRUE);
  
  schemaNamePart.toUpper();

  ULng32 len = 
    MINOF(schemaNamePart.length(),
	  strlen(COM_VOLATILE_SCHEMA_PREFIX));

  if ((len < strlen(COM_VOLATILE_SCHEMA_PREFIX)) ||
      (strncmp(schemaNamePart.data(), COM_VOLATILE_SCHEMA_PREFIX, len) != 0))
    {
      return FALSE;
    }
  
  return TRUE;
}
// -----------------------------------------------------------------------
// Translate ANSI SQL names from UCS-2/UTF-16 encoding values to
// the Default ANSI SQL Name character set.
// -----------------------------------------------------------------------
void CmAnsiNameToUTF8(const NAWString &inWcs, NAString &outMbs)
{
  outMbs.remove(0); // set to an empty string
  if (inWcs.length() <= 0)
  {
    return;
  }

  NAString *pConvStr =
    unicodeToChar ( inWcs.data()                        // in - const char * str
                  , (Int32)inWcs.length()               // in - Int32        len
                  , (Lng32)ComGetNameInterfaceCharSet() // in - Lng32        strCharSet
                  , (NAMemory *)STMTHEAP                // in - NAMemory *   h
                  , FALSE                               // in - NABoolean allowInvalidChar
                  );
  if (pConvStr != NULL AND pConvStr->length() > 0)
  {
    outMbs = *pConvStr;
  }
  delete pConvStr;
}
Int32 parseMVAge(const NAString& mvAge)
{
  Int32 result = 0;
  float number=0;
  char textChars[20];

  if (mvAge.length() < 15)
  {
    if (sscanf(mvAge.data(), "%f %s", &number, textChars) == 2)
    {
      const NAString text(textChars);
      if (!text.compareTo("Seconds", NAString::ignoreCase))
      {
	result = (Int32)floor(number);
      }
      else if (!text.compareTo("Minutes", NAString::ignoreCase))
      {
	result = (Int32)floor(number*60);
      }
      else if (!text.compareTo("Hours", NAString::ignoreCase))
      {
	result = (Int32)floor(number*60*60);
      }
      else if (!text.compareTo("Days", NAString::ignoreCase))
      {
	result = (Int32)floor(number*60*60*24);
      }
    }
  }

  if (result == 0)
  {
    QRLogger::log(CAT_MVCAND, LL_ERROR,
      "Invalid setting for MV_AGE default value: %s, Using only fresh MVs.",
      mvAge.data());

  }

  return result;
}
// ----------------------------------------------------------------------------
// Method:  glueQueryFragments
//
// This method combines the pieces of the metadata query into a single
// statement.  As part of this process, the leading spaces are removed.
//
// Input:  queryArraySize - number of fragments to glue together
//         QueryString - the fragments
//
// Output:  gluedQuery - the concatenated fragments
//          gluedQuerySize - the final length
//
// Space is allocated for the gluedQuery
// ----------------------------------------------------------------------------
void ExExeUtilTcb::glueQueryFragments(Lng32 queryArraySize,
				      const QueryString * queryArray,
				      char * &gluedQuery,
				      Lng32 &gluedQuerySize)
{
  Int32 i = 0;
  gluedQuerySize = 0;
  gluedQuery = NULL;
  NAString concatenatedQuery;
  NAString tempStr;

  for (i = 0; i < queryArraySize; i++)
    {
      tempStr = queryArray[i].str;
      concatenatedQuery += tempStr.strip(NAString::leading, ' ');
    }
  
  gluedQuerySize = concatenatedQuery.length();
  gluedQuery = new(getMyHeap()) char[gluedQuerySize + 100];
  strncpy(gluedQuery, concatenatedQuery.data(), gluedQuerySize);
  gluedQuery[gluedQuerySize] = '\0';
}
ItemExpr * buildEncodeTree(desc_struct * column,
                           desc_struct * key,
                           NAString * dataBuffer, //IN:contains original value
                           Generator * generator,
                           ComDiagsArea * diagsArea)
{
  ExpGenerator * expGen = generator->getExpGenerator();

  // values are encoded by evaluating the expression:
  //    encode (cast (<dataBuffer> as <datatype>))
  // where <dataBuffer> points to the string representation of the
  //      data value to be encoded, and <datatype> contains the
  //      PIC repsentation of the columns's datatype.

  // create the CAST part of the expression using the parser.
  
  // if this is a nullable column and the key value passed in
  // is a NULL value, then treat it as a special case. A NULL value
  // is passed in as an unquoted string of characters NULL in the
  // dataBuffer. This case has to be treated different since the
  // parser doesn't recognize the syntax "CAST (NULL as <datatype>)".
  NAString ns;
  ItemExpr * itemExpr;
  NABoolean nullValue = FALSE;

  NABoolean caseinsensitiveEncode = FALSE;
  if (column->body.columns_desc.caseinsensitive)
    caseinsensitiveEncode = TRUE;

  if (column->body.columns_desc.null_flag &&
      dataBuffer->length() >= 4 &&
      str_cmp(*dataBuffer, "NULL", 4) == 0)
    {
      nullValue = TRUE;

      ns = "CAST ( @A1 AS ";
      ns += column->body.columns_desc.pictureText;
      ns += ");";
  
      // create a NULL constant
      ConstValue * nullConst = new(expGen->wHeap()) ConstValue();
      nullConst->synthTypeAndValueId();

      itemExpr = expGen->createExprTree(ns,
                                        CharInfo::UTF8,
					ns.length(),
					1, nullConst);
    }
  else
    {
      ns = "CAST ( ";
      ns += *dataBuffer;
      ns += " AS ";
      ns += column->body.columns_desc.pictureText;
      ns += ");";
  
      itemExpr = expGen->createExprTree(ns,
                                        CharInfo::UTF8,
					ns.length());
    }

  CMPASSERT(itemExpr != NULL);
  ItemExpr *boundItemExpr =
  itemExpr->bindNode(generator->getBindWA());
  if (boundItemExpr == NULL)
    return NULL;

  // make sure that the source and target values have compatible type.
  // Do this only if source is not a null value.
  NAString srcval;
  srcval = "";
  srcval += *dataBuffer;
  srcval += ";";
  ItemExpr * srcNode = expGen->createExprTree(srcval, CharInfo::UTF8, srcval.length());
  CMPASSERT(srcNode != NULL);
  srcNode->synthTypeAndValueId();
  if ((NOT nullValue) &&
      (NOT srcNode->getValueId().getType().isCompatible(itemExpr->getValueId().getType())))
    {
      if (diagsArea)
	{
	  emitDyadicTypeSQLnameMsg(-4039, 
				   itemExpr->getValueId().getType(),
				   srcNode->getValueId().getType(),
				   column->body.columns_desc.colname,
				   NULL,
				   diagsArea);
	}

      return NULL;
    }

  if (column->body.columns_desc.null_flag)
    ((NAType *)&(itemExpr->getValueId().getType()))->setNullable(TRUE);
  else
    ((NAType *)&(itemExpr->getValueId().getType()))->setNullable(FALSE);
  
  // Explode varchars by moving them to a fixed field
  // whose length is equal to the max length of varchar.
  ////collation??
  DataType datatype = column->body.columns_desc.datatype;
  if (DFS2REC::isSQLVarChar(datatype))
    {
      char lenBuf[10];
      NAString vc((NASize_T)100);	// preallocate a big-enough buf

      size_t len = column->body.columns_desc.length;
      if (datatype == REC_BYTE_V_DOUBLE) len /= SQL_DBCHAR_SIZE;

      vc = "CAST (@A1 as CHAR(";
      vc += str_itoa(len, lenBuf);
      if ( column->body.columns_desc.character_set == CharInfo::UTF8 ||
           ( column->body.columns_desc.character_set == CharInfo::SJIS &&
             column->body.columns_desc.encoding_charset == CharInfo::SJIS ) )
        {
          vc += " BYTE";
          if (len > 1)
            vc += "S";
        }
      vc += ") CHARACTER SET ";
      vc += CharInfo::getCharSetName(column->body.columns_desc.character_set);
      vc += ");";

      itemExpr = expGen->createExprTree(vc, CharInfo::UTF8, vc.length(), 1, itemExpr);
      itemExpr->synthTypeAndValueId();

      ((NAType *)&(itemExpr->getValueId().getType()))->
        setNullable(column->body.columns_desc.null_flag);
  }

  // add the encode node on top of it.
  short desc_flag = TRUE;
  if (key->body.keys_desc.ordering == 0) // ascending
    desc_flag = FALSE;
  
  itemExpr = new(expGen->wHeap()) CompEncode(itemExpr, desc_flag);
  
  itemExpr->synthTypeAndValueId();
  
  ((CompEncode*)itemExpr)->setCaseinsensitiveEncode(caseinsensitiveEncode);

  return itemExpr;
}
Beispiel #15
0
NABoolean HHDFSMasterHostList::initializeWithSeaQuestNodes()
{
  NABoolean result = FALSE;
  FILE *pp;
  NAString fakeNodeNames =
    ActiveSchemaDB()->getDefaults().getValue(HIVE_USE_FAKE_SQ_NODE_NAMES);

  if (fakeNodeNames.length() <= 1)
    {
      // execute the command "sqshell -c node" and open a pipe to the output of this command.
      pp = popen("sqshell -c node", "r");
      if (pp != NULL)
        {
          // we want to add all the nodes returned by sqshell such that their HostIds
          // assigned here in class HHDFSMasterHostList matches their SeaQuest host number
          HostId nextHostId = getHosts()->entries();

          while (1)
            {
              char *line;
              char buf[1000];
              line = fgets(buf, sizeof buf, pp);
              if (line == NULL)
                {
                  // if we inserted anything without encountering an error, consider that success
                  numSQNodes_ = getHosts()->entries();
                  result = (numSQNodes_ > 0);
                  break;
                }
              char *nodeNum = strstr(line, "Node[");
              if (nodeNum)
                {
                  nodeNum += 5; // skip the matched text
                  int nodeId = atoi(nodeNum);
                  if (nodeId != nextHostId)
                    break; // out-of-sequence host ids are not supported

                  char *nodeName = strstr(nodeNum, "=");
                  if (nodeName == NULL)
                    break; // expecting "=" sign in the sqshell output
                  nodeName++;
                  char *nodeEnd = strstr(nodeName, ",");
                  if (nodeEnd == NULL)
                    break; // couldn't find the end of the node name
                  *nodeEnd = 0;

                  // resolve the found name to make it a fully qualified DNS name,
                  // like HDFS also uses it
                  struct hostent * h = gethostbyname(nodeName);
                  if (h)
                    nodeName = h->h_name;

                  HostId checkId = getHostNumInternal(nodeName);
                  if (checkId != nodeId)
                    if (checkId > nodeId)
                      break; // something must have gone wrong, this should not happen
                    else
                      {
                        // checkId < nodeId, this can happen if we have duplicate
                        // node ids. In this case, insert a dummy node to take up the
                        // number, so we stay in sync
                        sprintf(buf, "dummy.node.%d.nosite.com", nodeId);
                        HostId checkId2 = getHostNumInternal(buf);
                        if (checkId2 != nodeId)
                          break; // again, not expecting to get here
                        // remember that we mave multiple SQ nodes
                        // on the same physical node
                        hasVirtualSQNodes_ = TRUE;
                      }
                  nextHostId++;
                }
            }
          pclose(pp);
        }
    }
  else
    {
      // seed the host name list with fake SQ node names from the CQD insted
      const char delim = ',';
      const char *nodeStart = fakeNodeNames;
      const char *nodeEnd;

      do
        {
          // this is debug code, no error check, no blanks in this string!!!
          char buf[500];

          nodeEnd = strchrnul(nodeStart, delim);
          strncpy(buf, nodeStart, nodeEnd-nodeStart);
          getHostNumInternal(buf);
          nodeStart = nodeEnd+1;
        }
      while (*nodeEnd != 0);
      
      numSQNodes_ = getHosts()->entries();
      result = (numSQNodes_ > 0);
    }
  return result;
}
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;
  }
Beispiel #17
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);
  }

}
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;
  }
//
// Scans (parses) input external-format schema name.
//
// This method assumes that the parameter  externalSchemaName  only
// contains the external-format schema name.  The syntax of an
// schema name is
//
//   [ <catalog-name-part> ] . <schema-name-part>
//
// A schema name part must be specified; the catalog name part is optional.
//
// The method returns the number of bytes scanned via the parameter
// bytesScanned.  If the scanned schema name is illegal, bytesScanned
// contains the number of bytes examined when the name is determined
// to be invalid.
//
// If the specified external-format schema name is valid, this method
// returns TRUE and saves the parsed ANSI SQL name part into data
// members catalogNamePart_ and schemaNamePart_; otherwise, it returns
// FALSE and does not changes the contents of the data members.
//
NABoolean
ComSchemaName::scan(const NAString &externalSchemaName,
                    size_t &bytesScanned)
{
  size_t count;
  size_t externalSchemaNameLen = externalSchemaName.length();
  bytesScanned = 0;

  #define COPY_VALIDATED_STRING(x)	\
		      ComAnsiNamePart(x, ComAnsiNamePart::INTERNAL_FORMAT)

  if (( SqlParser_Initialized() && SqlParser_NAMETYPE == DF_NSK)       ||
      (!SqlParser_Initialized() && *externalSchemaName.data() == '\\')) {
    ComMPLoc loc(externalSchemaName);
    switch (loc.getFormat()) {
      case ComMPLoc::SUBVOL:
		catalogNamePart_ = COPY_VALIDATED_STRING(loc.getSysDotVol());
		schemaNamePart_  = COPY_VALIDATED_STRING(loc.getSubvolName());
		bytesScanned = externalSchemaNameLen;
		return TRUE;

      case ComMPLoc::FILE:
		if (!loc.hasSubvolName()) {
		  catalogNamePart_ = "";
		  schemaNamePart_  = COPY_VALIDATED_STRING(loc.getFileName());
		  bytesScanned = externalSchemaNameLen;
		  return TRUE;
		}
    }
  }

  // Each ComAnsiNamePart ctor below must be preceded by "count = 0;"
  // -- see ComAnsiNamePart.cpp, and for a better scan implementation,
  //    see ComObjectName::scan() + ComObjectName(bytesScanned) ctor.

  // ---------------------------------------------------------------------
  // Scan the leftmost ANSI SQL name part.
  // ---------------------------------------------------------------------

  count = 0;
  ComAnsiNamePart part1(externalSchemaName, count);
  bytesScanned += count;
  if (NOT part1.isValid())
    return FALSE;

  if (bytesScanned >= externalSchemaNameLen)
  {
    ComASSERT(bytesScanned == externalSchemaNameLen);
    schemaNamePart_  = part1;
    return TRUE;					// "sch"
  }

  // Get past the period separator
  if (NOT ComSqlText.isPeriod(externalSchemaName[bytesScanned++]))
    return FALSE;

  // ---------------------------------------------------------------------
  // Scan the last ANSI SQL name part
  // ---------------------------------------------------------------------

#pragma nowarn(1506)   // warning elimination 
  Int32 remainingLen = externalSchemaNameLen - bytesScanned;
#pragma warn(1506)  // warning elimination 
  NAString remainingName = externalSchemaName(bytesScanned, remainingLen);
  count = 0;
  ComAnsiNamePart part2(remainingName, count);
  bytesScanned += count;
  if (NOT part2.isValid())
    return FALSE;

  if (bytesScanned == externalSchemaNameLen)
  {
    catalogNamePart_ = part1;
    schemaNamePart_  = part2;
    return TRUE;					// "cat.sch"
  }

  // The specified external-format object name contains some extra
  // trailing characters -- illegal.
  //
  return FALSE;

} // ComSchemaName::scan()
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;
  }
Beispiel #21
0
short Param::convertValue(SqlciEnv * sqlci_env, short targetType,
			  Lng32 &targetLen,
			  Lng32 targetPrecision,
			  Lng32 targetScale,
                          Lng32 vcIndLen,
   			  ComDiagsArea* diags) {

  // get rid of the old converted value
  if (converted_value) {
    delete [] converted_value;
    converted_value = 0;
  };

  short sourceType;
  Lng32 sourceLen;

  // set up the source and its length based on the how the value is passed-in.
  if ( isInSingleByteForm() == FALSE ) {
    sourceLen = (Lng32)(NAWstrlen((NAWchar*)value) * BYTES_PER_NAWCHAR);
    switch (getCharSet()) {
      case CharInfo::UNICODE:
        sourceType = REC_NCHAR_F_UNICODE;
        break;

      case CharInfo::KANJI_MP:
      case CharInfo::KSC5601_MP:
        sourceType = REC_BYTE_F_ASCII; // KANJI/KSC passed in as NAWchar*
        break;

      default:
        return SQL_Error; // error case
    }
  } else {
    sourceLen = (Lng32)strlen(value); // for any source in single-byte format
    sourceType = REC_BYTE_F_ASCII;
  }

  char * pParamValue = value;

  if ( DFS2REC::isAnyCharacter(targetType) ) {

    if (termCS_ == CharInfo::UnknownCharSet)
      termCS_ = sqlci_env->getTerminalCharset();
    if (cs == CharInfo::UnknownCharSet)
    {
      isQuotedStrWithoutCharSetPrefix_ = TRUE;
      cs = termCS_;
    }

    // If the target is CHARACTER and param is set as [_cs_prefix]'...', then 
    // make sure the source is assignment compatible with the target.
    CharInfo::CharSet targetCharSet = (CharInfo::CharSet)targetScale;
    if ( targetCharSet == CharInfo::UNICODE )
    {
      if (getUTF16StrLit() == (NAWchar*)NULL)
      {
        utf16StrLit_ = new NAWchar [ sourceLen * 2 + 1 ]; // plenty of room
        Lng32 utf16StrLenInNAWchars =
          LocaleStringToUnicode(cs/*sourceCS*/, /*sourceStr*/value, sourceLen,
                                utf16StrLit_/*outputBuf*/, sourceLen+1/*outputBufSizeInNAWchars*/,
                                TRUE /* in - NABoolean addNullAtEnd*/);
        if (sourceLen > 0 && utf16StrLenInNAWchars == 0)
          return SQL_Error;

        // ComASSERT(utf16StrLenInNAWchars == NAWstrlen(getUTF16StrLit()));
        // Resize the NAWchar buffer to save space
        NAWchar *pNAWcharBuf = new NAWchar [ utf16StrLenInNAWchars + 1 ];
        NAWstrncpy (pNAWcharBuf, utf16StrLit_, utf16StrLenInNAWchars + 1);
        pNAWcharBuf[utf16StrLenInNAWchars] = NAWCHR('\0'); // play it safe
        delete [] utf16StrLit_;
        utf16StrLit_ = pNAWcharBuf; // do not deallocate pNAWcharBuf
      }
      sourceLen = (Lng32)(NAWstrlen(getUTF16StrLit()) * BYTES_PER_NAWCHAR);
      // check to see if the parameter utf16 string fits in the target
      if ( sourceLen > targetLen )
        return SQL_Error;

      pParamValue = (char *)getUTF16StrLit();
      sourceType = REC_NCHAR_F_UNICODE;
    }

  } else {
 
    // MP NCHAR (KANJI/KSC) can not be converted to non-character objects
   if ( CharInfo::is_NCHAR_MP(cs) )
      return SQL_Error;
  }


  switch(targetType) {
  case REC_BIN16_SIGNED:
  case REC_BIN16_UNSIGNED:
  case REC_BPINT_UNSIGNED:
  case REC_BIN32_SIGNED:
  case REC_BIN32_UNSIGNED:
  case REC_BIN64_SIGNED:
  case REC_DECIMAL_UNSIGNED:
  case REC_DECIMAL_LSE:
  case REC_FLOAT32:
  case REC_FLOAT64:
  case REC_TDM_FLOAT32:
  case REC_TDM_FLOAT64:
  case REC_BYTE_F_ASCII:
  case REC_BYTE_V_ASCII:
  case REC_BYTE_V_ASCII_LONG:
  case REC_NCHAR_F_UNICODE:
  case REC_NCHAR_V_UNICODE:
  {
    char *VCLen = NULL;
    short VCLenSize = 0;

// 5/27/98: added VARNCHAR cases
    if ((targetType == REC_BYTE_V_ASCII) || 
        (targetType == REC_BYTE_V_ASCII_LONG) ||
        (targetType == REC_NCHAR_V_UNICODE)) 
    {
      // add bytes for variable length field
      VCLenSize = vcIndLen; //sizeof(short);
      VCLen = converted_value = new char[targetLen + VCLenSize];
    } else
      converted_value = new char[targetLen];


#pragma nowarn(1506)   // warning elimination 
    ex_expr::exp_return_type ok;
    CharInfo::CharSet TCS = sqlci_env->getTerminalCharset();
    CharInfo::CharSet ISOMAPCS = sqlci_env->getIsoMappingCharset();
    
    NAString* tempstr;
    if ( 
        DFS2REC::isAnyCharacter(sourceType) && DFS2REC::isAnyCharacter(targetType) &&
        !(getUTF16StrLit() != NULL && sourceType == REC_NCHAR_F_UNICODE && targetScale == CharInfo::UCS2) &&
        /*source*/cs != targetScale/*i.e., targetCharSet*/
        )
    {
      charBuf cbuf((unsigned char*)pParamValue, sourceLen);
      NAWcharBuf* wcbuf = 0;
      Int32 errorcode = 0;
      wcbuf = csetToUnicode(cbuf, 0, wcbuf,
                            cs/*sourceCharSet*/
                            , errorcode);
      if (errorcode != 0) return SQL_Error;
      tempstr = unicodeToChar(wcbuf->data(),wcbuf->getStrLen(),
                              targetScale/*i.e., targetCharSet*/
                              );
      if (tempstr == NULL) 
	return SQL_Error;  //Avoid NULL ptr reference if conversion error
      sourceType = targetType; // we just converted it to the target type
      sourceLen = tempstr->length();
      pParamValue = (char *)tempstr->data();

      if ( sourceLen > targetLen )
        return SQL_Error;
    }

    ok = convDoIt(pParamValue,
		  sourceLen, 
		  sourceType,
		  0, // source Precision
		  targetScale, // new charset we converted to
		  &converted_value[VCLenSize],
		  targetLen,
		  targetType,
		  targetPrecision,
		  targetScale,
		  VCLen,
		  VCLenSize,
		  0,
		  &diags);
    
    if ( ok != ex_expr::EXPR_OK)
    {
      // No need to delete allocated memory before return because class member
      // converted_value still points to allocated memory that is deleted in 
      // desctructor.
      return SQL_Error; // error case
    }
#pragma warn(1506)  // warning elimination
    
  };
  break;


  case REC_DATETIME: {

    char *VCLen = NULL;
    short VCLenSize = 0;
    converted_value = new char[targetLen + 1];

#pragma nowarn(1506)   // warning elimination 
    ex_expr::exp_return_type ok = convDoIt(value,
					   sourceLen, 
					   sourceType,
					   0, // source Precision
					   0, // source Scale
					   converted_value,
					   targetLen,
					   targetType,
					   targetPrecision,
					   targetScale,
					   VCLen,
					   VCLenSize,
					   0,
					   &diags);
    
    if ( ok != ex_expr::EXPR_OK)
      {
	return SQL_Error; // error case
      }
#pragma warn(1506)  // warning elimination
  };
  break;

  case REC_INT_YEAR:
  case REC_INT_MONTH:
  case REC_INT_YEAR_MONTH:
  case REC_INT_DAY:
  case REC_INT_HOUR:
  case REC_INT_DAY_HOUR:
  case REC_INT_MINUTE:
  case REC_INT_HOUR_MINUTE:
  case REC_INT_DAY_MINUTE:
  case REC_INT_SECOND:
  case REC_INT_MINUTE_SECOND:
  case REC_INT_HOUR_SECOND:
  case REC_INT_DAY_SECOND: {

    // convert target back to string.
    converted_value = new char[targetLen];
    Lng32 convFlags = CONV_ALLOW_SIGN_IN_INTERVAL;
#pragma nowarn(1506)   // warning elimination 
    short ok = 
      convDoItMxcs(value,
		   sourceLen, 
		   sourceType,
		   0, // source Precision
		   0, // source Scale
		   converted_value,
		   targetLen,
		   targetType,
		   targetPrecision,
		   targetScale,
		   convFlags);
    
    if ( ok != 0 )
    {
      // No need to delete allocated memory before return because class member
      // converted_value still points to allocated memory that is deleted in 
      // desctructor.
      return SQL_Error; // error case
    }
#pragma warn(1506)  // warning elimination
  };
  break;

  case REC_NUM_BIG_UNSIGNED:
  case REC_NUM_BIG_SIGNED:
  {
    converted_value = new char[targetLen];
#pragma nowarn(1506)   // warning elimination 
    short ok = 
      convDoItMxcs(value,
		   sourceLen, 
		   sourceType,
		   0, // source Precision
		   0, // source Scale
		   converted_value,
		   targetLen,
		   targetType,
		   targetPrecision,
		   targetScale,
		   0);
    
    if ( ok != 0 )
    {
      // No need to delete allocated memory before return because class member
      // converted_value still points to allocated memory that is deleted in 
      // desctructor.
      return SQL_Error; // error case
    }
#pragma warn(1506)  // warning elimination
    
  };
  break;

  default:
    break;
  };

  return 0;
}
short Env::process(SqlciEnv *sqlci_env)
{
  // ## Should any of this text come from the message file,
  // ## i.e. from a translatable file for I18N?


  // When adding new variables, please keep the information in 
  // alphabetic order
  Logfile *log = sqlci_env->get_logfile();

  log->WriteAll("----------------------------------");
  log->WriteAll("Current Environment");
  log->WriteAll("----------------------------------");
 

  bool authenticationEnabled = false;
  bool authorizationEnabled = false;
  bool authorizationReady = false;
  bool auditingEnabled = false;
  Int32 rc = sqlci_env->getAuthState(authenticationEnabled,
                                     authorizationEnabled,
                                     authorizationReady,
                                     auditingEnabled);

  // TDB: add auditing state
  log->WriteAllWithoutEOL("AUTHENTICATION     ");
  if (authenticationEnabled)
    log->WriteAll("enabled");
  else
    log->WriteAll("disabled");

  log->WriteAllWithoutEOL("AUTHORIZATION      ");
  if (authorizationEnabled)
    log->WriteAll("enabled");
  else
    log->WriteAll("disabled");

  log->WriteAllWithoutEOL("CURRENT DIRECTORY  ");

  // NT_PORT (bv 10/24/96) Added NA_MAX_PATH here and in common/Platform.h
  log->WriteAll(getcwd((char *)NULL, NA_MAX_PATH));


  log->WriteAllWithoutEOL("LIST_COUNT         ");
  char buf[100];
  Int32 len = sprintf(buf, "%u", sqlci_env->getListCount());
  if (len-- > 0)
    if (buf[len] == 'L' || buf[len] == 'l')
      buf[len] = '\0';
  log->WriteAll(buf);
  
  if (log->IsOpen())
    {
      log->WriteAllWithoutEOL("LOG FILE           ");
      log->WriteAll(log->Logname());
    }
  else
    {
      log->WriteAll("LOG FILE");
    }

  log->WriteAllWithoutEOL("MESSAGEFILE        ");
  const char *mf = GetErrorMessageFileName();
  log->WriteAll(mf ? mf : "");

#if 0
  log->WriteAllWithoutEOL("ISO88591 MAPPING   ");
  log->WriteAll(CharInfo::getCharSetName(sqlci_env->getIsoMappingCharset()));

  log->WriteAllWithoutEOL("DEFAULT CHARSET    ");
  log->WriteAll(CharInfo::getCharSetName(sqlci_env->getDefaultCharset()));

  log->WriteAllWithoutEOL("INFER CHARSET      ");
  log->WriteAll((sqlci_env->getInferCharset())?"ON":"OFF");
#endif

  // ## These need to have real values detected from the env and written out:

  // "US English" is more "politically correct" than "American English".
  //
  log->WriteAllWithoutEOL("MESSAGEFILE LANG   US English\n");

  log->WriteAllWithoutEOL("MESSAGEFILE VRSN   ");
  char vmsgcode[10];
  sprintf(vmsgcode, "%d", SQLERRORS_MSGFILE_VERSION_INFO);
#pragma nowarn(1506)   // warning elimination 
  Error vmsg(vmsgcode, strlen(vmsgcode), Error::ENVCMD_);
#pragma warn(1506)  // warning elimination 
  vmsg.process(sqlci_env);

  ComAnsiNamePart defaultCat;
  ComAnsiNamePart defaultSch;

  sqlci_env->getDefaultCatAndSch (defaultCat, defaultSch);
  CharInfo::CharSet TCS = sqlci_env->getTerminalCharset();
  CharInfo::CharSet ISOMAPCS = sqlci_env->getIsoMappingCharset();

  if(TCS !=
            CharInfo::UTF8
     )  {
      NAString dCat = defaultCat.getExternalName();
	  NAString dSch = defaultSch.getExternalName();
	  charBuf cbufCat((unsigned char*)dCat.data(), dCat.length());
	  charBuf cbufSch((unsigned char*)dSch.data(), dSch.length());
      NAWcharBuf* wcbuf = 0;
	  Int32 errorcode	= 0;
	  
	  wcbuf = csetToUnicode(cbufCat, 0, wcbuf, CharInfo::UTF8, errorcode);
	  NAString* tempstr;
	  if (errorcode != 0){
	    tempstr = new NAString(defaultCat.getExternalName().data()); 
	  }
	  else {				
	    tempstr = unicodeToChar(wcbuf->data(),wcbuf->getStrLen(), TCS, NULL, TRUE);
	    TrimNAStringSpace(*tempstr, FALSE, TRUE);  // trim trailing blanks
	  }
      log->WriteAllWithoutEOL("SQL CATALOG        ");
      log->WriteAll(tempstr->data());

	  // Default Schema

	  wcbuf = 0;  // must 0 out to get next call to allocate memory.
	  wcbuf = csetToUnicode(cbufSch, 0, wcbuf, CharInfo::UTF8, errorcode);
	  if (errorcode != 0){
	    tempstr = new NAString(defaultSch.getExternalName().data()); 
	  }
	  else {				
	    tempstr = unicodeToChar(wcbuf->data(),wcbuf->getStrLen(), TCS, NULL, TRUE);
	    TrimNAStringSpace(*tempstr, FALSE, TRUE);  // trim trailing blanks
	  }
       log->WriteAllWithoutEOL("SQL SCHEMA         ");
       log->WriteAll(tempstr->data());
	}
	else
	{
  log->WriteAllWithoutEOL("SQL CATALOG        ");
  log->WriteAll(defaultCat.getExternalName());
  log->WriteAllWithoutEOL("SQL SCHEMA         ");
  log->WriteAll(defaultSch.getExternalName());
  }

  // On Linux we include the database user name and user ID in the
  // command output
  NAString username;
  rc = sqlci_env->getExternalUserName(username);
  log->WriteAllWithoutEOL("SQL USER CONNECTED "); 
  if (rc >= 0)
    log->WriteAll(username.data());
  else
    log->WriteAll("?");

  rc = sqlci_env->getDatabaseUserName(username);
  log->WriteAllWithoutEOL("SQL USER DB NAME   ");
  if (rc >= 0)
    log->WriteAll(username.data());
  else
    log->WriteAll("?");
  
  Int32 uid = 0;
  rc = sqlci_env->getDatabaseUserID(uid);
  log->WriteAllWithoutEOL("SQL USER ID        ");
  if (rc >= 0)
    sprintf(buf, "%d", (int) uid);
  else
    strcpy(buf, "?");
  log->WriteAll(buf);
  
  log->WriteAllWithoutEOL("TERMINAL CHARSET   ");
  log->WriteAll(CharInfo::getCharSetName(sqlci_env->getTerminalCharset()));

  Int64 transid;
  if (sqlci_env->statusTransaction(&transid))
    {
      // transaction is active.
      char transid_str[20];
      convertInt64ToAscii(transid, transid_str);
      log->WriteAllWithoutEOL("TRANSACTION ID     ");
      log->WriteAll(transid_str);
      log->WriteAll("TRANSACTION STATE  in progress");
    }  
  else
    {
      log->WriteAll("TRANSACTION ID     ");
      log->WriteAll("TRANSACTION STATE  not in progress");
    }

  if (log->isVerbose())
    log->WriteAll("WARNINGS           on");
  else
    log->WriteAll("WARNINGS           off");
  
  return 0;  
}