|  | /********************************************************************** | 
|  | // @@@ START COPYRIGHT @@@ | 
|  | // | 
|  | // Licensed to the Apache Software Foundation (ASF) under one | 
|  | // or more contributor license agreements.  See the NOTICE file | 
|  | // distributed with this work for additional information | 
|  | // regarding copyright ownership.  The ASF licenses this file | 
|  | // to you under the Apache License, Version 2.0 (the | 
|  | // "License"); you may not use this file except in compliance | 
|  | // with the License.  You may obtain a copy of the License at | 
|  | // | 
|  | //   http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, | 
|  | // software distributed under the License is distributed on an | 
|  | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
|  | // KIND, either express or implied.  See the License for the | 
|  | // specific language governing permissions and limitations | 
|  | // under the License. | 
|  | // | 
|  | // @@@ END COPYRIGHT @@@ | 
|  | **********************************************************************/ | 
|  |  | 
|  | /* -*-C++-*- | 
|  | ***************************************************************************** | 
|  | * | 
|  | * File:         CmpSeabaseDDLview.cpp | 
|  | * Description:  Implements ddl views for SQL/seabase tables. | 
|  | * | 
|  | * | 
|  | * Created:     6/30/2013 | 
|  | * Language:     C++ | 
|  | * | 
|  | * | 
|  | ***************************************************************************** | 
|  | */ | 
|  |  | 
|  | #define   SQLPARSERGLOBALS_FLAGS	// must precede all #include's | 
|  | #define   SQLPARSERGLOBALS_NADEFAULTS | 
|  |  | 
|  | #include "ComObjectName.h" | 
|  | #include "ComUser.h" | 
|  | #include "ComViewColUsage.h" | 
|  |  | 
|  | #include "StmtDDLCreateView.h" | 
|  | #include "StmtDDLDropView.h" | 
|  | #include "ElemDDLColDefArray.h" | 
|  | #include "ElemDDLColRefArray.h" | 
|  |  | 
|  | #include "SchemaDB.h" | 
|  | #include "CmpSeabaseDDLincludes.h" | 
|  |  | 
|  | #include "ExpHbaseInterface.h" | 
|  |  | 
|  | #include "ExExeUtilCli.h" | 
|  | #include "Generator.h" | 
|  |  | 
|  | // for privilege checking | 
|  | #include "PrivMgrCommands.h" | 
|  | #include "PrivMgrDefs.h" | 
|  | #include "PrivMgrPrivileges.h" | 
|  | #include <bitset> | 
|  |  | 
|  | #include "ComCextdecs.h" | 
|  |  | 
|  | static bool checkAccessPrivileges( | 
|  | const ParTableUsageList & vtul, | 
|  | const ParViewColTableColsUsageList & vctcul, | 
|  | NABoolean viewCreator, | 
|  | Int32 userID, | 
|  | PrivMgrBitmap & privilegesBitmap, | 
|  | PrivMgrBitmap & grantableBitmap); | 
|  |  | 
|  |  | 
|  | short CmpSeabaseDDL::buildViewText(StmtDDLCreateView * createViewParseNode, | 
|  | NAString &viewText) | 
|  | { | 
|  | const ParNameLocList &nameLocList = createViewParseNode->getNameLocList(); | 
|  | const char *pInputStr = nameLocList.getInputStringPtr(); | 
|  |  | 
|  | StringPos inputStrPos = createViewParseNode->getStartPosition(); | 
|  |  | 
|  | for (CollIndex i = 0; i < nameLocList.entries(); i++) | 
|  | { | 
|  | const ParNameLoc &nameLoc = nameLocList[i]; | 
|  | const NAString &nameExpanded = nameLoc.getExpandedName(FALSE/*no assert*/); | 
|  | size_t nameAsIs = 0; | 
|  | size_t nameLenInBytes = 0; | 
|  | size_t nameLenInNAWchars = 0; | 
|  |  | 
|  | // | 
|  | // When the character set of the input string is a variable-length/width | 
|  | // multi-byte characters set, the value returned by getNameLength() | 
|  | // may not be numerically equal to the number of bytes in the original | 
|  | // input string that we need to skip.  So, we get the character | 
|  | // conversion routines to tell us how many bytes we need to skip. | 
|  | // | 
|  | CMPASSERT(nameLocList.getInputStringCharSet() EQU CharInfo::UTF8); | 
|  | enum cnv_charset eCnvCS = convertCharsetEnum(nameLocList.getInputStringCharSet()); | 
|  |  | 
|  | const char *str_to_test = (const char *) &pInputStr[nameLoc.getNamePosition()]; | 
|  | const Int32 max_bytes2cnv = createViewParseNode->getEndPosition() | 
|  | - nameLoc.getNamePosition() + 1; | 
|  | const char *tmp_out_bufr = new (STMTHEAP) char[max_bytes2cnv * 4 + 10 /* Ensure big enough! */ ]; | 
|  | char * p1stUnstranslatedChar = NULL; | 
|  | UInt32 iTransCharCountInChars = 0; | 
|  | Int32 cnvErrStatus = LocaleToUTF16( | 
|  | cnv_version1          // in  - const enum cnv_version version | 
|  | , str_to_test           // in  - const char *in_bufr | 
|  | , max_bytes2cnv         // in  - const int in_len | 
|  | , tmp_out_bufr          // out - const char *out_bufr | 
|  | , max_bytes2cnv * 4 + 1 // in  - const int out_len | 
|  | , eCnvCS                // in  - enum cnv_charset charset | 
|  | , p1stUnstranslatedChar // out - char * & first_untranslated_char | 
|  | , NULL                  // out - unsigned int *output_data_len_p | 
|  | , 0                     // in  - const int cnv_flags | 
|  | , (Int32)TRUE           // in  - const int addNullAtEnd_flag | 
|  | , &iTransCharCountInChars  // out - unsigned int * translated_char_cnt_p | 
|  | , nameLoc.getNameLength()     // in  - unsigned int max_NAWchars_to_convert | 
|  | ); | 
|  | // NOTE: No errors should be possible -- string has been converted before. | 
|  |  | 
|  | NADELETEBASIC (tmp_out_bufr, STMTHEAP); | 
|  | nameLenInBytes = p1stUnstranslatedChar - str_to_test; | 
|  |  | 
|  | // If name not expanded, then use the original name as is | 
|  | if (nameExpanded.isNull()) | 
|  | nameAsIs = nameLenInBytes; | 
|  |  | 
|  | // Copy from (last position in) input string up to current name | 
|  | viewText += NAString(&pInputStr[inputStrPos], | 
|  | nameLoc.getNamePosition() - inputStrPos + | 
|  | nameAsIs); | 
|  |  | 
|  | if (NOT nameAsIs) // original name to be replaced with expanded | 
|  | { | 
|  | size_t namePos = nameLoc.getNamePosition(); | 
|  | size_t nameLen = nameLoc.getNameLength(); | 
|  |  | 
|  | if ( ( /* case #1 */ pInputStr[namePos] EQU '*' OR | 
|  | /* case #2 */ pInputStr[namePos] EQU '"' ) | 
|  | AND nameExpanded.data()[0] NEQ '"' | 
|  | AND namePos > 1 | 
|  | AND ( pInputStr[namePos - 1] EQU '_' OR | 
|  | isAlNumIsoMapCS((unsigned char)pInputStr[namePos - 1]) ) | 
|  | ) | 
|  | { | 
|  | // insert a blank separator to avoid syntax error | 
|  | // WITHOUT FIX | 
|  | // ex#1: CREATE VIEW C.S.V AS SELECTC.S.T.COL FROM C.S.T | 
|  | // ex#2: CREATE VIEW C.S.V AS SELECTC.S.T.COL FROM C.S.T | 
|  | viewText += " "; // the FIX | 
|  | // WITH FIX | 
|  | // ex#1: CREATE VIEW C.S.V AS SELECT C.S.T.COL FROM C.S.T | 
|  | // ex#2: CREATE VIEW C.S.V AS SELECT C.S.T.COL FROM C.S.T | 
|  | } | 
|  |  | 
|  | // Add the expanded (fully qualified) name (if exists) | 
|  | viewText += nameExpanded; | 
|  |  | 
|  | if ( ( /* case #3 */ ( pInputStr[namePos] EQU '*' AND nameLen EQU 1 ) OR | 
|  | /* case #4 */ pInputStr[namePos + nameLen - 1] EQU '"' ) | 
|  | AND nameExpanded.data()[nameExpanded.length() - 1] NEQ '"' | 
|  | AND pInputStr[namePos + nameLen] NEQ '\0' | 
|  | AND ( pInputStr[namePos + nameLen] EQU '_' OR | 
|  | isAlNumIsoMapCS((unsigned char)pInputStr[namePos + nameLen]) ) | 
|  | ) | 
|  | { | 
|  | // insert a blank separator to avoid syntax error | 
|  | // WITHOUT FIX | 
|  | // ex: CREATE VIEW C.S.V AS SELECT C.S.T.COLFROM C.S.T | 
|  | viewText += " "; // the FIX | 
|  | // WITH FIX | 
|  | // ex: CREATE VIEW C.S.V AS SELECT C.S.T.COL FROM C.S.T | 
|  | } | 
|  | } // if (NOT nameAsIs) | 
|  |  | 
|  | // Advance input pointer beyond original name in input string | 
|  | inputStrPos = nameLoc.getNamePosition() + nameLenInBytes /* same as nameLenInNAWchars */; | 
|  |  | 
|  | } // for | 
|  |  | 
|  | if (createViewParseNode->getEndPosition() >= inputStrPos) | 
|  | { | 
|  | viewText += NAString(&pInputStr[inputStrPos], | 
|  | createViewParseNode->getEndPosition() | 
|  | + 1 - inputStrPos); | 
|  | } | 
|  | else | 
|  | CMPASSERT(createViewParseNode->getEndPosition() == inputStrPos-1); | 
|  |  | 
|  | PrettifySqlText(viewText, | 
|  | CharType::getCharSetAsPrefix(SqlParser_NATIONAL_CHARSET)); | 
|  |  | 
|  | return 0; | 
|  | } // CmpSeabaseDDL::buildViewText() | 
|  |  | 
|  | short CmpSeabaseDDL::buildViewColInfo(StmtDDLCreateView * createViewParseNode, | 
|  | ElemDDLColDefArray *colDefArray) | 
|  | { | 
|  | // Builds the list of ElemDDLColDef parse nodes from the list of | 
|  | // NAType parse nodes derived from the query expression parse sub-tree | 
|  | // and the list of ElemDDLColViewDef parse nodes from the parse tree. | 
|  | // This extra step is needed to invoke (reuse) global func CatBuildColumnList. | 
|  |  | 
|  | CMPASSERT(createViewParseNode->getQueryExpression()-> | 
|  | getOperatorType() EQU REL_ROOT); | 
|  |  | 
|  | RelRoot * pQueryExpr = (RelRoot *)createViewParseNode->getQueryExpression(); | 
|  |  | 
|  | const ValueIdList &valIdList = pQueryExpr->compExpr();        // select-list | 
|  | CMPASSERT(valIdList.entries() > 0); | 
|  |  | 
|  | CollIndex numOfCols(createViewParseNode->getViewColDefArray().entries()); | 
|  | if (numOfCols NEQ valIdList.entries()) | 
|  | { | 
|  | *CmpCommon::diags() << DgSqlCode(-1108) //CAT_NUM_OF_VIEW_COLS_NOT_MATCHED | 
|  | << DgInt0(numOfCols) | 
|  | << DgInt1(valIdList.entries()); | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | const ElemDDLColViewDefArray &viewColDefArray = createViewParseNode-> | 
|  | getViewColDefArray(); | 
|  | for (CollIndex i = 0; i < numOfCols; i++) | 
|  | { | 
|  | // ANSI 11.19 SR8 | 
|  | if (viewColDefArray[i]->getColumnName().isNull()) | 
|  | { | 
|  | *CmpCommon::diags() << DgSqlCode(-1099) //CAT_VIEW_COLUMN_UNNAMED | 
|  | << DgInt0(i+1); | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | colDefArray->insert(new (STMTHEAP) ElemDDLColDef | 
|  | ( NULL, &viewColDefArray[i]->getColumnName() | 
|  | , (NAType *)&valIdList[i].getType() | 
|  | , NULL    // col attr list (not needed) | 
|  |  | 
|  | , STMTHEAP)); | 
|  |  | 
|  | if (viewColDefArray[i]->isHeadingSpecified()) | 
|  | { | 
|  | (*colDefArray)[i]->setIsHeadingSpecified(TRUE); | 
|  | (*colDefArray)[i]->setHeading(viewColDefArray[i]->getHeading()); | 
|  | } | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | // Build view column usages -> relate view-col <=> referenced-col | 
|  | // This relationship is a string of values that gets stored in the TEXT table | 
|  | short CmpSeabaseDDL::buildViewTblColUsage(const StmtDDLCreateView * createViewParseNode, | 
|  | const ComTdbVirtTableColumnInfo * colInfoArray, | 
|  | const Int64 objUID, NAString &viewColUsageText) | 
|  | { | 
|  | const ParViewUsages &vu = createViewParseNode->getViewUsages(); | 
|  | const ParViewColTableColsUsageList &vctcul = vu.getViewColTableColsUsageList(); | 
|  | BindWA bindWA(ActiveSchemaDB(),CmpCommon::context(),FALSE/*inDDL*/); | 
|  |  | 
|  | for (size_t i = 0; i < vctcul.entries(); i++) | 
|  | { | 
|  | const ParViewColTableColsUsage &vctcu = vctcul[i]; | 
|  | int32_t usingColNum = vctcu.getUsingViewColumnNumber(); | 
|  |  | 
|  | // Get column number for referenced table | 
|  | 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); | 
|  | CorrName cn(objectNamePart,STMTHEAP,schemaNamePart,catalogNamePart); | 
|  |  | 
|  | NATable *naTable = bindWA.getNATableInternal(cn); | 
|  | if (naTable == NULL) | 
|  | { | 
|  | SEABASEDDL_INTERNAL_ERROR("Bad NATable pointer in createSeabaseView"); | 
|  | 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 -1; | 
|  | } | 
|  |  | 
|  | ComViewColUsage colUsage(objUID, usingColNum, | 
|  | naTable->objectUid().get_value(), | 
|  | naCol->getPosition(), | 
|  | naTable->getObjectType()); | 
|  | NAString viewColUsageStr; | 
|  | colUsage.packUsage(viewColUsageStr); | 
|  | viewColUsageText += viewColUsageStr; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | const char * | 
|  | CmpSeabaseDDL::computeCheckOption(StmtDDLCreateView * createViewParseNode) | 
|  | { | 
|  | if (createViewParseNode->isWithCheckOptionSpecified()) | 
|  | { | 
|  | switch (createViewParseNode->getCheckOptionLevel()) | 
|  | { | 
|  | case COM_CASCADED_LEVEL : | 
|  | return COM_CASCADE_CHECK_OPTION_LIT; | 
|  | break; | 
|  | case COM_LOCAL_LEVEL: | 
|  | return COM_LOCAL_CHECK_OPTION_LIT; | 
|  | break; | 
|  | case COM_UNKNOWN_LEVEL : | 
|  | return COM_UNKNOWN_CHECK_OPTION_LIT; | 
|  | break; | 
|  | default: | 
|  | return COM_NONE_CHECK_OPTION_LIT; | 
|  | break; | 
|  | } // switch | 
|  | } | 
|  | else | 
|  | { | 
|  | return COM_NONE_CHECK_OPTION_LIT; | 
|  | } | 
|  |  | 
|  | return NULL; | 
|  |  | 
|  | } // CmpSeabaseDDL::computeCheckOption() | 
|  |  | 
|  | short CmpSeabaseDDL::updateViewUsage(StmtDDLCreateView * createViewParseNode, | 
|  | Int64 viewUID, | 
|  | ExeCliInterface * cliInterface) | 
|  | { | 
|  | const ParViewUsages &vu = createViewParseNode->getViewUsages(); | 
|  | const ParTableUsageList &vtul = vu.getViewTableUsageList(); | 
|  |  | 
|  | char query[1000]; | 
|  | char hiveObjsNoUsage[1010]; | 
|  | hiveObjsNoUsage[0] = 0; | 
|  | for (CollIndex i = 0; i < vtul.entries(); i++) | 
|  | { | 
|  | 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); | 
|  |  | 
|  | char objType[10]; | 
|  | Int64 usedObjUID = -1; | 
|  | if ((CmpCommon::getDefault(HIVE_VIEWS) == DF_ON) && | 
|  | (catalogNamePart == HIVE_SYSTEM_CATALOG)) | 
|  | { | 
|  | CorrName cn(objectNamePart,STMTHEAP, schemaNamePart,catalogNamePart); | 
|  |  | 
|  | BindWA bindWA(ActiveSchemaDB(),CmpCommon::context(),FALSE/*inDDL*/); | 
|  |  | 
|  | NATable *naTable = bindWA.getNATableInternal(cn); | 
|  | if (naTable == NULL) | 
|  | { | 
|  | SEABASEDDL_INTERNAL_ERROR("Bad NATable pointer in updateViewUsage"); | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | if ((naTable->isHiveTable()) && | 
|  | (NOT naTable->hasExternalTable()) && | 
|  | (CmpCommon::getDefault(HIVE_VIEWS_CREATE_EXTERNAL_TABLE) == DF_ON)) | 
|  | { | 
|  | // create an external table for this hive table. | 
|  | str_sprintf(query, "create external table \"%s\" for %s.\"%s\".\"%s\"", | 
|  | objectNamePart.data(), | 
|  | catalogNamePart.data(), | 
|  | schemaNamePart.data(), | 
|  | objectNamePart.data()); | 
|  | Lng32 cliRC = cliInterface->executeImmediate(query); | 
|  | if (cliRC < 0) | 
|  | { | 
|  | cliInterface->retrieveSQLDiagnostics(CmpCommon::diags()); | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | // remove NATable and reload it to include external table defn. | 
|  | ActiveSchemaDB()->getNATableDB()->removeNATable | 
|  | (cn, | 
|  | ComQiScope::REMOVE_MINE_ONLY, COM_BASE_TABLE_OBJECT, | 
|  | FALSE, FALSE); | 
|  |  | 
|  | naTable = bindWA.getNATableInternal(cn); | 
|  | if (naTable == NULL) | 
|  | { | 
|  | SEABASEDDL_INTERNAL_ERROR("Bad NATable pointer in updateViewUsage"); | 
|  | return -1; | 
|  | } | 
|  | } | 
|  |  | 
|  | if ((naTable->isHiveTable()) && | 
|  | (naTable->hasExternalTable()) && | 
|  | (naTable->objectUid().get_value() > 0)) | 
|  | { | 
|  | usedObjUID = naTable->objectUid().get_value(); | 
|  | strcpy(objType, COM_BASE_TABLE_OBJECT_LIT); | 
|  | } | 
|  |  | 
|  | // do not put in view usage list if it doesn't have an external table | 
|  | if (usedObjUID == -1) | 
|  | { | 
|  | appendErrorObjName(hiveObjsNoUsage, extUsedObjName); | 
|  | continue; | 
|  | } | 
|  | } // hive table | 
|  |  | 
|  | if (usedObjUID == -1) | 
|  | usedObjUID = getObjectUID(cliInterface, | 
|  | catalogNamePart.data(), schemaNamePart.data(), | 
|  | objectNamePart.data(), | 
|  | NULL, | 
|  | NULL, | 
|  | objType); | 
|  | if (usedObjUID < 0) | 
|  | { | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | str_sprintf(query, "upsert into %s.\"%s\".%s values (%Ld, %Ld, '%s', 0 )", | 
|  | getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_VIEWS_USAGE, | 
|  | viewUID, | 
|  | usedObjUID, | 
|  | objType); | 
|  | Lng32 cliRC = cliInterface->executeImmediate(query); | 
|  | if (cliRC < 0) | 
|  | { | 
|  | cliInterface->retrieveSQLDiagnostics(CmpCommon::diags()); | 
|  |  | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | } // for | 
|  |  | 
|  | // Views can also reference functions.  Add the list of functions | 
|  | // referenced to the VIEWS_USAGE table. | 
|  | const LIST(OptUDFInfo *) & uul = createViewParseNode->getUDFList(); | 
|  | for (CollIndex u = 0; u < uul.entries(); u++) | 
|  | { | 
|  |  | 
|  | char query[1000]; | 
|  | str_sprintf(query, "upsert into %s.\"%s\".%s values (%Ld, %Ld, '%s', 0 )", | 
|  | getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_VIEWS_USAGE, | 
|  | viewUID, | 
|  | uul[u]->getUDFUID(), | 
|  | COM_USER_DEFINED_ROUTINE_OBJECT_LIT); | 
|  | Lng32 cliRC = cliInterface->executeImmediate(query); | 
|  |  | 
|  |  | 
|  | if (cliRC < 0) | 
|  | { | 
|  | cliInterface->retrieveSQLDiagnostics(CmpCommon::diags()); | 
|  |  | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | } // for | 
|  |  | 
|  | if (strlen(hiveObjsNoUsage) > 0) | 
|  | { | 
|  | NAString reason; | 
|  | reason = hiveObjsNoUsage; | 
|  | *CmpCommon::diags() << DgSqlCode(CAT_HIVE_VIEW_USAGE_UNAVAILABLE) | 
|  | << DgString0(reason); | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | // **************************************************************************** | 
|  | // method: gatherViewPrivileges | 
|  | // | 
|  | // For each referenced object (table or view) directly associated with the new | 
|  | // view, combine privilege and grantable bitmaps together.  The list of | 
|  | // privileges gathered will be assigned as default privileges as the privilege | 
|  | // owner values. | 
|  | // | 
|  | // TBD:  when column privileges are added, need to check only the affected | 
|  | //       columns | 
|  | // | 
|  | // Parameters: | 
|  | //    createViewNode - for list of objects and isUpdatable/isInsertable flags | 
|  | //    cliInterface - used to get UID of referenced object | 
|  | //    viewCreator - determines which authID to use to gather privs | 
|  | //    userID - userID to use when root is performing operations on behalf | 
|  | //      of another user. | 
|  | //    privilegeBitmap - returns privileges this user has on the view | 
|  | //    grantableBitmap - returns privileges this user can grant | 
|  | // | 
|  | // returns: | 
|  | //    0 - successful | 
|  | //   -1 - user does not have the privilege | 
|  | // **************************************************************************** | 
|  | short CmpSeabaseDDL::gatherViewPrivileges (const StmtDDLCreateView * createViewNode, | 
|  | ExeCliInterface * cliInterface, | 
|  | NABoolean viewCreator, | 
|  | Int32 userID, | 
|  | PrivMgrBitmap &privilegesBitmap, | 
|  | PrivMgrBitmap &grantableBitmap) | 
|  | { | 
|  | if (!isAuthorizationEnabled()) | 
|  | return 0; | 
|  |  | 
|  | // set all bits to true initially, we will be ANDing with privileges | 
|  | // from all referenced objects | 
|  | // default table and view privileges are the same, set up default values | 
|  | PrivMgr::setTablePrivs(privilegesBitmap); | 
|  | PrivMgr::setTablePrivs(grantableBitmap); | 
|  |  | 
|  | const ParViewUsages &vu = createViewNode->getViewUsages(); | 
|  | const ParTableUsageList &vtul = vu.getViewTableUsageList(); | 
|  | const ParViewColTableColsUsageList &vctcul = vu.getViewColTableColsUsageList(); | 
|  |  | 
|  | // If DB__ROOT, no need to gather privileges | 
|  | if (!checkAccessPrivileges(vtul,vctcul,viewCreator,userID,privilegesBitmap,grantableBitmap)) | 
|  | return -1; | 
|  |  | 
|  | // If view is not updatable or insertable, turn off privs in bitmaps | 
|  | if (!createViewNode->getIsUpdatable()) | 
|  | { | 
|  | privilegesBitmap.set(UPDATE_PRIV,false); | 
|  | grantableBitmap.set(UPDATE_PRIV, false); | 
|  | privilegesBitmap.set(DELETE_PRIV,false); | 
|  | grantableBitmap.set(DELETE_PRIV, false); | 
|  | } | 
|  |  | 
|  | if (!createViewNode->getIsInsertable()) | 
|  | { | 
|  | privilegesBitmap.set(INSERT_PRIV,false); | 
|  | grantableBitmap.set(INSERT_PRIV, false); | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | // **************************************************************************** | 
|  | // method: getListOfReferencedTables | 
|  | // | 
|  | // Returns a list of all tables that are being referenced by the passed in | 
|  | // view UID | 
|  | // | 
|  | // Parameters: | 
|  | //    cliInterface - used to get the list of object usages | 
|  | //    objectUID - the UID being processed | 
|  | //    tableList - a list of objectRefdByMe structures describing each usage | 
|  | // | 
|  | // returns: | 
|  | //    0 - successful | 
|  | //   -1 - unexpected error occurred | 
|  | // **************************************************************************** | 
|  | short CmpSeabaseDDL::getListOfReferencedTables( | 
|  | ExeCliInterface * cliInterface, | 
|  | const Int64 objectUID, | 
|  | NAList<objectRefdByMe> &tablesList ) | 
|  | { | 
|  | Lng32 retcode = 0; | 
|  |  | 
|  | NAList <objectRefdByMe> tempRefdList(STMTHEAP); | 
|  | retcode = getListOfDirectlyReferencedObjects (cliInterface, objectUID, tempRefdList); | 
|  |  | 
|  | // If unexpected error - return | 
|  | if (retcode < 0) | 
|  | { | 
|  | if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0) | 
|  | SEABASEDDL_INTERNAL_ERROR("getting list of referenced tables"); | 
|  | return -1; | 
|  | } | 
|  |  | 
|  |  | 
|  | // For each view in the list, call getReferencedTables recursively | 
|  | for (CollIndex i = 0; i < tempRefdList.entries(); i++) | 
|  | { | 
|  | objectRefdByMe objectRefd = tempRefdList[i]; | 
|  |  | 
|  | // views should only be referencing tables, other views, or functions | 
|  | CMPASSERT(objectRefd.objectType == COM_BASE_TABLE_OBJECT_LIT || | 
|  | objectRefd.objectType == COM_USER_DEFINED_ROUTINE_OBJECT_LIT || | 
|  | objectRefd.objectType == COM_SEQUENCE_GENERATOR_OBJECT_LIT || | 
|  | objectRefd.objectType == COM_VIEW_OBJECT_LIT); | 
|  |  | 
|  | // found a table, add to list | 
|  | if (objectRefd.objectType == COM_BASE_TABLE_OBJECT_LIT) | 
|  | { | 
|  | // First make sure it has not already been added to the list | 
|  | NABoolean foundEntry = FALSE; | 
|  | for (CollIndex j = 0; j < tablesList.entries(); j++) | 
|  | { | 
|  | if (tablesList[j].objectUID == objectRefd.objectUID) | 
|  | foundEntry = TRUE; | 
|  | } | 
|  | if (!foundEntry) | 
|  | tablesList.insert(objectRefd); | 
|  | } | 
|  |  | 
|  | // found a view, get objects associated with the view | 
|  | if (objectRefd.objectType == COM_VIEW_OBJECT_LIT) | 
|  | getListOfReferencedTables(cliInterface, objectRefd.objectUID, tablesList); | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | // **************************************************************************** | 
|  | // method: getListOfDirectlyReferencedObjects | 
|  | // | 
|  | // Returns a list of objects that are being directly referenced by the passed | 
|  | // in objectUID | 
|  | // | 
|  | // Parameters: | 
|  | //    cliInterface - used to get the list of object usages | 
|  | //    objectUID - the UID being processed | 
|  | //    objectList - a list of objectRefdByMe structures describing each usage | 
|  | // | 
|  | // returns: | 
|  | //    0 - successful | 
|  | //   -1 - unexpected error occurred | 
|  | // **************************************************************************** | 
|  | short CmpSeabaseDDL::getListOfDirectlyReferencedObjects ( | 
|  | ExeCliInterface *cliInterface, | 
|  | const Int64 objectUID, | 
|  | NAList<objectRefdByMe> &objectsList) | 
|  | { | 
|  | // Select all the rows from views_usage associated with the passed in | 
|  | // objectUID | 
|  | Lng32 cliRC = 0; | 
|  | char buf[4000]; | 
|  | str_sprintf(buf, "select object_type, object_uid, catalog_name," | 
|  | "schema_name, object_name from %s.\"%s\".%s T, %s.\"%s\".%s VU " | 
|  | "where VU.using_view_uid = %Ld " | 
|  | "and T.object_uid = VU.used_object_uid", | 
|  | getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS, | 
|  | getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_VIEWS_USAGE, | 
|  | objectUID); | 
|  |  | 
|  | Queue * usingObjectsQueue = NULL; | 
|  | cliRC = cliInterface->fetchAllRows(usingObjectsQueue, buf, 0, FALSE, FALSE, TRUE); | 
|  | if (cliRC < 0) | 
|  | { | 
|  | cliInterface->retrieveSQLDiagnostics(CmpCommon::diags()); | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | // set up an objectRefdByMe struct for each returned row | 
|  | usingObjectsQueue->position(); | 
|  | for (int idx = 0; idx < usingObjectsQueue->numEntries(); idx++) | 
|  | { | 
|  | OutputInfo * oi = (OutputInfo*)usingObjectsQueue->getNext(); | 
|  | objectRefdByMe objectInfo; | 
|  | objectInfo.objectType = NAString(oi->get(0)); | 
|  | objectInfo.objectUID = *(Int64*)oi->get(1); | 
|  | objectInfo.catalogName = NAString(oi->get(2)); | 
|  | objectInfo.schemaName = NAString(oi->get(3)); | 
|  | objectInfo.objectName = NAString(oi->get(4)); | 
|  | objectsList.insert(objectInfo); | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | // ---------------------------------------------------------------------------- | 
|  | // method: createSeabaseView | 
|  | // ---------------------------------------------------------------------------- | 
|  | 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)) || | 
|  | (ComIsTrafodionExternalSchemaName(schemaNamePart))) && | 
|  | (!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 objectFlags = 0; | 
|  | Int64 objUID = getObjectInfo(&cliInterface, | 
|  | catalogNamePart.data(), schemaNamePart.data(), | 
|  | objectNamePart.data(), | 
|  | COM_VIEW_OBJECT, | 
|  | objectOwnerID,schemaOwnerID,objectFlags); | 
|  |  | 
|  | 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(); | 
|  |  | 
|  | // The view creator may not be the same as the view owner. | 
|  | // For shared schemas, the view creator is always the same as the view owner. | 
|  | // For private schemas, the view owner is the schema owner. However, the | 
|  | // user that is issuing the CREATE statement is not always the schema owner. | 
|  | NABoolean viewOwnerIsViewCreator  = | 
|  | ((schemaClass == COM_SCHEMA_CLASS_SHARED) ? TRUE : | 
|  | ((ComUser::getCurrentUser() == schemaOwnerID) ? TRUE : FALSE)); | 
|  |  | 
|  | // If DB ROOT is running command on behalf of another user, then the view | 
|  | // owner is the same of the view creator | 
|  | if (ComUser::isRootUserID() && (ComUser::getRootUserID() != schemaOwnerID)) | 
|  | viewOwnerIsViewCreator = TRUE; | 
|  |  | 
|  | // Gather privileges for the view creator | 
|  | NABoolean viewCreator = TRUE; | 
|  | if (gatherViewPrivileges(createViewNode, | 
|  | &cliInterface, | 
|  | viewCreator, | 
|  | schemaOwnerID, | 
|  | privilegesBitmap, | 
|  | grantableBitmap)) | 
|  | { | 
|  | processReturn(); | 
|  | deallocEHI(ehi); | 
|  | return; | 
|  | } | 
|  |  | 
|  | PrivMgrBitmap ownerPrivBitmap; | 
|  | PrivMgrBitmap ownerGrantableBitmap; | 
|  | ownerPrivBitmap.set(); | 
|  | ownerGrantableBitmap.set(); | 
|  |  | 
|  | // If view owner is the same as view creator, owner and creator privileges | 
|  | // are the same | 
|  | if (viewOwnerIsViewCreator) | 
|  | { | 
|  | ownerPrivBitmap = privilegesBitmap; | 
|  | ownerGrantableBitmap = grantableBitmap; | 
|  | } | 
|  |  | 
|  | // If view creator is not the same as the view owner, gather the | 
|  | // view owner privileges | 
|  | else | 
|  | { | 
|  | if (gatherViewPrivileges(createViewNode, | 
|  | &cliInterface, | 
|  | !viewCreator, | 
|  | schemaOwnerID, | 
|  | ownerPrivBitmap, | 
|  | ownerGrantableBitmap)) | 
|  | { | 
|  | processReturn(); | 
|  | deallocEHI(ehi); | 
|  | return; | 
|  | } | 
|  | } | 
|  |  | 
|  | NAString viewText(STMTHEAP); | 
|  | buildViewText(createViewNode, viewText); | 
|  |  | 
|  | 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, FALSE)) | 
|  | { | 
|  | deallocEHI(ehi); | 
|  | processReturn(); | 
|  |  | 
|  | return; | 
|  | } | 
|  |  | 
|  | ComTdbVirtTableTableInfo * tableInfo = new(STMTHEAP) ComTdbVirtTableTableInfo[1]; | 
|  | tableInfo->tableName = NULL, | 
|  | tableInfo->createTime = 0; | 
|  | tableInfo->redefTime = 0; | 
|  | tableInfo->objUID = 0; | 
|  | tableInfo->objOwnerID = objectOwnerID; | 
|  | tableInfo->schemaOwnerID = schemaOwnerID; | 
|  | tableInfo->isAudited = 1; | 
|  | tableInfo->validDef = 1; | 
|  | tableInfo->hbaseCreateOptions = NULL; | 
|  | tableInfo->numSaltPartns = 0; | 
|  | tableInfo->rowFormat = COM_UNKNOWN_FORMAT_TYPE; | 
|  | tableInfo->objectFlags = 0; | 
|  |  | 
|  | Int64 objUID = -1; | 
|  | if (updateSeabaseMDTable(&cliInterface, | 
|  | catalogNamePart, schemaNamePart, objectNamePart, | 
|  | COM_VIEW_OBJECT, | 
|  | "N", | 
|  | tableInfo, | 
|  | numCols, | 
|  | colInfoArray, | 
|  | 0, NULL, | 
|  | 0, NULL, | 
|  | objUID)) | 
|  | { | 
|  | deallocEHI(ehi); | 
|  |  | 
|  | processReturn(); | 
|  |  | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (objUID < 0) | 
|  | { | 
|  | deallocEHI(ehi); | 
|  | processReturn(); | 
|  | return; | 
|  | } | 
|  |  | 
|  | NAString viewColUsageText; | 
|  | if (buildViewTblColUsage(createViewNode, colInfoArray, objUID,  viewColUsageText)) | 
|  | { | 
|  | deallocEHI(ehi); | 
|  | processReturn(); | 
|  | return; | 
|  | } | 
|  |  | 
|  | // grant privileges for view | 
|  | if (isAuthorizationEnabled()) | 
|  | { | 
|  | // Initiate the privilege manager interface class | 
|  | NAString privMgrMDLoc; | 
|  | CONCAT_CATSCH(privMgrMDLoc, getSystemCatalog(), SEABASE_PRIVMGR_SCHEMA); | 
|  | PrivMgrCommands privInterface(std::string(privMgrMDLoc.data()), | 
|  | CmpCommon::diags()); | 
|  |  | 
|  | // Calculate the view owner (grantee) | 
|  | int32_t grantee = (viewOwnerIsViewCreator) | 
|  | ? ComUser::getCurrentUser() : schemaOwnerID; | 
|  | if (ComUser::isRootUserID() && (ComUser::getRootUserID() != schemaOwnerID)) | 
|  | grantee = schemaOwnerID; | 
|  |  | 
|  | // Grant view ownership - grantor is the SYSTEM | 
|  | retcode = privInterface.grantObjectPrivilege | 
|  | (objUID, std::string(extViewName.data()), COM_VIEW_OBJECT, | 
|  | SYSTEM_USER, grantee, | 
|  | ownerPrivBitmap, ownerGrantableBitmap); | 
|  | if (retcode != STATUS_GOOD && retcode != STATUS_WARNING) | 
|  | { | 
|  | deallocEHI(ehi); | 
|  | processReturn(); | 
|  | return; | 
|  | } | 
|  |  | 
|  | // if the view creator is different than view owner, assign creator | 
|  | // privileges (assigned by view owner to view creator) | 
|  | if (!viewOwnerIsViewCreator) | 
|  | { | 
|  | retcode = privInterface.grantObjectPrivilege | 
|  | (objUID, std::string(extViewName.data()), COM_VIEW_OBJECT, | 
|  | schemaOwnerID, ComUser::getCurrentUser(), | 
|  | 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[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, viewText)) | 
|  | { | 
|  | deallocEHI(ehi); | 
|  | processReturn(); | 
|  | return; | 
|  | } | 
|  |  | 
|  | // Views that contain UNION clauses do not have col usages available so | 
|  | // viewColUsageText could be null - see TRAFODION-2153 | 
|  | if (!viewColUsageText.isNull()) | 
|  | { | 
|  | if (updateTextTable(&cliInterface, objUID, COM_VIEW_REF_COLS_TEXT, 0, viewColUsageText)) | 
|  | { | 
|  | 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; | 
|  | } | 
|  |  | 
|  | if (updateObjectRedefTime(&cliInterface, | 
|  | catalogNamePart, schemaNamePart, objectNamePart, | 
|  | COM_VIEW_OBJECT_LIT, -2, objUID)) | 
|  | { | 
|  | deallocEHI(ehi); | 
|  |  | 
|  | processReturn(); | 
|  |  | 
|  | return; | 
|  | } | 
|  |  | 
|  | CorrName cn(objectNamePart, STMTHEAP, schemaNamePart, catalogNamePart); | 
|  | ActiveSchemaDB()->getNATableDB()->removeNATable | 
|  | (cn, | 
|  | ComQiScope::REMOVE_MINE_ONLY, COM_VIEW_OBJECT, | 
|  | createViewNode->ddlXns(), FALSE); | 
|  |  | 
|  | deallocEHI(ehi); | 
|  | processReturn(); | 
|  |  | 
|  | return; | 
|  | } | 
|  |  | 
|  | void CmpSeabaseDDL::dropSeabaseView( | 
|  | StmtDDLDropView * dropViewNode, | 
|  | NAString &currCatName, NAString &currSchName) | 
|  | { | 
|  | Lng32 cliRC = 0; | 
|  | Lng32 retcode = 0; | 
|  |  | 
|  | ExeCliInterface cliInterface(STMTHEAP, NULL, NULL, | 
|  | CmpCommon::context()->sqlSession()->getParentQid()); | 
|  |  | 
|  | NAString tabName = dropViewNode->getViewName(); | 
|  | NAString catalogNamePart, schemaNamePart, objectNamePart; | 
|  | NAString extTableName, extNameForHbase; | 
|  | NATable * naTable = NULL; | 
|  | CorrName cn; | 
|  | QualifiedName qn; | 
|  | retcode = | 
|  | setupAndErrorChecks(tabName, | 
|  | qn, | 
|  | currCatName, currSchName, | 
|  | catalogNamePart, schemaNamePart, objectNamePart, | 
|  | extTableName, extNameForHbase, cn, | 
|  | NULL, | 
|  | FALSE, FALSE, | 
|  | &cliInterface, | 
|  | COM_VIEW_OBJECT); | 
|  | if (retcode < 0) | 
|  | { | 
|  | processReturn(); | 
|  | return; | 
|  | } | 
|  |  | 
|  | Int32 objectOwnerID = 0; | 
|  | Int32 schemaOwnerID = 0; | 
|  | Int64 objectFlags = 0; | 
|  | Int64 objUID = getObjectInfo(&cliInterface, | 
|  | catalogNamePart.data(), schemaNamePart.data(), | 
|  | objectNamePart.data(), | 
|  | COM_VIEW_OBJECT, | 
|  | objectOwnerID,schemaOwnerID,objectFlags); | 
|  |  | 
|  | if (objUID < 0 || objectOwnerID == 0) | 
|  | { | 
|  | if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0) | 
|  | SEABASEDDL_INTERNAL_ERROR("getting object UID and owner for drop view"); | 
|  |  | 
|  | processReturn(); | 
|  |  | 
|  | return; | 
|  | } | 
|  |  | 
|  | // Verify user can perform operation | 
|  | if (!isDDLOperationAuthorized(SQLOperation::DROP_VIEW,objectOwnerID,schemaOwnerID)) | 
|  | { | 
|  | *CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED); | 
|  | processReturn (); | 
|  | return; | 
|  | } | 
|  |  | 
|  | Queue * usingViewsQueue = NULL; | 
|  | if (dropViewNode->getDropBehavior() == COM_RESTRICT_DROP_BEHAVIOR) | 
|  | { | 
|  | NAString usingObjName; | 
|  | cliRC = getUsingObject(&cliInterface, objUID, usingObjName); | 
|  | if (cliRC < 0) | 
|  | { | 
|  | processReturn(); | 
|  |  | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (cliRC != 100) // found an object | 
|  | { | 
|  | *CmpCommon::diags() << DgSqlCode(-1047) | 
|  | << DgTableName(usingObjName); | 
|  |  | 
|  | processReturn(); | 
|  |  | 
|  | return; | 
|  | } | 
|  | } | 
|  | else if (dropViewNode->getDropBehavior() == COM_CASCADE_DROP_BEHAVIOR) | 
|  | { | 
|  | cliRC = getUsingViews(&cliInterface, objUID, usingViewsQueue); | 
|  | if (cliRC < 0) | 
|  | { | 
|  | 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(STMTHEAP); | 
|  | short status = getListOfReferencedTables(&cliInterface, objUID, tablesRefdList); | 
|  |  | 
|  | ExpHbaseInterface * ehi = allocEHI(); | 
|  | if (ehi == NULL) | 
|  | { | 
|  | 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 (dropSeabaseObject(ehi, viewName, | 
|  | currCatName, currSchName, COM_VIEW_OBJECT, | 
|  | dropViewNode->ddlXns())) | 
|  | { | 
|  | deallocEHI(ehi); | 
|  | processReturn(); | 
|  |  | 
|  | return; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | if (dropSeabaseObject(ehi, tabName, | 
|  | currCatName, currSchName, COM_VIEW_OBJECT, | 
|  | dropViewNode->ddlXns())) | 
|  | { | 
|  | deallocEHI(ehi); | 
|  | processReturn(); | 
|  |  | 
|  | return; | 
|  | } | 
|  |  | 
|  | // clear view definition from my cache only. | 
|  | ActiveSchemaDB()->getNATableDB()->removeNATable | 
|  | (cn, | 
|  | ComQiScope::REMOVE_MINE_ONLY, COM_VIEW_OBJECT, | 
|  | dropViewNode->ddlXns(), FALSE); | 
|  |  | 
|  | // 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, | 
|  | ComQiScope::REMOVE_FROM_ALL_USERS, COM_BASE_TABLE_OBJECT, | 
|  | dropViewNode->ddlXns(), FALSE); | 
|  | } | 
|  |  | 
|  | deallocEHI(ehi); | 
|  | processReturn(); | 
|  |  | 
|  | return; | 
|  | } | 
|  |  | 
|  | void CmpSeabaseDDL::glueQueryFragments(Lng32 queryArraySize, | 
|  | const QString * queryArray, | 
|  | char * &gluedQuery, | 
|  | Lng32 &gluedQuerySize) | 
|  | { | 
|  | Int32 i = 0; | 
|  | gluedQuerySize = 0; | 
|  | gluedQuery = NULL; | 
|  |  | 
|  | for (i = 0; i < queryArraySize; i++) | 
|  | { | 
|  | UInt32 j = 0; | 
|  | const char * partn_frag = queryArray[i].str; | 
|  | while ((j < strlen(queryArray[i].str)) && | 
|  | (partn_frag[j] == ' ')) | 
|  | j++; | 
|  | if (j < strlen(queryArray[i].str)) | 
|  | gluedQuerySize += strlen(&partn_frag[j]); | 
|  | } | 
|  |  | 
|  | gluedQuery = | 
|  | new(STMTHEAP) char[gluedQuerySize + 100]; | 
|  | gluedQuery[0] = 0; | 
|  | for (i = 0; i < queryArraySize; i++) | 
|  | { | 
|  | UInt32 j = 0; | 
|  | const char * partn_frag = queryArray[i].str; | 
|  | while ((j < strlen(queryArray[i].str)) && | 
|  | (partn_frag[j] == ' ')) | 
|  | j++; | 
|  |  | 
|  | if (j < strlen(queryArray[i].str)) | 
|  | strcat(gluedQuery, &partn_frag[j]); | 
|  | } | 
|  | } | 
|  |  | 
|  | short CmpSeabaseDDL::createMetadataViews(ExeCliInterface * cliInterface) | 
|  | { | 
|  | Lng32 cliRC = 0; | 
|  | Lng32 retcode = 0; | 
|  |  | 
|  | char queryBuf[5000]; | 
|  |  | 
|  | for (Int32 i = 0; i < sizeof(allMDviewsInfo)/sizeof(MDViewInfo); i++) | 
|  | { | 
|  | const MDViewInfo &mdi = allMDviewsInfo[i]; | 
|  |  | 
|  | if (! mdi.viewName) | 
|  | continue; | 
|  |  | 
|  | for (Int32 j = 0; j < NUM_MAX_PARAMS; j++) | 
|  | { | 
|  | param_[j] = NULL; | 
|  | } | 
|  |  | 
|  | const QString * qs = NULL; | 
|  | Int32 sizeOfqs = 0; | 
|  |  | 
|  | qs = mdi.viewDefnQuery; | 
|  | sizeOfqs = mdi.sizeOfDefnArr; | 
|  |  | 
|  | Int32 qryArraySize = sizeOfqs / sizeof(QString); | 
|  | char * gluedQuery; | 
|  | Lng32 gluedQuerySize; | 
|  | glueQueryFragments(qryArraySize,  qs, | 
|  | gluedQuery, gluedQuerySize); | 
|  |  | 
|  | if (strcmp(mdi.viewName, TRAF_TABLES_VIEW) == 0) | 
|  | { | 
|  | param_[0] = getSystemCatalog(); | 
|  | param_[1] = SEABASE_MD_SCHEMA; | 
|  | param_[2] = getSystemCatalog(); | 
|  | param_[3] = SEABASE_MD_SCHEMA; | 
|  | param_[4] = SEABASE_OBJECTS; | 
|  | param_[5] = getSystemCatalog(); | 
|  | param_[6] = SEABASE_MD_SCHEMA; | 
|  | param_[7] = SEABASE_TABLES; | 
|  | param_[8] = getSystemCatalog(); | 
|  | param_[9] = SEABASE_MD_SCHEMA; | 
|  | param_[10] = COM_BASE_TABLE_OBJECT_LIT; | 
|  | } | 
|  | else if (strcmp(mdi.viewName, TRAF_COLUMNS_VIEW) == 0) | 
|  | { | 
|  | param_[0] = getSystemCatalog(); | 
|  | param_[1] = SEABASE_MD_SCHEMA; | 
|  | param_[2] = getSystemCatalog(); | 
|  | param_[3] = SEABASE_MD_SCHEMA; | 
|  | param_[4] = SEABASE_OBJECTS; | 
|  | param_[5] = getSystemCatalog(); | 
|  | param_[6] = SEABASE_MD_SCHEMA; | 
|  | param_[7] = SEABASE_COLUMNS; | 
|  | param_[8] = getSystemCatalog(); | 
|  | param_[9] = SEABASE_MD_SCHEMA; | 
|  | param_[10] = COM_BASE_TABLE_OBJECT_LIT; | 
|  | } | 
|  | else if (strcmp(mdi.viewName, TRAF_INDEXES_VIEW) == 0) | 
|  | { | 
|  | param_[0] = getSystemCatalog(); | 
|  | param_[1] = SEABASE_MD_SCHEMA; | 
|  | param_[2] = getSystemCatalog(); | 
|  | param_[3] = SEABASE_MD_SCHEMA; | 
|  | param_[4] = SEABASE_INDEXES; | 
|  | param_[5] = getSystemCatalog(); | 
|  | param_[6] = SEABASE_MD_SCHEMA; | 
|  | param_[7] = SEABASE_OBJECTS; | 
|  | param_[8] = getSystemCatalog(); | 
|  | param_[9] = SEABASE_MD_SCHEMA; | 
|  | param_[10] = SEABASE_OBJECTS; | 
|  | param_[11] = getSystemCatalog(); | 
|  | param_[12] = SEABASE_MD_SCHEMA; | 
|  | } | 
|  | else if (strcmp(mdi.viewName, TRAF_KEYS_VIEW) == 0) | 
|  | { | 
|  | param_[0] = getSystemCatalog(); | 
|  | param_[1] = SEABASE_MD_SCHEMA; | 
|  | param_[2] = getSystemCatalog(); | 
|  | param_[3] = SEABASE_MD_SCHEMA; | 
|  | param_[4] = SEABASE_TABLE_CONSTRAINTS; | 
|  | param_[5] = getSystemCatalog(); | 
|  | param_[6] = SEABASE_MD_SCHEMA; | 
|  | param_[7] = SEABASE_OBJECTS; | 
|  | param_[8] = getSystemCatalog(); | 
|  | param_[9] = SEABASE_MD_SCHEMA; | 
|  | param_[10] = SEABASE_OBJECTS; | 
|  | param_[11] = getSystemCatalog(); | 
|  | param_[12] = SEABASE_MD_SCHEMA; | 
|  | param_[13] = SEABASE_KEYS; | 
|  | param_[14] = getSystemCatalog(); | 
|  | param_[15] = SEABASE_MD_SCHEMA; | 
|  | } | 
|  | else if (strcmp(mdi.viewName, TRAF_REF_CONSTRAINTS_VIEW) == 0) | 
|  | { | 
|  | param_[0] = getSystemCatalog(); | 
|  | param_[1] = SEABASE_MD_SCHEMA; | 
|  | param_[2] = getSystemCatalog(); | 
|  | param_[3] = SEABASE_MD_SCHEMA; | 
|  | param_[4] = SEABASE_REF_CONSTRAINTS; | 
|  | param_[5] = getSystemCatalog(); | 
|  | param_[6] = SEABASE_MD_SCHEMA; | 
|  | param_[7] = SEABASE_OBJECTS; | 
|  | param_[8] = getSystemCatalog(); | 
|  | param_[9] = SEABASE_MD_SCHEMA; | 
|  | param_[10] = SEABASE_OBJECTS; | 
|  | param_[11] = getSystemCatalog(); | 
|  | param_[12] = SEABASE_MD_SCHEMA; | 
|  | param_[13] = SEABASE_OBJECTS; | 
|  | param_[14] = getSystemCatalog(); | 
|  | param_[15] = SEABASE_MD_SCHEMA; | 
|  | param_[16] = SEABASE_TABLE_CONSTRAINTS; | 
|  | param_[17] = getSystemCatalog(); | 
|  | param_[18] = SEABASE_MD_SCHEMA; | 
|  | } | 
|  | else if (strcmp(mdi.viewName, TRAF_SEQUENCES_VIEW) == 0) | 
|  | { | 
|  | param_[0] = getSystemCatalog(); | 
|  | param_[1] = SEABASE_MD_SCHEMA; | 
|  | param_[2] = getSystemCatalog(); | 
|  | param_[3] = SEABASE_MD_SCHEMA; | 
|  | param_[4] = SEABASE_OBJECTS; | 
|  | param_[5] = getSystemCatalog(); | 
|  | param_[6] = SEABASE_MD_SCHEMA; | 
|  | param_[7] = SEABASE_SEQ_GEN; | 
|  | param_[8] = getSystemCatalog(); | 
|  | param_[9] = SEABASE_MD_SCHEMA; | 
|  | param_[10] = COM_SEQUENCE_GENERATOR_OBJECT_LIT; | 
|  | } | 
|  | else if (strcmp(mdi.viewName, TRAF_VIEWS_VIEW) == 0) | 
|  | { | 
|  | param_[0] = getSystemCatalog(); | 
|  | param_[1] = SEABASE_MD_SCHEMA; | 
|  | param_[2] = getSystemCatalog(); | 
|  | param_[3] = SEABASE_MD_SCHEMA; | 
|  | param_[4] = SEABASE_OBJECTS; | 
|  | param_[5] = getSystemCatalog(); | 
|  | param_[6] = SEABASE_MD_SCHEMA; | 
|  | param_[7] = SEABASE_VIEWS; | 
|  | param_[8] = getSystemCatalog(); | 
|  | param_[9] = SEABASE_MD_SCHEMA; | 
|  | param_[10] = COM_VIEW_OBJECT_LIT; | 
|  | } | 
|  | else | 
|  | { | 
|  | NADELETEBASIC(gluedQuery, STMTHEAP); | 
|  | continue; | 
|  | } | 
|  |  | 
|  | str_sprintf(queryBuf, gluedQuery, | 
|  | param_[0], param_[1], param_[2], param_[3], param_[4], | 
|  | param_[5], param_[6], param_[7], param_[8], param_[9], | 
|  | param_[10], param_[11], param_[12], param_[13], param_[14], | 
|  | param_[15], param_[16], param_[17], param_[18]); | 
|  |  | 
|  | NADELETEBASIC(gluedQuery, STMTHEAP); | 
|  |  | 
|  | NABoolean xnWasStartedHere = FALSE; | 
|  | if (beginXnIfNotInProgress(cliInterface, xnWasStartedHere)) | 
|  | return -1; | 
|  |  | 
|  | cliRC = cliInterface->executeImmediate(queryBuf); | 
|  | if (cliRC == -1390)  // view already exists | 
|  | { | 
|  | // ignore the error. | 
|  | cliRC = 0; | 
|  | } | 
|  | else if (cliRC < 0) | 
|  | { | 
|  | cliInterface->retrieveSQLDiagnostics(CmpCommon::diags()); | 
|  | } | 
|  |  | 
|  | if (endXnIfStartedHere(cliInterface, xnWasStartedHere, cliRC) < 0) | 
|  | return -1; | 
|  |  | 
|  | } // for | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | short CmpSeabaseDDL::dropMetadataViews(ExeCliInterface * cliInterface) | 
|  | { | 
|  | Lng32 cliRC = 0; | 
|  | Lng32 retcode = 0; | 
|  |  | 
|  | char queryBuf[5000]; | 
|  |  | 
|  | for (Int32 i = 0; i < sizeof(allMDviewsInfo)/sizeof(MDViewInfo); i++) | 
|  | { | 
|  | const MDViewInfo &mdi = allMDviewsInfo[i]; | 
|  |  | 
|  | if (! mdi.viewName) | 
|  | continue; | 
|  |  | 
|  | str_sprintf(queryBuf, "drop view %s.\"%s\".%s", | 
|  | getSystemCatalog(), SEABASE_MD_SCHEMA, | 
|  | mdi.viewName); | 
|  |  | 
|  | NABoolean xnWasStartedHere = FALSE; | 
|  | if (beginXnIfNotInProgress(cliInterface, xnWasStartedHere)) | 
|  | return -1; | 
|  |  | 
|  | cliRC = cliInterface->executeImmediate(queryBuf); | 
|  | if (cliRC == -1389) // does not exist, ignore | 
|  | { | 
|  | cliRC = 0; | 
|  | } | 
|  | else if (cliRC < 0) | 
|  | { | 
|  | cliInterface->retrieveSQLDiagnostics(CmpCommon::diags()); | 
|  | } | 
|  |  | 
|  | if (endXnIfStartedHere(cliInterface, xnWasStartedHere, cliRC) < 0) | 
|  | return -1; | 
|  |  | 
|  | } // for | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | // ***************************************************************************** | 
|  | // *                                                                           * | 
|  | // * Function: checkAccessPrivileges                                           * | 
|  | // *                                                                           * | 
|  | // *   This function determines if a user has the requesite privileges to      * | 
|  | // * access the referenced objects that comprise the view. In addition it      * | 
|  | // * returns the privileges bitmap containing privileges to be granted to 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.                * | 
|  | // *                                                                           * | 
|  | // *  <viewCreator>            NABoolean                              In       * | 
|  | // *    If TRUE, gather privileges for the view creator, if FALSE,             * | 
|  | // *    gather privileges for the view owner                                   * | 
|  | // *                                                                           * | 
|  | // *  <userID>               Int32                                  In         * | 
|  | // *     userID to use when root is performing operations on behalf            * | 
|  | // *     of another user.                                                      * | 
|  | // *                                                                           * | 
|  | // *  <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, | 
|  | NABoolean viewCreator, | 
|  | Int32 userID, | 
|  | PrivMgrBitmap & privilegesBitmap, | 
|  | PrivMgrBitmap & grantableBitmap) | 
|  |  | 
|  | { | 
|  | BindWA bindWA(ActiveSchemaDB(),CmpCommon::context(),FALSE/*inDDL*/); | 
|  | PrivStatus retcode = STATUS_GOOD; | 
|  |  | 
|  | NAString privMgrMDLoc; | 
|  | CONCAT_CATSCH(privMgrMDLoc,CmpSeabaseDDL::getSystemCatalogStatic(),SEABASE_PRIVMGR_SCHEMA); | 
|  | PrivMgrCommands privInterface(std::string(privMgrMDLoc.data()), | 
|  | CmpCommon::diags()); | 
|  |  | 
|  | // generate the list of privileges and grantable privileges to assign to the view | 
|  | // a side effect is to return an error if basic privileges are not granted | 
|  | for (CollIndex i = 0; i < vtul.entries(); i++) | 
|  | { | 
|  | 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); | 
|  | NAString refdUsedObjName = usedObjName.getExternalName(TRUE); | 
|  | CorrName cn(objectNamePart,STMTHEAP, schemaNamePart,catalogNamePart); | 
|  |  | 
|  | // If a sequence, set correct type to get a valid NATable entry | 
|  | bool isSeq = (vtul[i].getSpecialType() == ExtendedQualName::SG_TABLE)? true : false; | 
|  | if (isSeq) | 
|  | cn.setSpecialType(ExtendedQualName::SG_TABLE); | 
|  |  | 
|  | NATable *naTable = bindWA.getNATableInternal(cn); | 
|  | if (naTable == NULL) | 
|  | { | 
|  | SEABASEDDL_INTERNAL_ERROR("Bad NATable pointer in checkAccessPrivileges"); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | PrivMgrUserPrivs privs; | 
|  | PrivMgrUserPrivs *pPrivInfo = NULL; | 
|  |  | 
|  | // If hive or ORC table and table does not have an external table, | 
|  | // skip priv checks. | 
|  | if ((naTable->isHiveTable()) && !naTable->hasExternalTable()) | 
|  | { | 
|  | privs.setOwnerDefaultPrivs(); | 
|  | pPrivInfo = &privs; | 
|  | } | 
|  | else | 
|  | { | 
|  | // If gathering privileges for the view creator, the NATable structure | 
|  | // contains the privileges we want to use to create bitmaps | 
|  | if (viewCreator) | 
|  | { | 
|  | // If the viewCreator is not the current user (DB__ROOT running request) | 
|  | // on behalf of the schema owner), get actual owner privs. | 
|  | if (ComUser::isRootUserID() && | 
|  | ComUser::getRootUserID() != naTable->getSchemaOwner()) | 
|  | { | 
|  | retcode = privInterface.getPrivileges((int64_t)naTable->objectUid().get_value(), | 
|  | naTable->getObjectType(), | 
|  | userID, | 
|  | privs); | 
|  |  | 
|  | if (retcode == STATUS_ERROR) | 
|  | { | 
|  | *CmpCommon::diags() << DgSqlCode(-CAT_UNABLE_TO_RETRIEVE_PRIVS); | 
|  | return false; | 
|  | } | 
|  | pPrivInfo = &privs; | 
|  | } | 
|  | else | 
|  | { | 
|  | pPrivInfo = naTable->getPrivInfo(); | 
|  | CMPASSERT(pPrivInfo != NULL); | 
|  | } | 
|  | } | 
|  |  | 
|  | // If the view owner is not the view creator, then we need to get schema | 
|  | // owner privileges from PrivMgr. | 
|  | else | 
|  | { | 
|  | PrivStatus retcode = privInterface.getPrivileges((int64_t)naTable->objectUid().get_value(), | 
|  | naTable->getObjectType(), | 
|  | naTable->getSchemaOwner(), | 
|  | privs); | 
|  |  | 
|  | if (retcode == STATUS_ERROR) | 
|  | { | 
|  | *CmpCommon::diags() << DgSqlCode(-CAT_UNABLE_TO_RETRIEVE_PRIVS); | 
|  | return false; | 
|  | } | 
|  | pPrivInfo = &privs; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Requester must have at least select privilege | 
|  | // For sequence generators USAGE is needed instead of SELECT | 
|  | bool noObjRequiredPriv = true; | 
|  | if  (isSeq) | 
|  | noObjRequiredPriv = !pPrivInfo->hasUsagePriv() ? true : false; | 
|  | else | 
|  | noObjRequiredPriv = !pPrivInfo->hasSelectPriv() ? true : false; | 
|  |  | 
|  | // Summarize privileges | 
|  | privilegesBitmap &= pPrivInfo->getObjectBitmap(); | 
|  | grantableBitmap &= pPrivInfo->getGrantableBitmap(); | 
|  |  | 
|  | // Gather column level privs to attach to the bitmap. | 
|  | // Even though privileges are granted on the column, they show up as | 
|  | // object privileges on the view. | 
|  | PrivColumnBitmap colPrivBitmap; | 
|  | PrivColumnBitmap colGrantableBitmap; | 
|  |  | 
|  | PrivMgrPrivileges::setColumnPrivs(colPrivBitmap); | 
|  | PrivMgrPrivileges::setColumnPrivs(colGrantableBitmap); | 
|  |  | 
|  | // Check for column privileges on each view column | 
|  | // This loop is performed for each object referenced by the view. | 
|  | // Only those columns that belong to the referenced object have their | 
|  | // privileges summarized. | 
|  | for (size_t i = 0; i < vctcul.entries(); i++) | 
|  | { | 
|  | const ParViewColTableColsUsage &vctcu = vctcul[i]; | 
|  | const ColRefName &usedColRef = vctcu.getUsedObjectColumnName(); | 
|  | ComObjectName usedObjName = | 
|  | usedColRef.getCorrNameObj().getQualifiedNameObj().getQualifiedNameAsAnsiString(); | 
|  | NAString colUsedObjName = usedObjName.getExternalName(TRUE); | 
|  |  | 
|  | // If column is part of the used object, summarize column privs | 
|  | if (colUsedObjName == refdUsedObjName) | 
|  | { | 
|  | // Get the refd object details | 
|  | 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(); | 
|  |  | 
|  | // If the user is missing SELECT at the object level and on at least one | 
|  | // column, view cannot be created.  No need to proceed. | 
|  | // Can't have sequences on views, so only need to check for SELECT | 
|  | if (noObjRequiredPriv && !pPrivInfo->hasColSelectPriv(usedColNumber)) | 
|  | { | 
|  | *CmpCommon::diags() << DgSqlCode(-4481) | 
|  | << DgString0("SELECT") | 
|  | << DgString1(colUsedObjName.data()); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | colPrivBitmap &= pPrivInfo->getColumnPrivBitmap(usedColNumber); | 
|  | colGrantableBitmap &= pPrivInfo->getColumnGrantableBitmap(usedColNumber); | 
|  | } // done with current view col | 
|  | } // done checking privs for all view cols | 
|  |  | 
|  | // Add summarize column privileges to the official bitmaps, bit is only | 
|  | // set if all cols have priv set. | 
|  | 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; | 
|  |  | 
|  | } | 
|  | //*********************** End of checkAccessPrivileges ************************* | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  |