blob: ae401f8e70b4d2f52ac19f28fc0ff9e21f638a59 [file] [log] [blame]
/**********************************************************************
// @@@ 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: CmpSeabaseDDLcommon.cpp
* Description: Implements common methods and operations for SQL/hbase tables.
*
*
* Created: 6/30/2013
* Language: C++
*
*
*****************************************************************************
*/
#include "CmpSeabaseDDLincludes.h"
#include "CmpSeabaseDDLcleanup.h"
#include "RelExeUtil.h"
#include "ControlDB.h"
#include "NumericType.h"
#include "CmpDDLCatErrorCodes.h"
#include "ValueDesc.h"
#include "Globals.h"
#include "Context.h"
#include "ExSqlComp.h"
#include "CmpSeabaseDDLauth.h"
#include "NAUserId.h"
#include "StmtDDLCreateView.h"
#include "StmtDDLDropView.h"
#include "StmtDDLAlterTableDisableIndex.h"
#include "StmtDDLAlterTableEnableIndex.h"
#include "StmtDDLCreateComponentPrivilege.h"
#include "StmtDDLDropComponentPrivilege.h"
#include "StmtDDLGive.h"
#include "StmtDDLGrantComponentPrivilege.h"
#include "StmtDDLRevokeComponentPrivilege.h"
#include "StmtDDLRegisterComponent.h"
#include "StmtDDLCreateRole.h"
#include "StmtDDLRoleGrant.h"
#include "PrivMgrCommands.h"
#include "PrivMgrMD.h"
#include "PrivMgrComponentPrivileges.h"
#include "PrivMgrPrivileges.h"
#include "PrivMgrRoles.h"
#include "ComUser.h"
#include "ComMisc.h"
#include "CmpSeabaseDDLmd.h"
#include "CmpSeabaseDDLroutine.h"
#include "StmtDDLAlterLibrary.h"
#include "logmxevent_traf.h"
#include "exp_clause_derived.h"
#include "TrafDDLdesc.h"
void cleanupLOBDataDescFiles(const char*, int, const char *);
class QualifiedSchema
{
public:
char catalogName[ComMAX_ANSI_IDENTIFIER_INTERNAL_LEN + 1];
char schemaName[ComMAX_ANSI_IDENTIFIER_INTERNAL_LEN + 1];
};
static __thread MDDescsInfo * trafMDDescsInfo_ = NULL;
static void createSeabaseComponentOperation(
const std::string & systemCatalog,
StmtDDLCreateComponentPrivilege *pParseNode);
static void dropSeabaseComponentOperation(
const std::string & systemCatalog,
StmtDDLDropComponentPrivilege *pParseNode);
static void grantSeabaseComponentPrivilege(
const std::string & systemCatalog,
StmtDDLGrantComponentPrivilege *pParseNode);
static void revokeSeabaseComponentPrivilege(
const std::string & systemCatalog,
StmtDDLRevokeComponentPrivilege *pParseNode);
static void grantRevokeSeabaseRole(
const std::string & systemCatalog,
StmtDDLRoleGrant *pParseNode);
static bool hasValue(
std::vector<int32_t> container,
int32_t value);
static NABoolean isTrueFalseStr(const NAText& str);
static NABoolean isHBaseCompressionOption(const NAText& str);
static NABoolean isHBaseDurabilityOption(const NAText& str);
static NABoolean isHBaseEncodingOption(const NAText& str);
static NABoolean isHBaseBloomFilterOption(const NAText& str);
#include "EncodedKeyValue.h"
#include "SCMVersHelp.h"
CmpSeabaseDDL::CmpSeabaseDDL(NAHeap *heap, NABoolean syscatInit)
{
savedCmpParserFlags_ = 0;
savedCliParserFlags_ = 0;
heap_ = heap;
cmpSwitched_ = FALSE;
if ((syscatInit) && (ActiveSchemaDB()))
{
const char* sysCat = ActiveSchemaDB()->getDefaults().getValue(SEABASE_CATALOG);
seabaseSysCat_ = sysCat;
CONCAT_CATSCH(seabaseMDSchema_,sysCat,SEABASE_MD_SCHEMA);
}
}
// We normally don't send user CQDs to the metadata CmpContext.
// To bypass this set the env variable TRAF_PROPAGATE_USER_CQDS to 1.
// The sendAllControlsAndFlags() uses current CmpContext pointer, if given,
// to get the user CQDs and pass them to the new CmpContext.
static THREAD_P Int32 passingUserCQDs = -1;
// RETURN: -1, if error. 0, if context switched successfully.
short CmpSeabaseDDL::switchCompiler(Int32 cntxtType)
{
if (passingUserCQDs == -1)
{
const char *pucStr = getenv("TRAF_PROPAGATE_USER_CQDS");
passingUserCQDs = 0; // check the flag only once
if (pucStr != NULL && atoi(pucStr) == 1)
passingUserCQDs = 1;
}
cmpSwitched_ = FALSE;
CmpContext* currContext = CmpCommon::context();
// we should switch to another CI only if we are in an embedded CI
if (IdentifyMyself::GetMyName() == I_AM_EMBEDDED_SQL_COMPILER)
{
if (SQL_EXEC_SWITCH_TO_COMPILER_TYPE(cntxtType))
{
// failed to switch/create compiler context.
return -1;
}
cmpSwitched_ = TRUE;
}
if (sendAllControlsAndFlags(currContext, cntxtType))
{
switchBackCompiler();
return -1;
}
return 0;
}
short CmpSeabaseDDL::switchBackCompiler()
{
if (cmpSwitched_)
{
GetCliGlobals()->currContext()->copyDiagsAreaToPrevCmpContext();
CmpCommon::diags()->clear();
}
// do restore here even though switching may not have happened, i.e.
// when switchToCompiler() was not called by the embedded CI, see above.
restoreAllControlsAndFlags();
if (cmpSwitched_)
{
// Clear the diagnostics area of the current CmpContext
CmpCommon::diags()->clear();
// switch back to the original commpiler, ignore return error
SQL_EXEC_SWITCH_BACK_COMPILER();
cmpSwitched_ = FALSE;
}
return 0;
}
// ----------------------------------------------------------------------------
// Method: getMDtableInfo
//
// When compiler context is instantiated, definitions of system and privmgr
// metadata tables are stored as an array of MDDescsInfo structs.
//
// This method searches the list of MDDescsInfo structs looking for the
// entry corresponding to the passed in name.
//
// Parameters:
// input:
// name - the fully qualified metadata table
// objType - the object type (base table, index, etc)
//
// output:
// tableInfo,
// colInfoSize, colInfo,
// keyInfoSize, keyInfo,
// indexInfoSize, indexInfo
//
// Return: TRUE, object is cached, FALSE, object not found (or error)
//
// Possible enhancements, instead of returning columns for each value in
// the MDDescsInfo entry, just return the MDDescsInfo entry
// ----------------------------------------------------------------------------
NABoolean CmpSeabaseDDL::getMDtableInfo(const ComObjectName &name,
ComTdbVirtTableTableInfo* &tableInfo,
Lng32 &colInfoSize,
const ComTdbVirtTableColumnInfo* &colInfo,
Lng32 &keyInfoSize,
const ComTdbVirtTableKeyInfo * &keyInfo,
Lng32 &indexInfoSize,
const ComTdbVirtTableIndexInfo* &indexInfo,
const ComObjectType objType)
{
tableInfo = NULL;
indexInfoSize = 0;
indexInfo = NULL;
NAString objName = name.getObjectNamePartAsAnsiString();
if (objName.isNull())
return FALSE;
// If metadata tables have not yet been added to the compiler context,
// return FALSE
if (! CmpCommon::context()->getTrafMDDescsInfo())
return FALSE;
// The first set of objects are system metadata. Check the passed in
// objName and objType for a match
if (isSeabaseMD(name.getCatalogNamePartAsAnsiString(),
name.getSchemaNamePartAsAnsiString(TRUE),
name.getObjectNamePartAsAnsiString()))
{
for (Int32 i = 0; i < sizeof(allMDtablesInfo)/sizeof(MDTableInfo); i++)
{
const MDTableInfo &mdti = allMDtablesInfo[i];
if (! mdti.newName)
return FALSE;
MDDescsInfo &mddi = CmpCommon::context()->getTrafMDDescsInfo()[i];
if (objName == mdti.newName)
{
if (objType == COM_BASE_TABLE_OBJECT)
{
colInfoSize = mddi.numNewCols;
colInfo = mddi.newColInfo;
keyInfoSize = mddi.numNewKeys;
keyInfo = mddi.newKeyInfo;
indexInfoSize = mddi.numIndexes;
indexInfo = mddi.indexInfo;
// this is an index. It cannot selected as a base table objects.
if (mdti.isIndex)
return FALSE;
}
else if (objType == COM_INDEX_OBJECT)
{
colInfoSize = mddi.numNewCols;
colInfo = mddi.newColInfo;
keyInfoSize = mddi.numNewKeys;
keyInfo = mddi.newKeyInfo;
}
else
return FALSE;
if (mddi.tableInfo == NULL)
{
const NAString catName(TRAFODION_SYSCAT_LIT);
const NAString schName(SEABASE_MD_SCHEMA);
NAString extTableName = catName + "." + "\"" + schName + "\"" + "." + objName;
CmpSeabaseDDL cmpSBD(STMTHEAP);
if (cmpSBD.getSpecialTableInfo(CTXTHEAP,
catName, schName, objName, extTableName,
objType, tableInfo) == 0)
mddi.tableInfo = (ComTdbVirtTableTableInfo*)tableInfo;
else
return FALSE; // error
}
else
tableInfo = mddi.tableInfo;
return TRUE;
}
else //if (mdti.oldName && (objName == mdti.oldName))
{
const char * oldName = NULL;
const QString * oldDDL = NULL;
Lng32 sizeOfoldDDL = 0;
if (getOldMDInfo(mdti, oldName, oldDDL, sizeOfoldDDL) == FALSE)
return FALSE;
if ((oldName) && (objName == oldName))
{
if ((mddi.numOldCols > 0) && (mddi.oldColInfo))
{
colInfoSize = mddi.numOldCols;
colInfo = mddi.oldColInfo;
}
else
{
colInfoSize = mddi.numNewCols;
colInfo = mddi.newColInfo;
}
if ((mddi.numOldKeys > 0) && (mddi.oldKeyInfo))
{
keyInfoSize = mddi.numOldKeys;
keyInfo = mddi.oldKeyInfo;
}
else
{
keyInfoSize = mddi.numNewKeys;
keyInfo = mddi.newKeyInfo;
}
return TRUE;
} // oldName
}
} // for
}
// check privmgr tables
if (isSeabasePrivMgrMD(name.getCatalogNamePartAsAnsiString(),
name.getSchemaNamePartAsAnsiString(TRUE)))
{
// privmgr metadata tables start after system metadata tables
size_t startingPos = sizeof(allMDtablesInfo)/sizeof(MDTableInfo);
for (size_t i = 0; i < sizeof(privMgrTables)/sizeof(PrivMgrTableStruct); i++)
{
const PrivMgrTableStruct &tableDefinition = privMgrTables[i];
MDDescsInfo &mddi = CmpCommon::context()->getTrafMDDescsInfo()[startingPos + i];
NAString descTbl(tableDefinition.tableName);
// Privmgr metadata tables get their definition from the new values
// stored in the MDDescsInfo struct
// At this time there are no indexes or views
if (objName == descTbl)
{
colInfoSize = mddi.numNewCols;
colInfo = mddi.newColInfo;
keyInfoSize = mddi.numNewKeys;
keyInfo = mddi.newKeyInfo;
indexInfoSize = mddi.numIndexes;
indexInfo = mddi.indexInfo;
if (mddi.tableInfo == NULL)
{
const NAString catName(TRAFODION_SYSCAT_LIT);
const NAString schName(SEABASE_PRIVMGR_SCHEMA);
NAString extTableName = catName + "." + "\"" + schName + "\"" + "." + objName;
CmpSeabaseDDL cmpSBD(STMTHEAP);
if (cmpSBD.getSpecialTableInfo(CTXTHEAP,
catName, schName, objName, extTableName,
objType, tableInfo) == 0)
mddi.tableInfo = (ComTdbVirtTableTableInfo*)tableInfo;
else
return FALSE; // error
}
else
tableInfo = mddi.tableInfo;
return TRUE;
}
}
}
return FALSE;
}
short CmpSeabaseDDL::convertColAndKeyInfoArrays(
Lng32 btNumCols, // IN
ComTdbVirtTableColumnInfo* btColInfoArray, // IN
Lng32 btNumKeys, // IN
ComTdbVirtTableKeyInfo* btKeyInfoArray, // IN
NAColumnArray *naColArray,
NAColumnArray *naKeyArr)
{
for (Lng32 i = 0; i < btNumCols; i++)
{
ComTdbVirtTableColumnInfo &ci = btColInfoArray[i];
Lng32 colnum, offset;
TrafDesc * desc =
TrafMakeColumnDesc(NULL, NULL, colnum, ci.datatype, ci.length,
offset, ci.nullable, ci.charset, NULL);
TrafColumnsDesc *column_desc = desc->columnsDesc();
column_desc->datatype = ci.datatype;
column_desc->length = ci.length;
column_desc->precision = ci.precision;
column_desc->scale = ci.scale;
column_desc->setNullable(ci.nullable);
column_desc->character_set/*CharInfo::CharSet*/
= (CharInfo::CharSet)ci.charset;
column_desc->setUpshifted(ci.upshifted);
column_desc->setCaseInsensitive(FALSE);
column_desc->collation_sequence = CharInfo::DefaultCollation;
column_desc->encoding_charset = (CharInfo::CharSet)ci.charset;
column_desc->datetimestart = (rec_datetime_field)ci.dtStart;
column_desc->datetimeend = (rec_datetime_field)ci.dtEnd;
column_desc->datetimefractprec = ci.scale;
column_desc->intervalleadingprec = ci.precision;
column_desc->setDefaultClass(ci.defaultClass);
column_desc->colFlags = ci.colFlags;
NAType *type;
NAColumn::createNAType(column_desc, NULL, type, STMTHEAP);
NAColumn * nac = new(STMTHEAP) NAColumn(ci.colName, i, type, STMTHEAP);
naColArray->insert(nac);
for (Lng32 ii = 0; ii < btNumKeys; ii++)
{
ComTdbVirtTableKeyInfo &ki = btKeyInfoArray[ii];
if (strcmp(ci.colName, ki.colName) == 0)
{
if (ki.ordering == ComTdbVirtTableKeyInfo::ASCENDING_ORDERING)
nac->setClusteringKey(ASCENDING);
else // ki.ordering should be 1
nac->setClusteringKey(DESCENDING);
naKeyArr->insert(nac);
}
} // for
} // for
return 0;
}
static short resetCQDs(NABoolean hbaseSerialization, NAString hbVal,
short retval)
{
if (hbaseSerialization)
{
ActiveSchemaDB()->getDefaults().validateAndInsert("hbase_serialization", hbVal, FALSE);
}
return retval;
}
short CmpSeabaseDDL::processDDLandCreateDescs(
Parser &parser,
const QString *ddl,
Lng32 sizeOfddl,
NABoolean isIndexTable,
Lng32 btNumCols, // IN
ComTdbVirtTableColumnInfo* btColInfoArray, // IN
Lng32 btNumKeys, // IN
ComTdbVirtTableKeyInfo* btKeyInfoArray, // IN
Lng32 &numCols, // OUT
ComTdbVirtTableColumnInfo* &colInfoArray, // OUT
Lng32 &numKeys, // OUT
ComTdbVirtTableKeyInfo* &keyInfoArray, // OUT
ComTdbVirtTableIndexInfo* &indexInfo) // OUT
{
numCols = 0;
numKeys = 0;
colInfoArray = NULL;
keyInfoArray = NULL;
indexInfo = NULL;
ExprNode * exprNode = NULL;
const QString * qs = NULL;
Int32 sizeOfqs = 0;
qs = ddl;
sizeOfqs = sizeOfddl;
Int32 qryArraySize = sizeOfqs / sizeof(QString);
char * gluedQuery;
Lng32 gluedQuerySize;
glueQueryFragments(qryArraySize, qs,
gluedQuery, gluedQuerySize);
NABoolean hbaseSerialization = FALSE;
NABoolean defaultColCharset = FALSE;
NAString hbVal;
if (CmpCommon::getDefault(HBASE_SERIALIZATION) == DF_ON)
{
NAString value("OFF");
hbVal = "ON";
ActiveSchemaDB()->getDefaults().validateAndInsert(
"hbase_serialization", value, FALSE);
hbaseSerialization = TRUE;
}
exprNode = parser.parseDML((const char*)gluedQuery, strlen(gluedQuery),
CharInfo::ISO88591);
NADELETEBASICARRAY(gluedQuery, STMTHEAP);
if (! exprNode)
return resetCQDs(hbaseSerialization, hbVal, -1);
RelExpr * rRoot = NULL;
if (exprNode->getOperatorType() EQU STM_QUERY)
{
rRoot = (RelRoot*)exprNode->getChild(0);
}
else if (exprNode->getOperatorType() EQU REL_ROOT)
{
rRoot = (RelRoot*)exprNode;
}
if (! rRoot)
return resetCQDs(hbaseSerialization, hbVal, -1);
ExprNode * ddlNode = NULL;
DDLExpr * ddlExpr = NULL;
ddlExpr = (DDLExpr*)rRoot->getChild(0);
ddlNode = ddlExpr->getDDLNode();
if (! ddlNode)
return resetCQDs(hbaseSerialization, hbVal, -1);
Lng32 keyLength = 0;
if (ddlNode->getOperatorType() == DDL_CREATE_TABLE)
{
StmtDDLCreateTable * createTableNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLCreateTable();
ElemDDLColDefArray &colArray = createTableNode->getColDefArray();
ElemDDLColRefArray &keyArray = createTableNode->getPrimaryKeyColRefArray();
numCols = colArray.entries();
numKeys = keyArray.entries();
colInfoArray = new(CTXTHEAP) ComTdbVirtTableColumnInfo[numCols];
keyInfoArray = new(CTXTHEAP) ComTdbVirtTableKeyInfo[numKeys];
if (buildColInfoArray(COM_BASE_TABLE_OBJECT,
TRUE, // this is a metadata, histogram or repository object
&colArray, colInfoArray, FALSE, FALSE, NULL, NULL, NULL, NULL,
CTXTHEAP))
{
return resetCQDs(hbaseSerialization, hbVal, -1);
}
if (buildKeyInfoArray(&colArray, NULL, &keyArray, colInfoArray, keyInfoArray, FALSE,
&keyLength, CTXTHEAP))
{
return resetCQDs(hbaseSerialization, hbVal, -1);
}
// if index table defn, append "@" to the hbase col qual.
if (isIndexTable)
{
for (Lng32 i = 0; i < numCols; i++)
{
ComTdbVirtTableColumnInfo &ci = colInfoArray[i];
char hcq[100];
strcpy(hcq, ci.hbaseColQual);
ci.hbaseColQual = new(CTXTHEAP) char[strlen(hcq) + 1 +1];
strcpy((char*)ci.hbaseColQual, (char*)"@");
strcat((char*)ci.hbaseColQual, hcq);
} // for
for (Lng32 i = 0; i < numKeys; i++)
{
ComTdbVirtTableKeyInfo &ci = keyInfoArray[i];
ci.hbaseColQual = new(CTXTHEAP) char[10];
str_sprintf((char*)ci.hbaseColQual, "@%d", ci.keySeqNum);
}
} // if
}
else if (ddlNode->getOperatorType() == DDL_CREATE_INDEX)
{
StmtDDLCreateIndex * createIndexNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLCreateIndex();
ComObjectName tableName(createIndexNode->getTableName());
NAString extTableName = tableName.getExternalName(TRUE);
NAString extIndexName = TRAFODION_SYSCAT_LIT;
extIndexName += ".";
extIndexName += "\"";
extIndexName += SEABASE_MD_SCHEMA;
extIndexName += "\"";
extIndexName += ".";
extIndexName += createIndexNode->getIndexName();
ElemDDLColRefArray & indexColRefArray = createIndexNode->getColRefArray();
NAColumnArray btNAColArray;
NAColumnArray btNAKeyArr;
if (convertColAndKeyInfoArrays(btNumCols, btColInfoArray,
btNumKeys, btKeyInfoArray,
&btNAColArray, &btNAKeyArr))
return resetCQDs(hbaseSerialization, hbVal, -1);
Lng32 keyColCount = 0;
Lng32 nonKeyColCount = 0;
Lng32 totalColCount = 0;
Lng32 numIndexCols = 0;
Lng32 numIndexKeys = 0;
Lng32 numIndexNonKeys = 0;
ComTdbVirtTableColumnInfo * indexColInfoArray = NULL;
ComTdbVirtTableKeyInfo * indexKeyInfoArray = NULL;
ComTdbVirtTableKeyInfo * indexNonKeyInfoArray = NULL;
NAList<NAString> selColList(STMTHEAP);
NAString defaultColFam(SEABASE_DEFAULT_COL_FAMILY);
if (createIndexColAndKeyInfoArrays(indexColRefArray,
createIndexNode->isUniqueSpecified(),
FALSE, // no syskey
FALSE, // not alignedFormat
defaultColFam,
btNAColArray, btNAKeyArr,
numIndexKeys, numIndexNonKeys, numIndexCols,
indexColInfoArray, indexKeyInfoArray,
selColList,
keyLength,
CTXTHEAP))
return resetCQDs(hbaseSerialization, hbVal, -1);
numIndexNonKeys = numIndexCols - numIndexKeys;
if (numIndexNonKeys > 0)
{
indexNonKeyInfoArray =
new(CTXTHEAP) ComTdbVirtTableKeyInfo[numIndexNonKeys];
}
Lng32 ink = 0;
for (Lng32 i = numIndexKeys; i < numIndexCols; i++)
{
ComTdbVirtTableColumnInfo &indexCol = indexColInfoArray[i];
ComTdbVirtTableKeyInfo &ki = indexNonKeyInfoArray[ink];
ki.colName = indexCol.colName;
NAColumn * nc = btNAColArray.getColumn(ki.colName);
Lng32 colNumber = nc->getPosition();
ki.tableColNum = colNumber;
ki.keySeqNum = i+1;
ki.ordering = ComTdbVirtTableKeyInfo::ASCENDING_ORDERING;
ki.nonKeyCol = 1;
ki.hbaseColFam = new(CTXTHEAP) char[strlen(SEABASE_DEFAULT_COL_FAMILY) + 1];
strcpy((char*)ki.hbaseColFam, SEABASE_DEFAULT_COL_FAMILY);
char qualNumStr[40];
str_sprintf(qualNumStr, "@%d", ki.keySeqNum);
ki.hbaseColQual = new(CTXTHEAP) char[strlen(qualNumStr)+1];
strcpy((char*)ki.hbaseColQual, qualNumStr);
ink++;
} // for
indexInfo = new(CTXTHEAP) ComTdbVirtTableIndexInfo[1];
indexInfo->baseTableName = new(CTXTHEAP) char[extTableName.length()+ 1];
strcpy((char*)indexInfo->baseTableName, extTableName.data());
indexInfo->indexName = new(CTXTHEAP) char[extIndexName.length()+ 1];
strcpy((char*)indexInfo->indexName, extIndexName.data());
indexInfo->keytag = 1;
indexInfo->isUnique = createIndexNode->isUniqueSpecified() ? 1 : 0;
indexInfo->isExplicit = 1;
indexInfo->keyColCount = numIndexKeys;
indexInfo->nonKeyColCount = numIndexNonKeys;
indexInfo->keyInfoArray = indexKeyInfoArray;
indexInfo->nonKeyInfoArray = indexNonKeyInfoArray;
indexInfo->hbaseCreateOptions = NULL;
indexInfo->numSaltPartns = 0;
numCols = 0;
colInfoArray = NULL;
numKeys = 0;
keyInfoArray = NULL;
}
else
return resetCQDs(hbaseSerialization, hbVal, -1);
return resetCQDs(hbaseSerialization, hbVal, 0);
}
// ----------------------------------------------------------------------------
// Method: createMDdescs
//
// This method is called when the compiler context is instantiated to create
// a cache of system and privmgr metadata.
// Metadata definitions are stored as an array of MDDescsInfo structs.
//
// This method extracts hardcoded definitions of each metadata table, creates
// an MDDescsInfo struct and appends it to the list of entries.
//
// The list of MDDescsInfo structs is organized as follows:
// Tables in "_MD_" schema ordered by list defined in allMDtablesInfo
// Tables in "_PRIVMGR_MGR_" schema order by list defined in PrivMgrTables
//
// Parameters:
// input/output:
// trafMDDescsInfo - returns the list of MDDescsInfo structs for metadata
// the list of structures will be allocated out of the CNTXHEAP
//
// RETURN: -1, error. 0, all ok.
// ----------------------------------------------------------------------------
short CmpSeabaseDDL::createMDdescs(MDDescsInfo *&trafMDDescsInfo)
{
int breadCrumb = -1; // useful for debugging purposes
// if structure is already allocated, just return
// Question - will trafMDDescsInfo ever be NOT NULL?
if (trafMDDescsInfo)
return 0;
size_t numMDTables = sizeof(allMDtablesInfo) / sizeof(MDTableInfo);
size_t numPrivTables = sizeof(privMgrTables)/sizeof(PrivMgrTableStruct);
// Allocate an array of MDDescsInfo structs to handle all system and
// privmgr metadata tables. Authorization may not be enabled but
// go ahead and load privmgr metadata definitions anyway - the current
// session may enable authorization so these entries will be available.
trafMDDescsInfo = (MDDescsInfo*)
new(CTXTHEAP) char[(numMDTables + numPrivTables) * sizeof(MDDescsInfo)];
// Initialize the SQL parser - it is called to get table details
Parser parser(CmpCommon::context());
// Load definitions of system metadata tables
for (size_t i = 0; i < numMDTables; i++)
{
// no need to do hive ddl checks for MD query compiles
parser.hiveDDLInfo_->init();
parser.hiveDDLInfo_->disableDDLcheck_ = TRUE;
const MDTableInfo &mdti = allMDtablesInfo[i];
const char * oldName = NULL;
const QString * oldDDL = NULL;
Lng32 sizeOfoldDDL = 0;
if (getOldMDInfo(mdti, oldName, oldDDL, sizeOfoldDDL) == FALSE)
goto label_error;
MDDescsInfo &mddi = trafMDDescsInfo[i];
if (!mdti.newDDL)
continue;
Lng32 numCols = 0;
Lng32 numKeys = 0;
ComTdbVirtTableColumnInfo * colInfoArray = NULL;
ComTdbVirtTableKeyInfo * keyInfoArray = NULL;
ComTdbVirtTableIndexInfo * indexInfo = NULL;
breadCrumb = 1;
if (processDDLandCreateDescs(parser,
mdti.newDDL, mdti.sizeOfnewDDL,
(mdti.isIndex ? TRUE : FALSE),
0, NULL, 0, NULL,
numCols, colInfoArray,
numKeys, keyInfoArray,
indexInfo))
goto label_error;
mddi.numNewCols = numCols;
mddi.newColInfo = colInfoArray;
mddi.numNewKeys = numKeys;
mddi.newKeyInfo = keyInfoArray;
if (oldDDL)
{
breadCrumb = 2;
if (processDDLandCreateDescs(parser,
oldDDL, sizeOfoldDDL,
(mdti.isIndex ? TRUE : FALSE),
0, NULL, 0, NULL,
numCols, colInfoArray,
numKeys, keyInfoArray,
indexInfo))
goto label_error;
}
mddi.numOldCols = numCols;
mddi.oldColInfo = colInfoArray;
mddi.numOldKeys = numKeys;
mddi.oldKeyInfo = keyInfoArray;
mddi.numIndexes = 0;
mddi.indexInfo = NULL;
mddi.tableInfo = NULL;
if (mdti.indexDDL)
{
mddi.numIndexes = 1;
mddi.indexInfo = NULL;
ComTdbVirtTableIndexInfo * indexInfo = NULL;
Lng32 numIndexCols = 0;
Lng32 numIndexKeys = 0;
ComTdbVirtTableColumnInfo * indexColInfoArray = NULL;
ComTdbVirtTableKeyInfo * indexKeyInfoArray = NULL;
breadCrumb = 3;
if (processDDLandCreateDescs(parser,
mdti.indexDDL, mdti.sizeOfIndexDDL,
FALSE,
numCols, colInfoArray,
numKeys, keyInfoArray,
numIndexCols, indexColInfoArray,
numIndexKeys, indexKeyInfoArray,
indexInfo))
goto label_error;
mddi.indexInfo = indexInfo;
}
} // for
// Load descs for privilege metadata
for (size_t i = 0; i < numPrivTables; i++)
{
const PrivMgrTableStruct &tableDefinition = privMgrTables[i];
MDDescsInfo &mddi = trafMDDescsInfo[numMDTables + i];
Lng32 numCols = 0;
Lng32 numKeys = 0;
ComTdbVirtTableColumnInfo * colInfoArray = NULL;
ComTdbVirtTableKeyInfo * keyInfoArray = NULL;
ComTdbVirtTableIndexInfo * indexInfo = NULL;
// Set up create table ddl
NAString tableDDL("CREATE TABLE ");
NAString privMgrMDLoc;
CONCAT_CATSCH(privMgrMDLoc, getSystemCatalog(), SEABASE_PRIVMGR_SCHEMA);
tableDDL += privMgrMDLoc.data() + NAString('.') + tableDefinition.tableName;
tableDDL += tableDefinition.tableDDL->str;
QString ddlString;
ddlString.str = tableDDL.data();
breadCrumb = 4;
if (processDDLandCreateDescs(parser,
&ddlString, sizeof(QString),
FALSE,
0, NULL, 0, NULL,
numCols, colInfoArray,
numKeys, keyInfoArray,
indexInfo))
goto label_error;
// Privmgr metadata is not needed to upgrade trafodion metadata so
// it uses standard SQL to perform upgrade operations. That means
// this code does not have to differenciate between old and new
// definitions.
mddi.numNewCols = numCols;
mddi.numOldCols = numCols;
mddi.newColInfo = colInfoArray;
mddi.oldColInfo = colInfoArray;
mddi.numNewKeys = numKeys;
mddi.numOldKeys = numKeys;
mddi.newKeyInfo = keyInfoArray;
mddi.oldKeyInfo = keyInfoArray;
mddi.numIndexes = 0;
mddi.indexInfo = NULL;
mddi.tableInfo = NULL;
}
return 0;
label_error:
// When debugging, you can look at the breadCrumb variable to figure out
// why you got here.
if (trafMDDescsInfo)
NADELETEBASIC(trafMDDescsInfo, CTXTHEAP);
trafMDDescsInfo = NULL;
char msg[80];
str_sprintf(msg,"CmpSeabaseDDL::createMDdescs failed, breadCrumb = %d",breadCrumb);
SQLMXLoggingArea::logSQLMXDebugEvent(msg, -1, __LINE__);
return -1;
}
NABoolean CmpSeabaseDDL::isHbase(const NAString &catName)
{
if ((CmpCommon::getDefault(MODE_SEABASE) == DF_ON) &&
(NOT catName.isNull()))
{
NAString hbaseDefCatName = "";
CmpCommon::getDefault(HBASE_CATALOG, hbaseDefCatName, FALSE);
hbaseDefCatName.toUpper();
if ((catName == HBASE_SYSTEM_CATALOG) ||
(catName == hbaseDefCatName))
return TRUE;
}
return FALSE;
}
ComBoolean CmpSeabaseDDL::isHbase(const ComObjectName &name)
{
return isHbase(name.getCatalogNamePartAsAnsiString());
}
bool CmpSeabaseDDL::isHistogramTable(const NAString &name)
{
if (name == HBASE_HIST_NAME ||
name == HBASE_HISTINT_NAME ||
name == HBASE_PERS_SAMP_NAME )
return true;
return false;
}
bool CmpSeabaseDDL::isSampleTable(const NAString &name)
{
if (name(0,min((sizeof(TRAF_SAMPLE_PREFIX)-1), name.length())) == TRAF_SAMPLE_PREFIX)
return true;
return false;
}
NABoolean CmpSeabaseDDL::isLOBDependentNameMatch(const NAString &name)
{
if ((name(0,min((sizeof(LOB_MD_PREFIX)-1), name.length())) == LOB_MD_PREFIX) ||
(name(0,min((sizeof(LOB_DESC_CHUNK_PREFIX)-1), name.length()))==LOB_DESC_CHUNK_PREFIX)||
(name(0,min((sizeof(LOB_DESC_HANDLE_PREFIX)-1), name.length()))==LOB_DESC_HANDLE_PREFIX)
)
return true;
else
return false;
}
NABoolean CmpSeabaseDDL::isSeabase(const NAString &catName)
{
if ((CmpCommon::getDefault(MODE_SEABASE) == DF_ON) &&
(NOT catName.isNull()))
{
NAString seabaseDefCatName = "";
CmpCommon::getDefault(SEABASE_CATALOG, seabaseDefCatName, FALSE);
seabaseDefCatName.toUpper();
if (catName == seabaseDefCatName)
return TRUE;
}
return FALSE;
}
ComBoolean CmpSeabaseDDL::isSeabase(const ComObjectName &name)
{
return isSeabase(name.getCatalogNamePartAsAnsiString());
}
NABoolean CmpSeabaseDDL::isSeabaseMD(
const NAString &catName,
const NAString &schName,
const NAString &objName)
{
if ((CmpCommon::getDefault(MODE_SEABASE) == DF_ON) &&
(NOT catName.isNull()))
{
NAString seabaseDefCatName = "";
CmpCommon::getDefault(SEABASE_CATALOG, seabaseDefCatName, FALSE);
seabaseDefCatName.toUpper();
if ((catName == seabaseDefCatName) &&
(schName == SEABASE_MD_SCHEMA ))
{
return TRUE;
}
}
return FALSE;
}
NABoolean CmpSeabaseDDL::isSeabasePrivMgrMD(
const NAString &catName,
const NAString &schName)
{
if ((CmpCommon::getDefault(MODE_SEABASE) == DF_ON) &&
(NOT catName.isNull()))
{
NAString seabaseDefCatName = "";
CmpCommon::getDefault(SEABASE_CATALOG, seabaseDefCatName, FALSE);
seabaseDefCatName.toUpper();
if ((catName == seabaseDefCatName) &&
(schName == SEABASE_PRIVMGR_SCHEMA))
{
return TRUE;
}
}
return FALSE;
}
NABoolean CmpSeabaseDDL::isSeabaseReservedSchema(
const NAString &catName,
const NAString &schName)
{
if (catName.isNull())
return FALSE;
NAString seabaseDefCatName = "";
CmpCommon::getDefault(SEABASE_CATALOG, seabaseDefCatName, FALSE);
seabaseDefCatName.toUpper();
return ComIsTrafodionReservedSchema(seabaseDefCatName, catName, schName);
}
NABoolean CmpSeabaseDDL::isSeabaseReservedSchema(
const ComObjectName &name)
{
const NAString &catName = name.getCatalogNamePartAsAnsiString(TRUE);
const NAString &schName = name.getSchemaNamePartAsAnsiString(TRUE);
return isSeabaseReservedSchema(catName, schName);
}
NABoolean CmpSeabaseDDL::isSeabaseExternalSchema(
const NAString &catName,
const NAString &schName)
{
if (catName.isNull())
return FALSE;
NAString seabaseDefCatName = "";
CmpCommon::getDefault(SEABASE_CATALOG, seabaseDefCatName, FALSE);
seabaseDefCatName.toUpper();
if (catName != seabaseDefCatName)
return FALSE;
return ComIsTrafodionExternalSchemaName(schName);
}
// ----------------------------------------------------------------------------
// Method: isUserUpdatableSeabaseMD
//
// This method returns TRUE if it is an updatable metadata table.
// For the most part metadata tables are no allowed to be updated directly.
// However, there is a subset of tables that can be updated directly.
//
// Since only a few tables are updatable, we will check the names directly
// instead of adding a table attribute.
// ----------------------------------------------------------------------------
NABoolean CmpSeabaseDDL::isUserUpdatableSeabaseMD(const NAString &catName,
const NAString &schName,
const NAString &objName)
{
if ((CmpCommon::getDefault(MODE_SEABASE) == DF_ON) &&
(NOT catName.isNull()))
{
NAString seabaseDefCatName = "";
CmpCommon::getDefault(SEABASE_CATALOG, seabaseDefCatName, FALSE);
seabaseDefCatName.toUpper();
if ((catName == seabaseDefCatName) &&
(schName == SEABASE_MD_SCHEMA) &&
(objName == SEABASE_DEFAULTS))
{
return TRUE;
}
}
return FALSE;
}
std::vector<std::string> CmpSeabaseDDL::getHistogramTables()
{
Int32 numHistTables = sizeof(allMDHistInfo) / sizeof(MDTableInfo);
std::vector<std::string> histTables;
for (Int32 i = 0; i < numHistTables; i++)
{
const MDTableInfo &mdh = allMDHistInfo[i];
std::string tableName(mdh.newName);
histTables.push_back(tableName);
}
return histTables;
}
ExpHbaseInterface* CmpSeabaseDDL::allocEHI(const char * server,
const char * zkPort,
NABoolean raiseError)
{
ExpHbaseInterface * ehi = NULL;
ehi = ExpHbaseInterface::newInstance
(heap_, server, zkPort);
Lng32 retcode = ehi->init(NULL);
if (retcode < 0)
{
if (raiseError) {
*CmpCommon::diags() << DgSqlCode(-8448)
<< DgString0((char*)"ExpHbaseInterface::init()")
<< DgString1(getHbaseErrStr(-retcode))
<< DgInt0(-retcode)
<< DgString2((char*)GetCliGlobals()->getJniErrorStr());
}
deallocEHI(ehi);
return NULL;
}
return ehi;
}
ExpHbaseInterface* CmpSeabaseDDL::allocEHI(NADefaults * defs)
{
ExpHbaseInterface * ehi = NULL;
NADefaults *defsL = defs;
if (!defsL)
defsL = &ActiveSchemaDB()->getDefaults();
const char * server = defsL->getValue(HBASE_SERVER);
const char* zkPort = defsL->getValue(HBASE_ZOOKEEPER_PORT);
ehi = allocEHI(server, zkPort, TRUE);
return ehi;
}
void CmpSeabaseDDL::deallocEHI(ExpHbaseInterface* &ehi)
{
if (ehi)
delete ehi;
ehi = NULL;
}
ComBoolean CmpSeabaseDDL::isSeabaseMD(const ComObjectName &name)
{
return isSeabaseMD(name.getCatalogNamePartAsAnsiString(),
name.getSchemaNamePartAsAnsiString(TRUE),
name.getObjectNamePartAsAnsiString());
}
ComBoolean CmpSeabaseDDL::isSeabasePrivMgrMD(const ComObjectName &name)
{
return isSeabasePrivMgrMD(name.getCatalogNamePartAsAnsiString(),
name.getSchemaNamePartAsAnsiString(TRUE));
}
void CmpSeabaseDDL::getColName(const char * colFam, const char * colQual,
NAString &colName)
{
char c;
colName.resize(0);
colName = colFam;
colName += ":";
c = str_atoi(colQual, strlen(colQual));
colName += c;
}
short CmpSeabaseDDL::readAndInitDefaultsFromSeabaseDefaultsTable
(NADefaults::Provenance overwriteIfNotYet, Int32 errOrWarn,
NADefaults *defs)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
if (defs->seabaseDefaultsTableRead())
return 0;
const char * server = defs->getValue(HBASE_SERVER);
const char * zkPort = defs->getValue(HBASE_ZOOKEEPER_PORT);
HbaseStr hbaseDefaults;
NAString hbaseDefaultsStr(getSystemCatalog());
hbaseDefaultsStr += ".";
hbaseDefaultsStr += SEABASE_MD_SCHEMA;
hbaseDefaultsStr += ".";
hbaseDefaultsStr += SEABASE_DEFAULTS;
hbaseDefaults.val = (char*)hbaseDefaultsStr.data();
hbaseDefaults.len = hbaseDefaultsStr.length();
NAString col1NameStr(heap_);
NAString col2NameStr(heap_);
getColName(SEABASE_DEFAULT_COL_FAMILY, "1", col1NameStr);
getColName(SEABASE_DEFAULT_COL_FAMILY, "2", col2NameStr);
LIST(NAString) col1ValueList(heap_);
LIST(NAString) col2ValueList(heap_);
LIST(NAString) listUnused(heap_);
HbaseStr col1TextStr;
HbaseStr col2TextStr;
HbaseStr colUnused;
char *col1 = NULL;
char *col2 = NULL;
ExpHbaseInterface * ehi = allocEHI(server, zkPort, FALSE);
if (! ehi)
{
retcode = -TRAF_HBASE_ACCESS_ERROR;
goto label_return;
}
retcode = existsInHbase(hbaseDefaultsStr, ehi);
if (retcode != 1) // does not exist
{
retcode = -1394;
goto label_return;
}
col1 = (char *) heap_->allocateMemory(col1NameStr.length() + 1, FALSE);
col2 = (char *) heap_->allocateMemory(col2NameStr.length() + 1, FALSE);
if (col1 == NULL || col2 == NULL)
{
retcode = -EXE_NO_MEM_TO_EXEC; // error -8571
goto label_return;
}
memcpy(col1, col1NameStr.data(), col1NameStr.length());
col1[col1NameStr.length()] = 0;
col1TextStr.val = col1;
col1TextStr.len = col1NameStr.length();
memcpy(col2, col2NameStr.data(), col2NameStr.length());
col2[col2NameStr.length()] = 0;
col2TextStr.val = col2;
col2TextStr.len = col2NameStr.length();
colUnused.val = NULL;
colUnused.len = 0;
retcode = ehi->fetchAllRows(hbaseDefaults,
2, // numCols
col1TextStr, col2TextStr, colUnused,
col1ValueList, col2ValueList, listUnused);
if (retcode != HBASE_ACCESS_SUCCESS)
{
retcode = -1394;
goto label_return;
}
retcode = 0;
defs->setSeabaseDefaultsTableRead(TRUE);
for (Lng32 i = 0; i < col1ValueList.entries(); i++)
{
NAString attrName(col1ValueList[i].data(), col1ValueList[i].length());
NAString attrValue(col2ValueList[i].data(), col2ValueList[i].length());
defs->validateAndInsert(attrName, attrValue, FALSE, errOrWarn, overwriteIfNotYet);
}
label_return:
deallocEHI(ehi);
if (col1)
heap_->deallocateMemory(col1);
if (col2)
heap_->deallocateMemory(col2);
return retcode;
}
#define VERS_CV_MAJ 1
#define VERS_CV_MIN 0
#define VERS_CV_UPD 1
VERS_BIN(xx) // get rid of warning
short CmpSeabaseDDL::getSystemSoftwareVersion(Int64 &softMajVers,
Int64 &softMinVers,
Int64 &softUpdVers)
{
// int cmaj, cmin, cupd;
int pmaj, pmin, pupd;
CALL_COMP_GET_PROD_VERS(xx,&pmaj,&pmin,&pupd);
softMajVers = pmaj;
softMinVers = pmin;
softUpdVers = pupd;
// CALL_COMP_GET_COMP_VERS(xx,cmaj,cmin,cupd);
// printf("pvers=%d.%d.%d\n", pmaj, pmin, pupd);
// printf("cvers=%d.%d.%d\n", cmaj, cmin, cupd);
return 0;
}
short CmpSeabaseDDL::validateVersions(NADefaults *defs,
ExpHbaseInterface * inEHI,
Int64 * mdMajorVersion,
Int64 * mdMinorVersion,
Int64 * mdUpdateVersion,
Int64 * sysSWMajorVersion,
Int64 * sysSWMinorVersion,
Int64 * sysSWUpdVersion,
Int64 * mdSWMajorVersion,
Int64 * mdSWMinorVersion,
Int64 * mdSWUpdateVersion,
Lng32 * hbaseErrNum,
NAString * hbaseErrStr)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
processSystemCatalog(defs);
Int64 sysMajorVersion = 0;
Int64 sysMinorVersion = 0;
Int64 sysUpdVersion = 0;
HbaseStr hbaseVersions;
NAString col1NameStr(heap_);
NAString col2NameStr(heap_);
NAString col3NameStr(heap_);
LIST(NAString) col1ValueList(heap_);
LIST(NAString) col2ValueList(heap_);
LIST(NAString) col3ValueList(heap_);
getColName(SEABASE_DEFAULT_COL_FAMILY, "1", col1NameStr);
getColName(SEABASE_DEFAULT_COL_FAMILY, "2", col2NameStr);
getColName(SEABASE_DEFAULT_COL_FAMILY, "3", col3NameStr);
char * col1 = NULL;
char * col2 = NULL;
char * col3 = NULL;
HbaseStr col1TextStr;
HbaseStr col2TextStr;
HbaseStr col3TextStr;
NAString hbaseVersionsStr(getSystemCatalog());
hbaseVersionsStr += ".";
hbaseVersionsStr += SEABASE_MD_SCHEMA;
hbaseVersionsStr += ".";
hbaseVersionsStr += SEABASE_VERSIONS;
hbaseVersions.val = (char*)hbaseVersionsStr.data();
hbaseVersions.len = hbaseVersionsStr.length();
NABoolean mdVersionFound = FALSE;
NABoolean invalidMD = FALSE;
ExpHbaseInterface * ehi = inEHI;
if (! ehi)
{
const char * server = defs->getValue(HBASE_SERVER);
const char * zkPort = defs->getValue(HBASE_ZOOKEEPER_PORT);
ehi = allocEHI(server, zkPort, TRUE);
if (! ehi)
{
// extract error info from diags area.
if ((CmpCommon::diags()) &&
(CmpCommon::diags()->getNumber() > 0))
{
ComCondition &cc = (*CmpCommon::diags())[1];
if (cc.getSQLCODE() == -8448)
{
if (hbaseErrNum)
*hbaseErrNum = cc.getOptionalInteger(0);
if (hbaseErrStr)
*hbaseErrStr = cc.getOptionalString(2);
}
CmpCommon::diags()->clear();
}
retcode = -TRAF_HBASE_ACCESS_ERROR;
goto label_return;
}
}
retcode = isMetadataInitialized(ehi);
if (retcode < 0)
{
if (hbaseErrNum)
*hbaseErrNum = retcode;
if (hbaseErrStr)
*hbaseErrStr = (char*)GetCliGlobals()->getJniErrorStr();
retcode = -TRAF_HBASE_ACCESS_ERROR;
goto label_return;
}
getSystemSoftwareVersion(sysMajorVersion, sysMinorVersion, sysUpdVersion);
if (sysSWMajorVersion || sysSWMinorVersion || sysSWUpdVersion)
{
if (sysSWMajorVersion)
*sysSWMajorVersion = sysMajorVersion;
if (sysSWMinorVersion)
*sysSWMinorVersion = sysMinorVersion;
if (sysSWUpdVersion)
*sysSWUpdVersion = sysUpdVersion;
}
if (retcode == 0) // not initialized
{
if ((sysMajorVersion != SOFTWARE_MAJOR_VERSION) ||
(sysMinorVersion != SOFTWARE_MINOR_VERSION) ||
(sysUpdVersion != SOFTWARE_UPDATE_VERSION))
{
retcode = -1397;
goto label_return;
}
retcode = -TRAF_NOT_INITIALIZED;
goto label_return;
}
if (retcode == 2)
invalidMD = TRUE;
retcode = existsInHbase(hbaseVersionsStr, ehi);
if (retcode != 1) // does not exist
{
retcode = -1394;
goto label_return;
}
col1 = (char *) heap_->allocateMemory(col1NameStr.length() + 1, FALSE);
col2 = (char *) heap_->allocateMemory(col2NameStr.length() + 1, FALSE);
col3 = (char *) heap_->allocateMemory(col3NameStr.length() + 1, FALSE);
if (col1 == NULL || col2 == NULL || col3 == NULL)
{
retcode = -EXE_NO_MEM_TO_EXEC; // error -8571
goto label_return;
}
memcpy(col1, col1NameStr.data(), col1NameStr.length());
col1[col1NameStr.length()] = 0;
col1TextStr.val = col1;
col1TextStr.len = col1NameStr.length();
memcpy(col2, col2NameStr.data(), col2NameStr.length());
col2[col2NameStr.length()] = 0;
col2TextStr.val = col2;
col2TextStr.len = col2NameStr.length();
memcpy(col3, col3NameStr.data(), col3NameStr.length());
col3[col3NameStr.length()] = 0;
col3TextStr.val = col3;
col3TextStr.len = col3NameStr.length();
retcode = ehi->fetchAllRows(hbaseVersions,
3, // numCols
col1TextStr, col2TextStr, col3TextStr,
col1ValueList, col2ValueList, col3ValueList);
if (retcode != HBASE_ACCESS_SUCCESS)
{
if (hbaseErrNum)
*hbaseErrNum = retcode;
if (hbaseErrStr)
*hbaseErrStr = (char*)GetCliGlobals()->getJniErrorStr();
retcode = -TRAF_HBASE_ACCESS_ERROR;
goto label_return;
}
else
retcode = 0;
if ((col1ValueList.entries() == 0) ||
(col2ValueList.entries() == 0) ||
(col3ValueList.entries() == 0))
{
retcode = -1394;
goto label_return;
}
for (Lng32 i = 0; i < col1ValueList.entries(); i++)
{
NAString versionType(col1ValueList[i].data(), col1ValueList[i].length());
Int64 majorVersion = *(Int64*)col2ValueList[i].data();
Int64 minorVersion = *(Int64*)col3ValueList[i].data();
NAString temp = versionType.strip(NAString::trailing, ' ');
if (temp == "METADATA")
{
Int64 updateVersion = minorVersion - (minorVersion / 10) * 10;
if (mdMajorVersion)
*mdMajorVersion = majorVersion;
if (mdMinorVersion)
*mdMinorVersion = minorVersion / 10;
if (mdUpdateVersion)
*mdUpdateVersion = updateVersion;
mdVersionFound = TRUE;
if ((majorVersion != METADATA_MAJOR_VERSION) ||
(minorVersion/10 != METADATA_MINOR_VERSION) ||
(updateVersion != METADATA_UPDATE_VERSION))
{
// version mismatch. Check if metadata is corrupt or need to be upgraded.
if (isOldMetadataInitialized(ehi))
{
retcode = -1395;
}
else
{
retcode = -1394;
}
goto label_return;
}
}
if (temp == "DATAFORMAT")
{
if ((majorVersion != DATAFORMAT_MAJOR_VERSION) ||
(minorVersion != DATAFORMAT_MINOR_VERSION))
{
retcode = -1396;
goto label_return;
}
}
if (temp == "SOFTWARE")
{
Int64 sysMajorVersion = 0;
Int64 sysMinorVersion = 0;
Int64 sysUpdVersion = 0;
getSystemSoftwareVersion(sysMajorVersion, sysMinorVersion, sysUpdVersion);
if (sysSWMajorVersion)
*sysSWMajorVersion = sysMajorVersion;
if (sysSWMinorVersion)
*sysSWMinorVersion = sysMinorVersion;
if (sysSWUpdVersion)
*sysSWUpdVersion = sysUpdVersion;
if (mdSWMajorVersion)
*mdSWMajorVersion = majorVersion;
if (mdSWMinorVersion)
*mdSWMinorVersion = minorVersion / 10;
if (mdSWUpdateVersion)
*mdSWUpdateVersion = minorVersion - (minorVersion / 10)*10;
if ((sysMajorVersion != SOFTWARE_MAJOR_VERSION) ||
(sysMinorVersion != SOFTWARE_MINOR_VERSION) ||
(sysUpdVersion != SOFTWARE_UPDATE_VERSION))
{
retcode = -1397;
goto label_return;
}
}
}
if ((NOT mdVersionFound) ||
(invalidMD))
{
retcode = -1394;
goto label_return;
}
label_return:
if (! inEHI)
deallocEHI(ehi);
if (col1)
heap_->deallocateMemory(col1);
if (col2)
heap_->deallocateMemory(col2);
if (col3)
heap_->deallocateMemory(col3);
return retcode;
}
#define CQD_SENT_MAX 7
short CmpSeabaseDDL::sendAllControlsAndFlags(CmpContext* prevContext,
Int32 cntxtType)
{
const NAString * val =
ActiveControlDB()->getControlSessionValue("SHOWPLAN");
NABoolean sendCSs = TRUE;
if ((val) && (*val == "ON"))
{
// we are within a showplan session.
// Do not send the SHOWPLAN control session or it will cause problems
// in generation of metadata plans.
sendCSs = FALSE;
}
// save the current parserflags setting from this compiler and executor context
savedCmpParserFlags_ = Get_SqlParser_Flags (0xFFFFFFFF);
SQL_EXEC_GetParserFlagsForExSqlComp_Internal(savedCliParserFlags_);
Int32 cliRC;
CmpContext *cmpctxt = CmpCommon::context();
CMPASSERT(cmpctxt->getCntlCount() >= 0 && cmpctxt->getCntlCount() <= CQD_SENT_MAX);
ExeCliInterface cliInterface(STMTHEAP);
cliRC = cliInterface.executeImmediate("control query shape hold;");
if (cliRC < 0)
{
cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
if (cmpctxt->getCntlCount() < CQD_SENT_MAX)
{
if (cmpctxt->getCntlCount() < 1)
{
cliRC = cliInterface.holdAndSetCQD("volatile_schema_in_use", "OFF");
if (cliRC < 0)
return -1;
else
cmpctxt->incCntlCount(); // = 1
}
if (cmpctxt->getCntlCount() < 2)
{
cliRC = cliInterface.holdAndSetCQD("hbase_filter_preds", "OFF");
if (cliRC < 0)
return -1;
else
cmpctxt->incCntlCount(); // = 2
}
if (cmpctxt->getCntlCount() < 3)
{
// We have to turn NJ on for meta query compilation.
cliRC = cliInterface.holdAndSetCQD("nested_joins", "ON");
if (cliRC < 0)
return -1;
else
cmpctxt->incCntlCount(); // = 3
}
if (cmpctxt->getCntlCount() < 4)
{
// turn off esp parallelism until optimizer fixes esp plan issue pbm.
cliRC = cliInterface.holdAndSetCQD("attempt_esp_parallelism", "OFF");
if (cliRC < 0)
return -1;
else
cmpctxt->incCntlCount(); // = 4
}
if (cmpctxt->getCntlCount() < 5)
{
// this cqd causes problems when internal indexes are created.
// disable it here for ddl operations.
// Not sure if this cqd is used anywhere or is needed.
// Maybe we should remove it.
cliRC = cliInterface.holdAndSetCQD("hide_indexes", "NONE");
if (cliRC < 0)
return -1;
else
cmpctxt->incCntlCount(); // = 5
}
if (cmpctxt->getCntlCount() < 6)
{
cliRC = cliInterface.holdAndSetCQD("traf_no_dtm_xn", "OFF");
if (cliRC < 0)
return -1;
else
cmpctxt->incCntlCount(); // = 6
}
if (cmpctxt->getCntlCount() < 7) // CQD_SENT_MAX is 7
{
cliRC = cliInterface.holdAndSetCQD("hbase_rowset_vsbb_opt", "OFF");
if (cliRC < 0)
return -1;
else
cmpctxt->incCntlCount(); // = 7
}
}
SQL_EXEC_SetParserFlagsForExSqlComp_Internal(INTERNAL_QUERY_FROM_EXEUTIL);
Set_SqlParser_Flags(ALLOW_VOLATILE_SCHEMA_IN_TABLE_NAME);
SQL_EXEC_SetParserFlagsForExSqlComp_Internal(ALLOW_VOLATILE_SCHEMA_IN_TABLE_NAME);
return 0;
}
void CmpSeabaseDDL::restoreAllControlsAndFlags()
{
Lng32 cliRC;
ExeCliInterface cliInterface(STMTHEAP);
cliRC = cliInterface.executeImmediate("control query shape restore;");
if (CmpCommon::context()->getCntlCount() > 0 &&
CmpCommon::context()->getCntlCount() <= CQD_SENT_MAX)
{
cliRC = cliInterface.restoreCQD("volatile_schema_in_use");
cliRC = cliInterface.restoreCQD("hbase_filter_preds");
cliRC = cliInterface.restoreCQD("nested_joins");
cliRC = cliInterface.restoreCQD("hide_indexes");
cliRC = cliInterface.restoreCQD("attempt_esp_parallelism");
cliRC = cliInterface.restoreCQD("traf_no_dtm_xn");
cliRC = cliInterface.restoreCQD("hbase_rowset_vsbb_opt");
}
// Restore parser flags settings of cmp and exe context to what they originally were
Set_SqlParser_Flags (savedCmpParserFlags_);
SQL_EXEC_AssignParserFlagsForExSqlComp_Internal(savedCliParserFlags_);
return;
}
void CmpSeabaseDDL::processReturn(Lng32 retcode)
{
return;
}
// Return value:
// 0: no metadata tables exist, metadata is not initialized
// 1: all metadata tables exists, metadata is initialized
// 2: some metadata tables exist, metadata is corrupted
// -ve: error code
short CmpSeabaseDDL::isMetadataInitialized(ExpHbaseInterface * ehi)
{
short retcode ;
ExpHbaseInterface * ehil = ehi;
if (ehil == NULL)
{
ehil = allocEHI();
if (ehil == NULL)
return 0;
}
// check to see if VERSIONS table exist. If it exist, then metadata is initialized.
// This is a quick check.
// We may still run into an issue where other metadata tables are missing or
// corrupted. That will cause an error to be returned when that table is actually
// accessed.
HbaseStr hbaseVersions;
NAString hbaseVersionsStr(getSystemCatalog());
hbaseVersionsStr += ".";
hbaseVersionsStr += SEABASE_MD_SCHEMA;
hbaseVersionsStr += ".";
hbaseVersionsStr += SEABASE_VERSIONS;
hbaseVersions.val = (char*)hbaseVersionsStr.data();
hbaseVersions.len = hbaseVersionsStr.length();
retcode = ehi->exists(hbaseVersions);
if (retcode == -1) // already exists
{
return 1; // metadata is initialized
}
else if (retcode != 0)
{
return retcode; // error accesing hbase
}
Lng32 numTotal = 0;
Lng32 numExists = 0;
retcode = 0;
for (Int32 i = 0;
(((retcode == 0) || (retcode == -1)) && (i < sizeof(allMDtablesInfo)/sizeof(MDTableInfo))); i++)
{
const MDTableInfo &mdi = allMDtablesInfo[i];
numTotal++;
HbaseStr hbaseTables;
NAString hbaseTablesStr(getSystemCatalog());
hbaseTablesStr += ".";
hbaseTablesStr += SEABASE_MD_SCHEMA;
hbaseTablesStr += ".";
hbaseTablesStr += mdi.newName;
hbaseTables.val = (char*)hbaseTablesStr.data();
hbaseTables.len = hbaseTablesStr.length();
retcode = ehil->exists(hbaseTables);
if (retcode == -1)
numExists++;
}
if (ehi == NULL)
deallocEHI(ehil);
if ((retcode != 0) && (retcode != -1))
return retcode; // error accessing metadata
if (numExists == 0)
return 0; // metadata not initialized
if (numExists == numTotal)
return 1; // metadata is initialized
if (numExists < numTotal)
return 2; // metadata is corrupt
return -1;
}
NABoolean CmpSeabaseDDL::isAuthorizationEnabled()
{
return CmpCommon::context()->isAuthorizationEnabled();
}
// ----------------------------------------------------------------------------
// method: isPrivMgrMetadataInitialized
//
// This method checks to see if the PrivMgr metadata is initialized
//
// Parameters:
// defs - pointer to the NADefaults class
// checkAllPrivTables
// (The call to verify HBase table existence is expensive so for a
// performance enhancement, we can optionally check for only one
// table and assume everything is good)
// TRUE - make sure all privmgr metadata tables exist
// FALSE - check for existence of one privmgr metadata tables
//
// returns the result of the request:
// (return codes based as same values returned for isMetadataInitialized)
// 0: no metadata tables exist, authorization is not enabled
// 1: at least one metadata tables exists, authorization is enabled
// 2: some metadata tables exist, privmgr metadata is corrupted
// -nnnn: an unexpected error occurred
// ----------------------------------------------------------------------------
short CmpSeabaseDDL::isPrivMgrMetadataInitialized(NADefaults *defs,
NABoolean checkAllPrivTables)
{
CMPASSERT(defs != NULL);
// We could call the PrivMgr "isAuthorizationEnabled" method but this causes
// a CLI request to be executed during startup which causes another compiler
// process/context to be started which then causes another compiler instance
// to be started - ad infinitem. So for now Hbase is called directly
// This code verifies that at least one the PrivMgr metadata table exist in
// HBase but it does not verify that the tables are defined correctly. A
// subsequent call to access a PrivMgr metadata table returns an error if the
// Trafodion metadata is corrupted.
const char * server = defs->getValue(HBASE_SERVER);
const char * zkPort = defs->getValue(HBASE_ZOOKEEPER_PORT);
ExpHbaseInterface * ehi = allocEHI(server, zkPort, FALSE);
if (! ehi)
{
// This code is not expected to be called, perhaps a core dump should be
// generated?
CmpCommon::diags()->clear();
deallocEHI(ehi);
return -TRAF_HBASE_ACCESS_ERROR;
}
// Call existsInHbase to check for privmgr metadata tables existence
NAString hbaseObjPrefix = getSystemCatalog();
hbaseObjPrefix += ".";
hbaseObjPrefix += SEABASE_PRIVMGR_SCHEMA;
hbaseObjPrefix += ".";
HbaseStr hbaseObjStr;
NAString hbaseObject;
int numTablesFound = 0;
short retcode = 0;
size_t numTables = (checkAllPrivTables) ?
sizeof(privMgrTables)/sizeof(PrivMgrTableStruct) : 1;
for (int ndx_tl = 0; ndx_tl < numTables; ndx_tl++)
{
const PrivMgrTableStruct &tableDef = privMgrTables[ndx_tl];
hbaseObject = hbaseObjPrefix + tableDef.tableName;
hbaseObjStr.val = (char*)hbaseObject.data();
hbaseObjStr.len = hbaseObject.length();
// existsInHbase returns 1 - found, 0 not found, anything else error
retcode = existsInHbase(hbaseObject, ehi);
if (retcode == 1) // found the table
numTablesFound ++;
// If an unexpected error occurs, just return the error
if (retcode < 0)
{
deallocEHI(ehi);
return retcode;
}
}
deallocEHI(ehi);
if (numTablesFound == 0)
retcode = 0;
else if (numTablesFound == numTables)
retcode = 1;
else
retcode = 2;
return retcode;
}
short CmpSeabaseDDL::existsInHbase(const NAString &objName,
ExpHbaseInterface * ehi)
{
ExpHbaseInterface * ehil = ehi;
if (! ehi)
{
ehil = allocEHI();
if (ehil == NULL)
return -1;
}
HbaseStr hbaseObj;
hbaseObj.val = (char*)objName.data();
hbaseObj.len = objName.length();
Lng32 retcode = ehil->exists(hbaseObj);
if (! ehi)
{
deallocEHI(ehil);
}
if (retcode == -1) // already exists
return 1;
if (retcode == 0)
return 0; // does not exist
return retcode; // error
}
// ----------------------------------------------------------------------------
// Method: processSystemCatalog
//
// This method sets up system catalog name in the CmpSeabaseDDL class
//
// The system define called SEABASE_CATALOG can be used to overwrite the
// default name of TRAFODION.
// ----------------------------------------------------------------------------
void CmpSeabaseDDL::processSystemCatalog(NADefaults *defs)
{
NAString value(TRAFODION_SYSCAT_LIT);
if (defs)
defs->validateAndInsert("SEABASE_CATALOG", value, FALSE);
else
ActiveSchemaDB()->getDefaults().validateAndInsert(
"SEABASE_CATALOG", value, FALSE);
seabaseSysCat_ = value;
CONCAT_CATSCH(seabaseMDSchema_,seabaseSysCat_,SEABASE_MD_SCHEMA);
}
const char * CmpSeabaseDDL::getSystemCatalog()
{
return seabaseSysCat_.data();
}
NAString CmpSeabaseDDL::getSystemCatalogStatic()
{
NAString value(TRAFODION_SYSCAT_LIT);
if (CmpCommon::context() && ActiveSchemaDB())
{
const char* sysCat = ActiveSchemaDB()->getDefaults().getValue(SEABASE_CATALOG);
value = sysCat;
}
return value;
}
NABoolean CmpSeabaseDDL::xnInProgress(ExeCliInterface *cliInterface)
{
if (cliInterface->statusXn() == 0) // xn in progress
return TRUE;
else
return FALSE;
}
short CmpSeabaseDDL::beginXn(ExeCliInterface *cliInterface)
{
Lng32 cliRC = 0;
cliRC = cliInterface->beginWork();
return cliRC;
}
short CmpSeabaseDDL::commitXn(ExeCliInterface *cliInterface)
{
Lng32 cliRC = 0;
cliRC = cliInterface->commitWork();
return cliRC;
}
short CmpSeabaseDDL::rollbackXn(ExeCliInterface *cliInterface)
{
Lng32 cliRC = 0;
cliRC = cliInterface->rollbackWork();
return cliRC;
}
short CmpSeabaseDDL::autoCommit(ExeCliInterface *cliInterface, NABoolean v)
{
Lng32 cliRC = 0;
cliRC = cliInterface->autoCommit(v);
return cliRC;
}
short CmpSeabaseDDL::beginXnIfNotInProgress(ExeCliInterface *cliInterface,
NABoolean &xnWasStartedHere)
{
Int32 cliRC = 0;
xnWasStartedHere = FALSE;
if (NOT xnInProgress(cliInterface))
{
cliRC = cliInterface->beginXn();
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
CmpContext* cmpContext = CmpCommon::context();
cmpContext->ddlObjsList().clear();
xnWasStartedHere = TRUE;
}
return 0;
}
short CmpSeabaseDDL::endXnIfStartedHere(ExeCliInterface *cliInterface,
NABoolean &xnWasStartedHere, Int32 cliRC)
{
if (xnWasStartedHere)
{
xnWasStartedHere = FALSE;
if (NOT xnInProgress(cliInterface))
return cliRC;
if (cliRC < 0)
{
// rollback transaction and return original error cliRC.
// Ignore rollback errors.
cliInterface->rollbackXn();
return cliRC;
}
else
{
cliRC = cliInterface->commitXn();
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return cliRC;
}
ddlInvalidateNATables();
}
CmpContext* cmpContext = CmpCommon::context();
cmpContext->ddlObjsList().clear();
}
return cliRC;
}
// Invalidate NATables for ddl objects that were affected in
// this transaction.
// DDL objects have already been set in ddlObjsList.
short CmpSeabaseDDL::ddlInvalidateNATables()
{
CmpContext* cmpContext = CmpCommon::context();
for (Lng32 i = 0; i < cmpContext->ddlObjsList().entries(); i++)
{
CmpContext::DDLObjInfo &ddlObj = cmpContext->ddlObjsList()[i];
NAString &ddlObjName = ddlObj.ddlObjName;
ComQiScope &qiScope = ddlObj.qiScope;
ComObjectType &ot = ddlObj.ot;
Int64 objUID = ddlObj.objUID;
ComObjectName tableName(ddlObjName);
const NAString catalogNamePart =
tableName.getCatalogNamePartAsAnsiString();
const NAString schemaNamePart =
tableName.getSchemaNamePartAsAnsiString(TRUE);
const NAString objectNamePart =
tableName.getObjectNamePartAsAnsiString(TRUE);
CorrName cn(objectNamePart, STMTHEAP, schemaNamePart, catalogNamePart);
if (ot == COM_USER_DEFINED_ROUTINE_OBJECT)
ActiveSchemaDB()->getNARoutineDB()->removeNARoutine(
cn.getQualifiedNameObj(),
qiScope, objUID, TRUE, TRUE);
else
ActiveSchemaDB()->getNATableDB()->removeNATable(cn, qiScope, ot, TRUE, TRUE);
}
return 0;
}
short CmpSeabaseDDL::populateKeyInfo(ComTdbVirtTableKeyInfo &keyInfo,
OutputInfo * oi, NABoolean isIndex)
{
// get the column name
Lng32 len = strlen(oi->get(0));
keyInfo.colName = new(STMTHEAP) char[len + 1];
strcpy((char*)keyInfo.colName, (char*)oi->get(0));
keyInfo.tableColNum = *(Lng32*)oi->get(1);
keyInfo.keySeqNum = *(Lng32*)oi->get(2);
keyInfo.ordering = *(Lng32*)oi->get(3);
keyInfo.nonKeyCol = *(Lng32*)oi->get(4);
if (isIndex)
{
keyInfo.hbaseColFam = new(STMTHEAP) char[strlen(SEABASE_DEFAULT_COL_FAMILY) + 1];
strcpy((char*)keyInfo.hbaseColFam, SEABASE_DEFAULT_COL_FAMILY);
char qualNumStr[40];
str_sprintf(qualNumStr, "@%d", keyInfo.keySeqNum);
keyInfo.hbaseColQual = new(STMTHEAP) char[strlen(qualNumStr)+1];
strcpy((char*)keyInfo.hbaseColQual, qualNumStr);
}
else
{
keyInfo.hbaseColFam = NULL;
keyInfo.hbaseColQual = NULL;
}
return 0;
}
NABoolean CmpSeabaseDDL::enabledForSerialization(NAColumn * nac)
{
const NAType *givenType = nac->getType();
if ((nac) &&
((NOT givenType->isEncodingNeeded()) ||
(nac && CmpSeabaseDDL::isSerialized(nac->getHbaseColFlags()))))
{
return TRUE;
}
return FALSE;
}
// NAColumn in memory is expected to have the correct HbaseColFlags for
// serialization depending on if it belongs to index or table.
// Index and Table row format can be different now. However, it is
// recommended that the function is called only when it is not aligned
// row format. The existing callers are verified to be working correctly
// even though some callers don't adhere to this recommendation
NABoolean CmpSeabaseDDL::isEncodingNeededForSerialization(NAColumn * nac)
{
const NAType *givenType = nac->getType();
if ((nac) &&
(CmpSeabaseDDL::isSerialized(nac->getHbaseColFlags())) &&
((givenType->isEncodingNeeded()) &&
(NOT DFS2REC::isAnyVarChar(givenType->getFSDatatype()))))
{
return TRUE;
}
return FALSE;
}
// removing leading and trailing blank pad characters and
// converting characters to upper case is done earlier.
static NABoolean isTrueFalseStr(const NAText& str)
{
if (str == "TRUE" || str == "FALSE")
return TRUE;
return FALSE;
}
static NABoolean isHBaseCompressionOption(const NAText& str)
{
if (str == "NONE" || str == "GZ" || str == "LZO" ||
str == "LZ4" || str == "SNAPPY")
return TRUE;
return FALSE;
}
static NABoolean isHBaseDurabilityOption(const NAText& str)
{
if (str == "ASYNC_WAL" || str == "FSYNC_WAL" || str == "SKIP_WAL" ||
str == "SYNC" || str == "USE_DEFAULT")
return TRUE;
return FALSE;
}
static NABoolean isHBaseEncodingOption(const NAText& str)
{
if (str == "NONE" || str == "PREFIX" || str == "PREFIX_TREE" ||
str == "DIFF" || str == "FAST_DIFF")
return TRUE;
return FALSE;
}
static NABoolean isHBaseBloomFilterOption(const NAText& str)
{
if (str == "NONE" || str == "ROW" || str == "ROWCOL")
return TRUE;
return FALSE;
}
// note: this function expects hbaseCreateOptionsArray to have
// HBASE_MAX_OPTIONS elements
short CmpSeabaseDDL::generateHbaseOptionsArray(
NAText * hbaseCreateOptionsArray,
NAList<HbaseCreateOption*> * hbaseCreateOptions)
{
if (! hbaseCreateOptions)
return 0;
for (CollIndex i = 0; i < hbaseCreateOptions->entries(); i++)
{
HbaseCreateOption * hbaseOption = (*hbaseCreateOptions)[i];
NAText &s = hbaseOption->val();
NAText valInOrigCase;
// trim leading and trailing spaces
size_t startpos = s.find_first_not_of(" ");
if (startpos != string::npos) // found a non-space character
{
size_t endpos = s.find_last_not_of(" ");
s = s.substr( startpos, endpos-startpos+1 );
}
// upcase value, save original (now trimmed).
valInOrigCase = s;
// Do not upcase column family name as fam name is case sensitive
if (hbaseOption->key() != "NAME")
std::transform(s.begin(), s.end(), s.begin(), ::toupper);
NABoolean isError = FALSE;
if (hbaseOption->key() == "NAME")
{
if (!hbaseCreateOptionsArray[HBASE_NAME].empty())
isError = TRUE;
hbaseCreateOptionsArray[HBASE_NAME] = hbaseOption->val();
}
else if (hbaseOption->key() == "MAX_VERSIONS")
{
if ((str_atoi(hbaseOption->val().data(),
hbaseOption->val().length()) == -1) ||
(!hbaseCreateOptionsArray[HBASE_MAX_VERSIONS].empty()))
isError = TRUE;
hbaseCreateOptionsArray[HBASE_MAX_VERSIONS] = hbaseOption->val();
}
else if (hbaseOption->key() == "MIN_VERSIONS")
{
if ((str_atoi(hbaseOption->val().data(),
hbaseOption->val().length()) == -1) ||
(!hbaseCreateOptionsArray[HBASE_MIN_VERSIONS].empty()))
isError = TRUE;
hbaseCreateOptionsArray[HBASE_MIN_VERSIONS] = hbaseOption->val();
}
else if ((hbaseOption->key() == "TIME_TO_LIVE") ||
(hbaseOption->key() == "TTL"))
{
if ((str_atoi(hbaseOption->val().data(),
hbaseOption->val().length()) == -1) ||
(!hbaseCreateOptionsArray[HBASE_TTL].empty()))
isError = TRUE;
hbaseCreateOptionsArray[HBASE_TTL] = hbaseOption->val();
}
else if (hbaseOption->key() == "BLOCKCACHE")
{
if ((!isTrueFalseStr(hbaseOption->val())) ||
(!hbaseCreateOptionsArray[HBASE_BLOCKCACHE].empty()))
isError = TRUE ;
hbaseCreateOptionsArray[HBASE_BLOCKCACHE] = hbaseOption->val();
}
else if (hbaseOption->key() == "IN_MEMORY")
{
if ((!isTrueFalseStr(hbaseOption->val())) ||
(!hbaseCreateOptionsArray[HBASE_IN_MEMORY].empty()))
isError = TRUE ;
hbaseCreateOptionsArray[HBASE_IN_MEMORY] = hbaseOption->val();
}
else if (hbaseOption->key() == "COMPRESSION")
{
if ((!isHBaseCompressionOption(hbaseOption->val())) ||
(!hbaseCreateOptionsArray[HBASE_COMPRESSION].empty()))
isError = TRUE ;
hbaseCreateOptionsArray[HBASE_COMPRESSION] = hbaseOption->val();
}
else if (hbaseOption->key() == "BLOOMFILTER")
{
if ((!isHBaseBloomFilterOption(hbaseOption->val())) ||
(!hbaseCreateOptionsArray[HBASE_BLOOMFILTER].empty()))
isError = TRUE ;
hbaseCreateOptionsArray[HBASE_BLOOMFILTER] = hbaseOption->val();
}
else if (hbaseOption->key() == "BLOCKSIZE")
{
if ((str_atoi(hbaseOption->val().data(),
hbaseOption->val().length()) == -1) ||
(!hbaseCreateOptionsArray[HBASE_BLOCKSIZE].empty()))
isError = TRUE;
hbaseCreateOptionsArray[HBASE_BLOCKSIZE] = hbaseOption->val();
}
else if (hbaseOption->key() == "DATA_BLOCK_ENCODING")
{
if ((!isHBaseEncodingOption(hbaseOption->val())) ||
(!hbaseCreateOptionsArray[HBASE_DATA_BLOCK_ENCODING].empty()))
isError = TRUE ;
hbaseCreateOptionsArray[HBASE_DATA_BLOCK_ENCODING] =
hbaseOption->val();
}
else if (hbaseOption->key() == "CACHE_BLOOMS_ON_WRITE")
{
if ((!isTrueFalseStr(hbaseOption->val())) ||
(!hbaseCreateOptionsArray[HBASE_CACHE_BLOOMS_ON_WRITE].empty()))
isError = TRUE ;
hbaseCreateOptionsArray[HBASE_CACHE_BLOOMS_ON_WRITE] =
hbaseOption->val();
}
else if (hbaseOption->key() == "CACHE_DATA_ON_WRITE")
{
if ((!isTrueFalseStr(hbaseOption->val())) ||
(!hbaseCreateOptionsArray[HBASE_CACHE_DATA_ON_WRITE].empty()))
isError = TRUE ;
hbaseCreateOptionsArray[HBASE_CACHE_DATA_ON_WRITE] =
hbaseOption->val();
}
else if (hbaseOption->key() == "CACHE_INDEXES_ON_WRITE")
{
if ((!isTrueFalseStr(hbaseOption->val())) ||
(!hbaseCreateOptionsArray[HBASE_CACHE_INDEXES_ON_WRITE].empty()))
isError = TRUE ;
hbaseCreateOptionsArray[HBASE_CACHE_INDEXES_ON_WRITE] =
hbaseOption->val();
}
else if (hbaseOption->key() == "COMPACT_COMPRESSION")
{
if ((!isHBaseCompressionOption(hbaseOption->val())) ||
(!hbaseCreateOptionsArray[HBASE_COMPACT_COMPRESSION].empty()))
isError = TRUE ;
hbaseCreateOptionsArray[HBASE_COMPACT_COMPRESSION] =
hbaseOption->val();
}
else if (hbaseOption->key() == "PREFIX_LENGTH_KEY")
{
if ((str_atoi(hbaseOption->val().data(),
hbaseOption->val().length()) == -1) ||
(!hbaseCreateOptionsArray[HBASE_PREFIX_LENGTH_KEY].empty()))
isError = TRUE;
hbaseCreateOptionsArray[HBASE_PREFIX_LENGTH_KEY] =
hbaseOption->val();
}
else if (hbaseOption->key() == "EVICT_BLOCKS_ON_CLOSE")
{
if ((!isTrueFalseStr(hbaseOption->val())) ||
(!hbaseCreateOptionsArray[HBASE_EVICT_BLOCKS_ON_CLOSE].empty()))
isError = TRUE ;
hbaseCreateOptionsArray[HBASE_EVICT_BLOCKS_ON_CLOSE] =
hbaseOption->val();
}
else if (hbaseOption->key() == "KEEP_DELETED_CELLS")
{
if ((!isTrueFalseStr(hbaseOption->val())) ||
(!hbaseCreateOptionsArray[HBASE_KEEP_DELETED_CELLS].empty()))
isError = TRUE ;
hbaseCreateOptionsArray[HBASE_KEEP_DELETED_CELLS] =
hbaseOption->val();
}
else if (hbaseOption->key() == "REPLICATION_SCOPE")
{
if ((str_atoi(hbaseOption->val().data(),
hbaseOption->val().length()) == -1) ||
(!hbaseCreateOptionsArray[HBASE_REPLICATION_SCOPE].empty()))
isError = TRUE;
hbaseCreateOptionsArray[HBASE_REPLICATION_SCOPE] =
hbaseOption->val();
}
else if (hbaseOption->key() == "MAX_FILESIZE")
{
if ((str_atoi(hbaseOption->val().data(),
hbaseOption->val().length()) == -1) ||
(!hbaseCreateOptionsArray[HBASE_MAX_FILESIZE].empty()))
isError = TRUE;
hbaseCreateOptionsArray[HBASE_MAX_FILESIZE] = hbaseOption->val();
}
else if (hbaseOption->key() == "COMPACT")
{
if ((!isTrueFalseStr(hbaseOption->val())) ||
(!hbaseCreateOptionsArray[HBASE_COMPACT].empty()))
isError = TRUE ;
hbaseCreateOptionsArray[HBASE_COMPACT] = hbaseOption->val();
}
else if (hbaseOption->key() == "DURABILITY")
{
if ((!isHBaseDurabilityOption(hbaseOption->val())) ||
(!hbaseCreateOptionsArray[HBASE_DURABILITY].empty()))
isError = TRUE ;
hbaseCreateOptionsArray[HBASE_DURABILITY] = hbaseOption->val();
}
else if (hbaseOption->key() == "MEMSTORE_FLUSH_SIZE")
{
if ((str_atoi(hbaseOption->val().data(),
hbaseOption->val().length()) == -1) ||
(!hbaseCreateOptionsArray[HBASE_MEMSTORE_FLUSH_SIZE].empty()))
isError = TRUE;
hbaseCreateOptionsArray[HBASE_MEMSTORE_FLUSH_SIZE] =
hbaseOption->val();
}
else if (hbaseOption->key() == "CACHE_DATA_IN_L1")
{
if ((!isTrueFalseStr(hbaseOption->val())) ||
(!hbaseCreateOptionsArray[HBASE_CACHE_DATA_IN_L1].empty()))
isError = TRUE ;
hbaseCreateOptionsArray[HBASE_CACHE_DATA_IN_L1] = hbaseOption->val();
}
else if (hbaseOption->key() == "PREFETCH_BLOCKS_ON_OPEN")
{
if ((!isTrueFalseStr(hbaseOption->val())) ||
(!hbaseCreateOptionsArray[HBASE_PREFETCH_BLOCKS_ON_OPEN].empty()))
isError = TRUE ;
hbaseCreateOptionsArray[HBASE_PREFETCH_BLOCKS_ON_OPEN] =
hbaseOption->val();
}
else if (hbaseOption->key() == "SPLIT_POLICY")
{
// for now, restrict the split policies to some well-known
// values, because specifying an invalid class gets us into
// a hang situation in the region server
if ((valInOrigCase == "org.apache.hadoop.hbase.regionserver.ConstantSizeRegionSplitPolicy" ||
valInOrigCase == "org.apache.hadoop.hbase.regionserver.IncreasingToUpperBoundRegionSplitPolicy"
||
valInOrigCase == "org.apache.hadoop.hbase.regionserver.KeyPrefixRegionSplitPolicy") && (hbaseCreateOptionsArray[HBASE_SPLIT_POLICY].empty()))
hbaseCreateOptionsArray[HBASE_SPLIT_POLICY] = valInOrigCase;
else
isError = TRUE;
}
else if (hbaseOption->key() == "HDFS_STORAGE_POLICY")
{
hbaseCreateOptionsArray[HBASE_HDFS_STORAGE_POLICY] =
hbaseOption->val();
}
else
isError = TRUE;
if (isError)
{
*CmpCommon::diags() << DgSqlCode(-8449)
<< DgString0(hbaseOption->key().data())
<< DgString1(valInOrigCase.data());
return -1;
}
} // for
return 0;
}
short CmpSeabaseDDL::createHbaseTable(ExpHbaseInterface *ehi,
HbaseStr *table,
std::vector<NAString> &colFamVec,
NAList<HbaseCreateOption*> * hbaseCreateOptions,
const int numSplits,
const int keyLength,
char** encodedKeysBuffer,
NABoolean doRetry,
NABoolean ddlXns)
{
// this method is called after validating that the table doesn't exist in seabase
// metadata. It creates the corresponding hbase table.
short retcode = 0;
HBASE_NAMELIST colFamList(STMTHEAP);
HbaseStr colFam;
retcode = -1;
Lng32 numTries = 0;
Lng32 delaySecs = 500; // 5 secs to start with
if (doRetry)
{
while ((numTries < 24) && (retcode == -1)) // max 2 min
{
retcode = ehi->exists(*table);
if (retcode == -1)
{
// if this state is reached, it indicates that the table was not found in metadata
// but exists in hbase. This may be due to that table being dropped from another
// process or thread in an asynchronous manner.
// Delay and check again.
numTries++;
DELAY(delaySecs);
}
} // while
}
else
retcode = ehi->exists(*table);
if (retcode == -1)
{
*CmpCommon::diags() << DgSqlCode(-1431)
<< DgString0(table->val);
return -1;
}
if (retcode < 0)
{
*CmpCommon::diags() << DgSqlCode(-8448)
<< DgString0((char*)"ExpHbaseInterface::exists()")
<< DgString1(getHbaseErrStr(-retcode))
<< DgInt0(-retcode)
<< DgString2((char*)GetCliGlobals()->getJniErrorStr());
return -1;
}
NAText hbaseCreateOptionsArray[HBASE_MAX_OPTIONS];
if (generateHbaseOptionsArray(hbaseCreateOptionsArray,
hbaseCreateOptions) < 0)
{
// diags already set
return -1;
}
if (NOT hbaseCreateOptionsArray[HBASE_NAME].empty())
{
short retcode = -HBASE_CREATE_OPTIONS_ERROR;
*CmpCommon::diags() << DgSqlCode(-8448)
<< DgString0((char*)"CmpSeabaseDDL::generateHbaseOptionsArray()")
<< DgString1(getHbaseErrStr(-retcode))
<< DgInt0(-retcode)
<< DgString2((char*)"NAME");
return -1;
}
NABoolean isMVCC = true;
if (CmpCommon::getDefault(TRAF_TRANS_TYPE) == DF_SSCC)
isMVCC = false;
NAString colFamNames;
for (int i = 0; i < colFamVec.size(); i++)
{
colFamNames += colFamVec[i];
colFamNames += " ";
}
hbaseCreateOptionsArray[HBASE_NAME] = colFamNames.data();
// TEMPTEMP
// Currently DTM crashes if number of column families goes beyond 5.
// Do not use ddl xns if number of explicitly specified column fams
// exceed 5. This is not a common case as recommendation from HBase
// for good performance is to keep num of col fams small (3 or 4).
// Once dtm bug is fixed, this check will be removed.
if (colFamVec.size() > 5)
ddlXns = FALSE;
retcode = ehi->create(*table, hbaseCreateOptionsArray,
numSplits, keyLength,
(const char **)encodedKeysBuffer,
(NOT ddlXns),
isMVCC);
if (retcode < 0)
{
*CmpCommon::diags() << DgSqlCode(-8448)
<< DgString0((char*)"ExpHbaseInterface::create()")
<< DgString1(getHbaseErrStr(-retcode))
<< DgInt0(-retcode)
<< DgString2((char*)GetCliGlobals()->getJniErrorStr());
return -1;
}
return 0;
}
short CmpSeabaseDDL::createHbaseTable(ExpHbaseInterface *ehi,
HbaseStr *table,
const char * cf1,
NAList<HbaseCreateOption*> * inHbaseCreateOptions,
const int numSplits,
const int keyLength,
char** encodedKeysBuffer,
NABoolean doRetry,
NABoolean ddlXns)
{
if (! cf1)
return -1;
std::vector<NAString> colFamVec;
colFamVec.push_back(cf1);
NAList<HbaseCreateOption*> lHbaseCreateOptions(STMTHEAP);
NAText lHbaseCreateOptionsArray[HBASE_MAX_OPTIONS];
NAList<HbaseCreateOption*> * hbaseCreateOptions = inHbaseCreateOptions;
if (! inHbaseCreateOptions)
hbaseCreateOptions = &lHbaseCreateOptions;
return createHbaseTable(ehi, table, colFamVec, hbaseCreateOptions,
numSplits, keyLength,
encodedKeysBuffer, doRetry, ddlXns);
}
short CmpSeabaseDDL::alterHbaseTable(ExpHbaseInterface *ehi,
HbaseStr *table,
NAList<NAString> &allColFams,
NAList<HbaseCreateOption*> * hbaseCreateOptions,
NABoolean ddlXns)
{
short retcode = 0;
NAText hbaseCreateOptionsArray[HBASE_MAX_OPTIONS];
if (generateHbaseOptionsArray(hbaseCreateOptionsArray,
hbaseCreateOptions))
{
// diags already set
retcode = -1;
}
else
{
NABoolean noXn = (NOT ddlXns);
retcode = 0;
// if col family name passed in, change attrs for that family.
// Otherwise change it for all user specified families.
if (hbaseCreateOptionsArray[HBASE_NAME].empty())
{
for (int i = 0; ((retcode != -1) && (i < allColFams.entries())); i++)
{
NAString colFam = allColFams[i];
hbaseCreateOptionsArray[HBASE_NAME] = colFam;
retcode = ehi->alter(*table, hbaseCreateOptionsArray, noXn);
} // for
} // if
else
{
retcode = ehi->alter(*table, hbaseCreateOptionsArray, noXn);
}
if (retcode < 0)
{
*CmpCommon::diags() << DgSqlCode(-8448)
<< DgString0((char*)"ExpHbaseInterface::alter()")
<< DgString1(getHbaseErrStr(-retcode))
<< DgInt0(-retcode)
<< DgString2((char*)GetCliGlobals()->getJniErrorStr());
retcode = -1;
} // if
} // else
return retcode;
}
short CmpSeabaseDDL::dropHbaseTable(ExpHbaseInterface *ehi,
HbaseStr *table, NABoolean asyncDrop,
NABoolean ddlXns)
{
short retcode = 0;
retcode = ehi->exists(*table);
if (retcode == -1) // exists
{
if ((CmpCommon::getDefault(HBASE_ASYNC_DROP_TABLE) == DF_ON) ||
(asyncDrop))
retcode = ehi->drop(*table, TRUE, (NOT ddlXns));
else
retcode = ehi->drop(*table, FALSE, (NOT ddlXns));
if (retcode < 0)
{
*CmpCommon::diags() << DgSqlCode(-8448)
<< DgString0((char*)"ExpHbaseInterface::drop()")
<< DgString1(getHbaseErrStr(-retcode))
<< DgInt0(-retcode)
<< DgString2((char*)GetCliGlobals()->getJniErrorStr());
return -1;
}
}
if (retcode != 0)
{
*CmpCommon::diags() << DgSqlCode(-8448)
<< DgString0((char*)"ExpHbaseInterface::exists()")
<< DgString1(getHbaseErrStr(-retcode))
<< DgInt0(-retcode)
<< DgString2((char*)GetCliGlobals()->getJniErrorStr());
return -1;
}
return 0;
}
short CmpSeabaseDDL::copyHbaseTable(ExpHbaseInterface *ehi,
HbaseStr *currTable, HbaseStr* oldTable)
{
short retcode = 0;
retcode = ehi->exists(*currTable);
if (retcode == -1) // exists
{
retcode = ehi->copy(*currTable, *oldTable);
if (retcode < 0)
{
*CmpCommon::diags() << DgSqlCode(-8448)
<< DgString0((char*)"ExpHbaseInterface::copy()")
<< DgString1(getHbaseErrStr(-retcode))
<< DgInt0(-retcode)
<< DgString2((char*)GetCliGlobals()->getJniErrorStr());
return -1;
}
}
if (retcode != 0)
{
*CmpCommon::diags() << DgSqlCode(-8448)
<< DgString0((char*)"ExpHbaseInterface::copy()")
<< DgString1(getHbaseErrStr(-retcode))
<< DgInt0(-retcode)
<< DgString2((char*)GetCliGlobals()->getJniErrorStr());
return -1;
}
return 0;
}
short CmpSeabaseDDL::checkDefaultValue(
const NAString & colExtName,
const NAType * colType,
ElemDDLColDef * colNode)
{
short rc = 0;
ItemExpr * defExpr = colNode->getDefaultValueExpr();
ConstValue *cvDefault = (ConstValue *)colNode->getDefaultValueExpr();
NAType * newType = (NAType *)colType;
if ((colType->getTypeQualifier() == NA_CHARACTER_TYPE) &&
(cvDefault->getType()->getTypeQualifier() == NA_CHARACTER_TYPE))
{
if (colType->getNominalSize() > cvDefault->getType()->getNominalSize())
{
newType = colType->newCopy(STMTHEAP);
newType->setNominalSize(
MAXOF(cvDefault->getType()->getNominalSize(), 1));
}
else if (colType->getNominalSize() < cvDefault->getType()->getNominalSize())
{
defExpr = new(STMTHEAP) Cast(defExpr, colType);
((Cast*)defExpr)->setCheckTruncationError(TRUE);
}
}
NAString castToTypeStr(newType->getTypeSQLname(TRUE));
char buf[1000];
str_sprintf(buf, "CAST(@A1 AS %s)", castToTypeStr.data());
rc = Generator::genAndEvalExpr(CmpCommon::context(),
buf, 1, defExpr, NULL,
CmpCommon::diags());
if (rc)
{
*CmpCommon::diags()
<< DgSqlCode(-CAT_INCOMPATIBLE_DATA_TYPE_IN_DEFAULT_CLAUSE)
<< DgColumnName(colExtName)
<< DgString0(castToTypeStr.data())
<< DgString1(cvDefault->getConstStr());
}
return rc;
}
short CmpSeabaseDDL::getTypeInfo(const NAType * naType,
NABoolean alignedFormat,
Lng32 serializedOption,
Lng32 &datatype,
Lng32 &length,
Lng32 &precision,
Lng32 &scale,
Lng32 &dtStart,
Lng32 &dtEnd,
Lng32 &upshifted,
Lng32 &nullable,
NAString &charset,
CharInfo::Collation &collationSequence,
ULng32 &hbaseColFlags)
{
short rc = 0;
datatype = 0;
length = 0;
precision = 0;
scale = 0;
dtStart = 0;
dtEnd = 0;
nullable = 0;
upshifted = 0;
charset = SQLCHARSETSTRING_UNKNOWN;
collationSequence = CharInfo::DefaultCollation;
datatype = (Lng32)naType->getFSDatatype();
length = naType->getNominalSize();
nullable = naType->supportsSQLnull();
switch (naType->getTypeQualifier())
{
case NA_CHARACTER_TYPE:
{
CharType *charType = (CharType *)naType;
scale = 0;
precision = charType->getPrecisionOrMaxNumChars();
charset = CharInfo::getCharSetName(charType->getCharSet());
upshifted = (charType->isUpshifted() ? -1 : 0);
collationSequence = charType->getCollation();
if (serializedOption == 1) // option explicitly specified
{
setFlags(hbaseColFlags, NAColumn::SEABASE_SERIALIZED);
}
else if ((serializedOption == -1) && // not specified
(CmpCommon::getDefault(HBASE_SERIALIZATION) == DF_ON) &&
(NOT alignedFormat))
{
setFlags(hbaseColFlags, NAColumn::SEABASE_SERIALIZED);
}
}
break;
case NA_NUMERIC_TYPE:
{
NumericType *numericType = (NumericType *)naType;
scale = numericType->getScale();
if (datatype == REC_BPINT_UNSIGNED)
precision = numericType->getPrecision();
else if (numericType->binaryPrecision())
precision = 0;
else
precision = numericType->getPrecision();
if (serializedOption == 1) // option explicitly specified
{
if (DFS2REC::isBinary(datatype))
setFlags(hbaseColFlags, NAColumn::SEABASE_SERIALIZED);
else if (numericType->isEncodingNeeded())
{
*CmpCommon::diags() << DgSqlCode(-1191)
<< DgString0(numericType->getSimpleTypeName());
return -1;
}
}
else if ((serializedOption == -1) && // not specified
(CmpCommon::getDefault(HBASE_SERIALIZATION) == DF_ON) &&
(DFS2REC::isBinary(datatype)) &&
(NOT alignedFormat))
{
setFlags(hbaseColFlags, NAColumn::SEABASE_SERIALIZED);
}
}
break;
case NA_DATETIME_TYPE:
case NA_INTERVAL_TYPE:
{
DatetimeIntervalCommonType *dtiCommonType =
(DatetimeIntervalCommonType *)naType;
scale = dtiCommonType->getFractionPrecision();
precision = dtiCommonType->getLeadingPrecision();
dtStart = dtiCommonType->getStartField();
dtEnd = dtiCommonType->getEndField();
if ((serializedOption == 1) &&
(dtiCommonType->isEncodingNeeded()))
{
*CmpCommon::diags() << DgSqlCode(-1191)
<< DgString0(dtiCommonType->getSimpleTypeName());
return -1;
}
}
break;
case NA_LOB_TYPE:
{
if (datatype == REC_BLOB)
{
SQLBlob *blobType = (SQLBlob *) naType;
precision = (ComSInt32)blobType->getLobLength();
}
else
{
SQLClob *clobType = (SQLClob *)naType;
precision = (ComSInt32)clobType->getLobLength();
}
}
break;
case NA_BOOLEAN_TYPE:
{
precision = 0;
}
break;
default:
{
*CmpCommon::diags() << DgSqlCode(-CAT_INVALID_COLUMN_DATATYPE);
return -1;
}
} // switch
if ((serializedOption == 1) && (alignedFormat))
{
// ignore serialized option on aligned format tables
resetFlags(hbaseColFlags, NAColumn::SEABASE_SERIALIZED);
/*
*CmpCommon::diags()
<< DgSqlCode(-4222)
<< DgString0("\"SERIALIZED option on ALIGNED format tables\"");
return -1;
*/
}
return 0;
}
short CmpSeabaseDDL::getNAColumnFromColDef
(ElemDDLColDef * colNode,
NAColumn* &naCol)
{
NAString colFamily;
NAString colName;
Lng32 datatype, length, precision, scale, dt_start, dt_end;
Lng32 nullable, upshifted;
ComColumnClass colClass;
ComColumnDefaultClass defaultClass;
NAString charset, defVal;
NAString heading;
ULng32 hbaseColFlags;
Int64 colFlags;
LobsStorage lobStorage;
NABoolean alignedFormat = FALSE;
if (getColInfo(colNode,
FALSE,
colFamily,
colName,
alignedFormat,
datatype, length, precision, scale, dt_start, dt_end,
upshifted, nullable,
charset, colClass, defaultClass, defVal, heading, lobStorage,
hbaseColFlags, colFlags))
{
*CmpCommon::diags() << DgSqlCode(-2004);
return -1;
}
NAType * naType = colNode->getColumnDataType();
if (! naType)
{
*CmpCommon::diags() << DgSqlCode(-2004);
return -1;
}
char * defV = NULL;
if ((defaultClass != COM_NO_DEFAULT) &&
(! defVal.isNull()))
{
char * data = (char*) defVal.data();
Lng32 len = defVal.length();
defV = new(STMTHEAP) char[len + 2];
str_cpy_all((char*)defV, data, len);
char * c = (char*)defV;
c[len] = 0;
c[len+1] = 0;
}
naCol = new(STMTHEAP) NAColumn(colNode->getColumnName().data(),
-1, // position
naType, NULL, NULL,
USER_COLUMN, //colClass,
defaultClass,
defV);
naCol->setHbaseColFlags(hbaseColFlags);
return 0;
}
short CmpSeabaseDDL::getColInfo(ElemDDLColDef * colNode,
NABoolean isMetadataHistOrReposColumn,
NAString &colFamily,
NAString &colName,
NABoolean alignedFormat,
Lng32 &datatype,
Lng32 &length,
Lng32 &precision,
Lng32 &scale,
Lng32 &dtStart,
Lng32 &dtEnd,
Lng32 &upshifted,
Lng32 &nullable,
NAString &charset,
ComColumnClass &colClass,
ComColumnDefaultClass &defaultClass,
NAString &defVal,
NAString &heading,
LobsStorage &lobStorage,
ULng32 &hbaseColFlags,
Int64 &colFlags)
{
short rc = 0;
hbaseColFlags = 0;
colFlags = 0;
colFamily = colNode->getColumnFamily();
colName = colNode->getColumnName();
if (colNode->isHeadingSpecified())
heading = colNode->getHeading();
Lng32 serializedOption = -1; // not specified
if (colNode->isSerializedSpecified())
{
serializedOption = (colNode->isSeabaseSerialized() ? 1 : 0);
}
NAType * naType = colNode->getColumnDataType();
if (! naType)
{
*CmpCommon::diags() << DgSqlCode(-2004);
return -1;
}
CharInfo::Collation collationSequence = CharInfo::DefaultCollation;
rc = getTypeInfo(naType, alignedFormat, serializedOption,
datatype, length, precision, scale, dtStart, dtEnd, upshifted, nullable,
charset, collationSequence, hbaseColFlags);
if (colName == "SYSKEY")
{
resetFlags(hbaseColFlags, NAColumn::SEABASE_SERIALIZED);
}
if (collationSequence != CharInfo::DefaultCollation)
{
// collation not supported
*CmpCommon::diags() << DgSqlCode(-4069)
<< DgColumnName(ToAnsiIdentifier(colName))
<< DgString0(CharInfo::getCollationName(collationSequence));
rc = -1;
}
if (rc)
{
return rc;
}
if ((!isMetadataHistOrReposColumn) &&
(naType->getTypeQualifier() == NA_CHARACTER_TYPE) &&
(naType->getNominalSize() > CmpCommon::getDefaultNumeric(TRAF_MAX_CHARACTER_COL_LENGTH)))
{
*CmpCommon::diags() << DgSqlCode(-4247)
<< DgInt0(naType->getNominalSize())
<< DgInt1(CmpCommon::getDefaultNumeric(TRAF_MAX_CHARACTER_COL_LENGTH))
<< DgColumnName(ToAnsiIdentifier(colName));
return -1;
}
lobStorage = Lob_Invalid_Storage;
if (naType->getTypeQualifier() == NA_LOB_TYPE)
lobStorage = colNode->getLobStorage();
colClass = colNode->getColumnClass();
NABoolean negateIt = FALSE;
if (colNode->getDefaultClauseStatus() == ElemDDLColDef::NO_DEFAULT_CLAUSE_SPEC)
defaultClass = COM_NO_DEFAULT;
else if (colNode->getDefaultClauseStatus() == ElemDDLColDef::DEFAULT_CLAUSE_NOT_SPEC)
{
if (nullable)
{
defaultClass = COM_NULL_DEFAULT;
}
else
defaultClass = COM_NO_DEFAULT;
}
else if (colNode->getDefaultClauseStatus() == ElemDDLColDef::DEFAULT_CLAUSE_SPEC)
{
ItemExpr * ie = colNode->getDefaultValueExpr();
if (colNode->getSGOptions())
{
if (colNode->getSGOptions()->isGeneratedAlways())
defaultClass = COM_IDENTITY_GENERATED_ALWAYS;
else
defaultClass = COM_IDENTITY_GENERATED_BY_DEFAULT;
}
else if (ie == NULL)
if (colNode->getComputedDefaultExpr().isNull())
defaultClass = COM_NO_DEFAULT;
else
{
defaultClass = COM_ALWAYS_COMPUTE_COMPUTED_COLUMN_DEFAULT;
defVal = colNode->getComputedDefaultExpr();
if (colNode->isDivisionColumn())
colFlags |= SEABASE_COLUMN_IS_DIVISION;
else if (colName == ElemDDLSaltOptionsClause::getSaltSysColName())
colFlags |= SEABASE_COLUMN_IS_SALT;
else
CMPASSERT(0);
}
else if (!colNode->getDefaultExprString().isNull())
{
defaultClass = COM_FUNCTION_DEFINED_DEFAULT;
defVal = colNode->getDefaultExprString();
}
else if (ie->getOperatorType() == ITM_CURRENT_TIMESTAMP)
{
defaultClass = COM_CURRENT_DEFAULT;
}
else if ((ie->getOperatorType() == ITM_CAST) &&
(ie->getChild(0)->castToItemExpr()->getOperatorType() == ITM_CURRENT_TIMESTAMP))
{
defaultClass = COM_CURRENT_DEFAULT;
}
else if (ie->getOperatorType() == ITM_UNIX_TIMESTAMP)
{
defaultClass = COM_CURRENT_UT_DEFAULT;
}
else if ((ie->getOperatorType() == ITM_CAST) &&
(ie->getChild(0)->castToItemExpr()->getOperatorType() == ITM_UNIX_TIMESTAMP))
{
defaultClass = COM_CURRENT_UT_DEFAULT;
}
else if (ie->getOperatorType() == ITM_UNIQUE_ID)
{
defaultClass = COM_UUID_DEFAULT;
}
else if ((ie->getOperatorType() == ITM_CAST) &&
(ie->getChild(0)->castToItemExpr()->getOperatorType() == ITM_UNIQUE_ID))
{
defaultClass = COM_UUID_DEFAULT;
}
else if ((ie->getOperatorType() == ITM_USER) ||
(ie->getOperatorType() == ITM_CURRENT_USER) ||
(ie->getOperatorType() == ITM_SESSION_USER))
{
defaultClass = COM_USER_FUNCTION_DEFAULT;
}
else if (ie->castToConstValue(negateIt) != NULL)
{
if (ie->castToConstValue(negateIt)->isNull())
{
defaultClass = COM_NULL_DEFAULT;
}
else
{
defaultClass = COM_USER_DEFINED_DEFAULT;
const ComString name = colNode->getColumnName();
const NAType * genericType = colNode->getColumnDataType();
rc = checkDefaultValue(ToAnsiIdentifier(name),
genericType, colNode);
if (rc)
return -1;
ie = colNode->getDefaultValueExpr();
ConstValue * cv = ie->castToConstValue(negateIt);
if (cv->getType()->getTypeQualifier() == NA_CHARACTER_TYPE)
{
if (((CharType*)(cv->getType()))->getCharSet() == CharInfo::UNICODE)
{
NAWString naws(CharInfo::UNICODE, (char*)cv->getConstValue(), cv->getStorageSize());
NAString * nas = unicodeToChar(naws.data(), naws.length(),
CharInfo::UTF8, STMTHEAP);
if (nas)
{
defVal = "_UCS2'";
defVal += *nas;
defVal += "'";
}
else
{
defVal = cv->getConstStr();
}
} // ucs2
else if (((CharType*)(cv->getType()))->getCharSet() == CharInfo::ISO88591)
{
char * cvalue = (char*)cv->getConstValue();
Lng32 cvlen = cv->getStorageSize();
if (cv->getType()->isVaryingLen())
{
cvlen = *(short*)cvalue;
cvalue = cvalue + sizeof(short);
}
// convert iso to utf8
NAString * nas = charToChar(CharInfo::UTF8,
cvalue, cvlen,
CharInfo::ISO88591, STMTHEAP);
if (nas)
{
defVal = "_ISO88591'";
defVal += *nas;
defVal += "'";
}
else
{
defVal = cv->getConstStr();
}
}
else
defVal = cv->getConstStr();
}
else
defVal = cv->getConstStr();
}
}
else
defaultClass = COM_NO_DEFAULT;
}
return 0;
}
short CmpSeabaseDDL::createRowId(NAString &key,
NAString &part1, Lng32 part1MaxLen,
NAString &part2, Lng32 part2MaxLen,
NAString &part3, Lng32 part3MaxLen,
NAString &part4, Lng32 part4MaxLen)
{
if (part1.isNull())
return 0;
part1MaxLen = part2MaxLen = part3MaxLen = part4MaxLen = 20;
NAString keyValPadded;
keyValPadded = part1;
if (part1.length() < part1MaxLen)
keyValPadded.append(' ', (part1MaxLen - part1.length()));
if (NOT part2.isNull())
{
keyValPadded += part2;
if (part2.length() < part2MaxLen)
keyValPadded.append(' ', (part2MaxLen - part2.length()));
}
if (NOT part3.isNull())
{
keyValPadded += part3;
if (part3.length() < part3MaxLen)
keyValPadded.append(' ', (part3MaxLen - part3.length()));
}
if (NOT part4.isNull())
{
keyValPadded += part4;
if (part4.length() < part4MaxLen)
keyValPadded.append(' ', (part4MaxLen - part4.length()));
}
// encode and convertToHex
key = keyValPadded;
return 0;
}
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
static short isValidHbaseName(const char * str)
{
// A valid hbase name must contain 'word characters': [a-zA-Z_0-9-.]
for (Lng32 i = 0; i < strlen(str); i++)
{
char c = str[i];
if (NOT (((c >= '0') && (c <= '9')) ||
((c >= 'a') && (c <= 'z')) ||
((c >= 'A') && (c <= 'Z')) ||
((c == '_') || (c == '-') || (c == '.'))))
return 0; // not a valid name
}
return -1; // valid name
}
NAString CmpSeabaseDDL::genHBaseObjName(const NAString &catName,
const NAString &schName,
const NAString &objName)
{
NAString extNameForHbase = "" ;
extNameForHbase += catName + "." + schName + "." + objName;
return extNameForHbase;
}
// RETURN: 1, exists. 0, does not exists. -1, error.
short CmpSeabaseDDL::existsInSeabaseMDTable(
ExeCliInterface *cliInterface,
const char * catName,
const char * schName,
const char * objName,
const ComObjectType objectType,
NABoolean checkForValidDef,
NABoolean checkForValidHbaseName,
NABoolean returnInvalidStateError)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
char cfvd[100];
strcpy(cfvd, " ");
if (checkForValidDef)
strcpy(cfvd, " and valid_def = 'Y' ");
// Name must be a valid hbase name
if (checkForValidHbaseName)
{
if ((! isValidHbaseName(catName)) ||
(! isValidHbaseName(schName)) ||
(! isValidHbaseName(objName)))
{
*CmpCommon::diags() << DgSqlCode(-1422);
return -1;
}
// HBase name must not be too long (see jira HDFS-6055)
// Generated HBase name = catName.schName.objName
Int32 nameLen = (strlen(catName) + 1 +
strlen(schName) + 1 +
strlen(objName));
if (nameLen > MAX_HBASE_NAME_LEN)
{
*CmpCommon::diags() << DgSqlCode(-CAT_HBASE_NAME_TOO_LONG)
<< DgInt0(nameLen)
<< DgInt1(MAX_HBASE_NAME_LEN);
return -1;
}
}
NAString quotedSchName;
ToQuotedString(quotedSchName, NAString(schName), FALSE);
NAString quotedObjName;
ToQuotedString(quotedObjName, NAString(objName), FALSE);
char objectTypeLit[3] = {0};
strncpy(objectTypeLit,PrivMgr::ObjectEnumToLit(objectType),2);
char buf[4000];
if (objectType == COM_UNKNOWN_OBJECT)
str_sprintf(buf, "select count(*) from %s.\"%s\".%s where catalog_name = '%s' and schema_name = '%s' and object_name = '%s' %s ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
catName, quotedSchName.data(), quotedObjName.data(),
cfvd);
else
str_sprintf(buf, "select count(*) from %s.\"%s\".%s where catalog_name = '%s' and schema_name = '%s' and object_name = '%s' and object_type = '%s' %s ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
catName, quotedSchName.data(), quotedObjName.data(), objectTypeLit,
cfvd);
Lng32 len = 0;
Int64 rowCount = 0;
cliRC = cliInterface->executeImmediate(buf, (char*)&rowCount, &len, FALSE);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
if (rowCount > 0)
return 1; // exists
else if (returnInvalidStateError)
{
NABoolean validDef = FALSE;
cliRC = getObjectValidDef(cliInterface,
catName, schName, objName,
objectType,
validDef);
if (cliRC < 0)
return -1;
if ((cliRC == 1) && (NOT validDef)) // found and not valid
{
// invalid object, return error.
NAString extTableName = NAString(catName) + "." + NAString(schName) + "."
+ NAString(objName);
CmpCommon::diags()->clear();
*CmpCommon::diags() << DgSqlCode(-4254)
<< DgString0(extTableName);
return -1;
}
return 0; // does not exist
}
else
return 0; // does not exist
}
Int64 CmpSeabaseDDL::getObjectTypeandOwner(
ExeCliInterface *cliInterface,
const char * catName,
const char * schName,
const char * objName,
ComObjectType & objectType,
Int32 & objectOwner)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
NAString quotedSchName;
ToQuotedString(quotedSchName, NAString(schName), FALSE);
NAString quotedObjName;
ToQuotedString(quotedObjName, NAString(objName), FALSE);
char buf[4000];
str_sprintf(buf, "select object_type, object_owner, object_UID from %s.\"%s\".%s "
"where catalog_name = '%s' and schema_name = '%s' and object_name = '%s' ",
getSystemCatalogStatic().data(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
catName, quotedSchName.data(), quotedObjName.data());
cliRC = cliInterface->fetchRowsPrologue(buf, TRUE/*no exec*/);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
cliRC = cliInterface->clearExecFetchClose(NULL, 0);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
if (cliRC == 100) // did not find the row
{
return -1;
}
char * ptr = NULL;
Lng32 len = 0;
char objectTypeLit[3] = {0};
cliInterface->getPtrAndLen(1, ptr, len);
str_cpy_and_null(objectTypeLit, ptr, len, '\0', ' ', TRUE);
objectType = PrivMgr::ObjectLitToEnum(objectTypeLit);
cliInterface->getPtrAndLen(2, ptr, len);
objectOwner = *(Int32*)ptr;
cliInterface->getPtrAndLen(3, ptr, len);
Int64 objUID = *(Int64*)ptr;
cliInterface->fetchRowsEpilogue(NULL, TRUE);
return objUID;
}
short CmpSeabaseDDL::getObjectName(
ExeCliInterface *cliInterface,
Int64 objUID,
NAString &catName,
NAString &schName,
NAString &objName,
char * outObjType,
NABoolean lookInObjects,
NABoolean lookInObjectsIdx)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
char buf[4000];
ExeCliInterface cqdCliInterface(STMTHEAP);
if (lookInObjectsIdx)
str_sprintf(buf, "select catalog_name, schema_name, object_name, object_type from table(index_table %s.\"%s\".%s) where \"OBJECT_UID@\" = %ld ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS_UNIQ_IDX,
objUID);
else
{
str_sprintf(buf, "select catalog_name, schema_name, object_name, object_type from %s.\"%s\".%s where object_uid = %ld ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
objUID);
}
if (lookInObjects)
{
char shapeBuf[1000];
str_sprintf(shapeBuf, "control query shape scan (path '%s.\"%s\".%s')",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS) ;
if (cqdCliInterface.setCQS(shapeBuf))
{
cqdCliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
}
cliRC = cliInterface->fetchRowsPrologue(buf, TRUE/*no exec*/);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
}
if (lookInObjects)
{
cqdCliInterface.resetCQS();
}
if (cliRC < 0)
{
return -1;
}
cliRC = cliInterface->clearExecFetchClose(NULL, 0);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
if (cliRC == 100) // did not find the row
{
*CmpCommon::diags() << DgSqlCode(-1389) << DgString0(objName);
return -1389;
}
char * ptr = NULL;
Lng32 len = 0;
cliInterface->getPtrAndLen(1, ptr, len);
catName = "";
catName.append(ptr, len);
cliInterface->getPtrAndLen(2, ptr, len);
schName = "";
schName.append(ptr, len);
cliInterface->getPtrAndLen(3, ptr, len);
objName = "";
objName.append(ptr, len);
if (outObjType)
{
cliInterface->getPtrAndLen(4, ptr, len);
str_cpy_and_null(outObjType, ptr, len, '\0', ' ', TRUE);
}
cliInterface->fetchRowsEpilogue(NULL, TRUE);
return 0;
}
Int64 CmpSeabaseDDL::getObjectUID(
ExeCliInterface *cliInterface,
const char * catName,
const char * schName,
const char * objName,
const char * inObjType,
const char * inObjTypeStr,
char * outObjType,
NABoolean lookInObjectsIdx,
NABoolean reportErrorNow)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
NAString quotedSchName;
ToQuotedString(quotedSchName, NAString(schName), FALSE);
NAString quotedObjName;
ToQuotedString(quotedObjName, NAString(objName), FALSE);
char buf[4000];
if (inObjType)
{
if (lookInObjectsIdx)
str_sprintf(buf, "select \"OBJECT_UID@\", object_type from table(index_table %s.\"%s\".%s) where catalog_name = '%s' and schema_name = '%s' and object_name = '%s' and object_type = '%s' ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS_UNIQ_IDX,
catName, quotedSchName.data(), quotedObjName.data(),
inObjType);
else
str_sprintf(buf, "select object_uid, object_type from %s.\"%s\".%s where catalog_name = '%s' and schema_name = '%s' and object_name = '%s' and object_type = '%s' ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
catName, quotedSchName.data(), quotedObjName.data(),
inObjType);
}
else if (inObjTypeStr)
str_sprintf(buf, "select object_uid, object_type from %s.\"%s\".%s where catalog_name = '%s' and schema_name = '%s' and object_name = '%s' and ( %s ) ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
catName, quotedSchName.data(), quotedObjName.data(),
inObjTypeStr);
else // inObjType == NULL
{
if (lookInObjectsIdx)
str_sprintf(buf, "select \"OBJECT_UID@\", object_type from table(index_table %s.\"%s\".%s) where catalog_name = '%s' and schema_name = '%s' and object_name = '%s' ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS_UNIQ_IDX,
catName, quotedSchName.data(), quotedObjName.data());
else
str_sprintf(buf, "select object_uid, object_type from %s.\"%s\".%s where catalog_name = '%s' and schema_name = '%s' and object_name = '%s' ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
catName, quotedSchName.data(), quotedObjName.data());
}
cliRC = cliInterface->fetchRowsPrologue(buf, TRUE/*no exec*/);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
cliRC = cliInterface->clearExecFetchClose(NULL, 0);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
if (cliRC == 100) // did not find the row
{
if (reportErrorNow)
*CmpCommon::diags() << DgSqlCode(-1389) << DgString0(objName);
return -1;
}
char * ptr = NULL;
Lng32 len = 0;
cliInterface->getPtrAndLen(1, ptr, len);
Int64 objUID = *(Int64*)ptr;
if (outObjType)
{
cliInterface->getPtrAndLen(2, ptr, len);
str_cpy_and_null(outObjType, ptr, len, '\0', ' ', TRUE);
}
cliInterface->fetchRowsEpilogue(NULL, TRUE);
return objUID;
}
Int64 CmpSeabaseDDL::getObjectInfo(
ExeCliInterface *cliInterface,
const char * catName,
const char * schName,
const char * objName,
const ComObjectType objectType,
Int32 & objectOwner,
Int32 & schemaOwner,
Int64 & objectFlags,
bool reportErrorNow,
NABoolean checkForValidDef,
Int64 *createTime)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
NAString quotedSchName;
ToQuotedString(quotedSchName, NAString(schName), FALSE);
NAString quotedObjName;
ToQuotedString(quotedObjName, NAString(objName), FALSE);
char objectTypeLit[3] = {0};
strncpy(objectTypeLit,PrivMgr::ObjectEnumToLit(objectType),2);
char cfvd[100];
strcpy(cfvd, " ");
if (checkForValidDef)
strcpy(cfvd, " and valid_def = 'Y' ");
char buf[4000];
str_sprintf(buf, "select object_uid, object_owner, schema_owner, flags, create_time from %s.\"%s\".%s where catalog_name = '%s' and schema_name = '%s' and object_name = '%s' and object_type = '%s' %s ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
catName, quotedSchName.data(), quotedObjName.data(),
objectTypeLit, cfvd);
cliRC = cliInterface->fetchRowsPrologue(buf, TRUE/*no exec*/);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
cliRC = cliInterface->clearExecFetchClose(NULL, 0);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
if (cliRC == 100) // did not find the row
{
if ( reportErrorNow )
*CmpCommon::diags() << DgSqlCode(-1389) << DgString0(objName);
return -1;
}
char * ptr = NULL;
Lng32 len = 0;
// return object_uid
cliInterface->getPtrAndLen(1, ptr, len);
Int64 objUID = *(Int64*)ptr;
// return object_owner
cliInterface->getPtrAndLen(2, ptr, len);
objectOwner = *(Int32*)ptr;
// return schema_owner
cliInterface->getPtrAndLen(3, ptr, len);
schemaOwner = *(Int32*)ptr;
// return flags
cliInterface->getPtrAndLen(4, ptr, len);
objectFlags = *(Int64*)ptr;
// return create_time
cliInterface->getPtrAndLen(5, ptr, len);
if (createTime)
*createTime = *(Int64*)ptr;
cliInterface->fetchRowsEpilogue(NULL, TRUE);
return objUID;
}
short CmpSeabaseDDL::getObjectOwner(ExeCliInterface *cliInterface,
const char * catName,
const char * schName,
const char * objName,
const char * objType,
Int32 * objectOwner)
{
Int32 retcode = 0;
Int32 cliRC = 0;
NAString stmt;
stmt = "select object_owner from ";
stmt += getSystemCatalog();
stmt += ".\"";
stmt += SEABASE_MD_SCHEMA;
stmt += "\".";
stmt += SEABASE_OBJECTS;
stmt += " where catalog_name = '";
stmt += catName;
stmt += "' and schema_name = '";
stmt += schName;
stmt += "' and object_name = '";
stmt += objName ;
if (objType)
{
stmt += "' and object_type = '";
stmt += objType;
}
stmt += "' for read uncommitted access";
cliRC = cliInterface->fetchRowsPrologue(stmt.data(), TRUE/*no exec*/);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
cliRC = cliInterface->clearExecFetchClose(NULL, 0);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
if (cliRC == 100) // did not find the row
{
NAString strObjName (catName);
strObjName += '.';
strObjName += schName;
strObjName += '.';
strObjName += objName;
*CmpCommon::diags() << DgSqlCode(-1389)
<< DgString0(strObjName.data());
return -1;
}
char * ptr = NULL;
Lng32 len = 0;
cliInterface->getPtrAndLen(1, ptr, len);
*objectOwner = *(Int32*)ptr;
cliInterface->fetchRowsEpilogue(NULL, TRUE);
return 0;
}
short CmpSeabaseDDL::getObjectValidDef(ExeCliInterface *cliInterface,
const char * catName,
const char * schName,
const char * objName,
const ComObjectType objectType,
NABoolean &validDef)
{
Int32 retcode = 0;
Int32 cliRC = 0;
char buf[4000];
NAString quotedSchName;
ToQuotedString(quotedSchName, NAString(schName), FALSE);
NAString quotedObjName;
ToQuotedString(quotedObjName, NAString(objName), FALSE);
char objectTypeLit[3] = {0};
strncpy(objectTypeLit,PrivMgr::ObjectEnumToLit(objectType),2);
if (objectType == COM_UNKNOWN_OBJECT)
str_sprintf(buf, "select valid_def from %s.\"%s\".%s where catalog_name = '%s' and schema_name = '%s' and object_name = '%s' ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
catName, quotedSchName.data(), quotedObjName.data());
else
str_sprintf(buf, "select valid_def from %s.\"%s\".%s where catalog_name = '%s' and schema_name = '%s' and object_name = '%s' and object_type = '%s' ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
catName, quotedSchName.data(), quotedObjName.data(),
objectTypeLit);
cliRC = cliInterface->fetchRowsPrologue(buf, TRUE/*no exec*/);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
cliRC = cliInterface->clearExecFetchClose(NULL, 0);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
if (cliRC == 100) // did not find the row
{
return 0;
}
char * ptr = NULL;
Lng32 len = 0;
cliInterface->getPtrAndLen(1, ptr, len);
validDef = ((memcmp(ptr, COM_YES_LIT, 1) == 0) ? TRUE : FALSE);
cliInterface->fetchRowsEpilogue(NULL, TRUE);
return 1;
}
Int64 CmpSeabaseDDL::getConstraintOnIndex(
ExeCliInterface *cliInterface,
Int64 btUID,
Int64 indexUID,
const char * constrType,
NAString &catName,
NAString &schName,
NAString &objName)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
char buf[4000];
str_sprintf(buf, "select C.constraint_uid, O.catalog_name, O.schema_name, O.object_name from %s.\"%s\".%s C, %s.\"%s\".%s O where C.table_uid = %ld and C.index_uid = %ld and C.constraint_type = '%s' and C.constraint_uid = O.object_uid",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_TABLE_CONSTRAINTS,
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
btUID, indexUID, constrType);
Queue * constrsQueue = NULL;
cliRC = cliInterface->fetchAllRows(constrsQueue, buf, 0, FALSE, FALSE, TRUE);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return cliRC;
}
if (constrsQueue->numEntries() == 0)
return 0;
constrsQueue->position();
OutputInfo * vi = (OutputInfo*)constrsQueue->getNext();
Int64 constrUID = *(Int64*)vi->get(0);
catName = vi->get(1);
schName = vi->get(2);
objName = vi->get(3);
return constrUID;
}
short CmpSeabaseDDL::getUsingObject(ExeCliInterface *cliInterface,
Int64 objUID,
NAString &usingObjName)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
char buf[4000];
str_sprintf(buf, "select trim(catalog_name) || '.' || trim(schema_name) || '.' || trim(object_name) from %s.\"%s\".%s T, %s.\"%s\".%s VU where VU.used_object_uid = %ld and T.object_uid = VU.using_view_uid and T.valid_def = 'Y' ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_VIEWS_USAGE,
objUID);
//Turn off CQDs MERGE_JOINS and HASH_JOINS to avoid a full table scan of
//SEABASE_OBJECTS table. Full table scan of SEABASE_OBJECTS table causes
//simultaneous DDL operations to run into conflict.
//Make sure to restore the CQDs after this query including error paths.
cliInterface->holdAndSetCQD("MERGE_JOINS", "OFF");
cliInterface->holdAndSetCQD("HASH_JOINS", "OFF");
Queue * usingViewsQueue = NULL;
cliRC = cliInterface->fetchAllRows(usingViewsQueue, buf, 0, FALSE, FALSE, TRUE);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
}
//restore CQDs.
cliInterface->restoreCQD("MERGE_JOINS");
cliInterface->restoreCQD("HASH_JOINS");
if (cliRC < 0)
return cliRC;
if (usingViewsQueue->numEntries() == 0)
return 100;
usingViewsQueue->position();
OutputInfo * vi = (OutputInfo*)usingViewsQueue->getNext();
char * viewName = vi->get(0);
usingObjName = viewName;
return 0;
}
short CmpSeabaseDDL::getBaseTable(ExeCliInterface *cliInterface,
const NAString &indexCatName,
const NAString &indexSchName,
const NAString &indexObjName,
NAString &btCatName,
NAString &btSchName,
NAString &btObjName,
Int64 &btUID,
Int32 &btObjOwner,
Int32 &btSchemaOwner)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
char buf[4000];
str_sprintf(buf, "select trim(O.catalog_name), trim(O.schema_name),"
" trim(O.object_name), O.object_uid, O.object_owner, O.schema_owner"
" from %s.\"%s\".%s O "
" where O.object_uid = (select I.base_table_uid from %s.\"%s\".%s I"
" where I.index_uid = (select O2.object_uid from %s.\"%s\".%s O2"
" where O2.catalog_name = '%s' and O2.schema_name = '%s' and"
" O2.object_name = '%s' and O2.object_type = 'IX')) ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_INDEXES,
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
(char*)indexCatName.data(), (char*)indexSchName.data(),
(char*)indexObjName.data());
Queue * usingTableQueue = NULL;
cliRC = cliInterface->fetchAllRows(usingTableQueue, buf, 0, FALSE, FALSE, TRUE);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return cliRC;
}
if (usingTableQueue->numEntries() != 1)
{
// error
*CmpCommon::diags() << DgSqlCode(-4082);
return -1;
}
usingTableQueue->position();
OutputInfo * vi = (OutputInfo*)usingTableQueue->getNext();
btCatName = vi->get(0);
btSchName = vi->get(1);
btObjName = vi->get(2);
btUID = *(Int64*)vi->get(3);
btObjOwner = *(Int32*)vi->get(4);
btSchemaOwner = *(Int32*)vi->get(5);
return 0;
}
short CmpSeabaseDDL::getUsingViews(ExeCliInterface *cliInterface,
Int64 objectUID,
Queue * &usingViewsQueue)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
char buf[4000];
str_sprintf(buf, "select '\"' || trim(catalog_name) || '\"' || '.' || '\"' || trim(schema_name) || '\"' || '.' || '\"' || trim(object_name) || '\"' "
"from %s.\"%s\".%s T, %s.\"%s\".%s VU "
"where T.object_uid = VU.using_view_uid and "
"T.valid_def = 'Y' and VU.used_object_uid = %ld ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_VIEWS_USAGE,
objectUID);
cliRC = cliInterface->fetchAllRows(usingViewsQueue, buf, 0, FALSE, FALSE, TRUE);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return cliRC;
}
return 0;
}
// finds all views that directly or indirectly(thru another view) contains
// the given object.
// Returns them in ascending order of their create time.
short CmpSeabaseDDL::getAllUsingViews(ExeCliInterface *cliInterface,
NAString &catName,
NAString &schName,
NAString &objName,
Queue * &usingViewsQueue)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
char buf[4000];
str_sprintf(buf, "select '\"' || trim(o.catalog_name) || '\"' || '.' || '\"' || trim(o.schema_name) || '\"' || '.' || '\"' || trim(o.object_name) || '\"' "
", o.create_time from %s.\"%s\".%s O, "
" (get all views on table \"%s\".\"%s\".\"%s\") x(a) "
" where trim(O.catalog_name) || '.' || trim(O.schema_name) || '.' || trim(O.object_name) = x.a "
" order by 2",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
catName.data(), schName.data(), objName.data());
cliRC = cliInterface->fetchAllRows(usingViewsQueue, buf, 0, FALSE, FALSE, TRUE);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return cliRC;
}
return 0;
}
/*
Get the salt column text for a given table or index.
Returns 0 for object does not have salt column
Returns 1 for object has salt column and it is being returned in saltText
Returns -1 for error, which for now is ignored as we have an alternate code path.
*/
short CmpSeabaseDDL::getSaltText(
ExeCliInterface *cliInterface,
const char * catName,
const char * schName,
const char * objName,
const char * inObjType,
NAString& saltText)
{
Lng32 cliRC = 0;
NAString quotedSchName;
ToQuotedString(quotedSchName, NAString(schName), FALSE);
NAString quotedObjName;
ToQuotedString(quotedObjName, NAString(objName), FALSE);
Int64 objUID;
Lng32 colNum;
NAString defaultValue;
char buf[4000];
char *data;
Lng32 len;
// determine object UID and column number of the _SALT_ column in the Trafodion table
// TBD: Once flags has been updated for older objects, replace predicates on column_name
// and default_class with a check for the SEABASE_COLUMN_IS_SALT bit in columns.flags
str_sprintf(buf, "select object_uid, column_number, cast(default_value as varchar(512) character set iso88591) from %s.\"%s\".%s o, %s.\"%s\".%s c where o.catalog_name = '%s' and o.schema_name = '%s' and o.object_name = '%s' and o.object_type = '%s' and o.object_uid = c.object_uid and c.column_name = '%s' and c.default_class = %d",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_COLUMNS,
catName, quotedSchName.data(), quotedObjName.data(),
inObjType,
ElemDDLSaltOptionsClause::getSaltSysColName(),
(int) COM_ALWAYS_COMPUTE_COMPUTED_COLUMN_DEFAULT);
Queue * saltQueue = NULL;
cliRC = cliInterface->fetchAllRows(saltQueue, buf, 0, FALSE, FALSE, TRUE);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
// did not find row
if (saltQueue->numEntries() == 0)
return 0;
saltQueue->position();
OutputInfo * vi = (OutputInfo*)saltQueue->getNext();
objUID = *(Int64 *)vi->get(0);
colNum = *(Lng32 *)vi->get(1);
defaultValue = vi->get(2);
// this should be the normal case, salt text is stored in the TEXT table,
// not the default value
cliRC = getTextFromMD(cliInterface,
objUID,
COM_COMPUTED_COL_TEXT,
colNum,
saltText);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
if (saltText.isNull())
saltText = defaultValue;
CMPASSERT(!saltText.isNull());
return 1;
}
short CmpSeabaseDDL::getAllIndexes(ExeCliInterface *cliInterface,
Int64 objUID,
NABoolean includeInvalidDefs,
Queue * &indexInfoQueue)
{
Lng32 cliRC = 0;
char query[4000];
str_sprintf(query, "select O.catalog_name, O.schema_name, O.object_name, O.object_uid from %s.\"%s\".%s I, %s.\"%s\".%s O , %s.\"%s\".%s T where I.base_table_uid = %ld and I.index_uid = O.object_uid %s and I.index_uid = T.table_uid and I.keytag != 0 for read committed access ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_INDEXES,
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_TABLES,
objUID,
(includeInvalidDefs ? " " : " and O.valid_def = 'Y' "));
cliRC = cliInterface->fetchAllRows(indexInfoQueue, query, 0, FALSE, FALSE, TRUE);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
processReturn();
return -1;
}
return 0;
}
// Convert from hbase options string format to list of structs.
// String format:
// HBASE_OPTIONS=>0002COMPRESSION='GZ'|BLOCKCACHE='10'|
//
// If beginPos and/or endPos parameters are not null, then the
// beginning and/or ending position of the HBASE_OPTIONS string
// is returned.
//
// Note that the input string may have things other than HBASE_OPTIONS
// in it (such as ROW_FORMAT=>ALIGNED, for example). Those other things
// are ignored by this method.
short CmpSeabaseDDL::genHbaseCreateOptions(
const char * hbaseCreateOptionsStr,
NAList<HbaseCreateOption*>* &hbaseCreateOptions,
NAMemory * heap,
size_t * beginPos,
size_t * endPos)
{
hbaseCreateOptions = NULL;
if (beginPos)
*beginPos = 0;
if (endPos)
*endPos = 0;
if (hbaseCreateOptionsStr == NULL)
return 0;
const char * hboStr = strstr(hbaseCreateOptionsStr, "HBASE_OPTIONS=>");
if (! hboStr)
return 0;
char numHBOstr[5];
const char * startNumHBO = hboStr + strlen("HBASE_OPTIONS=>");
memcpy(numHBOstr, startNumHBO, 4);
numHBOstr[4] = 0;
Lng32 numHBO = str_atoi(numHBOstr, 4);
if (numHBO == 0)
return 0;
hbaseCreateOptions = new(heap) NAList<HbaseCreateOption*>(heap);
const char * optionStart = startNumHBO + 4;
for (Lng32 i = 0; i < numHBO; i++)
{
// look for pattern =' to find the end of current option.
const char * optionEnd = strstr(optionStart, "='");
if (! optionEnd) // this is an error
{
for (CollIndex k = 0; k < hbaseCreateOptions->entries(); k++)
{
HbaseCreateOption * hbo = (*hbaseCreateOptions)[k];
delete hbo;
}
delete hbaseCreateOptions;
return -1;
}
const char * valStart = optionEnd + strlen("='");
const char * valEnd = strstr(valStart, "'|");
if (! valEnd) // this is an error
{
for (CollIndex k = 0; k < hbaseCreateOptions->entries(); k++)
{
HbaseCreateOption * hbo = (*hbaseCreateOptions)[k];
delete hbo;
}
delete hbaseCreateOptions;
return -1;
}
NAText key(optionStart, (optionEnd-optionStart));
NAText val(valStart, (valEnd - valStart));
HbaseCreateOption * hco = new(heap) HbaseCreateOption(key, val);
hbaseCreateOptions->insert(hco);
optionStart = valEnd + strlen("'|");
}
if (beginPos)
*beginPos = hboStr - hbaseCreateOptionsStr;
if (endPos)
// + 1 to allow for a space after the last |
// (this trailing space is always present)
*endPos = optionStart - hbaseCreateOptionsStr + 1;
return 0;
}
// The function below is an inverse of CmpSeabaseDDL::genHbaseCreateOptions.
// It takes an NAList of HbaseCreateOption objects and generates the equivalent
// metadata text. Returns 0 if successful (and it is always successful).
// Note that quotes inside the string are not doubled here.
short CmpSeabaseDDL::genHbaseOptionsMetadataString(
const NAList<HbaseCreateOption*> & hbaseCreateOptions,
NAString & hbaseOptionsMetadataString /* out */)
{
CollIndex numberOfOptions = hbaseCreateOptions.entries();
if (numberOfOptions == 0)
{
hbaseOptionsMetadataString = ""; // no HBase options so return empty string
}
else
{
hbaseOptionsMetadataString = "HBASE_OPTIONS=>";
// put in a 4-digit text NNNN indicating how many options there are
if (numberOfOptions > HBASE_OPTIONS_MAX_LENGTH)
// shouldn't happen; but truncate if it does for safety (note also
// that HBASE_OPTIONS_MAX_LENGTH happens to be 4 digits)
numberOfOptions = HBASE_OPTIONS_MAX_LENGTH;
char inTextForm[5]; // room for NNNN and null terminator
sprintf(inTextForm,"%04d",numberOfOptions);
hbaseOptionsMetadataString += inTextForm;
// now loop through list, appending KEY='VALUE'| for each option
for (CollIndex i = 0; i < numberOfOptions; i++)
{
HbaseCreateOption * hbaseOption = hbaseCreateOptions[i];
NAText &key = hbaseOption->key();
NAText &val = hbaseOption->val();
hbaseOptionsMetadataString += key.c_str();
hbaseOptionsMetadataString += "='";
hbaseOptionsMetadataString += val.c_str();
hbaseOptionsMetadataString += "'|";
}
hbaseOptionsMetadataString += " "; // add a trailing separator
}
return 0;
}
// This method updates the HBASE_OPTIONS=> text in the metadata with
// new HBase options.
short CmpSeabaseDDL::updateHbaseOptionsInMetadata(
ExeCliInterface * cliInterface,
Int64 objectUID,
ElemDDLHbaseOptions * edhbo)
{
short result = 0;
// get the text from the metadata
ComTextType textType = COM_HBASE_OPTIONS_TEXT; // to get text containing HBASE_OPTIONS=>
Lng32 textSubID = 0; // meaning, the text pertains to the object as a whole
NAString metadataText(STMTHEAP);
result = getTextFromMD(cliInterface,
objectUID,
textType,
textSubID,
metadataText /* out */);
if (result != 0)
return result;
// convert the text to an NAList <HbaseCreateOption *> representation
NAList<HbaseCreateOption *> * hbaseCreateOptions = NULL;
size_t beginHBOTextPos = 0;
size_t endHBOTextPos = 0;
result = genHbaseCreateOptions(metadataText.data(),
hbaseCreateOptions /* out */,
STMTHEAP,
&beginHBOTextPos /* out */,
&endHBOTextPos /* out */);
if (result != 0)
// genHbaseCreateOptions makes sure hbaseCreateOptions is deleted
return result;
// merge the new HBase options into the old ones, replacing any key
// value pairs that exist in both with the new one
// Note: It's likely that the typical case is just one Hbase option
// so we don't bother with clever optimizations such as what if the
// old list is empty.
if (!hbaseCreateOptions)
hbaseCreateOptions = new(STMTHEAP) NAList<HbaseCreateOption *>(STMTHEAP);
NAList<HbaseCreateOption *> & newHbaseCreateOptions = edhbo->getHbaseOptions();
for (CollIndex i = 0; i < newHbaseCreateOptions.entries(); i++)
{
HbaseCreateOption * newHbaseOption = newHbaseCreateOptions[i];
bool notFound = true;
for (CollIndex j = 0; notFound && j < hbaseCreateOptions->entries(); j++)
{
HbaseCreateOption * hbaseOption = (*hbaseCreateOptions)[j];
if (newHbaseOption->key() == hbaseOption->key())
{
hbaseOption->setVal(newHbaseOption->val());
notFound = false;
}
}
if (notFound)
{
HbaseCreateOption * copyOfNew = new(STMTHEAP) HbaseCreateOption(*newHbaseOption);
hbaseCreateOptions->insert(copyOfNew);
}
}
// convert the merged list to text
NAString hbaseOptionsMetadataString(STMTHEAP);
result = genHbaseOptionsMetadataString(*hbaseCreateOptions,
hbaseOptionsMetadataString /* out */);
if (result == 0)
{
// edit the old text, removing the present HBASE_OPTIONS=> text if any,
// and putting the new text in the same spot
metadataText.replace(beginHBOTextPos,
endHBOTextPos - beginHBOTextPos,
hbaseOptionsMetadataString);
// delete the old text from the metadata
// Note: It might be tempting to try an upsert instead of a
// delete followed by an insert, but this won't work. It is
// possible that the metadata text could shrink and take fewer
// rows in its new form than the old. So we do the simple thing
// to avoid such complications.
Lng32 cliRC = deleteFromTextTable(cliInterface, objectUID, textType, textSubID);
if (cliRC < 0)
{
result = -1;
}
else
{
// insert the text back into the metadata
result = updateTextTable(cliInterface,
objectUID,
textType,
textSubID,
metadataText);
}
}
// delete any items we created
// Note that HbaseCreateOption contains members that allocate
// storage from the global heap so we must delete HbaseCreateOption
// explicitly to avoid global heap memory leaks.
for (CollIndex k = 0; k < hbaseCreateOptions->entries(); k++)
{
HbaseCreateOption * hbaseOption = (*hbaseCreateOptions)[k];
delete hbaseOption;
}
delete hbaseCreateOptions;
return result;
}
void CmpSeabaseDDL::handleDDLCreateAuthorizationError(
int32_t SQLErrorCode,
const NAString & catalogName,
const NAString & schemaName)
{
switch (SQLErrorCode)
{
case CAT_INTERNAL_EXCEPTION_ERROR:
break;
case CAT_SCHEMA_DOES_NOT_EXIST_ERROR:
{
*CmpCommon::diags() << DgSqlCode(-CAT_SCHEMA_DOES_NOT_EXIST_ERROR)
<< DgString0(catalogName)
<< DgString1(schemaName);
break;
}
case CAT_NOT_AUTHORIZED:
{
*CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
break;
}
default:
SEABASEDDL_INTERNAL_ERROR("Switch statement in handleDDLCreateAuthorizationError");
}
}
short CmpSeabaseDDL::updateSeabaseMDObjectsTable(
ExeCliInterface *cliInterface,
const char * catName,
const char * schName,
const char * objName,
const ComObjectType & objectType,
const char * validDef,
Int32 objOwnerID,
Int32 schemaOwnerID,
Int64 objectFlags,
Int64 &inUID)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
char buf[4000];
Int64 objUID = 0;
if (inUID < 0)
{
ComUID comUID;
comUID.make_UID();
objUID = comUID.get_value();
}
else
objUID = inUID;
// return the generated objUID
inUID = objUID;
char objectTypeLit[3] = {0};
strncpy(objectTypeLit,PrivMgr::ObjectEnumToLit(objectType),2);
Int64 createTime = NA_JulianTimestamp();
NAString quotedSchName;
ToQuotedString(quotedSchName, NAString(schName), FALSE);
NAString quotedObjName;
ToQuotedString(quotedObjName, NAString(objName), FALSE);
str_sprintf(buf, "insert into %s.\"%s\".%s values ('%s', '%s', '%s', '%s', %ld, %ld, %ld, '%s', '%s', %d, %d, %ld )",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
catName, quotedSchName.data(), quotedObjName.data(),
objectTypeLit,
objUID,
createTime,
createTime,
(validDef ? validDef : COM_YES_LIT),
COM_NO_LIT,
objOwnerID,
schemaOwnerID,
objectFlags);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return cliRC;
}
return 0;
}
short CmpSeabaseDDL::deleteFromSeabaseMDObjectsTable(
ExeCliInterface *cliInterface,
const char * catName,
const char * schName,
const char * objName,
const ComObjectType & objectType)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
char buf[4000];
NAString quotedSchName;
ToQuotedString(quotedSchName, NAString(schName), FALSE);
NAString quotedObjName;
ToQuotedString(quotedObjName, NAString(objName), FALSE);
char objectTypeLit[3] = {0};
strncpy(objectTypeLit,PrivMgr::ObjectEnumToLit(objectType),2);
str_sprintf(buf, "delete from %s.\"%s\".%s where catalog_name = '%s' and schema_name = '%s' and object_name = '%s' and object_type = '%s' ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
catName, quotedSchName.data(), quotedObjName.data(), objectTypeLit);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
return 0;
}
static short AssignColEntry(ExeCliInterface *cliInterface, Lng32 entry,
char * currRWRSptr, const char * srcPtr,
Lng32 firstColOffset)
{
Lng32 cliRC = 0;
Lng32 fsDatatype;
Lng32 length;
Lng32 indOffset = -1;
Lng32 varOffset = -1;
cliRC = cliInterface->getAttributes(entry, TRUE, fsDatatype, length,
&indOffset, &varOffset);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
if (indOffset != -1)
*(short*)&currRWRSptr[indOffset] = 0;
if (DFS2REC::isAnyCharacter(fsDatatype))
{
if (DFS2REC::isAnyVarChar(fsDatatype))
{
if (SQL_VARCHAR_HDR_SIZE == sizeof(short))
*(short*)&currRWRSptr[firstColOffset + varOffset] = strlen(srcPtr);
else
*(Lng32*)&currRWRSptr[firstColOffset + varOffset] = strlen(srcPtr);
str_cpy_all(&currRWRSptr[firstColOffset + varOffset + SQL_VARCHAR_HDR_SIZE],
srcPtr, strlen(srcPtr));
}
else
{
str_cpy(&currRWRSptr[firstColOffset + varOffset], srcPtr, length, ' ');
}
}
else
{
str_cpy_all(&currRWRSptr[firstColOffset + varOffset], srcPtr, length);
}
return 0;
}
short CmpSeabaseDDL::updateSeabaseMDTable(
ExeCliInterface *cliInterface,
const char * catName,
const char * schName,
const char * objName,
const ComObjectType & objectType,
const char * validDef,
ComTdbVirtTableTableInfo * tableInfo,
Lng32 numCols,
const ComTdbVirtTableColumnInfo * colInfo,
Lng32 numKeys,
const ComTdbVirtTableKeyInfo * keyInfo,
Lng32 numIndexes,
const ComTdbVirtTableIndexInfo * indexInfo,
Int64 &inUID,
NABoolean updPrivs)
{
NABoolean useRWRS = FALSE;
if (CmpCommon::getDefault(TRAF_USE_RWRS_FOR_MD_INSERT) == DF_ON)
{
useRWRS = TRUE;
}
Int32 objOwnerID = (tableInfo) ? tableInfo->objOwnerID : SUPER_USER;
Int32 schemaOwnerID = (tableInfo) ? tableInfo->schemaOwnerID : SUPER_USER;
Int64 objectFlags = (tableInfo) ? tableInfo->objectFlags : 0;
Int64 tablesFlags = (tableInfo) ? tableInfo->tablesFlags : 0;
if (updateSeabaseMDObjectsTable(cliInterface,catName,schName,objName,objectType,
validDef,objOwnerID, schemaOwnerID, objectFlags, inUID))
return -1;
Int64 objUID = inUID;
Lng32 cliRC = 0;
char buf[4000];
Lng32 keyLength = 0;
Lng32 rowDataLength = 0;
Lng32 rowTotalLength = 0;
for (Lng32 i = 0; i < numKeys; i++)
{
str_sprintf(buf, "upsert into %s.\"%s\".%s values (%ld, '%s', %d, %d, %d, %d, 0)",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_KEYS,
objUID,
keyInfo->colName,
keyInfo->keySeqNum,
keyInfo->tableColNum,
keyInfo->ordering,
keyInfo->nonKeyCol);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
const ComTdbVirtTableColumnInfo * ci = &colInfo[keyInfo->tableColNum];
keyLength += ci->length + (colInfo->nullable ? 2 : 0);
keyInfo += 1;
}
Lng32 rsParamsLen = 0;
Lng32 inputRowLen = 0;
Lng32 inputRWRSlen = 0;
char * inputRWRSptr = NULL;
char * currRWRSptr = NULL;
char * inputRow = NULL;
Lng32 indOffset = 0;
Lng32 varOffset = 0;
Lng32 fsDatatype;
Lng32 length;
Lng32 entry = 0;
Int64 rowsAffected = 0;
ExeCliInterface rwrsCliInterface(STMTHEAP, 0, NULL,
CmpCommon::context()->sqlSession()->getParentQid());
if (useRWRS)
{
ExeCliInterface cqdCliInterface;
cliRC = cqdCliInterface.holdAndSetCQD("ODBC_PROCESS", "ON");
str_sprintf(buf, "upsert using rowset (max rowset size %d, input rowset size ?, input row max length ?, rowset buffer ?) into %s.\"%s\".%s values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
numCols,
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_COLUMNS);
cliRC = rwrsCliInterface.rwrsPrepare(buf, numCols);
if (cliRC < 0)
{
rwrsCliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
cliRC = cqdCliInterface.restoreCQD("ODBC_PROCESS");
return -1;
}
cliRC = cqdCliInterface.restoreCQD("ODBC_PROCESS");
// input rowset size
rsParamsLen = 0;
rwrsCliInterface.getAttributes(1, TRUE, fsDatatype, length, &indOffset, &varOffset);
rsParamsLen += length;
// input row max length
rwrsCliInterface.getAttributes(2, TRUE, fsDatatype, length, &indOffset, &varOffset);
rsParamsLen += length;
// rowwise rowset buffer addr
rwrsCliInterface.getAttributes(3, TRUE, fsDatatype, length, &indOffset, &varOffset);
rsParamsLen += length;
inputRowLen = rwrsCliInterface.inputDatalen();
inputRWRSlen = inputRowLen * numCols;
inputRow = new(heap_) char[inputRowLen];
}
for (Lng32 i = 0; i < numCols; i++)
{
NAString quotedColHeading;
if (colInfo->colHeading)
{
ToQuotedString(quotedColHeading, colInfo->colHeading, FALSE);
}
NAString quotedDefVal;
NAString computedColumnDefinition;
NABoolean isComputedColumn = FALSE;
if (colInfo->defVal)
{
NAString defVal = colInfo->defVal;
if (DFS2REC::isAnyCharacter(colInfo->datatype))
{
// double quote any quotes within outer quotes
TrimNAStringSpace(defVal);
size_t startPos = defVal.index("'");
char endChar = defVal.data()[defVal.length()-1];
if ((startPos >= 0) && (endChar == '\'') && ((defVal.length()-startPos) > 2))
{
NAString innerStr(&defVal.data()[startPos+1], defVal.length() - startPos - 2);
NAString innerQuotedStr;
ToQuotedString(innerQuotedStr, innerStr, TRUE);
NAString defVal2(defVal.data(), startPos);
defVal2 += innerQuotedStr;
defVal = defVal2;
}
}
if (colInfo->defaultClass == COM_ALWAYS_COMPUTE_COMPUTED_COLUMN_DEFAULT ||
colInfo->defaultClass == COM_ALWAYS_DEFAULT_COMPUTED_COLUMN_DEFAULT)
{
computedColumnDefinition = defVal;
// quotedDefVal = "";
isComputedColumn = TRUE;
}
else if (useRWRS)
{
quotedDefVal = defVal; // outer quotes not needed when inserting using rowsets
}
else
ToQuotedString(quotedDefVal, defVal, FALSE);
} // colInfo->defVal
const char *colClassLit = NULL;
switch (colInfo->columnClass)
{
case COM_UNKNOWN_CLASS:
colClassLit = COM_UNKNOWN_CLASS_LIT;
break;
case COM_SYSTEM_COLUMN:
colClassLit = COM_SYSTEM_COLUMN_LIT;
break;
case COM_USER_COLUMN:
colClassLit = COM_USER_COLUMN_LIT;
break;
case COM_ADDED_USER_COLUMN:
colClassLit = COM_ADDED_USER_COLUMN_LIT;
break;
case COM_MV_SYSTEM_ADDED_COLUMN:
colClassLit = COM_MV_SYSTEM_ADDED_COLUMN_LIT;
break;
}
if (useRWRS)
{
Lng32 firstColOffset = 0;
cliRC = rwrsCliInterface.getAttributes(4, TRUE, fsDatatype, length,
&indOffset, &firstColOffset);
entry = 4;
AssignColEntry(&rwrsCliInterface, entry++, inputRow, (char*)&objUID, firstColOffset);
AssignColEntry(&rwrsCliInterface, entry++, inputRow, colInfo->colName, firstColOffset);
AssignColEntry(&rwrsCliInterface, entry++, inputRow, (char*)&colInfo->colNumber, firstColOffset);
AssignColEntry(&rwrsCliInterface, entry++, inputRow, colClassLit, firstColOffset);
AssignColEntry(&rwrsCliInterface, entry++, inputRow, (char*)&colInfo->datatype, firstColOffset);
AssignColEntry(&rwrsCliInterface, entry++, inputRow, getAnsiTypeStrFromFSType(colInfo->datatype), firstColOffset);
AssignColEntry(&rwrsCliInterface, entry++, inputRow, (char*)&colInfo->length, firstColOffset);
AssignColEntry(&rwrsCliInterface, entry++, inputRow, (char*)&colInfo->precision, firstColOffset);
AssignColEntry(&rwrsCliInterface, entry++, inputRow, (char*)&colInfo->scale, firstColOffset);
AssignColEntry(&rwrsCliInterface, entry++, inputRow, (char*)&colInfo->dtStart, firstColOffset);
AssignColEntry(&rwrsCliInterface, entry++, inputRow, (char*)&colInfo->dtEnd, firstColOffset);
AssignColEntry(&rwrsCliInterface, entry++, inputRow, (colInfo->upshifted ? COM_YES_LIT : COM_NO_LIT), firstColOffset);
AssignColEntry(&rwrsCliInterface, entry++, inputRow, (char*)&colInfo->hbaseColFlags, firstColOffset);
AssignColEntry(&rwrsCliInterface, entry++, inputRow, (char*)&colInfo->nullable, firstColOffset);
AssignColEntry(&rwrsCliInterface, entry++, inputRow, CharInfo::getCharSetName((CharInfo::CharSet)colInfo->charset), firstColOffset);
AssignColEntry(&rwrsCliInterface, entry++, inputRow, (char*)&colInfo->defaultClass, firstColOffset);
AssignColEntry(&rwrsCliInterface, entry++, inputRow, (colInfo->defVal ? quotedDefVal.data() : ""), firstColOffset);
AssignColEntry(&rwrsCliInterface, entry++, inputRow, (colInfo->colHeading ? quotedColHeading.data() : ""), firstColOffset);
AssignColEntry(&rwrsCliInterface, entry++, inputRow, (colInfo->hbaseColFam ? colInfo->hbaseColFam : ""), firstColOffset);
AssignColEntry(&rwrsCliInterface, entry++, inputRow, (colInfo->hbaseColQual ? colInfo->hbaseColQual : ""), firstColOffset);
AssignColEntry(&rwrsCliInterface, entry++, inputRow, colInfo->paramDirection, firstColOffset);
AssignColEntry(&rwrsCliInterface, entry++, inputRow, (colInfo->isOptional ? COM_YES_LIT : COM_NO_LIT), firstColOffset);
AssignColEntry(&rwrsCliInterface, entry++, inputRow, (char*)&colInfo->colFlags, firstColOffset);
cliRC = rwrsCliInterface.rwrsExec(inputRow, inputRowLen, &rowsAffected);
if (cliRC < 0)
{
rwrsCliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
}
else
{
str_sprintf(buf, "insert into %s.\"%s\".%s values (%ld, '%s', %d, '%s', %d, '%s', %d, %d, %d, %d, %d, '%s', %d, %d, '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', %ld)",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_COLUMNS,
objUID,
colInfo->colName,
colInfo->colNumber,
colClassLit,
colInfo->datatype,
getAnsiTypeStrFromFSType(colInfo->datatype),
colInfo->length,
colInfo->precision,
colInfo->scale,
colInfo->dtStart,
colInfo->dtEnd,
(colInfo->upshifted ? "Y" : "N"),
colInfo->hbaseColFlags,
colInfo->nullable,
CharInfo::getCharSetName((CharInfo::CharSet)colInfo->charset),
(Lng32)colInfo->defaultClass,
(colInfo->defVal ? quotedDefVal.data() : ""),
(colInfo->colHeading ? quotedColHeading.data() : ""),
colInfo->hbaseColFam ? colInfo->hbaseColFam : "" ,
colInfo->hbaseColQual ? colInfo->hbaseColQual : "",
colInfo->paramDirection,
colInfo->isOptional ? "Y" : "N",
colInfo->colFlags);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
}
if (isComputedColumn)
{
cliRC = updateTextTable(cliInterface,
objUID,
COM_COMPUTED_COL_TEXT,
colInfo->colNumber,
computedColumnDefinition);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
}
rowDataLength += colInfo->length + (colInfo->nullable ? 1 : 0);
// compute HBase cell overhead.
// For each stored cell/column, overhead is:
// timestamp, colFam, colQual, rowKey
// For aligned format tables, only one cell is stored.
// The overhead will be computed after exiting the 'for' loop.
if ((!tableInfo) ||
(tableInfo->rowFormat != COM_ALIGNED_FORMAT_TYPE))
{
rowTotalLength += colInfo->length + (colInfo->nullable ? 1 : 0) +
keyLength +
sizeof(Int64)/*timestamp*/ +
(colInfo->hbaseColFam ? strlen(colInfo->hbaseColFam) : strlen(SEABASE_DEFAULT_COL_FAMILY)) +
(colInfo->hbaseColQual ? strlen(colInfo->hbaseColQual) : 2);
}
colInfo += 1;
} // for
if (tableInfo && tableInfo->rowFormat == COM_ALIGNED_FORMAT_TYPE)
{
// one cell contains the aligned row
rowTotalLength = rowDataLength + keyLength +
sizeof(Int64)/*timestamp*/ +
strlen(SEABASE_DEFAULT_COL_FAMILY) + 2/* 2 bytes for col qual #1*/;
}
if (useRWRS)
{
cliRC = rwrsCliInterface.rwrsClose();
if (cliRC < 0)
{
rwrsCliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
}
if (objectType == COM_BASE_TABLE_OBJECT || objectType == COM_INDEX_OBJECT)
{
Lng32 isAudited = 1;
Lng32 numSaltPartns = 0;
const char * hbaseCreateOptions = NULL;
char rowFormat[10];
strcpy(rowFormat, COM_HBASE_FORMAT_LIT);
if (tableInfo)
{
isAudited = tableInfo->isAudited;
if (tableInfo->rowFormat == COM_ALIGNED_FORMAT_TYPE)
strcpy(rowFormat, COM_ALIGNED_FORMAT_LIT);
else if (tableInfo->rowFormat == COM_HBASE_STR_FORMAT_TYPE)
strcpy(rowFormat, COM_HBASE_STR_FORMAT_LIT);
numSaltPartns = tableInfo->numSaltPartns;
hbaseCreateOptions = tableInfo->hbaseCreateOptions;
}
str_sprintf(buf, "upsert into %s.\"%s\".%s values (%ld, '%s', '%s', %d, %d, %d, %d, %ld) ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_TABLES,
objUID,
rowFormat,
(isAudited ? "Y" : "N"),
rowDataLength,
rowTotalLength,
keyLength,
numSaltPartns,
tablesFlags);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
if (hbaseCreateOptions)
{
NAString nas(hbaseCreateOptions);
if (updateTextTable(cliInterface, objUID, COM_HBASE_OPTIONS_TEXT, 0, nas))
{
return -1;
}
}
} // BT
if (objectType == COM_INDEX_OBJECT && numIndexes > 0)
{
// this is an index, update the INDEXES table
ComObjectName baseTableName(indexInfo->baseTableName);
const NAString catalogNamePart =
baseTableName.getCatalogNamePartAsAnsiString();
const NAString schemaNamePart =
baseTableName.getSchemaNamePartAsAnsiString(TRUE);
const NAString objectNamePart =
baseTableName.getObjectNamePartAsAnsiString(TRUE);
Int64 baseTableUID =
getObjectUID(cliInterface,
catalogNamePart.data(), schemaNamePart.data(), objectNamePart.data(),
COM_BASE_TABLE_OBJECT_LIT);
str_sprintf(buf, "insert into %s.\"%s\".%s values (%ld, %d, %d, %d, %d, %d, %ld, 0) ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_INDEXES,
baseTableUID,
indexInfo->keytag,
indexInfo->isUnique,
indexInfo->keyColCount,
indexInfo->nonKeyColCount,
indexInfo->isExplicit,
objUID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
} // is an index
// Grant owner privileges
if ((isAuthorizationEnabled()) &&
(updPrivs))
{
NAString fullName (catName);
fullName += ".";
fullName += schName;
fullName += ".";
fullName += objName;
if (!insertPrivMgrInfo(objUID,
fullName,
objectType,
objOwnerID,
schemaOwnerID,
ComUser::getCurrentUser()))
{
*CmpCommon::diags()
<< DgSqlCode(-CAT_UNABLE_TO_GRANT_PRIVILEGES)
<< DgTableName(objName);
return -1;
}
}
return 0;
}
short CmpSeabaseDDL::updateSeabaseMDSPJ(
ExeCliInterface *cliInterface,
const char * catName,
const char * schName,
const char * libName,
const char * libPath,
const Int32 ownerID,
const Int32 schemaOwnerID,
const ComTdbVirtTableRoutineInfo * routineInfo,
Lng32 numCols,
const ComTdbVirtTableColumnInfo * colInfo)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
char buf[4000];
ComUID libUID;
libUID.make_UID();
Int64 libObjUID = libUID.get_value();
Int64 createTime = NA_JulianTimestamp();
NAString quotedSchName;
ToQuotedString(quotedSchName, NAString(schName), FALSE);
NAString quotedLibObjName;
ToQuotedString(quotedLibObjName, NAString(libName), FALSE);
str_sprintf(buf, "insert into %s.\"%s\".%s values ('%s', '%s', '%s', '%s', %ld, %ld, %ld, '%s', '%s', %d, %d, 0 )",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
catName, quotedSchName.data(), quotedLibObjName.data(),
COM_LIBRARY_OBJECT_LIT,
libObjUID,
createTime,
createTime,
COM_YES_LIT,
COM_NO_LIT,
ownerID,
schemaOwnerID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
str_sprintf(buf, "insert into %s.\"%s\".%s values (%ld, '%s', %d, 0)",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_LIBRARIES,
libObjUID, libPath, routineInfo->library_version);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
NAString catalogNamePart(getSystemCatalog());
NAString schemaNamePart;
ToQuotedString(schemaNamePart, NAString(SEABASE_MD_SCHEMA), FALSE);
NAString quotedSpjObjName;
ToQuotedString(quotedSpjObjName, NAString(routineInfo->routine_name), FALSE);
Int64 objUID = -1;
ComTdbVirtTableTableInfo * tableInfo = new(STMTHEAP) ComTdbVirtTableTableInfo[1];
tableInfo->tableName = NULL,
tableInfo->createTime = 0;
tableInfo->redefTime = 0;
tableInfo->objUID = 0;
tableInfo->objOwnerID = ownerID;
tableInfo->schemaOwnerID = schemaOwnerID;
tableInfo->isAudited = 1;
tableInfo->validDef = 1;
tableInfo->hbaseCreateOptions = NULL;
tableInfo->numSaltPartns = 0;
tableInfo->rowFormat = COM_UNKNOWN_FORMAT_TYPE;
tableInfo->objectFlags = 0;
if (updateSeabaseMDTable(cliInterface,
catalogNamePart, schemaNamePart, quotedSpjObjName,
COM_USER_DEFINED_ROUTINE_OBJECT,
"Y",
tableInfo,
numCols,
colInfo,
0, NULL,
0, NULL,
objUID))
{
return -1;
}
Int64 spjObjUID = getObjectUID(cliInterface,
catalogNamePart, schemaNamePart, quotedSpjObjName,
COM_USER_DEFINED_ROUTINE_OBJECT_LIT);
if (spjObjUID == -1)
return -1;
str_sprintf(buf, "insert into %s.\"%s\".%s values (%ld, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', '%s', '%s', '%s', %ld, '%s', 0 )",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_ROUTINES,
spjObjUID,
routineInfo->UDR_type,
routineInfo->language_type,
routineInfo->deterministic ? "Y" : "N" ,
routineInfo->sql_access,
routineInfo->call_on_null ? "Y" : "N" ,
routineInfo->isolate ? "Y" : "N" ,
routineInfo->param_style,
routineInfo->transaction_attributes,
routineInfo->max_results,
routineInfo->state_area_size,
routineInfo->external_name,
routineInfo->parallelism,
routineInfo->user_version,
routineInfo->external_security,
routineInfo->execution_mode,
libObjUID,
routineInfo->signature);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
str_sprintf(buf, "insert into %s.\"%s\".%s values (%ld, %ld, 0)",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_LIBRARIES_USAGE,
libObjUID, spjObjUID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
return 0;
}
short CmpSeabaseDDL::deleteFromSeabaseMDTable(
ExeCliInterface *cliInterface,
const char * catName,
const char * schName,
const char * objName,
const ComObjectType objType)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
char buf[4000];
char objectTypeLit[3] = {0};
strncpy(objectTypeLit,PrivMgr::ObjectEnumToLit(objType),2);
Int64 objUID = getObjectUID(cliInterface, catName, schName, objName, objectTypeLit);
if (objUID < 0)
return -1;
cliRC = deleteFromSeabaseMDObjectsTable(cliInterface,
catName, schName, objName,
objType);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
if (objType == COM_LIBRARY_OBJECT)
{
str_sprintf(buf, "delete from %s.\"%s\".%s where library_uid = %ld",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_LIBRARIES,
objUID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
// delete comment from TEXT table for library
str_sprintf(buf, "delete from %s.\"%s\".%s where text_uid = %ld",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_TEXT,
objUID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
return 0; // nothing else to do for libraries
}
if (objType == COM_SEQUENCE_GENERATOR_OBJECT)
{
str_sprintf(buf, "delete from %s.\"%s\".%s where seq_uid = %ld",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_SEQ_GEN,
objUID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
}
str_sprintf(buf, "delete from %s.\"%s\".%s where object_uid = %ld",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_COLUMNS,
objUID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
// delete data from TEXT table
str_sprintf(buf, "delete from %s.\"%s\".%s where text_uid = %ld",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_TEXT,
objUID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
if (objType == COM_USER_DEFINED_ROUTINE_OBJECT)
{
str_sprintf(buf, "delete from %s.\"%s\".%s where udr_uid = %ld",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_ROUTINES,
objUID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
str_sprintf(buf, "delete from %s.\"%s\".%s where used_udr_uid = %ld",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_LIBRARIES_USAGE,
objUID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
return 0; // nothing else to do for routines
}
str_sprintf(buf, "delete from %s.\"%s\".%s where object_uid = %ld ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_KEYS,
objUID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
str_sprintf(buf, "delete from %s.\"%s\".%s where table_uid = %ld ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_TABLES,
objUID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
if (objType == COM_INDEX_OBJECT)
{
str_sprintf(buf, "delete from %s.\"%s\".%s where index_uid = %ld ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_INDEXES,
objUID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
}
if (objType == COM_VIEW_OBJECT)
{
str_sprintf(buf, "delete from %s.\"%s\".%s where view_uid = %ld ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_VIEWS,
objUID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
str_sprintf(buf, "delete from %s.\"%s\".%s where using_view_uid = %ld ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_VIEWS_USAGE,
objUID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
}
return 0;
}
short CmpSeabaseDDL::deleteConstraintInfoFromSeabaseMDTables(
ExeCliInterface *cliInterface,
Int64 tableUID,
Int64 otherTableUID, // valid for ref constrs
Int64 constrUID,
Int64 otherConstrUID, // valid for ref constrs
const char * constrCatName,
const char * constrSchName,
const char * constrObjName,
const ComObjectType constrType)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
char buf[4000];
if (deleteFromSeabaseMDTable(cliInterface,
constrCatName, constrSchName, constrObjName,
constrType))
return -1;
// delete data from table constraints MD
str_sprintf(buf, "delete from %s.\"%s\".%s where table_uid = %ld and constraint_uid = %ld",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_TABLE_CONSTRAINTS,
tableUID, constrUID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
// delete data from ref constraints MD
str_sprintf(buf, "delete from %s.\"%s\".%s where ref_constraint_uid = %ld and unique_constraint_uid = %ld",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_REF_CONSTRAINTS,
constrUID, otherConstrUID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
// delete data from unique ref constraints usage MD
str_sprintf(buf, "delete from %s.\"%s\".%s where unique_constraint_uid = %ld and foreign_constraint_uid = %ld",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_UNIQUE_REF_CONSTR_USAGE,
otherConstrUID, constrUID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
// delete data from TEXT table
str_sprintf(buf, "delete from %s.\"%s\".%s where text_uid = %ld",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_TEXT,
constrUID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
return 0;
}
short CmpSeabaseDDL::checkAndGetStoredObjectDesc(
ExeCliInterface *cliInterface,
Int64 objUID,
TrafDesc* *retDesc)
{
Lng32 cliRC = 0;
NAString packedDesc;
cliRC = getTextFromMD(
cliInterface, objUID, COM_STORED_DESC_TEXT, 0, packedDesc, TRUE);
if (cliRC < 0)
{
*CmpCommon::diags() << DgSqlCode(-4493)
<< DgString0("Error reading from metadata.");
processReturn();
return -1;
}
if (packedDesc.length() == 0)
{
// stored desc doesn't exist
*CmpCommon::diags() << DgSqlCode(-4493)
<< DgString0("Does not exist. It needs to be regenerated.");
processReturn();
return -2;
}
char * descBuf = new(STMTHEAP) char[packedDesc.length()];
str_cpy_all(descBuf, packedDesc.data(), packedDesc.length());
TrafDesc * desc = (TrafDesc*)descBuf;
TrafDesc dummyDesc;
desc = (TrafDesc*)desc->driveUnpack((void*)desc, &dummyDesc, NULL);
if (! desc)
{
NADELETEBASIC(descBuf, STMTHEAP);
// error during unpack. Desc need to be regenerated.
*CmpCommon::diags() << DgSqlCode(-4493)
<< DgString0("Error during unpacking due to change in stored structures. It needs to be regenerated.");
processReturn();
return -3;
}
// all good
*CmpCommon::diags() << DgSqlCode(4493)
<< DgString0("Uptodate and current.");
if (retDesc)
*retDesc = desc;
else
NADELETEBASIC(descBuf, STMTHEAP);
return 0;
}
// rt = -1, generate redef time. rt = -2, dont update redef time.
// otherwise use provided redef time.
//
// Also generate and update object descriptor in metadata.
short CmpSeabaseDDL::updateObjectRedefTime(
ExeCliInterface *cliInterface,
const NAString &catName,
const NAString &schName,
const NAString &objName,
const char * objType,
Int64 rt,
Int64 objUID,
NABoolean force)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
char buf[4000];
Int64 redefTime = ((rt == -1) ? NA_JulianTimestamp() : rt);
NAString quotedSchName;
ToQuotedString(quotedSchName, NAString(schName), FALSE);
NAString quotedObjName;
ToQuotedString(quotedObjName, NAString(objName), FALSE);
Int64 flags = 0;
if (((CmpCommon::getDefault(TRAF_STORE_OBJECT_DESC) == DF_ON) ||
(force)) &&
(objUID > 0) &&
(NOT isSeabaseReservedSchema(catName, schName)) &&
((strcmp(objType, COM_BASE_TABLE_OBJECT_LIT) == 0) ||
(strcmp(objType, COM_VIEW_OBJECT_LIT) == 0)))
{
Int32 ctlFlags = GEN_PACKED_DESC | GET_SNAPSHOTS;
Int32 packedDescLen = 0;
TrafDesc * ds =
getSeabaseUserTableDesc(catName, schName, objName,
(strcmp(objType, COM_BASE_TABLE_OBJECT_LIT) == 0
? COM_BASE_TABLE_OBJECT : COM_VIEW_OBJECT),
FALSE, ctlFlags, packedDescLen);
if (! ds)
{
processReturn();
return -1;
}
cliRC = updateTextTableWithBinaryData
(cliInterface, objUID,
COM_STORED_DESC_TEXT, 0,
(char*)ds, packedDescLen,
TRUE /*delete existing data*/);
if (cliRC < 0)
{
processReturn();
return -1;
}
CmpSeabaseDDL::setMDflags(flags, MD_OBJECTS_STORED_DESC);
}
buf[0] = 0;
if ((flags & MD_OBJECTS_STORED_DESC) != 0)
{
if (rt == -2)
str_sprintf(buf, "update %s.\"%s\".%s set flags = bitor(flags, %ld) where catalog_name = '%s' and schema_name = '%s' and object_name = '%s' and object_type = '%s' ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
flags,
catName.data(), quotedSchName.data(), quotedObjName.data(),
objType);
else
str_sprintf(buf, "update %s.\"%s\".%s set redef_time = %ld, flags = bitor(flags, %ld) where catalog_name = '%s' and schema_name = '%s' and object_name = '%s' and object_type = '%s' ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
redefTime,
flags,
catName.data(), quotedSchName.data(), quotedObjName.data(),
objType);
}
else if (rt != -2)
{
str_sprintf(buf, "update %s.\"%s\".%s set redef_time = %ld where catalog_name = '%s' and schema_name = '%s' and object_name = '%s' and object_type = '%s' ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
redefTime,
catName.data(), quotedSchName.data(), quotedObjName.data(),
objType);
}
if (strlen(buf) > 0)
{
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
}
return 0;
}
short CmpSeabaseDDL::updateObjectValidDef(
ExeCliInterface *cliInterface,
const char * catName,
const char * schName,
const char * objName,
const char * objType,
const char * validDef)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
char buf[4000];
NAString quotedSchName;
ToQuotedString(quotedSchName, NAString(schName), FALSE);
NAString quotedObjName;
ToQuotedString(quotedObjName, NAString(objName), FALSE);
str_sprintf(buf, "update %s.\"%s\".%s set valid_def = '%s' where catalog_name = '%s' and schema_name = '%s' and object_name = '%s' and object_type = '%s' ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
validDef,
catName, quotedSchName.data(), quotedObjName.data(),
objType);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
return 0;
}
short CmpSeabaseDDL::updateObjectName(
ExeCliInterface *cliInterface,
Int64 objUID,
const char * catName,
const char * schName,
const char * objName)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
char buf[4000];
NAString quotedSchName;
ToQuotedString(quotedSchName, NAString(schName), FALSE);
NAString quotedObjName;
ToQuotedString(quotedObjName, NAString(objName), FALSE);
str_sprintf(buf, "update %s.\"%s\".%s set catalog_name = '%s', schema_name = '%s', object_name = '%s' where object_uid = %ld ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
catName, quotedSchName.data(), quotedObjName.data(),
objUID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
return 0;
}
short CmpSeabaseDDL::updateObjectAuditAttr(
ExeCliInterface *cliInterface,
const char * catName,
const char * schName,
const char * objName,
NABoolean audited,
const NAString &objType)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
char buf[4000];
Int64 objectUID = getObjectUID(cliInterface, catName, schName, objName, objType);
if (objectUID < 0)
return -1;
str_sprintf(buf, "update %s.\"%s\".%s set is_audited = '%s' where table_uid = %ld ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_TABLES,
(audited ? "Y" : "N"),
objectUID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
return 0;
}
short CmpSeabaseDDL::updateObjectFlags(
ExeCliInterface *cliInterface,
const Int64 objUID,
const Int64 inFlags,
NABoolean reset)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
char buf[4000];
Int64 flags = inFlags;
if (reset)
flags = ~inFlags;
if (reset)
str_sprintf(buf, "update %s.\"%s\".%s set flags = bitand(flags, %ld) where object_uid = %ld",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
flags, objUID);
else
str_sprintf(buf, "update %s.\"%s\".%s set flags = bitor(flags, %ld) where object_uid = %ld",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
flags, objUID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
return 0;
}
void CmpSeabaseDDL::cleanupObjectAfterError(
ExeCliInterface &cliInterface,
const NAString &catName,
const NAString &schName,
const NAString &objName,
const ComObjectType objectType,
NABoolean dontForceCleanup)
{
//if ddlXns are being used, no need of additional cleanup.
//transactional rollback will take care of cleanup.
if (dontForceCleanup)
return;
Lng32 cliRC = 0;
char buf[1000];
// save current diags area
ComDiagsArea * tempDiags = ComDiagsArea::allocate(heap_);
tempDiags->mergeAfter(*CmpCommon::diags());
CmpCommon::diags()->clear();
if (objectType == COM_BASE_TABLE_OBJECT)
str_sprintf(buf, "cleanup table \"%s\".\"%s\".\"%s\" ",
catName.data(), schName.data(), objName.data());
else if (objectType == COM_INDEX_OBJECT)
str_sprintf(buf, "cleanup index \"%s\".\"%s\".\"%s\" ",
catName.data(), schName.data(), objName.data());
else
str_sprintf(buf, "cleanup object \"%s\".\"%s\".\"%s\" ",
catName.data(), schName.data(), objName.data());
cliRC = cliInterface.executeImmediate(buf);
CmpCommon::diags()->clear();
CmpCommon::diags()->mergeAfter(*tempDiags);
if (cliRC < 0)
{
cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
}
tempDiags->clear();
tempDiags->deAllocate();
return;
}
void CmpSeabaseDDL::purgedataObjectAfterError(
ExeCliInterface &cliInterface,
const NAString &catName,
const NAString &schName,
const NAString &objName,
const ComObjectType objectType,
NABoolean dontForceCleanup)
{
//if ddlXns are being used, no need of additional cleanup.
//transactional rollback will take care of cleanup.
if (dontForceCleanup)
return;
PushAndSetSqlParserFlags savedParserFlags(INTERNAL_QUERY_FROM_EXEUTIL);
Lng32 cliRC = 0;
char buf[1000];
// save current diags area
ComDiagsArea * tempDiags = ComDiagsArea::allocate(heap_);
tempDiags->mergeAfter(*CmpCommon::diags());
CmpCommon::diags()->clear();
if (objectType == COM_BASE_TABLE_OBJECT)
str_sprintf(buf, "purgedata \"%s\".\"%s\".\"%s\" ",
catName.data(), schName.data(), objName.data());
else if (objectType == COM_INDEX_OBJECT)
str_sprintf(buf, "purgedata table(index_table \"%s\".\"%s\".\"%s\" ) ",
catName.data(), schName.data(), objName.data());
else
ex_assert(0, "purgedata object is not supported");
cliRC = cliInterface.executeImmediate(buf);
CmpCommon::diags()->clear();
CmpCommon::diags()->mergeAfter(*tempDiags);
if (cliRC < 0)
{
cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
}
tempDiags->clear();
tempDiags->deAllocate();
return;
}
// user created traf stored col fam is of the form: #<1-byte-num>
// 1-byte-num is character '2' through '9', or 'a' through 'x'.
// This allows for 32 column families and
// is the index of user specified col family stored in naTable.allColFam().
//
// Family "#1" is reserved for system default column family name. This is also
// the name that was used priori to multi-col fam support.
short CmpSeabaseDDL::genTrafColFam(int index, NAString &trafColFamily)
{
trafColFamily = "#";
unsigned char v;
if (index >= 0 && index <= 7)
v = (unsigned char)('2' + index);
else if (index >= 8 && index <= 32)
v = (unsigned char)('a' + (index - 8));
else
return -1; // error
trafColFamily.append((char*)&v, 1);
return 0;
}
short CmpSeabaseDDL::extractTrafColFam(const NAString &trafColFam, int &index)
{
unsigned char v = (unsigned char)trafColFam.data()[1];
index = 0;
if (v >= '2' && v <= '9')
index = v - '2';
else if (v >= 'a' && v <= 'x')
index = ((v - 'a') + 8);
else
return -1;
return 0;
}
// inColFamily: user specified column family
// trafColFamily: col fam stored in traf tables
// userColFamVec: unique array of user col families
// trafColFamVec: unique array of traf col families
short CmpSeabaseDDL::processColFamily(NAString &inColFamily,
NAString &trafColFamily,
std::vector<NAString> *userColFamVec,
std::vector<NAString> *trafColFamVec)
{
if (inColFamily.isNull())
return 0;
if (! userColFamVec)
{
trafColFamily = inColFamily;
return 0;
}
int i = 0;
NABoolean found = FALSE;
while ((NOT found) && (i < userColFamVec->size()))
{
NAString &nas = (*userColFamVec)[i];
if (nas == inColFamily)
{
found = TRUE;
}
else
i++;
}
// add this user col fam to user fam array if not already there.
if (NOT found)
{
userColFamVec->push_back(inColFamily);
}
if (inColFamily == SEABASE_DEFAULT_COL_FAMILY)
trafColFamily = SEABASE_DEFAULT_COL_FAMILY;
else
{
genTrafColFam(i, trafColFamily);
}
if (trafColFamVec)
{
found = FALSE;
i = 0;
while ((NOT found) && (i < trafColFamVec->size()))
{
NAString &nas = (*trafColFamVec)[i];
if (nas == trafColFamily)
{
found = TRUE;
}
else
i++;
}
if (not found)
trafColFamVec->push_back(trafColFamily);
}
return 0;
}
short CmpSeabaseDDL::buildColInfoArray(
ComObjectType objType,
NABoolean isMetadataHistOrReposObject,
ElemDDLColDefArray *colArray,
ComTdbVirtTableColumnInfo * colInfoArray,
NABoolean implicitPK,
NABoolean alignedFormat,
Lng32 *identityColPos, // IN_OUT
std::vector<NAString> *userColFamVec, // IN_OUT
std::vector<NAString> *trafColFamVec, // IN_OUT
const char * inColFam, // IN
NAMemory * heap)
{
std::vector<NAString> myvector;
if (identityColPos)
*identityColPos = -1;
NAString defaultColFam = (inColFam ? inColFam : SEABASE_DEFAULT_COL_FAMILY);
NABoolean nullColFamFound = FALSE;
size_t index = 0;
for (index = 0; index < colArray->entries(); index++)
{
ElemDDLColDef *colNode = (*colArray)[index];
NAString colFamily;
NAString colName;
Lng32 datatype, length, precision, scale, dt_start, dt_end, nullable, upshifted;
ComColumnClass colClass;
ComColumnDefaultClass defaultClass;
NAString charset, defVal;
NAString heading;
ULng32 hbaseColFlags;
Int64 colFlags;
LobsStorage lobStorage;
if (getColInfo(colNode,
isMetadataHistOrReposObject,
colFamily,
colName,
alignedFormat,
datatype, length, precision, scale, dt_start, dt_end, upshifted, nullable,
charset, colClass, defaultClass, defVal, heading, lobStorage, hbaseColFlags, colFlags))
return -1;
colInfoArray[index].hbaseColFlags = hbaseColFlags;
char * col_name = new((heap ? heap : STMTHEAP)) char[colName.length() + 1];
strcpy(col_name, (char*)colName.data());
myvector.push_back(col_name);
colInfoArray[index].colName = col_name;
colInfoArray[index].colNumber = index;
colInfoArray[index].columnClass = colClass;
colInfoArray[index].datatype = datatype;
colInfoArray[index].length = length;
colInfoArray[index].nullable = nullable;
colInfoArray[index].charset = (SQLCHARSET_CODE)CharInfo::getCharSetEnum(charset);
colInfoArray[index].precision = precision;
colInfoArray[index].scale = scale;
colInfoArray[index].dtStart = dt_start;
colInfoArray[index].dtEnd = dt_end;
colInfoArray[index].upshifted = upshifted;
colInfoArray[index].defaultClass = defaultClass;
colInfoArray[index].defVal = NULL;
if (defVal.length() > 0)
{
char * def_val = new((heap ? heap : STMTHEAP)) char[defVal.length() +1];
str_cpy_all(def_val, (char*)defVal.data(), defVal.length());
def_val[defVal.length()] = 0;
colInfoArray[index].defVal = def_val;
}
if ((identityColPos) &&
((defaultClass == COM_IDENTITY_GENERATED_BY_DEFAULT) ||
(defaultClass == COM_IDENTITY_GENERATED_ALWAYS)))
{
if ((objType == COM_BASE_TABLE_OBJECT) &&
(*identityColPos >= 0)) // previously found
{
// cannot have more than one identity cols
*CmpCommon::diags() << DgSqlCode(-1511);
return -1;
}
*identityColPos = index;
}
colInfoArray[index].colHeading = NULL;
if (heading.length() > 0)
{
char * head_val = new((heap ? heap : STMTHEAP)) char[heading.length() +1];
str_cpy_all(head_val, (char*)heading.data(), heading.length());
head_val[heading.length()] = 0;
colInfoArray[index].colHeading = head_val;
}
if (colFamily.isNull())
{
colFamily = defaultColFam;
nullColFamFound = TRUE;
}
else
{
if (alignedFormat)
{
*CmpCommon::diags() << DgSqlCode(-4223)
<< DgString0("Column Family specification on columns of an aligned format table is");
return -1;
}
}
NAString storedColFamily;
processColFamily(colFamily, storedColFamily, userColFamVec, trafColFamVec);
colInfoArray[index].hbaseColFam =
new((heap ? heap : STMTHEAP)) char[storedColFamily.length() +1];
strcpy((char*)colInfoArray[index].hbaseColFam, (char*)storedColFamily.data());
char idxNumStr[40];
str_itoa(index+1, idxNumStr);
colInfoArray[index].hbaseColQual =
new((heap ? heap : STMTHEAP)) char[strlen(idxNumStr) + 1];
strcpy((char*)colInfoArray[index].hbaseColQual, idxNumStr);
strcpy(colInfoArray[index].paramDirection, COM_UNKNOWN_PARAM_DIRECTION_LIT);
colInfoArray[index].isOptional = FALSE;
colInfoArray[index].colFlags = colFlags;
}
if ((objType == COM_BASE_TABLE_OBJECT) ||
(objType == COM_VIEW_OBJECT))
{
// find duplicate colname references. If found, return error and first dup colname.
std::sort (myvector.begin(), myvector.end());
std::vector<NAString>::iterator it = adjacent_find(myvector.begin(), myvector.end());
if (it != myvector.end())
{
*CmpCommon::diags() << DgSqlCode(-1080)
<< DgColumnName(*it);
return -1;
}
}
if (userColFamVec && (userColFamVec->size() > 32))
{
*CmpCommon::diags() << DgSqlCode(-4225);
return -1;
}
return 0;
}
short CmpSeabaseDDL::buildColInfoArray(
ElemDDLParamDefArray *paramArray,
ComTdbVirtTableColumnInfo * colInfoArray
)
{
size_t index = 0;
for (index = 0; index < paramArray->entries(); index++)
{
ElemDDLParamDef *paramNode = (*paramArray)[index];
ElemDDLColDef colNode(NULL, &paramNode->getParamName(),
paramNode->getParamDataType(),
NULL, STMTHEAP);
NAString colFamily;
NAString colName;
Lng32 datatype, length, precision, scale, dt_start, dt_end, nullable, upshifted;
ComColumnClass colClass;
ComColumnDefaultClass defaultClass;
NAString charset, defVal;
NAString heading;
ULng32 hbaseColFlags;
Int64 colFlags;
LobsStorage lobStorage;
if (getColInfo(&colNode,
FALSE,
colFamily,
colName,
FALSE,
datatype, length, precision, scale, dt_start, dt_end,
upshifted, nullable, charset, colClass, defaultClass, defVal,
heading, lobStorage, hbaseColFlags, colFlags))
return -1;
colInfoArray[index].hbaseColFlags = hbaseColFlags;
char * col_name = NULL;
if (colName.length() == 0) {
char idxNumStr[10];
idxNumStr[0] = '#' ;
idxNumStr[1] = ':' ;
str_itoa(index, &(idxNumStr[2]));
col_name = new(STMTHEAP) char[strlen(idxNumStr) + 1];
strcpy(col_name, idxNumStr);
}
else {
col_name = new(STMTHEAP) char[colName.length() + 1];
strcpy(col_name, (char*)colName.data());
}
colInfoArray[index].colName = col_name;
colInfoArray[index].colNumber = index;
colInfoArray[index].columnClass = colClass;
colInfoArray[index].datatype = datatype;
colInfoArray[index].length = length;
colInfoArray[index].nullable = nullable;
colInfoArray[index].charset = (SQLCHARSET_CODE)
CharInfo::getCharSetEnum(charset);
colInfoArray[index].precision = precision;
colInfoArray[index].scale = scale;
colInfoArray[index].dtStart = dt_start;
colInfoArray[index].dtEnd = dt_end;
colInfoArray[index].upshifted = upshifted;
colInfoArray[index].defaultClass = defaultClass;
colInfoArray[index].defVal = NULL;
colInfoArray[index].colHeading = NULL;
colInfoArray[index].hbaseColFam = NULL;
colInfoArray[index].hbaseColQual = NULL;
if (paramNode->getParamDirection() == COM_INPUT_PARAM)
strcpy(colInfoArray[index].paramDirection, COM_INPUT_PARAM_LIT);
else if (paramNode->getParamDirection() == COM_OUTPUT_PARAM)
strcpy(colInfoArray[index].paramDirection, COM_OUTPUT_PARAM_LIT);
else if (paramNode->getParamDirection() == COM_INOUT_PARAM)
strcpy(colInfoArray[index].paramDirection, COM_INOUT_PARAM_LIT);
else
strcpy(colInfoArray[index].paramDirection,
COM_UNKNOWN_PARAM_DIRECTION_LIT);
colInfoArray[index].isOptional = 0; // Aways FALSE for now
colInfoArray[index].colFlags = colFlags;
}
return 0;
}
short CmpSeabaseDDL::buildKeyInfoArray(
ElemDDLColDefArray *colArray,
NAColumnArray * nacolArray,
ElemDDLColRefArray *keyArray,
ComTdbVirtTableColumnInfo * colInfoArray,
ComTdbVirtTableKeyInfo * keyInfoArray,
NABoolean allowNullableUniqueConstr,
Lng32 *keyLength,
NAMemory * heap)
{
if (keyLength)
*keyLength = 0;
size_t index = 0;
for ( index = 0; index < keyArray->entries(); index++)
{
char * col_name = new((heap ? heap : STMTHEAP))
char[strlen((*keyArray)[index]->getColumnName()) + 1];
strcpy(col_name, (*keyArray)[index]->getColumnName());
keyInfoArray[index].colName = col_name; //(*keyArray)[index]->getColumnName();
keyInfoArray[index].keySeqNum = index+1;
if ((! colArray) && (! nacolArray))
{
// this col doesn't exist. Return error.
*CmpCommon::diags() << DgSqlCode(-1009)
<< DgColumnName(keyInfoArray[index].colName);
return -1;
}
NAString nas((*keyArray)[index]->getColumnName());
keyInfoArray[index].tableColNum = (Lng32)
(colArray ?
colArray->getColumnIndex((*keyArray)[index]->getColumnName()) :
nacolArray->getColumnPosition(nas));
if (keyInfoArray[index].tableColNum == -1)
{
// this col doesn't exist. Return error.
*CmpCommon::diags() << DgSqlCode(-1009)
<< DgColumnName(keyInfoArray[index].colName);
return -1;
}
keyInfoArray[index].ordering =
((*keyArray)[index]->getColumnOrdering() == COM_ASCENDING_ORDER ?
ComTdbVirtTableKeyInfo::ASCENDING_ORDERING :
ComTdbVirtTableKeyInfo::DESCENDING_ORDERING);
keyInfoArray[index].nonKeyCol = 0;
ElemDDLColDef *colDef = (*colArray)[keyInfoArray[index].tableColNum];
if (colDef && colDef->getConstraintPK() && colDef->getConstraintPK()->isNullableSpecified())
allowNullableUniqueConstr = TRUE;
if ((colInfoArray) &&
(colInfoArray[keyInfoArray[index].tableColNum].nullable != 0) &&
(NOT allowNullableUniqueConstr))
{
*CmpCommon::diags() << DgSqlCode(-CAT_CLUSTERING_KEY_COL_MUST_BE_NOT_NULL_NOT_DROP)
<< DgColumnName(keyInfoArray[index].colName);
return -1;
}
keyInfoArray[index].hbaseColFam = NULL;
keyInfoArray[index].hbaseColQual = NULL;
if (keyLength)
{
NAType *colType =
(*colArray)[keyInfoArray[index].tableColNum]->getColumnDataType();
*keyLength += colType->getEncodedKeyLength();
}
}
return 0;
}
// subID: 0, for text that belongs to table. colNumber, for column based text.
short CmpSeabaseDDL::updateTextTable(ExeCliInterface *cliInterface,
Int64 objUID,
ComTextType textType,
Lng32 subID,
NAString &textInputData,
char * binaryInputData,
Lng32 binaryInputDataLen,
NABoolean withDelete)
{
Lng32 cliRC = 0;
if (withDelete)
{
// Note: It might be tempting to try an upsert instead of a
// delete followed by an insert, but this won't work. It is
// possible that the metadata text could shrink and take fewer
// rows in its new form than the old. So we do the simple thing
// to avoid such complications.
cliRC = deleteFromTextTable(cliInterface, objUID, textType, subID);
if (cliRC < 0)
{
return -1;
}
}
char * dataToInsert = NULL;
Lng32 dataLen = -1;
if (binaryInputData)
{
Lng32 encodedMaxLen = str_encoded_len(binaryInputDataLen);
char * encodedData = new(STMTHEAP) char[encodedMaxLen];
Lng32 encodedLen =
str_encode(encodedData, encodedMaxLen, binaryInputData, binaryInputDataLen);
dataToInsert = encodedData;
dataLen = encodedLen;
}
else
{
dataToInsert = (char*)textInputData.data();
dataLen = textInputData.length();
}
Int32 maxLen = TEXTLEN;
char queryBuf[1000];
Lng32 numRows = ((dataLen -1) / maxLen) + 1;
Lng32 currPos = 0;
Lng32 currDataLen = 0;
for (Lng32 i = 0; i < numRows; i++)
{
if (i < numRows-1)
currDataLen = maxLen;
else
currDataLen = dataLen - currPos;
str_sprintf(queryBuf, "insert into %s.\"%s\".%s values (%ld, %d, %d, %d, 0, cast(? as char(%d bytes) not null))",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_TEXT,
objUID,
textType,
subID,
i,
currDataLen);
cliRC = cliInterface->executeImmediateCEFC
(queryBuf, &dataToInsert[currPos], currDataLen, NULL, NULL, NULL);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
currPos += maxLen;
}
return 0;
}
short CmpSeabaseDDL::updateTextTableWithBinaryData
(ExeCliInterface *cliInterface,
Int64 objUID,
ComTextType textType,
Lng32 subID,
char * inputData,
Int32 inputDataLen,
NABoolean withDelete)
{
NAString dummy;
return updateTextTable(cliInterface, objUID, textType, subID, dummy,
inputData, inputDataLen, withDelete);
}
short CmpSeabaseDDL::deleteFromTextTable(ExeCliInterface *cliInterface,
Int64 objUID,
ComTextType textType,
Lng32 subID)
{
Lng32 cliRC = 0;
char buf[1000];
str_sprintf(buf, "delete from %s.\"%s\".%s where text_uid = %ld and text_type = %d and sub_id = %d",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_TEXT,
objUID, static_cast<int>(textType), subID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
return 0;
}
ItemExpr *CmpSeabaseDDL::bindDivisionExprAtDDLTime(ItemExpr *expr,
NAColumnArray *availableCols,
NAHeap *heap)
{
// This doesn't fully "bind" the ItemExpr like ItemExpr::bindNode() would do it.
// Instead, it will find column references in the expression, validate that they
// refer to columns passed in as available columns and replace them with
// NamedTypeToItem ItemExprs that contain the column name and the type. This
// will allow us to do type synthesis for this expression later. We can
// also unparse the expression but the result isn't any good for any other
// purpose.
ItemExpr *retval = expr;
CollIndex nc = expr->getArity();
// call the method recursively on the children, this may modify the
// expression passed in
for (CollIndex c=0; c<nc; c++)
{
ItemExpr *boundChild =
bindDivisionExprAtDDLTime(expr->child(c), availableCols, heap);
if (boundChild)
expr->child(c) = boundChild;
else
retval = NULL;
}
if (retval)
switch (expr->getOperatorType())
{
case ITM_REFERENCE:
{
const NAType *colType = NULL;
const NAString &colName = ((ColReference *) expr)->getColRefNameObj().getColName();
// look up column name and column type in availableCols
for (CollIndex c=0; c<availableCols->entries() && colType == NULL; c++)
if (colName == (*availableCols)[c]->getColName())
colType = (*availableCols)[c]->getType();
if (colType)
{
retval = new(heap) NamedTypeToItem(colName.data(),
colType->newCopy(heap),
heap);
}
else
{
// column not found
NAString unparsed;
expr->unparse(unparsed, PARSER_PHASE, COMPUTED_COLUMN_FORMAT);
*CmpCommon::diags() << DgSqlCode(-4240)
<< DgString0(unparsed);
retval = NULL;
}
}
break;
case ITM_NAMED_TYPE_TO_ITEM:
case ITM_CONSTANT:
// these are leaf operators that are allowed without further check
break;
default:
// we want to control explicitly what types of leaf operators we allow
if (nc == 0)
{
// general error, this expression is not supported in DIVISION BY
NAString unparsed;
expr->unparse(unparsed, PARSER_PHASE, COMPUTED_COLUMN_FORMAT);
*CmpCommon::diags() << DgSqlCode(-4243) << DgString0(unparsed);
retval = NULL;
}
}
return retval;
}
short CmpSeabaseDDL::validateDivisionByExprForDDL(ItemExpr *divExpr)
{
// Validate a DIVISION BY expression in a DDL statement
// Check that the DIVISION BY expression conforms to the
// supported types of expressions. This assumes that we
// already verified that the expression refers only to
// key columns
short result = 0;
NABoolean exprIsValid = TRUE;
ItemExpr *missingConstHere = NULL;
ItemExpr *missingColHere = NULL;
ItemExpr *unsupportedExpr = NULL;
ItemExpr *topLevelCast = NULL;
NABoolean topLevelCastIsOk = FALSE;
const OperatorTypeEnum leafColType = ITM_NAMED_TYPE_TO_ITEM;
const NAType &origDivType = divExpr->getValueId().getType();
if (divExpr->getOperatorType() == ITM_CAST)
{
// a cast on top of the divisioning expr is allowed
// in limited cases
topLevelCast = divExpr;
divExpr = topLevelCast->child(0).getPtr();
}
// check the shape of the divisioning expression
switch (divExpr->getOperatorType())
{
case leafColType:
{
// a simple column is not allowed
exprIsValid = FALSE;
unsupportedExpr = divExpr;
}
break;
case ITM_EXTRACT: // for all variants except YEAR
case ITM_EXTRACT_ODBC: // for YEAR
{
// Allowed are:
// date_part('year', <arg>)
// date_part('yearquarter', <arg>)
// date_part('yearmonth', <arg>)
// date_part('yearquarterd', <arg>)
// date_part('yearmonthd', <arg>)
//
// <arg> can be one of the following:
// <col>
// add_months(<col>, <const> [, 0])
// <col> + <const>
// <col> - <const>
enum rec_datetime_field ef = ((Extract *) divExpr)->getExtractField();
if (ef == REC_DATE_YEAR ||
ef == REC_DATE_YEARQUARTER_EXTRACT ||
ef == REC_DATE_YEARMONTH_EXTRACT ||
ef == REC_DATE_YEARQUARTER_D_EXTRACT ||
ef == REC_DATE_YEARMONTH_D_EXTRACT)
{
// check for the <arg> syntax shown above
// Note that the parser changes ADD_MONTHS(a, b [,c]) into
// a + cast(b as interval)
if (divExpr->child(0)->getOperatorType() != leafColType)
{
if ((divExpr->child(0)->getOperatorType() == ITM_PLUS ||
divExpr->child(0)->getOperatorType() == ITM_MINUS) &&
divExpr->child(0)->child(0)->getOperatorType() == leafColType)
{
BiArith *plusMinus = (BiArith *) divExpr->child(0).getPtr();
ItemExpr *addedValue = plusMinus->child(1);
if (plusMinus->isKeepLastDay())
{
// we don't support keep last day normalization
// (1 as third argument to ADD_MONTHS)
exprIsValid = FALSE;
unsupportedExpr = plusMinus;
}
if (addedValue->getOperatorType() == ITM_CAST)
addedValue = addedValue->child(0);
if (addedValue->getOperatorType() == ITM_CAST)
addedValue = addedValue->child(0); // sometimes 2 casts are stacked here
if (NOT(addedValue->getOperatorType() == ITM_CONSTANT))
{
exprIsValid = FALSE;
missingConstHere = addedValue;
}
}
else
{
exprIsValid = FALSE;
missingColHere = divExpr->child(0);
}
}
}
else
{
// invalid type of extract field
exprIsValid = FALSE;
*CmpCommon::diags() << DgSqlCode(-4244);
}
}
break;
case ITM_DATE_TRUNC_MINUTE:
case ITM_DATE_TRUNC_SECOND:
case ITM_DATE_TRUNC_MONTH:
case ITM_DATE_TRUNC_HOUR:
case ITM_DATE_TRUNC_CENTURY:
case ITM_DATE_TRUNC_DECADE:
case ITM_DATE_TRUNC_YEAR:
case ITM_DATE_TRUNC_DAY:
{
// Allowed are:
// DATE_TRUNC(<string>, <col>)
if (divExpr->child(0)->getOperatorType() != leafColType)
{
exprIsValid = FALSE;
missingColHere = divExpr->child(0);
}
}
break;
case ITM_DATEDIFF_YEAR:
case ITM_DATEDIFF_QUARTER:
case ITM_DATEDIFF_WEEK:
case ITM_DATEDIFF_MONTH:
// Allowed are:
// DATEDIFF(<date-part>, <const>, <col>)
if (divExpr->child(0)->getOperatorType() != ITM_CONSTANT)
{
exprIsValid = FALSE;
missingConstHere = divExpr->child(1);
}
if (divExpr->child(1)->getOperatorType() != leafColType)
{
exprIsValid = FALSE;
missingColHere = divExpr->child(0);
}
break;
case ITM_YEARWEEK:
case ITM_YEARWEEKD:
{
// Allowed are:
// DATE_PART('YEARWEEK', <col>)
// DATE_PART('YEARWEEKD', <col>)
if (divExpr->child(0)->getOperatorType() != leafColType)
{
exprIsValid = FALSE;
missingColHere = divExpr->child(0);
}
}
break;
case ITM_DIVIDE:
{
// Allowed are:
// <col> [ + <const> ] / <const>
// cast(<col> [ + <const> ] / <const> as <numeric-type>)
//
// Note: cast (if present) is stored in topLevelCast, not divExpr
if (divExpr->child(0)->getOperatorType() != leafColType)
{
if (divExpr->child(0)->getOperatorType() == ITM_PLUS)
{
if (divExpr->child(0)->child(0)->getOperatorType() != leafColType)
{
exprIsValid = FALSE;
missingColHere = divExpr->child(0)->child(0);
}
if (divExpr->child(0)->child(1)->getOperatorType() != ITM_CONSTANT)
{
exprIsValid = FALSE;
missingConstHere = divExpr->child(0)->child(1);
}
}
else
{
exprIsValid = FALSE;
missingColHere = divExpr->child(0);
}
}
if (divExpr->child(1)->getOperatorType() != ITM_CONSTANT)
{
exprIsValid = FALSE;
missingConstHere = divExpr->child(1);
}
if (topLevelCast)
{
topLevelCastIsOk =
(topLevelCast->getValueId().getType().getTypeQualifier() == NA_NUMERIC_TYPE);
}
}
break;
case ITM_SUBSTR:
case ITM_LEFT:
{
// Allowed are:
// SUBSTRING(<col>, 1, <const>)
// SUBSTRING(<col> FROM 1 FOR <const>) (which is the same thing)
// LEFT(<col>, <const>)
if (divExpr->child(0)->getOperatorType() != leafColType)
{
if (divExpr->child(0)->getOperatorType() == ITM_CAST &&
divExpr->child(0)->child(0)->getOperatorType() == leafColType)
{
// tolerate a CAST(<basecolumn>), as long as it doesn't
// alter the data type
const CharType& tgtType =
(const CharType &) divExpr->child(0)->getValueId().getType();
const CharType& srcType =
(const CharType &) divExpr->child(0)->child(0)->getValueId().getType();
if (NOT(
srcType.getTypeQualifier() == NA_CHARACTER_TYPE &&
tgtType.getTypeQualifier() == NA_CHARACTER_TYPE &&
srcType.getCharSet() == tgtType.getCharSet() &&
srcType.getFSDatatype() == tgtType.getFSDatatype() &&
srcType.isVaryingLen() == tgtType.isVaryingLen()))
{
exprIsValid = FALSE;
// show the whole expression, the cast itself may
// not tell the user much, it may have been inserted
unsupportedExpr = divExpr;
}
}
else
{
exprIsValid = FALSE;
missingColHere = divExpr->child(0);
}
}
if (divExpr->child(1)->getOperatorType() != ITM_CONSTANT)
{
exprIsValid = FALSE;
missingConstHere = divExpr->child(1);
}
if (exprIsValid)
{
if (divExpr->getOperatorType() == ITM_LEFT)
{
// condition for LEFT: child 1 must be a constant
if (divExpr->child(1)->getOperatorType() != ITM_CONSTANT)
{
exprIsValid = FALSE;
missingConstHere = divExpr->child(2);
}
}
else
{
// additional conditions for SUBSTR: Second argument must be a
// constant and evaluate to 1, third argument needs to
// be present and be a constant
NABoolean negate = FALSE;
ConstValue *child1 = divExpr->child(1)->castToConstValue(negate);
Int64 child1Value = 0;
if (child1 && child1->canGetExactNumericValue())
child1Value = child1->getExactNumericValue();
if (child1Value != 1 OR
divExpr->getArity() != 3)
{
exprIsValid = FALSE;
unsupportedExpr = divExpr;
}
else if (divExpr->child(2)->getOperatorType() != ITM_CONSTANT)
{
exprIsValid = FALSE;
missingConstHere = divExpr->child(2);
}
}
}
}
break;
default:
{
// everything else is not allowed in DIVISION BY
exprIsValid = FALSE;
unsupportedExpr = divExpr;
}
}
if (topLevelCast && !topLevelCastIsOk)
{
exprIsValid = FALSE;
if (!missingConstHere && !missingColHere && !unsupportedExpr)
unsupportedExpr = topLevelCast;
}
if (NOT exprIsValid)
{
// common code for error handling
NAString unparsed;
result = -1;
if (missingConstHere)
{
missingConstHere->unparse(unparsed, BINDER_PHASE, COMPUTED_COLUMN_FORMAT);
*CmpCommon::diags() << DgSqlCode(-4241) << DgString0(unparsed);
}
if (missingColHere)
{
missingColHere->unparse(unparsed, BINDER_PHASE, COMPUTED_COLUMN_FORMAT);
*CmpCommon::diags() << DgSqlCode(-4242) << DgString0(unparsed);
}
if (unsupportedExpr)
{
// general error, this expression is not supported in DIVISION BY
unsupportedExpr->unparse(unparsed, BINDER_PHASE, COMPUTED_COLUMN_FORMAT);
*CmpCommon::diags() << DgSqlCode(-4243) << DgString0(unparsed);
}
}
if (origDivType.getTypeQualifier() == NA_NUMERIC_TYPE &&
!((NumericType &) origDivType).isExact())
{
// approximate numeric data types are not supported, since
// rounding errors could lead to incorrect computation of
// divisioning keys
result = -1;
*CmpCommon::diags() << DgSqlCode(-4257);
}
return result;
}
short CmpSeabaseDDL::createEncodedKeysBuffer(char** &encodedKeysBuffer,
int &numSplits,
TrafDesc * colDescs,
TrafDesc * keyDescs,
int numSaltPartitions,
Lng32 numSaltSplits,
NAString *splitByClause,
Lng32 numKeys,
Lng32 keyLength,
NABoolean isIndex)
{
encodedKeysBuffer = NULL;
numSplits = 0;
if (numSaltSplits <= 0)
return 0;
// make a list of NAStrings with the default values for start keys
NAString ** defaultSplits = createInArrayForLowOrHighKeys(
colDescs,
keyDescs,
numKeys,
FALSE,
isIndex,
STMTHEAP );
NAString **splitValuesAsText = new(STMTHEAP) NAString *[numKeys];
ElemDDLPartitionList * pPartitionList = NULL;
ElemDDLPartitionRange *pPartitionRange = NULL;
numSplits = numSaltSplits;
// for salt splits, only the first key column value
// is variable, the rest use the default values
for (int k=1; k<numKeys; k++)
splitValuesAsText[k] = defaultSplits[k];
// allocate the result buffers, numSplits buffers of length keyLength
encodedKeysBuffer = new (STMTHEAP) char*[numSplits];
for(int i =0; i < numSplits; i++)
encodedKeysBuffer[i] = new (STMTHEAP) char[keyLength];
char splitNumCharStr[10];
NAString splitNumString;
// loop over the splits, HBase will create 1 more region than the
// number of rows in the split array
for(Int32 i =0; i < numSplits; i++)
{
/* We are splitting along salt partitions. In the example below we have a
salt column and an integer column as the key. KeyLength is 4 + 4 = 8.
encodedKeysBuffer will have 4 elements, each of length 8. When this
buffer is given to HBase through the Java API we get a table with 5
regions (4 splits) and begin/end keys as shown below
Start Key End Key
\x00\x00\x00\x01\x00\x00\x00\x00
\x00\x00\x00\x01\x00\x00\x00\x00 \x00\x00\x00\x02\x00\x00\x00\x00
\x00\x00\x00\x02\x00\x00\x00\x00 \x00\x00\x00\x03\x00\x00\x00\x00
\x00\x00\x00\x03\x00\x00\x00\x00 \x00\x00\x00\x04\x00\x00\x00\x00
\x00\x00\x00\x04\x00\x00\x00\x00
When we have more salt partitions than regions, the salt values
will be distributed across the regions as evenly as possible
*/
snprintf(splitNumCharStr, sizeof(splitNumCharStr), "%d",
((i+1)*numSaltPartitions)/(numSaltSplits+1));
splitNumString = splitNumCharStr;
splitValuesAsText[0] = &splitNumString;
short retVal = 0;
// convert the array of NAStrings with textual values into
// an encoded binary key buffer
retVal = encodeKeyValues(colDescs,
keyDescs,
splitValuesAsText, // INPUT
isIndex,
FALSE, // encoding for Min Key
encodedKeysBuffer[i], // OUTPUT
STMTHEAP,
CmpCommon::diags());
if (retVal)
return -1;
// check whether the encoded keys are ascending
if (i > 0 &&
memcmp(encodedKeysBuffer[i-1],
encodedKeysBuffer[i],
keyLength) >= 0)
{
*CmpCommon::diags() << DgSqlCode(-1211)
<< DgInt0(i+1);
return -1;
}
} // loop over splits
return 0;
}
short CmpSeabaseDDL::dropSeabaseObject(ExpHbaseInterface * ehi,
const NAString &objName,
NAString &currCatName, NAString &currSchName,
const ComObjectType objType,
NABoolean ddlXns,
NABoolean dropFromMD,
NABoolean dropFromHbase)
{
Lng32 retcode = 0;
ComObjectName tableName(objName);
ComAnsiNamePart currCatAnsiName(currCatName);
ComAnsiNamePart currSchAnsiName(currSchName);
tableName.applyDefaults(currCatAnsiName, currSchAnsiName);
const NAString catalogNamePart = tableName.getCatalogNamePartAsAnsiString();
const NAString schemaNamePart = tableName.getSchemaNamePartAsAnsiString(TRUE);
const NAString objectNamePart = tableName.getObjectNamePartAsAnsiString(TRUE);
NAString extTableName = tableName.getExternalName(TRUE);
const NAString extNameForHbase = catalogNamePart + "." + schemaNamePart + "." + objectNamePart;
ExeCliInterface cliInterface(STMTHEAP, 0, NULL,
CmpCommon::context()->sqlSession()->getParentQid() );
if (dropFromMD)
{
if (isAuthorizationEnabled())
{
NABoolean isHive = FALSE;
NAString hiveNativeName;
Int32 objOwnerID = 0;
Int32 schemaOwnerID = 0;
Int64 objectFlags = 0;
Int64 objUID = -1;
// remove priv info if this hive table is not registered in traf
// metadata. Could happen for hive external tables created prior
// to hive registration support.
if ((ComIsTrafodionExternalSchemaName(schemaNamePart, &isHive)) &&
(isHive))
{
NAString quotedSchemaName;
quotedSchemaName = '\"';
quotedSchemaName += schemaNamePart;
quotedSchemaName += '\"';
hiveNativeName = ComConvertTrafNameToNativeName(
catalogNamePart, quotedSchemaName, objectNamePart);
// see if this hive table has been registered in traf metadata
ComObjectName hiveTableName(hiveNativeName);
const NAString hiveCatName = hiveTableName.getCatalogNamePartAsAnsiString();
const NAString hiveSchName = hiveTableName.getSchemaNamePartAsAnsiString();
const NAString hiveObjName = hiveTableName.getObjectNamePartAsAnsiString();
CorrName cn(hiveObjName, STMTHEAP, hiveSchName, hiveCatName);
BindWA bindWA(ActiveSchemaDB(),CmpCommon::context(),FALSE/*inDDL*/);
NATable *naTable = bindWA.getNATableInternal(cn);
if ((naTable) && (naTable->isHiveTable()))
{
if (NOT naTable->isRegistered())
{
objUID = naTable->objectUid().get_value();
extTableName = hiveTableName.getExternalName(TRUE);
objOwnerID = naTable->getOwner();
schemaOwnerID = naTable->getSchemaOwner();
}
}
}
// Revoke owner privileges for object
// it would be more efficient to pass in the object owner and UID
// than to do an extra I/O.
if (objUID < 0)
{
objUID = getObjectInfo(&cliInterface,
catalogNamePart.data(), schemaNamePart.data(),
objectNamePart.data(), objType,
objOwnerID,schemaOwnerID,objectFlags);
}
if (objUID < 0 || objOwnerID == 0)
{ //TODO: Internal error?
return -1;
}
if (!deletePrivMgrInfo ( extTableName, objUID, objType ))
{
return -1;
}
}
if (deleteFromSeabaseMDTable(&cliInterface,
catalogNamePart, schemaNamePart, objectNamePart, objType ))
return -1;
}
if (dropFromHbase)
{
if (objType != COM_VIEW_OBJECT)
{
HbaseStr hbaseTable;
hbaseTable.val = (char*)extNameForHbase.data();
hbaseTable.len = extNameForHbase.length();
retcode = dropHbaseTable(ehi, &hbaseTable, FALSE, ddlXns);
if (retcode < 0)
{
return -1;
}
}
}
return 0;
}
short CmpSeabaseDDL::dropSeabaseStats(ExeCliInterface *cliInterface,
const char * catName,
const char * schName,
Int64 tableUID)
{
Lng32 cliRC = 0;
char buf[4000];
// delete any histogram statistics
str_sprintf(buf, "delete from %s.\"%s\".%s where table_uid = %ld",
catName, schName, HBASE_HIST_NAME, tableUID);
cliRC = cliInterface->executeImmediate(buf);
// If the histogram table does not exist, don't bother checking
// the histogram intervals table.
//
// Note: cliRC == 100 happens when we delete some histogram rows
// and also when there are no histogram rows to delete, so we
// can't decide based on that.
if (cliRC != -4082)
{
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
str_sprintf(buf, "delete from %s.\"%s\".%s where table_uid = %ld",
catName, schName, HBASE_HISTINT_NAME, tableUID);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
}
// Drop any persistent sample tables also. (It is possible that these
// might exist even if the histograms table does not exist.)
// Delete the row in the persistent_samples table if one exists
str_sprintf(buf, "select translate(sample_name using ucs2toutf8) from "
" (delete from %s.\"%s\".%s where table_uid = %ld) as t",
catName, schName, HBASE_PERS_SAMP_NAME, tableUID);
Lng32 len = 0;
char sampleTableName[1000];
cliRC = cliInterface->executeImmediate(buf, (char*)&sampleTableName, &len, FALSE);
if (cliRC == -4082) // if persistent_samples table does not exist
cliRC = 0; // then there isn't a persistent sample table
else if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
else if ((len > 0) && (sampleTableName[0])) // if we got a sample table name back
{
// try to drop the sample table
sampleTableName[len] = '\0';
str_sprintf(buf, "drop table %s", sampleTableName);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
}
return 0;
}
short CmpSeabaseDDL::updateSeabaseVersions(
ExeCliInterface *cliInterface,
const char* sysCat,
Lng32 majorVersion)
{
Lng32 cliRC = 0;
char buf[4000];
str_sprintf(buf, "delete from %s.\"%s\".%s ",
sysCat, SEABASE_MD_SCHEMA, SEABASE_VERSIONS);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
Int64 initTime = NA_JulianTimestamp();
str_sprintf(buf, "insert into %s.\"%s\".%s values ('METADATA', %d, %d, %ld, 'initialize trafodion'), ('DATAFORMAT', %d, %d, %ld, 'initialize trafodion'), ('SOFTWARE', %d, %d, %ld, 'initialize trafodion') ",
sysCat, SEABASE_MD_SCHEMA, SEABASE_VERSIONS,
(majorVersion != -1 ? majorVersion : METADATA_MAJOR_VERSION),
(METADATA_MINOR_VERSION * 10 + METADATA_UPDATE_VERSION), initTime,
DATAFORMAT_MAJOR_VERSION, DATAFORMAT_MINOR_VERSION, initTime,
SOFTWARE_MAJOR_VERSION,
(SOFTWARE_MINOR_VERSION * 10 + SOFTWARE_UPDATE_VERSION), initTime);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
return 0;
}
short CmpSeabaseDDL::updateSeabaseAuths(
ExeCliInterface *cliInterface,
const char* sysCat)
{
Lng32 cliRC = 0;
char buf[4000];
str_sprintf(buf, "delete from %s.\"%s\".%s ",
sysCat, SEABASE_MD_SCHEMA, SEABASE_AUTHS);
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
Int64 initTime = NA_JulianTimestamp();
NAString mdLocation;
CONCAT_CATSCH(mdLocation, getSystemCatalog(), SEABASE_MD_SCHEMA);
CmpSeabaseDDLuser authOperation(sysCat, mdLocation.data());
authOperation.registerStandardUser(DB__ROOT, ROOT_USER_ID);
if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_))
return -1;
return 0;
}
/*
// This method has been rewritten and moved to CmpSeabaseDDLinitraf.cpp.
void CmpSeabaseDDL::initSeabaseMD(NABoolean ddlXns, NABoolean minimal)
New method is called initTrafMD.
*/
void CmpSeabaseDDL::createSeabaseMDviews()
{
if (!ComUser::isRootUserID())
{
*CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
return;
}
Lng32 retcode = 0;
Lng32 cliRC = 0;
ExeCliInterface cliInterface(STMTHEAP, 0, NULL,
CmpCommon::context()->sqlSession()->getParentQid());
if ((CmpCommon::context()->isUninitializedSeabase()) &&
(CmpCommon::context()->uninitializedSeabaseErrNum() == -TRAF_NOT_INITIALIZED))
{
*CmpCommon::diags() << DgSqlCode(-TRAF_NOT_INITIALIZED);
return;
}
if (createMetadataViews(&cliInterface))
{
return;
}
}
void CmpSeabaseDDL::dropSeabaseMDviews()
{
// verify user is authorized
if (!ComUser::isRootUserID())
{
*CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
return;
}
Lng32 retcode = 0;
Lng32 cliRC = 0;
ExeCliInterface cliInterface(STMTHEAP, 0, NULL,
CmpCommon::context()->sqlSession()->getParentQid());
if ((CmpCommon::context()->isUninitializedSeabase()) &&
(CmpCommon::context()->uninitializedSeabaseErrNum() == -TRAF_NOT_INITIALIZED))
{
*CmpCommon::diags() << DgSqlCode(-TRAF_NOT_INITIALIZED);
return;
}
if (dropMetadataViews(&cliInterface))
{
return;
}
}
void CmpSeabaseDDL::createSeabaseSchemaObjects()
{
if (!ComUser::isRootUserID())
{
*CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
return;
}
Lng32 retcode = 0;
Lng32 cliRC = 0;
ExeCliInterface cliInterface(STMTHEAP, 0, NULL,
CmpCommon::context()->sqlSession()->getParentQid());
if ((CmpCommon::context()->isUninitializedSeabase()) &&
(CmpCommon::context()->uninitializedSeabaseErrNum() == -TRAF_NOT_INITIALIZED))
{
*CmpCommon::diags() << DgSqlCode(-TRAF_NOT_INITIALIZED);
return;
}
if (createSchemaObjects(&cliInterface))
{
return;
}
}
short CmpSeabaseDDL::createDefaultSystemSchema(ExeCliInterface *cliInterface)
{
Lng32 cliRC = 0;
char buf[4000];
str_sprintf(buf,"create shared schema " TRAFODION_SYSCAT_LIT"." SEABASE_SYSTEM_SCHEMA" ");
cliRC = cliInterface->executeImmediate(buf);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
return 0;
}
short CmpSeabaseDDL::createSchemaObjects(ExeCliInterface *cliInterface)
{
Lng32 retcode = 0;
Lng32 cliRC = 0;
char buf[4000];
str_sprintf(buf,"SELECT DISTINCT TRIM(CATALOG_NAME), TRIM(SCHEMA_NAME) FROM %s.%s ",
getMDSchema(),SEABASE_OBJECTS);
Queue * queue = NULL;
cliRC = cliInterface->fetchAllRows(queue,buf,0,false,false,true);
if (cliRC < 0)
{
cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
return -1;
}
if (cliRC == 100) // did not find the row
{
cliInterface->clearGlobalDiags();
return 0;
}
if (queue == NULL)
return -1;
std::vector<QualifiedSchema> schemaNames;
queue->position();
for (size_t r = 0; r < queue->numEntries(); r++)
{
OutputInfo * cliInterface = (OutputInfo*)queue->getNext();
QualifiedSchema qualifiedSchema;
char *ptr;
Int32 length;
char value[ComMAX_ANSI_IDENTIFIER_INTERNAL_LEN + 1];
// column 1: CATALOG_NAME
cliInterface->get(0,ptr,length);
strncpy(value,ptr,length);
value[length] = 0;
strcpy(qualifiedSchema.catalogName,value);
// column 2: SCHEMA_NAME
cliInterface->get(1,ptr,length);
strncpy(value,ptr,length);
value[length] = 0;
strcpy(qualifiedSchema.schemaName,value);
schemaNames.push_back(qualifiedSchema);
}
NABoolean xnWasStartedHere = false;
if (beginXnIfNotInProgress(cliInterface, xnWasStartedHere))
return -1;
// save the current parserflags setting
ULng32 savedParserFlags = Get_SqlParser_Flags(0xFFFFFFFF);
Set_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL);
for (size_t s = 0; s < schemaNames.size(); s++)
{
QualifiedSchema schemaEntry = schemaNames[s];
// Ignore if entry already exists.
if (existsInSeabaseMDTable(cliInterface,schemaEntry.catalogName,
schemaEntry.schemaName,
SEABASE_SCHEMA_OBJECTNAME))
continue;
// Catalog or schema names could be delimited names. Surround them
// in quotes to avoid scanning problems.
NAString quotedCatalogName;
quotedCatalogName = '\"';
quotedCatalogName += schemaEntry.catalogName;
quotedCatalogName += '\"';
NAString quotedSchemaName;
quotedSchemaName = '\"';
quotedSchemaName += schemaEntry.schemaName;
quotedSchemaName += '\"';
ComSchemaName schemaName(quotedCatalogName,quotedSchemaName);
if (addSchemaObject(*cliInterface,schemaName,
COM_SCHEMA_CLASS_SHARED,SUPER_USER, FALSE))
{
// Restore parser flags settings to what they originally were
Assign_SqlParser_Flags(savedParserFlags);
return -1;
}
}
// Restore parser flags settings to what they originally were
Assign_SqlParser_Flags(savedParserFlags);
if (endXnIfStartedHere(cliInterface, xnWasStartedHere, 0) < 0)
return -1;
return 0;
}
// ----------------------------------------------------------------------------
// method: createPrivMgrRepos
//
// This method is called during initialize trafodion to create the privilege
// manager repository.
//
// Params:
// cliInterface - pointer to a CLI helper class
//
// returns:
// 0: successful
// -1: failed
//
// The diags area is populated with any unexpected errors
// ----------------------------------------------------------------------------
short CmpSeabaseDDL::createPrivMgrRepos(ExeCliInterface *cliInterface,
NABoolean ddlXns)
{
std::vector<std::string> tablesCreated;
std::vector<std::string> tablesUpgraded;
if (initSeabaseAuthorization(cliInterface, ddlXns,
tablesCreated, tablesUpgraded) < 0)
return -1;
return 0;
}
void CmpSeabaseDDL::createSeabaseSequence(StmtDDLCreateSequence * createSequenceNode,
NAString &currCatName, NAString &currSchName)
{
Lng32 cliRC;
Lng32 retcode;
char buf[4000];
NAString sequenceName = (NAString&)createSequenceNode->getSeqName();
ComObjectName seqName(sequenceName, COM_TABLE_NAME);
ComAnsiNamePart currCatAnsiName(currCatName);
ComAnsiNamePart currSchAnsiName(currSchName);
seqName.applyDefaults(currCatAnsiName, currSchAnsiName);
NAString catalogNamePart = seqName.getCatalogNamePartAsAnsiString();
NAString schemaNamePart = seqName.getSchemaNamePartAsAnsiString(TRUE);
NAString seqNamePart = seqName.getObjectNamePartAsAnsiString(TRUE);
const NAString extSeqName = seqName.getExternalName(TRUE);
ElemDDLSGOptions * sgo = createSequenceNode->getSGoptions();
ExeCliInterface cliInterface(STMTHEAP, 0, NULL,
CmpCommon::context()->sqlSession()->getParentQid());
// Verify that the current user has authority to perform operation
Int32 objectOwnerID;
Int32 schemaOwnerID;
ComSchemaClass schemaClass;
retcode = verifyDDLCreateOperationAuthorized(&cliInterface,
SQLOperation::CREATE_SEQUENCE,
catalogNamePart,
schemaNamePart,
schemaClass,
objectOwnerID,
schemaOwnerID);
if (retcode != 0)
{
handleDDLCreateAuthorizationError(retcode,catalogNamePart,schemaNamePart);
processReturn();
return;
}
if (isSeabaseReservedSchema(seqName))
{
*CmpCommon::diags() << DgSqlCode(-CAT_CREATE_TABLE_NOT_ALLOWED_IN_SMD)
<< DgTableName(extSeqName);
processReturn();
return;
}
retcode = existsInSeabaseMDTable(&cliInterface,
catalogNamePart, schemaNamePart, seqNamePart);
if (retcode < 0)
{
processReturn();
return;
}
if (retcode == 1) // already exists
{
*CmpCommon::diags() << DgSqlCode(-1390)
<< DgString0(extSeqName);
processReturn();
return;
}
ComUID seqUID;
seqUID.make_UID();
Int64 seqObjUID = seqUID.get_value();
Int64 createTime = NA_JulianTimestamp();
NAString quotedSchName;
ToQuotedString(quotedSchName, schemaNamePart, FALSE);
NAString quotedSeqObjName;
ToQuotedString(quotedSeqObjName, seqNamePart, FALSE);
Int32 objOwner = ComUser::getCurrentUser();
str_sprintf(buf, "insert into %s.\"%s\".%s values ('%s', '%s', '%s', '%s', %ld, %ld, %ld, '%s', '%s', %d, %d, 0)",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS,
catalogNamePart.data(), quotedSchName.data(), quotedSeqObjName.data(),
COM_SEQUENCE_GENERATOR_OBJECT_LIT,
seqObjUID,
createTime,
createTime,
COM_YES_LIT,
COM_NO_LIT,
objectOwnerID,
schemaOwnerID);
cliRC = cliInterface.executeImmediate(buf);
if (cliRC < 0)
{
cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
return;
}
str_sprintf(buf, "insert into %s.\"%s\".%s values ('%s', %ld, %d, %ld, %ld, %ld, %ld, '%s', %ld, %ld, %ld, %ld, %ld, 0)",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_SEQ_GEN,
(sgo->isExternalSG() ? COM_EXTERNAL_SG_LIT : COM_INTERNAL_SG_LIT),
seqObjUID,
sgo->getFSDataType(), //REC_BIN64_SIGNED,
sgo->getStartValue(),
sgo->getIncrement(),
sgo->getMaxValue(),
sgo->getMinValue(),
(sgo->getCycle() ? COM_YES_LIT : COM_NO_LIT),
sgo->getCache(),
sgo->getStartValue(),
0L,
createTime,
0L);
cliRC = cliInterface.executeImmediate(buf);
if (cliRC < 0)
{
cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
return;
}
// Add privileges for the sequence
if (!insertPrivMgrInfo(seqObjUID,
extSeqName,
COM_SEQUENCE_GENERATOR_OBJECT,
objectOwnerID,
schemaOwnerID,
ComUser::getCurrentUser()))
{
*CmpCommon::diags()
<< DgSqlCode(-CAT_UNABLE_TO_GRANT_PRIVILEGES)
<< DgTableName(extSeqName);
processReturn();
return;
}
return;
}
void CmpSeabaseDDL::alterSeabaseSequence(StmtDDLCreateSequence * alterSequenceNode,
NAString &currCatName, NAString &currSchName)
{
Lng32 cliRC;
Lng32 retcode;
char buf[4000];
NAString sequenceName = (NAString&)alterSequenceNode->getSeqName();
ComObjectName seqName(sequenceName, COM_TABLE_NAME);
ComAnsiNamePart currCatAnsiName(currCatName);
ComAnsiNamePart currSchAnsiName(currSchName);
seqName.applyDefaults(currCatAnsiName, currSchAnsiName);
NAString catalogNamePart = seqName.getCatalogNamePartAsAnsiString();
NAString schemaNamePart = seqName.getSchemaNamePartAsAnsiString(TRUE);
NAString seqNamePart = seqName.getObjectNamePartAsAnsiString(TRUE);
const NAString extSeqName = seqName.getExternalName(TRUE);
ElemDDLSGOptions * sgo = alterSequenceNode->getSGoptions();
ExeCliInterface cliInterface(STMTHEAP, 0, NULL,
CmpCommon::context()->sqlSession()->getParentQid());
retcode = existsInSeabaseMDTable(&cliInterface,
catalogNamePart, schemaNamePart, seqNamePart);
if (retcode < 0)
{
processReturn();
return;
}
if (retcode == 0) // does not exist
{
CmpCommon::diags()->clear();
*CmpCommon::diags() << DgSqlCode(-1389)
<< DgString0(extSeqName);
processReturn();
return;
}
Int32 objectOwnerID = 0;
Int32 schemaOwnerID = 0;
Int64 objectFlags = 0;
Int64 seqUID = getObjectInfo(&cliInterface,
catalogNamePart.data(), schemaNamePart.data(),
seqNamePart.data(), COM_SEQUENCE_GENERATOR_OBJECT,
objectOwnerID,schemaOwnerID,objectFlags);
// Check for error getting metadata information
if (seqUID == -1 || objectOwnerID == 0)
{
if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
SEABASEDDL_INTERNAL_ERROR("getting object UID and owner for alter sequence");
processReturn();
return;
}
// Verify that the current user has authority to perform operation
if (!isDDLOperationAuthorized(SQLOperation::ALTER_SEQUENCE,
objectOwnerID,schemaOwnerID))
{
*CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
processReturn();
return;
}
char setOptions[2000];
char tmpBuf[1000];
strcpy(setOptions, " set ");
if (sgo->isIncrementSpecified())
{
str_sprintf(tmpBuf, " increment = %ld,", sgo->getIncrement());
strcat(setOptions, tmpBuf);
}
if (sgo->isMaxValueSpecified())
{
str_sprintf(tmpBuf, " max_value = %ld,", sgo->getMaxValue());
strcat(setOptions, tmpBuf);
}
if (sgo->isMinValueSpecified())
{
str_sprintf(tmpBuf, " min_value = %ld,", sgo->getMinValue());
strcat(setOptions, tmpBuf);
}
if (sgo->isCacheSpecified())
{
str_sprintf(tmpBuf, " cache_size = %ld,", sgo->getCache());
strcat(setOptions, tmpBuf);
}
if (sgo->isCycleSpecified())
{
str_sprintf(tmpBuf, " cycle_option = '%s',", (sgo->getCycle() ? "Y" : "N"));
strcat(setOptions, tmpBuf);
}
if (sgo->isResetSpecified())
{
str_sprintf(tmpBuf, " next_value = start_value, num_calls = 0, ");
strcat(setOptions, tmpBuf);
}
Int64 redefTime = NA_JulianTimestamp();
str_sprintf(tmpBuf, " redef_ts = %ld", redefTime);
strcat(setOptions, tmpBuf);
str_sprintf(buf, "update %s.\"%s\".%s %s where seq_uid = %ld",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_SEQ_GEN,
setOptions,
seqUID);
cliRC = cliInterface.executeImmediate(buf);
if (cliRC < 0)
{
cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
return;
}
if (updateObjectRedefTime(&cliInterface,
catalogNamePart, schemaNamePart, seqNamePart,
COM_SEQUENCE_GENERATOR_OBJECT_LIT,
redefTime))
{
processReturn();
return;
}
CorrName cn(seqNamePart, STMTHEAP, schemaNamePart, catalogNamePart);
cn.setSpecialType(ExtendedQualName::SG_TABLE);
ActiveSchemaDB()->getNATableDB()->removeNATable
(cn,
ComQiScope::REMOVE_FROM_ALL_USERS, COM_SEQUENCE_GENERATOR_OBJECT,
alterSequenceNode->ddlXns(), FALSE);
return;
}
void CmpSeabaseDDL::dropSeabaseSequence(StmtDDLDropSequence * dropSequenceNode,
NAString &currCatName, NAString &currSchName)
{
Lng32 cliRC = 0;
Lng32 retcode = 0;
NAString sequenceName = (NAString&)dropSequenceNode->getSeqName();
ComObjectName seqName(sequenceName, COM_TABLE_NAME);
ComAnsiNamePart currCatAnsiName(currCatName);
ComAnsiNamePart currSchAnsiName(currSchName);
seqName.applyDefaults(currCatAnsiName, currSchAnsiName);
NAString catalogNamePart = seqName.getCatalogNamePartAsAnsiString();
NAString schemaNamePart = seqName.getSchemaNamePartAsAnsiString(TRUE);
NAString objectNamePart = seqName.getObjectNamePartAsAnsiString(TRUE);
const NAString extSeqName = seqName.getExternalName(TRUE);
ExeCliInterface cliInterface(STMTHEAP, 0, NULL,
CmpCommon::context()->sqlSession()->getParentQid());
retcode = existsInSeabaseMDTable(&cliInterface,
catalogNamePart, schemaNamePart, objectNamePart);
if (retcode < 0)
{
processReturn();
return;
}
if (retcode == 0) // does not exist
{
CmpCommon::diags()->clear();
*CmpCommon::diags() << DgSqlCode(-1389)
<< DgString0(extSeqName);
processReturn();
return;
}
// remove any privileges
if (isAuthorizationEnabled())
{
Int32 objectOwnerID = 0;
Int32 schemaOwnerID = 0;
Int64 objectFlags = 0;
Int64 seqUID = getObjectInfo(&cliInterface,
catalogNamePart.data(), schemaNamePart.data(),
objectNamePart.data(), COM_SEQUENCE_GENERATOR_OBJECT,
objectOwnerID,schemaOwnerID,objectFlags);
// Check for error getting metadata information
if (seqUID == -1 || objectOwnerID == 0)
{
if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
SEABASEDDL_INTERNAL_ERROR("getting object UID and owner for drop sequence");
processReturn();
return;
}
// Check to see if the user has the authority to drop the table
if (!isDDLOperationAuthorized(SQLOperation::DROP_SEQUENCE,objectOwnerID,
schemaOwnerID))
{
*CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
processReturn ();
return;
}
if (!deletePrivMgrInfo ( objectNamePart,
seqUID,
COM_SEQUENCE_GENERATOR_OBJECT ))
{
*CmpCommon::diags() << DgSqlCode(-CAT_NOT_ALL_PRIVILEGES_REVOKED);
processReturn();
return;
}
}
if (deleteFromSeabaseMDTable(&cliInterface,
catalogNamePart, schemaNamePart, objectNamePart,
COM_SEQUENCE_GENERATOR_OBJECT))
return;
CorrName cn(objectNamePart, STMTHEAP, schemaNamePart, catalogNamePart);
cn.setSpecialType(ExtendedQualName::SG_TABLE);
ActiveSchemaDB()->getNATableDB()->removeNATable
(cn,
ComQiScope::REMOVE_FROM_ALL_USERS, COM_SEQUENCE_GENERATOR_OBJECT,
dropSequenceNode->ddlXns(), FALSE);
return;
}
short CmpSeabaseDDL::dropSeabaseObjectsFromHbase(const char * pattern,
NABoolean ddlXns)
{
ExpHbaseInterface * ehi = allocEHI();
if (ehi == NULL)
return -1;
short retcode = ehi->dropAll(pattern, FALSE, (NOT ddlXns));
if (retcode < 0)
{
*CmpCommon::diags() << DgSqlCode(-8448)
<< DgString0((char*)"ExpHbaseInterface::dropAll()")
<< DgString1(getHbaseErrStr(-retcode))
<< DgInt0(-retcode)
<< DgString2((char*)GetCliGlobals()->getJniErrorStr());
return retcode;
}
return 0;
}
void CmpSeabaseDDL::dropSeabaseMD(NABoolean ddlXns)
{
// verify user is authorized
if (!ComUser::isRootUserID())
{
*CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
return;
}
Lng32 cliRC;
Lng32 retcode = 0;
NABoolean xnWasStartedHere = FALSE;
if ((CmpCommon::context()->isUninitializedSeabase()) &&
(CmpCommon::context()->uninitializedSeabaseErrNum() == -TRAF_NOT_INITIALIZED))
{
*CmpCommon::diags() << DgSqlCode(-TRAF_NOT_INITIALIZED);
return;
}
// drop all objects that match the pattern "TRAFODION.*"
dropSeabaseObjectsFromHbase("TRAFODION\\..*", ddlXns);
//drop all lob data and descriptor files
dropLOBHdfsFiles();
CmpCommon::context()->setIsUninitializedSeabase(TRUE);
CmpCommon::context()->uninitializedSeabaseErrNum() = -TRAF_NOT_INITIALIZED;
CmpCommon::context()->setIsAuthorizationEnabled(FALSE);
// kill child arkcmp process. It would ensure that a subsequent
// query, if sent to arkcmp, doesnt get stale information. After restart,
// the new arkcmp will cause its context to have uninitialized state.
// Note: TESTEXIT command only works if issued internally.
ExeCliInterface cliInterface(STMTHEAP, NULL, NULL);
cliInterface.executeImmediate("SELECT TESTEXIT;");
cliInterface.clearGlobalDiags();
return;
}
void CmpSeabaseDDL::dropLOBHdfsFiles()
{
NAString lobHdfsServer;
CmpCommon::getDefault(LOB_HDFS_SERVER,lobHdfsServer,FALSE);
Int32 lobHdfsPort = CmpCommon::getDefaultNumeric(LOB_HDFS_PORT);
NAString lobHdfsLoc;
CmpCommon::getDefault(LOB_STORAGE_FILE_DIR,lobHdfsLoc,FALSE);
cleanupLOBDataDescFiles(lobHdfsServer,lobHdfsPort,lobHdfsLoc);
}
NABoolean CmpSeabaseDDL::appendErrorObjName(char * errorObjs,
const char * objName)
{
if ((strlen(errorObjs) + strlen(objName)) < 1000)
{
strcat(errorObjs, objName);
strcat(errorObjs, " ");
}
else if (strlen(errorObjs) < 1005) // errorObjs maxlen = 1010
{
strcat(errorObjs, "...");
}
return TRUE;
}
// ----------------------------------------------------------------------------
// method: initSeabaseAuthorization
//
// This method:
// creates privilege manager metadata, if it does not yet exist
// upgrades privilege manager metadata, if it already exists
//
// Params:
// cliInterface - a pointer to a CLI helper class
// ddlXns - TRUE if DDL transactions is enabled
// tablesCreated - the list of tables that were created
// tablesUpgraded - the list of tables that were upgraded
//
// returns
// 0: successful
// -1: failed
//
// The diags area is populated with any unexpected errors
// ----------------------------------------------------------------------------
short CmpSeabaseDDL::initSeabaseAuthorization(
ExeCliInterface *cliInterface,
NABoolean ddlXns,
std::vector<std::string> &tablesCreated,
std::vector<std::string> &tablesUpgraded)
{
Lng32 cliRC = 0;
NABoolean xnWasStartedHere = FALSE;
if (!ComUser::isRootUserID())
{
*CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
return -1;
}
if (NOT ddlXns)
{
if (beginXnIfNotInProgress(cliInterface, xnWasStartedHere))
{
SEABASEDDL_INTERNAL_ERROR("initialize authorization");
return -1;
}
}
NAString mdLocation;
CONCAT_CATSCH(mdLocation, getSystemCatalog(), SEABASE_MD_SCHEMA);
NAString objectsLocation = mdLocation + NAString(".") + SEABASE_OBJECTS;
NAString authsLocation = mdLocation + NAString(".") + SEABASE_AUTHS;
NAString colsLocation = mdLocation + NAString(".") + SEABASE_COLUMNS ;
NAString privMgrMDLoc;
CONCAT_CATSCH(privMgrMDLoc, getSystemCatalog(), SEABASE_PRIVMGR_SCHEMA);
PrivMgrCommands privInterface(std::string(privMgrMDLoc.data()), CmpCommon::diags());
PrivStatus retcode = privInterface.initializeAuthorizationMetadata
(std::string(objectsLocation.data()),
std::string(authsLocation.data()),
std::string(colsLocation.data()),
tablesCreated, tablesUpgraded);
if (retcode == STATUS_ERROR)
{
// make sure authorization status is FALSE in compiler context
GetCliGlobals()->currContext()->setAuthStateInCmpContexts(FALSE, FALSE);
// If not running in DDL transactions, drop any tables were created
// Ignore any returned errors
if (NOT ddlXns)
{
bool doCleanup = true;
retcode = privInterface.dropAuthorizationMetadata(doCleanup);
}
// Add an error if none yet defined in the diags area
if ( CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
SEABASEDDL_INTERNAL_ERROR("initialize authorization");
return -1;
}
// If DDL transactions are not enabled, commit the transaction so privmgr
// schema exists in other processes
if (NOT ddlXns)
{
endXnIfStartedHere(cliInterface, xnWasStartedHere, 0);
if (beginXnIfNotInProgress(cliInterface, xnWasStartedHere))
{
SEABASEDDL_INTERNAL_ERROR("initialize authorization");
return -1;
}
}
// change authorization status in compiler contexts
CmpCommon::context()->setAuthorizationState (1);
GetCliGlobals()->currContext()->setAuthStateInCmpContexts(TRUE, TRUE);
// change authorization status in compiler processes
cliRC = GetCliGlobals()->currContext()->updateMxcmpSession();
if (cliRC == -1)
{
if ( CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
SEABASEDDL_INTERNAL_ERROR("initialize authorization - updating authorization state failed");
}
NABoolean warnings = FALSE;
// Adjust hive external table ownership - if someone creates external
// tables before initializing authorization, the external schemas are
// owned by DB__ROOT -> change to DB__HIVEROLE.
// Also if you have initialized authorization and created external tables
// before the fix for JIRA 1895, rerunning initialize authorization will
// fix the metadata inconsistencies
if (adjustHiveExternalSchemas(cliInterface) != 0)
warnings = TRUE;
// If someone initializes trafodion with library management but does not
// initialize authorization, then the role DB__LIBMGRROLE has not been
// granted to LIBMGR procedures. Do this now
cliRC = existsInSeabaseMDTable(cliInterface,
getSystemCatalog(), SEABASE_LIBMGR_SCHEMA,
SEABASE_LIBMGR_LIBRARY,
COM_LIBRARY_OBJECT, TRUE, FALSE);
if (cliRC == 1) // library exists
{
cliRC = grantLibmgrPrivs(cliInterface);
if (cliRC == -1)
warnings = TRUE;
}
if (NOT ddlXns)
endXnIfStartedHere(cliInterface, xnWasStartedHere, cliRC);
// If not able to adjust hive ownership or grant library management privs
// allow operation to continue but return issues as warnings.
if (warnings)
{
CmpCommon::diags()->negateAllErrors();
*CmpCommon::diags() << DgSqlCode(CAT_AUTH_COMPLETED_WITH_WARNINGS);
}
return 0;
}
void CmpSeabaseDDL::dropSeabaseAuthorization(
ExeCliInterface *cliInterface,
NABoolean doCleanup)
{
if (!ComUser::isRootUserID())
{
*CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
return;
}
NAString privMgrMDLoc;
CONCAT_CATSCH(privMgrMDLoc, getSystemCatalog(), SEABASE_PRIVMGR_SCHEMA);
PrivMgrCommands privInterface(std::string(privMgrMDLoc.data()), CmpCommon::diags());
PrivStatus retcode = privInterface.dropAuthorizationMetadata(doCleanup);
if (retcode == STATUS_ERROR)
{
if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
SEABASEDDL_INTERNAL_ERROR("drop authorization");
return;
}
// Turn off authorization in compiler contexts
GetCliGlobals()->currContext()->setAuthStateInCmpContexts(FALSE, FALSE);
// Turn off authorization in arkcmp processes
Int32 cliRC = GetCliGlobals()->currContext()->updateMxcmpSession();
if (cliRC == -1)
{
if ( CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
SEABASEDDL_INTERNAL_ERROR("drop authorization - updating authorization state failed");
}
return;
}
// ----------------------------------------------------------------------------
// method: insertPrivMgrInfo
//
// this method calls the privilege manager interface to perform privilege
// grants that are required for the object owner.
//
// input: the object's UID, name, type, owner, schema owner, and creator
//
// returns:
// TRUE if the privileges were successfully inserted (granted)
// FALSE if an error occurred (ComDiags is set up with the error)
// ----------------------------------------------------------------------------
NABoolean CmpSeabaseDDL::insertPrivMgrInfo(const Int64 objUID,
const NAString &objName,
const ComObjectType objectType,
const Int32 objOwnerID,
const Int32 schemaOwnerID,
const Int32 creatorID)
{
if (!PrivMgr::isSecurableObject(objectType))
return TRUE;
// Traf view privileges are handled differently than other objects. For views,
// the creator does not automatically get all privileges. Therefore, view
// owner privileges are not granted through this mechanism -
// see gatherViewPrivileges for details on how owner privileges are
// calculated and granted.
// Hive views are created outside of trafodion. They are treated like base
// table objects.
// Return TRUE if traf views.
if (objectType == COM_VIEW_OBJECT)
{
ComObjectName viewName(objName, COM_TABLE_NAME);
if (viewName.getCatalogNamePartAsAnsiString() == TRAFODION_SYSCAT_LIT)
return TRUE;
}
// If authorization is not enabled, return TRUE, no grants are needed
if (!isAuthorizationEnabled())
return TRUE;
// get the username from the objOwnerID
char username[MAX_USERNAME_LEN+1];
Int32 lActualLen = 0;
Int16 status = ComUser::getAuthNameFromAuthID( (Int32) schemaOwnerID
, (char *)&username
, MAX_USERNAME_LEN+1
, lActualLen );
if (status != FEOK)
{
*CmpCommon::diags() << DgSqlCode(-20235)
<< DgInt0(status)
<< DgInt1(schemaOwnerID);
return FALSE;
}
std::string schemaOwnerGrantee(username);
std::string ownerGrantee;
std::string creatorGrantee;
if (schemaOwnerID == objOwnerID)
ownerGrantee = schemaOwnerGrantee;
else
{
char username[MAX_USERNAME_LEN+1];
Int32 lActualLen = 0;
Int16 status = ComUser::getAuthNameFromAuthID( (Int32) objOwnerID
, (char *)&username
, MAX_USERNAME_LEN+1
, lActualLen );
if (status != FEOK)
{
*CmpCommon::diags() << DgSqlCode(-20235)
<< DgInt0(status)
<< DgInt1(objOwnerID);
return FALSE;
}
ownerGrantee = username;
}
if (creatorID == objOwnerID)
creatorGrantee = ownerGrantee;
else
{
char username[MAX_USERNAME_LEN+1];
Int32 lActualLen = 0;
Int16 status = ComUser::getAuthNameFromAuthID( (Int32) creatorID
, (char *)&username
, MAX_USERNAME_LEN+1
, lActualLen );
if (status != FEOK)
{
*CmpCommon::diags() << DgSqlCode(-20235)
<< DgInt0(status)
<< DgInt1(creatorID);
return FALSE;
}
creatorGrantee = username;
}
// Grant the ownership privileges
NAString privMgrMDLoc;
CONCAT_CATSCH(privMgrMDLoc, getSystemCatalog(), SEABASE_PRIVMGR_SCHEMA);
PrivMgrPrivileges privileges(objUID,std::string(objName),SYSTEM_USER,
std::string(privMgrMDLoc.data()),CmpCommon::diags());
PrivStatus retcode = privileges.grantToOwners(objectType,schemaOwnerID,
schemaOwnerGrantee,objOwnerID,
ownerGrantee,creatorID,
creatorGrantee);
if (retcode != STATUS_GOOD && retcode != STATUS_WARNING)
return FALSE;
return TRUE;
}
// ----------------------------------------------------------------------------
// method: deletePrivMgrInfo
//
// this method calls the privilege manager interface to perform revokes
// when objects are dropped to remove all privileges
//
// input: the object's UID, name, and type
//
// returns:
// TRUE if the privileges were correctly deleted (revoked)
// FALSE if an error occurred (ComDiags is set up with the error)
// ----------------------------------------------------------------------------
NABoolean CmpSeabaseDDL::deletePrivMgrInfo(const NAString &objectName,
const Int64 objUID,
const ComObjectType objectType)
{
if (!PrivMgr::isSecurableObject(objectType))
return TRUE;
// Initiate the privilege manager interface class
NAString privMgrMDLoc;
CONCAT_CATSCH(privMgrMDLoc, getSystemCatalog(), SEABASE_PRIVMGR_SCHEMA);
PrivMgrCommands privInterface(std::string(privMgrMDLoc.data()), CmpCommon::diags());
// If authorization is not enabled, return TRUE, no grants are needed
if (!isAuthorizationEnabled())
return TRUE;
const std::string objName(objectName.data());
PrivStatus retcode =
privInterface.revokeObjectPrivilege (objUID, objName, -2);
if (retcode == STATUS_ERROR)
return FALSE;
NegateAllErrors(CmpCommon::diags());
return TRUE;
}
short CmpSeabaseDDL::dropMDTable(ExpHbaseInterface *ehi, const char * tab)
{
if (!ComUser::isRootUserID())
{
*CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
return -1;
}
Lng32 retcode = 0;
HbaseStr hbaseObjStr;
NAString hbaseObjPrefix = getSystemCatalog();
hbaseObjPrefix += ".";
hbaseObjPrefix += SEABASE_MD_SCHEMA;
hbaseObjPrefix += ".";
NAString hbaseObject = hbaseObjPrefix + tab;
hbaseObjStr.val = (char*)hbaseObject.data();
hbaseObjStr.len = hbaseObject.length();
retcode = existsInHbase(hbaseObject, ehi);
if (retcode == 1) // exists
{
retcode = dropHbaseTable(ehi, &hbaseObjStr, FALSE, FALSE);
return retcode;
}
return 0;
}
void CmpSeabaseDDL::updateVersion()
{
if (!ComUser::isRootUserID())
{
*CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
return;
}
Lng32 retcode = 0;
Lng32 cliRC = 0;
ExeCliInterface cliInterface(STMTHEAP, 0, NULL,
CmpCommon::context()->sqlSession()->getParentQid());
if ((CmpCommon::context()->isUninitializedSeabase()) &&
(CmpCommon::context()->uninitializedSeabaseErrNum() == -TRAF_NOT_INITIALIZED))
{
*CmpCommon::diags() << DgSqlCode(-TRAF_NOT_INITIALIZED);
return;
}
Int64 softMajorVersion;
Int64 softMinorVersion;
Int64 softUpdVersion;
getSystemSoftwareVersion(softMajorVersion, softMinorVersion, softUpdVersion);
char queryBuf[5000];
Int64 updateTime = NA_JulianTimestamp();
str_sprintf(queryBuf, "update %s.\"%s\".%s set major_version = %ld, minor_version = %ld, init_time = %ld, comment = 'update version' where version_type = 'SOFTWARE' ",
getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_VERSIONS,
softMajorVersion, softMinorVersion,
updateTime);
NABoolean xnWasStartedHere = FALSE;
if (beginXnIfNotInProgress(&cliInterface, xnWasStartedHere))
return;
cliRC = cliInterface.executeImmediate(queryBuf);
if (cliRC < 0)
{
cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
}
if (endXnIfStartedHere(&cliInterface, xnWasStartedHere, cliRC) < 0)
return;
}
// truncate is a non-transactional operation. Caller need to restore back
// the truncated table if an error occurs.
short CmpSeabaseDDL::truncateHbaseTable(const NAString &catalogNamePart,
const NAString &schemaNamePart,
const NAString &objectNamePart,
const NABoolean hasSaltedColumn,
ExpHbaseInterface * ehi)
{
Lng32 retcode = 0;
const NAString extNameForHbase =
catalogNamePart + "." + schemaNamePart + "." + objectNamePart;
HbaseStr hbaseTable;
hbaseTable.val = (char*)extNameForHbase.data();
hbaseTable.len = extNameForHbase.length();
// if salted table, preserve splits.
if (hasSaltedColumn)
retcode = ehi->truncate(hbaseTable, TRUE, TRUE);
else
retcode = ehi->truncate(hbaseTable, FALSE, TRUE);
if (retcode)
{
*CmpCommon::diags() << DgSqlCode(-8448)
<< DgString0((char*)"ExpHbaseInterface::truncate()")
<< DgString1(getHbaseErrStr(-retcode))
<< DgInt0(-retcode)
<< DgString2((char*)GetCliGlobals()->getJniErrorStr());
processReturn();
return -1;
}
return 0;
}
void CmpSeabaseDDL::purgedataHbaseTable(DDLExpr * ddlExpr,
NAString &currCatName, NAString &currSchName)
{
Lng32 cliRC;
Lng32 retcode = 0;
NABoolean xnWasStartedHere = FALSE;
CorrName &purgedataTableName = ddlExpr->purgedataTableName();
NAString tabName = ddlExpr->getQualObjName();
ComObjectName tableName(tabName, COM_TABLE_NAME);
ComAnsiNamePart currCatAnsiName(currCatName);
ComAnsiNamePart currSchAnsiName(currSchName);
tableName.applyDefaults(currCatAnsiName, currSchAnsiName);
NAString catalogNamePart = tableName.getCatalogNamePartAsAnsiString();
NAString schemaNamePart = tableName.getSchemaNamePartAsAnsiString(TRUE);
NAString objectNamePart = tableName.getObjectNamePartAsAnsiString(TRUE);
const NAString extTableName = tableName.getExternalName(TRUE);
const NAString extNameForHbase = catalogNamePart + "." + schemaNamePart + "." + objectNamePart;
ExeCliInterface cliInterface(STMTHEAP, 0, NULL,
CmpCommon::context()->sqlSession()->getParentQid());
ExpHbaseInterface * ehi = allocEHI();
if (ehi == NULL)
{
processReturn();
return;
}
if ((isSeabaseReservedSchema(tableName)) &&
(!Get_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL)))
{
*CmpCommon::diags() << DgSqlCode(-CAT_USER_CANNOT_DROP_SMD_TABLE)
<< DgTableName(extTableName);
deallocEHI(ehi);
processReturn();
return;
}
// special tables, like index, can only be purged in internal mode with special
// flag settings. Otherwise, it can make database inconsistent.
if ((purgedataTableName.isSpecialTable()) &&
(!Get_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL)))
{
*CmpCommon::diags()
<< DgSqlCode(-1010);
processReturn();
return;
}
ActiveSchemaDB()->getNATableDB()->useCache();
BindWA bindWA(ActiveSchemaDB(), CmpCommon::context(), FALSE/*inDDL*/);
CorrName cn(tableName.getObjectNamePart().getInternalName(),
STMTHEAP,
tableName.getSchemaNamePart().getInternalName(),
tableName.getCatalogNamePart().getInternalName());
cn.setSpecialType(purgedataTableName);
if (cn.isHive())
{
*CmpCommon::diags() << DgSqlCode(-3242)
<< DgString0("Purgedata is not allowed for Hive tables. Use 'Truncate Table' command.");
return;
}
if (cn.isHbase())
{
*CmpCommon::diags() << DgSqlCode(-3242)
<< DgString0("Purgedata is not allowed for HBase tables.");
return;
}
NATable *naTable = bindWA.getNATable(cn);
// if table doesn't exist and 'if exists' clause is specified, return.
if (ddlExpr->purgedataIfExists() && (! naTable))
{
bindWA.resetErrStatus();
CmpCommon::diags()->clear();
return;
}
if (naTable == NULL || bindWA.errStatus())
{
processReturn();
return;
}
// Verify that the current user has authority to perform operation
if (!Get_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL) && isAuthorizationEnabled())
{
PrivMgrUserPrivs* privs = naTable->getPrivInfo();
if (privs == NULL)
{
*CmpCommon::diags() << DgSqlCode(-CAT_UNABLE_TO_RETRIEVE_PRIVS);
deallocEHI(ehi);
processReturn();
return;
}
NABoolean privCheckFailed = FALSE;
if (!privs->hasSelectPriv())
{
privCheckFailed = TRUE;
*CmpCommon::diags() << DgSqlCode( -4481 )
<< DgString0( "SELECT" )
<< DgString1( extTableName );
}
if (!privs->hasDeletePriv())
{
privCheckFailed = TRUE;
*CmpCommon::diags() << DgSqlCode( -4481 )
<< DgString0( "DELETE" )
<< DgString1( extTableName );
}
if (privCheckFailed)
{
deallocEHI(ehi);
processReturn();
return;
}
}
// cannot purgedata a view
if (naTable->getViewText())
{
*CmpCommon::diags()
<< DgSqlCode(-1010);
processReturn();
return;
}
if (naTable->getUniqueConstraints().entries() > 0)
{
const AbstractRIConstraintList &uniqueList = naTable->getUniqueConstraints();
for (Int32 i = 0; i < uniqueList.entries(); i++)
{
AbstractRIConstraint *ariConstr = uniqueList[i];
if (ariConstr->getOperatorType() != ITM_UNIQUE_CONSTRAINT)
continue;
UniqueConstraint * uniqConstr = (UniqueConstraint*)ariConstr;
if (uniqConstr->hasRefConstraintsReferencingMe())
{
NAString reason("Reason: Foreign Key constraints from other tables are referencing this table");
*CmpCommon::diags()
<< DgSqlCode(-1425)
<< DgTableName(extTableName)
<< DgString0(reason.data());
deallocEHI(ehi);
processReturn();
return;
}
} // for
}
retcode = updateObjectValidDef(&cliInterface,
catalogNamePart.data(), schemaNamePart.data(), objectNamePart.data(),
COM_BASE_TABLE_OBJECT_LIT, COM_NO_LIT);
if (retcode)
{
deallocEHI(ehi);
processReturn();
return;
}
NABoolean ddlXns = ddlExpr->ddlXns();
if (truncateHbaseTable(catalogNamePart, schemaNamePart, objectNamePart,
naTable->hasSaltedColumn(), ehi))
{
deallocEHI(ehi);
processReturn();
return;
}
if (naTable->hasSecondaryIndexes()) // user indexes
{
const NAFileSetList &indexList = naTable->getIndexList();
// purgedata from all indexes
for (Int32 i = 0; i < indexList.entries(); i++)
{
const NAFileSet * naf = indexList[i];
if (naf->getKeytag() == 0)
continue;
const QualifiedName &qn = naf->getFileSetName();
NAString catName = qn.getCatalogName();
NAString schName = qn.getSchemaName();
NAString idxName = qn.getObjectName();
retcode = truncateHbaseTable(catName, schName, idxName,
naTable->hasSaltedColumn(), ehi);
if (retcode)
{
deallocEHI(ehi);
processReturn();
return;
}
} // for
} // secondary indexes
retcode = updateObjectValidDef(&cliInterface,
catalogNamePart.data(), schemaNamePart.data(), objectNamePart.data(),
COM_BASE_TABLE_OBJECT_LIT, COM_YES_LIT);
if (retcode)
{
deallocEHI(ehi);
processReturn();
return;
}
return;
}
short CmpSeabaseDDL::executeSeabaseDDL(DDLExpr * ddlExpr, ExprNode * ddlNode,
NAString &currCatName, NAString &currSchName,
CmpDDLwithStatusInfo *dws)
{
Lng32 cliRC = 0;
ExeCliInterface cliInterface(STMTHEAP, 0, NULL,
CmpCommon::context()->sqlSession()->getParentQid());
// error accessing hbase. Return.
if ((CmpCommon::context()->isUninitializedSeabase()) &&
(CmpCommon::context()->uninitializedSeabaseErrNum() == -TRAF_HBASE_ACCESS_ERROR))
{
*CmpCommon::diags() << DgSqlCode(CmpCommon::context()->uninitializedSeabaseErrNum())
<< DgInt0(CmpCommon::context()->hbaseErrNum())
<< DgString0(CmpCommon::context()->hbaseErrStr());
return -1;
}
NABoolean xnWasStartedHere = FALSE;
NABoolean ignoreUninitTrafErr = FALSE;
if ((ddlExpr) &&
((ddlExpr->initHbase()) ||
(ddlExpr->createMDViews()) ||
(ddlExpr->dropMDViews()) ||
(ddlExpr->createRepos()) ||
(ddlExpr->dropRepos()) ||
(ddlExpr->upgradeRepos()) ||
(ddlExpr->addSchemaObjects()) ||
(ddlExpr->createLibmgr()) ||
(ddlExpr->updateVersion())))
ignoreUninitTrafErr = TRUE;
if ((Get_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL)) &&
(CmpCommon::context()->isUninitializedSeabase()))
{
ignoreUninitTrafErr = TRUE;
}
if (dws && dws->getInitTraf())
ignoreUninitTrafErr = TRUE;
if ((CmpCommon::context()->isUninitializedSeabase()) &&
(NOT ignoreUninitTrafErr))
{
*CmpCommon::diags() << DgSqlCode(CmpCommon::context()->uninitializedSeabaseErrNum());
return -1;
}
if (sendAllControlsAndFlags())
{
CMPASSERT(0);
return -1;
}
NABoolean startXn = FALSE;
NABoolean ddlXns = FALSE;
if (ddlExpr && ddlExpr->ddlXnsInfo(ddlXns, startXn))
return -1;
if (startXn)
{
if (beginXnIfNotInProgress(&cliInterface, xnWasStartedHere))
goto label_return;
}
if (dws)
{
if (dws->getMDcleanup())
{
StmtDDLCleanupObjects * co =
(ddlNode ? ddlNode->castToStmtDDLNode()->castToStmtDDLCleanupObjects()
: NULL);
CmpSeabaseMDcleanup cmpSBDC(STMTHEAP);
cmpSBDC.cleanupObjects(co, currCatName, currSchName, dws);
return 0;
}
else if (dws->getInitTraf())
{
if (ddlExpr)
{
dws->setDDLXns(TRUE);
if (ddlExpr->minimal())
dws->setMinimalInitTraf(TRUE);
}
initTrafMD(dws);
return 0;
}
}
if (ddlExpr->initHbase())
{
// will reach here it 'init traf' is to be done without returning status.
// drive initTrafMD method in a loop without returning any status rows.
// Do this until DONE state is returned.
CmpDDLwithStatusInfo dws;
dws.setDDLXns(TRUE);
if (ddlExpr->minimal())
dws.setMinimalInitTraf(TRUE);
NABoolean done = FALSE;
while (NOT done)
{
initTrafMD(&dws);
if (dws.done())
done = TRUE;
}
}
else if (ddlExpr->dropHbase())
{
dropSeabaseMD(ddlExpr->ddlXns());
}
else if (ddlExpr->createMDViews())
{
createSeabaseMDviews();
}
else if (ddlExpr->dropMDViews())
{
dropSeabaseMDviews();
}
else if (ddlExpr->initAuth())
{
std::vector<std::string> tablesCreated;
std::vector<std::string> tablesUpgraded;
// Can ignore status returned, diags area contains any unexpected errors
initSeabaseAuthorization(&cliInterface, ddlExpr->ddlXns(),
tablesCreated, tablesUpgraded);
#ifdef _DEBUG
// Do we want to display this information? Base it on a cqd or envvar?
// Do it in debug mode or log it somewhere instead?
NAString msgBuf ("tables created: ");
if (tablesCreated.size() == 0)
msgBuf += "none";
else
{
for (size_t i = 0; i < tablesCreated.size(); i++)
msgBuf += tablesCreated[i].c_str() + NAString(" ");
}
msgBuf += "\ntables upgraded: ";
if (tablesUpgraded.size() == 0)
msgBuf += "none";
else
{
for (size_t i = 0; i < tablesUpgraded.size(); i++)
msgBuf += tablesUpgraded[i].c_str() + NAString(" ");
}
cout << msgBuf.data() << endl;
#endif
}
else if (ddlExpr->dropAuth())
{
dropSeabaseAuthorization(&cliInterface, FALSE);
}
else if (ddlExpr->cleanupAuth())
{
dropSeabaseAuthorization(&cliInterface, TRUE);
}
else if (ddlExpr->addSchemaObjects())
{
createSeabaseSchemaObjects();
}
else if (ddlExpr->createLibmgr())
{
createSeabaseLibmgr(&cliInterface);
}
else if (ddlExpr->dropLibmgr())
{
dropSeabaseLibmgr(&cliInterface);
}
else if (ddlExpr->upgradeLibmgr())
{
upgradeSeabaseLibmgr(&cliInterface);
}
else if (ddlExpr->updateVersion())
{
updateVersion();
}
else if (ddlExpr->purgedata())
{
purgedataHbaseTable(ddlExpr, currCatName, currSchName);
}
else if ((ddlExpr->createRepos()) ||
(ddlExpr->dropRepos()) ||
(ddlExpr->upgradeRepos()))
{
if (!ComUser::isRootUserID())
*CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
else
processRepository(ddlExpr->createRepos(),
ddlExpr->dropRepos(),
ddlExpr->upgradeRepos());
}
else
{
CMPASSERT(ddlNode);
if (ddlNode->getOperatorType() == DDL_CREATE_TABLE)
{
// create hbase table
StmtDDLCreateTable * createTableParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLCreateTable();
if ((createTableParseNode->getAddConstraintUniqueArray().entries() > 0) ||
(createTableParseNode->getAddConstraintRIArray().entries() > 0) ||
(createTableParseNode->getAddConstraintCheckArray().entries() > 0))
createSeabaseTableCompound(createTableParseNode, currCatName, currSchName);
else
{
createSeabaseTable(createTableParseNode, currCatName, currSchName);
if (((getenv("SQLMX_REGRESS")) ||
(CmpCommon::getDefault(TRAF_AUTO_CREATE_SCHEMA) == DF_ON)) &&
(CmpCommon::diags()->getNumber(DgSqlCode::ERROR_)) &&
(CmpCommon::diags()->mainSQLCODE() == -CAT_SCHEMA_DOES_NOT_EXIST_ERROR))
{
ComObjectName tableName(createTableParseNode->getTableName());
ComAnsiNamePart currCatAnsiName(currCatName);
ComAnsiNamePart currSchAnsiName(currSchName);
tableName.applyDefaults(currCatAnsiName, currSchAnsiName);
const NAString schemaNamePart =
tableName.getSchemaNamePartAsAnsiString(TRUE);
char query[1000];
if ((getenv("SQLMX_REGRESS")) &&
(schemaNamePart == SEABASE_REGRESS_DEFAULT_SCHEMA))
{
CmpCommon::diags()->clear();
str_sprintf(query, "create shared schema %s.%s",
TRAFODION_SYSCAT_LIT,
SEABASE_REGRESS_DEFAULT_SCHEMA);
cliRC = cliInterface.executeImmediate(query);
if (cliRC >= 0)
{
str_sprintf(query, "upsert into %s.\"%s\".%s values ('SCHEMA ', '%s.%s ', 'inserted during regressions run', 0);",
TRAFODION_SYSCAT_LIT,
SEABASE_MD_SCHEMA,
SEABASE_DEFAULTS,
TRAFODION_SYSCAT_LIT,
SEABASE_REGRESS_DEFAULT_SCHEMA);
cliRC = cliInterface.executeImmediate(query);
if (cliRC >= 0)
{
createSeabaseTable(createTableParseNode, currCatName, currSchName);
}
}
} // if
else if (CmpCommon::getDefault(TRAF_AUTO_CREATE_SCHEMA) == DF_ON)
{
// create this schema
CmpCommon::diags()->clear();
str_sprintf(query, "create schema %s.\"%s\";",
TRAFODION_SYSCAT_LIT, schemaNamePart.data());
cliRC = cliInterface.executeImmediate(query);
if (cliRC >= 0)
{
createSeabaseTable(createTableParseNode, currCatName, currSchName);
}
}
}
}
}
else if (ddlNode->getOperatorType() == DDL_CREATE_HBASE_TABLE)
{
// create hbase table
StmtDDLCreateHbaseTable * createTableParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLCreateHbaseTable();
createNativeHbaseTable(&cliInterface, createTableParseNode, currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_DROP_TABLE)
{
// drop seabase table
StmtDDLDropTable * dropTableParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLDropTable();
dropSeabaseTable(dropTableParseNode, currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_DROP_HBASE_TABLE)
{
// drop hbase table
StmtDDLDropHbaseTable * dropTableParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLDropHbaseTable();
dropNativeHbaseTable(&cliInterface, dropTableParseNode, currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_CREATE_INDEX)
{
// create seabase index
StmtDDLCreateIndex * createIndexParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLCreateIndex();
createSeabaseIndex(createIndexParseNode, currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_POPULATE_INDEX)
{
// populate seabase index
StmtDDLPopulateIndex * populateIndexParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLPopulateIndex();
populateSeabaseIndex(populateIndexParseNode, currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_DROP_INDEX)
{
// drop seabase table
StmtDDLDropIndex * dropIndexParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLDropIndex();
dropSeabaseIndex(dropIndexParseNode, currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_ALTER_TABLE_ADD_COLUMN)
{
StmtDDLAlterTableAddColumn * alterAddColNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLAlterTableAddColumn();
alterSeabaseTableAddColumn(alterAddColNode,
currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_ALTER_TABLE_DROP_COLUMN)
{
StmtDDLAlterTableDropColumn * alterDropColNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLAlterTableDropColumn();
alterSeabaseTableDropColumn(alterDropColNode,
currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_ALTER_TABLE_ADD_CONSTRAINT_PRIMARY_KEY)
{
StmtDDLAddConstraint * alterAddConstraint =
ddlNode->castToStmtDDLNode()->castToStmtDDLAddConstraint();
alterSeabaseTableAddPKeyConstraint(alterAddConstraint,
currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_ALTER_TABLE_ADD_CONSTRAINT_UNIQUE)
{
StmtDDLAddConstraint * alterAddConstraint =
ddlNode->castToStmtDDLNode()->castToStmtDDLAddConstraint();
alterSeabaseTableAddUniqueConstraint(alterAddConstraint,
currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_ALTER_TABLE_ADD_CONSTRAINT_REFERENTIAL_INTEGRITY)
{
StmtDDLAddConstraint * alterAddConstraint =
ddlNode->castToStmtDDLNode()->castToStmtDDLAddConstraint();
alterSeabaseTableAddRIConstraint(alterAddConstraint,
currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_ALTER_TABLE_ADD_CONSTRAINT_CHECK)
{
StmtDDLAddConstraint * alterAddConstraint =
ddlNode->castToStmtDDLNode()->castToStmtDDLAddConstraint();
alterSeabaseTableAddCheckConstraint(alterAddConstraint,
currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_ALTER_TABLE_DROP_CONSTRAINT)
{
StmtDDLDropConstraint * alterDropConstraint =
ddlNode->castToStmtDDLNode()->castToStmtDDLDropConstraint();
alterSeabaseTableDropConstraint(alterDropConstraint,
currCatName, currSchName);
}
else if ((ddlNode->getOperatorType() == DDL_ALTER_TABLE_DISABLE_INDEX) ||
(ddlNode->getOperatorType() == DDL_ALTER_TABLE_ENABLE_INDEX))
{
NABoolean allIndexes = FALSE;
NABoolean allUniquesOnly = FALSE;
StmtDDLAlterTableDisableIndex * disableIdx = ddlNode->castToStmtDDLNode()->castToStmtDDLAlterTableDisableIndex();
NAString tabNameNAS ;
if (disableIdx)
{
allIndexes = disableIdx->getAllIndexes();
tabNameNAS = disableIdx->getTableName();
allUniquesOnly = disableIdx->getAllUniqueIndexes();
}
else
{
StmtDDLAlterTableEnableIndex * enableIdx = ddlNode->castToStmtDDLNode()->castToStmtDDLAlterTableEnableIndex();
allIndexes = enableIdx->getAllIndexes() ;
tabNameNAS = enableIdx->getTableName();
allUniquesOnly = enableIdx->getAllUniqueIndexes();
}
if (!(allIndexes || allUniquesOnly))
alterSeabaseTableDisableOrEnableIndex(ddlNode,
currCatName,
currSchName);
else
{
alterSeabaseTableDisableOrEnableAllIndexes(ddlNode,
currCatName,
currSchName,
(NAString &) tabNameNAS,
allUniquesOnly);
}
}
else if (ddlNode->getOperatorType() == DDL_ALTER_TABLE_RENAME)
{
StmtDDLAlterTableRename * alterRenameTable =
ddlNode->castToStmtDDLNode()->castToStmtDDLAlterTableRename();
renameSeabaseTable(alterRenameTable,
currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_ALTER_TABLE_STORED_DESC)
{
StmtDDLAlterTableStoredDesc * alterStoredDesc =
ddlNode->castToStmtDDLNode()->castToStmtDDLAlterTableStoredDesc();
alterSeabaseTableStoredDesc(alterStoredDesc, currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_ALTER_TABLE_ALTER_HBASE_OPTIONS)
{
StmtDDLAlterTableHBaseOptions * athbo =
ddlNode->castToStmtDDLNode()->castToStmtDDLAlterTableHBaseOptions();
alterSeabaseTableHBaseOptions(athbo, currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_ALTER_INDEX_ALTER_HBASE_OPTIONS)
{
StmtDDLAlterIndexHBaseOptions * aihbo =
ddlNode->castToStmtDDLNode()->castToStmtDDLAlterIndexHBaseOptions();
alterSeabaseIndexHBaseOptions(aihbo, currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_CREATE_VIEW)
{
// create seabase view
StmtDDLCreateView * createViewParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLCreateView();
createSeabaseView(createViewParseNode, currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_DROP_VIEW)
{
// drop seabase table
StmtDDLDropView * dropViewParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLDropView();
dropSeabaseView(dropViewParseNode, currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_REGISTER_USER)
{
StmtDDLRegisterUser *registerUserParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLRegisterUser();
StmtDDLRegisterUser::RegisterUserType ruType =
registerUserParseNode->getRegisterUserType();
if (ruType == StmtDDLRegisterUser::REGISTER_USER)
registerSeabaseUser(registerUserParseNode);
else
unregisterSeabaseUser(registerUserParseNode);
}
else if (ddlNode->getOperatorType() == DDL_REG_OR_UNREG_OBJECT)
{
StmtDDLRegOrUnregObject *regOrUnregObjectParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLRegOrUnregObject();
regOrUnregNativeObject(
regOrUnregObjectParseNode, currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_CREATE_ROLE)
{
StmtDDLCreateRole *createRoleParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLCreateRole();
CmpSeabaseDDLrole role(getSystemCatalog(),getMDSchema());
if (createRoleParseNode->isCreateRole())
role.createRole(createRoleParseNode);
else
role.dropRole(createRoleParseNode);
}
else if (ddlNode->getOperatorType() == DDL_ALTER_USER)
{
StmtDDLAlterUser *alterUserParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLAlterUser();
alterSeabaseUser(alterUserParseNode);
}
else if (ddlNode->getOperatorType() == DDL_REGISTER_COMPONENT)
{
StmtDDLRegisterComponent *registerComponentParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLRegisterComponent();
registerSeabaseComponent(registerComponentParseNode);
}
else if (ddlNode->getOperatorType() == DDL_CREATE_COMPONENT_PRIVILEGE)
{
StmtDDLCreateComponentPrivilege *createComponentOperationParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLCreateComponentPrivilege();
createSeabaseComponentOperation(getSystemCatalog(),
createComponentOperationParseNode);
}
else if (ddlNode->getOperatorType() == DDL_DROP_COMPONENT_PRIVILEGE)
{
StmtDDLDropComponentPrivilege *dropComponentOperationParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLDropComponentPrivilege();
dropSeabaseComponentOperation(getSystemCatalog(),
dropComponentOperationParseNode);
}
else if (ddlNode->getOperatorType() == DDL_GRANT_COMPONENT_PRIVILEGE)
{
StmtDDLGrantComponentPrivilege *grantComponentPrivilegeParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLGrantComponentPrivilege();
grantSeabaseComponentPrivilege(getSystemCatalog(),
grantComponentPrivilegeParseNode);
}
else if (ddlNode->getOperatorType() == DDL_REVOKE_COMPONENT_PRIVILEGE)
{
StmtDDLRevokeComponentPrivilege *revokeComponentPrivilegeParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLRevokeComponentPrivilege();
revokeSeabaseComponentPrivilege(getSystemCatalog(),
revokeComponentPrivilegeParseNode);
}
else if (ddlNode->getOperatorType() == DDL_GRANT_ROLE)
{
StmtDDLRoleGrant *grantRoleParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLRoleGrant();
grantRevokeSeabaseRole(getSystemCatalog(),grantRoleParseNode);
}
else if ((ddlNode->getOperatorType() == DDL_GRANT) ||
(ddlNode->getOperatorType() == DDL_REVOKE))
{
// grant/revoke seabase table
StmtDDLNode * stmtDDLParseNode =
ddlNode->castToStmtDDLNode();
seabaseGrantRevoke(stmtDDLParseNode,
(ddlNode->getOperatorType() == DDL_GRANT
? TRUE : FALSE),
currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_GIVE_ALL)
{
StmtDDLGiveAll *giveAllParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLGiveAll();
giveSeabaseAll(giveAllParseNode);
}
else if (ddlNode->getOperatorType() == DDL_GIVE_OBJECT)
{
StmtDDLGiveObject *giveObjectParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLGiveObject();
giveSeabaseObject(giveObjectParseNode);
}
else if (ddlNode->getOperatorType() == DDL_GIVE_SCHEMA)
{
StmtDDLGiveSchema *giveSchemaParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLGiveSchema();
giveSeabaseSchema(giveSchemaParseNode,currCatName);
}
else if (ddlNode->getOperatorType() == DDL_CREATE_SCHEMA)
{
StmtDDLCreateSchema * createSchemaParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLCreateSchema();
createSeabaseSchema(createSchemaParseNode,currCatName);
}
else if (ddlNode->getOperatorType() == DDL_DROP_SCHEMA)
{
// drop all tables in schema
StmtDDLDropSchema * dropSchemaParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLDropSchema();
dropSeabaseSchema(dropSchemaParseNode);
}
else if (ddlNode->getOperatorType() == DDL_ALTER_SCHEMA)
{
StmtDDLAlterSchema * alterSchemaParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLAlterSchema();
alterSeabaseSchema(alterSchemaParseNode);
}
else if (ddlNode->getOperatorType() == DDL_CREATE_LIBRARY)
{
// create seabase library
StmtDDLCreateLibrary * createLibraryParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLCreateLibrary();
createSeabaseLibrary(createLibraryParseNode, currCatName,
currSchName);
}
else if (ddlNode->getOperatorType() == DDL_DROP_LIBRARY)
{
// drop seabase library
StmtDDLDropLibrary * dropLibraryParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLDropLibrary();
dropSeabaseLibrary(dropLibraryParseNode, currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_ALTER_LIBRARY)
{
// create seabase library
StmtDDLAlterLibrary * alterLibraryParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLAlterLibrary();
alterSeabaseLibrary(alterLibraryParseNode, currCatName,
currSchName);
}
else if (ddlNode->getOperatorType() == DDL_CREATE_ROUTINE)
{
// create seabase routine
StmtDDLCreateRoutine * createRoutineParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLCreateRoutine();
createSeabaseRoutine(createRoutineParseNode, currCatName,
currSchName);
}
else if (ddlNode->getOperatorType() == DDL_DROP_ROUTINE)
{
// drop seabase routine
StmtDDLDropRoutine * dropRoutineParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLDropRoutine();
dropSeabaseRoutine(dropRoutineParseNode, currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_CREATE_SEQUENCE)
{
// create seabase sequence
StmtDDLCreateSequence * createSequenceParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLCreateSequence();
if (createSequenceParseNode->isAlter())
alterSeabaseSequence(createSequenceParseNode, currCatName,
currSchName);
else
createSeabaseSequence(createSequenceParseNode, currCatName,
currSchName);
}
else if (ddlNode->getOperatorType() == DDL_DROP_SEQUENCE)
{
// drop seabase sequence
StmtDDLDropSequence * dropSequenceParseNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLDropSequence();
dropSeabaseSequence(dropSequenceParseNode, currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_ALTER_TABLE_ALTER_COLUMN_SET_SG_OPTION)
{
StmtDDLAlterTableAlterColumnSetSGOption * alterIdentityColNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLAlterTableAlterColumnSetSGOption();
alterSeabaseTableAlterIdentityColumn(alterIdentityColNode,
currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_ALTER_TABLE_ALTER_COLUMN_DATATYPE)
{
StmtDDLAlterTableAlterColumnDatatype * alterColNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLAlterTableAlterColumnDatatype();
alterSeabaseTableAlterColumnDatatype(alterColNode,
currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_ALTER_TABLE_ALTER_COLUMN_RENAME)
{
StmtDDLAlterTableAlterColumnRename * alterColNode =
ddlNode->castToStmtDDLNode()->castToStmtDDLAlterTableAlterColumnRename();
alterSeabaseTableAlterColumnRename(alterColNode,
currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_CLEANUP_OBJECTS)
{
StmtDDLCleanupObjects * co =
ddlNode->castToStmtDDLNode()->castToStmtDDLCleanupObjects();
CmpSeabaseMDcleanup cmpSBDC(STMTHEAP);
cmpSBDC.cleanupObjects(co, currCatName, currSchName, dws);
}
else if (ddlNode->getOperatorType() == DDL_COMMENT_ON)
{
StmtDDLCommentOn * comment =
ddlNode->castToStmtDDLNode()->castToStmtDDLCommentOn();
doSeabaseCommentOn(comment, currCatName, currSchName);
}
else if (ddlNode->getOperatorType() == DDL_ON_HIVE_OBJECTS)
{
StmtDDLonHiveObjects * hddl =
ddlNode->castToStmtDDLNode()->castToStmtDDLonHiveObjects();
processDDLonHiveObjects(hddl, currCatName, currSchName);
}
else
{
// some operator type that this routine doesn't support yet
*CmpCommon::diags() << DgSqlCode(-CAT_UNSUPPORTED_COMMAND_ERROR);
}
} // else
label_return:
restoreAllControlsAndFlags();
if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_))
{
cliRC = -1;
// some ddl stmts are executed as multiple sub statements.
// some of those sub stmts may abort the enclosing xn started here
// in case of an error, and add an error condition that the xn
// was aborted.
// remove that error condition from the diags area. But dont do it
// if it is the main error.
// if (xnWasStartedHere &&
if (CmpCommon::diags()->mainSQLCODE() != -CLI_VALIDATE_TRANSACTION_ERROR)
{
CollIndex i =
CmpCommon::diags()->returnIndex(-CLI_VALIDATE_TRANSACTION_ERROR);
if (i != NULL_COLL_INDEX)
CmpCommon::diags()->deleteError(i);
}
}
if (endXnIfStartedHere(&cliInterface, xnWasStartedHere, cliRC) < 0)
return -1;
return 0;
}
void CmpSeabaseDDL::registerSeabaseUser(StmtDDLRegisterUser * authParseNode)
{
CmpSeabaseDDLuser user(getSystemCatalog(),getMDSchema());
user.registerUser(authParseNode);
}
void CmpSeabaseDDL::alterSeabaseUser(StmtDDLAlterUser * authParseNode)
{
CmpSeabaseDDLuser user(getSystemCatalog(),getMDSchema());
user.alterUser(authParseNode);
}
void CmpSeabaseDDL::unregisterSeabaseUser(StmtDDLRegisterUser * authParseNode)
{
CmpSeabaseDDLuser user(getSystemCatalog(),getMDSchema());
user.unregisterUser(authParseNode);
}
// *****************************************************************************
// * *
// * Function: CmpSeabaseDDL::giveSeabaseAll *
// * *
// * This function transfers ownership of all SQL objects owned by one *
// * authID to another authID. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <giveAllParseNode> StmtDDLGiveAll * In *
// * is a pointer to parse node containing the data for the GIVE ALL command*
// * *
// *****************************************************************************
void CmpSeabaseDDL::giveSeabaseAll(StmtDDLGiveAll * giveAllParseNode)
{
//
// A user cannot give away all of their own objects unless they have the
// ALTER privilege.
//
if (!isDDLOperationAuthorized(SQLOperation::ALTER,NA_UserIdDefault,
NA_UserIdDefault))
{
*CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
return;
}
int32_t fromOwnerID = -1;
if (ComUser::getAuthIDFromAuthName(giveAllParseNode->getFromID().data(),
fromOwnerID) != 0)
{
*CmpCommon::diags() << DgSqlCode(-CAT_AUTHID_DOES_NOT_EXIST_ERROR)
<< DgString0(giveAllParseNode->getFromID().data());
return;
}
int32_t toOwnerID = -1;
if (ComUser::getAuthIDFromAuthName(giveAllParseNode->getToID().data(),
toOwnerID) != 0)
{
*CmpCommon::diags() << DgSqlCode(-CAT_AUTHID_DOES_NOT_EXIST_ERROR)
<< DgString0(giveAllParseNode->getToID().data());
return;
}
// If the FROM and TO IDs are the same, just return.
if (fromOwnerID == toOwnerID)
return;
char buf[4000];
ExeCliInterface cliInterface(STMTHEAP, 0, NULL,
CmpCommon::context()->sqlSession()->getParentQid());
Lng32 cliRC = 0;
str_sprintf(buf,"UPDATE %s.\"%s\".%s "
"SET object_owner = %d "
"WHERE object_owner = %d",
getSystemCatalog(),SEABASE_MD_SCHEMA,SEABASE_OBJECTS,
toOwnerID,fromOwnerID);
cliRC = cliInterface.executeImmediate(buf);
if (cliRC < 0)
{
cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
return;
}
// Verify all objects in the database have been given to the new owner.
str_sprintf(buf,"SELECT COUNT(*) "
"FROM %s.\"%s\".%s "
"WHERE object_owner = %d "
"FOR READ COMMITTED ACCESS",
getSystemCatalog(),SEABASE_MD_SCHEMA,SEABASE_OBJECTS,
fromOwnerID);
int32_t length = 0;
Int64 rowCount = 0;
cliRC = cliInterface.executeImmediate(buf,(char*)&rowCount,&length,FALSE);
if (cliRC < 0)
{
cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
return;
}
if (rowCount > 0)
{
SEABASEDDL_INTERNAL_ERROR("Not all objects were given");
return;
}
}
//******************** End of CmpSeabaseDDL::giveSeabaseAll ********************
// *****************************************************************************
// * *
// * Function: CmpSeabaseDDL::giveSeabaseObject *
// * *
// * This function transfers ownership of a SQL object to another authID. *
// * authID *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <giveObjectParseNode> StmtDDLGiveObject * In *
// * is a pointer to parse node containing the data for the GIVE command. *
// * *
// *****************************************************************************
void CmpSeabaseDDL::giveSeabaseObject(StmtDDLGiveObject * giveObjectParseNode)
{
*CmpCommon::diags() << DgSqlCode(-CAT_UNSUPPORTED_COMMAND_ERROR);
}
//****************** End of CmpSeabaseDDL::giveSeabaseObject *******************
// *****************************************************************************
// * *
// * Function: CmpSeabaseDDL::dropOneTableorView *
// * *
// * Drops a table or view and all its dependent objects. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <cliInterface> ExeCliInterface & In *
// * is a reference to an Executor CLI interface handle. *
// * *
// * <objectName> const char * In *
// * is the fully quailified name of the object to drop. *
// * *
// * <objectType> ComObjectType In *
// * is the type of object (Table or view) to drop. *
// * *
// * <isVolatile> bool In *
// * is true if the object is volatile or part of a volatile schema. *
// * *
// *****************************************************************************
// * *
// * Returns: bool *
// * *
// * true: Could not drop table/view or one of its dependent objects. *
// * false: Drop successful or could not set CQD for NATable cache reload. *
// * *
// *****************************************************************************
bool CmpSeabaseDDL::dropOneTableorView(
ExeCliInterface & cliInterface,
const char * objectName,
ComObjectType objectType,
bool isVolatile)
{
char buf [1000];
bool someObjectsCouldNotBeDropped = false;
char volatileString[20] = {0};
char objectTypeString[20] = {0};
switch (objectType)
{
case COM_BASE_TABLE_OBJECT:
strcpy(objectTypeString,"TABLE");
break;
case COM_VIEW_OBJECT:
strcpy(objectTypeString,"VIEW");
break;
default:
SEABASEDDL_INTERNAL_ERROR("Unsupported object type in CmpSeabaseDDL::dropOneTableorView");
}
if (isVolatile)
strcpy(volatileString,"VOLATILE");
str_sprintf(buf,"DROP %s %s %s CASCADE",
volatileString,objectTypeString,objectName);
// Turn on the internal query parser flag; note that when
// this object is destroyed, the flags will be reset to
// their original state
PushAndSetSqlParserFlags savedParserFlags(INTERNAL_QUERY_FROM_EXEUTIL);
Lng32 cliRC = 0;
try
{
cliRC = cliInterface.executeImmediate(buf);
}
catch (...)
{
throw;
}
if (cliRC < 0 && cliRC != -CAT_OBJECT_DOES_NOT_EXIST_IN_TRAFODION)
someObjectsCouldNotBeDropped = true;
return someObjectsCouldNotBeDropped;
}
//****************** End of CmpSeabaseDDL::dropOneTableorView ******************
// *****************************************************************************
// * *
// * Function: CmpSeabaseDDL::verifyDDLCreateOperationAuthorized *
// * *
// * This member function determines if a user has the authority to perform *
// * a specific DDL operation in a specified schema. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <cliInterface> ExeCliInterface & In *
// * is a pointer to an Executor CLI interface handle. *
// * *
// * <operation> SQLOperation In *
// * is operation the user wants to perform. *
// * *
// * <catalogName> const NAString & In *
// * is the name of the catalog where the object is to be created. *
// * *
// * <schemaName> const NAString & In *
// * is the name of the schema where the object is to be created. If this *
// * is a CREATE SCHEMA request, this is the name of the schema to be created *
// * *
// * <schemaClass> ComSchemaClass & Out *
// * passes back the class of the schema where the object to be created. *
// * *
// * <objectOwner> Int32 & Out *
// * passes back the user ID to use for object ownership. *
// * *
// * <schemaOwner> Int32 & Out *
// * passes back the user ID to use for schema ownership. *
// * *
// *****************************************************************************
// * *
// * Returns: int32_t/SQL error code *
// * *
// * 0: Create operation is authorized. *
// * 1001: Internal error - not a create operation. *
// * 1003: Schema does not exist. *
// * 1017: Create operation not authorized *
// * *
// *****************************************************************************
int32_t CmpSeabaseDDL::verifyDDLCreateOperationAuthorized(
ExeCliInterface * cliInterface,
SQLOperation operation,
const NAString & catalogName,
const NAString & schemaName,
ComSchemaClass & schemaClass,
Int32 & objectOwner,
Int32 & schemaOwner)
{
int32_t currentUser = ComUser::getCurrentUser();
NAString privMgrMDLoc;
CONCAT_CATSCH(privMgrMDLoc,getSystemCatalog(),SEABASE_PRIVMGR_SCHEMA);
PrivMgrComponentPrivileges componentPrivileges(std::string(privMgrMDLoc.data()),
CmpCommon::diags());
// CREATE SCHEMA is a special case. There is no existing schema with an
// an owner or class. A new schema may be created if the user is DB__ROOT,
// authorization is not enabled, or the user has the CREATE_SCHEMA privilege.
if (operation == SQLOperation::CREATE_SCHEMA)
{
objectOwner = schemaOwner = currentUser;
if (currentUser == ComUser::getRootUserID())
return 0;
if (!isAuthorizationEnabled())
return 0;
if (componentPrivileges.hasSQLPriv(currentUser,
SQLOperation::CREATE_SCHEMA,
true))
return 0;
objectOwner = schemaOwner = NA_UserIdDefault;
return CAT_NOT_AUTHORIZED;
}
//
// Not CREATE SCHEMA, but verify the operation is a create operation.
//
if (!PrivMgr::isSQLCreateOperation(operation))
{
SEABASEDDL_INTERNAL_ERROR("Unknown create operation");
objectOwner = schemaOwner = NA_UserIdDefault;
return CAT_INTERNAL_EXCEPTION_ERROR;
}
// User is asking to create an object in an existing schema. Determine if this
// schema exists, and if it exists, the owner of the schema. The schema class
// and owner will determine if this user can create an object in the schema and
// who will own the object.
ComObjectType objectType;
if (getObjectTypeandOwner(cliInterface,catalogName.data(),schemaName.data(),
SEABASE_SCHEMA_OBJECTNAME,objectType,schemaOwner) == -1)
{
objectOwner = schemaOwner = NA_UserIdDefault;
return CAT_SCHEMA_DOES_NOT_EXIST_ERROR;
}
// All users are authorized to create objects in shared schemas.
if (objectType == COM_SHARED_SCHEMA_OBJECT)
{
schemaClass = COM_SCHEMA_CLASS_SHARED;
objectOwner = currentUser;
return 0;
}
if (objectType != COM_PRIVATE_SCHEMA_OBJECT)
{
SEABASEDDL_INTERNAL_ERROR("Unknown schema class");
objectOwner = schemaOwner = NA_UserIdDefault;
return CAT_INTERNAL_EXCEPTION_ERROR;
}
// For private schemas, the objects are always owned by the schema owner.
schemaClass = COM_SCHEMA_CLASS_PRIVATE;
objectOwner = schemaOwner;
// Root user is authorized for all create operations in private schemas. For
// installations with no authentication, all users are mapped to root database
// user, so all users have full DDL create authority.
if (currentUser == ComUser::getRootUserID())
return 0;
// If authorization is not enabled, then authentication should not be enabled
// either, and the previous check should have already returned. But just in
// case, verify authorization is enabled before proceeding. Eventually this
// state should be recorded somewhere, e.g. CLI globals.
if (!isAuthorizationEnabled())
return 0;
// If this is an internal operation, allow the operation.
if (Get_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL))
return 0;
// To create an object in a private schema, one of three conditions must be true:
//
// 1) The user is the owner of the schema.
// 2) The schema is owned by a role, and the user has been granted the role.
// 3) The user has been granted the requisite system-level SQL_OPERATIONS
// component create privilege.
//
// NOTE: In the future, schema-level create authority will be supported.
if (currentUser == schemaOwner)
return 0;
if (CmpSeabaseDDLauth::isRoleID(schemaOwner))
{
PrivMgrRoles roles(std::string(getMDSchema()),
std::string(privMgrMDLoc.data()),
CmpCommon::diags());
if (roles.hasRole(currentUser,schemaOwner))
return 0;
}
// Current user is not the schema owner. See if they have been granted the
// requisite create privilege.
if (componentPrivileges.hasSQLPriv(currentUser,operation,true))
return 0;
// TODO: When schema-level privileges are implemented, see if user has the
// requisite create privilege for this specific schema.
objectOwner = schemaOwner = NA_UserIdDefault;
return CAT_NOT_AUTHORIZED;
}
//********* End of CmpSeabaseDDL::verifyDDLCreateOperationAuthorized ***********
// *****************************************************************************
// * *
// * Function: CmpSeabaseDDL::isDDLOperationAuthorized *
// * *
// * This member function determines if a user has authority to perform a *
// * specific DDL operation. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <operation> SQLOperation In *
// * is operation the user wants to perform. *
// * *
// * <objOwner> const Int32 In *
// * is the userID of the object owner. *
// * *
// * <schemaOwner> const Int32 In *
// * is the userID of the schema owner. *
// * *
// *****************************************************************************
// * *
// * Returns: bool *
// * *
// * true: DDL operation is authorized. *
// * false: DDL operation is NOT authorized. *
// * *
// *****************************************************************************
bool CmpSeabaseDDL::isDDLOperationAuthorized(
SQLOperation operation,
const Int32 objOwner,
const Int32 schemaOwner)
{
// Root user is authorized for all operations. For installations with no
// security, all users are mapped to root database user, so all users have
// full DDL authority.
int32_t currentUser = ComUser::getCurrentUser();
if (currentUser == ComUser::getRootUserID())
return true;
// If this is an internal operation, allow the operation.
if (Get_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL))
return true;
// If authorization is not enabled, then authentication should not be enabled
// either, and the previous check should have already returned. But just in
// case, verify authorization is enabled before proceeding. Eventually this
// state should be recorded somewhere, e.g. CLI globals.
if (!isAuthorizationEnabled())
return true;
// For create operations there is no object owner; the object does not exist
// yet. Function isDDLCreateOperationAuthorized() should be called instead.
// Reject any create callers.
if (PrivMgr::isSQLCreateOperation(operation) &&
operation != SQLOperation::CREATE_INDEX)
{
SEABASEDDL_INTERNAL_ERROR("isDDLOperationAuthorized called for a create operation");
return false;
}
if (currentUser == objOwner || currentUser == schemaOwner)
return true;
NAString privMgrMDLoc;
CONCAT_CATSCH(privMgrMDLoc,getSystemCatalog(),SEABASE_PRIVMGR_SCHEMA);
if (CmpSeabaseDDLauth::isRoleID(schemaOwner))
{
PrivMgrRoles roles(std::string(getMDSchema()),
std::string(privMgrMDLoc.data()),
CmpCommon::diags());
if (roles.hasRole(currentUser,schemaOwner))
return true;
}
PrivMgrComponentPrivileges componentPrivileges(std::string(privMgrMDLoc.data()),
CmpCommon::diags());
if (componentPrivileges.hasSQLPriv(currentUser,operation,true))
return true;
//TODO: check for schema-level DDL privileges.
//TODO: check for object-level DDL privileges.
return false;
}
//************** End of CmpSeabaseDDL::isDDLOperationAuthorized ****************
// *****************************************************************************
// * *
// * Function: createSeabaseComponentOperation *
// * *
// * This functions handles the CREATE COMPONENT PRIVILEGE command. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <systemCatalog> const std::string & In *
// * is catalog where system tables reside. *
// * *
// * <pParseNode> StmtDDLCreateComponentPrivilege * In *
// * is a pointer to parse node containing the data for the CREATE *
// * COMPONENT PRIVILEGE command. *
// * *
// *****************************************************************************
static void createSeabaseComponentOperation(
const std::string & systemCatalog,
StmtDDLCreateComponentPrivilege *pParseNode)
{
NAString privMgrMDLoc;
CONCAT_CATSCH(privMgrMDLoc, systemCatalog.c_str(), SEABASE_PRIVMGR_SCHEMA);
PrivMgrCommands componentOperations(std::string(privMgrMDLoc.data()),CmpCommon::diags());
if (!CmpCommon::context()->isAuthorizationEnabled())
{
*CmpCommon::diags() << DgSqlCode(-CAT_AUTHORIZATION_NOT_ENABLED);
return;
}
const std::string componentName = pParseNode->getComponentName().data();
const std::string operationName = pParseNode->getComponentPrivilegeName().data();
const std::string operationCode = pParseNode->getComponentPrivilegeAbbreviation().data();
bool isSystem = pParseNode->isSystem();
const std::string operationDescription = pParseNode->getComponentPrivilegeDetailInformation().data();
PrivStatus retcode = STATUS_GOOD;
retcode = componentOperations.createComponentOperation(componentName,
operationName,
operationCode,
isSystem,
operationDescription);
if (retcode == STATUS_ERROR &&
CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
SEABASEDDL_INTERNAL_ERROR("CREATE COMPONENT PRIVILEGE command");
}
//****************** End of createSeabaseComponentOperation ********************
// *****************************************************************************
// * *
// * Function: dropSeabaseComponentOperation *
// * *
// * This functions handles the DROP COMPONENT PRIVILEGE command. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <systemCatalog> const std::string & In *
// * is catalog where system tables reside. *
// * *
// * <pParseNode> StmtDDLDropComponentPrivilege * In *
// * is a pointer to parse node containing the data for the DROP *
// * COMPONENT PRIVILEGE command. *
// * *
// *****************************************************************************
static void dropSeabaseComponentOperation(
const std::string & systemCatalog,
StmtDDLDropComponentPrivilege *pParseNode)
{
NAString privMgrMDLoc;
CONCAT_CATSCH(privMgrMDLoc, systemCatalog.c_str(), SEABASE_PRIVMGR_SCHEMA);
PrivMgrCommands componentOperations(std::string(privMgrMDLoc.data()),CmpCommon::diags());
if (!CmpCommon::context()->isAuthorizationEnabled())
{
*CmpCommon::diags() << DgSqlCode(-CAT_AUTHORIZATION_NOT_ENABLED);
return;
}
const std::string componentName = pParseNode->getComponentName().data();
const std::string operationName = pParseNode->getComponentPrivilegeName().data();
// Convert from SQL enums to PrivMgr enums.
PrivDropBehavior privDropBehavior;
if (pParseNode->getDropBehavior() == COM_CASCADE_DROP_BEHAVIOR)
privDropBehavior = PrivDropBehavior::CASCADE;
else
privDropBehavior = PrivDropBehavior::RESTRICT;
PrivStatus retcode = STATUS_GOOD;
retcode = componentOperations.dropComponentOperation(componentName,
operationName,
privDropBehavior);
if (retcode == STATUS_ERROR &&
CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
SEABASEDDL_INTERNAL_ERROR("DROP COMPONENT PRIVILEGE command");
}
//******************* End of dropSeabaseComponentOperation *********************
// *****************************************************************************
// * *
// * Function: grantRevokeSeabaseRole *
// * *
// * This function handles the GRANT ROLE and REVOKE ROLE commands. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <systemCatalog> const std::string & In *
// * is catalog where system tables reside. *
// * *
// * <pParseNode> StmtDDLGrantRole * In *
// * is a pointer to parse node containing the data for the GRANT *
// * ROLE or REVOKE ROLE command. *
// * *
// *****************************************************************************
static void grantRevokeSeabaseRole(
const std::string & systemCatalog,
StmtDDLRoleGrant *pParseNode)
{
NAString trafMDLocation;
CONCAT_CATSCH(trafMDLocation,systemCatalog.c_str(),SEABASE_MD_SCHEMA);
NAString privMgrMDLoc;
CONCAT_CATSCH(privMgrMDLoc,systemCatalog.c_str(),SEABASE_PRIVMGR_SCHEMA);
PrivMgrCommands roleCommand(std::string(trafMDLocation.data()),
std::string(privMgrMDLoc.data()),
CmpCommon::diags());
if (!CmpCommon::context()->isAuthorizationEnabled())
{
*CmpCommon::diags() << DgSqlCode(-CAT_AUTHORIZATION_NOT_ENABLED);
return;
}
// The GRANT ROLE and REVOKE ROLE commands each take a list of roles
// and a list of grantees (authorization names to grant the role to).
// All items on both lists need to be verified for existence and no
// duplication. The results are stored in two parallel name/ID vectors.
//
// Currently roles may only be granted to users, and may not be granted
// to PUBLIC, so some code takes shortcuts and assumes users, while other
// code is prepared for eventually supporting all authorization types.
// By default, the user issuing the GRANT or REVOKE ROLE command is
// the grantor. However, if the GRANTED BY clause is specified,
// that authorization ID is the grantor.
//
// If the GRANTED BY clause is NOT specified, and the user is
// DB__ROOT, then the GRANT/REVOKE is assumed to have been
// issued by the owner/creator of the role. So if no GRANTED BY
// clause and grantor is DB__ROOT, note it, so we can look for the
// role creator later.
int32_t grantorID = ComUser::getCurrentUser();
std::string grantorName;
bool grantorIsRoot = false;
ElemDDLGrantee *grantedBy = pParseNode->getGrantedBy();
if (grantedBy != NULL)
{
// GRANTED BY clause reserved for DB__ROOT and users with the MANAGE_ROLES
// component privilege.
if (grantorID != ComUser::getRootUserID())
{
PrivMgrComponentPrivileges componentPrivileges(std::string(privMgrMDLoc.data()),CmpCommon::diags());
if (!componentPrivileges.hasSQLPriv(grantorID,
SQLOperation::MANAGE_ROLES,
true))
{
*CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
return;
}
}
// BY clause specified. Determine the grantor
ComString grantedByName = grantedBy->getAuthorizationIdentifier();
//TODO: will need to update this if grant role to role is supported,
// i.e., the granted by could be a role. getUserIDFromUserName() only
// supports users.
if (ComUser::getUserIDFromUserName(grantedByName.data(),grantorID) != 0)
{
*CmpCommon::diags() << DgSqlCode(-CAT_AUTHID_DOES_NOT_EXIST_ERROR)
<< DgString0(grantedByName.data());
return;
}
grantorName = grantedByName.data();
} // grantedBy not null
else
{
grantorName = ComUser::getCurrentUsername();
if (grantorID == ComUser::getRootUserID())
grantorIsRoot = true;
}
// Next, walk through the list of roles being granted, making sure
// each one exists and none appear more than once. For each role,
// if the grantor is DB__ROOT, determine the creator of the role and
// use that data for the entries in the grantor vectors.
ElemDDLGranteeArray & roles = pParseNode->getRolesArray();
std::vector<int32_t> grantorIDs;
std::vector<std::string> grantorNames;
std::vector<int32_t> roleIDs;
std::vector<std::string> roleNames;
for (size_t r = 0; r < roles.entries(); r++)
{
ComString roleName(roles[r]->getAuthorizationIdentifier());
CmpSeabaseDDLrole roleInfo;
int32_t roleID;
// See if role exists
if (!roleInfo.getRoleIDFromRoleName(roleName.data(),roleID))
{
*CmpCommon::diags() << DgSqlCode(-CAT_ROLE_NOT_EXIST)
<< DgString0(roleName.data());
return;
}
// See if this role has already been specified.
if (hasValue(roleIDs,roleID))
{
*CmpCommon::diags() << DgSqlCode(-CAT_DUPLICATE_ROLES_IN_LIST)
<< DgString0(roleName.data());
return;
}
roleIDs.push_back(roleID);
roleNames.push_back(roleName.data());
// If grantor is DB__ROOT, substitute the role creator as the grantor.
if (grantorIsRoot)
{
grantorIDs.push_back(roleInfo.getAuthCreator());
char GrantorNameString[MAX_DBUSERNAME_LEN + 1];
int32_t length;
Int16 retCode = ComUser::getAuthNameFromAuthID(roleInfo.getAuthCreator(),
GrantorNameString,
sizeof(GrantorNameString),
length);
if (retCode != 0)
SEABASEDDL_INTERNAL_ERROR("Role administrator not registered");
grantorNames.push_back(GrantorNameString);
}
else
{
grantorIDs.push_back(grantorID);
grantorNames.push_back(grantorName);
}
}
// Now, walk throught the list of grantees, making sure they all exist
// and none appear more than once.
ElemDDLGranteeArray & grantees = pParseNode->getGranteeArray();
std::vector<int32_t> granteeIDs;
std::vector<std::string> granteeNames;
std::vector<PrivAuthClass> granteeClasses;
for (size_t g = 0; g < grantees.entries(); g++)
{
int32_t granteeID;
ComString granteeName(grantees[g]->getAuthorizationIdentifier());
//TODO: the parser goes through a lot of work to segregrate PUBLIC from
// other grantees, requiring more work here. Could be simplified.
// Note, _SYSTEM is not separated, but is included with other
// grantee names.
if (grantees[g]->isPublic())
{
granteeID = ComUser::getPublicUserID();
granteeName = ComUser::getPublicUserName();
}
else
{
granteeName = grantees[g]->getAuthorizationIdentifier();
Int16 retCode = ComUser::getUserIDFromUserName(granteeName.data(),granteeID);
//TODO: API only supports up/down on "is a user." Could be a role
// or PUBLIC. Instead of "name does not exist" we could say
// "name is not a user" or "Roles can only be granted to users, name is
// not a user". If support is added for granting to roles, a new
// API is needed.
if (retCode != 0)
{
*CmpCommon::diags() << DgSqlCode(-CAT_USER_NOT_EXIST)
<< DgString0(granteeName.data());
return;
}
}
// See if the grantee has already been specified.
if (hasValue(granteeIDs,granteeID))
{
*CmpCommon::diags() << DgSqlCode(-CAT_DUPLICATE_USERS_IN_LIST)
<< DgString0(granteeName.data());
return;
}
granteeIDs.push_back(granteeID);
granteeNames.push_back(granteeName.data());
granteeClasses.push_back(PrivAuthClass::USER);
}
// The WITH ADMIN option means the grantee can grant the role to another
// authorization ID. In the case of REVOKE, this ability (but not the role
// itself) is being taken from the grantee.
int32_t grantDepth = 0;
bool withAdminOptionSpecified = false;
if (pParseNode->isWithAdminOptionSpecified())
{
if (pParseNode->isGrantRole())
grantDepth = -1;
withAdminOptionSpecified = true;
}
// For REVOKE ROLE, the operation can either be RESTRICT, i.e. restrict
// the command if any dependencies exist or CASCADE, in which case any
// dependencies are silently removed. Currently only RESTRICT is supported.
PrivDropBehavior privDropBehavior = PrivDropBehavior::RESTRICT;
if (pParseNode->getDropBehavior() == COM_CASCADE_DROP_BEHAVIOR)
privDropBehavior = PrivDropBehavior::CASCADE;
else
privDropBehavior = PrivDropBehavior::RESTRICT;
PrivStatus privStatus = STATUS_GOOD;
std::string commandString;
if (pParseNode->isGrantRole())
{
commandString = "GRANT ROLE";
privStatus = roleCommand.grantRole(roleIDs,
roleNames,
grantorIDs,
grantorNames,
PrivAuthClass::USER,
granteeIDs,
granteeNames,
granteeClasses,
grantDepth);
}
else
{
commandString = "REVOKE ROLE";
privStatus = roleCommand.revokeRole(roleIDs,
granteeIDs,
granteeClasses,
grantorIDs,
withAdminOptionSpecified,
grantDepth,
privDropBehavior);
}
if (privStatus == STATUS_ERROR &&
CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
{
commandString += " command";
SEABASEDDL_INTERNAL_ERROR(commandString.c_str());
}
// update the redef timestamp for the role in auths table
char buf[(roleIDs.size()*12) + 500];
Int64 redefTime = NA_JulianTimestamp();
std::string roleList;
for (size_t i = 0; i < roleIDs.size(); i++)
{
if (i > 0)
roleList += ", ";
roleList += to_string((long long int)roleIDs[i]);
}
str_sprintf(buf, "update %s.\"%s\".%s set auth_redef_time = %ld "
"where auth_id in (%s)",
systemCatalog.c_str(), SEABASE_MD_SCHEMA, SEABASE_AUTHS,
redefTime, roleList.c_str());
ExeCliInterface cliInterface(STMTHEAP);
Int32 cliRC = cliInterface.executeImmediate(buf);
if (cliRC < 0)
cliInterface.retrieveSQLDiagnostics(CmpCommon::diags());
}
//********************** End of grantRevokeSeabaseRole *************************
// *****************************************************************************
// * *
// * Function: grantSeabaseComponentPrivilege *
// * *
// * This functions handles the GRANT COMPONENT PRIVILEGE command. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <systemCatalog> const std::string & In *
// * is catalog where system tables reside. *
// * *
// * <pParseNode> StmtDDLGrantComponentPrivilege * In *
// * is a pointer to parse node containing the data for the GRANT *
// * COMPONENT PRIVILEGE command. *
// * *
// *****************************************************************************
static void grantSeabaseComponentPrivilege(
const std::string & systemCatalog,
StmtDDLGrantComponentPrivilege *pParseNode)
{
NAString privMgrMDLoc;
CONCAT_CATSCH(privMgrMDLoc, systemCatalog.c_str(), SEABASE_PRIVMGR_SCHEMA);
PrivMgrCommands componentPrivileges(std::string(privMgrMDLoc.data()),CmpCommon::diags());
if (!CmpCommon::context()->isAuthorizationEnabled())
{
*CmpCommon::diags() << DgSqlCode(-CAT_AUTHORIZATION_NOT_ENABLED);
return;
}
const std::string componentName = pParseNode->getComponentName().data();
const ConstStringList & privList = pParseNode->getComponentPrivilegeNameList();
const NAString & granteeName = pParseNode->getUserRoleName();
int32_t granteeID;
if (ComUser::getAuthIDFromAuthName(granteeName.data(),granteeID) != 0)
{
*CmpCommon::diags() << DgSqlCode(-CAT_AUTHID_DOES_NOT_EXIST_ERROR)
<< DgString0(granteeName.data());
return;
}
int32_t grantorID = ComUser::getCurrentUser();
std::string grantorName;
ElemDDLGrantee *grantedBy = pParseNode->getGrantedBy();
if (grantedBy != NULL)
{
if (grantorID != ComUser::getRootUserID())
{
PrivMgrComponentPrivileges componentPrivileges(std::string(privMgrMDLoc.data()),CmpCommon::diags());
if (!componentPrivileges.hasSQLPriv(grantorID,
SQLOperation::MANAGE_COMPONENTS,
true))
{
*CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
return;
}
}
// BY clause specified. Determine the grantor
ComString grantedByName = grantedBy->getAuthorizationIdentifier();
if (ComUser::getAuthIDFromAuthName(grantedByName.data(),grantorID) != 0)
{
*CmpCommon::diags() << DgSqlCode(-CAT_AUTHID_DOES_NOT_EXIST_ERROR)
<< DgString0(grantedByName.data());
return;
}
grantorName = grantedByName.data();
//TODO: Cannot grant to _SYSTEM. PUBLIC ok?
}
else // Grantor is the current user.
grantorName = ComUser::getCurrentUsername();
int32_t grantDepth = 0;
if (pParseNode->isWithGrantOptionSpecified())
{
// Don't allow WGO for roles
if (CmpSeabaseDDLauth::isRoleID(granteeID) &&
(CmpCommon::getDefault(ALLOW_WGO_FOR_ROLES) == DF_OFF))
{
*CmpCommon::diags() << DgSqlCode(-CAT_WGO_NOT_ALLOWED);
return;
}
grantDepth = -1;
}
vector<std::string> operationNamesList;
for (size_t i = 0; i < privList.entries(); i++)
{
const ComString * operationName = privList[i];
operationNamesList.push_back(operationName->data());
}
PrivStatus retcode = STATUS_GOOD;
retcode = componentPrivileges.grantComponentPrivilege(componentName,
operationNamesList,
grantorID,
grantorName,
granteeID,
granteeName.data(),
grantDepth);
if (retcode == STATUS_ERROR &&
CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
SEABASEDDL_INTERNAL_ERROR("GRANT COMPONENT PRIVILEGE command");
}
//****************** End of grantSeabaseComponentPrivilege *********************
// *****************************************************************************
// * *
// * Function: hasValue *
// * *
// * This function determines if a vector contains a value. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <container> std::vector<int32_t> In *
// * is the vector of 32-bit values. *
// * *
// * <value> int32_t In *
// * is the value to be compared against existing values in the vector. *
// * *
// *****************************************************************************
static bool hasValue(
std::vector<int32_t> container,
int32_t value)
{
for (size_t index = 0; index < container.size(); index++)
if (container[index] == value)
return true;
return false;
}
//***************************** End of hasValue ********************************
// *****************************************************************************
// * *
// * Function: CmpSeabaseDDL::registerSeabaseComponent *
// * *
// * This function handles register (adding) and unregister (drop) of *
// * components known to the Privilege Manager. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <pParseNode> StmtDDLRegisterComponent * In *
// * is a pointer to parse node containing the data for the REGISTER or *
// * UNREGISTER COMPONENT command. *
// * *
// *****************************************************************************
void CmpSeabaseDDL::registerSeabaseComponent(StmtDDLRegisterComponent *pParseNode)
{
NAString privMgrMDLoc;
CONCAT_CATSCH(privMgrMDLoc, getSystemCatalog(), SEABASE_PRIVMGR_SCHEMA);
PrivMgrCommands component(std::string(privMgrMDLoc.data()),CmpCommon::diags());
if (!isAuthorizationEnabled())
{
*CmpCommon::diags() << DgSqlCode(-CAT_AUTHORIZATION_NOT_ENABLED);
return;
}
const std::string componentName = pParseNode->getExternalComponentName().data();
PrivStatus retcode = STATUS_GOOD;
switch (pParseNode->getRegisterComponentType())
{
case StmtDDLRegisterComponent::REGISTER_COMPONENT:
{
const NAString details = pParseNode->getRegisterComponentDetailInfo();
bool isSystem = pParseNode->isSystem();
const std::string componentDetails = details.data();
retcode = component.registerComponent(componentName,isSystem,componentDetails);
break;
}
case StmtDDLRegisterComponent::UNREGISTER_COMPONENT:
{
PrivDropBehavior privDropBehavior;
if (pParseNode->getDropBehavior() == COM_CASCADE_DROP_BEHAVIOR)
privDropBehavior = PrivDropBehavior::CASCADE;
else
privDropBehavior = PrivDropBehavior::RESTRICT;
retcode = component.unregisterComponent(componentName,privDropBehavior);
}
break;
default:
retcode = STATUS_ERROR;
}
if (retcode == STATUS_ERROR &&
CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
SEABASEDDL_INTERNAL_ERROR("REGISTER/UNREGISTER COMPONENT command");
}
//************** End of CmpSeabaseDDL::registerSeabaseComponent ****************
// *****************************************************************************
// * *
// * Function: revokeSeabaseComponentPrivilege *
// * *
// * This functions handles the REVOKE COMPONENT PRIVILEGE command. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <systemCatalog> const std::string & In *
// * is catalog where system tables reside. *
// * *
// * <pParseNode> StmtDDLRevokeComponentPrivilege * In *
// * is a pointer to parse node containing the data for the REVOKE *
// * COMPONENT PRIVILEGE command. *
// * *
// *****************************************************************************
static void revokeSeabaseComponentPrivilege(
const std::string & systemCatalog,
StmtDDLRevokeComponentPrivilege *pParseNode)
{
NAString privMgrMDLoc;
CONCAT_CATSCH(privMgrMDLoc, systemCatalog.c_str(), SEABASE_PRIVMGR_SCHEMA);
PrivMgrCommands componentPrivileges(std::string(privMgrMDLoc.data()),CmpCommon::diags());
if (!CmpCommon::context()->isAuthorizationEnabled())
{
*CmpCommon::diags() << DgSqlCode(-CAT_AUTHORIZATION_NOT_ENABLED);
return;
}
const std::string componentName = pParseNode->getComponentName().data();
const ConstStringList & privList = pParseNode->getComponentPrivilegeNameList();
const NAString & granteeName = pParseNode->getUserRoleName();
int32_t granteeID;
if (ComUser::getAuthIDFromAuthName(granteeName.data(),granteeID) != 0)
{
*CmpCommon::diags() << DgSqlCode(-CAT_AUTHID_DOES_NOT_EXIST_ERROR)
<< DgString0(granteeName.data());
return;
}
int32_t grantorID = ComUser::getCurrentUser();
ElemDDLGrantee *grantedBy = pParseNode->getGrantedBy();
if (grantedBy != NULL)
{
if (grantorID != ComUser::getRootUserID())
{
PrivMgrComponentPrivileges componentPrivileges(std::string(privMgrMDLoc.data()),CmpCommon::diags());
if (!componentPrivileges.hasSQLPriv(grantorID,
SQLOperation::MANAGE_COMPONENTS,
true))
{
*CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED);
return;
}
}
// BY clause specified. Determine the grantor
ComString grantedByName = grantedBy->getAuthorizationIdentifier();
if (ComUser::getAuthIDFromAuthName(grantedByName.data(),grantorID) != 0)
{
*CmpCommon::diags() << DgSqlCode(-CAT_AUTHID_DOES_NOT_EXIST_ERROR)
<< DgString0(grantedByName.data());
return;
}
} // grantedBy not null
bool isGOFSpecified = false;
if (pParseNode->isGrantOptionForSpecified())
isGOFSpecified = true;
vector<std::string> operationNamesList;
for (size_t i = 0; i < privList.entries(); i++)
{
const ComString * operationName = privList[i];
operationNamesList.push_back(operationName->data());
}
PrivStatus retcode = STATUS_GOOD;
PrivDropBehavior dropBehavior = PrivDropBehavior::RESTRICT;
retcode = componentPrivileges.revokeComponentPrivilege(componentName,
operationNamesList,
grantorID,
granteeID,
isGOFSpecified,
dropBehavior);
if (retcode == STATUS_ERROR &&
CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
SEABASEDDL_INTERNAL_ERROR("REVOKE COMPONENT PRIVILEGE command");
}
//****************** End of revokeSeabaseComponentPrivilege ********************
short
CmpSeabaseDDL::setupHbaseOptions(ElemDDLHbaseOptions * hbaseOptionsClause,
Int32 numSplits, const NAString& objName,
NAList<HbaseCreateOption*>& hbaseCreateOptions,
NAString& hco)
{
NAText hbaseOptionsStr;
NABoolean maxFileSizeOptionSpecified = FALSE;
NABoolean splitPolicyOptionSpecified = FALSE;
const char *maxFileSizeOptionString = "MAX_FILESIZE";
const char *splitPolicyOptionString = "SPLIT_POLICY";
NABoolean dataBlockEncodingOptionSpecified = FALSE;
NABoolean compressionOptionSpecified = FALSE;
NABoolean memstoreFlushSizeOptionSpecified = FALSE;
const char *dataBlockEncodingOptionString = "DATA_BLOCK_ENCODING";
const char *compressionOptionString = "COMPRESSION";
const char *flushSizeOptionString = "MEMSTORE_FLUSH_SIZE";
Lng32 numHbaseOptions = 0;
if (hbaseOptionsClause)
{
for (CollIndex i = 0; i < hbaseOptionsClause->getHbaseOptions().entries();
i++)
{
HbaseCreateOption * hbaseOption =
hbaseOptionsClause->getHbaseOptions()[i];
hbaseCreateOptions.insert(hbaseOption);
if (hbaseOption->key() == maxFileSizeOptionString)
maxFileSizeOptionSpecified = TRUE;
else if (hbaseOption->key() == splitPolicyOptionString)
splitPolicyOptionSpecified = TRUE;
else if (hbaseOption->key() == dataBlockEncodingOptionString)
dataBlockEncodingOptionSpecified = TRUE;
else if (hbaseOption->key() == compressionOptionString)
compressionOptionSpecified = TRUE;
else if (hbaseOption->key() == flushSizeOptionString)
memstoreFlushSizeOptionSpecified= TRUE;
hbaseOptionsStr += hbaseOption->key();
hbaseOptionsStr += "='";
hbaseOptionsStr += hbaseOption->val();
hbaseOptionsStr += "'";
hbaseOptionsStr += "|";
}
numHbaseOptions += hbaseOptionsClause->getHbaseOptions().entries();
}
if (numSplits > 0 /* i.e. a salted table */)
{
// set table-specific region split policy and max file
// size, controllable by CQDs, but only if they are not
// already set explicitly in the DDL.
// Save these options in metadata if they are specified by user through
// explicit create option or through a cqd.
double maxFileSize =
CmpCommon::getDefaultNumeric(HBASE_SALTED_TABLE_MAX_FILE_SIZE);
NABoolean usePerTableSplitPolicy =
(CmpCommon::getDefault(HBASE_SALTED_TABLE_SET_SPLIT_POLICY) == DF_ON);
HbaseCreateOption * hbaseOption = NULL;
if (maxFileSize > 0 && !maxFileSizeOptionSpecified)
{
char fileSizeOption[100];
Int64 maxFileSizeInt;
if (maxFileSize < LLONG_MAX)
maxFileSizeInt = maxFileSize;
else
maxFileSizeInt = LLONG_MAX;
snprintf(fileSizeOption,100,"%ld", maxFileSizeInt);
hbaseOption = new(STMTHEAP)
HbaseCreateOption("MAX_FILESIZE", fileSizeOption);
hbaseCreateOptions.insert(hbaseOption);
if (ActiveSchemaDB()->getDefaults().userDefault(
HBASE_SALTED_TABLE_MAX_FILE_SIZE) == TRUE)
{
numHbaseOptions += 1;
snprintf(fileSizeOption,100,"MAX_FILESIZE='%ld'|", maxFileSizeInt);
hbaseOptionsStr += fileSizeOption;
}
}
if (usePerTableSplitPolicy && !splitPolicyOptionSpecified)
{
const char *saltedTableSplitPolicy =
"org.apache.hadoop.hbase.regionserver.ConstantSizeRegionSplitPolicy";
hbaseOption = new(STMTHEAP) HbaseCreateOption(
"SPLIT_POLICY", saltedTableSplitPolicy);
hbaseCreateOptions.insert(hbaseOption);
if (ActiveSchemaDB()->getDefaults().userDefault(
HBASE_SALTED_TABLE_SET_SPLIT_POLICY) == TRUE)
{
numHbaseOptions += 1;
hbaseOptionsStr += "SPLIT_POLICY='";
hbaseOptionsStr += saltedTableSplitPolicy;
hbaseOptionsStr += "'|";
}
}
}
NAString dataBlockEncoding =
CmpCommon::getDefaultString(HBASE_DATA_BLOCK_ENCODING_OPTION);
NAString compression =
CmpCommon::getDefaultString(HBASE_COMPRESSION_OPTION);
NAString flushSize =
CmpCommon::getDefaultString(HBASE_MEMSTORE_FLUSH_SIZE_OPTION);
HbaseCreateOption * hbaseOption = NULL;
char optionStr[200];
if (!dataBlockEncoding.isNull() && !dataBlockEncodingOptionSpecified)
{
hbaseOption = new(STMTHEAP) HbaseCreateOption("DATA_BLOCK_ENCODING",
dataBlockEncoding.data());
hbaseCreateOptions.insert(hbaseOption);
if (ActiveSchemaDB()->getDefaults().userDefault
(HBASE_DATA_BLOCK_ENCODING_OPTION) == TRUE)
{
numHbaseOptions += 1;
snprintf(optionStr, 200, "DATA_BLOCK_ENCODING='%s'|", dataBlockEncoding.data());
hbaseOptionsStr += optionStr;
}
}
if (!flushSize.isNull() && !memstoreFlushSizeOptionSpecified)
{
hbaseOption = new(STMTHEAP) HbaseCreateOption("MEMSTORE_FLUSH_SIZE",
flushSize.data());
hbaseCreateOptions.insert(hbaseOption);
if (ActiveSchemaDB()->getDefaults().userDefault
(HBASE_MEMSTORE_FLUSH_SIZE_OPTION) == TRUE)
{
numHbaseOptions += 1;
snprintf(optionStr, 200, "MEMSTORE_FLUSH_SIZE='%s'|", flushSize.data());
hbaseOptionsStr += optionStr;
}
}
if (!compression.isNull() && !compressionOptionSpecified)
{
hbaseOption = new(STMTHEAP) HbaseCreateOption("COMPRESSION",
compression.data());
hbaseCreateOptions.insert(hbaseOption);
if (ActiveSchemaDB()->getDefaults().userDefault
(HBASE_COMPRESSION_OPTION) == TRUE)
{
numHbaseOptions += 1;
snprintf(optionStr, 200, "COMPRESSION='%s'|", compression.data());
hbaseOptionsStr += optionStr;
}
}
/////////////////////////////////////////////////////////////////////
// update HBASE_CREATE_OPTIONS field in metadata TABLES table.
// Format of data stored in this field, if applicable.
// HBASE_OPTIONS=>numOptions(4bytes)option='val'| ...
///////////////////////////////////////////////////////////////////////
if (hbaseOptionsStr.size() > 0)
{
hco += "HBASE_OPTIONS=>";
char hbaseOptionsNumCharStr[HBASE_OPTION_MAX_INTEGER_LENGTH];
snprintf(hbaseOptionsNumCharStr, HBASE_OPTION_MAX_INTEGER_LENGTH, "%04d", numHbaseOptions);
hco += hbaseOptionsNumCharStr;
hco += hbaseOptionsStr.data();
hco += " "; // separator
}
if (hco.length() > HBASE_OPTIONS_MAX_LENGTH)
{
*CmpCommon::diags() << DgSqlCode(-CAT_INVALID_HBASE_OPTIONS_CLAUSE)
<< DgString0(objName);
return -1 ;
}
return 0;
}