// ---------------------------------------------------------------------------- // method: removeNARoutine // // The method is called when DDL is performed against a routine making its // definition incorrect. // It has a side affect of generating query invalidation keys that are // propagate to all the other processes that could have the routine stored // in cache. // ---------------------------------------------------------------------------- void NARoutineDB::removeNARoutine2(QualifiedName &routineName, ComQiScope qiScope, Int64 objUID) { NAHashDictionaryIterator<NARoutineDBKey,NARoutine> iter (*this); NARoutineDBKey *key = NULL; NARoutine *cachedNARoutine = NULL; NASet<Int64> objectUIDs(CmpCommon::statementHeap(), 1); // If there are no items in cache, skip if (entries() > 0) { NASet<Int64> objectUIDs(CmpCommon::statementHeap(), 1); // iterate over all entries and remove the ones that match the name iter.reset(); iter.getNext(key,cachedNARoutine); while(key && cachedNARoutine) { if (cachedNARoutine->getSqlName() == routineName) { objectUIDs.insert(cachedNARoutine->getRoutineID()); moveRoutineToDeleteList(cachedNARoutine,key); } iter.getNext(key,cachedNARoutine); } } // clear out the other users' caches too. if (qiScope == REMOVE_FROM_ALL_USERS) { // There are some scenarios where the affected object does not have an // NARoutine cache entry. However, other processes may have this routine // in their caches. Go ahead and create an invalidation key if (0 == objectUIDs.entries()) objectUIDs.insert(objUID); Int32 numKeys = objectUIDs.entries(); SQL_QIKEY qiKeys[numKeys]; for (CollIndex i = 0; i < numKeys; i++) { qiKeys[i].ddlObjectUID = objectUIDs[i]; qiKeys[i].operation[0] = 'O'; qiKeys[i].operation[1] = 'R'; } long retcode = SQL_EXEC_SetSecInvalidKeys(numKeys, qiKeys); } }
// ---------------------------------------------------------------------------- // method: free_entries_with_QI_key // // This method is sent a list of query invalidation keys. // It looks through the list of routines to see if any of them need to be // removed from cache because their definitions are no longer valid. // // numKeys - number of existing invalidation keys // qiKeyArray - actual keys // ---------------------------------------------------------------------------- void NARoutineDB::free_entries_with_QI_key(Int32 numKeys, SQL_QIKEY* qiKeyArray) { NAHashDictionaryIterator<NARoutineDBKey,NARoutine> iter (*this); NARoutineDBKey *key; NARoutine *routine; iter.getNext(key,routine); while(key && routine) { // See if item should be removed if (qiCheckForInvalidObject(numKeys, qiKeyArray, routine->getRoutineID(), routine->getSecKeySet())) moveRoutineToDeleteList(routine, key); iter.getNext(key,routine); } }
void CmpSeabaseDDL::dropSeabaseRoutine(StmtDDLDropRoutine * dropRoutineNode, NAString &currCatName, NAString &currSchName) { Lng32 retcode = 0; ComObjectName routineName(dropRoutineNode->getRoutineName()); ComAnsiNamePart currCatAnsiName(currCatName); ComAnsiNamePart currSchAnsiName(currSchName); routineName.applyDefaults(currCatAnsiName, currSchAnsiName); const NAString catalogNamePart = routineName.getCatalogNamePartAsAnsiString(); const NAString schemaNamePart = routineName.getSchemaNamePartAsAnsiString(TRUE); const NAString objectNamePart = routineName.getObjectNamePartAsAnsiString(TRUE); const NAString extRoutineName = routineName.getExternalName(TRUE); ExpHbaseInterface * ehi = NULL; ExeCliInterface cliInterface(STMTHEAP, NULL, NULL, CmpCommon::context()->sqlSession()->getParentQid()); ehi = allocEHI(); if (ehi == NULL) { processReturn(); return; } retcode = existsInSeabaseMDTable(&cliInterface, catalogNamePart, schemaNamePart, objectNamePart, COM_USER_DEFINED_ROUTINE_OBJECT, TRUE, FALSE); if (retcode < 0) { deallocEHI(ehi); processReturn(); return; } if (retcode == 0) // does not exist { *CmpCommon::diags() << DgSqlCode(-1389) << DgString0(extRoutineName); deallocEHI(ehi); processReturn(); return; } // get objectOwner Int64 objUID = 0; Int32 objectOwnerID = 0; Int32 schemaOwnerID = 0; Int64 objectFlags = 0; // see if routine is cached BindWA bindWA(ActiveSchemaDB(), CmpCommon::context(), FALSE/*inDDL*/); NARoutineDB *pRoutineDBCache = ActiveSchemaDB()->getNARoutineDB(); QualifiedName qualRoutineName(routineName, STMTHEAP); NARoutineDBKey key(qualRoutineName, STMTHEAP); NARoutine *cachedNARoutine = pRoutineDBCache->get(&bindWA, &key); if (cachedNARoutine) { objUID = cachedNARoutine->getRoutineID(); objectOwnerID = cachedNARoutine->getObjectOwner(); schemaOwnerID = cachedNARoutine->getSchemaOwner(); } else { objUID = getObjectInfo(&cliInterface, catalogNamePart.data(), schemaNamePart.data(), objectNamePart.data(), COM_USER_DEFINED_ROUTINE_OBJECT, objectOwnerID,schemaOwnerID,objectFlags); if (objUID < 0 || objectOwnerID == 0 || schemaOwnerID == 0) { deallocEHI(ehi); processReturn(); return; } } // Verify user has privilege to drop routine if (!isDDLOperationAuthorized(SQLOperation::DROP_ROUTINE,objectOwnerID,schemaOwnerID)) { *CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED); deallocEHI(ehi); processReturn (); return; } // Determine if this function is referenced by any other objects. Lng32 cliRC = 0; Queue * usingViewsQueue = NULL; if (dropRoutineNode->getDropBehavior() == COM_RESTRICT_DROP_BEHAVIOR) { NAString usingObjName; cliRC = getUsingObject(&cliInterface, objUID, usingObjName); if (cliRC < 0) { deallocEHI(ehi); processReturn(); return; } if (cliRC != 100) // found an object { *CmpCommon::diags() << DgSqlCode(-CAT_DEPENDENT_VIEW_EXISTS) << DgTableName(usingObjName); deallocEHI(ehi); processReturn(); return; } } else if (dropRoutineNode->getDropBehavior() == COM_CASCADE_DROP_BEHAVIOR) { cliRC = getUsingViews(&cliInterface, objUID, usingViewsQueue); if (cliRC < 0) { deallocEHI(ehi); processReturn(); return; } } if (usingViewsQueue) { usingViewsQueue->position(); for (int idx = 0; idx < usingViewsQueue->numEntries(); idx++) { OutputInfo * vi = (OutputInfo*)usingViewsQueue->getNext(); char * viewName = vi->get(0); if (dropOneTableorView(cliInterface,viewName,COM_VIEW_OBJECT,false)) { deallocEHI(ehi); processReturn(); return; } } } // Removed routine from metadata if (dropSeabaseObject(ehi, dropRoutineNode->getRoutineName(), currCatName, currSchName, COM_USER_DEFINED_ROUTINE_OBJECT, TRUE, FALSE)) { deallocEHI(ehi); processReturn(); return; } // Remove cached entries in other processes pRoutineDBCache->removeNARoutine(qualRoutineName, NARoutineDB::REMOVE_FROM_ALL_USERS, objUID); deallocEHI(ehi); processReturn(); return; }