Exemplo n.º 1
0
//
// 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_);
      
    }

}
Exemplo n.º 2
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;
}
// *****************************************************************************
// *                                                                           *
// * 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;
   }
    
}
// *****************************************************************************
// *                                                                           *
// * 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);
    
}
// *****************************************************************************
// *                                                                           *
// * Function: CmpSeabaseDDL::describeSchema                                   *
// *                                                                           *
// *    Provides text for SHOWDDL SCHEMA comnmand.                             *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// *  Parameters:                                                              *
// *                                                                           *
// *  <catalogName>                   const NAString &                In       *
// *    is a reference to a catalog name.                                      *
// *                                                                           *
// *  <schemaName>                    const NAString &                In       *
// *    is a reference to a schema name.                                       *
// *                                                                           *
// *  <output>                        NAString &                      Out      *
// *    passes back text for the SHOWDDL SCHEMA command, specifically the      *
// *  command to create the specified schema.                                  *
// *                                                                           *
// *****************************************************************************
// *                                                                           *
// * Returns: bool                                                             *
// *                                                                           *
// * true: Text returned for specified schema.                                 *
// * false: Could not retrieve information for specified schema.               *
// *                                                                           *
// *****************************************************************************
bool CmpSeabaseDDL::describeSchema(
   const NAString & catalogName,
   const NAString & schemaName,
   NAString & output)
   
{

ExeCliInterface cliInterface(STMTHEAP, NULL, NULL, 
CmpCommon::context()->sqlSession()->getParentQid());
ComSchemaClass schemaClass;
Int32 objectOwner;
Int32 schemaOwner;
ComObjectType objectType;

   CmpSeabaseDDL cmpSBD(STMTHEAP);
   if (cmpSBD.switchCompiler())
   {
      *CmpCommon::diags() << DgSqlCode(-CAT_UNABLE_TO_RETRIEVE_PRIVS);
      return false;
   }

Int64 schemaUID = getObjectTypeandOwner(&cliInterface,
                                        catalogName.data(),
                                        schemaName.data(),
                                        SEABASE_SCHEMA_OBJECTNAME,
                                        objectType,
                                        objectOwner);
                                        
   if (schemaUID < 0)
   {
      *CmpCommon::diags() << DgSqlCode(-CAT_SCHEMA_DOES_NOT_EXIST_ERROR)
                          << DgSchemaName(catalogName + "." + schemaName);
      cmpSBD.switchBackCompiler();
      return false;
   }
      
char username[MAX_USERNAME_LEN+1];
Int32 lActualLen = 0;
Int16 status = ComUser::getAuthNameFromAuthID(objectOwner,username, 
                                              MAX_USERNAME_LEN,lActualLen);
   if (status != FEOK)
   {
      *CmpCommon::diags() << DgSqlCode(-20235) // Error converting user ID.
                          << DgInt0(status)
                          << DgInt1(objectOwner);
      cmpSBD.switchBackCompiler();
      return false;
   }
      
// Generate output text
   output = "CREATE ";
   switch (objectType)
   {
      case COM_PRIVATE_SCHEMA_OBJECT:
         output += "PRIVATE";
         break;
      case COM_SHARED_SCHEMA_OBJECT:
         output += "SHARED";
         break;
      default:
         return false;
   }
   output += " SCHEMA \"";
   output += catalogName.data();
   output += "\".\"";
   output += schemaName.data();
   
// AUTHORIZATION clause is rarely used, but include it for replay.
   output += "\" AUTHORIZATION \"";
   output += username;
   output += "\";";

   cmpSBD.switchBackCompiler();
   return true;
   
}
// *****************************************************************************
// *                                                                           *
// * 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;

}