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
// ----------------------------------------------------------------------------- // * * // * 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; }
NABoolean CmpSqlSession::volatileSchemaInUse() { return ((volatileSchemaInUse_) && (NOT Get_SqlParser_Flags(DISABLE_VOLATILE_SCHEMA))); }
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; } }
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; }