Esempio n. 1
0
NABoolean CmpSqlSession::validateVolatileSchemaName(NAString &schName)
{
  if (NOT schName.isNull())
    {
      ComSchemaName csn(schName);

      if (NOT csn.isValid())
	{
	  // Schema name $0~SchemaName is not valid.
	  *CmpCommon::diags() << DgSqlCode(-8009) 
			      << DgSchemaName(schName);
	  return FALSE;
	}

      Lng32 len = MINOF(strlen(csn.getSchemaNamePartAsAnsiString().data()),
		       strlen(COM_VOLATILE_SCHEMA_PREFIX));
      NAString upSch(csn.getSchemaNamePartAsAnsiString().data());
      upSch.toUpper();
      if ((NOT Get_SqlParser_Flags(ALLOW_VOLATILE_SCHEMA_IN_TABLE_NAME)) &&
	  (len > 0) &&
	  (strncmp(upSch.data(), COM_VOLATILE_SCHEMA_PREFIX, len) == 0))
	{
	  *CmpCommon::diags() << DgSqlCode(-4193) 
			      << DgString0(COM_VOLATILE_SCHEMA_PREFIX);
	  return FALSE;
	}
    }

  return TRUE;
}
//
// constructor
//
StmtDDLDropSchema::StmtDDLDropSchema(//const SchemaName & schemaName,
				     const ElemDDLSchemaName & aSchemaNameParseNode,
                                     ComDropBehavior dropBehavior,
                                     ComBoolean cleanupMode,
                                     ComBoolean dropObjectsOnly)
        : StmtDDLNode(DDL_DROP_SCHEMA),
          schemaQualName_(aSchemaNameParseNode.getSchemaName(), PARSERHEAP()),
          dropBehavior_(dropBehavior),
          cleanupMode_(cleanupMode),
          dropObjectsOnly_(dropObjectsOnly),
          dropIfExists_(FALSE),
          schemaName_(PARSERHEAP())
{
  if (schemaQualName_.getCatalogName().isNull())
  {
    schemaName_ = ToAnsiIdentifier(schemaQualName_.getSchemaName());
  }
  else
  {
    schemaName_ = ToAnsiIdentifier(schemaQualName_.getCatalogName()) + "." +
      ToAnsiIdentifier(schemaQualName_.getSchemaName());
  }

  // If the schema name specified is reserved name, users cannot drop them.
  // They can only be dropped internally.
  if ((! Get_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL)) &&
      (ComIsTrafodionReservedSchemaName(schemaQualName_.getSchemaName())))
    {
      // error.
      *SqlParser_Diags << DgSqlCode(-1430)
                       << DgSchemaName(schemaName_);
      
    }

}
// *****************************************************************************
// *                                                                           *
// * Function: dropOneTable                                                    *
// *                                                                           *
// *    Drops a table and all its dependent objects.                           *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <cliInterface>                  ExeCliInterface &               In       *
// *    is a reference to an Executor CLI interface handle.                    *
// *                                                                           *
// *  <catalogName>                   const char *                    In       *
// *    is the catalog of the table to drop.                                   *
// *                                                                           *
// *  <schemaName>                    const char *                    In       *
// *    is the schema of the table to drop.                                    *
// *                                                                           *
// *  <objectName>                    const char *                    In       *
// *    is the name of the table to drop.                                      *
// *                                                                           *
// *  <isVolatile>                    bool                            In       *
// *    is true if the object is volatile or part of a volatile schema.        *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: bool                                                             *
// *                                                                           *
// * true: Could not drop table or one of its dependent objects.               *
// * false: Drop successful or could not set CQD for NATable cache reload.     *
// *                                                                           *
// *****************************************************************************
static bool dropOneTable(
   ExeCliInterface & cliInterface,
   const char * catalogName, 
   const char * schemaName, 
   const char * objectName,
   bool isVolatile)
   
{

char buf [1000];

bool someObjectsCouldNotBeDropped = false;

char volatileString[20] = {0};
Lng32 cliRC = 0;

   if (isVolatile)
      strcpy(volatileString,"VOLATILE");

   if (ComIsTrafodionExternalSchemaName(schemaName))
     str_sprintf(buf,"DROP EXTERNAL TABLE \"%s\" FOR \"%s\".\"%s\".\"%s\" CASCADE",
                 objectName,catalogName,schemaName,objectName);
   else
     str_sprintf(buf,"DROP %s TABLE \"%s\".\"%s\".\"%s\" CASCADE",
                 volatileString,catalogName,schemaName,objectName);
 
ULng32 savedParserFlags = Get_SqlParser_Flags(0xFFFFFFFF);

   try
   {            
      Set_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL);
               
      cliRC = cliInterface.executeImmediate(buf);
   }
   catch (...)
   {
      // Restore parser flags settings to what they originally were
      Assign_SqlParser_Flags(savedParserFlags);
      
      throw;
   }
   
// Restore parser flags settings to what they originally were
   Set_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL);
   
   if (cliRC < 0 && cliRC != -CAT_OBJECT_DOES_NOT_EXIST_IN_TRAFODION)
      someObjectsCouldNotBeDropped = true;
   
// remove NATable entry for this table
   CorrName cn(objectName,STMTHEAP,schemaName,catalogName);

   ActiveSchemaDB()->getNATableDB()->removeNATable(cn,
     NATableDB::REMOVE_FROM_ALL_USERS, COM_BASE_TABLE_OBJECT);

   return someObjectsCouldNotBeDropped;
   
}
// Constructor that parses a 1-, 2-, or 3-part external (Ansi) name string
// and optionally applies default catalog and schema to it.
// Use this on a string gotten from a trusted source (Sql Catalog), because
// if it doesn't parse, the ctor cannot return an error so it CMPASSERTs.
//
// This code cloned for CorrName::applyPrototype below.
//
QualifiedName::QualifiedName(const NAString &ansiString, 
                             Int32 minNameParts,
                             CollHeap * h, 
                             BindWA *bindWA) :
     SchemaName(h),
     objectName_(h),
     objectNameSpace_(COM_UNKNOWN_NAME),
     flagbits_(0)
{
  if (HasMPLocPrefix(ansiString.data())) {
    ComMPLoc loc(ansiString);
    catalogName_ = loc.getSysDotVol();
    schemaName_ = loc.getSubvolName();
    objectName_ = loc.getFileName();
  }
  else
  {
    CmpContext *cmpContext = bindWA ? bindWA->currentCmpContext() : NULL;
    Parser parser(cmpContext);
    NAString ns("TABLE " + ansiString + ";", CmpCommon::statementHeap());
#pragma nowarn(1506)   // warning elimination 
    // save the current parserflags setting
    ULng32 savedParserFlags = Get_SqlParser_Flags (0xFFFFFFFF);
    StmtQuery *stmt = (StmtQuery *)parser.parseDML(ns, ns.length(), GetAnsiNameCharSet());
    // Restore parser flags settings 
    Set_SqlParser_Flags (savedParserFlags);
#pragma warn(1506)  // warning elimination 
    if (stmt) {
      CMPASSERT(stmt->getOperatorType() == STM_QUERY);
      *this = stmt->getQueryExpression()->getScanNode()->getTableName().getQualifiedNameObj();
      delete stmt;
    } else {
      // It is possible for the parser to get errors when parsing SQL/MP
      // stored text.  The caller is expected to check the contents of
      // this QualifiedName.
      //
      return;
    }
  }

  Int32 nameParts = 0;
  if (minNameParts > 0) {
    nameParts = getCatalogName() != "" ? 3 :
		getSchemaName()  != "" ? 2 :
		getObjectName()  != "" ? 1 : 0;
    CMPASSERT(nameParts >= minNameParts);
  }

  if (bindWA && nameParts < 3)
    applyDefaults(bindWA->getDefaultSchema());
} // end of QualifiedName::QualifiedName 
Esempio n. 5
0
// -----------------------------------------------------------------------------
// *                                                                           *
// * Function: validateExternalUsername                                        *
// *                                                                           *
// *    Determines if an external username is valid.                           *
// *                                                                           *
// -----------------------------------------------------------------------------
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <externalUsername>          const char *                             In  *
// *    is the username to be validated.                                       *
// *                                                                           *
// *  <configurationNumber>      DBUserAuth::AuthenticationConfiguration   In  *
// *    specifies which configuration to use to validate the username; a       *
// *  configuration designates one or more identity stores and their           *
// *  parameters.  A value of zero indicates the "default" configuration       *
// *  should be used.                                                          *
// *                                                                           *
// *  <foundConfigurationNumber> DBUserAuth::AuthenticationConfiguration & In  *
// *    passes back the configuration used to validate the username.           *
// *                                                                           *
// -----------------------------------------------------------------------------
inline static bool validateExternalUsername(
   const char *                                 externalUsername,
   DBUserAuth::AuthenticationConfiguration      configurationNumber,
   DBUserAuth::AuthenticationConfiguration &    foundConfigurationNumber)

{

// During initialization external checking needs to be disabled to setup
// standard database users.
   if (Get_SqlParser_Flags(DISABLE_EXTERNAL_USERNAME_CHECK))
      return true;

// Verify that the external username is defined in the identity store.
DBUserAuth::CheckUserResult chkUserRslt = DBUserAuth::UserDoesNotExist;

   chkUserRslt = DBUserAuth::CheckExternalUsernameDefined(externalUsername,
                                                          configurationNumber,
                                                          foundConfigurationNumber);

// Username was found!
   if (chkUserRslt == DBUserAuth::UserExists)
      return true;

// Who?
   if (chkUserRslt == DBUserAuth::UserDoesNotExist)
   {
      *CmpCommon::diags() << DgSqlCode(-CAT_LDAP_USER_NOT_FOUND)
                          << DgString0(externalUsername);
      return false;
   }

// Problem looking up the username.  Could be a bad configuration, a
// problem at the identity store, or communicating with the identity store.
   if (chkUserRslt == DBUserAuth::ErrorDuringCheck)
   {
      *CmpCommon::diags() << DgSqlCode(-CAT_LDAP_COMM_ERROR);
      return false;
   }

   return false;

}
// validate REPLICATE_IO_VERSION setting
// setting may be schema or catalog.schema
Int32 ValidateReplIoVersion::validate( const char *value,
                                    const NADefaults *nad,
                                    Int32 attrEnum,
                                    Int32 errOrWarn,
                                    float *alreadyHaveFloat ) const
{
  Int32 isValid = FALSE;
  float flt;
  Int32 min;

  if (alreadyHaveFloat)
    flt = *alreadyHaveFloat;
  else {
    isValid = nad->validateFloat(value, flt, attrEnum, SilentIfSYSTEM);
    if (isValid == SilentIfSYSTEM) return SilentIfSYSTEM;
  }

  if (alreadyHaveFloat || isValid) 
  {
    if (Get_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL))
       min = 1;
    else
       min = min_; 
    if (flt >= min && flt <= max_)
       return TRUE;                            // valid
  }

  if (alreadyHaveFloat) *alreadyHaveFloat = (float)min_;

  if (errOrWarn)
    *CmpCommon::diags() << DgSqlCode(ERRWARN(2055))
        << DgString0(value)
        << DgString1(nad->lookupAttrName(attrEnum, errOrWarn));

  return FALSE;

}
// *****************************************************************************
// *                                                                           *
// * Function: CmpSeabaseDDL::addSchemaObject                                  *
// *                                                                           *
// *    Inserts a schema object row into the OBJECTS table.                    *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <cliInterface>                  ExeCliInterface &               In       *
// *    is a reference to an Executor CLI interface handle.                    *
// *                                                                           *
// *  <schemaName>                    const ComSchemaName &           In       *
// *    is a reference to a ComSchemaName instance.  The catalog name must be  *
// *  set.                                                                     *
// *                                                                           *
// *  <schemaClass>                   ComSchemaClass                  In       *
// *    is the class (private or shared) of the schema to be added.            *
// *                                                                           *
// *  <ownerID>                       Int32                           In       *
// *    is the authorization ID that will own the schema.                      *
// *                                                                           *
// *  <ignoreIfExists>                NABoolean                       In       *
// *    do not return an error is schema already exists                        *
// *****************************************************************************
// *                                                                           *
// * Returns: PrivStatus                                                       *
// *                                                                           *
// *   0: Schema as added                                                      *
// *  -1: Schema was not added.  A CLI error is put into the diags area.       *
// *                                                                           *
// *****************************************************************************
int CmpSeabaseDDL::addSchemaObject(
   ExeCliInterface & cliInterface,
   const ComSchemaName & schemaName,
   ComSchemaClass schemaClass,
   Int32 ownerID,
   NABoolean ignoreIfExists)
   
{

NAString catalogName = schemaName.getCatalogNamePartAsAnsiString();
ComAnsiNamePart schemaNameAsComAnsi = schemaName.getSchemaNamePart();
NAString schemaNamePart = schemaNameAsComAnsi.getInternalName();

ComObjectName objName(catalogName,schemaNamePart,NAString(SEABASE_SCHEMA_OBJECTNAME), 
                      COM_TABLE_NAME,TRUE);
                      
   if (isSeabaseReservedSchema(objName) &&
       !Get_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL))
   {
      *CmpCommon::diags() << DgSqlCode(-CAT_RESERVED_METADATA_SCHEMA_NAME)
                          << DgSchemaName(schemaName.getExternalName().data());
      return -1;
   }
                      
NAString objectNamePart = objName.getObjectNamePartAsAnsiString(TRUE);

Lng32 retcode = existsInSeabaseMDTable(&cliInterface,catalogName,schemaNamePart, 
                                       objectNamePart, COM_UNKNOWN_OBJECT, FALSE);
   if (retcode < 0)
      return -1;
  
   if (retcode == 1 ) // already exists
   {
      if (ignoreIfExists)
        return 0;
      else
        *CmpCommon::diags() << DgSqlCode(-CAT_SCHEMA_ALREADY_EXISTS)
                            << DgSchemaName(schemaName.getExternalName().data());
      return -1;
   }

char buf[4000];

ComUID schemaUID;

   schemaUID.make_UID();
   
Int64 schemaObjectUID = schemaUID.get_value();
  
Int64 createTime = NA_JulianTimestamp();

NAString quotedSchName;
NAString quotedObjName;

   ToQuotedString(quotedSchName,schemaNamePart,FALSE);
   ToQuotedString(quotedObjName,NAString(SEABASE_SCHEMA_OBJECTNAME),FALSE);

char schemaObjectLit[3] = {0};
   
   switch (schemaClass)
   {
      case COM_SCHEMA_CLASS_PRIVATE:
      {
         strncpy(schemaObjectLit,COM_PRIVATE_SCHEMA_OBJECT_LIT,2);
         break;
      }
      case COM_SCHEMA_CLASS_SHARED:
      {
         strncpy(schemaObjectLit,COM_SHARED_SCHEMA_OBJECT_LIT,2);
         break;
      }
      case COM_SCHEMA_CLASS_DEFAULT:
      default:
      {
         // Schemas are private by default, but could choose a different
         // default class here based on CQD or other attribute.
         strncpy(schemaObjectLit,COM_PRIVATE_SCHEMA_OBJECT_LIT,2);
         break;
      } 
   }
   
   str_sprintf(buf, "insert into %s.\"%s\".%s values ('%s', '%s', '%s', '%s', %Ld, %Ld, %Ld, '%s', '%s', %d, %d, 0)",
               getSystemCatalog(),SEABASE_MD_SCHEMA,SEABASE_OBJECTS,
               catalogName.data(), quotedSchName.data(), quotedObjName.data(),
               schemaObjectLit,
               schemaObjectUID,
               createTime, 
               createTime,
               COM_YES_LIT, // valid_def
               COM_NO_LIT,  // droppable
               ownerID,ownerID);
               
Int32 cliRC = cliInterface.executeImmediate(buf);
   
   if (cliRC < 0)
   {
      cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
      return -1;
   }

   return 0;

}
// We come here from syntax like
//	SELECT * FROM :hv PROTOTYPE 'cat.sch.tbl';  -- host variable, static SQL
//	TABLE $ev;				    -- env var, static or dynam
// (Internally, both host vars and env vars are HostVar objects.)
//
// If there's an environment variable, get its value at time of compilation,
// and stick that into the internal prototype value.  Generator will need
// to save these env var name/value pairs in the generated code;
// Executor needs to use the saved compile-time value of any name that is not
// defined at run-time.
//
// If there's a prototype value, parse it as an actual table name
// (1, 2, or 3-part name) and overwrite the bogus values in *this with the
// parsed prototype value.  Our caller, applyDefaults, will overwrite any
// remaining blank name parts.  Generator needs to save the host var names
// for actual input at run-time, and to save the prototype values for
// similarity check at run-time.
//
// We avoid re-parsing and re-overwriting this CorrName by checking/setting
// its bound state.  Note that we do not rely on its prototype's bound state
// because that is a separate, pointed at object: some Binder subroutines
// make local copies of CorrNames, and any apply methods invoked on the locals
// would not be propagated to the caller's originals: relying on the then True
// value of the prototype's bound state would be fallacious.
//
// If no error in proto, node is bound and bindWA errStatus unchanged
// (note that not having a proto is not an error).
// If error in proto, node is left unbound and bindWA errStatus is set.
//
void CorrName::applyPrototype(BindWA *bindWA)
{
  if (nodeIsBound()) return;
  HostVar *proto = getPrototype();
  if (!proto) {
    markAsBound();
    return;
  }

  // CMPASSERT(this == proto->getPrototypeTarget());
  CMPASSERT(!proto->getName().isNull());
  if (proto->isEnvVar()) {
    char *value = getenv(proto->getName());
    if (!value) {
      // Environment variable has no defined value.
      *CmpCommon::diags() << DgSqlCode(-4086) << DgString0(proto->getName());
      bindWA->setErrStatus();
      return;
    }
    // upcase value returned by getenv
#pragma nowarn(1506)   // warning elimination 
    Int32 len = strlen(value);
#pragma warn(1506)  // warning elimination 
    char * ucValue = new (bindWA->wHeap()) char[len+1];
    str_cpy_convert(ucValue, value, len, -1/*upshift*/);
    ucValue[len] = 0;
    proto->getPrototypeValue() = ucValue;
    // do not free "ucValue" here, it is still used in "proto"
    // to prevent Coverity RESOURCE_LEAK error, add the following
    // coverity[leaked_storage]
  }

  // defines can not be used on linux platform
  if (proto->isDefine()) {
      *CmpCommon::diags() << DgSqlCode(-4155) << DgString0(proto->getName());
      bindWA->setErrStatus();
      return;
  }

  CMPASSERT(!proto->getPrototypeValue().isNull());

  // Some of the following code is cloned from the QualifiedName ctor above
  Parser parser(bindWA->currentCmpContext());
  NAString ns("TABLE " + proto->getPrototypeValue() + ";",
              CmpCommon::statementHeap());
#pragma nowarn(1506)   // warning elimination 
  // save the current parserflags setting
  ULng32 savedParserFlags = Get_SqlParser_Flags (0xFFFFFFFF);
  StmtQuery *stmt = (StmtQuery *)parser.parseDML(ns, ns.length(), GetAnsiNameCharSet());
  // Restore parser flags settings 
  Set_SqlParser_Flags (savedParserFlags);
#pragma warn(1506)  // warning elimination 
  if (stmt) {
    CMPASSERT(stmt->getOperatorType() == STM_QUERY);
    CorrName &protoCorrName = 
      		stmt->getQueryExpression()->getScanNode()->getTableName();

    // Unless the hostvar type was forced directly,
    // copy the special table type to me, the prototype may be a
    // resource fork
    if (getSpecialType() == ExtendedQualName::NORMAL_TABLE)
      setSpecialType(protoCorrName);

    // This if-test prevents pathologies such as
    //	   SELECT col FROM :hv1 PROTOTYPE ':hv2 PROTOTYPE ''tbl''';
    // but allows
    //	   SELECT col FROM :hv1 PROTOTYPE '$ev';
    //
    // (The assertion below ensures that only host var syntax allows prototypes,
    // that you can't say ... FROM $ev PROTOTYPE '...'.)
    //
    HostVar *proto2 = protoCorrName.getPrototype();
    CMPASSERT(!proto2 || !proto->isEnvVar());
    if (!proto2 || proto2->isEnvVar()) {

      if (proto2) {
        // Here if proto2->isEnvVar.
	// Recurse (once only; the assertion above ensures that)
	// to get the value of the var, parse it and all.
	protoCorrName.applyPrototype(bindWA);
	if (bindWA->errStatus()) return;
      }

      #ifndef NDEBUG
	if (getenv("HV_DEBUG"))
	  cout << "HostVar/Prototype: parsed (" 
	       << (Int32)proto->nodeIsBound() << ") "
	       << proto->getName() << " " 
	       << protoCorrName.getExposedNameAsAnsiString() << endl;
      #endif

      // assert *before* overwriting with 0
	//      CMPASSERT(!getQualifiedNameObj().getNamePosition());
      getQualifiedNameObj() = protoCorrName.getQualifiedNameObj();

      proto->setPrototypeType(HostVar::QUALIFIEDNAME);

      // mark that we, the trusted CorrName, are bound
      markAsBound();
    }
  }

  if (!nodeIsBound()) {
    // Clear parser syntax error and emit "Prototype value not valid"
    #ifndef NDEBUG
      if (!getenv("HV_DEBUG"))
    #endif
    CmpCommon::diags()->clear();
    *CmpCommon::diags() << DgSqlCode(-4087) 
      << DgString0(proto->getPrototypeValue());
    bindWA->setErrStatus();
  }

  delete stmt;

} // applyPrototype
void CmpSeabaseDDL::createSeabaseView(
				      StmtDDLCreateView * createViewNode,
				      NAString &currCatName, NAString &currSchName)
{
  Lng32 retcode = 0;
  Lng32 cliRC = 0;

  ComObjectName viewName(createViewNode->getViewName());
  ComAnsiNamePart currCatAnsiName(currCatName);
  ComAnsiNamePart currSchAnsiName(currSchName);
  viewName.applyDefaults(currCatAnsiName, currSchAnsiName);
  const NAString catalogNamePart = viewName.getCatalogNamePartAsAnsiString();
  const NAString schemaNamePart = viewName.getSchemaNamePartAsAnsiString(TRUE);
  const NAString objectNamePart = viewName.getObjectNamePartAsAnsiString(TRUE);
  const NAString extViewName = viewName.getExternalName(TRUE);
  const NAString extNameForHbase = catalogNamePart + "." + schemaNamePart + "." + objectNamePart;
  
  ExeCliInterface cliInterface(STMTHEAP, NULL, NULL, 
  CmpCommon::context()->sqlSession()->getParentQid());
  Int32 objectOwnerID = SUPER_USER;
  Int32 schemaOwnerID = SUPER_USER;
  ComSchemaClass schemaClass;

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

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

     return;
    }

  if ((isSeabaseReservedSchema(viewName)) &&
      (!Get_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL)))
     {
      *CmpCommon::diags() << DgSqlCode(-1118)
			  << DgTableName(extViewName);
      deallocEHI(ehi); 
      return;
    }

  //if metadata views are being created and seabase is uninitialized, then this
  //indicates that these views are being created during 'initialize trafodion'
  //and this compiler contains stale version.
  //Reload version info.
  //
  if ((isSeabaseMD(viewName)) &&
      (CmpCommon::context()->isUninitializedSeabase()))
    {
      CmpCommon::context()->setIsUninitializedSeabase(FALSE);
      CmpCommon::context()->uninitializedSeabaseErrNum() = 0;
    }

  retcode = existsInSeabaseMDTable(&cliInterface, 
				   catalogNamePart, schemaNamePart, objectNamePart, 
				   COM_UNKNOWN_OBJECT, FALSE, FALSE);
  if (retcode < 0)
    {
      deallocEHI(ehi); 

      processReturn();

      return;
    }

  if (retcode == 1) // already exists
    {
      if (NOT ((createViewNode->isCreateOrReplaceViewCascade())|| 
	       (createViewNode->isCreateOrReplaceView())))
	{
	  *CmpCommon::diags() << DgSqlCode(-1390)
			      << DgString0(extViewName);
	  deallocEHI(ehi); 
	  
	  processReturn();
	  
	  return;
	}
    }

  char * query = NULL;
  int64_t objectUID = -1;
  std::vector<ObjectPrivsRow> viewPrivsRows;
  bool replacingView = false;
  
  if ((retcode == 1) && // exists
      ((createViewNode->isCreateOrReplaceViewCascade())|| 
       (createViewNode->isCreateOrReplaceView())))
    {
      // Replace view. Drop this view and recreate it.
      
      Int32 objectOwnerID = 0;
      Int32 schemaOwnerID = 0;
      Int64 objUID = getObjectUIDandOwners(&cliInterface,
    			                   catalogNamePart.data(), schemaNamePart.data(), 
    			                   objectNamePart.data(),
    			                   COM_VIEW_OBJECT,
                                           objectOwnerID,schemaOwnerID);

      if (objUID < 0 || objectOwnerID == 0)
        {
          if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
            SEABASEDDL_INTERNAL_ERROR("getting object UID and owner for create or replace view");

          deallocEHI(ehi); 

          processReturn();

          return;
        }

      if (isAuthorizationEnabled())
      {
         // Verify user can perform operation
         if (!isDDLOperationAuthorized(SQLOperation::ALTER_VIEW,objectOwnerID,schemaOwnerID))
         {
            *CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
            deallocEHI(ehi);
            processReturn ();
            return;
         }
      
         // Initiate the privilege manager interface class
         NAString privMgrMDLoc;
         CONCAT_CATSCH(privMgrMDLoc,getSystemCatalog(),SEABASE_PRIVMGR_SCHEMA);
         PrivMgrCommands privInterface(std::string(privMgrMDLoc.data()), 
                                       CmpCommon::diags());
      
         PrivStatus privStatus = privInterface.getPrivRowsForObject(objUID,viewPrivsRows);
         if (privStatus != PrivStatus::STATUS_GOOD)
         {
            SEABASEDDL_INTERNAL_ERROR("Unable to retrieve privileges for replaced view");
            deallocEHI(ehi); 
            processReturn();
            
            return;
         }
         
      }
      
      if (dropOneTableorView(cliInterface,extViewName.data(),COM_VIEW_OBJECT,false))
      
        {
          deallocEHI(ehi); 
          processReturn();
          
          return;
        }
      replacingView = true;
    }

  // Gather the object and grantable privileges that the view creator has.
  // This code also verifies that the current user has the necessary
  // privileges to create the view.
  PrivMgrBitmap privilegesBitmap;
  PrivMgrBitmap grantableBitmap;
  privilegesBitmap.set();
  grantableBitmap.set();
  if (gatherViewPrivileges(createViewNode, 
                           &cliInterface, 
                           privilegesBitmap, 
                           grantableBitmap))
    {
      processReturn();

      deallocEHI(ehi); 
	  
      return;
    }

  NAString viewText(STMTHEAP);
  buildViewText(createViewNode, viewText);

  NAString newViewText(STMTHEAP);
  for (Lng32 i = 0; i < viewText.length(); i++)
    {
      if (viewText.data()[i] == '\'')
	newViewText += "''";
      else
	newViewText += viewText.data()[i];
    }

  ElemDDLColDefArray colDefArray(STMTHEAP);
  if (buildViewColInfo(createViewNode, &colDefArray))
    {
      deallocEHI(ehi); 
      processReturn();

      return;
    }

  Lng32 numCols = colDefArray.entries();
  ComTdbVirtTableColumnInfo * colInfoArray = 
    new(STMTHEAP) ComTdbVirtTableColumnInfo[numCols];

  if (buildColInfoArray(COM_VIEW_OBJECT, &colDefArray, colInfoArray, FALSE, 0, FALSE))
    {
      deallocEHI(ehi); 
      processReturn();
      
      return;
    }

  Int64 objUID = -1;
  if (updateSeabaseMDTable(&cliInterface, 
			   catalogNamePart, schemaNamePart, objectNamePart,
			   COM_VIEW_OBJECT,
			   "N",
			   NULL,
			   numCols,
			   colInfoArray,	       
			   0, NULL,
			   0, NULL,
                           objectOwnerID,
                           schemaOwnerID,
                           objUID))
    {
      deallocEHI(ehi); 

      processReturn();

      return;
    }

    if (objUID < 0)
      {
        deallocEHI(ehi);
        processReturn();
        return;
      }

  // grant privileges for view
  if (isAuthorizationEnabled())
    {
      char authName[MAX_AUTHNAME_LEN+1];
      Int32 lActualLen = 0;
      Int16 status = ComUser::getAuthNameFromAuthID( (Int32) objectOwnerID
                                                   , (char *)&authName
                                                   , MAX_AUTHNAME_LEN
                                                   , lActualLen );
      if (status != FEOK)
        {
          *CmpCommon::diags() << DgSqlCode(-20235)
                              << DgInt0(status)
                              << DgInt1(objectOwnerID);

          deallocEHI(ehi);

          processReturn();

          return;
       }

      // Initiate the privilege manager interface class
      NAString privMgrMDLoc;
      CONCAT_CATSCH(privMgrMDLoc, getSystemCatalog(), SEABASE_PRIVMGR_SCHEMA);
      PrivMgrCommands privInterface(std::string(privMgrMDLoc.data()), 
                                    CmpCommon::diags());

      retcode = privInterface.grantObjectPrivilege 
       (objUID, std::string(extViewName.data()), COM_VIEW_OBJECT, 
        objectOwnerID, std::string(authName), 
        privilegesBitmap, grantableBitmap);
      if (retcode != STATUS_GOOD && retcode != STATUS_WARNING)
        {
          deallocEHI(ehi);

          processReturn();

          return;
        }
      if (replacingView)
      {
         PrivStatus privStatus = privInterface.insertPrivRowsForObject(objUID,viewPrivsRows);
         
         if (privStatus != PrivStatus::STATUS_GOOD)
         {
            SEABASEDDL_INTERNAL_ERROR("Unable to restore privileges for replaced view");
            deallocEHI(ehi); 
            processReturn();
            
            return;
         }
      }  
    }


  query = new(STMTHEAP) char[newViewText.length() + 1000];
  str_sprintf(query, "upsert into %s.\"%s\".%s values (%Ld, '%s', %d, %d, 0)",
	      getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_VIEWS,
	      objUID,
	      computeCheckOption(createViewNode),
	      (createViewNode->getIsUpdatable() ? 1 : 0),
	      (createViewNode->getIsInsertable() ? 1 : 0));
  
  cliRC = cliInterface.executeImmediate(query);

  NADELETEBASIC(query, STMTHEAP);
  if (cliRC < 0)
    {
      if (cliRC == -8402)
        // string overflow, view text does not fit into metadata table
        *CmpCommon::diags() << DgSqlCode(-1198);
      else
        cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());

      deallocEHI(ehi); 
      processReturn();

      return;
    }

  if (updateTextTable(&cliInterface, objUID, COM_VIEW_TEXT, 0, newViewText))
    {
      deallocEHI(ehi); 
      processReturn();
      return;
    }

  if (updateViewUsage(createViewNode, objUID, &cliInterface))
    {
      deallocEHI(ehi); 
      processReturn();
     
      return;
    }

  if (updateObjectValidDef(&cliInterface, 
			   catalogNamePart, schemaNamePart, objectNamePart,
			   COM_VIEW_OBJECT_LIT,
			   "Y"))
    {
      deallocEHI(ehi); 

      processReturn();

      return;
    }

  CorrName cn(objectNamePart, STMTHEAP, schemaNamePart, catalogNamePart);
  ActiveSchemaDB()->getNATableDB()->removeNATable(cn,
    NATableDB::REMOVE_MINE_ONLY, COM_VIEW_OBJECT);

  deallocEHI(ehi); 
  processReturn();

  return;
}
CmpStatement::ReturnStatus
CmpStatement::process (const CmpMessageDDL& statement)
{
  CmpMain cmpmain;

  CMPASSERT(statement.getCmpCompileInfo());
  
  char * sqlStr = NULL;
  Int32 sqlStrLen = 0;
  Lng32 inputCS = 0;
  NAString currCatName;
  NAString currSchName;
  char * recompControlInfo = NULL;
  NABoolean isSchNameRecvd;
  NABoolean nametypeNsk;
  NABoolean odbcProcess;
  NABoolean noTextCache;
  NABoolean aqrPrepare;
  NABoolean standaloneQuery;
  isDDL_ = TRUE;

  if (processRecvdCmpCompileInfo(this,
				 statement,
  				 statement.getCmpCompileInfo(),
				 context_,
				 sqlStr, 
				 sqlStrLen, // out - long &
				 inputCS,
				 isSchNameRecvd, 
				 currCatName, currSchName, 
				 recompControlInfo,
				 nametypeNsk,
				 odbcProcess,
				 noTextCache,
				 aqrPrepare,
				 standaloneQuery))
    return CmpStatement_ERROR;

  CmpCommon::context()->sqlSession()->setParentQid(
    statement.getParentQid());
  // process recompControlInfo, if received
  if (recompControlInfo)
    setupRecompControlInfo(recompControlInfo, &cmpmain);

  cmpmain.setSqlParserFlags(statement.getFlags());

  // set the current catalog and schema names.
  InitSchemaDB();

  // C control character embedded in sqlStr is not handled.  Now replace 
  // control characters tabs, line feeds, spaces with spaces. (no longer 
  // substitute for \n so we can recognized embedded comments)
  for (Int32 i = 0; sqlStr[i]; i++)
   if (sqlStr[i] != '\n' && isSpace8859_1((unsigned char)sqlStr[i])) sqlStr[i] = ' ';

  // skip leading blanks
  NAString ns(sqlStr);
  ns = ns.strip(NAString::leading, ' ');

  // if this is an "update statistics..." request,
  // then do not send it catalog manager.
  Int32 foundUpdStat = 0;

  // check if the first token is UPDATE
  size_t position = ns.index("UPDATE", 0, NAString::ignoreCase);
  if (position == 0)
    {
      // found UPDATE. See if the next token is STATISTICS.
      ns = ns(6, ns.length()-6); // skip over UPDATE
      ns = ns.strip(NAString::leading, ' ');

      position = ns.index("STATISTICS", 0, NAString::ignoreCase);
      if (position == 0)
	foundUpdStat = -1;
    }

  if (foundUpdStat)
    {
      // TODO, should be removed later
      
      // A pointer to user SQL query is stored in CmpStatement; if an exception
      // is thrown the user query is copied from here. It is reset upon return
      // from the UpdateStats() method.
      
      char *userStr= new (heap()) char[2000];
#pragma nowarn(1506)   // warning elimination 
      Int32 len=strlen(sqlStr);
#pragma warn(1506)  // warning elimination 
      
      if (len > 1999)
        len=1999;
      
      strncpy(userStr, sqlStr, len);
      userStr[len]='\0';
      
      sqlTextStr_ = userStr;
      sqlTextLen_ = len;
      
      if (UpdateStats(sqlStr))
        {
	  sqlTextStr_ = NULL;
	  sqlTextLen_ = 0;
	  if (recompControlInfo)
	    restoreRecompControlInfo(recompControlInfo);
	  return CmpStatement_ERROR;
        }
      
      sqlTextStr_ = NULL;
      sqlTextLen_ = 0;
      
      if (recompControlInfo)
	restoreRecompControlInfo(recompControlInfo);
      return CmpStatement_SUCCESS;
    }

  ReturnStatus status = CmpStatement_SUCCESS;
  if (statement.getCmpCompileInfo()->isHbaseDDL())
    {
      CmpMain::ReturnStatus rs = CmpMain::SUCCESS;
      
      QueryText qText(sqlStr, inputCS);

      CmpMessageReplyCode
	*bound = new(outHeap_) CmpMessageReplyCode(outHeap_, statement.id(), 0, 0, outHeap_);

      //      CmpMain cmpmain;
      Set_SqlParser_Flags(DELAYED_RESET);	// sqlcompCleanup resets for us
      Parser parser(CmpCommon::context());
      BindWA bindWA(ActiveSchemaDB(), CmpCommon::context(), TRUE);

      // save parser flags
      Int32 savedParserFlags = Get_SqlParser_Flags (0xFFFFFFFF);
      ExprNode * exprNode = NULL;
      if (parser.parseDML(qText, &exprNode, NULL))
	{
	  error(arkcmpErrorNoDiags, statement.data());
	  sqlTextStr_=NULL;
	  return CmpStatement_ERROR;
	}

      RelExpr * rRoot = NULL;
      if (exprNode->getOperatorType() EQU STM_QUERY)
	{
	  rRoot = (RelRoot*)exprNode->getChild(0);
	}
      else if (exprNode->getOperatorType() EQU REL_ROOT)
	{
	  rRoot = (RelRoot*)exprNode;
	}
      
      CMPASSERT(rRoot);

      ExprNode *boundDDL = rRoot->bindNode(&bindWA);
      CMPASSERT(boundDDL);

      if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_))
	{
	  return CmpStatement_ERROR;
	}
      
      ExprNode * ddlNode = NULL;
      DDLExpr * ddlExpr = NULL;

      ddlExpr = (DDLExpr*)rRoot->getChild(0);
      ddlNode = ddlExpr->getDDLNode();

      if (ddlNode)
	{
	  boundDDL = ddlNode->castToStmtDDLNode()->bindNode(&bindWA);
	  CMPASSERT(boundDDL);

	  if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_))
	    {
	      return CmpStatement_ERROR;
	    }
 	  
	  ddlNode = boundDDL;
	}

      // reset saved flags
      Set_SqlParser_Flags (savedParserFlags);
      CmpSeabaseDDL cmpSBD(heap_);
      if (cmpSBD.executeSeabaseDDL(ddlExpr, ddlNode,
				   currCatName, currSchName))
      {
        Set_SqlParser_Flags(0);
	return CmpStatement_ERROR;
      }
      Set_SqlParser_Flags (0);

      // TEMPTEMP.
      // Until support for metadata invalidation is in, clear up query cache for
      // this process. That way statements issued later from this session will
      // not see stale definitions.
      // This also helps in running tests where tables are modified and accessed from
      // the same session.
      // This does not solve the issue of stale definition seen by other processes,
      // that will be fixed once we have metadata invalidation.
      CURRENTQCACHE->makeEmpty();

      return CmpStatement_SUCCESS;
    } // hbaseDDL

  // This is a normal DDL request, call Catalog manager
  *diags() << DgSqlCode(-4222)
           << DgString0("SQL Compiler DDL");
  return CmpStatement_ERROR;
}
Esempio n. 11
0
NABoolean CmpSqlSession::volatileSchemaInUse() 
{ 
  return ((volatileSchemaInUse_) &&
	  (NOT Get_SqlParser_Flags(DISABLE_VOLATILE_SCHEMA)));
}
Esempio n. 12
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::dropSeabaseView(
				    StmtDDLDropView * dropViewNode,
				    NAString &currCatName, NAString &currSchName)
{
  Lng32 cliRC = 0;
  Lng32 retcode = 0;

  const NAString &tabName = dropViewNode->getViewName();

  ComObjectName viewName(tabName);
  ComAnsiNamePart currCatAnsiName(currCatName);
  ComAnsiNamePart currSchAnsiName(currSchName);
  viewName.applyDefaults(currCatAnsiName, currSchAnsiName);

  const NAString catalogNamePart = viewName.getCatalogNamePartAsAnsiString();
  const NAString schemaNamePart = viewName.getSchemaNamePartAsAnsiString(TRUE);
  const NAString objectNamePart = viewName.getObjectNamePartAsAnsiString(TRUE);
  const NAString extViewName = viewName.getExternalName(TRUE);

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

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

  if ((isSeabaseReservedSchema(viewName)) &&
      (!Get_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL)))
    {
      *CmpCommon::diags() << DgSqlCode(-1119)
			  << DgTableName(extViewName);
      deallocEHI(ehi); 

      processReturn();

      return;
    }

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

      processReturn();

      return;
    }

  if (retcode == 0) // does not exist
    {
      *CmpCommon::diags() << DgSqlCode(-1389)
			  << DgString0(extViewName);

      deallocEHI(ehi); 

      processReturn();
      
      return;
    }

  Int32 objectOwnerID = 0;
  Int32 schemaOwnerID = 0;
  Int64 objUID = getObjectUIDandOwners(&cliInterface,
			              catalogNamePart.data(), schemaNamePart.data(), 
			              objectNamePart.data(),
			              COM_VIEW_OBJECT,
                                      objectOwnerID,schemaOwnerID);

  if (objUID < 0 || objectOwnerID == 0)
    {
      if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
        SEABASEDDL_INTERNAL_ERROR("getting object UID and owner for drop view");

      deallocEHI(ehi); 

      processReturn();

      return;
    }

  // Verify user can perform operation
  if (!isDDLOperationAuthorized(SQLOperation::DROP_VIEW,objectOwnerID,schemaOwnerID))
  {
     *CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
     deallocEHI(ehi);
     processReturn ();
     return;
  }
 
  Queue * usingViewsQueue = NULL;
  if (dropViewNode->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(-1047)
			      << DgTableName(usingObjName);

	  deallocEHI(ehi); 

	  processReturn();

	  return;
	}
    }
  else if (dropViewNode->getDropBehavior() == COM_CASCADE_DROP_BEHAVIOR)
    {
      cliRC = getUsingViews(&cliInterface, objUID, usingViewsQueue);
      if (cliRC < 0)
	{
	  deallocEHI(ehi); 

	  processReturn();
	  
	  return;
	}
    }

  // get the list of all tables referenced by the view.  Save this list so 
  // referenced tables can be removed from cache later
  NAList<objectRefdByMe> tablesRefdList;
  short status = getListOfReferencedTables(&cliInterface, objUID, tablesRefdList);

  if (usingViewsQueue)
    {
      usingViewsQueue->position();
      for (int idx = 0; idx < usingViewsQueue->numEntries(); idx++)
	{
	  OutputInfo * vi = (OutputInfo*)usingViewsQueue->getNext(); 
	  
	  char * viewName = vi->get(0);
	  
	  if (dropSeabaseObject(ehi, viewName,
				 currCatName, currSchName, COM_VIEW_OBJECT))
	    {
	      deallocEHI(ehi); 

	      processReturn();
	      
	      return;
	    }
	}
    }

  if (dropSeabaseObject(ehi, tabName,
			 currCatName, currSchName, COM_VIEW_OBJECT))
    {
      deallocEHI(ehi); 

      processReturn();

      return;
    }

  // clear view definition from my cache only. 
  CorrName cn(objectNamePart, STMTHEAP, schemaNamePart, catalogNamePart);
  ActiveSchemaDB()->getNATableDB()->removeNATable(cn,
    NATableDB::REMOVE_MINE_ONLY, COM_VIEW_OBJECT);

  // clear view from all other caches here. This compensates for a 
  // scenario where the object UID is not available in removeNATable, 
  // and the look up failed too.  Solution is just to use the objectUID 
  // here.
  SQL_QIKEY qiKey;
  qiKey.operation[0] = 'O';
  qiKey.operation[1] = 'R';
  qiKey.ddlObjectUID = objUID;
  SQL_EXEC_SetSecInvalidKeys(1, &qiKey);

  // Now remove referenced tables from cache.
  // When a query that references a view is compiled, all views are converted
  // to the underlying base tables.  Query plans are generated to access the
  // tables, and the views are no longer relevant.
  // When dropping a view, query plans that reference the dropped view will
  // continue to work if the plans are cached.  This code removes the 
  // referenced tables from caches to force recompilations so dropped views
  // are noticed.
  for (CollIndex i = 0; i < tablesRefdList.entries(); i++)
    {
      CorrName cn(tablesRefdList[i].objectName,
                  STMTHEAP,
                  tablesRefdList[i].schemaName,
                  tablesRefdList[i].catalogName);
      ActiveSchemaDB()->getNATableDB()->removeNATable(cn,
        NATableDB::REMOVE_FROM_ALL_USERS, COM_BASE_TABLE_OBJECT);
    }

  deallocEHI(ehi); 
      
  processReturn();

  return;
}
// *****************************************************************************
// *                                                                           *
// * Function: CmpSeabaseDDL::dropSeabaseSchema                                *
// *                                                                           *
// *    Implements the DROP SCHEMA command.                                    *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <dropSchemaNode>                StmtDDLDropSchema *             In       *
// *    is a pointer to a create schema parser node.                           *
// *                                                                           *
// *****************************************************************************
void CmpSeabaseDDL::dropSeabaseSchema(StmtDDLDropSchema * dropSchemaNode)
   
{

Lng32 cliRC = 0;

ComSchemaName schemaName(dropSchemaNode->getSchemaName());
NAString catName = schemaName.getCatalogNamePartAsAnsiString();
ComAnsiNamePart schNameAsComAnsi = schemaName.getSchemaNamePart();
NAString schName = schNameAsComAnsi.getInternalName();

ExeCliInterface cliInterface(STMTHEAP, NULL, NULL, 
CmpCommon::context()->sqlSession()->getParentQid());
Int32 objectOwnerID = 0;
Int32 schemaOwnerID = 0;
ComObjectType objectType;

   Int64 schemaUID = getObjectTypeandOwner(&cliInterface,catName.data(),schName.data(),
                             SEABASE_SCHEMA_OBJECTNAME,objectType,schemaOwnerID);
   
   // if schemaUID == -1, then either the schema does not exist or an unexpected error occurred
   if (schemaUID == -1)
   {
      // If an error occurred, return
      if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) > 0)
        return;
 
      // schema does not exist and IF EXISTS specified, then ignore and continue
      if (dropSchemaNode->dropIfExists())
        return;

      // A Trafodion schema does not exist if the schema object row is not
      // present: CATALOG-NAME.SCHEMA-NAME.__SCHEMA__.
      *CmpCommon::diags() << DgSqlCode(-CAT_SCHEMA_DOES_NOT_EXIST_ERROR)
                          << DgSchemaName(schemaName.getExternalName().data());
      return;
   }

   if (!isDDLOperationAuthorized(SQLOperation::DROP_SCHEMA,
                                 schemaOwnerID,schemaOwnerID))
   {
      *CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
      return;
   }
 
ComObjectName objName(catName,schName,NAString("dummy"),COM_TABLE_NAME,TRUE);

   if ((isSeabaseReservedSchema(objName) ||
        (schName == SEABASE_SYSTEM_SCHEMA)) &&
       !Get_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL))
   {
      *CmpCommon::diags() << DgSqlCode(-CAT_USER_CANNOT_DROP_SMD_SCHEMA)
                          << DgSchemaName(schemaName.getExternalName().data());
      return;
   }
   
bool isVolatile = (memcmp(schName.data(),"VOLATILE_SCHEMA",strlen("VOLATILE_SCHEMA")) == 0);

// Can't drop a schema whose name begins with VOLATILE_SCHEMA unless the 
// keyword VOLATILE was specified in the DROP SCHEMA command. 
   if (isVolatile && !dropSchemaNode->isVolatile())
   {
      *CmpCommon::diags() << DgSqlCode(-CAT_RESERVED_METADATA_SCHEMA_NAME)
                          << DgTableName(schName);
      return;
   }

// Get a list of all objects in the schema, excluding the schema object itself.
char query[4000];

   str_sprintf(query,"SELECT TRIM(object_name), TRIM(object_type) "
                     "FROM %s.\"%s\".%s "
                     "WHERE catalog_name = '%s' AND schema_name = '%s' AND "
                     "object_name <> '"SEABASE_SCHEMA_OBJECTNAME"'" 
                     "FOR READ COMMITTED ACCESS",
               getSystemCatalog(),SEABASE_MD_SCHEMA,SEABASE_OBJECTS,
               (char*)catName.data(),(char*)schName.data());
  
Queue * objectsQueue = NULL;

   cliRC = cliInterface.fetchAllRows(objectsQueue, query, 0, FALSE, FALSE, TRUE);
   if (cliRC < 0)
   {
      cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
      return;
   }

   objectsQueue->position();
   if ((dropSchemaNode->getDropBehavior() == COM_RESTRICT_DROP_BEHAVIOR) &&
       (objectsQueue->numEntries() > 0))
   {
      OutputInfo * oi = (OutputInfo*)objectsQueue->getCurr(); 
      
      *CmpCommon::diags() << DgSqlCode(-CAT_SCHEMA_IS_NOT_EMPTY)
                          << DgTableName(oi->get(0));
      return;
   }

bool someObjectsCouldNotBeDropped = false;

// Drop libraries, procedures (SPJs), UDFs (functions), and views 
   objectsQueue->position();
   for (int idx = 0; idx < objectsQueue->numEntries(); idx++)
   {
      OutputInfo * vi = (OutputInfo*)objectsQueue->getNext(); 

      char * objName = vi->get(0);
      NAString objectTypeLit = vi->get(1);
      ComObjectType objectType = PrivMgr::ObjectLitToEnum(objectTypeLit.data());
      char buf[1000];
      NAString objectTypeString;
      NAString cascade = " ";
      
      switch (objectType)
      {
         // These object types are handled later and can be ignored for now.
         case COM_BASE_TABLE_OBJECT:
         case COM_INDEX_OBJECT:
         case COM_CHECK_CONSTRAINT_OBJECT:
         case COM_NOT_NULL_CONSTRAINT_OBJECT:
         case COM_PRIMARY_KEY_CONSTRAINT_OBJECT:
         case COM_REFERENTIAL_CONSTRAINT_OBJECT:
         case COM_SEQUENCE_GENERATOR_OBJECT:
         case COM_UNIQUE_CONSTRAINT_OBJECT:
         {
            continue;
         }
         case COM_LIBRARY_OBJECT:
         {
            objectTypeString = "LIBRARY";
            cascade = "CASCADE";
            break;
         }
         case COM_STORED_PROCEDURE_OBJECT:
         {
            objectTypeString = "PROCEDURE";
            break;
         }
         case COM_USER_DEFINED_ROUTINE_OBJECT:
         {
            objectTypeString = "FUNCTION";
            cascade = "CASCADE";
            break;
         }
         case COM_VIEW_OBJECT:
         {
            objectTypeString = "VIEW";
            cascade = "CASCADE";
            break;
         }
         // These object types should not be seen.
         case COM_MV_OBJECT: 
         case COM_MVRG_OBJECT:    
         case COM_TRIGGER_OBJECT:
         case COM_LOB_TABLE_OBJECT:
         case COM_TRIGGER_TABLE_OBJECT:
         case COM_SYNONYM_OBJECT:
         case COM_PRIVATE_SCHEMA_OBJECT:
         case COM_SHARED_SCHEMA_OBJECT:
         case COM_EXCEPTION_TABLE_OBJECT:
         case COM_LOCK_OBJECT:
         case COM_MODULE_OBJECT:
         default:
            SEABASEDDL_INTERNAL_ERROR("Unrecognized object type in schema");
            return;
      }
         
      str_sprintf(buf, "drop %s \"%s\".\"%s\".\"%s\" %s",
                  objectTypeString.data(),(char*)catName.data(),(char*)schName.data(), 
                  objName,cascade.data());
         
      cliRC = cliInterface.executeImmediate(buf);
      if (cliRC < 0 && cliRC != -CAT_OBJECT_DOES_NOT_EXIST_IN_TRAFODION)
         someObjectsCouldNotBeDropped = true;
   } 

// Drop all tables in the schema.  This will also drop any associated constraints. 
// Drop of histogram tables is deferred.
bool histExists = false;

   objectsQueue->position();
   for (int idx = 0; idx < objectsQueue->numEntries(); idx++)
   {
      OutputInfo * vi = (OutputInfo*)objectsQueue->getNext(); 

      NAString objName = vi->get(0);
      NAString objType = vi->get(1);

      // drop user objects first
      if (objType == COM_BASE_TABLE_OBJECT_LIT)
      {
         if (!(objName == HBASE_HIST_NAME || objName == HBASE_HISTINT_NAME))
         {
            if (dropOneTable(cliInterface,(char*)catName.data(), 
                             (char*)schName.data(),(char*)objName.data(),
                             isVolatile))
               someObjectsCouldNotBeDropped = true;
         }
         else
            histExists = true;
      } 
   } 

// Drop any remaining indexes.

   str_sprintf(query,"SELECT TRIM(object_name), TRIM(object_type) "
                     "FROM %s.\"%s\".%s "
                     "WHERE catalog_name = '%s' AND "
                     "      schema_name = '%s' AND "
                     "      object_type = '%s' "
                     "FOR READ COMMITTED ACCESS ",
               getSystemCatalog(),SEABASE_MD_SCHEMA,SEABASE_OBJECTS,
               (char*)catName.data(),(char*)schName.data(), 
               COM_INDEX_OBJECT_LIT);
   
   cliRC = cliInterface.fetchAllRows(objectsQueue,query,0,FALSE,FALSE,TRUE);
   if (cliRC < 0)
   {
      cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
      return;
   }

   objectsQueue->position();
   for (int idx = 0; idx < objectsQueue->numEntries(); idx++)
   {
      OutputInfo * vi = (OutputInfo*)objectsQueue->getNext(); 

      char * objName = vi->get(0);
      NAString objType = vi->get(1);
    
      if (objType == COM_INDEX_OBJECT_LIT)
      {
         char buf [1000];

         str_sprintf(buf, "DROP INDEX \"%s\".\"%s\".\"%s\" CASCADE",
                     (char*)catName.data(), (char*)schName.data(), objName);
         cliRC = cliInterface.executeImmediate(buf);

         if (cliRC < 0 && cliRC != -CAT_OBJECT_DOES_NOT_EXIST_IN_TRAFODION)
            someObjectsCouldNotBeDropped = true;
      }  
   }  

// Drop any remaining sequences.

   str_sprintf(query,"SELECT TRIM(object_name), TRIM(object_type) "
                     "FROM %s.\"%s\".%s "
                     "WHERE catalog_name = '%s' AND "
                     "      schema_name = '%s' AND "
                     "      object_type = '%s' "
                     "FOR READ COMMITTED ACCESS ",
               getSystemCatalog(),SEABASE_MD_SCHEMA,SEABASE_OBJECTS,
               (char*)catName.data(),(char*)schName.data(), 
               COM_SEQUENCE_GENERATOR_OBJECT_LIT);
   
   cliRC = cliInterface.fetchAllRows(objectsQueue,query,0,FALSE,FALSE,TRUE);
   if (cliRC < 0)
   {
      cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
      return;
   }

   objectsQueue->position();
   for (int idx = 0; idx < objectsQueue->numEntries(); idx++)
   {
      OutputInfo * vi = (OutputInfo*)objectsQueue->getNext(); 

      char * objName = vi->get(0);
      NAString objType = vi->get(1);
    
      if (objType == COM_SEQUENCE_GENERATOR_OBJECT_LIT)
      {
         char buf [1000];

         str_sprintf(buf, "DROP SEQUENCE \"%s\".\"%s\".\"%s\"",
                     (char*)catName.data(), (char*)schName.data(), objName);
         cliRC = cliInterface.executeImmediate(buf);

         if (cliRC < 0 && cliRC != -CAT_OBJECT_DOES_NOT_EXIST_IN_TRAFODION)
            someObjectsCouldNotBeDropped = true;
      }  
   }  

// For volatile schemas, sometimes only the objects get dropped.    
// If the dropObjectsOnly flag is set, just exit now, we are done.
   if (dropSchemaNode->dropObjectsOnly())
      return;

// Now drop any histogram objects
   if (histExists)
   {
      if (dropOneTable(cliInterface,(char*)catName.data(),(char*)schName.data(), 
                      (char*)HBASE_HISTINT_NAME,false))
         someObjectsCouldNotBeDropped = true;
      
      if (dropOneTable(cliInterface,(char*)catName.data(),(char*)schName.data(), 
                       (char*)HBASE_HIST_NAME,false))
         someObjectsCouldNotBeDropped = true;
   }

   if (someObjectsCouldNotBeDropped)
   {
      CmpCommon::diags()->clear();
      
      *CmpCommon::diags() << DgSqlCode(-CAT_UNABLE_TO_DROP_SCHEMA)
                          << DgSchemaName(catName + "." + schName);
      return;
   }
   
// Verify all objects in the schema have been dropped.   
   str_sprintf(query,"SELECT COUNT(*) "
                     "FROM %s.\"%s\".%s "
                     "WHERE catalog_name = '%s' AND schema_name = '%s' AND "
                     "object_name <> '"SEABASE_SCHEMA_OBJECTNAME"'" 
                     "FOR READ COMMITTED ACCESS",
               getSystemCatalog(),SEABASE_MD_SCHEMA,SEABASE_OBJECTS,
               (char*)catName.data(),(char*)schName.data());
               
int32_t length = 0;
int32_t rowCount = 0;

   cliRC = cliInterface.executeImmediate(query,(char*)&rowCount,&length,NULL);
  
   if (cliRC < 0)
   {
      cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
      return;
   }
   
   if (rowCount > 0)
   {
      CmpCommon::diags()->clear();
      
      *CmpCommon::diags() << DgSqlCode(-CAT_UNABLE_TO_DROP_SCHEMA)
                          << DgSchemaName(catName + "." + schName);
      return;
   }
   
// After all objects in the schema have been dropped, drop the schema object itself.
    
char buf [1000];

   str_sprintf(buf,"DELETE FROM %s.\"%s\".%s "
                   "WHERE CATALOG_NAME = '%s' AND SCHEMA_NAME = '%s' AND " 
                   "OBJECT_NAME = '"SEABASE_SCHEMA_OBJECTNAME"'",
               getSystemCatalog(),SEABASE_MD_SCHEMA,SEABASE_OBJECTS,
               (char*)catName.data(),(char*)schName.data());
   cliRC = cliInterface.executeImmediate(buf);
   if (cliRC < 0) 
      *CmpCommon::diags() << DgSqlCode(-CAT_UNABLE_TO_DROP_SCHEMA)
                          << DgSchemaName(catName + "." + schName);
    
}
short CmpStatement::getDDLExprAndNode(char * sqlStr, Lng32 inputCS,
                                      DDLExpr* &ddlExpr, ExprNode* &ddlNode)
{

  ddlNode = NULL;
  ddlExpr = NULL;
      
  if (! sqlStr)
    return 0;

  // C control character embedded in sqlStr is not handled.  Now replace 
  // control characters tabs, line feeds, spaces with spaces. (no longer 
  // substitute for \n so we can recognized embedded comments)
  for (Int32 i = 0; sqlStr[i]; i++)
    if (sqlStr[i] != '\n' && isSpace8859_1((unsigned char)sqlStr[i])) sqlStr[i] = ' ';
  
  // skip leading blanks
  NAString ns(sqlStr);
  ns = ns.strip(NAString::leading, ' ');
  
  ReturnStatus status = CmpStatement_SUCCESS;
  CmpMain::ReturnStatus rs = CmpMain::SUCCESS;
  
  QueryText qText(sqlStr, inputCS);
  
  //  CmpMessageReplyCode
  //    *bound = new(outHeap_) CmpMessageReplyCode(outHeap_, statement.id(), 0, 0, outHeap_);
  
  Set_SqlParser_Flags(DELAYED_RESET);	// sqlcompCleanup resets for us
  Parser parser(CmpCommon::context());
  BindWA bindWA(ActiveSchemaDB(), CmpCommon::context(), TRUE);

  ExprNode *boundDDL = NULL;
  RelExpr * rRoot = NULL;
  
  // save parser flags
  Int32 savedParserFlags = Get_SqlParser_Flags (0xFFFFFFFF);
  ExprNode * exprNode = NULL;
  if (parser.parseDML(qText, &exprNode, NULL))
    {
      error(arkcmpErrorNoDiags, sqlStr);
      sqlTextStr_=NULL;
      goto label_error;
    }
  
  if (exprNode->getOperatorType() EQU STM_QUERY)
    {
      rRoot = (RelRoot*)exprNode->getChild(0);
    }
  else if (exprNode->getOperatorType() EQU REL_ROOT)
    {
      rRoot = (RelRoot*)exprNode;
    }
  
  CMPASSERT(rRoot);
  
  boundDDL = rRoot->bindNode(&bindWA);
  CMPASSERT(boundDDL);
  
  if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_))
    {
      goto label_error;
    }
  
  ddlExpr = (DDLExpr*)rRoot->getChild(0);
  ddlNode = ddlExpr->getDDLNode();
  
  if (ddlNode)
    {
      boundDDL = ddlNode->castToStmtDDLNode()->bindNode(&bindWA);
      CMPASSERT(boundDDL);
      
      if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_))
        {
          goto label_error;
        }
      
      ddlNode = boundDDL;
    }

  Set_SqlParser_Flags (savedParserFlags);
  return 0;

 label_error:  
  // reset saved flags
  Set_SqlParser_Flags (savedParserFlags);
  return CmpStatement_ERROR;
}
// *****************************************************************************
// *                                                                           *
// * Function: CmpSeabaseDDL::giveSeabaseSchema                                *
// *                                                                           *
// *    Implements the GIVE SCHEMA command.                                    *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <giveSchemaNode>                StmtDDLGiveSchema *             In       *
// *    is a pointer to a create schema parser node.                           *
// *                                                                           *
// *  <currentCatalogName>            NAString &                      In       *
// *    is the name of the current catalog.                                    *
// *                                                                           *
// *****************************************************************************
void CmpSeabaseDDL::giveSeabaseSchema(
   StmtDDLGiveSchema * giveSchemaNode,
   NAString          & currentCatalogName)
   
{

ComDropBehavior dropBehavior = giveSchemaNode->getDropBehavior(); 
NAString catalogName = giveSchemaNode->getCatalogName();
NAString schemaName = giveSchemaNode->getSchemaName();

   if (catalogName.isNull())
      catalogName = currentCatalogName;  

ExeCliInterface cliInterface(STMTHEAP, NULL, NULL,
CmpCommon::context()->sqlSession()->getParentQid());
Int32 objectOwnerID = 0;
Int32 schemaOwnerID = 0;
ComObjectType objectType;

Int64 schemaUID = getObjectTypeandOwner(&cliInterface,catalogName.data(),
                                        schemaName.data(),SEABASE_SCHEMA_OBJECTNAME,
                                        objectType,schemaOwnerID);
                                       
   if (schemaUID == -1)
   {
      // A Trafodion schema does not exist if the schema object row is not
      // present: CATALOG-NAME.SCHEMA-NAME.__SCHEMA__.
      *CmpCommon::diags() << DgSqlCode(-CAT_SCHEMA_DOES_NOT_EXIST_ERROR)
                          << DgSchemaName(schemaName.data());
      return;
   }
   
// *****************************************************************************
// *                                                                           *
// *    A schema owner can give their own schema to another authID, but they   *
// * cannot give the objects in a shared schema to another authID.  Only       *
// * DB__ROOT or a user with the ALTER_SCHEMA privilege can change the owners  *
// * of objects in a shared schema.  So if the schema is private, or if only   *
// * the schema is being given, we do standard authentication checking.  But   *
// * if giving all the objects in a shared schema, we change the check ID to   *
// * the default user to force the ALTER_SCHEMA privilege check.               *
// *                                                                           *
// *****************************************************************************

int32_t checkID = schemaOwnerID;

   if (objectType == COM_SHARED_SCHEMA_OBJECT && 
       dropBehavior == COM_CASCADE_DROP_BEHAVIOR)
      checkID = NA_UserIdDefault; 

   if (!isDDLOperationAuthorized(SQLOperation::ALTER_SCHEMA,checkID,checkID))
   {
      *CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
      return;
   }
 
ComObjectName objName(catalogName,schemaName,NAString("dummy"),COM_TABLE_NAME,TRUE);

   if (isSeabaseReservedSchema(objName) &&
       !Get_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL))
   {
      *CmpCommon::diags() << DgSqlCode(-CAT_USER_CANNOT_DROP_SMD_SCHEMA)
                          << DgSchemaName(schemaName.data());
      return;
   }
   
bool isVolatile = (memcmp(schemaName.data(),"VOLATILE_SCHEMA",strlen("VOLATILE_SCHEMA")) == 0);

// Can't give a schema whose name begins with VOLATILE_SCHEMA. 
   if (isVolatile)
   {
      *CmpCommon::diags() << DgSqlCode(-CAT_RESERVED_METADATA_SCHEMA_NAME)
                          << DgTableName(schemaName);
      return;
   }
   
int32_t newOwnerID = -1;

   if (ComUser::getAuthIDFromAuthName(giveSchemaNode->getAuthID().data(),
                                      newOwnerID) != 0)
   {
      *CmpCommon::diags() << DgSqlCode(-CAT_AUTHID_DOES_NOT_EXIST_ERROR)
                          << DgString0(giveSchemaNode->getAuthID().data());
      return;
   }

// *****************************************************************************
// *                                                                           *
// *   Drop behavior is only relevant for shared schemas.  For shared schemas, *
// * ownership of the schema OR the schema and all its objects may be given to *
// * another authorization ID.  For private schemas, all objects are owned by  *
// * the schema owner, so the drop behavior is always CASCADE.                 *
// *                                                                           *
// * NOTE: The syntax for drop behavior always defaults to RESTRICT; for       *
// *       private schemas this is simply ignored, as opposed to requiring     *
// *       users to always specify CASCASE.                                    *
// *                                                                           *
// *****************************************************************************

Lng32 cliRC = 0;
char buf[4000];
   
   if (objectType == COM_SHARED_SCHEMA_OBJECT && 
       dropBehavior == COM_RESTRICT_DROP_BEHAVIOR)
   {
      str_sprintf(buf,"UPDATE %s.\"%s\".%s "
                      "SET object_owner = %d "
                      "WHERE object_UID = %Ld",
                  getSystemCatalog(),SEABASE_MD_SCHEMA,SEABASE_OBJECTS,
                  newOwnerID,schemaUID);
      cliRC = cliInterface.executeImmediate(buf);
      if (cliRC < 0)
         cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
                      
      return;
   }
//
// At this point, we are giving all objects in the schema (as well as the 
// schema itself) to the new authorization ID.  If authentication is enabled,
// update the privileges first.
//
   if (isAuthorizationEnabled())
   {
      int32_t rc = transferObjectPrivs(getSystemCatalog(),catalogName.data(),
                                       schemaName.data(),newOwnerID,
                                       giveSchemaNode->getAuthID().data());
      if (rc != 0)
      {
         if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
         {
          //TODO: add error
         
         }
         return;
      }
   }
   
// Now update the object owner for all objects in the schema.
      
   str_sprintf(buf,"UPDATE %s.\"%s\".%s "
                   "SET object_owner = %d "
                   "WHERE catalog_name = '%s' AND schema_name = '%s'",
               getSystemCatalog(),SEABASE_MD_SCHEMA,SEABASE_OBJECTS,
               newOwnerID,catalogName.data(),schemaName.data());
   cliRC = cliInterface.executeImmediate(buf);
   if (cliRC < 0)
   {
      cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
      return;
   }             

// Verify all objects in the schema have been given to the new owner.   
   str_sprintf(buf,"SELECT COUNT(*) "
                   "FROM %s.\"%s\".%s "
                   "WHERE catalog_name = '%s' AND schema_name = '%s' AND "
                   "object_name <> '"SEABASE_SCHEMA_OBJECTNAME"' AND "
                   "object_owner <> %d " 
                   "FOR READ COMMITTED ACCESS",
               getSystemCatalog(),SEABASE_MD_SCHEMA,SEABASE_OBJECTS,
               catalogName.data(),schemaName.data(),newOwnerID);
               
int32_t length = 0;
int32_t rowCount = 0;

   cliRC = cliInterface.executeImmediate(buf,(char*)&rowCount,&length,NULL);
  
   if (cliRC < 0)
   {
      cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
      return;
   }
   
   if (rowCount > 0)
   {
      SEABASEDDL_INTERNAL_ERROR("Not all objects in schema were given");
      return;
   }
    
}
Esempio n. 17
0
CmpStoredProc::ExecStatus CmpInternalSP::fetch(CmpISPDataObject& data)
{
  CMPASSERT(state_ == PROCESS);

  // Need to send controls explicitly from the compiler space to the
  // cli context so ISP requests can perform CLI operations to extract
  // their values.
  // For now, only send controls for MODIFY, POPULATE INDEX, TRANSFORM,
  // PURGEDATA, MV_refresh and VALIDATE sp requests.
  // This also means RECOVER since these operations
  // can be perfomed through a RECOVER operation.
  //
  // VO, Versioning Light: Also send controls for sp_SchLevel
  //                       (UPGRADE and DOWNGRADE)
  if (procName() == "sp_partn" || 
      procName() == "sp_populate" ||
      procName() == "sp_purgedata" ||
      procName() == "sp_recover" ||
      procName() == "sp_transform" ||
      procName() == "sp_validate" || 
      procName() == "sp_purgedata" ||
      procName() == "sp_refresh" ||
      procName() == "sp_SchLevel")  
    {
      sendAllControls(FALSE, FALSE, TRUE);
      
      // set the parent qid for this session
      const char *parentQid = cmpContext()->sqlSession()->getParentQid();
      if (parentQid != NULL)
	{
	  setParentQidAtSession(cmpContext()->statementHeap(), parentQid);
	}
    }

  // Send sqlparser_flags
  if (Get_SqlParser_Flags(ALLOW_FUNNY_IDENTIFIER))
    sendParserFlag(ALLOW_FUNNY_IDENTIFIER);

  initSP_ERROR_STRUCT();
  SP_STATUS spStatus =
      (*(procFuncs_.procFunc_))( SP_PROC_FETCH, 
                                (SP_ROW_DATA)data.input(),
                                CmpSPExtractFunc,
                                (SP_ROW_DATA)data.output(), 
                                CmpSPFormatFunc,
                                (SP_KEY_VALUE)data.key(), 
                                CmpSPKeyValueFunc,
                                &procHandle_, 
                                procFuncs_.spHandle_, 
                                &spError_[0]);

  if (spStatus == SP_FAIL)
  {
    // Errors, go get them
    data.output()->MoveDiags(spError_, spStatus);
    if (CmpCommon::diags() != NULL)
    {
      data.output()->MergeDiags(CmpCommon::diags());
      CmpCommon::diags()->clear();
    }
    return FAIL;
  }

  if (CmpCommon::diags() != NULL)
  {
    data.output()->MergeDiags(CmpCommon::diags());
    CmpCommon::diags()->clear();
  }

  if ( spStatus == SP_MOREDATA)
  {
    return MOREDATA;
  }
  return SUCCESS;
}