void HSTableDef::setNATable() { //BindWA bindWA(ActiveSchemaDB(), CmpCommon::context(), FALSE, getIsNativeHbaseOrHive()); BindWA bindWA(ActiveSchemaDB(), CmpCommon::context(), FALSE, HSGlobalsClass::isNativeCat(*catalog_)); CorrName corrName(*object_, STMTHEAP, *schema_, *catalog_); if (isVolatile()) corrName.setIsVolatile(TRUE); Scan scan(corrName, NULL, REL_SCAN, STMTHEAP); ULng32 flagToSet = 0; // don't turn on flag unless next 'if' is true if (CmpCommon::context()->sqlSession()->volatileSchemaInUse()) flagToSet = ALLOW_VOLATILE_SCHEMA_IN_TABLE_NAME; // set ALLOW_VOLATILE_SCHEMA_IN_TABLE_NAME bit in Sql_ParserFlags // if needed, and return it to its entry value on exit PushAndSetSqlParserFlags savedParserFlags(flagToSet); scan.bindNode(&bindWA); if (!bindWA.errStatus()) { naTbl_ = bindWA.getNATable(corrName); HS_ASSERT(naTbl_); objectType_ = naTbl_->getObjectType(); } }
/////////////////////////////////////////////////////////////////// // This function takes as input an array of key values, where each // key value is in ASCII string format (the way it is stored in // catalogs). It encodes the key values and returns the encoded // value in the encodedKeyBuffer. // RETURNS: -1, if error. 0, if all Ok. /////////////////////////////////////////////////////////////////// short encodeKeyValues(desc_struct * column_descs, desc_struct * key_descs, NAString * inValuesArray[], // INPUT NABoolean isIndex, char * encodedKeyBuffer, // OUTPUT CollHeap * h, ComDiagsArea * diagsArea) { short error = 0; // assume all will go well NABoolean deleteLater = FALSE; // set up binder/generator stuff so expressions could be generated. InitSchemaDB(); CmpStatement cmpStatement(CmpCommon::context()); ActiveSchemaDB()->createStmtTables(); BindWA bindWA(ActiveSchemaDB(), CmpCommon::context()); Generator generator(CmpCommon::context()); ExpGenerator expGen(&generator); generator.appendAtEnd(); // alloc a new map table generator.setBindWA(&bindWA); generator.setExpGenerator(&expGen); FragmentDir * compFragDir = generator.getFragmentDir(); // create the fragment (independent code space) for this expression CollIndex myFragmentId = compFragDir->pushFragment(FragmentDir::MASTER); // space where RCB will be generated Space * space = generator.getSpace(); // Let's start with a list of size 4 rather than resizing continuously ValueIdList encodedValueIdList(4); desc_struct * column = column_descs; desc_struct * key = key_descs; Int32 i = 0; if (inValuesArray == NULL) deleteLater = TRUE; while (key) { // for an index, keys_desc has columns in the same order as columns_desc, // the following for loop is not needed. if (!isIndex) { column = column_descs; for (Int32 j = 0; j < key->body.keys_desc.tablecolnumber; j++) column = column->header.next; } if (inValuesArray[i] == NULL) inValuesArray[i] = getMinMaxValue(column, key, FALSE, h); ItemExpr * itemExpr = buildEncodeTree(column, key, inValuesArray[i], &generator, diagsArea); if (! itemExpr) return -1; encodedValueIdList.insert(itemExpr->getValueId()); i++; key = key->header.next; if (isIndex) column = column->header.next; } // allocate a work cri desc to encode keys. It has // 3 entries: 0, for consts. 1, for temps. // 2, for the encoded key. ex_cri_desc * workCriDesc = new(space) ex_cri_desc(3, space); short keyAtpIndex = 2; // where the encoded key will be built ULng32 encodedKeyLen; ex_expr * keExpr = 0; expGen.generateContiguousMoveExpr(encodedValueIdList, 0 /*don't add conv nodes*/, 0 /*atp*/, keyAtpIndex, ExpTupleDesc::SQLMX_KEY_FORMAT, encodedKeyLen, &keExpr); // create a DP2 expression and initialize it with the key encode expr. ExpDP2Expr * keyEncodeExpr = new(space) ExpDP2Expr(keExpr, workCriDesc, space); keyEncodeExpr->getExpr()->fixup(0,expGen.getPCodeMode(), (ex_tcb *)space,space, h, FALSE, NULL); atp_struct * workAtp = keyEncodeExpr->getWorkAtp(); workAtp->getTupp(keyAtpIndex).setDataPointer(encodedKeyBuffer); if (keyEncodeExpr->getExpr()->eval(workAtp, 0, space) == ex_expr::EXPR_ERROR) error = -1; if (deleteLater) delete [] inValuesArray; generator.removeAll(NULL); return error; }
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; }
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; }
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; }
// ***************************************************************************** // * * // * Function: checkAccessPrivileges * // * * // * This function determines if a user has the requesite privileges to * // * access the referenced objects that comprise the view. * // * * // ***************************************************************************** // * * // * Parameters: * // * * // * <vtul> const ParTableUsageList & In * // * is a reference to a list of objects used by the view. * // * * // * <vctcul> const ParViewColTableColsUsageList & In * // * is a reference to the list of columns used by the view. * // * * // * <privilegesBitmap> PrivMgrBitmap & Out * // * passes back the union of privileges the user has on the referenced * // * objects. * // * * // * <grantableBitmap> PrivMgrBitmap & Out * // * passes back the union of the with grant option authority the user has * // * on the referenced objects. * // * * // ***************************************************************************** // * * // * Returns: bool * // * * // * true: User has requisite privileges; bitmap unions returned. * // * false: Could not retrieve privileges or user does not have requesite * // * privileges; see diags area for error details. * // * * // ***************************************************************************** static bool checkAccessPrivileges( const ParTableUsageList & vtul, const ParViewColTableColsUsageList & vctcul, PrivMgrBitmap & privilegesBitmap, PrivMgrBitmap & grantableBitmap) { BindWA bindWA(ActiveSchemaDB(),CmpCommon::context(),FALSE/*inDDL*/); bool missingPrivilege = false; NAString extUsedObjName; // generate the lists of privileges and grantable privileges // a side effect is to return an error if basic privileges are not granted for (CollIndex i = 0; i < vtul.entries(); i++) { if (vtul[i].getSpecialType() == ExtendedQualName::SG_TABLE) continue; ComObjectName usedObjName(vtul[i].getQualifiedNameObj().getQualifiedNameAsAnsiString(), vtul[i].getAnsiNameSpace()); const NAString catalogNamePart = usedObjName.getCatalogNamePartAsAnsiString(); const NAString schemaNamePart = usedObjName.getSchemaNamePartAsAnsiString(TRUE); const NAString objectNamePart = usedObjName.getObjectNamePartAsAnsiString(TRUE); const NAString extUsedObjName = usedObjName.getExternalName(TRUE); CorrName cn(objectNamePart,STMTHEAP, schemaNamePart,catalogNamePart); NATable *naTable = bindWA.getNATable(cn); if (naTable == NULL) { SEABASEDDL_INTERNAL_ERROR("Bad NATable pointer in checkAccessPrivileges"); return false; } // Grab privileges from the NATable structure PrivMgrUserPrivs *privs = naTable->getPrivInfo(); if (privs == NULL) { *CmpCommon::diags() << DgSqlCode(-CAT_UNABLE_TO_RETRIEVE_PRIVS); return false; } // Requester must have at least select privilege if ( !privs->hasSelectPriv() ) missingPrivilege = true; // Summarize privileges privilegesBitmap &= privs->getObjectBitmap(); grantableBitmap &= privs->getGrantableBitmap(); } if (!missingPrivilege) return true; missingPrivilege = false; PrivColumnBitmap colPrivBitmap; PrivColumnBitmap colGrantableBitmap; PrivMgrPrivileges::setColumnPrivs(colPrivBitmap); PrivMgrPrivileges::setColumnPrivs(colGrantableBitmap); for (size_t i = 0; i < vctcul.entries(); i++) { const ParViewColTableColsUsage &vctcu = vctcul[i]; int32_t usingColNum = vctcu.getUsingViewColumnNumber(); const ColRefName &usedColRef = vctcu.getUsedObjectColumnName(); ComObjectName usedObjName; usedObjName = usedColRef.getCorrNameObj().getQualifiedNameObj(). getQualifiedNameAsAnsiString(); const NAString catalogNamePart = usedObjName.getCatalogNamePartAsAnsiString(); const NAString schemaNamePart = usedObjName.getSchemaNamePartAsAnsiString(TRUE); const NAString objectNamePart = usedObjName.getObjectNamePartAsAnsiString(TRUE); extUsedObjName = usedObjName.getExternalName(TRUE); CorrName cn(objectNamePart,STMTHEAP,schemaNamePart,catalogNamePart); NATable *naTable = bindWA.getNATable(cn); if (naTable == NULL) { SEABASEDDL_INTERNAL_ERROR("Bad NATable pointer in checkAccessPrivileges"); return -1; } const NAColumnArray &nacolArr = naTable->getNAColumnArray(); ComString usedObjColName(usedColRef.getColName()); const NAColumn * naCol = nacolArr.getColumn(usedObjColName); if (naCol == NULL) { *CmpCommon::diags() << DgSqlCode(-CAT_COLUMN_DOES_NOT_EXIST_ERROR) << DgColumnName(usedObjColName); return false; } int32_t usedColNumber = naCol->getPosition(); // Grab privileges from the NATable structure PrivMgrUserPrivs *privs = naTable->getPrivInfo(); if (privs == NULL) { *CmpCommon::diags() << DgSqlCode(-CAT_UNABLE_TO_RETRIEVE_PRIVS); return false; } // If the user is missing SELECT on at least one column-level privilege, // view cannot be created. No need to proceed. if (!privs->hasColSelectPriv(usedColNumber)) { missingPrivilege = true; break; } colPrivBitmap &= privs->getColumnPrivBitmap(usedColNumber); colGrantableBitmap &= privs->getColumnGrantableBitmap(usedColNumber); } if (missingPrivilege || vctcul.entries() == 0) { *CmpCommon::diags() << DgSqlCode(-4481) << DgString0("SELECT") << DgString1(extUsedObjName.data()); return false; } for (size_t i = FIRST_DML_COL_PRIV; i <= LAST_DML_COL_PRIV; i++ ) { if (colPrivBitmap.test(PrivType(i))) privilegesBitmap.set(PrivType(i)); if (colGrantableBitmap.test(PrivType(i))) grantableBitmap.set(PrivType(i)); } return true; }