Lng32 ExExeUtilTcb::extractParts
(char * objectName,
 char ** paramParts0,
 char ** paramParts1,
 char ** paramParts2
 )
{

  char * parts[4];
  Lng32 numParts = 0;
  Lng32 rc = 0;

  // We want to ignore any "." dots within a delimited
  // name.  The AnsiOrNskName object is ultimately deleted
  // in the ExExeUtilMainObjectTcb destructor.
  
  if (extractedPartsObj_)
    delete extractedPartsObj_;

  extractedPartsObj_ = new (getHeap()) AnsiOrNskName(objectName);
  if ((rc = extractedPartsObj_->extractParts(numParts, parts)) != 0 ||
      (numParts != 3))
    {
      *getDiagsArea() << DgSqlCode(-CLI_INTERNAL_ERROR);
      return -1;
    }


  char * parts0 = NULL;
  char * parts1 = NULL;
  char * parts2 = NULL;

  Lng32 parts0Len = strlen(parts[0]);
  Lng32 parts1Len = strlen(parts[1]);
  Lng32 parts2Len = strlen(parts[2]);

  Lng32 parts0OffsetLen = 0;
  Lng32 parts1OffsetLen = 0;
  Lng32 parts2OffsetLen = 0;

  Lng32 foundParts0 = 0;
  Lng32 foundParts1 = 0;
  Lng32 foundParts2 = 0;

  char * testParts = NULL;
  char * ptr = NULL;

  testParts = parts[0];

  ptr = (char *) strchr (testParts, '\'');
  while (ptr != NULL)
  {
    foundParts0++;
    ptr = (char *) strchr (ptr+1,'\'');
  }

  testParts = parts[1];
 
  ptr = (char *) strchr (testParts, '\'');
  while (ptr != NULL)
  {
    foundParts1++;
    ptr = (char *) strchr (ptr+1,'\'');
  }

  testParts = parts[2];
 
  ptr = (char *) strchr (testParts, '\'');
  while (ptr != NULL)
  {
    foundParts2++;
    ptr = (char *) strchr (ptr+1,'\'');
  }

  Lng32 lenToCopy = 0;
  char * beginTestParts = NULL;
  char * formattedParts = NULL;
  Lng32 totalLen = 0;

  if (foundParts0)
  {
    totalLen = parts0Len + foundParts0 + 1;
    parts0 = new(getHeap()) char[totalLen];

    for (Int32 i = 0; i < totalLen; i++)
      parts0[i] = ' ';

    parts0[totalLen-1] = '\0';

    testParts = parts[0];
    ptr = NULL;
  
    ptr = (char *) strchr (testParts, '\'');

    while (ptr != NULL)
    {
      lenToCopy = ptr - testParts;
    
      strncpy(parts0 + parts0OffsetLen,testParts,++lenToCopy);
       
      strncpy(parts0 + parts0OffsetLen + lenToCopy, "'",1);
         
      testParts = testParts + lenToCopy;
      parts0OffsetLen += lenToCopy;
      parts0OffsetLen++;

      ptr = (char *) strchr (ptr+1,'\'');
    }

    strncpy(parts0 + parts0OffsetLen, testParts,strlen(testParts));
    parts0[totalLen-1] = '\0';
  }
 else
  {
    totalLen = parts0Len + 1;
    parts0 = new(getHeap()) char[totalLen];
    strcpy(parts0, parts[0]);
  }

 if (foundParts1)
  {
    totalLen = parts1Len + foundParts1 + 1;
    parts1 = new(getHeap()) char[totalLen];

    for (Int32 i = 0; i < totalLen; i++)
      parts1[i] = ' ';

    parts1[totalLen-1] = '\0';

    testParts = parts[1];
    ptr = NULL;
  
    ptr = (char *) strchr (testParts, '\'');

    while (ptr != NULL)
    {
      lenToCopy = ptr - testParts;
    
      strncpy(parts1 + parts1OffsetLen,testParts,++lenToCopy);
       
      strncpy(parts1 + parts1OffsetLen + lenToCopy, "'",1);
         
      testParts = testParts + lenToCopy;
      parts1OffsetLen += lenToCopy;
      parts1OffsetLen++;

      ptr = (char *) strchr (ptr+1,'\'');
    }

    strncpy(parts1 + parts1OffsetLen, testParts,strlen(testParts));
    parts1[totalLen-1] = '\0';
  }
 else
  {
    totalLen = parts1Len + 1;
    parts1 = new(getHeap()) char[totalLen];
    strcpy(parts1, parts[1]);
  }

 if (foundParts2)
  {
    totalLen = parts2Len + foundParts2 + 1;
    parts2 = new(getHeap()) char[totalLen];

    for (Int32 i = 0; i < totalLen; i++)
      parts2[i] = ' ';

    parts2[totalLen-1] = '\0';

    testParts = parts[2];
    ptr = NULL;
  
    ptr = (char *) strchr (testParts, '\'');

    while (ptr != NULL)
    {
      lenToCopy = ptr - testParts;
 
      strncpy(parts2 + parts2OffsetLen,testParts,++lenToCopy);
      
      strncpy(parts2 + parts2OffsetLen + lenToCopy, "'",1);
         
      testParts = testParts + lenToCopy;
      parts2OffsetLen += lenToCopy;
      parts2OffsetLen++;

      ptr = (char *) strchr (ptr+1,'\'');
    }

    strncpy(parts2 + parts2OffsetLen, testParts,strlen(testParts));
    parts2[totalLen-1] = '\0';
  }
 else
  {
    totalLen = parts2Len + 1;
    parts2 = new(getHeap()) char[totalLen];
    strcpy(parts2, parts[2]);
  }

  /* The AnsiOrNskName() method strips out the leading
     and ending double quotes.  The following code
     is no longer needed.

  // 
  // Strip out the delimited name quotes.
  // If these are not stripped out, then a maximum
  // name of 128 characters will cause an overflow
  // by actually having 130 characters.

  char maxName[129];
  maxName[0] = '\0';

  if (parts0[0] == '"')
  {
    strncpy(maxName,parts0+1,strlen(parts0) -2);
    maxName[strlen(parts0)-2] = '\0';
    strncpy(parts0,maxName,strlen(parts0) -2);
    parts0[strlen(maxName)] = '\0';
  }

  maxName[0] = '\0';

  if (parts1[0] == '"')
  {
    strncpy(maxName,parts1+1,strlen(parts1) -2);
    maxName[strlen(parts1)-2] = '\0';
    strncpy(parts1,maxName,strlen(parts1) -2);
    parts1[strlen(maxName)] = '\0';
  }

  maxName[0] = '\0';

  if (parts2[0] == '"')
  {
    strncpy(maxName,parts2+1,strlen(parts2) -2);
    maxName[strlen(parts2)-2] = '\0';
    strncpy(parts2,maxName,strlen(parts2) -2);
    parts2[strlen(maxName)] = '\0';
  }

  maxName[0] = '\0';
*/

  *paramParts0 = parts0;
  *paramParts1 = parts1;
  *paramParts2 = parts2;

  return 0;
}
Beispiel #2
0
// ----------------------------------------------------------------------------
// Method: registerUser
//
// registers a user in the Trafodion metadata
//
// Input:  parse tree containing a definition of the user
// Output: the global diags area is set up with the result
// ----------------------------------------------------------------------------
void CmpSeabaseDDLuser::registerUser(StmtDDLRegisterUser * pNode)
{
  // Set up a global try/catch loop to catch unexpected errors
  try
  {
    // Verify user is authorized

    verifyAuthority();

    // Verify that the specified user name is not reserved
    // TBD - add the isCatman concept
    if (isAuthNameReserved(pNode->getDbUserName()))
    {
      *CmpCommon::diags() << DgSqlCode (-CAT_AUTH_NAME_RESERVED)
                          << DgString0(pNode->getDbUserName().data());
      DDLException excp (CAT_AUTH_NAME_RESERVED, NULL, 0);
      excp.throwException();
    }


    // set up class members from parse node
    setAuthDbName(pNode->getDbUserName());
    setAuthExtName(pNode->getExternalUserName());
    setAuthImmutable(pNode->isImmutable());
    setAuthType(COM_USER_CLASS);  // we are a user
    setAuthValid(true); // assume a valid user

    Int64 createTime = NA_JulianTimestamp();
    setAuthCreateTime(createTime);
    setAuthRedefTime(createTime);  // make redef time the same as create time

    // Make sure db user has not already been registered
    if (authExists())
    {
      *CmpCommon::diags() << DgSqlCode(-CAT_AUTHID_ALREADY_EXISTS)
                          << DgString0(getAuthDbName().data());
      DDLException excp (CAT_AUTHID_ALREADY_EXISTS, NULL, 0);
      excp.throwException();
    }

    // Make sure external user has not already been registered
    if (authExists(true))
    {
      *CmpCommon::diags() << DgSqlCode(-CAT_LDAP_USER_ALREADY_EXISTS)
                          << DgString0(getAuthExtName().data());
      DDLException excp (CAT_LDAP_USER_ALREADY_EXISTS, NULL, 0);
      excp.throwException();
    }

DBUserAuth::AuthenticationConfiguration configurationNumber = DBUserAuth::DefaultConfiguration;
DBUserAuth::AuthenticationConfiguration foundConfigurationNumber = DBUserAuth::DefaultConfiguration;

    if (!validateExternalUsername(pNode->getExternalUserName().data(),
                                  configurationNumber,
                                  foundConfigurationNumber))
       return;

    // Get a unique auth ID number
    // TBD - check a parserflag (or something) to add DB__ROOT
    Int32 userID = 0;
    if (getAuthDbName() == DB__ROOT)
      userID = SUPER_USER;
    else
      userID = getUniqueUserID();

    setAuthID (userID);

    // If the BY clause was specified, then register the user on behalf of the
    // authorization ID specified in this clause.
    // Need to translate the creator name to its authID
    if (pNode->getOwner() == NULL)
    {
      // get effective user from the Context
      // TBD - replace this call with SQL_EXEC_ call
      Int32 *pUserID = GetCliGlobals()->currContext()->getDatabaseUserID();
      setAuthCreator(*pUserID);
    }
    else
    {
      const NAString creatorName =
        pNode->getOwner()->getAuthorizationIdentifier();
      // TBD: get the authID for the creatorName
      // TBD: verify creator can register users
      setAuthCreator(NA_UserIdDefault);
    }

    // Add the user to AUTHS table
    insertRow();
  }
  catch (...)
  {
    // At this time, an error should be in the diags area.
    // If there is no error, set up an internal error
    Int32 numErrors = CmpCommon::diags()->getNumber(DgSqlCode::ERROR_);
    if (numErrors == 0)
      *CmpCommon::diags() << DgSqlCode (-CAT_INTERNAL_EXCEPTION_ERROR)
                          << DgInt0(__LINE__)
                          << DgString0("register user");

  }
}
// -----------------------------------------------------------------------
// Method for creating NAType from desc_struct.
// -----------------------------------------------------------------------
NABoolean NAColumn::createNAType(columns_desc_struct *column_desc	/*IN*/,
				 const NATable *table  		/*IN*/,
				 NAType *&type       		/*OUT*/,
				 NAMemory *heap			/*IN*/,
				 Lng32 * errorCode
				 )
{
  //
  // Compute the NAType for this column
  //
  #define REC_INTERVAL REC_MIN_INTERVAL

  DataType datatype = column_desc->datatype;
  if (REC_MIN_INTERVAL <= datatype && datatype <= REC_MAX_INTERVAL)
    datatype = REC_INTERVAL;

  Lng32 charCount = column_desc->length;

  if ( DFS2REC::isAnyCharacter(column_desc->datatype) )
  {
     if ( CharInfo::isCharSetSupported(column_desc->character_set) == FALSE ) {
       if (!errorCode)
       {
         *CmpCommon::diags() << DgSqlCode(-4082)
	       << DgTableName(makeTableName(table, column_desc));
       }
       else
       {
         *errorCode = 4082;
       }
       return TRUE; // error
     }

     if ( CharInfo::is_NCHAR_MP(column_desc->character_set) )
        charCount /= SQL_DBCHAR_SIZE;
  }

  switch (datatype)
    {

    case REC_BPINT_UNSIGNED :
      type = new (heap)
      SQLBPInt(column_desc->precision, column_desc->null_flag, FALSE, heap);
      break;

    case REC_BIN8_SIGNED:
      if (column_desc->precision > 0)
	type = new (heap)
	SQLNumeric(column_desc->length,
		   column_desc->precision,
		   column_desc->scale,
		   TRUE,
		   column_desc->null_flag,
                   heap
		   );
      else
	type = new (heap)
	SQLTiny(TRUE,
		 column_desc->null_flag,
                 heap
		 );
      break;
    case REC_BIN8_UNSIGNED:
      if (column_desc->precision > 0)
	type = new (heap)
	SQLNumeric(column_desc->length,
		   column_desc->precision,
		   column_desc->scale,
		   FALSE,
		   column_desc->null_flag,
                   heap
		   );
      else
	type = new (heap)
	SQLTiny(FALSE,
		 column_desc->null_flag,
                 heap
		 );
      break;

   case REC_BIN16_SIGNED:
      if (column_desc->precision > 0)
	type = new (heap)
	SQLNumeric(column_desc->length,
		   column_desc->precision,
		   column_desc->scale,
		   TRUE,
		   column_desc->null_flag,
                   heap
		   );
      else
	type = new (heap)
	SQLSmall(TRUE,
		 column_desc->null_flag,
                 heap
		 );
      break;
    case REC_BIN16_UNSIGNED:
      if (column_desc->precision > 0)
	type = new (heap)
	SQLNumeric(column_desc->length,
		   column_desc->precision,
		   column_desc->scale,
		   FALSE,
		   column_desc->null_flag,
                   heap
		   );
      else
	type = new (heap)
	SQLSmall(FALSE,
		 column_desc->null_flag,
                 heap
		 );
      break;

    case REC_BIN32_SIGNED:
      if (column_desc->precision > 0)
	type = new (heap)
	SQLNumeric(column_desc->length,
		   column_desc->precision,
		   column_desc->scale,
		   TRUE,
		   column_desc->null_flag,
                   heap
		   );
      else
	type = new (heap)
	SQLInt(TRUE,
	       column_desc->null_flag,
               heap
	       );
      break;
    case REC_BIN32_UNSIGNED:
      if (column_desc->precision > 0)
	type = new (heap)
	SQLNumeric(column_desc->length,
		   column_desc->precision,
		   column_desc->scale,
		   FALSE,
		   column_desc->null_flag,
                   heap
		   );
      else
	type = new (heap)
	SQLInt(FALSE,
	       column_desc->null_flag,
               heap
	       );
      break;
    case REC_BIN64_SIGNED:
      if (column_desc->precision > 0)
	type = new (heap)
	SQLNumeric(column_desc->length,
		   column_desc->precision,
		   column_desc->scale,
		   TRUE,
		   column_desc->null_flag,
                   heap
		   );
      else
	type = new (heap)
	SQLLargeInt(TRUE,
		    column_desc->null_flag,
                    heap
		    );
      break;
    case REC_BIN64_UNSIGNED:
      if (column_desc->precision > 0)
	type = new (heap)
	SQLNumeric(column_desc->length,
		   column_desc->precision,
		   column_desc->scale,
		   FALSE,
		   column_desc->null_flag,
                   heap
		   );
      else
	type = new (heap)
        SQLLargeInt(FALSE,
		    column_desc->null_flag,
                    heap
		    );
      break;
    case REC_DECIMAL_UNSIGNED:
      type = new (heap)
	SQLDecimal(column_desc->length,
		   column_desc->scale,
		   FALSE,
		   column_desc->null_flag,
                   heap
		   );
      break;
    case REC_DECIMAL_LSE:
      type = new (heap)
	SQLDecimal(column_desc->length,
		   column_desc->scale,
		   TRUE,
		   column_desc->null_flag,
                   heap
		   );
      break;
    case REC_NUM_BIG_UNSIGNED:
      type = new (heap)
	SQLBigNum(column_desc->precision,
		  column_desc->scale,
		  TRUE, // is a real bignum
		  FALSE,
		  column_desc->null_flag,
		  heap
		  );
      break;
    case REC_NUM_BIG_SIGNED:
      type = new (heap)
	SQLBigNum(column_desc->precision,
		  column_desc->scale,
		  TRUE, // is a real bignum
		  TRUE,
		  column_desc->null_flag,
		  heap
		  );
      break;

    case REC_FLOAT32:
      type = new (heap)
	SQLReal(column_desc->null_flag, heap, column_desc->precision);
      break;

    case REC_FLOAT64:
      type = new (heap)
	SQLDoublePrecision(column_desc->null_flag, heap, column_desc->precision);
      break;

    case REC_BYTE_F_DOUBLE:
      charCount /= SQL_DBCHAR_SIZE;	    // divide the storage length by 2
      type = new (heap)
	SQLChar(charCount,
		column_desc->null_flag,
		column_desc->upshift,
		column_desc->caseinsensitive,
		FALSE,
		column_desc->character_set,
		column_desc->collation_sequence,
		CharInfo::IMPLICIT
		);
      break;

    case REC_BYTE_F_ASCII:
      if (column_desc->character_set == CharInfo::UTF8 ||
          (column_desc->character_set == CharInfo::SJIS &&
           column_desc->encoding_charset == CharInfo::SJIS))
      {
        Lng32 maxBytesPerChar = CharInfo::maxBytesPerChar(column_desc->character_set);
        Lng32 sizeInChars = charCount ;  // Applies when CharLenUnit == BYTES
        if ( column_desc->precision > 0 )
           sizeInChars = column_desc->precision;
        type = new (heap)
	SQLChar(CharLenInfo(sizeInChars, charCount/*in_bytes*/),
		column_desc->null_flag,
		column_desc->upshift,
		column_desc->caseinsensitive,
		FALSE, // varLenFlag
		column_desc->character_set,
		column_desc->collation_sequence,
		CharInfo::IMPLICIT, // Coercibility
		column_desc->encoding_charset
		);
      }
      else // keep the old behavior
      type = new (heap)
	SQLChar(charCount,
		column_desc->null_flag,
		column_desc->upshift,
		column_desc->caseinsensitive,
		FALSE,
		column_desc->character_set,
		column_desc->collation_sequence,
		CharInfo::IMPLICIT
		);
      break;

    case REC_BYTE_V_DOUBLE:
      charCount /= SQL_DBCHAR_SIZE;	    // divide the storage length by 2
      // fall thru
    case REC_BYTE_V_ASCII:
      if (column_desc->character_set == CharInfo::SJIS ||
          column_desc->character_set == CharInfo::UTF8)
      {
        Lng32 maxBytesPerChar = CharInfo::maxBytesPerChar(column_desc->character_set);
        Lng32 sizeInChars = charCount ;  // Applies when CharLenUnit == BYTES
        if ( column_desc->precision > 0 )
           sizeInChars = column_desc->precision;
        type = new (heap)
	SQLVarChar(CharLenInfo(sizeInChars, charCount/*in_bytes*/),
		   column_desc->null_flag,
		   column_desc->upshift,
		   column_desc->caseinsensitive,
		   column_desc->character_set,
		   column_desc->collation_sequence,
		   CharInfo::IMPLICIT, // Coercibility
		   column_desc->encoding_charset
		   );
      }
      else // keep the old behavior
      type = new (heap)
	SQLVarChar(charCount,
		   column_desc->null_flag,
		   column_desc->upshift,
		   column_desc->caseinsensitive,
		   column_desc->character_set,
		   column_desc->collation_sequence,
		   CharInfo::IMPLICIT
		   );
      break;

    case REC_BYTE_V_ASCII_LONG:
      type = new (heap)
	SQLLongVarChar(charCount,
		       FALSE,
		       column_desc->null_flag,
		       column_desc->upshift,
		       column_desc->caseinsensitive,
		       column_desc->character_set,
		       column_desc->collation_sequence,
		       CharInfo::IMPLICIT
		      );
      break;
    case REC_DATETIME:
      type = DatetimeType::constructSubtype(
					    column_desc->null_flag,
					    column_desc->datetimestart,
					    column_desc->datetimeend,
					    column_desc->datetimefractprec,
					    heap
					    );
      CMPASSERT(type);
      if (!type->isSupportedType())
	{
         column_desc->defaultClass = COM_NO_DEFAULT;           // can't set a default for these, either.
	  // 4030 Column is an unsupported combination of datetime fields
     if (!errorCode)
     {
         *CmpCommon::diags() << DgSqlCode(4030)
	    << DgColumnName(makeColumnName(table, column_desc))
	    << DgInt0(column_desc->datetimestart)
	    << DgInt1(column_desc->datetimeend)
	    << DgInt2(column_desc->datetimefractprec);
     }
     else
     {
       *errorCode = 4030;
     }
	}
      break;
    case REC_INTERVAL:
      type = new (heap)
         SQLInterval(column_desc->null_flag,
		    column_desc->datetimestart,
		    column_desc->intervalleadingprec,
		    column_desc->datetimeend,
		    column_desc->datetimefractprec,
                    heap
		    );
      CMPASSERT(type);
      if (! ((SQLInterval *)type)->checkValid(CmpCommon::diags()))
         return TRUE;                                            // error
      if (!type->isSupportedType())
      {
        column_desc->defaultClass = COM_NO_DEFAULT;           // can't set a default for these, either.
        if (!errorCode)
          *CmpCommon::diags() << DgSqlCode(3044) << DgString0(column_desc->colname);
        else
          *errorCode = 3044;

      }
      break;
    case REC_BLOB :
      type = new (heap)
	SQLBlob(column_desc->precision, Lob_Invalid_Storage,
		column_desc->null_flag);
      break;

    case REC_CLOB :
      type = new (heap)
	SQLClob(column_desc->precision, Lob_Invalid_Storage,
		column_desc->null_flag);
      break;

    default:
      {
	// 4031 Column %s is an unknown data type, %d.
        if (!errorCode)
        {
	*CmpCommon::diags() << DgSqlCode(-4031)
	  << DgColumnName(makeColumnName(table, column_desc))
	  << DgInt0(column_desc->datatype);
        }
        else
        {
          *errorCode = 4031;
        }
	return TRUE;						// error
      }
    } // end switch (column_desc->datatype)

  CMPASSERT(type);

  if (type->getTypeQualifier() == NA_CHARACTER_TYPE) {
    CharInfo::Collation co = ((CharType *)type)->getCollation();

    // a "mini-cache" to avoid proc call, for perf
    static THREAD_P CharInfo::Collation cachedCO = CharInfo::UNKNOWN_COLLATION;
    static THREAD_P Int32         cachedFlags = CollationInfo::ALL_NEGATIVE_SYNTAX_FLAGS;

    if (cachedCO != co) {
      cachedCO = co;
      cachedFlags = CharInfo::getCollationFlags(co);
    }

    if (cachedFlags & CollationInfo::ALL_NEGATIVE_SYNTAX_FLAGS) {
      //
      //## The NCHAR/COLLATE NSK-Rel1 project is forced to disallow all user-
      //	defined collations here.  What we can't handle is:
      //	- full support!  knowledge of how to really collate!
      //	- safe predicate-ability of collated columns, namely
      //	  . ORDER/SEQUENCE/SORT BY
      //	    MIN/MAX
      //	    < <= > >=
      //		These *would* have been disallowed by the
      //		CollationInfo::ORDERED_CMP_ILLEGAL flag.
      //	  . DISTINCT
      //	    GROUP BY
      //	    = <>
      //		These *would* have been disallowed by the
      //		CollationInfo::EQ_NE_CMP_ILLEGAL flag.
      //	  . SELECTing a collated column which is a table or index key
      //		We *would* have done full table scan only, based on flag
      //	  . INS/UPD/DEL involving a collated column which is a key
      //		We *would* have had to disallow this, based on flag;
      //		otherwise we would position in wrong and corrupt either
      //		our partitioning or b-trees or both.
      //	See the "MPcollate.doc" document, and
      //	see sqlcomp/DefaultValidator.cpp ValidateCollationList comments.
      //
	{
	  // 4069 Column TBL.COL uses unsupported collation COLLAT.
	  if (!errorCode)
	  {
	  *CmpCommon::diags() << DgSqlCode(-4069)
	    << DgColumnName(makeColumnName(table, column_desc));
	  }
	  else
	  {
	    *errorCode= 4069;
	  }
	  return TRUE;						// error
	}
    }
  }

  return FALSE;							// no error

} // createNAType()
// Apply defaults to self, and then (ANSI 12.1 SR 3) apply self to SchemaDB.
NABoolean StmtModule::applyDefaults(NABoolean wantR18behavior)
{
  NABoolean err = FALSE;

  if (charSet().isNull())
    charSet() = CharInfo::getCharSetName(CharInfo::DefaultCharSet);

  if (CharInfo::isCharSetSupported(charSet())) {
    // Get charset name in canonical format (the name of the enum of the name).
    charSet() = CharInfo::getCharSetName(CharInfo::getCharSetEnum(charSet()));
  }
  else {
    *CmpCommon::diags() << DgSqlCode(-3010) << DgString0(charSet());
    err = TRUE;
  }

  if (!CharInfo::isModuleCharSetSupported(CharInfo::getCharSetEnum(charSet()))) 
  {
    *CmpCommon::diags() << DgSqlCode(-3404) << DgString0(charSet());
    err = TRUE;
  }

  // Here we're using internal-format names
  if (name().getCatalogName().isNull()) {

    // Must be an Ansi name, not an MPLOC.
    const SchemaName& defcs =
      ActiveSchemaDB()->getDefaultSchema(
        SchemaDB::REFRESH_CACHE | SchemaDB::FORCE_ANSI_NAMETYPE);

    if (name().getSchemaName().isNull()) {
      if (name().getObjectName().isNull()) {
        name().setObjectName("SQLMX_DEFAULT_MODULE_");
      }
      name().setSchemaName(defcs.getSchemaName());
    }
    name().setCatalogName(defcs.getCatalogName());

  }

  if (wantR18behavior) {
    // And now we use external-format names, for the ANSI 12.1 SR 3 stuff.
    NAString catName(name().getCatalogNameAsAnsiString());
    if (!ActiveSchemaDB()->getDefaults().setCatalog(catName))
      err = TRUE;
  
    NAString schName(name().getUnqualifiedSchemaNameAsAnsiString());
    if (!ActiveSchemaDB()->getDefaults().setSchema(schName))
      err = TRUE;
  }
  else { // want R2 (correct) behavior
    // We used to take the catalog & schema of the module directive and apply
    // them above as the default catalog & schema. This was a misguided
    // attempt to "use external-format names, for the ANSI 12.1 SR 3 stuff"
    // in the SQL92 std. 
    // 
    // In SQL99, this has been clarified in section 13.1 of ISO/IEC FDIS 
    // 9075-2:1999 (aka the 1999 Foundation doc) where syntax rules 3 & 4
    // specify that:
    // 
    // "If the explicit or implicit <schema name> does not specify a <catalog
    //  name>, then an implementation-defined <catalog name> is implicit."
    // 
    // "The implicit or explicit <catalog name> is the implicit <catalog name>
    //  for all unqualified <schema name>s in the <SQL-client module 
    //  definition>."
    //
    // Three observations may be worth pointing out here:
    // 1) SQL/MX client modules do not have a <module authorization clause> as
    //    specified by the SQL99 std.
    // 2) Even if (in the future) SQL/MX tries to conform to the SQL99 std for 
    //    client module definition(s), the SQL99 std itself (syntax rule 3) 
    //    allows us to use "an implementation-defined <catalog name>" to 
    //    implicitly qualify unqualified <schema name>s.
    // 3) This current "implementation is a deviation from ANSI in
    //    that the module name is a 3-part name. This deviation and the use of
    //    cat/sch name to qualify unqualified SQL objects in the module are
    //    also 'valid' implementation of the 2 syntax rules 13.1, rules 3 & 4
    //    of ANSI."
    // Similar logic can be applied to using an implementation-defined
    // <schema name> to implicitly qualify unqualified table names, etc.
    // 
    // In other words, our technique of using CQD default CATALOG & SCHEMA
    // settings to qualify unqualified table names, view names, etc is allowed
    // for by the SQL99 std.
    // 
    // Deleting the old code that was here is part of the fix to genesis
    // cases 10-030725-8215, 10-030730-8326, 10-030826-0792.
  }
  return err;
}
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;
  }
ExprNode *
ElemDDLPartitionSystem::bindNode(BindWA * /*pBindWA*/)
{
  //
  // location
  //
  ComLocationName defaultLocName;  // empty object

  if (getLocationName().isNull())
    //
    // location clause not specified (only allowed for primary partition)
    //
    guardianLocation_ =
      defaultLocName.getGuardianFullyQualifiedName();
  else  // LOCATION clause was specified
  {
    ComLocationName locName;         // empty object
    switch (getLocationNameType())
    {
    case ElemDDLLocation::LOCATION_GUARDIAN_NAME :
      locName.copy(getLocationName(),
                   ComLocationName::GUARDIAN_LOCATION_NAME_FORMAT);
      if (NOT locName.isValid())
      {
        // Illegal location name format.
        *SqlParser_Diags << DgSqlCode(-3061) << DgString0(getLocationName());
        guardianLocation_ =
          defaultLocName.getGuardianFullyQualifiedName();
      }
      else  // valid location
        guardianLocation_ =
          locName.getGuardianFullyQualifiedName();
      break;

    case ElemDDLLocation::LOCATION_OSS_NAME :
      locName.copy(getLocationName(),
                   ComLocationName::OSS_LOCATION_NAME_FORMAT);
      if (NOT locName.isValid())
      {
        // Illegal location name format.
        *SqlParser_Diags << DgSqlCode(-3061) << DgString0(getLocationName());
        guardianLocation_ =
          defaultLocName.getGuardianFullyQualifiedName();
      }
      else  // valid location
        guardianLocation_ =
          locName.getGuardianFullyQualifiedName();
      break;

#if 0
      //
      // Currently we do not handle this case
      // The grammar productions don't accept this syntax.
      // So comment out the following code for now.
      //
    case ElemDDLLocation::LOCATION_ENVIRONMENT_VARIABLE :
      {
        NAString envVarName(getLocationName());
        //
        // if the specified OSS environment variable has the
        // dollar sign prefix, removes it.
        //
	    if (envVarName[(size_t) 0] EQU '$')            // NT_PORT FIX SK 07/15/96
        {
          envVarName = envVarName(1/*startpos*/, envVarName.length() - 1);
        }
        const char * pEnvVarValue = getenv((const char *)envVarName);
        NAString locationName;
        if (pEnvVarValue NEQ NULL)
        {
          locationName = pEnvVarValue;
        }
        if (locationName.isNull())
        {
          guardianLocation_ = defaultLocName.
                              getGuardianFullyQualifiedName();
        }
        else
        {
          guardianLocationName = locationName;
          if (guardianLocationName.isValid())
          {
            guardianLocation_ = (guardianLocationName.
                                 getGuardianFullyQualifiedName());
            
          }
          else
          {
            ossLocationName = locationName;
            if (ossLocationName.isValid())
            {
              guardianLocation_ = (ossLocationName.
                                   getGuardianFullyQualifiedName());
            }
            else
            {
              // OSS environment variable $1~string1 contains illegal
              // location name $0~string0.
              *SqlParser_Diags << DgSqlCode(-3061) 
		<< DgString0(locationName)
	        << DgString1(envVarName)
		;
            }
          }
        }
      }
      break;
#endif // 0

    default :
      NAAbort("ElemDDLPartition.C", __LINE__, "internal logic error");
      break;
    }
  }

  markAsBound();
  return this;
}
// return next token
ExtQualModuleNames::tokenType ExtQualModuleNames::scanner()
{
  currentToken_ = "";
  if (atEnd()) {
    return SCANEOF;
  }
  while (!atEnd()) {
    const char cc = returnAdvanceChar();
    if (isspace((unsigned char)cc)) {   // For VS2003...
      continue; // do nothing
    }
    else if (isalpha(cc)) { // regular identifier
      currentToken_ += cc;
      while (isalnum(currentChar()) || currentChar() == '_') {
        currentToken_ += currentChar();
        advanceChar();
      }
      // convert id to internal format (ie, uppercase it)
      NAString id(currentToken_.c_str());
      if (ToInternalIdentifier(id) != 0) {
        *mxCUMptr << FAIL << DgSqlCode(-2215)
                  << DgString0(currentToken_.c_str());
      }
      currentToken_ = id.data();
      return checkReserved();
    }
    currentToken_ += cc;
    switch (cc) {
    case '{' :
    case '}' :
    case ',' :
    case '.' :
    case '=' :
      return tokenType(cc);
    case '"':
      // "delimited identifier" specified by \"([^\"]|"\"\"")*\"
      while (!atEnd()) {
        const char c1 = returnAdvanceChar();
        currentToken_ += c1;
        if (c1 == '"') {
          if (currentChar() == '"') {
            currentToken_ += currentChar();
          }
          else { // end of delimited identifier
            // convert delimited id to internal format
            NAString id(currentToken_.c_str());
            if (ToInternalIdentifier(id, FALSE, TRUE) != 0) {
              *mxCUMptr << FAIL << DgSqlCode(-2209)
                        << DgString0(currentToken_.c_str());
            }
            currentToken_ = id.data();
            return ID;
          }
        }
      }
      *mxCUMptr << FAIL << DgSqlCode(-2210); // unterminated string
      return ID;
    default:
      advanceChar();
      *mxCUMptr << FAIL << DgSqlCode(-2211)
                << DgString0(currentToken_.c_str());
      return SCANERROR;
    }
  }
  return SCANEOF;
}
short CmpSeabaseDDL::validateRoutine(ExeCliInterface *cliInterface,
                                     const char * className,
                                     const char * methodName,
                                     const char * externalPath,
                                     char * signature,
                                     Int32 numSqlParam,
                                     Int32 maxResultSets,
                                     const char * optionalSig)
{
  
  //
  // Now proceed with the internal CALL statement...
  //

  Lng32 sigLen = 0;
  if (signature)
    sigLen = str_len(signature) + 1;

  char * query = new(STMTHEAP) char[2000+sigLen];
  str_sprintf(query, "call %s.\"%s\".%s ('%s', '%s', '%s', '%s', %d, %d, %d, ?x, ?y, ?z)",
	      getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_VALIDATE_SPJ,
	      className, methodName, externalPath, signature,
              numSqlParam, maxResultSets, optionalSig ? 1 : 0); 
             
  Lng32 cliRC = cliInterface->fetchRowsPrologue(query, TRUE/*no exec*/);
  if (cliRC < 0)
  {
     cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
     return -1;
  }

  cliRC = cliInterface->clearExecFetchClose(NULL, 0);
  if (cliRC < 0)
  {
    cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
     return -1;
  }
 
  NADELETEBASIC(query, STMTHEAP);

  char * ptr = NULL;
  Lng32 len = 0;
  Int32 errCode = 0;

  cliInterface->getPtrAndLen(1, ptr, len);
  str_cpy_all(signature, ptr, len);
  signature[len] =  '\0';
  cliInterface->getPtrAndLen(2, ptr, len);
  errCode = *(Int32 *)ptr;

  // in code below methodName may need to be added to the signature that is printed 
  // out in some error messages.
  // Check for errors returned from VALIDATEROUTINE
  switch (errCode)
  {
    case 0://Success - Check to see if returned signature is null
        if (signature[0] NEQ '\0')
          return 0;
        else
          return -1;
      break;
    case 11205://Class not found
        *CmpCommon::diags() << DgSqlCode(-errCode)
                            << DgString0(className)
                            << DgString1(externalPath);
      break;
    case 11206://Class definition not found
        *CmpCommon::diags() << DgSqlCode(-errCode)
                  << DgString0(className);
      break;
    case 11230://Overloaded methods were found
        *CmpCommon::diags() << DgSqlCode(-errCode)
                            << DgString0(methodName)
                            << DgString1(className);
      break;
    case 11239://No compatible methods were found
      *CmpCommon::diags() << DgSqlCode(-errCode)
                          << DgString0(methodName)
                          << DgString1(className);
      break;
    case 11231://Method found but not public
      if(signature[0] NEQ '\0')
        *CmpCommon::diags() << DgSqlCode(-errCode)
                            << DgString0(signature)
                            << DgString1(className);
      break;
    case 11232://Method found but not static
      if(signature[0] NEQ '\0')
        *CmpCommon::diags() << DgSqlCode(-errCode)
                            << DgString0(signature)
                            << DgString1(className);
      break;
    case 11233://Method found but not void
        if(signature[0] NEQ '\0')
          *CmpCommon::diags() << DgSqlCode(-errCode)
                              << DgString0(signature)
                              << DgString1(className);
        break;
    case 11234://Method not found
        if(signature[0] NEQ '\0')
          *CmpCommon::diags() << DgSqlCode(-errCode)
                              << DgString0(signature)
                              << DgString1(className);
        break;
    default://Unknown error code
      break ;
  }
  return -1;

} // CmpSeabaseDDL::validateRoutine
void CmpSeabaseDDL::createSeabaseLibrary(
				      StmtDDLCreateLibrary * createLibraryNode,
				      NAString &currCatName, 
                                      NAString &currSchName)
{
  Lng32 retcode = 0;
 
  ComObjectName libraryName(createLibraryNode->getLibraryName());
  ComAnsiNamePart currCatAnsiName(currCatName);
  ComAnsiNamePart currSchAnsiName(currSchName);
  libraryName.applyDefaults(currCatAnsiName, currSchAnsiName);
  const NAString catalogNamePart = 
    libraryName.getCatalogNamePartAsAnsiString();
  const NAString schemaNamePart = 
    libraryName.getSchemaNamePartAsAnsiString(TRUE);
  const NAString objectNamePart = 
    libraryName.getObjectNamePartAsAnsiString(TRUE);
  const NAString extLibraryName = libraryName.getExternalName(TRUE);
  const NAString extNameForHbase = catalogNamePart + "." + schemaNamePart + 
    "." + objectNamePart;
  
  // Verify that the requester has MANAGE_LIBRARY privilege.
  if (isAuthorizationEnabled() && !ComUser::isRootUserID())
    {
      NAString privMgrMDLoc;
      CONCAT_CATSCH(privMgrMDLoc, getSystemCatalog(), SEABASE_PRIVMGR_SCHEMA);

      PrivMgrComponentPrivileges componentPrivileges(std::string(privMgrMDLoc.data()),CmpCommon::diags());

      if (!componentPrivileges.hasSQLPriv
            (ComUser::getCurrentUser(),SQLOperation::MANAGE_LIBRARY,true))
      {
         *CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
         processReturn ();
         return;
      }
    }

  // Check to see if user has the authority to create the library
  ExeCliInterface cliInterface(STMTHEAP, NULL, NULL,
    CmpCommon::context()->sqlSession()->getParentQid());
  Int32 objectOwnerID = SUPER_USER;
  Int32 schemaOwnerID = SUPER_USER;
  ComSchemaClass schemaClass;

  retcode = verifyDDLCreateOperationAuthorized(&cliInterface,
                                               SQLOperation::CREATE_LIBRARY,
                                               catalogNamePart,
                                               schemaNamePart,
                                               schemaClass,
                                               objectOwnerID,
                                               schemaOwnerID);
  if (retcode != 0)
  {
     handleDDLCreateAuthorizationError(retcode,catalogNamePart,schemaNamePart);
     return;
  }
     
  ExpHbaseInterface * ehi = NULL;

  ehi = allocEHI();
  if (ehi == NULL)
    {
      processReturn();
      return;
    }

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

  if (retcode == 1) // already exists
    {
      *CmpCommon::diags() << DgSqlCode(-1390)
			  << DgString0(extLibraryName);
      deallocEHI(ehi); 
      processReturn();
      return;
    }

  NAString libFileName = createLibraryNode->getFilename() ;
  // strip blank spaces
  libFileName = libFileName.strip(NAString::both, ' ');

  if (validateLibraryFileExists(libFileName, FALSE))
    {
      deallocEHI(ehi); 
      processReturn();
      return;
    }

  ComTdbVirtTableTableInfo * tableInfo = new(STMTHEAP) ComTdbVirtTableTableInfo[1];
  tableInfo->tableName = NULL,
  tableInfo->createTime = 0;
  tableInfo->redefTime = 0;
  tableInfo->objUID = 0;
  tableInfo->objOwnerID = objectOwnerID;
  tableInfo->schemaOwnerID = schemaOwnerID;
  tableInfo->isAudited = 1;
  tableInfo->validDef = 1;
  tableInfo->hbaseCreateOptions = NULL;
  tableInfo->numSaltPartns = 0;
  tableInfo->rowFormat = COM_UNKNOWN_FORMAT_TYPE;
  tableInfo->objectFlags = 0;
  
  Int64 objUID = -1;
  if (updateSeabaseMDTable(&cliInterface, 
			   catalogNamePart, schemaNamePart, objectNamePart,
			   COM_LIBRARY_OBJECT,
			   "N",
			   tableInfo,
			   0,
			   NULL,
			   0,			       
			   NULL,
			   0, NULL,
                           objUID))
    {
      deallocEHI(ehi); 
      processReturn();
      return;
    }

  if (objUID == -1)
    {
      deallocEHI(ehi); 
      processReturn();
      return;
    }
 
  char * query = new(STMTHEAP) char[1000];
  str_sprintf(query, "insert into %s.\"%s\".%s values (%Ld, '%s', %d)",
	      getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_LIBRARIES,
	      objUID,
              libFileName.data(),
              createLibraryNode->getVersion());
  
  Lng32 cliRC = cliInterface.executeImmediate(query);

  NADELETEBASIC(query, STMTHEAP);
  if (cliRC < 0)
    {
      cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
      processReturn();
      return;
    }

  // hope to remove this call soon by setting thevalid flag to Y sooner
  if (updateObjectValidDef(&cliInterface, 
			   catalogNamePart, schemaNamePart, objectNamePart,
			   COM_LIBRARY_OBJECT_LIT,
			   "Y"))
    {
      deallocEHI(ehi); 
      processReturn();
      return;
    }

  processReturn();

  return;
}
// constructor
ElemDDLColDef::ElemDDLColDef(
     const NAString *columnFamily,
     const NAString *columnName,
     NAType * pColumnDataType,
     ElemDDLNode * pColAttrList,
     CollHeap * heap)
: ElemDDLNode(ELM_COL_DEF_ELEM),
  columnName_(*columnName, heap),
  columnDataType_(pColumnDataType),
  defaultClauseStatus_(DEFAULT_CLAUSE_NOT_SPEC),
  isNewAdjustedDefaultConstValueNode_(FALSE),
  pDefault_(NULL),
  isHeadingSpec_(FALSE),
  heading_(heap),
  columnClass_(COM_USER_COLUMN),
  isNotNullSpec_(FALSE),
  isNotNullNondroppable_(FALSE),
  isLoggableSpec_(FALSE),
  isLoggable_(TRUE),
  pConstraintNotNull_(NULL),
  isPrimaryKeySpec_(FALSE),
  pConstraintPK_(NULL),
  columnConstraintArray_(heap),
  primaryKeyColRefArray_(heap),
  direction_(COM_OUTPUT_COLUMN),
  pSGOptions_(NULL),
  pSGLocation_(NULL),
  isDivisionColumn_(FALSE),
  divisionColumnSeqNum_(-1),
  isLobAttrsSpec_(FALSE),
  lobStorage_(Lob_HDFS_File),
  isSeabaseSerializedSpec_(FALSE),
  seabaseSerialized_(FALSE),
  isColDefaultSpec_(FALSE)
{
  //  ComASSERT(pColumnDataType NEQ NULL);

  if (columnFamily)
    columnFamily_ = *columnFamily;

  if (pColumnDataType NEQ NULL)
  {
    const NAString dataTypeName = pColumnDataType->getTypeName();

    // Create table with data type DATETIME not supported. Must check for DATE,
    // TIME, and TIMESTAMP as well since DATETIME might be converted into these,
    if(
      dataTypeName == "DATETIME" ||
      dataTypeName == "DATE" ||
      dataTypeName == "TIME" ||
      dataTypeName == "TIMESTAMP"
      )
    {
      // Check flag to see if DATETIME originally specified
      if( ((DatetimeIntervalCommonType *)pColumnDataType)->
	  getDTIFlag(DatetimeIntervalCommonType::UNSUPPORTED_DDL_DATA_TYPE))
      {
	// Only put error into diags if it doesn't already contain it
	if(!SqlParser_Diags->contains(-3195))
        {
	  *SqlParser_Diags << DgSqlCode(-3195) 
			   << DgString0("DATETIME");
	}
	return;
      }
    }
    // Create table with data type INTERVAL with FRACTION field(s) not supported
    else if (dataTypeName == "INTERVAL")
    {
      // Check flag to see if FRACTION was originally specified
      if( ((DatetimeIntervalCommonType *)pColumnDataType)->
	  getDTIFlag(DatetimeIntervalCommonType::UNSUPPORTED_DDL_DATA_TYPE))
      {
	// Only put error into diags if it doesn't already contain it
	if(!SqlParser_Diags->contains(-3195))
	{
	  *SqlParser_Diags << DgSqlCode(-3195)
			   << DgString0("INTERVAL with FRACTION field(s)");
	}
	return;
      }

      // Check to see if interval second is specified with leading 
      // precision of 0
      if(!((SQLInterval *)pColumnDataType)->isSupportedType())
      {
	// Only put error into diags if it doesn't already contain it
        if(!SqlParser_Diags->contains(-3195))
        {
	  *SqlParser_Diags << DgSqlCode(-3195)
			   << DgString0("INTERVAL SECOND with leading precision 0");
	}
	return;
      }
    }
  }

  setChild(INDEX_ELEM_DDL_COL_ATTR_LIST, pColAttrList);

  // initialize data member pDefault_

  ComBoolean isIdentityColumn = FALSE;

  //
  // Traverse the list of column attributes to check for duplicate
  // HEADING clause and duplicate NOT NULL column constraint definition
  //

  if (pColAttrList NEQ NULL)
  {
    for (CollIndex index = 0; index < pColAttrList->entries(); index++)
    {
      setColumnAttribute((*pColAttrList)[index]);
    }
  }

  // At this point we will know if the user
  // has specified NOT NULL NOT DROPPABLE for IDENTITY
  // column. If not specified, then automatically add
  // it. 
  if (pSGOptions_) //isIdentityColumn
    {
      // if NOT NULL not specified, then specify it here.
      if(NOT getIsConstraintNotNullSpecified())
	isNotNullSpec_ = TRUE;
      
      // [NOT] DROPPABLE is the only attribute for NOT NULL.
      if (pConstraintNotNull_)
	{
	  // if DROPPABLE was specified explicity then raise an error.
	  if (pConstraintNotNull_->isDroppableSpecifiedExplicitly())
	    {
	      *SqlParser_Diags << DgSqlCode(-3413)
			       << DgColumnName(ToAnsiIdentifier(getColumnName()));
	      return;
	    }
          else
            {
              // add the NOT DROPPABLE attribute to the NOT NULL .
              pConstraintNotNull_->setConstraintAttributes
                (new (PARSERHEAP()) ElemDDLConstraintAttrDroppable(FALSE)); 
            }
	}
      else
	{
	  // by default NOT NULLs are NOT DROPPABLEs as well in SQL/MX
	  pConstraintNotNull_ = new (PARSERHEAP()) ElemDDLConstraintNotNull(PARSERHEAP());
	  pConstraintNotNull_->setConstraintAttributes
	    (new (PARSERHEAP()) ElemDDLConstraintAttrDroppable(FALSE)); 
	}
    } //if isIdentityColumn
  
  //
  // All column attributes has been checked and saved.
  // If there exists a NOT NULL NONDROPPABLE constraint
  // associating with the currently defined column, makes
  // sure that the associating NAType (data type) parse
  // node does not allow null values.
  //

  if (getIsConstraintNotNullSpecified() AND
      NOT getConstraintNotNull()->isDroppable())
  {
    isNotNullNondroppable_ = TRUE; 
    if (columnDataType_)
      columnDataType_->setNullable(FALSE);
  }
  
}  // ElemDDLColDef()
void CmpSeabaseDDL::dropSeabaseRoutine(StmtDDLDropRoutine * dropRoutineNode,
                                       NAString &currCatName, 
                                       NAString &currSchName)
{
  Lng32 retcode = 0;
 
  ComObjectName routineName(dropRoutineNode->getRoutineName());
  ComAnsiNamePart currCatAnsiName(currCatName);
  ComAnsiNamePart currSchAnsiName(currSchName);
  routineName.applyDefaults(currCatAnsiName, currSchAnsiName);
  const NAString catalogNamePart = 
    routineName.getCatalogNamePartAsAnsiString();
  const NAString schemaNamePart = 
    routineName.getSchemaNamePartAsAnsiString(TRUE);
  const NAString objectNamePart = 
    routineName.getObjectNamePartAsAnsiString(TRUE);
  const NAString extRoutineName = routineName.getExternalName(TRUE);
  
  ExpHbaseInterface * ehi = NULL;
  ExeCliInterface cliInterface(STMTHEAP, NULL, NULL, 
    CmpCommon::context()->sqlSession()->getParentQid());

  ehi = allocEHI();
  if (ehi == NULL)
    {
      processReturn();
      return;
    }

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

  if (retcode == 0) // does not exist
    {
      *CmpCommon::diags() << DgSqlCode(-1389)
			  << DgString0(extRoutineName);
      deallocEHI(ehi); 
      processReturn();
      return;
    }
  
  // get objectOwner
  Int64 objUID = 0;
  Int32 objectOwnerID = 0;
  Int32 schemaOwnerID = 0;
  Int64 objectFlags = 0;

  // see if routine is cached
  BindWA bindWA(ActiveSchemaDB(), CmpCommon::context(), FALSE/*inDDL*/);
  NARoutineDB *pRoutineDBCache  = ActiveSchemaDB()->getNARoutineDB();
  QualifiedName qualRoutineName(routineName, STMTHEAP);
  NARoutineDBKey key(qualRoutineName, STMTHEAP);

  NARoutine *cachedNARoutine = pRoutineDBCache->get(&bindWA, &key);
  if (cachedNARoutine)
    {
      objUID = cachedNARoutine->getRoutineID();
      objectOwnerID = cachedNARoutine->getObjectOwner();
      schemaOwnerID = cachedNARoutine->getSchemaOwner();
    }
  else
    {
      objUID = getObjectInfo(&cliInterface,
			      catalogNamePart.data(), schemaNamePart.data(), 
			      objectNamePart.data(), COM_USER_DEFINED_ROUTINE_OBJECT,
                              objectOwnerID,schemaOwnerID,objectFlags);
    if (objUID < 0 || objectOwnerID == 0 || schemaOwnerID == 0)
      {
        deallocEHI(ehi); 
        processReturn();
        return;
      }
    }

  // Verify user has privilege to drop routine
  if (!isDDLOperationAuthorized(SQLOperation::DROP_ROUTINE,objectOwnerID,schemaOwnerID))
  {
     *CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
     deallocEHI(ehi);
     processReturn ();
     return;
  }
  
  // Determine if this function is referenced by any other objects.
  Lng32 cliRC = 0;
  Queue * usingViewsQueue = NULL;
  if (dropRoutineNode->getDropBehavior() == COM_RESTRICT_DROP_BEHAVIOR)
    {
      NAString usingObjName;
      cliRC = getUsingObject(&cliInterface, objUID, usingObjName);
      if (cliRC < 0)
        {
          deallocEHI(ehi); 
          processReturn();
          
          return;
        }

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

          deallocEHI(ehi); 
          processReturn();

          return;
        }
    }
  else 
    if (dropRoutineNode->getDropBehavior() == COM_CASCADE_DROP_BEHAVIOR)
    {
      cliRC = getUsingViews(&cliInterface, objUID, usingViewsQueue);
      if (cliRC < 0)
        {
          deallocEHI(ehi); 
          processReturn();
          
          return;
        }
    }
  
  if (usingViewsQueue)
    {
      usingViewsQueue->position();
      for (int idx = 0; idx < usingViewsQueue->numEntries(); idx++)
        {
          OutputInfo * vi = (OutputInfo*)usingViewsQueue->getNext(); 
          
          char * viewName = vi->get(0);
          
          if (dropOneTableorView(cliInterface,viewName,COM_VIEW_OBJECT,false))
          
            {
              deallocEHI(ehi); 
              processReturn();
              
              return;
            }
        }
    }
  
  // Removed routine from metadata 
  if (dropSeabaseObject(ehi, dropRoutineNode->getRoutineName(),
                        currCatName, currSchName, COM_USER_DEFINED_ROUTINE_OBJECT,
                        TRUE, FALSE))
    {
      deallocEHI(ehi); 
      processReturn();
      return;
    }

  // Remove cached entries in other processes
  pRoutineDBCache->removeNARoutine(qualRoutineName, 
                                   NARoutineDB::REMOVE_FROM_ALL_USERS,
                                   objUID);

  deallocEHI(ehi);      
  processReturn();
  return;
}
void
ElemDDLColDef::setColumnAttribute(ElemDDLNode * pColAttr)
{
  switch(pColAttr->getOperatorType())
  {
  case ELM_COL_HEADING_ELEM :
    if (isHeadingSpec_)
    {
       // Duplicate HEADING clauses in column definition.
      *SqlParser_Diags << DgSqlCode(-3051)
                       << DgColumnName(ToAnsiIdentifier(getColumnName()));
    }
    ComASSERT(pColAttr->castToElemDDLColHeading() NEQ NULL);
    heading_ = pColAttr->castToElemDDLColHeading()->getColumnHeading();
    isHeadingSpec_ = TRUE;

    // Report an error if heading_ is too long.
    if (heading_.length() > ElemDDLColHeading::maxHeadingLength)
    {
      *SqlParser_Diags << DgSqlCode(-3132)
                       << DgColumnName(ToAnsiIdentifier(getColumnName())); 
    }
    break;

  case ELM_CONSTRAINT_CHECK_ELEM :
    ComASSERT(pColAttr->castToElemDDLConstraintCheck() NEQ NULL);
    columnConstraintArray_.insert(pColAttr->castToElemDDLConstraint());
    break;

  case ELM_CONSTRAINT_NOT_NULL_ELEM :
    ComASSERT(pColAttr->castToElemDDLConstraintNotNull() NEQ NULL);
    if (isNotNullSpec_)
    {
      // Duplicate NOT NULL clauses in column definition.
      *SqlParser_Diags << DgSqlCode(-3052)
                       << DgString0("NOT NULL")
                       << DgColumnName(ToAnsiIdentifier(getColumnName()));
    }
    isNotNullSpec_ = TRUE;
    pConstraintNotNull_ = pColAttr->castToElemDDLConstraintNotNull();

    if (NOT pConstraintNotNull_->isDroppable())
      {
	isNotNullNondroppable_ = TRUE;    
	if (columnDataType_)
	  columnDataType_->setNullable(FALSE);
      }

    // Note that we do not insert pConstraintNotNull_ into
    // columnConstraintArray_ even though Not Null constraint is
    // also a column constraint.  The user can use the accessors
    // getIsConstraintNotNullSpecified and getConstraintNotNull
    // instead.

    break;


  case ELM_LOGGABLE:
	  ComASSERT( NULL NEQ pColAttr->castToElemDDLLoggable())
		if(TRUE == isLoggableSpec_)
		{
			// Duplicate LOGGABLE in column definition.
			*SqlParser_Diags << DgSqlCode(-12064)
						   << DgColumnName(ToAnsiIdentifier(getColumnName()));
		}

		isLoggableSpec_ = TRUE;
		isLoggable_ = pColAttr->castToElemDDLLoggable()->getIsLoggable();
		break;


  case ELM_CONSTRAINT_PRIMARY_KEY_COLUMN_ELEM :
    {
      ComASSERT(pColAttr->castToElemDDLConstraintPKColumn() NEQ NULL);
      ComASSERT(pColAttr->castToElemDDLConstraintPKColumn()
                        ->getConstraintKind()
             EQU ElemDDLConstraint::COLUMN_CONSTRAINT_DEF);
      if (isPrimaryKeySpec_)
      {
	// Duplicate PRIMARY KEY clauses in column definition.
	*SqlParser_Diags << DgSqlCode(-3053)
                         << DgColumnName(ToAnsiIdentifier(getColumnName()));
      }
      isPrimaryKeySpec_ = TRUE;
      ElemDDLConstraintPKColumn * pColPKConstraint =
                                  pColAttr->castToElemDDLConstraintPKColumn();
      //
      // Copies the pointer to the parse node representing the column
      // primary key constraint to pConstraintPK_ so the user (caller)
      // can access the information easier.  Note that this pointer is
      // not inserted into columnConstraintArray_ because primary key
      // constraint is special.  (There can only be one primary key
      // constraint associating with a table.)  The user (caller) can
      // use method getIsConstraintPKSpecified() and getConstraintPK()
      // to get the primary key constraint information.
      //
      pConstraintPK_ = pColPKConstraint;

      // The column name is not specified in the column primary key
      // constraint definition.  To make the user (caller) to access
      // to this information easier, creates a parse node containing
      // the column name.
      
      ComASSERT(pColPKConstraint->getColumnRefList() EQU NULL);
      ElemDDLColRef * pColRef = new(PARSERHEAP())
	ElemDDLColRef(getColumnName(),
		      pColPKConstraint->
		      getColumnOrdering(),
                      PARSERHEAP());
      pColPKConstraint->setColumnRefList(pColRef);
      primaryKeyColRefArray_.insert(pColRef);
    }
    break;

  case ELM_CONSTRAINT_REFERENTIAL_INTEGRITY_ELEM :
    {
      ComASSERT(pColAttr->castToElemDDLConstraintRI() NEQ NULL);
      ComASSERT(pColAttr->castToElemDDLConstraintRI()->getConstraintKind()
                EQU ElemDDLConstraint::COLUMN_CONSTRAINT_DEF);
      columnConstraintArray_.insert(pColAttr->castToElemDDLConstraint());
      //
      // The column name is not specified in the column referential
      // integrity constraint definition.  To make the user (caller)
      // to access to this information easier, creates a parse node
      // containing the column name.
      //
      ElemDDLConstraintRI * pColRIConstraint =
                            pColAttr->castToElemDDLConstraintRI();
      ComASSERT(pColRIConstraint->getReferencingColumnNameList() EQU NULL);
      ElemDDLColName * pColName = new(PARSERHEAP())
	ElemDDLColName(getColumnName());
      pColRIConstraint->setReferencingColumnNameList(pColName);
    }
    break;

  case ELM_CONSTRAINT_UNIQUE_ELEM :
    {
      ComASSERT(pColAttr->castToElemDDLConstraintUnique() NEQ NULL);
      ComASSERT(pColAttr->castToElemDDLConstraintUnique()->getConstraintKind()
                EQU ElemDDLConstraint::COLUMN_CONSTRAINT_DEF);
      columnConstraintArray_.insert(pColAttr->castToElemDDLConstraint());
      //
      // The column name is not specified in the column unique
      // constraint definition.  To make the user (caller) to access
      // to this information easier, creates a parse node containing
      // the column name.
      //
      ElemDDLConstraintUnique * pColUniqueConstraint =
                                pColAttr->castToElemDDLConstraintUnique();
      ComASSERT(pColUniqueConstraint->getColumnRefList() EQU NULL);
      ElemDDLColRef * pColRef = new(PARSERHEAP())
	ElemDDLColRef(getColumnName(),
		      COM_ASCENDING_ORDER,
		      PARSERHEAP());
      pColUniqueConstraint->setColumnRefList(pColRef);
    }
    break;

  case ELM_LOBATTRS:
    {
      ComASSERT( NULL NEQ pColAttr->castToElemDDLLobAttrs())
	if(TRUE == isLobAttrsSpec_)
	  {
	    // Duplicate LOB attrs in column definition.
            *SqlParser_Diags << DgSqlCode(-3052)
                             << DgString0("LOB")
                             << DgColumnName(ToAnsiIdentifier(getColumnName()));
	  }
      
      isLobAttrsSpec_ = TRUE;
      lobStorage_ = pColAttr->castToElemDDLLobAttrs()->getLobStorage();
    }
    break;

  case ELM_SEABASE_SERIALIZED:
    {
      ComASSERT( NULL NEQ pColAttr->castToElemDDLSeabaseSerialized())
	if(TRUE == isSeabaseSerializedSpec_)
	  {
	    // Duplicate SERIALIZED attrs in column definition.
            *SqlParser_Diags << DgSqlCode(-3052)
                             << DgString0("SERIALIZED")
                             << DgColumnName(ToAnsiIdentifier(getColumnName()));
	  }
      
      isSeabaseSerializedSpec_ = TRUE;
      seabaseSerialized_ =  pColAttr->castToElemDDLSeabaseSerialized()->serialized();
    }
    break;

  case ELM_COL_DEFAULT_ELEM:
    {
      ComASSERT( NULL NEQ pColAttr->castToElemDDLColDefault());
	if(TRUE == isColDefaultSpec_)
	  {
	    // Duplicate DEFAULT attrs in column definition.
            *SqlParser_Diags << DgSqlCode(-3052)
                             << DgString0("DEFAULT")
                             << DgColumnName(ToAnsiIdentifier(getColumnName()));
	  }
      
      isColDefaultSpec_ = TRUE;
      setDefaultAttribute(pColAttr->castToElemDDLColDefault());
    }
    break;

  default :
    ABORT("internal logic error");
    break;
    
  }  // switch
}
void
ElemDDLColDef::setDefaultAttribute(ElemDDLNode * pColDefaultNode)
{
  ElemDDLColDefault * pColDefault = NULL;
  ComBoolean isIdentityColumn = FALSE;

  NAType * pColumnDataType = columnDataType_;

  if (pColDefaultNode NEQ NULL)
    {
      ComASSERT(pColDefaultNode->castToElemDDLColDefault() NEQ NULL);
      pColDefault = pColDefaultNode->castToElemDDLColDefault();
    }

  if (pColDefault NEQ NULL)
    {
      switch (pColDefault->getColumnDefaultType())
        {
        case ElemDDLColDefault::COL_NO_DEFAULT:
          defaultClauseStatus_ = NO_DEFAULT_CLAUSE_SPEC;
          break;
        case ElemDDLColDefault::COL_DEFAULT:
          {
            defaultClauseStatus_ = DEFAULT_CLAUSE_SPEC;
            
            if (pColDefault->getSGOptions())
              {
                isIdentityColumn = TRUE;
                pSGOptions_ = pColDefault->getSGOptions();
                pSGLocation_ = pColDefault->getSGLocation();
              }
            else
              {
                ComASSERT(pColDefault->getDefaultValueExpr() NEQ NULL);
                pDefault_ = pColDefault->getDefaultValueExpr();
              }
            
            // The cast ItemExpr to ConstValue for (ConstValue *)pDefault_; 
            // statement below sets arbitary value for the isNULL_. 
            // Bypass these checks for ID column (basically ITM_IDENTITY).
            ConstValue *cvDef = (ConstValue *)pDefault_;
            if ((cvDef && !cvDef->isNull()) && (!isIdentityColumn))
              {
                const NAType *cvTyp = cvDef->getType();
                NABoolean isAnErrorAlreadyIssued = FALSE;
                
                if ( cvTyp->getTypeQualifier() == NA_CHARACTER_TYPE )
                  {
                    CharInfo::CharSet defaultValueCS = ((const CharType *)cvTyp)->getCharSet();
                    // Always check for INFER_CHARSET setting before the ICAT setting.
                    NAString inferCharSetFlag;
                    if (getCharSetInferenceSetting(inferCharSetFlag) == TRUE &&
                        NOT cvDef->isStrLitWithCharSetPrefixSpecified())
                      {
                        if (pColumnDataType->getTypeQualifier() == NA_CHARACTER_TYPE
                            && ((const CharType *)pColumnDataType)->getCharSet() == CharInfo::UCS2
                            && SqlParser_DEFAULT_CHARSET == CharInfo::UCS2
                            && defaultValueCS == CharInfo::ISO88591
                            )
                          {
                            *SqlParser_Diags << DgSqlCode(-1186)
                                             << DgColumnName(ToAnsiIdentifier(getColumnName()))
                                             << DgString0(pColumnDataType->getTypeSQLname(TRUE/*terse*/))
                                             << DgString1(cvTyp->getTypeSQLname(TRUE/*terse*/));
                            isAnErrorAlreadyIssued = TRUE;
                          }
                        else
                          {
                            cvTyp = cvDef -> pushDownType(*columnDataType_, NA_CHARACTER_TYPE);
                          }
                      }
                    else if (CmpCommon::getDefault(ALLOW_IMPLICIT_CHAR_CASTING) == DF_ON &&
                             NOT cvDef->isStrLitWithCharSetPrefixSpecified() &&
                             cvTyp->getTypeQualifier() == NA_CHARACTER_TYPE &&
                             SqlParser_DEFAULT_CHARSET == CharInfo::ISO88591 &&
                             defaultValueCS == CharInfo::UnknownCharSet)
                      {
                        cvTyp = cvDef -> pushDownType(*columnDataType_, NA_CHARACTER_TYPE);
                      }
                    
                  } // column default value has character data type
                
                if (NOT isAnErrorAlreadyIssued &&
                    pColumnDataType->getTypeQualifier() == NA_CHARACTER_TYPE &&
                    cvTyp->getTypeQualifier() == NA_CHARACTER_TYPE &&
                    (
                         CmpCommon::getDefault(ALLOW_IMPLICIT_CHAR_CASTING) == DF_ON ||
                         NOT cvDef->isStrLitWithCharSetPrefixSpecified()))
                  {
                    const CharType *cdCharType = (const CharType *)pColumnDataType;
                    const CharType *cvCharType = (const CharType *)cvTyp;
                    CharInfo::CharSet cdCharSet = cdCharType->getCharSet(); // cd = column definition
                    CharInfo::CharSet cvCharSet = cvCharType->getCharSet(); // cv = constant value
                    if (cvCharSet == CharInfo::ISO88591)  // default value is a _ISO88591 str lit
                      {
                        
                      }
                    else if ( (cvCharSet == CharInfo::UNICODE ||  // default value is a _UCS2 string literal
                               cvCharSet == CharInfo::UTF8)   &&  // or a _UTF8 string literal
                              cdCharSet != cvCharSet )
                      {
                        //
                        // Check to see if all characters in the specified column default
                        // string literal value can be successfully converted/translated
                        // to the actual character set of the column.
                        //
                        char buf[2032];  // the output buffer - should be big enough
                        buf[0] = '\0';
                        enum cnv_charset eCnvCS = convertCharsetEnum( cdCharSet );
                        const char * pInStr = cvDef->getRawText()->data();
                        Int32 inStrLen = cvDef->getRawText()->length();
                        char * p1stUnstranslatedChar = NULL;
                        UInt32 outStrLenInBytes = 0;
                        unsigned charCount = 0;  // number of characters translated/converted
                        Int32 cnvErrStatus = 0;
                        char *pSubstitutionChar = NULL;
                        Int32 convFlags = 0;
                        
                        if ( cvCharSet == CharInfo::UNICODE )
                          {
                            cnvErrStatus =
                              UTF16ToLocale
                              ( cnv_version1            // in  - const enum cnv_version version
                                , pInStr                  // in  - const char *in_bufr
                                , inStrLen                // in  - const int in_len
                                , buf                     // out - const char *out_bufr
                                , 2016                    // in  - const int out_len
                                , eCnvCS                  // in  - enum cnv_charset charset
                                , p1stUnstranslatedChar   // out - char * & first_untranslated_char
                                , &outStrLenInBytes       // out - unsigned int *output_data_len_p
                                , convFlags               // in  - const int cnv_flags
                                , (Int32)TRUE               // in  - const int addNullAtEnd_flag
                                , (Int32)FALSE              // in  - const int allow_invalids
                                , &charCount              // out - unsigned int * translated_char_cnt_p
                                , pSubstitutionChar       // in  - const char *substitution_char
                                );
                          }
                        else // cvCharSet must be CharInfo::UTF8
                          {
                            cnvErrStatus =
                              UTF8ToLocale
                              ( cnv_version1            // in  - const enum cnv_version version
                                , pInStr                  // in  - const char *in_bufr
                                , inStrLen                // in  - const int in_len
                                , buf                     // out - const char *out_bufr
                                , 2016                    // in  - const int out_len
                                , eCnvCS                  // in  - enum cnv_charset charset
                                , p1stUnstranslatedChar   // out - char * & first_untranslated_char
                                , &outStrLenInBytes       // out - unsigned int *output_data_len_p
                                , (Int32)TRUE               // in  - const int addNullAtEnd_flag
                                , (Int32)FALSE              // in  - const int allow_invalids
                                , &charCount              // out - unsigned int * translated_char_cnt_p
                                , pSubstitutionChar       // in  - const char *substitution_char
                                );
                          }
                        switch (cnvErrStatus)
                          {
                          case 0: // success
                          case CNV_ERR_NOINPUT: // an empty input string will get this error code
                            {
                              ConstValue *pMBStrLitConstValue ;
                              // convert the string literal saved in cvDef (column default value)
                              // from UNICODE (e.g. UTF16) to the column character data type
                              if ( cdCharSet != CharInfo::UNICODE)
                                {
                                  NAString mbs2(buf, PARSERHEAP());  // note that buf is NULL terminated
                                  pMBStrLitConstValue =
                                    new(PARSERHEAP()) ConstValue ( mbs2
                                                                   , cdCharSet // use this for str lit prefix
                                                                   , CharInfo::DefaultCollation
                                                                   , CharInfo::COERCIBLE
                                                                   , PARSERHEAP()
                                                                   );
                                }
                              else
                                {
                                  NAWString mbs2((NAWchar*)buf, PARSERHEAP());  // note that buf is NULL terminated
                                  pMBStrLitConstValue = 
                                    new(PARSERHEAP()) ConstValue ( mbs2
                                                                   , cdCharSet // use this for str lit prefix
                                                                   , CharInfo::DefaultCollation
                                                                   , CharInfo::COERCIBLE
                                                                   , PARSERHEAP()
                                                                   );
                                }
                              delete pDefault_; // deallocate the old ConstValue object
                              cvDef = NULL;     // do not use cvDef anymore
                              pDefault_ = pMBStrLitConstValue;
                              pColDefault->setDefaultValueExpr(pDefault_);
                            }
                            break;
                          case CNV_ERR_INVALID_CHAR:
                            {
                              // 1401 ==  CAT_UNABLE_TO_CONVERT_COLUMN_DEFAULT_VALUE_TO_CHARSET
                              *SqlParser_Diags << DgSqlCode(-1401)
                                               << DgColumnName(ToAnsiIdentifier(getColumnName()))
                                               << DgString0(CharInfo::getCharSetName(cdCharSet));
                            }
                            break;
                          case CNV_ERR_BUFFER_OVERRUN: // output buffer not big enough
                          case CNV_ERR_INVALID_CS:
                          default:
                            CMPABORT_MSG("Parser internal logic error");
                            break;
                          } // switch
                      }
                    else if(!pColumnDataType->isCompatible(*cvTyp))
                      {
                        if (NOT isAnErrorAlreadyIssued)
                          {
                            *SqlParser_Diags << DgSqlCode(-1186)
                                             << DgColumnName(ToAnsiIdentifier(getColumnName()))
                                             << DgString0(pColumnDataType->getTypeSQLname(TRUE/*terse*/))
                                             << DgString1(cvTyp->getTypeSQLname(TRUE/*terse*/));
                            isAnErrorAlreadyIssued = TRUE;
                          }
                      }
                  } // column has character data type
                else
                  // if interval data type, the default value must have the same
                  // interval qualifier as the column.
                  if (NOT isAnErrorAlreadyIssued &&
                      (!pColumnDataType->isCompatible(*cvTyp) ||
                       (pColumnDataType->getTypeQualifier() == NA_INTERVAL_TYPE &&
                        pColumnDataType->getFSDatatype() != cvTyp->getFSDatatype())))
                    {
                      *SqlParser_Diags << DgSqlCode(-1186)
                                       << DgColumnName(ToAnsiIdentifier(getColumnName()))
                                       << DgString0(pColumnDataType->getTypeSQLname(TRUE/*terse*/))
                                       << DgString1(cvTyp->getTypeSQLname(TRUE/*terse*/));
                      isAnErrorAlreadyIssued = TRUE;
                    }
              }
          }
          break;
        case ElemDDLColDefault::COL_COMPUTED_DEFAULT:
          {
            defaultClauseStatus_ = DEFAULT_CLAUSE_SPEC;
            computedDefaultExpr_ = pColDefault->getComputedDefaultExpr();
          }
          break;
        default:
          CMPABORT_MSG("Parser internal logic error");
          break;
        }
    }

}
short
PhysSample::codeGen(Generator *generator) 
{  
  // Get a local handle on some of the generator objects.
  //
  CollHeap *wHeap = generator->wHeap();
  Space *space = generator->getSpace();
  MapTable *mapTable = generator->getMapTable();
  ExpGenerator *expGen = generator->getExpGenerator();

  // Allocate a new map table for this node. This must be done
  // before generating the code for my child so that this local
  // map table will be sandwiched between the map tables already
  // generated and the map tables generated by my offspring.
  //
  // Only the items available as output from this node will
  // be put in the local map table. Before exiting this function, all of
  // my offsprings map tables will be removed. Thus, none of the outputs 
  // from nodes below this node will be visible to nodes above it except 
  // those placed in the local map table and those that already exist in
  // my ancestors map tables. This is the standard mechanism used in the
  // generator for managing the access to item expressions.
  //
  MapTable *localMapTable = generator->appendAtEnd();

  // Since this operation doesn't modify the row on the way down the tree,
  // go ahead and generate the child subtree. Capture the given composite row
  // descriptor and the child's returned TDB and composite row descriptor.
  //
  ex_cri_desc * givenCriDesc = generator->getCriDesc(Generator::DOWN);
  child(0)->codeGen(generator);
  ComTdb *childTdb = (ComTdb*)generator->getGenObj();
  ex_cri_desc * childCriDesc = generator->getCriDesc(Generator::UP);
  ExplainTuple *childExplainTuple = generator->getExplainTuple();

  // Geneate the sampling expression.
  //
  ex_expr *balExpr = NULL;
  Int32 returnFactorOffset = 0;
  ValueId val;
  val = balanceExpr().init();
  if(balanceExpr().next(val))
    expGen->generateSamplingExpr(val, &balExpr, returnFactorOffset);

  // Alias the sampleColumns() so that they reference the underlying
  // expressions directly. This is done to avoid having to generate and
  // execute a project expression that simply moves the columns from
  // one tupp to another to reflect the application of the sampledCol
  // function.
  //
//   ValueId valId;
//   for(valId = sampledColumns().init();
//       sampledColumns().next(valId);
//       sampledColumns().advance(valId))
//     {
//       MapInfo *mapInfoChild = localMapTable->getMapInfoAsIs
// 	(valId.getItemExpr()->child(0)->castToItemExpr()->getValueId());
//       GenAssert(mapInfoChild, "Sample::codeGen -- no child map info.");
//       Attributes *attr = mapInfoChild->getAttr();
//       MapInfo *mapInfo = localMapTable->addMapInfoToThis(valId, attr);
//       mapInfo->codeGenerated();
//     }
// check if any of the columns inthe sampled columns are lob columns. If so, return an error.
  ValueId valId;
  for(valId = sampledColumns().init();
      sampledColumns().next(valId);
      sampledColumns().advance(valId))
    {
      const NAType &colType = valId.getType();
      if ((colType.getFSDatatype() == REC_BLOB) ||
	  (colType.getFSDatatype() == REC_CLOB))
	{
	   *CmpCommon::diags() << DgSqlCode(-4322);
	   GenExit();
	}
    }
  // Now, remove all attributes from the map table except the 
  // the stuff in the local map table -- the result of this node.
  //
//  localMapTable->removeAll();

  // Generate the expression to evaluate predicate on the sampled row.
  //
  ex_expr *postPred = 0;
  if (!selectionPred().isEmpty()) {
    ItemExpr * newPredTree 
      = selectionPred().rebuildExprTree(ITM_AND,TRUE,TRUE);

    expGen->generateExpr(newPredTree->getValueId(), ex_expr::exp_SCAN_PRED,
			 &postPred);
  }

  // Construct the Sample TDB.
  //
  ComTdbSample *sampleTdb
    = new(space) ComTdbSample(NULL,
			      balExpr,
			      returnFactorOffset,
			      postPred,
			      childTdb,
			      givenCriDesc,
			      childCriDesc,
			      (queue_index)getDefault(GEN_SAMPLE_SIZE_DOWN),
			      (queue_index)getDefault(GEN_SAMPLE_SIZE_UP));
  generator->initTdbFields(sampleTdb);

  if(!generator->explainDisabled()) {
    generator->
      setExplainTuple(addExplainInfo(sampleTdb,
                                     childExplainTuple,
                                     0,
                                     generator));
  }

  generator->setCriDesc(givenCriDesc, Generator::DOWN);
  generator->setCriDesc(childCriDesc, Generator::UP);
  generator->setGenObj(this, sampleTdb);

  return 0;
}
Beispiel #15
0
NABoolean CmpSqlSession::validateVolatileQualifiedName(QualifiedName &inName)
{
  if (NOT Get_SqlParser_Flags(ALLOW_VOLATILE_SCHEMA_IN_TABLE_NAME))
    {
      if (NOT inName.getCatalogName().isNull())
	{
	  // cannot be a 3-part name
	  *CmpCommon::diags() << DgSqlCode(-4192);
	  return FALSE;
	}
      
      if (NOT inName.getSchemaName().isNull())
	{
	  // validate that the schemaName part is the currentUserName
	  if (inName.getSchemaName() != externalUserName_)
	    {
	      *CmpCommon::diags() << DgSqlCode(-4191) <<
		DgString0(inName.getSchemaName()) <<
		DgString1(externalUserName_);
	      return FALSE;
	    }
	}
    }
  else
    {
      // Volatile schema name is allowed.
      // Make sure that it is a valid volatile 3 part name.
      if ((NOT inName.getCatalogName().isNull()) &&
	  (NOT inName.getSchemaName().isNull()))
	{
	  // move to a temp to upcase
	  ComSchemaName csn(inName.getSchemaName());
	  
	  ULng32 len = 
	    MINOF(strlen(csn.getSchemaNamePartAsAnsiString().data()),
		  strlen(COM_VOLATILE_SCHEMA_PREFIX));
	  NAString upSch(csn.getSchemaNamePartAsAnsiString().data());
	  upSch.toUpper();
	  if ((len < strlen(COM_VOLATILE_SCHEMA_PREFIX)) ||
	      (strncmp(upSch.data(), COM_VOLATILE_SCHEMA_PREFIX, len) != 0))
	    {
	      *CmpCommon::diags() << DgSqlCode(-4192);
	      return FALSE;
	    }
	}
      else if (NOT inName.getSchemaName().isNull())
	{
	  // 2 part name
	  // validate that the schemaName part is the currentUserName
	  if (inName.getSchemaName() != externalUserName_)
	    {
	      *CmpCommon::diags() << DgSqlCode(-4191) <<
		DgString0(inName.getSchemaName()) <<
		DgString1(externalUserName_);
	      return FALSE;
	    }
	}
    }

  return TRUE;
}
void CmpSeabaseDDL::dropSeabaseLibrary(StmtDDLDropLibrary * dropLibraryNode,
                                       NAString &currCatName, 
                                       NAString &currSchName)
{
  Lng32 cliRC = 0;
  Lng32 retcode = 0;

  const NAString &objName = dropLibraryNode->getLibraryName();

  ComObjectName libraryName(objName);
  ComAnsiNamePart currCatAnsiName(currCatName);
  ComAnsiNamePart currSchAnsiName(currSchName);
  libraryName.applyDefaults(currCatAnsiName, currSchAnsiName);

  const NAString catalogNamePart = libraryName.
    getCatalogNamePartAsAnsiString();
  const NAString schemaNamePart = libraryName.
    getSchemaNamePartAsAnsiString(TRUE);
  const NAString objectNamePart = libraryName.
    getObjectNamePartAsAnsiString(TRUE);
  const NAString extLibraryName = libraryName.getExternalName(TRUE);

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

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

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

  if (retcode == 0) // does not exist
    {
      *CmpCommon::diags() << DgSqlCode(-1389)
			  << DgString0(extLibraryName);
      deallocEHI(ehi); 
      processReturn();
      return;
    }

  Int32 objectOwnerID = 0;
  Int32 schemaOwnerID = 0;
  Int64 objectFlags = 0;
  Int64 objUID = getObjectInfo(&cliInterface,
			      catalogNamePart.data(), schemaNamePart.data(), 
			      objectNamePart.data(), COM_LIBRARY_OBJECT,
                              objectOwnerID,schemaOwnerID,objectFlags);
  if (objUID < 0 || objectOwnerID == 0 || schemaOwnerID == 0)
    {
      deallocEHI(ehi); 
      processReturn();
      return;
    }

  if (!isDDLOperationAuthorized(SQLOperation::DROP_LIBRARY,
                                objectOwnerID,
                                schemaOwnerID))
  {
     *CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
     processReturn ();
     return;
  }
  
  Queue * usingRoutinesQueue = NULL;
  cliRC = getUsingRoutines(&cliInterface, objUID, usingRoutinesQueue);
  if (cliRC < 0)
    {
      deallocEHI(ehi); 
      processReturn();
      return;
    }
  // If RESTRICT and the library is being used, return an error
  if (cliRC != 100 && dropLibraryNode->getDropBehavior() == COM_RESTRICT_DROP_BEHAVIOR) 
    {
      *CmpCommon::diags() << DgSqlCode(-CAT_DEPENDENT_ROUTINES_EXIST);

      deallocEHI(ehi); 
      processReturn();
      return;
    }
    
  for (size_t i = 0; i < usingRoutinesQueue->numEntries(); i++)
  { 
     usingRoutinesQueue->position();
     OutputInfo * rou = (OutputInfo*)usingRoutinesQueue->getNext(); 
     
     char * routineName = rou->get(0);
     ComObjectType objectType = PrivMgr::ObjectLitToEnum(rou->get(1));

     if (dropSeabaseObject(ehi, routineName,
                           currCatName, currSchName, objectType,
                           TRUE, FALSE))
     {
       deallocEHI(ehi); 
       processReturn();
       return;
     }
   }
 
  // can get a slight perf. gain if we pass in objUID
  if (dropSeabaseObject(ehi, objName,
                        currCatName, currSchName, COM_LIBRARY_OBJECT,
                        TRUE, FALSE))
    {
      deallocEHI(ehi); 
      processReturn();
      return;
    }

  deallocEHI(ehi);      
  processReturn();
  return;
}
ExWorkProcRetcode ExCancelTcb::work()
{

  ExMasterStmtGlobals *masterGlobals = 
     getGlobals()->castToExExeStmtGlobals()->castToExMasterStmtGlobals();

  CliGlobals *cliGlobals = masterGlobals->getCliGlobals();

  while ((qparent_.down->isEmpty() == FALSE) && 
         (qparent_.up->isFull() == FALSE))
  {
    ex_queue_entry *pentry_down = qparent_.down->getHeadEntry();
  
    switch (step_)
    {
      case NOT_STARTED:
      {
        if (pentry_down->downState.request == ex_queue::GET_NOMORE)
          step_ = DONE;
        else
        {
          retryCount_ = 0;
          // Priv checking is done during compilation. To support 
          // REVOKE, prevent a prepared CANCEL/SUSPEND/ACTIVATE
          // that was compiled more than 1 second ago from executing 
          // by raising the 8734 error to force an AQR. 
          Int64 microSecondsSinceCompile = NA_JulianTimestamp() - 
              masterGlobals->getStatement()->getCompileEndTime();

          if (microSecondsSinceCompile > 1000*1000)
          {

            ComDiagsArea *diagsArea =
              ComDiagsArea::allocate(getGlobals()->getDefaultHeap());
            *diagsArea << DgSqlCode(-CLI_INVALID_QUERY_PRIVS);
            reportError(diagsArea);
            step_ = DONE;
            break;
          }
          
          // Figure out which MXSSMP broker to use.
          if (cancelTdb().getAction() == ComTdbCancel::CancelByPname)
          {
            int nid = -1;
            int rc = msg_mon_get_process_info(cancelTdb().getCancelPname(),
                                &nid, &pid_);
            switch (rc)
            {
              case XZFIL_ERR_OK:
                cpu_ = (short) nid;
                break;
              case XZFIL_ERR_NOTFOUND:
              case XZFIL_ERR_BADNAME:
              case XZFIL_ERR_NOSUCHDEV:
                {
                  ComDiagsArea *diagsArea =
                    ComDiagsArea::allocate(getGlobals()->getDefaultHeap());

                  *diagsArea << DgSqlCode(-EXE_CANCEL_PROCESS_NOT_FOUND);
                  *diagsArea << DgString0(cancelTdb().getCancelPname());
                  reportError(diagsArea);

                  step_ = DONE;
                  break;
                }
              default:
                {
                  char buf[200];
                  str_sprintf(buf, "Unexpected error %d returned from "
                                   "msg_mon_get_process_info", rc);
                  ex_assert(0, buf);
                }
            }
            if (step_ != NOT_STARTED)
              break;
          }
          else if  (cancelTdb().getAction() == ComTdbCancel::CancelByNidPid)
          {
            cpu_ = (short) cancelTdb().getCancelNid();
            pid_ = cancelTdb().getCancelPid();

            // check that process exists, if not report error.
            char processName[MS_MON_MAX_PROCESS_NAME];
            int rc = msg_mon_get_process_name(cpu_, pid_, processName);
            if (XZFIL_ERR_OK == rc)
              ; // good. nid & pid are valid.
            else
            {
              if ((XZFIL_ERR_NOTFOUND  != rc) &&
                  (XZFIL_ERR_BADNAME   != rc) &&
                  (XZFIL_ERR_NOSUCHDEV != rc))
              {
                // Log rc in case it needs investigation later.
               char buf[200];
               str_sprintf(buf, "Unexpected error %d returned from "
                                "msg_mon_get_process_name", rc);
               SQLMXLoggingArea::logExecRtInfo(__FILE__, __LINE__,
                                               buf, 0);
              }
              char nid_pid_str[32];
              str_sprintf(nid_pid_str, "%d, %d", cpu_, pid_);
              ComDiagsArea *diagsArea =
                    ComDiagsArea::allocate(getGlobals()->getDefaultHeap());

              *diagsArea << DgSqlCode(-EXE_CANCEL_PROCESS_NOT_FOUND);
              *diagsArea << DgString0(nid_pid_str);
              reportError(diagsArea);

              step_ = DONE;
              break;
            }
          }
          else
          {
            char * qid = cancelTdb().qid_;
            Lng32 qid_len = str_len(qid);

            // This static method is defined in SqlStats.cpp.  It side-effects
            // the nodeName and cpu_ according to the input qid.
            if (getMasterCpu(
                  qid, qid_len, nodeName_, sizeof(nodeName_) - 1, cpu_) == -1)
            {
              ComDiagsArea *diagsArea =
                ComDiagsArea::allocate(getGlobals()->getDefaultHeap());

              *diagsArea << DgSqlCode(-EXE_RTS_INVALID_QID);

              reportError(diagsArea);

              step_ = DONE;
              break;
            }
          }

          // Testpoints for hard to reproduce problems:
          bool fakeError8028 = false;
          fakeError8028 = (getenv("HP_FAKE_ERROR_8028") != NULL);
          if ((cliGlobals->getCbServerClass() == NULL) || fakeError8028)
          {
            ComDiagsArea *diagsArea = 
              ComDiagsArea::allocate(getGlobals()->getDefaultHeap());

            *diagsArea << DgSqlCode(-EXE_CANCEL_PROCESS_NOT_FOUND);
            *diagsArea << DgString0("$ZSM000");

            reportError(diagsArea);

            step_ = DONE;
            break;
          }

          ComDiagsArea *diagsArea = NULL;
          bool fakeError2024 = false;
          fakeError2024 = (getenv("HP_FAKE_ERROR_2024") != NULL);
        
          if (fakeError2024)
          {
            cbServer_ = NULL;
            diagsArea =
                  ComDiagsArea::allocate(getGlobals()->getDefaultHeap());
            if (getenv("HP_FAKE_ERROR_8142"))
            {
               *diagsArea << DgSqlCode(-8142);
               *diagsArea << DgString0(__FILE__);
               *diagsArea << DgString1("cbServer_ is NULL");
            }
            else
               *diagsArea << DgSqlCode(-2024);
          }
          else
            cbServer_ = cliGlobals->getCbServerClass()->allocateServerProcess(
                      &diagsArea, 
                      cliGlobals->getEnvironment()->getHeap(),
                      nodeName_,
                      cpu_,
                      IPC_PRIORITY_DONT_CARE,
                      FALSE,  // usesTransactions 
                      TRUE,   // waitedCreation
                      2       // maxNowaitRequests -- cancel+(1 extra).
                      );


          if (cbServer_ == NULL || cbServer_->getControlConnection() == NULL)
          {
            ex_assert(diagsArea != NULL, 
                      "allocateServerProcess failed, but no diags");

            // look for SQLCode 2024 
            // "*** ERROR[2024] Server Process $0~string0 
            // is not running or could not be created. Operating System 
            // Error $1~int0 was returned."
            // Remap to cancel-specfic error 8028.
            if (diagsArea->contains(-2024)  &&
                cancelTdb().actionIsCancel())
            {
              diagsArea->deleteError(diagsArea->returnIndex(-2024));
              reportError(diagsArea, true, EXE_CANCEL_PROCESS_NOT_FOUND, 
                          nodeName_, cpu_);
            }
            else
              reportError(diagsArea);

            step_ = DONE;
            break;
          }

          // the reportError method was not called -- see break above.
          if (diagsArea != NULL)
            diagsArea->decrRefCount();

          //Create the stream on the IpcHeap, since we don't dispose 
          // of it immediately.  We just add it to the list of completed 
          // messages in the IpcEnv, and it is disposed of later.

          cancelStream_  = new (cliGlobals->getIpcHeap())
                CancelMsgStream(cliGlobals->getEnvironment(), this);

          cancelStream_->addRecipient(cbServer_->getControlConnection());

        }

        step_ = SEND_MESSAGE;

        break;
      }  // end case NOT_STARTED

#pragma warning (disable : 4291)

      case SEND_MESSAGE:
      {
        RtsHandle rtsHandle = (RtsHandle) this;

        if (cancelTdb().actionIsCancel())
        {
          Int64 cancelStartTime = JULIANTIMESTAMP();

          Lng32 firstEscalationInterval = cliGlobals->currContext()->
                    getSessionDefaults()->getCancelEscalationInterval();

          Lng32 secondEscalationInterval = cliGlobals->currContext()->
                    getSessionDefaults()->getCancelEscalationMxosrvrInterval();

          NABoolean cancelEscalationSaveabend = cliGlobals->currContext()->
                    getSessionDefaults()->getCancelEscalationSaveabend();

          bool cancelLogging = (TRUE == cliGlobals->currContext()->
                    getSessionDefaults()->getCancelLogging());

          CancelQueryRequest *cancelMsg = new (cliGlobals->getIpcHeap()) 
            CancelQueryRequest(rtsHandle, cliGlobals->getIpcHeap(), 
                      cancelStartTime,
                      firstEscalationInterval,
                      secondEscalationInterval,
                      cancelEscalationSaveabend,
                      cancelTdb().getCommentText(),
                      str_len(cancelTdb().getCommentText()),
                      cancelLogging,
                      cancelTdb().action_ != ComTdbCancel::CancelByQid,
                      pid_,
                      cancelTdb().getCancelPidBlockThreshold());

#pragma warning (default : 4291)

          *cancelStream_ << *cancelMsg;

          cancelMsg->decrRefCount();
        }
        else if (ComTdbCancel::Suspend == cancelTdb().action_)
        {

          bool suspendLogging = (TRUE == cliGlobals->currContext()->
                    getSessionDefaults()->getSuspendLogging());

#pragma warning (disable : 4291)
          SuspendQueryRequest * suspendMsg = new (cliGlobals->getIpcHeap()) 
            SuspendQueryRequest(rtsHandle, cliGlobals->getIpcHeap(),
                                ComTdbCancel::Force ==
                                cancelTdb().forced_,
                                suspendLogging);
#pragma warning (default : 4291)

          *cancelStream_ << *suspendMsg;

          suspendMsg->decrRefCount();
        }
        else
        {
          ex_assert(
            ComTdbCancel::Activate == cancelTdb().action_,
            "invalid action for ExCancelTcb");

          bool suspendLogging = (TRUE == cliGlobals->currContext()->
                    getSessionDefaults()->getSuspendLogging());

#pragma warning (disable : 4291)
          ActivateQueryRequest * activateMsg = new (cliGlobals->getIpcHeap()) 
            ActivateQueryRequest(rtsHandle, cliGlobals->getIpcHeap(),
                                 suspendLogging);
#pragma warning (default : 4291)

          *cancelStream_ << *activateMsg;

          activateMsg->decrRefCount();
        }

        if ((cancelTdb().getAction() != ComTdbCancel::CancelByPname) &&
            (cancelTdb().getAction() != ComTdbCancel::CancelByNidPid))
        {
          char * qid = cancelTdb().qid_;
          Lng32 qid_len = str_len(qid);

#pragma warning (disable : 4291)
          RtsQueryId *rtsQueryId = new (cliGlobals->getIpcHeap())
                           RtsQueryId( cliGlobals->getIpcHeap(), qid, qid_len);
#pragma warning (default : 4291)

          *cancelStream_ << *rtsQueryId;
          rtsQueryId->decrRefCount();
        }

        // send a no-wait request to the cancel broker.
        cancelStream_->send(FALSE);

        step_ = GET_REPLY;    
        // Come back when I/O completes.
        return WORK_OK; 

        break;
      }  // end case SEND_MESSAGE

      case GET_REPLY:
      {

        // Handle general IPC error.
        bool fakeError201 = false;
        fakeError201 = (getenv("HP_FAKE_ERROR_201") != NULL);
        if ((cbServer_->getControlConnection()->getErrorInfo() != 0) ||
            fakeError201)
        {
          ComDiagsArea *diagsArea = 
            ComDiagsArea::allocate(getGlobals()->getDefaultHeap());

          cbServer_->getControlConnection()->
              populateDiagsArea( diagsArea, getGlobals()->getDefaultHeap());

          if (fakeError201)
          {
            *diagsArea << DgSqlCode(-2034) << DgInt0(201)
                       << DgString0("I say") << DgString1("control broker");
          }

          if (diagsArea->contains(-8921))
          {
            // Should not get timeout error 8921. Get a core-file
            // of the SSMP and this process too so that this can be
            // debugged.
            cbServer_->getControlConnection()->
              dumpAndStopOtherEnd(true, false);
            genLinuxCorefile("Unexpected timeout error");
          }

          reportError(diagsArea);

          step_ = DONE;
          break;
        }

        // See if stream has the reply yet.
        if (!cancelStream_->moreObjects())
          return WORK_OK; 

#pragma warning (disable : 4291)

        ControlQueryReply *reply = new (cliGlobals->getIpcHeap()) 
              ControlQueryReply(INVALID_RTS_HANDLE, cliGlobals->getIpcHeap());

#pragma warning (default : 4291)

        *cancelStream_ >> *reply;

        if (reply->didAttemptControl())
        {
          // yeaah!
          cancelStream_->clearAllObjects();
        }
        else
        {
          if (cancelStream_->moreObjects() &&
              cancelStream_->getNextObjType() == IPC_SQL_DIAG_AREA)
          {
            ComDiagsArea *diagsArea = 
              ComDiagsArea::allocate(getGlobals()->getDefaultHeap());

            *cancelStream_ >> *diagsArea;
            cancelStream_->clearAllObjects();

            if ( retryQidNotActive_ &&
                (diagsArea->mainSQLCODE() == -EXE_SUSPEND_QID_NOT_ACTIVE) &&
                (++retryCount_ <= 60))
            {
              SQLMXLoggingArea::logExecRtInfo(__FILE__, __LINE__, 
                                             "Retrying error 8672.", 0);
              DELAY(500);
              diagsArea->decrRefCount();
              step_ = SEND_MESSAGE;
              break;
            }

            reportError(diagsArea);
          }
          else 
            ex_assert(0, "Control failed, but no diagnostics.");
        }

        step_ = DONE;
        break;
      }
      case DONE: 
      {
        if (cancelStream_)
        {
          cancelStream_->addToCompletedList();
          cancelStream_ = NULL;
        }
        if (cbServer_)
        {
          cbServer_->release();
          cbServer_ = NULL;
        }

        ex_queue_entry * up_entry = qparent_.up->getTailEntry();
        up_entry->copyAtp(pentry_down);
        up_entry->upState.parentIndex = pentry_down->downState.parentIndex;
        up_entry->upState.downIndex = qparent_.down->getHeadIndex();     
        up_entry->upState.setMatchNo(1);
        up_entry->upState.status = ex_queue::Q_NO_DATA;
        qparent_.up->insert();

        qparent_.down->removeHead();

        step_ = NOT_STARTED;
        break;
      }
      default:
        ex_assert( 0, "Unknown step_.");
    }
void CmpSeabaseDDL::createSeabaseRoutine(
				      StmtDDLCreateRoutine * createRoutineNode,
				      NAString &currCatName, 
                                      NAString &currSchName)
{
  Lng32 retcode = 0;
 
  ComObjectName routineName(createRoutineNode->getRoutineName());
  ComAnsiNamePart currCatAnsiName(currCatName);
  ComAnsiNamePart currSchAnsiName(currSchName);
  routineName.applyDefaults(currCatAnsiName, currSchAnsiName);
  const NAString catalogNamePart = 
    routineName.getCatalogNamePartAsAnsiString();
  const NAString schemaNamePart = 
    routineName.getSchemaNamePartAsAnsiString(TRUE);
  const NAString objectNamePart = 
    routineName.getObjectNamePartAsAnsiString(TRUE);
  const NAString extRoutineName = routineName.getExternalName(TRUE);
  ComRoutineType rType          = createRoutineNode->getRoutineType();
  ComRoutineLanguage language   = createRoutineNode->getLanguageType();
  ComRoutineParamStyle ddlStyle = createRoutineNode->getParamStyle();
  ComRoutineParamStyle style    = ddlStyle;
  NABoolean isJava              = (language == COM_LANGUAGE_JAVA);

  // Check to see if user has the authority to create the routine
  ExeCliInterface cliInterface(STMTHEAP, NULL, NULL, 
    CmpCommon::context()->sqlSession()->getParentQid());
  Int32 objectOwnerID = SUPER_USER;
  Int32 schemaOwnerID = SUPER_USER;
  ComSchemaClass schemaClass;

  retcode = verifyDDLCreateOperationAuthorized(&cliInterface,
                                               SQLOperation::CREATE_ROUTINE,
                                               catalogNamePart,
                                               schemaNamePart,
                                               schemaClass,
                                               objectOwnerID,
                                               schemaOwnerID);
  if (retcode != 0)
  {
     handleDDLCreateAuthorizationError(retcode,catalogNamePart,schemaNamePart);
     return;
  }
  
  ExpHbaseInterface * ehi = NULL;

  ehi = allocEHI();
  if (ehi == NULL)
    {
      processReturn();
      return;
    }
  
  retcode = existsInSeabaseMDTable(&cliInterface, 
				   catalogNamePart, schemaNamePart, 
                                   objectNamePart, COM_USER_DEFINED_ROUTINE_OBJECT, 
                                   TRUE, FALSE);
  if (retcode < 0)
    {
      deallocEHI(ehi); 
      processReturn();
      return;
    }

  if (retcode == 1) // already exists
    {
      *CmpCommon::diags() << DgSqlCode(-1390)
			  << DgString0(extRoutineName);
      deallocEHI(ehi); 
      processReturn();
      return;
    }

  
  ComObjectName libName(createRoutineNode->
                        getLibraryName().getQualifiedNameAsAnsiString());
  libName.applyDefaults(currCatAnsiName, currSchAnsiName);	
  NAString libCatNamePart = libName.getCatalogNamePartAsAnsiString();
  NAString libSchNamePart = libName.getSchemaNamePartAsAnsiString(TRUE);
  NAString libObjNamePart = libName.getObjectNamePartAsAnsiString(TRUE);
  const NAString extLibraryName = libName.getExternalName(TRUE);
  char externalPath[512] ;
  Lng32 cliRC = 0;
	
  // this call needs to change
  Int64 libUID = getObjectUID(&cliInterface, 
                              libCatNamePart, 
                              libSchNamePart, 
                              libObjNamePart,
                              COM_LIBRARY_OBJECT_LIT);

  if (libUID < 0)
    {
      processReturn();    
      return;
    }

  if (libUID == 0) // does not exist
    {
      *CmpCommon::diags() << DgSqlCode(-1361)
			  << DgString0(extLibraryName);
      deallocEHI(ehi); 
      processReturn();
      return;
    }

  // read the library path name from the LIBRARIES metadata table

  char * buf = new(STMTHEAP) char[200];
  str_sprintf(buf, "select library_filename from %s.\"%s\".%s"
              " where library_uid = %Ld for read uncommitted access",
              getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_LIBRARIES, libUID);

  cliRC = cliInterface.fetchRowsPrologue(buf, TRUE/*no exec*/);
  if (cliRC < 0)
    {
      cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
      deallocEHI(ehi); 
      processReturn();
      return;
    }

  cliRC = cliInterface.clearExecFetchClose(NULL, 0);
  if (cliRC < 0)
    {
      cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
      deallocEHI(ehi); 
      processReturn();
      return;
    }
  if (cliRC == 100) // did not find the row
    {
      *CmpCommon::diags() << DgSqlCode(-1231)
                          << DgString0(extRoutineName);
      deallocEHI(ehi); 
      processReturn();
      return;
    }

  char * ptr = NULL;
  Lng32 len = 0;
  cliInterface.getPtrAndLen(1, ptr, len);
  str_cpy_all(externalPath, ptr, len);
  externalPath[len] = '\0'; 

  // determine language and parameter styles based on the library
  // type, unless already specified
  if (!createRoutineNode->isLanguageTypeSpecified())
    {
      NAString extPath(externalPath);
      size_t lastDot = extPath.last('.');
      NAString libSuffix;

      if (lastDot != NA_NPOS)
        libSuffix = extPath(lastDot,extPath.length()-lastDot);

      libSuffix.toUpper();

      if (libSuffix == ".JAR")
        {
          isJava = TRUE;
          language = COM_LANGUAGE_JAVA;
        }
      else if (libSuffix == ".SO" ||
               libSuffix == ".DLL")
        {
          // a known C/C++ library, set
          // language and parameter style below
        }
      else
        {
          // language not specified and library name
          // is inconclusive, issue an error
          *CmpCommon::diags() << DgSqlCode( -3284 )
                              << DgString0( externalPath );
          processReturn();
        }
    }

  // set parameter style and also language, if not already
  // specified, based on routine type and type of library
  if (isJava)
    {
      // library is a jar file

      if (rType == COM_PROCEDURE_TYPE)
        // Java stored procedures use the older Java style
        style = COM_STYLE_JAVA_CALL;
      else
        // Java UDFs use the newer Java object style
        style = COM_STYLE_JAVA_OBJ;
    }
  else
    {
      // assume the library is a DLL with C or C++ code
      if (rType == COM_TABLE_UDF_TYPE &&
          (language == COM_LANGUAGE_CPP ||
           !createRoutineNode->isLanguageTypeSpecified()))
        {
          // Table UDFs (TMUDFs) default to the C++ interface
          language = COM_LANGUAGE_CPP;
          style    = COM_STYLE_CPP_OBJ;
        }
      else if (rType == COM_SCALAR_UDF_TYPE &&
               (language == COM_LANGUAGE_C ||
                !createRoutineNode->isLanguageTypeSpecified()))
        {
          // scalar UDFs default to C and SQL parameter style
          language = COM_LANGUAGE_C;
          style    = COM_STYLE_SQL;
        }
      else
        {
          // some invalid combination of routine type, language and
          // library type
          *CmpCommon::diags() << DgSqlCode(-3286);
          processReturn();
          return;
        }
    } // C/C++ DLL

  if (createRoutineNode->isParamStyleSpecified() &&
      ddlStyle != style)
    {
      // An unsupported PARAMETER STYLE was specified
      *CmpCommon::diags() << DgSqlCode(-3280);
      processReturn();
      return;
    }

  NAString externalName;
  if (language == COM_LANGUAGE_JAVA &&
      style == COM_STYLE_JAVA_CALL)
    {
      // the external name is a Java method signature
      externalName = createRoutineNode->getJavaClassName();
      externalName += "." ;
      externalName += createRoutineNode->getJavaMethodName();
    }
  else
    // the external name is a C/C++ entry point or a
    // Java class name
    externalName = createRoutineNode->getExternalName();

  // Verify that current user has authority to create the routine
  // User must be DB__ROOT or have privileges
  if (isAuthorizationEnabled() && !ComUser::isRootUserID())
    {

      // For now, go get privileges directly.  If we ever cache routines, then
      // make sure privileges are stored in the cache.
      NAString privMgrMDLoc;
      CONCAT_CATSCH(privMgrMDLoc, getSystemCatalog(), SEABASE_PRIVMGR_SCHEMA);
      PrivMgrCommands privInterface(privMgrMDLoc.data(), CmpCommon::diags());
      PrivMgrUserPrivs privs;
      PrivStatus retcode = privInterface.getPrivileges(libUID, COM_LIBRARY_OBJECT, 
                                                       ComUser::getCurrentUser(), privs);
      if (retcode != STATUS_GOOD)
        {
          if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
            SEABASEDDL_INTERNAL_ERROR("checking routine privilege");
          processReturn();
          return;
        }

      // Requester must have USAGE privilege on the library
      NABoolean hasPriv = TRUE;
      if ( !privs.hasUsagePriv() )
        {
          *CmpCommon::diags() << DgSqlCode( -4481 )
                              << DgString0( "USAGE" )
                              << DgString1( extLibraryName.data());
          processReturn();
          return;
        }
    }

  ElemDDLParamDefArray &routineParamArray =
        createRoutineNode->getParamArray();
  Lng32 numParams = routineParamArray.entries();

  if ((createRoutineNode->getRoutineType() == COM_SCALAR_UDF_TYPE) &&
      (numParams > 32))
    {
      *CmpCommon::diags() << DgSqlCode( -1550 )
                          << DgString0( extRoutineName )
                          << DgInt0( numParams );
      deallocEHI(ehi); 
      processReturn();
      return;
    }
#define MAX_SIGNATURE_LENGTH 8193
  // Allocate buffer for generated signature
  char sigBuf[MAX_SIGNATURE_LENGTH];
  sigBuf[0] = '\0';

  if (style == COM_STYLE_JAVA_CALL) 
  {
     // validate routine for Java call based on signature
     Lng32 numJavaParam = 0;
     ComFSDataType *paramType = new ComFSDataType[numParams];
     ComUInt32     *subType   = new ComUInt32    [numParams];
     ComColumnDirection *direction = new ComColumnDirection[numParams];
     NAType *genericType;

     // Gather the param attributes for LM from the paramDefArray previously
     // populated and from the routineparamList generated from paramDefArray.

     for (CollIndex i = 0; (Int32)i < numParams; i++)
     {
       paramType[i] = (ComFSDataType)routineParamArray[i]->getParamDataType()->getFSDatatype();
       subType[i] = 0;  // default
       // Set subType for special cases detected by LM
       switch ( paramType[i] )
       {
         case COM_SIGNED_BIN16_FSDT :
         case COM_SIGNED_BIN32_FSDT :
         case COM_SIGNED_BIN64_FSDT :
         case COM_UNSIGNED_BIN16_FSDT :
         case COM_UNSIGNED_BIN32_FSDT :
         case COM_UNSIGNED_BPINT_FSDT :
         {
           genericType = routineParamArray[i]->getParamDataType() ;
           if (genericType->getTypeName() == LiteralNumeric)
             subType[i] = genericType->getPrecision();
           else
             subType[i] = 0 ;

           break;
         }

         case COM_DATETIME_FSDT :
         {
           genericType = routineParamArray[i]->getParamDataType() ;
           DatetimeType & datetimeType = (DatetimeType &) *genericType;
            if (datetimeType.getSimpleTypeName() EQU "DATE")
              subType[i] = 1 ;
            else if (datetimeType.getSimpleTypeName() EQU "TIME")
              subType[i] = 2;
            else if (datetimeType.getSimpleTypeName() EQU "TIMESTAMP")
              subType[i] = 3;
         }
       } // end switch paramType[i]

       direction[i] = (ComColumnDirection) routineParamArray[i]->getParamDirection();
     }
    
     // If the syntax specified a signature, pass that to LanguageManager.
     NAString specifiedSig( createRoutineNode->getJavaSignature() );
     char* optionalSig;
     if ( specifiedSig.length() == 0 )
       optionalSig = NULL;
     else
       optionalSig = (char *)specifiedSig.data();
     
     ComBoolean isJavaMain =
       ((str_cmp_ne(createRoutineNode->getJavaMethodName(), "main") == 0) ? TRUE : FALSE);

     LmResult createSigResult;
     LmJavaSignature *lmSignature =  new (STMTHEAP) LmJavaSignature(NULL,
                                                                    STMTHEAP);
     createSigResult = lmSignature->createSig(paramType, subType, direction,
                                              numParams, COM_UNKNOWN_FSDT, 0,
                                              createRoutineNode->getMaxResults(), optionalSig, isJavaMain, sigBuf,
                                              MAX_SIGNATURE_LENGTH,
                                              CmpCommon::diags());
     NADELETE(lmSignature, LmJavaSignature, STMTHEAP);
     delete [] paramType;
     delete [] subType;
     delete [] direction;

     // Lm returned error. Lm fills diags area, so no need to worry about diags.
     if (createSigResult == LM_ERR)
     {
       *CmpCommon::diags() << DgSqlCode(-1231)
			  << DgString0(extRoutineName);
       deallocEHI(ehi); 
       processReturn();
       return;
     }

     numJavaParam = (isJavaMain ? 1 : numParams);

     if (validateRoutine(&cliInterface, 
                         createRoutineNode->getJavaClassName(),
                         createRoutineNode->getJavaMethodName(),
                         externalPath,
                         sigBuf,
                         numJavaParam,
                         createRoutineNode->getMaxResults(),
                         optionalSig))
     {
       *CmpCommon::diags() << DgSqlCode(-1231)
                           << DgString0(extRoutineName);
       deallocEHI(ehi); 
       processReturn();
       return;
     }
  }
  else if (style == COM_STYLE_JAVA_OBJ ||
           style == COM_STYLE_CPP_OBJ)
  {
    // validate existence of the C++ or Java class in the library
    Int32 routineHandle = NullCliRoutineHandle;
    NAString externalPrefix(externalPath);
    NAString externalNameForValidation(externalName);
    NAString containerName;

    if (language == COM_LANGUAGE_C || language == COM_LANGUAGE_CPP)
      {
        // separate the actual DLL name from the prefix
        char separator = '/';
        size_t separatorPos = externalPrefix.last(separator);

        if (separatorPos != NA_NPOS)
          {
            containerName = externalPrefix(separatorPos+1,
                                           externalPrefix.length()-separatorPos-1);
            externalPrefix.remove(separatorPos,
                                  externalPrefix.length()-separatorPos);
          }
        else
          {
            // assume the entire string is a local name
            containerName = externalPrefix;
            externalPrefix = ".";
          }
      }
    else
      {
        // For Java, the way the language manager works is that the
        // external path is the fully qualified name of the jar and
        // the container is the class name (external name).  We load
        // the container (the class) by searching in the path (the
        // jar). The external name is the method name, which in this
        // case is the constructor of the class, <init>.

        // leave externalPrevix unchanged, fully qualified jar file
        containerName = externalName;
        externalNameForValidation = "<init>";
      }

    // use a CLI call to validate that the library contains the routine
    if (cliInterface.getRoutine(
             NULL, // No InvocationInfo specified in this step
             0,
             NULL,
             0,
             (Int32) language,
             (Int32) style,
             externalNameForValidation.data(),
             containerName.data(),
             externalPrefix.data(),
             extLibraryName.data(),
             &routineHandle,
             CmpCommon::diags()) != LME_ROUTINE_VALIDATED)
      {
        if (routineHandle != NullCliRoutineHandle)
          cliInterface.putRoutine(routineHandle,
                                  CmpCommon::diags());

        CMPASSERT(CmpCommon::diags()->mainSQLCODE() < 0);
        processReturn();
        return;
      }

    cliInterface.putRoutine(routineHandle,
                            CmpCommon::diags());
  }

  ComTdbVirtTableColumnInfo * colInfoArray = (ComTdbVirtTableColumnInfo*)
    new(STMTHEAP) ComTdbVirtTableColumnInfo[numParams];

  if (buildColInfoArray(&routineParamArray, colInfoArray))
    {
      processReturn();
      return;
    }

  ComTdbVirtTableTableInfo * tableInfo = new(STMTHEAP) ComTdbVirtTableTableInfo[1];
  tableInfo->tableName = NULL,
  tableInfo->createTime = 0;
  tableInfo->redefTime = 0;
  tableInfo->objUID = 0;
  tableInfo->objOwnerID = objectOwnerID;
  tableInfo->schemaOwnerID = schemaOwnerID;
  tableInfo->isAudited = 1;
  tableInfo->validDef = 1;
  tableInfo->hbaseCreateOptions = NULL;
  tableInfo->numSaltPartns = 0;
  tableInfo->rowFormat = COM_UNKNOWN_FORMAT_TYPE;
  tableInfo->objectFlags = 0;

  Int64 objUID = -1;
  if (updateSeabaseMDTable(&cliInterface, 
			   catalogNamePart, schemaNamePart, objectNamePart,
			   COM_USER_DEFINED_ROUTINE_OBJECT,
			   "N",
			   tableInfo,
			   numParams,
			   colInfoArray,
			   0, NULL,
			   0, NULL,
                           objUID))
    {
      deallocEHI(ehi); 
      processReturn();
      return;
    }

  if (objUID == -1)
    {
      deallocEHI(ehi); 
      processReturn();
      return;
    }

  NAString udrType;
  getRoutineTypeLit(createRoutineNode->getRoutineType(), udrType);
  NAString languageType;
  getLanguageTypeLit(language, languageType);
  NAString sqlAccess;
  getSqlAccessLit(createRoutineNode->getSqlAccess(), sqlAccess);
  NAString paramStyle;
  getParamStyleLit(style, paramStyle);
  NAString transactionAttributes;
  getTransAttributesLit(createRoutineNode->getTransactionAttributes(), transactionAttributes);
  NAString parallelism;
  getParallelismLit(createRoutineNode->getParallelism(), parallelism);
  NAString externalSecurity;
  getExternalSecurityLit(createRoutineNode->getExternalSecurity(), externalSecurity);
  NAString executionMode;
  getExecutionModeLit(createRoutineNode->getExecutionMode(), executionMode);
  

  char * query = new(STMTHEAP) char[2000+MAX_SIGNATURE_LENGTH];
  str_sprintf(query, "insert into %s.\"%s\".%s values (%Ld, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', '%s', '%s', '%s', %Ld, '%s' )",
	      getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_ROUTINES,
	      objUID,
              udrType.data(),
              languageType.data(),
              createRoutineNode->isDeterministic() ? "Y" : "N" ,
              sqlAccess.data(),
              createRoutineNode->isCallOnNull() ? "Y" : "N" ,
              createRoutineNode->isIsolate() ? "Y" : "N" ,
              paramStyle.data(),
              transactionAttributes.data(),
              createRoutineNode->getMaxResults(),
              createRoutineNode->getStateAreaSize(),
              externalName.data(),
              parallelism.data(),
              createRoutineNode->getUserVersion().data(),
              externalSecurity.data(),
              executionMode.data(),
              libUID,
              sigBuf);
  
  cliRC = cliInterface.executeImmediate(query);
  NADELETEBASIC(query, STMTHEAP);
  if (cliRC < 0)
    {
      cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
      processReturn();
      return;
    }

  char * query1 = new(STMTHEAP) char[1000];
  str_sprintf(query1, "insert into %s.\"%s\".%s values (%Ld, %Ld)",
	      getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_LIBRARIES_USAGE,
	      libUID, objUID);
  
  cliRC = cliInterface.executeImmediate(query1);
  NADELETEBASIC(query1, STMTHEAP);
  if (cliRC < 0)
    {
      cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
      processReturn();
      return;
    }

  // hope to remove this call soon by setting the valid flag to Y sooner
  if (updateObjectValidDef(&cliInterface, 
			   catalogNamePart, schemaNamePart, objectNamePart,
			   COM_USER_DEFINED_ROUTINE_OBJECT_LIT,
			   "Y"))
    {
      deallocEHI(ehi); 
      processReturn();
      return;
    }

  processReturn();
  return;
}
// static helper function to generate one list of disks
// (returns an array of ExScratchDiskDrive objects)
static ExScratchDiskDrive * genScratchDisks(const NAString &def,
						Lng32 &numDirs,
						Generator *generator,
						const char *defName)
{
  ExScratchDiskDrive *result = NULL;

  // temporary
  //  numDrives = 0;
  //  return result;
  // end temporary

  const char *str = def.data();
  if (!str || str[0]=='\0')
    {
      numDirs = 0;
      return result;		// fast return if empty NADefaults val
    }

  
  // ---------------------------------------------------------------------
  // Convert the strings into a temporary list of ExScratchDiskDrive
  // objects (temporary because we want to make the final list a
  // contiguous array)
  // ---------------------------------------------------------------------
  CollHeap *heap = generator->wHeap();
  Space *space = generator->getSpace();
  LIST(ExScratchDiskDrive *) tempList(heap);
  struct stat st;
  
 
  Lng32 nodeNum;
 
  char *token,*saveptr = NULL;
  //save the pointer to this since token will keep changing.

  char *sep = (char *)":";
  token = strtok_r((char *)str,sep,&saveptr);
  while (token != NULL)
    {
      //validate the directory
      if ((stat(token,&st) != 0 ) &&  !S_ISDIR(st.st_mode) ) //&& (numDirs > MAX_SCRATCH_LOCATIONS))
        {
          // syntax error in default, issue a warning (not an error)
          *CmpCommon::diags() << DgSqlCode(2055)
			      << DgString0(def)
			      << DgString1(defName);
          // don't continue after a syntax error
          str = NULL;
        }
      else
        {
          tempList.insert(new(heap) ExScratchDiskDrive(
                               token,
                               strlen(token) ));
        }
      token = strtok_r(NULL,sep,&saveptr);
    }
      
 
  token  = NULL;
    

  // ---------------------------------------------------------------------
  // Calculate total generated space needed and allocate it
  // ---------------------------------------------------------------------
  numDirs = tempList.entries();
 
  Lng32 allDirNamesLen = 0;
  char *generatedDirNames = NULL;

  Int32 i=0;
  for (; i<numDirs; i++)
    {
      allDirNamesLen += str_len(tempList[i]->getDirName())+1;
    }

  if (numDirs >0)
    {
      result = new(space) ExScratchDiskDrive[numDirs];
      generatedDirNames = new(space) char[allDirNamesLen];
    }

  // ---------------------------------------------------------------------
  // Loop over the temporary list and copy it into the generated space
  // ---------------------------------------------------------------------
  for (i=0; i<numDirs; i++)
    {
      ExScratchDiskDrive *src = tempList[i];
      Lng32 dirNameLen = src->getDirNameLength();
        
      str_cpy_all(generatedDirNames, src->getDirName(), dirNameLen);
      generatedDirNames[dirNameLen] = 0;
      result[i].setDirName(generatedDirNames);
      result[i].setDirNameLength(dirNameLen);
      generatedDirNames += dirNameLen+1;
    }
  return result;
}
// read and return procedure location table area (header + entries)
Int32
readPLTArea
(fstream              &mf,          // (IN) : binary module file
 module_header_struct &latestModHdr,// (IN) : its module header
 NAHeap               &heap,        // (IN) : allocate PLT area from here
 const char *     name,       // (IN) : module name (for error msg)
 ComDiagsArea         &diags,       // (IN) : deposit any error msg here
 plt_header_struct   *&pltArea)     // (OUT): plt header + entries
{
  // make sure we have reasonable arguments
  if (latestModHdr.plt_area_offset  <= 0 ||
      latestModHdr.plt_area_length  <= 0 ||
      latestModHdr.plt_hdr_length   <= 0 ||
      latestModHdr.plt_entry_length <= 0)
    return -1;

  // allocate space for PLT header
  plt_header_struct pltHdrCls, *latestPLTHdr, *plt;
  plt = (plt_header_struct *)
    heap.allocateMemory(latestModHdr.plt_hdr_length);

  // read procedure location table header
  mf.seekg(latestModHdr.plt_area_offset, ios::beg);
  mf.read((char *)plt, latestModHdr.plt_hdr_length);
  if (mf.fail()) {
    diags << DgSqlCode(-CLI_READ_ERROR) << DgString0(name);
    return -1;
  }
      
  // give versioning a chance to massage/migrate it to this version
  latestPLTHdr = (plt_header_struct*)plt->driveUnpack(plt, &pltHdrCls,NULL);
  if (!latestPLTHdr) {
    // error: version is no longer supported
    diags << DgSqlCode(-CLI_MOD_PLT_HDR_VERSION_ERROR) 
          << DgString0(name);
    return -1;
  }

  pltArea = latestPLTHdr;
  Int32 num_procs = latestPLTHdr->num_procedures;
  
  if (num_procs >= 1) {
	// allocate space for PLT header + entries
    heap.deallocateMemory(plt);
    plt = (plt_header_struct *)
      heap.allocateMemory((size_t)latestModHdr.plt_area_length);
	  
    // read procedure location table header + entries
    mf.seekg(latestModHdr.plt_area_offset, ios::beg);
    mf.read((char *)plt, (Int32)latestModHdr.plt_area_length);
    if (mf.fail()) {
      diags << DgSqlCode(-CLI_READ_ERROR) << DgString0(name);
      return -1;
    }
	  
    // give versioning a chance to massage/migrate it to this version
    latestPLTHdr = (plt_header_struct*)plt->driveUnpack(plt, &pltHdrCls, NULL);
    if (!latestPLTHdr) {
      // error: version is no longer supported
      diags << DgSqlCode(-CLI_MOD_PLT_HDR_VERSION_ERROR) 
            << DgString0(name);
      return -1;
    }
    pltArea = latestPLTHdr;
  }

  // verify its validity
  Lng32 errCode = pltArea->RtduStructIsCorrupt();
  if (errCode) {
    // the module file is corrupted or has invalid data
    diags << DgSqlCode(errCode) << DgString0(name);
    heap.deallocateMemory(plt);
    return -1;
  }
  return num_procs;
}
Beispiel #21
0
// ----------------------------------------------------------------------------
// method: getPrivileges
//
// If authorization is enabled, set privs based on the passed in priv_desc
// and set up query invalidation (security) keys for the routine.
// ----------------------------------------------------------------------------
void NARoutine::getPrivileges(TrafDesc *priv_desc)
{
  if ( !CmpCommon::context()->isAuthorizationEnabled() || ComUser::isRootUserID())
  {
    privInfo_ = new(heap_) PrivMgrUserPrivs;
    privInfo_->setOwnerDefaultPrivs();
    return;
  }

  NAString privMDLoc = CmpSeabaseDDL::getSystemCatalogStatic();
  privMDLoc += ".\"";
  privMDLoc += SEABASE_PRIVMGR_SCHEMA;
  privMDLoc += "\"";
  PrivMgrCommands privInterface(privMDLoc.data(), CmpCommon::diags(),PrivMgr::PRIV_INITIALIZED);

  if (priv_desc == NULL)
  {
    privInfo_ = new(heap_) PrivMgrUserPrivs;

    CmpSeabaseDDL cmpSBD(STMTHEAP);
    if (cmpSBD.switchCompiler(CmpContextInfo::CMPCONTEXT_TYPE_META))
    {
      if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
        *CmpCommon::diags() << DgSqlCode( -4400 );

      return;
    }

    ComObjectType objectType = (UDRType_ == COM_PROCEDURE_TYPE ?
                                COM_STORED_PROCEDURE_OBJECT :
                                COM_USER_DEFINED_ROUTINE_OBJECT);

    std::vector <ComSecurityKey *>* secKeyVec = new(heap_) std::vector<ComSecurityKey *>;
    if (privInterface.getPrivileges(objectUID_, objectType,
                                    ComUser::getCurrentUser(), 
                                   *privInfo_, secKeyVec) != STATUS_GOOD)
    {
      NADELETE(privInfo_, PrivMgrUserPrivs, heap_);
      privInfo_ = NULL;
    }

    cmpSBD.switchBackCompiler();

    if (privInfo_)
    {
      for (std::vector<ComSecurityKey*>::iterator iter = secKeyVec->begin();
           iter != secKeyVec->end();
           iter++)
      {
        // Insertion of the dereferenced pointer results in NASet making
        // a copy of the object, and then we delete the original.
        routineSecKeySet_.insert(**iter);
          delete *iter;
      }
    }
  }
  else
  {
    // get roles granted to current user 
    // SQL_EXEC_GetRoleList returns the list of roles from the CliContext
    std::vector<int32_t> myRoles;
    Int32 numRoles = 0;
    Int32 *roleIDs = NULL;
    if (SQL_EXEC_GetRoleList(numRoles, roleIDs) < 0)
    {
      *CmpCommon::diags() << DgSqlCode(-1034);
      return;
    }

    // At this time we should have at least one entry in roleIDs (PUBLIC_USER)
    CMPASSERT (roleIDs && numRoles > 0);

    for (Int32 i = 0; i < numRoles; i++)
      myRoles.push_back(roleIDs[i]);

    privInfo_ = new (heap_) PrivMgrUserPrivs;
    privInfo_->initUserPrivs(myRoles, priv_desc, ComUser::getCurrentUser(),objectUID_, routineSecKeySet_);
  }
}
short ExTupleFlowTcb::work()
{
  // This is some sort of a hack to fix the problems with the number of rows
  // inserted returned to the user for packed tables. For these tables, rows
  // are packed (by the Pack node which is the left child of this tuple flow)
  // before they are sent off to DP2. DP2 has no idea that it's actually
  // inserting multiple logical rows (as perceived by the user). However,
  // there is actually a hidden count of logical rows stored as the first 4
  // bytes of the packed row. This counter is supposed to keep track of a sum
  // of this number in each packed row it gets from the left. When all
  // insertions are done, this sum is used to override what's stored by the
  // PA node in the executor global area the number of rows inserted. This is
  // not a very good place to have this fix, but since this is a low-priority
  // problem at this time, here we are.
  //                                                       
  // 
  // NB: The code introduced for this fix 
  //      could be safely removed if desired. Also, all changes are within
  //     this file.
  // 

  if (qParent_.down->isEmpty())
    return WORK_OK;
  
  ex_queue_entry * pentry_down = qParent_.down->getHeadEntry();
  ExTupleFlowPrivateState &  pstate = 
    *((ExTupleFlowPrivateState*) pentry_down->pstate);

  if ((tflowTdb().userSidetreeInsert()) &&
      (pentry_down->downState.request == ex_queue::GET_EOD) &&
      (NOT pstate.parentEOD_))
    {
      pstate.step_ = MOVE_EOD_TO_TGT_;
    }
  else if ((pstate.step_ != DONE_) &&
     (pstate.step_ != CANCELLED_) &&
      (pentry_down->downState.request == ex_queue::GET_NOMORE))
    {
      if (pstate.step_ == EMPTY_)
        pstate.step_ = DONE_;
      else
        pstate.step_ = CANCELLED_;
    }

  while (1)
    {
      switch (pstate.step_)
	{
	case EMPTY_:
	  {
	    if (qSrc_.down->isFull())
	      return WORK_OK;

	    ex_queue_entry * src_entry = qSrc_.down->getTailEntry();

	    src_entry->downState.request = pentry_down->downState.request;
	    src_entry->downState.requestValue = 
	      pentry_down->downState.requestValue;

	    if ((tflowTdb().firstNRows() >= 0) &&
		(pentry_down->downState.request != ex_queue::GET_N))
	      {
		src_entry->downState.request = ex_queue::GET_N;
		src_entry->downState.requestValue = tflowTdb().firstNRows();
	      }

	    src_entry->downState.parentIndex = 
              qParent_.down->getHeadIndex();

	    src_entry->passAtp(pentry_down);
	    
	    qSrc_.down->insert();

	    // just checking to make sure we got a diags area from the CLI if we are 
	    // executing a non-tomic insert. This is done now so that we don't have to do it in multiple
	    // places later.
	    if (tflowTdb().isNonFatalErrorTolerated()) {
	      ComDiagsArea *cliDiagsArea = pentry_down->getDiagsArea();
	      ex_assert(cliDiagsArea, "In Tupleflow : Non-Atomic insert received no diags area from the CLI");
	    }

	    pstate.parentEOD_ = FALSE;
	    pstate.srcEOD_ = FALSE;
            pstate.matchCount_ = 0;
            pstate.tgtRequests_ = 0;
	    pstate.tgtRowsSent_ = FALSE;
	    pstate.noOfUnPackedRows_ = 0;
	    pstate.srcRequestCount_ = -1;
            pstate.nonFatalErrorSeen_ = FALSE;
	    // Set startRightIndex_ so that CancelReques doesn't do anything.
	    pstate.startRightIndex_ = pstate.srcRequestCount_;
	    pstate.step_ = MOVE_SRC_TO_TGT_;
	  }
	  break;

	case MOVE_SRC_TO_TGT_:
	  {
	    // if there are some rows in source up queue, move them to target.
	    while ((! qSrc_.up->isEmpty()) && (! qTgt_.down->isFull())
                     && (pstate.step_ != HANDLE_ERROR_))
	      {
		ex_queue_entry * src_entry = qSrc_.up->getHeadEntry();
		ex_queue_entry * tgt_entry = qTgt_.down->getTailEntry();

		switch (src_entry->upState.status)
		  {
		  case ex_queue::Q_OK_MMORE:
		    {
		      // move this source row to target.
                      
                      // LCOV_EXCL_START
                      // BEGIN:  - Read note at beginning of work().
                      // 
                      if (tcbSrc_->getNodeType() == ComTdb::ex_PACKROWS)
                      {
                        char* packTuppPtr =
                          src_entry->getTupp(src_entry->numTuples()-1)
			  .getDataPointer();
                        Int32 noOfRows = *((Int32 *)packTuppPtr);
                        pstate.noOfUnPackedRows_ += (noOfRows - 1);
			
                      }
                      //
                      // END:- Read note at beginning of work().
                      // LCOV_EXCL_STOP

		      pstate.srcRequestCount_++;
		      tgt_entry->downState.request = 
			pentry_down->downState.request;
		      tgt_entry->downState.requestValue = 
			pentry_down->downState.requestValue;
		      tgt_entry->downState.parentIndex = 
                       (Lng32) pstate.srcRequestCount_;
		      tgt_entry->copyAtp(src_entry);
		      qTgt_.down->insert();
                      pstate.tgtRequests_++;
	              pstate.tgtRowsSent_ = TRUE;
		      qSrc_.up->removeHead();
		    }
		    break;

		  case ex_queue::Q_NO_DATA:
		    {
		      if ((tflowTdb().vsbbInsertOn()) &&
	                  (pstate.tgtRowsSent_ == TRUE))
			{
			  if (tflowTdb().userSidetreeInsert())
			    {
			      tgt_entry->downState.request = 
				ex_queue::GET_EOD_NO_ST_COMMIT;
			    }
			  else
			    {
			      tgt_entry->downState.request = 
				ex_queue::GET_EOD;
			    }

			  tgt_entry->downState.requestValue = 
			    pentry_down->downState.requestValue;
			  tgt_entry->downState.parentIndex = 
                            (Lng32) pstate.srcRequestCount_;
			  tgt_entry->copyAtp(src_entry);
			  
			  qTgt_.down->insert();
                          pstate.tgtRequests_++;
			}

                      // LCOV_EXCL_START
	              if ((pstate.tgtRowsSent_ == FALSE) &&
			  (src_entry->getDiagsArea()))
			{
			  // a warning is returned with EOD and
			  // nothing else was returned from source.
			  // Move warning to parent's up queue.
			  if (qParent_.up->isFull())
			    return WORK_OK;

			  ex_queue_entry * up_entry = 
			    qParent_.up->getTailEntry();
			  up_entry->setDiagsArea(src_entry->getDiagsArea());
			}
                      // LCOV_EXCL_STOP

		      qSrc_.up->removeHead();
		      
		      pstate.srcEOD_ = TRUE;
                      
                      // LCOV_EXCL_START
		      if (tflowTdb().sendEODtoTgt())
			pstate.step_ = MOVE_EOD_TO_TGT_;
                      // LCOV_EXCL_STOP
		    }
		    break;
		    
		  case ex_queue::Q_SQLERROR:
                    {
	              if (qParent_.up->isFull())
	                return WORK_OK;
	    
	              ex_queue_entry * pentry = qParent_.up->getTailEntry();
		      ComDiagsArea * da = src_entry->getDiagsArea();
		      ex_assert(da, "We have a Q_SQLERROR in Tupleflow but no diags area");
		      
		      if (tflowTdb().isNonFatalErrorTolerated() &&
			 (da->getNextRowNumber(ComCondition::NONFATAL_ERROR) == 
			  ComCondition::NONFATAL_ERROR)) 
			{
			  pstate.nonFatalErrorSeen_ = TRUE;		
			}
		      else 
			{
			  pstate.step_ = HANDLE_ERROR_;
			  pstate.nonFatalErrorSeen_ = FALSE;
			}

		      pstate.srcRequestCount_++;
		      if(tflowTdb().isRowsetIterator())
	                da->setAllRowNumber((Lng32) pstate.srcRequestCount_); 

                      ComDiagsArea *accumulatedDiagsArea = pentry->getDiagsArea();
			if (accumulatedDiagsArea)
			  {
			    accumulatedDiagsArea->mergeAfter(*da);
			    if (!(accumulatedDiagsArea->canAcceptMoreErrors()) && 
				tflowTdb().isNonFatalErrorTolerated()) 
			      {
				pstate.nonFatalErrorSeen_ = FALSE;
				pstate.step_ = HANDLE_ERROR_; 
			      }
			  }
                        else
			  {
			    pentry->setDiagsArea(da);
			    da->incrRefCount();
			    accumulatedDiagsArea = da ;
			    if (tflowTdb().isNonFatalErrorTolerated()) 
			      {
				ComDiagsArea *cliDiagsArea = pentry_down->getDiagsArea();
				da->setLengthLimit(cliDiagsArea->getLengthLimit());
			      }
			  }

			// For Non-Fatal errors we will remove this Q_SQLERROR reply from the 
			// left child right below as we will continue to stay in this state (MOVE_SRC_TO_TGT_).
			// For fatal errors this Q_SQLERROR reply is removed in HANDLE_ERROR step to which
			// we will transition immediately.
			if (pstate.nonFatalErrorSeen_ == TRUE)
			  qSrc_.up->removeHead();	
                    }
                    break;

		  case ex_queue::Q_REC_SKIPPED:
                    {
		      pstate.srcRequestCount_++;
		      ComDiagsArea * da = src_entry->getDiagsArea();
		      if (da)
			pstate.nonFatalErrorSeen_ = TRUE;		  
		      qSrc_.up->removeHead();
                    }
                    break;

		  default:
		    {
		      ex_assert(0, "ExTupleFlowTcb::work() Error returned from src"); // LCOV_EXCL_LINE
		    }
		    break;
		  } // switch

	      } // while
	    
            // if the child reply is not an Q_SQLERROR, then process target
            if ((pstate.step_ != HANDLE_ERROR_) &&
		(pstate.step_ != MOVE_EOD_TO_TGT_))
	      pstate.step_ = PROCESS_TGT_;
	  } // MOVE_SRC_TO_TGT
	  break;

	case MOVE_EOD_TO_TGT_:
	  {
	    pstate.parentEOD_ = TRUE;

	    if (qTgt_.down->isFull())
	      return WORK_OK;

	    ex_queue_entry * tgt_entry = qTgt_.down->getTailEntry();
	    tgt_entry->downState.request = ex_queue::GET_EOD;
	    
	    tgt_entry->downState.requestValue = 
	      pentry_down->downState.requestValue;
	    tgt_entry->downState.parentIndex = 
	      qParent_.down->getHeadIndex();
	    //tgt_entry->passAtp(pentry_down);
	    
	    qTgt_.down->insert();

	    pstate.tgtRequests_++;

            // LCOV_EXCL_START
	    if (tflowTdb().sendEODtoTgt())
	      pstate.srcEOD_ = TRUE;
            // LCOV_EXCL_STOP
	    else
	      pstate.srcEOD_ = FALSE;

	    pstate.step_ = PROCESS_TGT_;
	  }
	break;

	case PROCESS_TGT_:
	  {
	    while (! qTgt_.up->isEmpty()  &&  pstate.step_ != HANDLE_ERROR_)
	      {
		ex_queue_entry * tgt_entry = qTgt_.up->getHeadEntry();
		switch (tgt_entry->upState.status)
		  {
		  case ex_queue::Q_OK_MMORE:
		    {
		      if (!tflowTdb().isNonFatalErrorTolerated()) 
			{
			  // ex_assert(0, "ExTupleFlowTcb::work() OK_MMORE from tgt");
			  if (qParent_.up->isFull())
			    return WORK_OK;

			  ex_queue_entry * pentry = qParent_.up->getTailEntry();

			  pentry->upState.status = ex_queue::Q_OK_MMORE;
			  pentry->upState.downIndex = qParent_.down->getHeadIndex();
			  pentry->upState.parentIndex = pentry_down->downState.parentIndex;
			  pentry->upState.setMatchNo(pstate.matchCount_);
			  
			  // copy input tupps from parent request
			  pentry->copyAtp(pentry_down);

			  // copy child's atp to
			  // the output atp (to parent's up queue)
			  pentry->copyAtp(tgt_entry);

			  // insert into parent up queue
			  qParent_.up->insert();	  
			}
		      else 
			{
			  ComDiagsArea * da = tgt_entry->getDiagsArea();
			  ex_assert(da, "We have a Q_OK_MMORE in Tupleflow but no diags area");
			  if (da->mainSQLCODE() != 0) {
			    // Non-atomic Rowsets sends OK_MMORE with non-empty diags from child
			    // empty diags (mainsqlcode == 0) implies OK_MMORE sent by ignoreDupKey code
			    // when NAR is on, for -8102 error.  Just consume the OK_MMORE.
			    
			    if(tflowTdb().isRowsetIterator()) 
			      {
				da->setAllRowNumber(Lng32 (tgt_entry->upState.parentIndex));
			      }
			    
			    pstate.nonFatalErrorSeen_ = TRUE;
			    ex_queue_entry * pentry = qParent_.up->getTailEntry();
			    ComDiagsArea *accumulatedDiagsArea = pentry->getDiagsArea();
			    if (accumulatedDiagsArea)
			      {
				accumulatedDiagsArea->mergeAfter(*da);
				if (!(accumulatedDiagsArea->canAcceptMoreErrors()) && 
				    tflowTdb().isNonFatalErrorTolerated()) 
				  {
				    pstate.nonFatalErrorSeen_ = FALSE;
				    pstate.step_ = HANDLE_ERROR_; 
				  }
			      }
			    else
			      {
				pentry->setDiagsArea(da);
				da->incrRefCount();
				if (tflowTdb().isNonFatalErrorTolerated()) {
				  ComDiagsArea *cliDiagsArea = pentry_down->getDiagsArea();
				  da->setLengthLimit(cliDiagsArea->getLengthLimit());
				}
			      }
			  }
			}

		      qTgt_.up->removeHead();
		    }
		  break;
		  
		  case ex_queue::Q_NO_DATA:
		    {
                      ComDiagsArea * da = tgt_entry->getDiagsArea();
                      if (da)
                        {
	                  ex_queue_entry * pentry = qParent_.up->getTailEntry();
                          ComDiagsArea *accumulatedDiagsArea = pentry->getDiagsArea();
                          if (accumulatedDiagsArea) 
                            accumulatedDiagsArea->mergeAfter(*da);
                          else
                            {
	                      pentry->setDiagsArea(da);
                              da->incrRefCount();
			      if (tflowTdb().isNonFatalErrorTolerated()) {
				ComDiagsArea *cliDiagsArea = pentry_down->getDiagsArea();
				da->setLengthLimit(cliDiagsArea->getLengthLimit());
			      }
                            }
                        }
		      pstate.matchCount_ += tgt_entry->upState.getMatchNo();
		      qTgt_.up->removeHead();
		      pstate.tgtRequests_--;
		      pstate.startRightIndex_++;
		    }
		    break;
		    
		  case ex_queue::Q_SQLERROR:
                    {
		      if (qParent_.up->isFull())
			return WORK_OK;
	    
		      ex_queue_entry * pentry = qParent_.up->getTailEntry();
		      pentry->copyAtp(tgt_entry);  
		      pstate.nonFatalErrorSeen_ = FALSE;
		      pstate.step_ = HANDLE_ERROR_; 

		      if(tflowTdb().isRowsetIterator()) 
		      {
			ex_queue_entry * pentry = qParent_.up->getTailEntry();
	                ComDiagsArea *da = pentry->getDiagsArea();
			ex_assert(da, "To set RowNumber, an error condition must be present in the diags area");
	                da->setAllRowNumber(Lng32 (tgt_entry->upState.parentIndex));		      
		      }
	    
                    }
                    break;
                             
		  default:
		    {
		      ex_assert(0, "ExTupleFlowTcb::work() Error returned from tgt"); // LCOV_EXCL_LINE
		    }
		    break;
		    
		  } // switch
		
	      } // while 

            if (pstate.step_ == HANDLE_ERROR_)
              break;

	    // if source has returned EOD,
	    // and there are no pending requests in target's down
	    // queue, then we are done with this parent request.
	    if (((pstate.srcEOD_ == TRUE) ||
		 (pstate.parentEOD_ == TRUE)) &&
		(qTgt_.down->isEmpty()))
	      pstate.step_ = DONE_;
	    else
	      {
		if (NOT pstate.parentEOD_)
		  pstate.step_ = MOVE_SRC_TO_TGT_;

	        if (qSrc_.up->isEmpty() || qTgt_.down->isFull())
	 	  return WORK_OK;
	        else
		  return WORK_CALL_AGAIN;
	      }
	  }
	  break;

        case HANDLE_ERROR_:
          {
	     ex_queue_entry * pentry = qParent_.up->getTailEntry();

 	     pentry->upState.status = ex_queue::Q_SQLERROR;
	     pentry->upState.downIndex = qParent_.down->getHeadIndex();
	     pentry->upState.parentIndex = pentry_down->downState.parentIndex;
	     pentry->upState.setMatchNo(pstate.matchCount_);

	     ComDiagsArea *da = pentry->getDiagsArea();
	     if (tflowTdb().isNonFatalErrorTolerated() &&
		  !(da->canAcceptMoreErrors())) {
	      ComDiagsArea *cliDiagsArea = pentry_down->getDiagsArea();
	      da->removeLastErrorCondition();
	      *da << DgSqlCode(-EXE_NONATOMIC_FAILURE_LIMIT_EXCEEDED) 
			      << DgInt0(cliDiagsArea->getLengthLimit());
	     }
	    
	     // insert into parent up queue
	     qParent_.up->insert();
   
             pstate.step_ = CANCELLED_;
          }
          break;

        case CANCELLED_:
          {
            qSrc_.down->cancelRequestWithParentIndex(qParent_.down->getHeadIndex());

            // Cancel all the outstanding requests that have been sent to the target.
            // Cancel all requests within given range (inclusive)
            qTgt_.down->cancelRequestWithParentIndexRange((queue_index)pstate.startRightIndex_+1,
                                                          (queue_index)pstate.srcRequestCount_);
            pstate.startRightIndex_ = pstate.srcRequestCount_;

            //ignore all rows from source child, till Q_NO_DATA is reached
            while ((pstate.srcEOD_ != TRUE) && (!qSrc_.up->isEmpty()))
              {
	        ex_queue_entry * src_entry = qSrc_.up->getHeadEntry();
                switch(src_entry->upState.status)
                  {
                    case ex_queue::Q_OK_MMORE:
                    case ex_queue::Q_SQLERROR:
		    case ex_queue::Q_REC_SKIPPED:
                      {
                        qSrc_.up->removeHead();
                      }
                      break;

                    case ex_queue::Q_NO_DATA:
                      {
                        pstate.srcEOD_ = TRUE;
                        qSrc_.up->removeHead();
                      }
                      break;
                        
                    default:
                      {
		        ex_assert(0, "ExTupleFlowTcb::work() Error returned from src"); // LCOV_EXCL_LINE
		      }
		      break;
                  }
              }

            //ignore all rows from target child, till Q_NO_DATA is reached
            while (pstate.tgtRequests_ && !qTgt_.up->isEmpty())
              {
	        ex_queue_entry * tgt_entry = qTgt_.up->getHeadEntry();
                switch(tgt_entry->upState.status)
                  {
                    case ex_queue::Q_OK_MMORE:
                    case ex_queue::Q_SQLERROR:
                      {
                        qTgt_.up->removeHead();
                      }
                      break;

                    case ex_queue::Q_NO_DATA:
                      {
                        qTgt_.up->removeHead();
                        pstate.tgtRequests_--;
                      }
                      break;
                    
                    default:
                      {
                        ex_assert(0, "ExTupleFlowTcb::work() Error returned from tgt"); // LCOV_EXCL_LINE
                      }
		      break;
                  }
              }

            // if both source and target returned all the rows,
            // insert Q_SQLERROR into the parent up queue
            if ((pstate.srcEOD_ == TRUE)  &&  !pstate.tgtRequests_)
              {
	        pstate.step_ = DONE_; 
              }
            else
              return WORK_OK;
          }
          break;
	  
	case DONE_:
	  {
	    if (qParent_.up->isFull())
	      return WORK_OK;
	    
	    ex_queue_entry * pentry = qParent_.up->getTailEntry();

	    if (pstate.nonFatalErrorSeen_) {
	      ComDiagsArea *da = pentry->getDiagsArea();
	      ComDiagsArea *cliDiagsArea = pentry_down->getDiagsArea();
	      ex_assert((da || cliDiagsArea), "We have non-fatal errors in Tupleflow but no diags area");
	      if (cliDiagsArea) {
		  if (da)
		    da->mergeAfter(*cliDiagsArea);
		  else
		    {
		      pentry->setDiagsArea(cliDiagsArea);
		      cliDiagsArea->incrRefCount();
		    }
	      } 

	      if (cliDiagsArea->canAcceptMoreErrors()) {
	      	  ComDiagsArea *mergedDiagsArea = pentry->getDiagsArea();
		  // used to make mainSQLCODE() return 30022 or 30035.
		  mergedDiagsArea->setNonFatalErrorSeen(TRUE);
		  NABoolean anyRowsAffected = FALSE;


		  // This tupleflow should be in the master for
		  // non-atomic rowsets.
		  ExMasterStmtGlobals *g = getGlobals()->
			castToExExeStmtGlobals()->castToExMasterStmtGlobals();
		  ex_assert(g, "Rowset insert has a flow node that is not in the master executor");
		  if (g->getRowsAffected() > 0)
		    anyRowsAffected = TRUE;
		  
		  if (anyRowsAffected)
		      *mergedDiagsArea << DgSqlCode(EXE_NONFATAL_ERROR_SEEN);
		  else 
		      *mergedDiagsArea << DgSqlCode(EXE_NONFATAL_ERROR_ON_ALL_ROWS);

	      } // we exceeded the Nonfatal error limit when merging with the CLI diags area
	      else {
		pstate.step_ = HANDLE_ERROR_;
		// will prevent us from merging the diags areas again
		pstate.nonFatalErrorSeen_ = FALSE ;
		break ;
	      }
	    }
	    
	    pentry->upState.status = ex_queue::Q_NO_DATA;
	    pentry->upState.downIndex = qParent_.down->getHeadIndex();
	    pentry->upState.parentIndex = pentry_down->downState.parentIndex;
	    pentry->upState.setMatchNo(pstate.matchCount_);

            // LCOV_EXCL_START
            // BEGIN:  Read note at beginning of work().
            //
            if(pstate.noOfUnPackedRows_ != 0)
            {
	      ComDiagsArea *da = pentry->getDiagsArea();
	      if (da == NULL)
		{
		  da = ComDiagsArea::allocate(getGlobals()->getDefaultHeap());
		  pentry->setDiagsArea(da);
		}
	      da->addRowCount(pstate.noOfUnPackedRows_);
              pstate.noOfUnPackedRows_ = 0;
            }
            //
            // END: - Read note at beginning of work().
            // LCOV_EXCL_STOP

	    // if stats are to be collected, collect them.
	    if (getStatsEntry())
	      {
		// nothing yet returned from right child or returned
		// to parent.
		getStatsEntry()->setActualRowsReturned(0);
	      }
	    
	    // insert into parent up queue
	    qParent_.up->insert();
	    
	    pstate.step_ = EMPTY_;
	    qParent_.down->removeHead();	

	    return WORK_CALL_AGAIN;  // check for more down requests

	  }
	  break;

	} // switch pstate.step_
    } // while
  
#pragma nowarn(203)   // warning elimination 
  return 0;
#pragma warn(203)  // warning elimination 
}
//////////////////////////////////////////////////////
// work() for ExTimeoutTcb
//////////////////////////////////////////////////////
short ExTimeoutTcb::work()
{
  while (1) {
    // if no parent request, return
    if (qparent_.down->isEmpty())
      return WORK_OK;
      
    // if no room in up queue, won't be able to return data/status.
    // Come back later.
    if (qparent_.up->isFull()) return WORK_OK;
      
    ex_queue_entry * pentry_down = qparent_.down->getHeadEntry(); 
    ExTimeoutPrivateState & pstate =
      *((ExTimeoutPrivateState*) pentry_down->pstate);

    // Calculate the timeout actual value
    Lng32 timeoutValue = 0; 
    NABoolean goodTimeoutValue = TRUE ;
    if (timeoutValueExpr()) {
      if ( timeoutValueExpr()->eval(pentry_down->getAtp(), workAtp_) 
	   == ex_expr::EXPR_ERROR ) { // expression did not yield a valid value
	handleErrors(pentry_down, pentry_down->getAtp()->getDiagsArea()); 
	goodTimeoutValue = FALSE ;
      } else {
	tupp TP = workAtp_->getTupp(timeoutTdb().workCriDesc_->noTuples()-1);
	timeoutValue = *(Lng32 *)TP.getDataPointer(); // pointer is (char *)
      }
    }

    /****************************************************/
    /********   Do the actual SET TIMEOUT work   ********/
    /**                                                **/
    /** The scope of the work is only making changes   **/
    /** to the global timeout data kept at the context **/
    /****************************************************/

    // Get the global timeout-data object
    ContextCli * currContext = getGlobals()->castToExExeStmtGlobals()->
      castToExMasterStmtGlobals()->getStatement()->getContext();
    
    TimeoutData * GlobalTimeouts = currContext->getTimeouts();

#if _DEBUG    // For debugging only !!!!!
    if ( getenv("DEBUG_TIMEOUT") ) {
      ComDiagsArea* diagsArea = 
	ComDiagsArea::allocate (getGlobals()->getDefaultHeap());
      char errmsg[120];

      if ( timeoutTdb().isStream() ) {   // it was a SET STREAM TIMEOUT
	if ( GlobalTimeouts->isStreamTimeoutSet() ) {
	  sprintf(errmsg, "Stream timeout set to %d\n",
		  GlobalTimeouts->getStreamTimeout() );
	} else sprintf(errmsg, "Stream timeout was NOT SET ! \n");
      } // lock timeout -- not stream
      else {
	if ( theTableName_[0] == '*' ) { // For all tables
	  sprintf(errmsg, "Number of lock timeouts set: %d\n",
		  GlobalTimeouts->entries() );
	} else {
	  Lng32 timeoutValue;
	  NABoolean found = 
	    GlobalTimeouts->getLockTimeout(theTableName_, timeoutValue );
	  if ( ! found ) 
	    sprintf(errmsg, "Lock timeout for table %s was NOT SET ! \n",
		    theTableName_ );
	  else sprintf(errmsg, "Lock timeout for table %s is %d \n",
		       theTableName_ , timeoutValue );
	}
      }
      // emit message as an error ( msg 3066 has no text of its own )
      *diagsArea << DgSqlCode(-3066)
		<< DgString0(errmsg) ;
      ExHandleArkcmpErrors(qparent_, pentry_down, 0, getGlobals(), 
			   diagsArea, (ExeErrorCode) -3066 );
    }  // end of debugging section  
    else   
#endif    

    if ( goodTimeoutValue ) {

      // Update the globals as needed
      if ( timeoutTdb().isStream() ) {   // it was a SET STREAM TIMEOUT
	if ( timeoutTdb().isReset() )  // it was a RESET
	  GlobalTimeouts->resetStreamTimeout(); 
	else                           // it was a SET (with a value)
	  GlobalTimeouts->setStreamTimeout(timeoutValue);
      }
      else {                     // setting a LOCK TIMEOUT
	// TBD =============>>> Check if FORALL string includes CAT.SCH ......
	if ( theTableName_[0] == '*' ) { // For all tables
	  if ( timeoutTdb().isReset() )  // it was a RESET
	    GlobalTimeouts->resetAllLockTimeout();
	  else GlobalTimeouts->setAllLockTimeout(timeoutValue);
	}
	else {  // per specific table
	  if ( timeoutTdb().isReset() )  // it was a RESET
	    GlobalTimeouts->resetTableLockTimeout( theTableName_ );
	  else GlobalTimeouts->setTableLockTimeout(theTableName_,timeoutValue);
	}
      }

      // execution of every SET TIMEOUT stmt increments the change counter !!
      currContext->incrementTimeoutChangeCounter();

      // clear up (i.e. deallocate) the global timeout data, if possible
      if ( GlobalTimeouts->noLockTimeoutsSet() &&
	   ! GlobalTimeouts->isStreamTimeoutSet() )
	currContext->clearTimeoutData();

    } // end of if ( goodTimeoutValue )

    /**********  at this point the actual work is done  ******************/
      
    // all ok. Return EOF.
    ex_queue_entry * up_entry = qparent_.up->getTailEntry();
      
    up_entry->upState.parentIndex = 
      pentry_down->downState.parentIndex;
      
    up_entry->upState.setMatchNo(0);
    up_entry->upState.status = ex_queue::Q_NO_DATA;
      
    // insert into parent
    qparent_.up->insert();
    
    qparent_.down->removeHead();
  }  
  return WORK_OK;
}
LmResult LmRoutineCppObj::invokeRoutineMethod(
     /* IN */     tmudr::UDRInvocationInfo::CallPhase phase,
     /* IN */     const char   *serializedInvocationInfo,
     /* IN */     Int32         invocationInfoLen,
     /* OUT */    Int32        *invocationInfoLenOut,
     /* IN */     const char   *serializedPlanInfo,
     /* IN */     Int32         planInfoLen,
     /* IN */     Int32         planNum,
     /* OUT */    Int32        *planInfoLenOut,
     /* IN */     char         *inputParamRow,
     /* IN */     Int32         inputParamRowLen,
     /* OUT */    char         *outputRow,
     /* IN */     Int32         outputRowLen,
     /* IN/OUT */ ComDiagsArea *da)
{
  LmResult result = LM_OK;

  // initialize out parameters
  *invocationInfoLenOut = 0;
  *planInfoLenOut = 0;

  // some parameter checks
  if (invocationInfoLen <= 0 &&
      invocationInfo_ == NULL)
    {
      // we need to have an Invocation info
      *da << DgSqlCode(-LME_OBJECT_INTERFACE_ERROR)
          << DgString0(getNameForDiags())
          << DgString1(tmudr::UDRInvocationInfo::callPhaseToString(
                            tmudr::UDRInvocationInfo::COMPILER_INITIAL_CALL))
          << DgString2("LmRoutineCppObj::invokeRoutineMethod()")
          << DgString3("Missing UDRInvocationInfo");
    }

  try
    {
      if (invocationInfoLen > 0)
        {
          if (invocationInfo_ == NULL)
            invocationInfo_ = new tmudr::UDRInvocationInfo;

          // unpack the invocation info
          invocationInfo_->deserializeObj(serializedInvocationInfo,
                                          invocationInfoLen);
        }

      if (planInfoLen > 0)
        {
          if (!planInfos_.used(planNum))
            planInfos_.insertAt(planNum, new tmudr::UDRPlanInfo(invocationInfo_,
                                                                planNum));

          // unpack the invocation info
          planInfos_[planNum]->deserializeObj(serializedPlanInfo,
                                              planInfoLen);
        }

      // some parameter checks
      if (inputParamRowLen < inputParamRowLen_)
        return LM_ERR;
      // test to do for scalar UDFs
      // if (outputRowLen < invocationInfo_->out().getRecordLength())
      //   return LM_ERR;

      if (inputParamRow && inputParamRowLen_ > 0)
        // copy parameter row
        memcpy(invocationInfo_->par().getRowPtr(), inputParamRow, inputParamRowLen_);

      invocationInfo_->callPhase_ = phase;
      switch (phase)
        {
        case tmudr::UDRInvocationInfo::COMPILER_INITIAL_CALL:
          if (invocationInfo_->getDebugFlags() &
              tmudr::UDRInvocationInfo::PRINT_INVOCATION_INFO_INITIAL)
            invocationInfo_->print();

          if (invocationInfo_->getDebugFlags() &
              tmudr::UDRInvocationInfo::DEBUG_INITIAL_COMPILE_TIME_LOOP)
            if (invocationInfo_->getSessionUser() == ComUser::getRootUserName())
              interfaceObj_->debugLoop();
            else if (da)
              *da << DgSqlCode(1260); // warning, only root user can debug

          interfaceObj_->describeParamsAndColumns(*invocationInfo_);
          break;

        case tmudr::UDRInvocationInfo::COMPILER_DATAFLOW_CALL:
          interfaceObj_->describeDataflowAndPredicates(*invocationInfo_);
          break;

        case tmudr::UDRInvocationInfo::COMPILER_CONSTRAINTS_CALL:
          interfaceObj_->describeConstraints(*invocationInfo_);
          break;

        case tmudr::UDRInvocationInfo::COMPILER_STATISTICS_CALL:
          interfaceObj_->describeStatistics(*invocationInfo_);
          break;

        case tmudr::UDRInvocationInfo::COMPILER_DOP_CALL:
          interfaceObj_->describeDesiredDegreeOfParallelism(
               *invocationInfo_,
               *planInfos_[planNum]);
          break;

        case tmudr::UDRInvocationInfo::COMPILER_PLAN_CALL:
          interfaceObj_->describePlanProperties(*invocationInfo_,
                                                *planInfos_[planNum]);
          break;

        case tmudr::UDRInvocationInfo::COMPILER_COMPLETION_CALL:
          interfaceObj_->completeDescription(*invocationInfo_,
                                             *planInfos_[planNum]);
          if (invocationInfo_->getDebugFlags() &
              tmudr::UDRInvocationInfo::PRINT_INVOCATION_INFO_END_COMPILE)
            {
              invocationInfo_->print();
              printf("\n");
              for (CollIndex i=0; i<planInfos_.getUsedLength(); i++)
                if (planInfos_.used(i))
                  {
                    if (i == planNum)
                      printf("++++++++++ Chosen plan: ++++++++++\n");
                    else
                      printf("-------- Plan not chosen: --------\n");
                    planInfos_[i]->print();
                  }
            }

          break;

        case tmudr::UDRInvocationInfo::RUNTIME_WORK_CALL:
          {
            if (invocationInfo_->getDebugFlags() &
                tmudr::UDRInvocationInfo::PRINT_INVOCATION_INFO_AT_RUN_TIME)
              {
                invocationInfo_->print();
                planInfos_[planNum]->print();
              }

            if ((invocationInfo_->getDebugFlags() &
                 tmudr::UDRInvocationInfo::DEBUG_INITIAL_RUN_TIME_LOOP_ALL) ||
                (invocationInfo_->getDebugFlags() &
                 tmudr::UDRInvocationInfo::DEBUG_INITIAL_RUN_TIME_LOOP_ONE &&
                 invocationInfo_->getMyInstanceNum() == 0))
              interfaceObj_->debugLoop();

            interfaceObj_->processData(*invocationInfo_,
                                       *planInfos_[planNum]);

            if (result == LM_OK)
              {
                if (invocationInfo_->getDebugFlags() & tmudr::UDRInvocationInfo::TRACE_ROWS)
                  printf("(%d) Emitting EOD\n",
                         invocationInfo_->getMyInstanceNum());

                // call emitRow to indicate EOD, something the
                // C interface would do inside the UDF
                SQLUDR_Q_STATE qstate = SQLUDR_Q_EOD;

                (*interfaceObj_->emitRowPtr_)(
                     invocationInfo_->out().getRowPtr(),
                     0,
                     &qstate);
              }
          }
          break;

        default:
          *da << DgSqlCode(-11111)
              << DgString0("Invalid call phase in LmRoutineCppObj::invokeRoutineMethod()");

          result = LM_ERR;
          break;
        
        }

      // return length of updated invocation and plan info for
      // compile-time phases
      if (invocationInfo_ &&
          phase < tmudr::UDRInvocationInfo::RUNTIME_WORK_CALL)
        {
          *invocationInfoLenOut = invocationInfo_->serializedLength();
          if (planInfos_.used(planNum))
            *planInfoLenOut = planInfos_[planNum]->serializedLength();
        }
    }
  catch (tmudr::UDRException e)
    {
      // Check the returned SQLSTATE value and raise appropriate
      // SQL code. Valid SQLSTATE values begin with "38" except "38000"
      const char *sqlState = e.getSQLState();

      if ((strncmp(sqlState, "38", 2) == 0) &&
          (strncmp(sqlState, "38000", 5) != 0))
        {
          *da << DgSqlCode(-LME_CUSTOM_ERROR)
              << DgString0(e.getMessage().c_str())
              << DgString1(sqlState);
          *da << DgCustomSQLState(sqlState);
        }
      else
        {
          *da << DgSqlCode(-LME_UDF_ERROR)
              << DgString0(invocationInfo_->getUDRName().c_str())
              << DgString1(sqlState)
              << DgString2(e.getMessage().c_str());
        }
      result = LM_ERR;
    }
  catch (...)
    {
      *da << DgSqlCode(-LME_OBJECT_INTERFACE_ERROR)
          << DgString0(getNameForDiags())
          << DgString1(invocationInfo_->callPhaseToString(phase))
          << DgString2("LmRoutineCppObj::invokeRoutineMethod()")
          << DgString3("general exception");
      result = LM_ERR;
    }

  invocationInfo_->callPhase_ =
    tmudr::UDRInvocationInfo::UNKNOWN_CALL_PHASE;

  return result;
}
Beispiel #25
0
void processALoadMessage(UdrGlobals *UdrGlob,
                         UdrServerReplyStream &msgStream,
                         UdrLoadMsg &request,
                         IpcEnvironment &env)
{
  const char *moduleName = "processALoadMessage";
  char errorText[MAXERRTEXT];

  ComDiagsArea *diags = ComDiagsArea::allocate(UdrGlob->getIpcHeap());

  doMessageBox(UdrGlob, TRACE_SHOW_DIALOGS,
               UdrGlob->showLoad_, moduleName);

  NABoolean showLoadLogic = (UdrGlob->verbose_ &&
                             UdrGlob->traceLevel_ >= TRACE_IPMS &&
                             UdrGlob->showLoad_);

  if (showLoadLogic)
  {
    ServerDebug("[UdrServ (%s)] Processing load request", moduleName);
  }

  // UDR_LOAD message always comes with transaction and they are out
  // side Enter Tx and Exit Tx pair. Make sure we are under correct
  // transaction.
  msgStream.activateCurrentMsgTransaction();

  //
  // Check to see if the incoming UDR handle has already been seen
  //
  NABoolean handleAlreadyExists = FALSE;
  SPInfo *sp = UdrGlob->getSPList()->spFind(request.getHandle());
  if (sp)
  {
    handleAlreadyExists = TRUE;
    if (showLoadLogic)
    {
      ServerDebug("    Duplicate handle arrived");
      ServerDebug("    SPInfoState is %s", sp->getSPInfoStateString());
    }

    if (sp->getSPInfoState() != SPInfo::UNLOADING)
    {
      //
      // An SPInfo exists but it is not one of the token instances to
      // represent an out-of-sequence LOAD/UNLOAD. This is an internal
      // error. Something has been botched in the message protocol.
      //
      char buf[100];
      convertInt64ToAscii(request.getHandle(), buf);
      *diags << DgSqlCode(-UDR_ERR_DUPLICATE_LOADS);
      *diags << DgString0(buf);
    }
    else
    {
      // The LOAD/UNLOAD requests for this handle arrived
      // out-of-sequence. Nothing to do at this point. An empty reply
      // will be generated later in this function.
    }
  }

  if (!handleAlreadyExists)
  {
    if (!UdrHandleIsValid(request.getHandle()))
    {
      *diags << DgSqlCode(-UDR_ERR_MISSING_UDRHANDLE);
      *diags << DgString0("Load Message");
    }
    else
    {
      //
      // First process the metadata in the LOAD requests and then
      // contact Language Manager to load the SP.
      //
      sp = processLoadParameters(UdrGlob, request, *diags);
      
      if (showLoadLogic)
      {
        ServerDebug("[UdrServ (%s)]  About to call LM::getRoutine",
                    moduleName);
      }
      
      if (sp == NULL)
      {
        *diags << DgSqlCode(-UDR_ERR_UNABLE_TO_ALLOCATE_MEMORY);
        *diags << DgString0("SPInfo");
      }
      else
      {
        UdrGlob->setCurrSP(sp);
        LmRoutine *lmRoutine;
        LmResult lmResult;
        LmLanguageManager *lm =
          UdrGlob->getOrCreateLM(lmResult, sp->getLanguage(), diags);
        LmHandle emitRowFuncPtr;

        if (sp->getParamStyle() == COM_STYLE_CPP_OBJ)
          emitRowFuncPtr = (LmHandle)&SpInfoEmitRowCpp;
        else
          emitRowFuncPtr = (LmHandle)&SpInfoEmitRow;
        
        if (lm)
        {
          if (sp->getParamStyle() == COM_STYLE_JAVA_OBJ ||
              sp->getParamStyle() == COM_STYLE_CPP_OBJ)
            {
              lmResult = lm->getObjRoutine(
                   request.getUDRSerInvocationInfo(),
                   request.getUDRSerInvocationInfoLen(),
                   request.getUDRSerPlanInfo(),
                   request.getUDRSerPlanInfoLen(),
                   sp->getLanguage(),
                   sp->getParamStyle(),
                   sp->getExternalName(),
                   sp->getContainerName(),
                   sp->getExternalPathName(),
                   sp->getLibrarySqlName(),
                   &lmRoutine,
                   diags);

              if (lmRoutine)
                {
                  LmRoutineCppObj *objRoutine =
                    static_cast<LmRoutineCppObj *>(lmRoutine);

                  if (sp->getParamStyle() == COM_STYLE_CPP_OBJ)
                    // set function pointers for functions provided
                    // by tdm_udrserv
                    objRoutine->setFunctionPtrs(SpInfoGetNextRow,
                                                SpInfoEmitRowCpp);

                  // add items to the UDRInvocationInfo that are not
                  // known at compile time (total # of instances is
                  // kind of known, but we want to give the executor a
                  // chance to change it)
                  lmRoutine->setRuntimeInfo(request.getParentQid(),
                                            request.getNumInstances(),
                                            request.getInstanceNum());

#ifndef NDEBUG
                  int debugLoop = 2;

                  if (objRoutine->getInvocationInfo()->getDebugFlags() &
                      tmudr::UDRInvocationInfo::DEBUG_LOAD_MSG_LOOP)
                    debugLoop = 1;
                  // go into a loop to allow the user to attach a debugger,
                  // if requested, set debugLoop = 2 in the debugger to get out
                  while (debugLoop < 2)
                    debugLoop = 1-debugLoop;
#endif

                }
            }
          else
            lmResult = lm->getRoutine(sp->getNumParameters(),
                                      sp->getLmParameters(),
                                      sp->getNumTables(),
                                      sp->getLmTables(),
                                      sp->getReturnValue(),
                                      sp->getParamStyle(),
                                      sp->getTransactionAttrs(),
                                      sp->getSQLAccessMode(),
                                      sp->getParentQid(),
                                      sp->getRequestRowSize(),
                                      sp->getReplyRowSize(),
                                      sp->getSqlName(),
                                      sp->getExternalName(),
                                      sp->getRoutineSig(),
                                      sp->getContainerName(),
                                      sp->getExternalPathName(),
                                      sp->getLibrarySqlName(),
                                      UdrGlob->getCurrentUserName(),
                                      UdrGlob->getSessionUserName(),
                                      sp->getExternalSecurity(),
                                      sp->getRoutineOwnerId(),
                                      &lmRoutine,
                                      (LmHandle)&SpInfoGetNextRow,
                                      emitRowFuncPtr,
                                      sp->getMaxNumResultSets(),
                                      diags);
        }
        
        if (lmResult == LM_OK)
        {
          if (lmRoutine == NULL)
          {
            *diags << DgSqlCode(-UDR_ERR_MISSING_LMROUTINE);
            *diags << DgString0("error: returned a null LM handle");
            *diags << DgInt1((Int32)0);
          }
          else
          {
            sp->setLMHandle(lmRoutine);

	    // Retrieve any optional data from UdrLoadMsg.
	    copyRoutineOptionalData(request, sp);

            reportLoadResults(UdrGlob, sp, lmRoutine);
            sp->setSPInfoState(SPInfo::LOADED);
          }

        } // lmResult == LM_OK

        if (showLoadLogic)
        {
          if (lmResult == LM_OK)
          {
            sprintf(errorText,
                    "[UdrServ (%.30s)]  LM::getRoutine was successful.",
                    moduleName);
          }
          else
          {
            sprintf(errorText,
                    "[UdrServ (%.30s)]  LM::getRoutine resulted in error.",
                    moduleName);
          }
          ServerDebug(errorText);
          doMessageBox(UdrGlob, TRACE_SHOW_DIALOGS,
                       UdrGlob->showMain_, errorText);
        }

        if (sp && !(sp->isLoaded()))
        {
          sp->setSPInfoState(SPInfo::LOAD_FAILED);
        }

      } // if (sp == NULL) else ...
    } // if (handle is not valid) else ...
  } // !handleAlreadyExists

  // build a reply and send it
  msgStream.clearAllObjects();

  UdrLoadReply *reply = new (UdrGlob->getIpcHeap())
    UdrLoadReply(UdrGlob->getIpcHeap());

  if (reply == NULL)
  {  // no reply buffer build...
    controlErrorReply(UdrGlob, msgStream, UDR_ERR_MESSAGE_PROCESSING,
                      INVOKE_ERR_NO_REPLY_BUFFER, NULL);
    return;
  }

  // Only return a valid UDR Handle if diagnostics are not present and
  // no LM errors occurred. We also return a valid handle if this LOAD
  // arrived out-of-sequence after the UNLOAD and no diagnostics have
  // been generated yet.
  if (diags && diags->getNumber() > 0)
  {
    reply->setHandle(INVALID_UDR_HANDLE);
  }
  else if (sp)
  {
    if (sp->isLoaded() || handleAlreadyExists)
    {
      reply->setHandle(sp->getUdrHandle());
    }
    else
    {
      reply->setHandle(INVALID_UDR_HANDLE);
    }
  }

  msgStream << *reply;

  if (diags && diags->getNumber() > 0)
  {
    msgStream << *diags;
    UdrGlob->numErrUDR_++;
    UdrGlob->numErrSP_++;
    UdrGlob->numErrLoadSP_++;
    if (showLoadLogic)
      dumpDiagnostics(diags, 2);
  }

  if (showLoadLogic)
  {
    ServerDebug("[UdrServ (%s)] About to send LOAD reply", moduleName);
  }

#ifdef NA_DEBUG_C_RUNTIME
  if (UdrGlob && UdrGlob->getJavaLM())
  {
    sleepIfPropertySet(*(UdrGlob->getJavaLM()),
                       "MXUDR_LOAD_DELAY", diags);
  }
#endif // NA_DEBUG_C_RUNTIME

  sendControlReply(UdrGlob, msgStream, sp);

  if (diags)
  {
    diags->decrRefCount();
  }

  reply->decrRefCount();

} // processALoadMessage
LmResult LmRoutineCppObj::getRoutineInvocationInfo(
     /* IN/OUT */ char         *serializedInvocationInfo,
     /* IN */     Int32         invocationInfoMaxLen,
     /* OUT */    Int32        *invocationInfoLenOut,
     /* IN/OUT */ char         *serializedPlanInfo,
     /* IN */     Int32         planInfoMaxLen,
     /* IN */     Int32         planNum,
     /* OUT */    Int32        *planInfoLenOut,
     /* IN/OUT */ ComDiagsArea *da)
{
  LmResult result = LM_OK;

  // Retrieve updated invocation and plan info.
  // The invokeRoutineMethod provided the required buffer
  // space, so there is no excuse for having insufficient
  // buffer when calling this, and doing so will raise
  // an exception in the try block below.
  try
    {
      if (invocationInfo_ && invocationInfoMaxLen > 0)
        {
          char *tempiibuf = serializedInvocationInfo;
          int tempiilen   = invocationInfoMaxLen;
          *invocationInfoLenOut = invocationInfo_->serialize(
               tempiibuf, tempiilen);
        }
      else
        *invocationInfoLenOut = 0;

      if (planInfos_.used(planNum) && planInfoMaxLen > 0)
        {
          char *temppibuf = serializedPlanInfo;
          int temppilen   = planInfoMaxLen;
          *planInfoLenOut = planInfos_[planNum]->serialize(
               temppibuf, temppilen);
        }
      else
        *planInfoLenOut = 0;
    }
  catch (tmudr::UDRException e)
    {
      // this UDRException is generated by Trafodion code and
      // it is an internal error to fail serializing the structs,
      // even though the user might have caused it by corrupting
      // these structs
      *da << DgSqlCode(-LME_OBJECT_INTERFACE_ERROR)
          << DgString0(getNameForDiags())
          << DgString1(invocationInfo_->callPhaseToString(invocationInfo_->getCallPhase()))
          << DgString2("LmRoutineCppObj::getRoutineInvocationInfo()")
          << DgString3(e.getMessage().c_str());
      result = LM_ERR;
    }
  catch (...)
    {
      *da << DgSqlCode(-LME_OBJECT_INTERFACE_ERROR)
          << DgString0(getNameForDiags())
          << DgString1(invocationInfo_->callPhaseToString(invocationInfo_->getCallPhase()))
          << DgString2("LmRoutineCppObj::getRoutineInvocationInfo()")
          << DgString3("general exception");
      result = LM_ERR;
    }

  return result;
}
Beispiel #27
0
// ----------------------------------------------------------------------------
// method:  unregisterUser
//
// This method removes a user from the database
//
// Input:  parse tree containing a definition of the user
// Output: the global diags area is set up with the result
// ----------------------------------------------------------------------------
void CmpSeabaseDDLuser::unregisterUser (StmtDDLRegisterUser * pNode)
{
  try
  {
    verifyAuthority();

    // CASCADE option not yet supported
    if (pNode->getDropBehavior() == COM_CASCADE_DROP_BEHAVIOR)
    {
      *CmpCommon::diags() << DgSqlCode (-CAT_ONLY_SUPPORTING_RESTRICT_DROP_BEHAVIOR);
       DDLException excp (CAT_ONLY_SUPPORTING_RESTRICT_DROP_BEHAVIOR, NULL, 0);
       excp.throwException();
    }

    // Verify that the specified user name is not reserved
    // TBD - add the isCatman concept
    if (isAuthNameReserved(pNode->getDbUserName()))
    {
      *CmpCommon::diags() << DgSqlCode (-CAT_AUTH_NAME_RESERVED)
                          << DgString0(pNode->getDbUserName().data());
       DDLException excp (CAT_AUTH_NAME_RESERVED, NULL, 0);
       excp.throwException();
    }

    // set up class members from parse node
    // Read the row from the AUTHS table
    const NAString dbUserName(pNode->getDbUserName());
    NAString sysCat = CmpSeabaseDDL::getSystemCatalogStatic();
    char buf[1000];
    str_sprintf(buf, "select auth_id, auth_db_name, auth_ext_name, auth_type, auth_creator, auth_is_valid, auth_create_time, auth_redef_time from %s.\"%s\".%s where auth_db_name = '%s' ",
              sysCat.data(), SEABASE_MD_SCHEMA, SEABASE_AUTHS, dbUserName.data());

    NAString cmd (buf);
    if (!selectExactRow(cmd))
    {
      // TBD - add CQD to return okay if user has already been unregistered
      *CmpCommon::diags() << DgSqlCode(-CAT_USER_NOT_EXIST)
                          << DgString0(dbUserName.data());
       DDLException excp (CAT_USER_NOT_EXIST, NULL, 0);
       excp.throwException();
    }

    // Cannot unregister immutable users
    if (isAuthImmutable())
    {
      *CmpCommon::diags() << DgSqlCode(-1387);
       DDLException excp (1387, NULL, 0);
       excp.throwException();
    }

    // TBD, check to see if the user owns anything before removing

    // delete the row
    deleteRow(getAuthDbName());
  }
  catch (...)
  {
    // At this time, an error should be in the diags area.
    // If there is no error, set up an internal error
    Int32 numErrors = CmpCommon::diags()->getNumber(DgSqlCode::ERROR_);
    if (numErrors == 0)
      *CmpCommon::diags() << DgSqlCode (-CAT_INTERNAL_EXCEPTION_ERROR)
                          << DgInt0(__LINE__)
                          << DgString0("unregister user");

  }
}
Beispiel #28
0
void ex_queue::injectErrorOrCancel()
{
#ifdef _DEBUG
  ex_queue_entry *qe = getQueueEntry(tail_-1);

  // DO the ol' switcheroo, but not every time.
  ULng32 freq = insertSubtask_->getTcb()->getGlobals()->getInjectErrorAtQueue();
  if (freq == 0)
      return;
  if (upDown_ == UP_QUEUE)
    {
       if ((rand() & (freq-1)) != 0)
         return;
        NABoolean needsError = FALSE;
        switch (qe->upState.status)
        {
        case Q_OK_MMORE:
          {
            needsError = TRUE;
            qe->upState.status = Q_SQLERROR;
            cerr << "Converting a Q_OK_MMORE to a Q_SQLERROR, from "
                 << NodeTypeToString(unblockSubtask_->getTcb()->getNodeType())
                 << "(" << unblockSubtask_->getTcb() << ")" 
                 << " to "
                 << NodeTypeToString(insertSubtask_->getTcb()->getNodeType())
                 << "(" << insertSubtask_->getTcb() << ")" 
                 << endl;
            break;
          }
        case Q_NO_DATA:
          if (!isFull())
            {
              needsError = TRUE;
              qe->upState.status = Q_SQLERROR;
              ex_queue_entry *newQNODATA = getTailEntry();
              newQNODATA->upState = qe->upState;
              newQNODATA->upState.status  = Q_NO_DATA;
              newQNODATA->getAtp()->copyAtp(qe->getAtp());
              tail_++;
              cerr << "Injecting a Q_SQLERROR before a Q_NO_DATA, from " 
                 << NodeTypeToString(unblockSubtask_->getTcb()->getNodeType())
                 << "(" << unblockSubtask_->getTcb() << ")" 
                 << " to "
                 << NodeTypeToString(insertSubtask_->getTcb()->getNodeType())
                 << "(" << insertSubtask_->getTcb() << ")" 
                 << endl;
            }
          break;
        default:
            break;
        } 
        if (needsError)
          {
            ComDiagsArea * da = qe->getDiagsArea();
            if (!da) 
              da = ComDiagsArea::allocate(insertSubtask_->getTcb()->getHeap());
            else
              da = da->copy();
            qe->setDiagsArea(da);

            *da << DgSqlCode(-EXE_ERROR_INJECTED)
                << DgString0(__FILE__)
                << DgInt0(__LINE__);
          }
    }
#endif

  return;
}
void EspNewIncomingConnectionStream::actOnReceive(IpcConnection *connection)
{
  // check for OS errors
  if (getState() == ERROR_STATE)
  {
    ex_assert(FALSE,"Error while receiving first message from client");
  }

  // check for protocol errors
  bool willPassTheAssertion = 
             (getType() == IPC_MSG_SQLESP_DATA_REQUEST OR
              getType() == IPC_MSG_SQLESP_CANCEL_REQUEST) AND
              getVersion() == CurrEspRequestMessageVersion AND
              moreObjects();
  if (!willPassTheAssertion)
  {
    char *doCatchBugCRx = getenv("ESP_BUGCATCHER_CR_NONUMBER");
    if (!doCatchBugCRx ||
        *doCatchBugCRx != '0')
    {
      connection->dumpAndStopOtherEnd(true, false);
      environment_->getControlConnection()->
        castToGuaReceiveControlConnection()->
        getConnection()->dumpAndStopOtherEnd(true, false);
    }
  }

  ex_assert((getType() == IPC_MSG_SQLESP_DATA_REQUEST OR
             getType() == IPC_MSG_SQLESP_CANCEL_REQUEST) AND
	    getVersion() == CurrEspRequestMessageVersion AND
	    moreObjects(),
	    "Invalid first message from client");

  // take a look at the type of the first object in the message
  IpcMessageObjType nextObjType = getNextObjType();
  switch (nextObjType)
  {
    case ESP_OPEN_HDR:
    case ESP_LATE_CANCEL_HDR:
      {
        ExFragKey key;
        Lng32 remoteInstNum;
        NABoolean isParallelExtract = false; 

        // peek at the message header to see for whom it is
        if (nextObjType == ESP_OPEN_HDR)
        {
          ExEspOpenReqHeader reqHdr((NAMemory *) NULL);
	   
	  *this >> reqHdr;
	  key = reqHdr.key_;
	  remoteInstNum = reqHdr.myInstanceNum_;
	  if (reqHdr.getOpenType() == ExEspOpenReqHeader::PARALLEL_EXTRACT) 
          {
            isParallelExtract = true;
	  }
	}
        else
	{
          // note that the late cancel request may or may not
	  // arrive as the first request (only in the former case
	  // will we reach here)
	  ExEspLateCancelReqHeader reqHdr((NAMemory *) NULL);
	   
	  *this >> reqHdr;
	  key = reqHdr.key_;
	  remoteInstNum = reqHdr.myInstanceNum_;
	}

        if (!isParallelExtract) 
        {
          ExFragInstanceHandle handle =
	    espFragInstanceDir_->findHandle(key);

	  if (handle != NullFragInstanceHandle)
	  {
            // the send bottom node # myInstanceNum of this downloaded fragment
            // is the true recipient of this open request
            ex_split_bottom_tcb * receivingTcb =
              espFragInstanceDir_->getTopTcb(handle);
            ex_send_bottom_tcb *receivingSendTcb =
              receivingTcb->getSendNode(remoteInstNum);

            // Check the connection for a co-located client, and if so,
            // tell the split bottom, because it may prefer this send 
            // bottom when using skew buster uniform distribution.
            if (espFragInstanceDir_->
                  getEnvironment()->
                  getMyOwnProcessId(IPC_DOM_GUA_PHANDLE).match(
                    connection->getOtherEnd().getNodeName(),
                    connection->getOtherEnd().getCpuNum()))
              receivingTcb->setLocalSendBottom(remoteInstNum);

            // Portability note for the code above: we pass IPC_DOM_GUA_PHANDLE
            // for IpcEnvironment::getMyOwnProcessId, even though that method
            // can be called with the default param (IpcNetworkDomain 
            // IPC_DOM_INVALID).  In fact it would  probably be better 
            // to call the object without specifying the IpcNetworkDomain so
            // that it can decide for itself what domain it is using.
            // But there is a problem with the Windows implementation
            // of IpcEnvironment::getMyOwnProcessId, it seems to assume
            // that its domain is IPC_DOM_INTERNET and so this will 
            // cause the botch of an assertion that its control connection 
            // (which is type EspGuaControlConnection) can be cast to a 
            // SockControlConnection.  When this problem is fixed, the 
            // IPC_DOM_GUA_PHANDLE param above can be removed.  Also,
            // when this code is ported to run it a domain other than
            // "guardian", it will be necessary to fix this and to
            // fix IpcEnvironment::getMyOwnProcessId to work properly on
            // windows.

            receivingSendTcb->setClient(connection);
            receivingSendTcb->routeMsg(*this);
          }
	  else
	  {
            connection->dumpAndStopOtherEnd(true, false);
	    ex_assert(FALSE,"entry not found, set diagnostics area and reply");
	  }

        } // normal case, not parallel extract

        else 
        {
          // The OPEN request is from a parallel extract consumer. The
          // incoming request contains a user ID which we will compare
          // against the current user ID for this ESP.

          // NOTE: The user ID for the extract security check is
          // currently sent and compared as a C string. On Linux it is
          // possible to send and compare integers which would lead to
          // simpler code. The code to send/compare strings is still
          // used because it works on all platforms.

          char errorStr[150];

	  // check if next msg is of securityInfo type. 
          ex_assert(moreObjects(), "expected object not received");
          ex_assert(getNextObjType() == ESP_SECURITY_INFO,
	            "received message for unknown message type");
          
	  // unpack security info
	  ExMsgSecurityInfo secInfo(environment_->getHeap());
	  *this >> secInfo;

          // Get the auth ID of this ESP in text form and compare it
          // to the auth ID that arrived in the message. Skip this
          // step in the debug build if an environment variable is
          // set.
          NABoolean doAuthIdCheck = TRUE;
          Int32 status = 0;
#ifdef NA_DEBUG_C_RUNTIME
          const char *envvar = getenv("NO_EXTRACT_AUTHID_CHECK");
          if (envvar && envvar[0])
            doAuthIdCheck = FALSE;
#endif
          if (doAuthIdCheck)
          {
            // Get user ID from ExMsgSecurityInfo -> (secUserID)
            // the user ID is the integer value made into a string
            // Convert it back into its integer value
            short userIDLen = (short) str_len(secInfo.getAuthID());
            Int32 secUserID = str_atoi(secInfo.getAuthID(), userIDLen);

            // Get the current user ID
            Int32 curUserID = ComUser::getSessionUser(); 

            // Report an error if the user ID is not valid
            if (curUserID == NA_UserIdDefault || secUserID == NA_UserIdDefault)
            {
              str_cpy_c(errorStr,
                        "Producer ESP could not authenticate the consumer, "
                        "no valid current user.");
              status = -1;
            }

            // Make sure user id passed in ExMsgSecurityInfo matches
            // the user id associated with the current session

#if defined(NA_DEBUG_C_RUNTIME)
            NABoolean doDebug = (getenv("DBUSER_DEBUG") ? TRUE : FALSE);
            if (doDebug)
              printf("[DBUSER:%d] ESP extract user ID: "
                     "local [%d], msg [%d]\n",
                     (int) getpid(), curUserID, secUserID);
#endif

              // Compare user ID, Report an error, if comparison fails
              if (curUserID != secUserID)
              {
                str_cpy_c(errorStr,
                          "Producer ESP could not authenticate the consumer, "
                          "user named passed in ExMsgSecurityInfo is not the "
                          "current user");
                status = -1;
              }

          } // if (doAuthIdCheck)
		   
          // get the split bottom TCB that matches the securityKey
          ex_split_bottom_tcb *receivingTcb = NULL;
          if (status == 0) 
          {
            receivingTcb = espFragInstanceDir_->getExtractTop(secInfo.getSecurityKey());
            if (receivingTcb == NULL) 
            {
              str_cpy_c(errorStr, "Producer ESP could not locate extract node");
              status = -1;
            }
          }

	  // get the sendBottom TCB if not already connected to a client
	  ex_send_bottom_tcb *receivingSendTcb = NULL;
	  if (status == 0)
	  {
	    receivingSendTcb = receivingTcb->getConsumerSendBottom();
	    if (receivingSendTcb == NULL) 
	    {
	      str_cpy_c(errorStr, "Producer ESP already connected to a client");
	      status = -1;
	    }
	  }

          // send the error message to the consumer 
	  if (status != 0) 
	  {
            clearAllObjects();
            setType(IPC_MSG_SQLESP_DATA_REPLY);

            NAMemory *heap = environment_->getHeap();

	    IpcMessageObj* baseObj =
	      new(heap)IpcMessageObj(IPC_SQL_DIAG_AREA, CurrEspReplyMessageVersion);
	    *this << *baseObj;

	    // prepare proper error message
	    char phandle[100];
	    MyGuaProcessHandle myHandle;
            myHandle.toAscii(phandle, 100);

	    ComDiagsArea *diags = ComDiagsArea::allocate(heap);
            *diags << DgSqlCode(-EXE_PARALLEL_EXTRACT_OPEN_ERROR)
                   << DgString0(phandle)
                   << DgString1(errorStr);
	    *this  << *diags;

	    diags->decrRefCount();

            send(TRUE /* TRUE indicates waited */);
          }

          // if everything okay, then make the connection
	  if (status == 0) 
          {
            receivingSendTcb->setClient(connection);
            receivingSendTcb->routeMsg(*this);
          }
        } // parallel extract case
      } // open or cancel header
Int32 SqlciEnv::executeCommands(InputStmt *& input_stmt)
{
   Int32 retval = 0;
   Int32 ignore_toggle = 0;
   SqlciNode * sqlci_node = 0;

   NABoolean inputPassedIn = (input_stmt ? TRUE : FALSE);

   try
   {

     while (!retval)
      {
	 total_opens = 0;
	 total_closes = 0;

	 // This is new'd here, deleted when history buffer fills up,
	 // in SqlciStmts::add/StmtEntry::set
	 if (NOT inputPassedIn)
	   input_stmt = new InputStmt(this);



	 Int32 read_error = 0;
	 if (NOT inputPassedIn)
	   read_error = input_stmt->readStmt(NULL/*i.e. input is stdin*/);

         prev_err_flush_input = 0;

	 if (cin.eof() || read_error == -99)
	   {
	       // allow the other thread to process
	       Sleep(50);				// milliseconds
	     if (!input_stmt->isEmpty())
	       {
		 // Unterminated statement in input file (redirected stdin).
		 // Make the parser emit an error message.
		 if (!isInteractiveSession())
		   input_stmt->display((UInt16)0);
		 input_stmt->logStmt();
		 input_stmt->syntaxErrorOnEof();
		 displayDiagnostics();
		 sqlci_DA.clear();
	       }
	     char command[10];
	     strcpy(command, ">>exit;");
	     if (!isInteractiveSession())
	       get_logfile()->WriteAll(command);
	     else if (get_logfile()->IsOpen())
#pragma nowarn(1506)   // warning elimination 
	       get_logfile()->Write(command, strlen(command));
#pragma warn(1506)  // warning elimination 
	     sqlci_parser(&command[2], &command[2], &sqlci_node,this);

	     if (sqlci_node)
	       {
		 retval = sqlci_node->process(this);
		 delete sqlci_node;
                 sqlci_node = NULL;
	       }
	   }
	 else
	   {
	     if (!isInteractiveSession())
	       input_stmt->display((UInt16)0);

	     if (logCommands())
	       get_logfile()->setNoLog(FALSE);
	     input_stmt->logStmt();
	     if (logCommands())
	       get_logfile()->setNoLog(TRUE);

	     if (!input_stmt->sectionMatches())
	       {
		 Int32 ignore_stmt = input_stmt->isIgnoreStmt();
		 if (ignore_stmt)
		   ignore_toggle = ~ignore_toggle;
		 if (ignore_stmt || ignore_toggle || input_stmt->ignoreJustThis())
		   {
		     // ignore until stmt following the untoggling ?ignore
		     sqlci_DA.clear();
		   }
		 else
		 {
		     getSqlciStmts()->add(input_stmt);
		     if (!read_error)
		     {
			retval = sqlci_parser(input_stmt->getPackedString(),
				   input_stmt->getPackedString(),
				   &sqlci_node, this);
			if (sqlci_node)
                        {
			  retval = sqlci_node->process(this);
			  delete sqlci_node;
                          sqlci_node = NULL;

			  if (retval == SQL_Canceled)
                            retval = 0;
			} else {
                          // pure MXCI synatax error. Reset retval
                            retval = 0;
                        }
		    }
                    if (retval > 0)
                    {
			if (!eol_seen_on_input)
			{
				prev_err_flush_input = -1;
			}
			retval = 0;
                    }

                 } // else
	    }// if
         } // else
	 if ( read_error == -20)
	 {
	    sqlci_DA << DgSqlCode(SQLCI_BREAK_RECEIVED, DgSqlCode::WARNING_);
	 }
         
         if (read_error == SqlciEnv::MAX_FRAGMENT_LEN_OVERFLOW && !eolSeenOnInput() )
           setPrevErrFlushInput();


        displayDiagnostics();
        sqlci_DA.clear(); // Clear the DiagnosticsArea for the next command...

	if (total_opens != total_closes)
	{
	    char buf[100];

	    sprintf(buf, "total opens = %d, total closes = %d", total_opens, total_closes);

#pragma nowarn(1506)   // warning elimination 
	    get_logfile()->WriteAll(buf, strlen(buf));
#pragma warn(1506)  // warning elimination 
	}

	// Delete the stmt if not one of those we saved on the history list
	if (!input_stmt->isInHistoryList())
	    delete input_stmt;
   
	if (inputPassedIn)
	  retval = 1;
    } // while
    if (retval == SQL_Canceled)
      return SQL_Canceled;
    else
      return 0;
   }
   catch(EHBreakException&)
   {
     sqlci_DA << DgSqlCode(SQLCI_BREAK_RECEIVED, DgSqlCode::WARNING_);
     displayDiagnostics();
     sqlci_DA.clear(); // Clear the DiagnosticsArea for the next command...

     if (sqlci_node)
       delete sqlci_node;
     sqlci_node = NULL;
     cin.clear();
     // NOTE: EnterCriticalSection has been done in ThrowBreakException()
     LeaveCriticalSection(&g_CriticalSection);
     return -1;
   }
   catch(...)
   {
      return 1;
   }

} // executeCommands