| /********************************************************************** |
| // @@@ 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: ExExeUtilCommon.cpp |
| * Description: |
| * |
| * |
| * Language: C++ |
| * |
| * |
| * |
| * |
| ***************************************************************************** |
| */ |
| |
| #include "ComCextdecs.h" |
| #include "ComSizeDefs.h" |
| #include "cli_stdh.h" |
| #include "ex_stdh.h" |
| #include "sql_id.h" |
| #include "ex_transaction.h" |
| #include "ComTdb.h" |
| #include "ex_tcb.h" |
| #include "ComSqlId.h" |
| |
| #include "ExExeUtil.h" |
| #include "ex_exe_stmt_globals.h" |
| #include "exp_expr.h" |
| #include "exp_clause_derived.h" |
| #include "ComRtUtils.h" |
| #include "ExStats.h" |
| #include "ComSmallDefs.h" |
| |
| #include "logmxevent.h" |
| |
| // Generate a lock name from the input simple object name and the given suffix. |
| // If the generated name is longer than 128 NAWchar's, remove the extra char's |
| // from the simple object name part in the generated lock name without changing |
| // the suffix. |
| // |
| static NABoolean generateLockName(const char * objInternal1PartName, // in UTF-8 format |
| const char * lockSuffix, // contains 7-bit ASCII chars only |
| char * lockInternal1PartNameOutBuf, // in UTF-8 format |
| Int32 lockInInternal1PartNameOutBufLen) // in bytes |
| { |
| Int32 objInt1PartNameLen = str_len(objInternal1PartName); |
| char *tempPtr; |
| char buf[20]; |
| Int32 hashValue = 0; |
| Int32 suffixLen = str_len(lockSuffix)+8; // 8 characters for hashvalue of truncated |
| // object name |
| // More than 60 characters won't be truncated and hence 8 characters should be |
| // good enough |
| Int32 allowedLen = lightValidateUTF8Str(objInternal1PartName, |
| objInt1PartNameLen, |
| // max allowed chars in UTF-8 (same as allowed bytes in ISO) |
| ComMAX_1_PART_INTERNAL_ISO88591_NAME_LEN -suffixLen); |
| |
| if (lockInternal1PartNameOutBuf == NULL || |
| allowedLen + suffixLen >= lockInInternal1PartNameOutBufLen) |
| return FALSE; |
| if (allowedLen < objInt1PartNameLen) |
| { |
| // Just simple hashing by adding the byte contents |
| tempPtr = (char *)objInternal1PartName + allowedLen; |
| for (; *tempPtr != '\0';) |
| hashValue += *tempPtr++; |
| } |
| str_cpy_all(lockInternal1PartNameOutBuf, |
| objInternal1PartName, |
| allowedLen); |
| lockInternal1PartNameOutBuf[allowedLen] = '\0'; |
| if (hashValue > 0) |
| { |
| str_sprintf(buf, "%d", hashValue); |
| buf[8] = '\0'; |
| strcat(lockInternal1PartNameOutBuf, buf); |
| } |
| strcat(lockInternal1PartNameOutBuf, lockSuffix); |
| return TRUE; |
| } |
| |
| ex_tcb * ExExeUtilTdb::build(ex_globals * glob) |
| { |
| ExExeUtilTcb * exe_util_tcb; |
| |
| exe_util_tcb = new(glob->getSpace()) ExExeUtilTcb(*this, NULL, glob); |
| |
| exe_util_tcb->registerSubtasks(); |
| |
| return (exe_util_tcb); |
| } |
| |
| |
| //////////////////////////////////////////////////////////////// |
| // Constructor for class ExExeUtilTcb |
| /////////////////////////////////////////////////////////////// |
| ExExeUtilTcb::ExExeUtilTcb(const ComTdbExeUtil & exe_util_tdb, |
| const ex_tcb * child_tcb, // for child queue |
| ex_globals * glob) |
| : ex_tcb( exe_util_tdb, 1, glob), |
| workAtp_(NULL), |
| query_(NULL), |
| infoList_(NULL), |
| infoListIsOutputInfo_(TRUE), |
| explQuery_(NULL), |
| childQueryId_(NULL), |
| childQueryIdLen_(0), |
| outputBuf_(NULL) |
| { |
| Space * space = (glob ? glob->getSpace() : 0); |
| CollHeap * heap = (glob ? glob->getDefaultHeap() : 0); |
| |
| // Allocate the buffer pool |
| pool_ = new(space) sql_buffer_pool(exe_util_tdb.numBuffers_, |
| exe_util_tdb.bufferSize_, |
| space); |
| |
| childTcb_ = child_tcb; |
| if (childTcb_) |
| { |
| qchild_ = childTcb_->getParentQueue(); |
| } |
| |
| // Allocate the queue to communicate with parent |
| qparent_.down = new(space) ex_queue(ex_queue::DOWN_QUEUE, |
| exe_util_tdb.queueSizeDown_, |
| exe_util_tdb.criDescDown_, |
| space); |
| |
| qparent_.up = new(space) ex_queue(ex_queue::UP_QUEUE, |
| exe_util_tdb.queueSizeUp_, |
| exe_util_tdb.criDescUp_, |
| space); |
| |
| if (exe_util_tdb.workCriDesc_) |
| { |
| workAtp_ = allocateAtp(exe_util_tdb.workCriDesc_, glob->getSpace()); |
| pool_->get_free_tuple(workAtp_->getTupp(((ComTdbExeUtil&)exe_util_tdb).workAtpIndex()), 0); |
| } |
| |
| tcbFlags_ = 0; |
| |
| if (exe_util_tdb.inputExpr_) |
| (void)exe_util_tdb.inputExpr_->fixup(0, getExpressionMode(), this, |
| space, heap, FALSE, glob); |
| if (exe_util_tdb.outputExpr_) |
| (void)exe_util_tdb.outputExpr_->fixup(0, getExpressionMode(), this, |
| space, heap, FALSE, glob); |
| |
| if (exe_util_tdb.scanExpr_) |
| (void)exe_util_tdb.scanExpr_->fixup(0, getExpressionMode(), this, |
| space, heap, FALSE, glob); |
| |
| ContextCli * currContext = |
| (glob->castToExExeStmtGlobals()->castToExMasterStmtGlobals() ? |
| glob->castToExExeStmtGlobals()->castToExMasterStmtGlobals()->getStatement()->getContext() : |
| NULL); |
| |
| // internal queries are already in isoMapping and do not need to be |
| // translated before sending to mxcmp. |
| // Set the ISO_MAPPING charset code to indicate that. |
| char *parentQid; |
| if (glob->castToExExeStmtGlobals()->castToExMasterStmtGlobals()) |
| parentQid = glob->castToExExeStmtGlobals()->castToExMasterStmtGlobals()->getStatement()->getUniqueStmtId(); |
| else |
| if (glob->castToExExeStmtGlobals()->castToExEspStmtGlobals() && |
| glob->castToExExeStmtGlobals()->castToExEspStmtGlobals()->getStmtStats()) |
| parentQid = glob->castToExExeStmtGlobals()->castToExEspStmtGlobals()->getStmtStats()->getQueryId(); |
| else |
| parentQid = NULL; |
| |
| cliInterface_ = new(heap) ExeCliInterface(heap, |
| SQLCHARSETCODE_ISO88591, // ISO_MAPPING=ISO88591 |
| currContext, |
| parentQid); |
| |
| cliInterface2_ = new(heap) ExeCliInterface(heap, |
| SQLCHARSETCODE_ISO88591, // ISO_MAPPING=ISO88591 |
| currContext, |
| parentQid); |
| |
| diagsArea_ = NULL; |
| |
| pqStep_ = PROLOGUE_; |
| |
| VersionToString(COM_VERS_MXV, versionStr_); |
| versionStrLen_ = DIGITS_IN_VERSION_NUMBER; |
| |
| VersionToString(COM_VERS_MXV, sysVersionStr_); |
| sysVersionStrLen_ = DIGITS_IN_VERSION_NUMBER; |
| |
| extractedPartsObj_ = NULL; |
| }; |
| |
| ExExeUtilTcb::~ExExeUtilTcb() |
| { |
| delete qparent_.up; |
| delete qparent_.down; |
| if (workAtp_) |
| { |
| workAtp_->release(); |
| deallocateAtp(workAtp_, getGlobals()->getSpace()); |
| workAtp_ = NULL; |
| } |
| freeResources(); |
| |
| if (extractedPartsObj_) |
| { |
| delete extractedPartsObj_; |
| extractedPartsObj_ = NULL; |
| } |
| if (explQuery_) |
| NADELETEBASIC(explQuery_, getHeap()); |
| if (childQueryId_ != NULL) |
| { |
| NADELETEBASIC(childQueryId_, getHeap()); |
| childQueryId_ = NULL; |
| childQueryIdLen_ = 0; |
| } |
| if (outputBuf_ != NULL) |
| { |
| NADELETEBASIC(outputBuf_, getHeap()); |
| outputBuf_ = NULL; |
| outputBuf_ = 0; |
| } |
| |
| }; |
| |
| ex_queue_pair ExExeUtilTcb::getParentQueue() const {return qparent_;} |
| |
| Int32 ExExeUtilTcb::orderedQueueProtocol() const |
| { |
| return ((const ExExeUtilTdb &)tdb).orderedQueueProtocol(); |
| } |
| |
| Int32 ExExeUtilTcb::numChildren() const |
| { |
| if (childTcb_) |
| return 1; |
| else |
| return 0; |
| } |
| |
| const ex_tcb* ExExeUtilTcb::getChild(Int32 pos) const |
| { |
| if (pos == 0) |
| return childTcb_; |
| else |
| return NULL; |
| }; |
| |
| void ExExeUtilTcb::freeResources() |
| { |
| delete pool_; |
| pool_ = 0; |
| } |
| |
| short ExExeUtilTcb::work() |
| { |
| // nothing implemented here, the derived classes contains real work. |
| ex_assert(0, "ExExeUtilTcb::work() MUST be redefined"); |
| return -1; |
| } |
| |
| NABoolean ExExeUtilTcb::isUpQueueFull(short size) |
| { |
| if ((qparent_.up->getSize() - qparent_.up->getLength()) < size) |
| return TRUE; |
| else |
| return FALSE; |
| } |
| |
| short ExExeUtilTcb::moveRowToUpQueue(const char * row, Lng32 len, |
| short * rc, NABoolean isVarchar) |
| { |
| short retcode = ex_tcb::moveRowToUpQueue(&qparent_, exeUtilTdb().tuppIndex_, |
| row, len, rc, isVarchar); |
| return retcode; |
| } |
| |
| char * ExExeUtilTcb::getTimeAsString(Int64 elapsedTime, char * timeBuf, |
| NABoolean noUsec) |
| { |
| ULng32 sec = (ULng32) (elapsedTime / 1000000); |
| ULng32 usec = (ULng32) (elapsedTime % 1000000); |
| ULng32 min = sec/60; |
| sec = sec % 60; |
| ULng32 hour = min/60; |
| min = min % 60; |
| |
| if (noUsec) |
| str_sprintf (timeBuf, "%02u:%02u:%02u", |
| hour, min, sec); |
| else |
| str_sprintf (timeBuf, "%02u:%02u:%02u.%03u", |
| hour, min, sec, TO_FMT3u(usec)); |
| |
| return timeBuf; |
| } |
| |
| char * ExExeUtilTcb::getTimestampAsString(Int64 juliantimestamp, |
| char * timeBuf) |
| { |
| short timestamp[8]; |
| Int64 localTimestamp = CONVERTTIMESTAMP(juliantimestamp,0,-1,0); |
| INTERPRETTIMESTAMP(localTimestamp, timestamp); |
| short year = timestamp[0]; |
| char month = (char) timestamp[1]; |
| char day = (char) timestamp[2]; |
| char hour = (char) timestamp[3]; |
| char minute = (char) timestamp[4]; |
| char second = (char) timestamp[5]; |
| Lng32 fraction = timestamp[6] * 1000 + timestamp[7]; |
| |
| str_sprintf (timeBuf, "%04u-%02u-%02u %02u:%02u:%02u.%03u", |
| year, month, day, hour, minute, second, fraction); |
| |
| return timeBuf; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // Method: glueQueryFragments |
| // |
| // This method combines the pieces of the metadata query into a single |
| // statement. As part of this process, the leading spaces are removed. |
| // |
| // Input: queryArraySize - number of fragments to glue together |
| // QueryString - the fragments |
| // |
| // Output: gluedQuery - the concatenated fragments |
| // gluedQuerySize - the final length |
| // |
| // Space is allocated for the gluedQuery |
| // ---------------------------------------------------------------------------- |
| void ExExeUtilTcb::glueQueryFragments(Lng32 queryArraySize, |
| const QueryString * queryArray, |
| char * &gluedQuery, |
| Lng32 &gluedQuerySize) |
| { |
| Int32 i = 0; |
| gluedQuerySize = 0; |
| gluedQuery = NULL; |
| NAString concatenatedQuery; |
| NAString tempStr; |
| |
| for (i = 0; i < queryArraySize; i++) |
| { |
| tempStr = queryArray[i].str; |
| concatenatedQuery += tempStr.strip(NAString::leading, ' '); |
| } |
| |
| gluedQuerySize = concatenatedQuery.length(); |
| gluedQuery = new(getMyHeap()) char[gluedQuerySize + 100]; |
| strncpy(gluedQuery, concatenatedQuery.data(), gluedQuerySize); |
| gluedQuery[gluedQuerySize] = '\0'; |
| } |
| |
| Lng32 ExExeUtilTcb::changeAuditAttribute(char * tableName, |
| NABoolean makeAudited, |
| NABoolean isVolatile, |
| NABoolean isIndex, |
| NABoolean parallelAlter) |
| { |
| Lng32 retcode = 0; |
| |
| // Get the globals stucture of the master executor. |
| ExExeStmtGlobals *exeGlob = getGlobals()->castToExExeStmtGlobals(); |
| ExMasterStmtGlobals *masterGlob = exeGlob->castToExMasterStmtGlobals(); |
| |
| // set sqlparserflags to allow change of audit attribute |
| masterGlob->getStatement()->getContext()->setSqlParserFlags(0x400); // ALLOW_AUDIT_CHANGE |
| |
| // make table unaudited |
| char stmt[500]; |
| strcpy(stmt, "alter "); |
| if (isVolatile) |
| strcat(stmt, "volatile "); |
| strcat(stmt, "table "); |
| strcat(stmt, tableName); |
| if (makeAudited) |
| strcat(stmt, " attribute audit"); |
| else |
| strcat(stmt, " attribute no audit"); |
| |
| if (parallelAlter) |
| strcat(stmt, " no label update"); |
| |
| strcat(stmt, ";"); |
| ComDiagsArea *diagsArea = getDiagsArea(); |
| retcode = cliInterface()->executeImmediate |
| (stmt, NULL, NULL, TRUE, NULL, 0, &diagsArea); |
| setDiagsArea(diagsArea); |
| masterGlob->getStatement()->getContext()->resetSqlParserFlags(0x400); // ALLOW_AUDIT_CHANGE |
| |
| if (retcode < 0) |
| return retcode; |
| |
| if (parallelAlter) |
| { |
| retcode = alterAuditFlag(makeAudited, tableName, isIndex); |
| if (retcode < 0) |
| return retcode; |
| } |
| |
| return 0; |
| } |
| |
| void ExExeUtilTcb::handleErrors(Lng32 rc) |
| { |
| cliInterface()->allocAndRetrieveSQLDiagnostics(diagsArea_); |
| } |
| |
| short ExExeUtilTcb::initializeInfoList(Queue* &infoList) |
| { |
| return cliInterface()->initializeInfoList(infoList, infoListIsOutputInfo_); |
| } |
| |
| short ExExeUtilTcb::fetchAllRows(Queue * &infoList, |
| char * query, |
| Lng32 numOutputEntries, |
| NABoolean varcharFormat, |
| short &rc, |
| NABoolean monitorThis) |
| { |
| rc = cliInterface()->fetchAllRows(infoList, query, numOutputEntries, varcharFormat, |
| monitorThis); |
| if (rc < 0) |
| { |
| handleErrors(rc); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| char * ExExeUtilTcb::getStatusString(const char * operation, |
| const char * status, |
| const char * object, |
| char * outBuf, |
| NABoolean isET, |
| char * timeBuf, |
| char * queryBuf, |
| char * errorBuf) |
| { |
| if (! outBuf) |
| return NULL; |
| |
| char o[16]; |
| char s[10]; |
| byte_str_cpy(o, 15, operation, strlen(operation), ' '); |
| o[15] = 0; |
| byte_str_cpy(s, 9, status, strlen(status), ' '); |
| s[9] = 0; |
| if (queryBuf) |
| { |
| str_sprintf(outBuf, "Task: %s Status: %s Command: %s", |
| o, s, queryBuf); |
| } |
| else if (timeBuf && isET) |
| { |
| str_sprintf(outBuf, "Task: %s Status: %s Elapsed Time: %s", |
| o, s, timeBuf); |
| } |
| else if (errorBuf) |
| { |
| str_sprintf(outBuf, "Task: %s Status: %s Details: %s", |
| o, s, errorBuf); |
| } |
| else if (timeBuf) |
| { |
| str_sprintf(outBuf, "Task: %s Status: %s Time: %s", |
| o, s, timeBuf); |
| } |
| else |
| { |
| if (object) |
| str_sprintf(outBuf, "Task: %s Status: %s Object: %s", |
| o, s, object); |
| else |
| str_sprintf(outBuf, "Task: %s Status: %s", |
| o, s); |
| } |
| |
| return outBuf; |
| } |
| |
| short ExExeUtilTcb::executeQuery(char * task, |
| char * object, |
| char * query, |
| NABoolean displayStartTime, |
| NABoolean displayEndTime, |
| short &rc, |
| short * warning, |
| Lng32 * ec, |
| NABoolean moveErrorRow, |
| NABoolean continueOnError, |
| NABoolean monitorThis) |
| { |
| short retcode = 0; |
| char buf[BUFFER_SIZE]; |
| char timeBuf[200]; |
| |
| while (1) |
| { |
| switch (pqStep_) |
| { |
| case PROLOGUE_: |
| { |
| warning_ = 0; |
| startTime_ = NA_JulianTimestamp(); |
| elapsedTime_ = 0; |
| if (displayStartTime) |
| { |
| getTimestampAsString(startTime_, timeBuf); |
| getStatusString(task, "Started", object, buf, FALSE, timeBuf); |
| if (moveRowToUpQueue(buf, 0, &rc)) |
| return 1; |
| } |
| |
| pqStep_ = EXECUTE_; |
| rc = WORK_RESCHEDULE_AND_RETURN; |
| return 1; |
| } |
| break; |
| |
| case EXECUTE_: |
| { |
| retcode = cliInterface()->fetchRowsPrologue(query,FALSE,monitorThis); |
| if (retcode < 0) |
| { |
| pqStep_ = ERROR_RETURN_; |
| break; |
| } |
| |
| pqStep_ = FETCH_ROW_; |
| } |
| break; |
| |
| case FETCH_ROW_: |
| { |
| retcode = (short)cliInterface()->fetch(); |
| if (retcode < 0) |
| { |
| pqStep_ = ERROR_RETURN_; |
| break; |
| } |
| |
| if ((retcode > 0) && |
| (retcode != 100)) |
| warning_ = retcode; |
| |
| if ((retcode != 100) && |
| (cliInterface()->outputBuf())) |
| pqStep_ = RETURN_ROW_; |
| else |
| pqStep_ = CLOSE_; |
| } |
| break; |
| |
| case RETURN_ROW_: |
| { |
| char * ptr; |
| Lng32 len; |
| |
| cliInterface()->getPtrAndLen(1, ptr, len); |
| retcode = moveRowToUpQueue(ptr, len, &rc); |
| if (retcode) |
| return 1; |
| |
| pqStep_ = FETCH_ROW_; |
| } |
| break; |
| |
| case CLOSE_: |
| { |
| retcode = cliInterface()->fetchRowsEpilogue(""); |
| if (retcode < 0) |
| { |
| pqStep_ = ERROR_RETURN_; |
| break; |
| } |
| |
| pqStep_ = EPILOGUE_; |
| } |
| break; |
| |
| case EPILOGUE_: |
| { |
| endTime_ = NA_JulianTimestamp(); |
| elapsedTime_ = endTime_ - startTime_; |
| |
| if (displayEndTime) |
| { |
| getTimestampAsString(endTime_, timeBuf); |
| getStatusString(task, "Ended", object, buf, FALSE, timeBuf); |
| if (moveRowToUpQueue(buf, 0, &rc)) |
| return 1; |
| getTimeAsString(elapsedTime_, timeBuf); |
| getStatusString(task, "Ended", object, buf, TRUE, timeBuf); |
| if (moveRowToUpQueue(buf, 0, &rc)) |
| return 1; |
| } |
| |
| pqStep_ = ALL_DONE_; |
| rc = WORK_RESCHEDULE_AND_RETURN; |
| return 1; |
| } |
| break; |
| |
| case ERROR_RETURN_: |
| { |
| Lng32 sqlcode = 0; |
| char * stringParam1 = NULL; |
| Lng32 intParam1 = ComDiags_UnInitialized_Int; |
| |
| cliInterface()->allocAndRetrieveSQLDiagnostics(diagsArea_); |
| if (getDiagsArea() != NULL) |
| retcode = 0; |
| if (moveErrorRow) |
| { |
| if (retcode == 0) |
| { |
| ComDiagsArea * da = getDiagsArea(); |
| |
| sqlcode = (short)da->mainSQLCODE(); |
| |
| ComCondition * cc; |
| if (sqlcode < 0) |
| cc = da->getErrorEntry(1); |
| else |
| cc = da->getWarningEntry(1); |
| |
| if (sqlcode < 0 && ec != NULL) |
| *ec = sqlcode; |
| |
| if (cc->getOptionalStringCharSet(0) == CharInfo::ISO88591 || cc->getOptionalStringCharSet(0) == CharInfo::UTF8) |
| stringParam1 = (char*)cc->getOptionalString(0); |
| else |
| stringParam1 = NULL; |
| intParam1 = cc->getOptionalInteger(0); |
| } |
| else |
| { |
| sqlcode = retcode; |
| } |
| |
| Lng32 errorBufLen = |
| 200 + (stringParam1 ? strlen(stringParam1) : 0); |
| |
| char * errorBuf = new(getHeap()) char[errorBufLen]; |
| |
| str_sprintf(errorBuf, "%d", sqlcode); |
| if (stringParam1) |
| str_sprintf(&errorBuf[strlen(errorBuf)], ", %s", stringParam1); |
| if (intParam1 != ComDiags_UnInitialized_Int) |
| str_sprintf(&errorBuf[strlen(errorBuf)], ", %d", intParam1); |
| |
| char * outBuf = new(getHeap()) char[errorBufLen+400]; |
| getStatusString(task, "Error", NULL, outBuf, |
| FALSE, NULL, |
| errorBuf); |
| |
| NADELETEBASIC(errorBuf, getHeap()); |
| |
| if ((moveErrorRow) && |
| (moveRowToUpQueue(outBuf, 0, &rc))) |
| { |
| NADELETEBASIC(outBuf, getHeap()); |
| |
| return 1; |
| } |
| |
| NADELETEBASIC(outBuf, getHeap()); |
| } |
| |
| // close cursor, etc. Ignore errors. |
| cliInterface()->fetchRowsEpilogue(""); |
| |
| if (continueOnError) |
| { |
| pqStep_ = ALL_DONE_; |
| |
| rc = WORK_RESCHEDULE_AND_RETURN; |
| return 1; |
| } |
| else |
| { |
| pqStep_ = PROLOGUE_; |
| return -1; |
| } |
| } |
| break; |
| |
| case ALL_DONE_: |
| { |
| pqStep_ = PROLOGUE_; |
| |
| if (warning) |
| *warning = warning_; |
| |
| return 0; |
| } |
| break; |
| |
| } |
| } |
| } |
| |
| short ExExeUtilTcb::holdAndSetCQD(const char * defaultName, const char * defaultValue, |
| ComDiagsArea * globalDiags) |
| { |
| Lng32 cliRC; |
| |
| cliRC = holdAndSetCQD(defaultName, defaultValue, cliInterface(), |
| globalDiags); |
| if (cliRC < 0) |
| { |
| handleErrors(cliRC); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| short ExExeUtilTcb::restoreCQD(const char * defaultName, ComDiagsArea * globalDiags) |
| { |
| Lng32 cliRC; |
| |
| cliRC = restoreCQD(defaultName, cliInterface(), globalDiags); |
| if (cliRC < 0) |
| { |
| handleErrors(cliRC); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| Lng32 ExExeUtilTcb::holdAndSetCQD(const char * defaultName, const char * defaultValue, |
| ExeCliInterface * cliInterface, |
| ComDiagsArea * globalDiags) |
| { |
| Lng32 cliRC; |
| |
| cliRC = cliInterface->holdAndSetCQD(defaultName, defaultValue, globalDiags); |
| return cliRC; |
| } |
| |
| Lng32 ExExeUtilTcb::restoreCQD(const char * defaultName, |
| ExeCliInterface * cliInterface, |
| ComDiagsArea * globalDiags) |
| { |
| Lng32 cliRC; |
| |
| cliRC = cliInterface->restoreCQD(defaultName, globalDiags); |
| |
| return cliRC; |
| } |
| |
| short ExExeUtilTcb::setCS(const char * csName, char * csValue, |
| ComDiagsArea * globalDiags) |
| { |
| Lng32 cliRC; |
| |
| cliRC = setCS(csName, csValue, cliInterface(), globalDiags); |
| if (cliRC < 0) |
| { |
| handleErrors(cliRC); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| short ExExeUtilTcb::resetCS(const char * csName, ComDiagsArea * globalDiags) |
| { |
| Lng32 cliRC; |
| |
| cliRC = resetCS(csName, cliInterface(), globalDiags); |
| if (cliRC < 0) |
| { |
| handleErrors(cliRC); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| Lng32 ExExeUtilTcb::setCS(const char * csName, char * csValue, |
| ExeCliInterface * cliInterface, |
| ComDiagsArea * globalDiags) |
| { |
| Lng32 cliRC; |
| |
| char buf[400]; |
| |
| strcpy(buf, "control session '"); |
| strcat(buf, csName); |
| strcat(buf, "' '"); |
| strcat(buf, csValue); |
| strcat(buf, "';"); |
| |
| cliRC = |
| cliInterface->executeImmediate(buf, NULL, NULL, TRUE, NULL,FALSE, |
| &globalDiags); |
| if (cliRC < 0) |
| { |
| return cliRC; |
| } |
| |
| return 0; |
| } |
| |
| Lng32 ExExeUtilTcb::resetCS(const char * csName, |
| ExeCliInterface * cliInterface, |
| ComDiagsArea * globalDiags) |
| { |
| Lng32 cliRC; |
| |
| char buf[400]; |
| |
| strcpy(buf, "control session '"); |
| strcat(buf, csName); |
| strcat(buf, "' reset;"); |
| cliRC = cliInterface->executeImmediate(buf, NULL, NULL, TRUE, NULL,FALSE, |
| &globalDiags); |
| if (cliRC < 0) |
| { |
| return cliRC; |
| } |
| |
| return 0; |
| } |
| |
| short ExExeUtilTcb::disableCQS() |
| { |
| // disable any CQS in affect |
| Lng32 rc = cliInterface()-> |
| executeImmediate("control query shape hold;"); |
| if (rc < 0) |
| { |
| handleErrors(rc); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| short ExExeUtilTcb::restoreCQS() |
| { |
| Lng32 rc = cliInterface()-> |
| executeImmediate("control query shape restore;"); |
| if (rc < 0) |
| { |
| handleErrors(rc); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| void ExExeUtilTcb::setMaintainControlTableTimeout(char * catalog) |
| { |
| Lng32 cliRC; |
| char buf[400+ComMAX_1_PART_EXTERNAL_UTF8_NAME_LEN_IN_BYTES]; |
| Lng32 markValue = -1; |
| char timeoutHoldBuf[100]; |
| Lng32 timeoutHoldBufLen = 0; |
| |
| // The MAINTAIN_CONTROL_TABLE_TIMEOUT CQD default is '30000', 5 minutes |
| restoreTimeout_ = FALSE; |
| |
| strcpy(buf, "showcontrol default "); |
| strcat(buf, "MAINTAIN_CONTROL_TABLE_TIMEOUT"); |
| strcat(buf, " , match full, no header;"); |
| |
| markValue = getDiagsArea()->mark(); |
| |
| // get the current value of MAINTAIN_CONTROL_TABLE_TIMEOUT |
| |
| cliRC = |
| cliInterface()-> |
| executeImmediate(buf, timeoutHoldBuf, &timeoutHoldBufLen); |
| |
| // If we were unable to obtain the default value, |
| // then just return and allow the 60 second general |
| // timeout for a table to remain. |
| |
| if (cliRC < 0) |
| { |
| // Ignore any error occurring from the executeImmediate call. |
| // Rewind to not report this one error. |
| getDiagsArea()->rewind(markValue); |
| SQL_EXEC_ClearDiagnostics(NULL); |
| return; |
| } |
| |
| // The timeout setting will be retained for the duration |
| // of executing the maintain tasks. |
| |
| // Execute the set table timeout statement. |
| // The SET TABLE TIMEOUT statement sets a dynamic timeout value for a lock timeout |
| // or a stream timeout in the environment of the current session. The dynamic timeout |
| // value overrides the compiled static timeout value in the execution of subsequent DML |
| // statements. |
| |
| markValue = getDiagsArea()->mark(); |
| |
| strcpy(buf, "SET TABLE "); |
| strcat(buf, catalog); |
| strcat(buf, ".\"@MAINTAIN_SCHEMA@\".\"@MAINTAIN_CONTROL_INFO@\" "); |
| strcat(buf, " TIMEOUT "); |
| strcat(buf, " '"); |
| strcat(buf, timeoutHoldBuf); |
| strcat(buf, "';"); |
| |
| cliRC = |
| cliInterface()->executeImmediate(buf); |
| |
| if (cliRC < 0) |
| { |
| // Ignore any error occurring from the executeImmediate call. |
| // Rewind to not report this one error. |
| getDiagsArea()->rewind(markValue); |
| SQL_EXEC_ClearDiagnostics(NULL); |
| return; |
| } |
| |
| // Set the flag to indicate the timeout |
| // should be restored |
| |
| restoreTimeout_ = TRUE; |
| |
| return; |
| } |
| |
| void ExExeUtilTcb::restoreMaintainControlTableTimeout(char * catalog) |
| { |
| Lng32 cliRC; |
| char buf[400+ComMAX_1_PART_EXTERNAL_UTF8_NAME_LEN_IN_BYTES]; |
| Lng32 markValue = -1; |
| |
| // If the restoration timeout flag is not set, |
| // then just return. |
| |
| if (!restoreTimeout_) |
| return; |
| |
| markValue = getDiagsArea()->mark(); |
| |
| // Reset the timeout to its previous setting. |
| // Errors are ignored. |
| |
| strcpy(buf, "SET TABLE "); |
| strcat(buf, catalog); |
| strcat(buf, ".\"@MAINTAIN_SCHEMA@\".\"@MAINTAIN_CONTROL_INFO@\" "); |
| strcat(buf, " TIMEOUT RESET;"); |
| |
| cliRC = |
| cliInterface()->executeImmediate(buf); |
| |
| if (cliRC < 0) |
| { |
| // ignore any error occurring from the executeImmediate call |
| // rewind to not report this one error |
| getDiagsArea()->rewind(markValue); |
| SQL_EXEC_ClearDiagnostics(NULL); |
| return; |
| } |
| |
| restoreTimeout_ = FALSE; |
| |
| return; |
| } |
| |
| short ExExeUtilTcb::setSchemaVersion(char * param1) |
| { |
| // For SeaQuest, the version number will always be the same |
| // this is a no-op. |
| return 0; |
| } |
| |
| short ExExeUtilTcb::setSystemVersion() |
| { |
| Lng32 cliRC = 0; |
| |
| if (sysVersionStrLen_ == 0) |
| { |
| // since SUBSTRING isn't currently supported for UTF-8 strings |
| // and GET VERSION OF SYSTEM returns a UTF-8 string, convert it |
| // to UCS2, do the substring, then convert to ISO88591 (we |
| // expect a number here so it would be an error to get anything |
| // other than ISO88591 characters). |
| cliRC = |
| cliInterface()->executeImmediate("select translate(substring(translate(a using utf8toucs2), 10, 4) using ucs2toiso88591) from (get version of system) x(a)", |
| sysVersionStr_, &sysVersionStrLen_); |
| if (cliRC < 0) |
| { |
| cliInterface()->allocAndRetrieveSQLDiagnostics(diagsArea_); |
| return -1; |
| } |
| |
| sysVersionStr_[sysVersionStrLen_] = 0; |
| } |
| |
| return 0; |
| } |
| |
| static const QueryString getObjectUidQuery[] = |
| { |
| {" select cast(O.object_uid as char(24)) from "}, |
| {" HP_SYSTEM_CATALOG.system_schema.schemata S, "}, |
| {" \"%s\".HP_DEFINITION_SCHEMA.objects O "}, |
| {" where S.schema_name = '%s' and "}, |
| {" S.schema_uid = O.schema_uid and "}, |
| {" O.object_name = '%s' and "}, |
| {" O.object_name_space = '%s' and "}, |
| {" O.object_type = '%s' "}, |
| {" for read uncommitted access "}, |
| {" ; "} |
| }; |
| |
| short ExExeUtilTcb::getObjectUid(char * catName, char * schName, |
| char * objName, |
| NABoolean isIndex, NABoolean isMv, |
| char* uid) |
| { |
| Lng32 cliRC = 0; |
| |
| ex_queue_entry * pentry_down = qparent_.down->getHeadEntry(); |
| ExExeUtilPrivateState & pstate = |
| *((ExExeUtilPrivateState*) pentry_down->pstate); |
| |
| ExExeStmtGlobals *exeGlob = getGlobals()->castToExExeStmtGlobals(); |
| ExMasterStmtGlobals *masterGlob = exeGlob->castToExMasterStmtGlobals(); |
| |
| const QueryString * qs; |
| Int32 sizeOfqs = 0; |
| versionStrLen_ = 0; |
| |
| qs = getObjectUidQuery; |
| sizeOfqs = sizeof(getObjectUidQuery); |
| |
| Int32 qryArraySize = sizeOfqs / sizeof(QueryString); |
| char * gluedQuery; |
| Lng32 gluedQuerySize; |
| glueQueryFragments(qryArraySize, qs, |
| gluedQuery, gluedQuerySize); |
| |
| Lng32 extraSpace = 10 /*segment name*/+ ComMAX_3_PART_EXTERNAL_UTF8_NAME_LEN_IN_BYTES/*cat/sch/obj name in UTF8*/ + 100; |
| |
| char * infoQuery = |
| new(getHeap()) char[gluedQuerySize + extraSpace + 1]; |
| |
| str_sprintf(infoQuery, gluedQuery, |
| catName, schName, objName, |
| (isIndex ? "IX" : "TA"), |
| (isMv ? "MV" : (isIndex ? "IX" : "BT"))); |
| |
| NADELETEBASIC(gluedQuery, getMyHeap()); |
| |
| Lng32 uidLen; |
| cliRC = |
| cliInterface()->executeImmediate(infoQuery, |
| uid, &uidLen); |
| if (cliRC < 0) |
| { |
| cliInterface()->allocAndRetrieveSQLDiagnostics(diagsArea_); |
| return -1; |
| } |
| uid[uidLen] = 0; |
| |
| return 0; |
| } |
| |
| short ExExeUtilTcb::alterObjectState(NABoolean online, |
| char * tableName, |
| char * failReason, |
| NABoolean forPurgedata) |
| { |
| char buf[4000]; |
| Lng32 cliRC = 0; |
| |
| // Get the globals stucture of the master executor. |
| ExExeStmtGlobals *exeGlob = getGlobals()->castToExExeStmtGlobals(); |
| ExMasterStmtGlobals *masterGlob = exeGlob->castToExMasterStmtGlobals(); |
| |
| // make object online |
| str_sprintf(buf, "ALTER TABLE %s %s %s", |
| tableName, |
| (online ? "ONLINE" : "OFFLINE"), |
| (forPurgedata ? "FOR PURGEDATA" : " ")); |
| |
| // set sqlparserflags to allow 'FOR PURGEDATA' syntax |
| masterGlob->getStatement()->getContext()->setSqlParserFlags(0x1); |
| |
| cliRC = cliInterface()->executeImmediate(buf); |
| |
| masterGlob->getStatement()->getContext()->resetSqlParserFlags(0x1); |
| |
| if (cliRC < 0) |
| { |
| str_sprintf(failReason, "Could not alter the state of table %s to %s.", |
| tableName, (online ? "online" : "offline")); |
| |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| short ExExeUtilTcb::lockUnlockObject(char * tableName, |
| NABoolean lock, |
| NABoolean parallel, |
| char * failReason) |
| { |
| char buf[4000]; |
| Lng32 cliRC = 0; |
| |
| // Get the globals stucture of the master executor. |
| ExExeStmtGlobals *exeGlob = getGlobals()->castToExExeStmtGlobals(); |
| ExMasterStmtGlobals *masterGlob = exeGlob->castToExMasterStmtGlobals(); |
| |
| // lock or unlock the table. |
| if (parallel) |
| { |
| if (lock) |
| str_sprintf(buf, "LOCK TABLE %s IN PROTECTED MODE NO INDEX LOCK PARALLEL EXECUTION ON", |
| tableName); |
| else |
| str_sprintf(buf, "UNLOCK TABLE %s PARALLEL EXECUTION ON", |
| tableName); |
| } |
| else |
| { |
| if (lock) |
| str_sprintf(buf, "LOCK TABLE %s IN PROTECTED MODE", |
| tableName); |
| else |
| str_sprintf(buf, "UNLOCK TABLE %s", |
| tableName); |
| } |
| masterGlob->getStatement()->getContext()->setSqlParserFlags(0x100001); |
| |
| cliRC = cliInterface()->executeImmediate(buf); |
| |
| masterGlob->getStatement()->getContext()->resetSqlParserFlags(0x100001); |
| |
| if (cliRC < 0) |
| { |
| if (lock) |
| str_sprintf(failReason, "Could not lock table %s in protected mode using parallel execution.", |
| tableName); |
| else |
| str_sprintf(failReason, "Could not unlock table %s using parallel execution.", |
| tableName); |
| |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| short ExExeUtilTcb::doubleQuoteStr(char * str, char * newStr, |
| NABoolean singleQuote) |
| { |
| // replace single quotes with 2 single quotes |
| unsigned short i = 0; |
| unsigned short j = 0; |
| short len = (short)(str ? strlen(str) : 0); |
| while (i < len) |
| { |
| if (singleQuote) |
| { |
| if (str[i] == '\'') |
| { |
| newStr[j] = '\''; |
| j++; |
| newStr[j] = '\''; |
| } |
| else |
| newStr[j] = str[i]; |
| } |
| else |
| { |
| if (str[i] == '\"') |
| { |
| newStr[j] = '\"'; |
| j++; |
| newStr[j] = '\"'; |
| } |
| else |
| newStr[j] = str[i]; |
| } |
| |
| i++; |
| j++; |
| } |
| newStr[j] = 0; |
| |
| return 0; |
| } |
| |
| // lockType: COM_UTIL_PURGEDATA (= 9), COM_UTIL_REPLICATE (= 19). |
| // (definition in common/ComSmallDefs.h). |
| short ExExeUtilTcb::alterDDLLock(NABoolean add, char * tableName, |
| char * failReason, NABoolean isMV, |
| Int32 lockType, |
| const char * lockSuffix, |
| NABoolean skipDDLLockCheck) |
| { |
| char buf[4000]; |
| Lng32 cliRC = 0; |
| |
| // Get the globals stucture of the master executor. |
| ExExeStmtGlobals *exeGlob = getGlobals()->castToExExeStmtGlobals(); |
| ExMasterStmtGlobals *masterGlob = exeGlob->castToExMasterStmtGlobals(); |
| |
| AnsiName aonn(tableName); |
| aonn.convertAnsiName(FALSE); |
| char * parts[4]; |
| Lng32 numParts; |
| aonn.extractParts(numParts, parts); |
| |
| char * quotedParts0 = NULL; |
| char * quotedParts1 = NULL; |
| |
| if (numParts == 3) |
| { |
| quotedParts0 = |
| new(getGlobals()->getDefaultHeap()) char[strlen(parts[0]) * 2 + 1]; |
| quotedParts1 = |
| new(getGlobals()->getDefaultHeap()) char[strlen(parts[1]) * 2 + 1]; |
| |
| doubleQuoteStr(parts[0], quotedParts0, FALSE); |
| doubleQuoteStr(parts[1], quotedParts1, FALSE); |
| } |
| |
| //////////////////////////////////////////////////////////////// |
| // see sqlshare/catapirequest.h for details on CAT API params. |
| // CatApi has the form: |
| // CREATE TANDEM_CAT_REQUEST&1 <request-type> <num-params> |
| // <lock-name> <object-name> <object-type> <operation-type> |
| // request-type: 1 (create lock) or 2 (drop lock) |
| // num-params: 5 |
| // lock-name: getTableName() appended with _DDL_LOCK |
| // object-name: getTableName() |
| // object-type: 0 (table) or 2 (MV) |
| // operation-type: 9 (purgedata) |
| // lockStatus: 9 (parallel purgedata) |
| //////////////////////////////////////////////////////////////// |
| |
| char sdlc[200]; |
| if (skipDDLLockCheck) |
| { |
| str_sprintf(sdlc, "<> <0> <1>"); |
| } |
| |
| // alter(add or drop) DDL lock |
| if (numParts == 3) |
| { |
| char lockNameSuffix[200]; |
| str_sprintf(lockNameSuffix, "_DDL_LOCK%s", (lockSuffix ? lockSuffix : "")); |
| generateLockName(parts[2], lockNameSuffix, buf, sizeof buf - 20); |
| char quotedLockName[ComMAX_3_PART_EXTERNAL_UTF8_NAME_LEN_IN_BYTES+200]; // a big buffer |
| doubleQuoteStr(buf, quotedLockName, FALSE); |
| str_sprintf(buf, "CREATE TANDEM_CAT_REQUEST&1 %s %d <\"%s\".\"%s\".\"%s\"> <%s%s> <%s> <%d> %s %s", |
| (add ? "1" : "2"), |
| (skipDDLLockCheck ? 8 : 5), //(lockType == COM_UTIL_PURGEDATA ? 5 : 4), |
| quotedParts0, quotedParts1, quotedLockName, |
| tableName, "", |
| (isMV ? "2" : "0"), |
| lockType, |
| (lockType == COM_UTIL_PURGEDATA ? "<9>" : "<0>"), |
| skipDDLLockCheck ? sdlc : ""); |
| } |
| else |
| str_sprintf(buf, "CREATE TANDEM_CAT_REQUEST&1 %s %d <%s_DDL_LOCK%s> <%s%s> <%s> <%d> %s %s", |
| (add ? "1" : "2"), |
| // (lockType == COM_UTIL_PURGEDATA ? 5 : 4), |
| (skipDDLLockCheck ? 8 : 5), //(lockType == COM_UTIL_PURGEDATA ? 5 : 4), |
| tableName, |
| (lockSuffix ? lockSuffix : ""), |
| tableName, "", |
| (isMV ? "2" : "0"), |
| lockType, |
| (lockType == COM_UTIL_PURGEDATA ? "<9>" : "<0>"), |
| skipDDLLockCheck ? sdlc : ""); |
| |
| // set sqlparserflags to allow CAT_API_REQUEST |
| masterGlob->getStatement()->getContext()->setSqlParserFlags(0x1); |
| |
| cliRC = cliInterface()->executeImmediate(buf); |
| |
| masterGlob->getStatement()->getContext()->resetSqlParserFlags(0x1); |
| |
| NADELETEBASIC(quotedParts0, getGlobals()->getDefaultHeap()); |
| NADELETEBASIC(quotedParts1, getGlobals()->getDefaultHeap()); |
| |
| if (cliRC < 0) |
| { |
| str_sprintf(failReason, "Could not %s ddl lock for object %s.", |
| (add ? "add" : "drop"), tableName); |
| |
| return (short)cliRC; |
| } |
| else |
| return 0; |
| } |
| |
| short ExExeUtilTcb::alterCorruptBit(short val, char * tableName, |
| char * failReason, Queue* indexList) |
| { |
| char buf[4000]; |
| Lng32 cliRC = 0; |
| |
| // Get the globals stucture of the master executor. |
| ExExeStmtGlobals *exeGlob = getGlobals()->castToExExeStmtGlobals(); |
| ExMasterStmtGlobals *masterGlob = exeGlob->castToExMasterStmtGlobals(); |
| |
| // change the corrupt bit in the label |
| str_sprintf(buf, "LABEL_ALTER TABLE %s PARALLEL EXECUTION ON OPCODE 9 '%s'", |
| tableName, (val == 1 ? "1" : "0")); |
| |
| // set sqlparserflags to allow 'label_alter' syntax |
| masterGlob->getStatement()->getContext()->setSqlParserFlags(0x1); |
| |
| cliRC = cliInterface()->executeImmediate(buf); |
| |
| masterGlob->getStatement()->getContext()->resetSqlParserFlags(0x1); |
| |
| if (cliRC < 0) |
| { |
| str_sprintf(failReason, "Could not %s the corrupt bit on table %s.", |
| (val == 1 ? "set" : "reset"), tableName); |
| return -1; |
| } |
| |
| if (indexList) |
| { |
| indexList->position(); |
| |
| while (NOT indexList->atEnd()) |
| { |
| char * indexName = (char*)indexList->getNext(); |
| |
| str_sprintf(buf, "LABEL_ALTER INDEX_TABLE %s PARALLEL EXECUTION ON OPCODE 9 '%s'", |
| indexName, (val == 1 ? "1" : "0")); |
| |
| // set sqlparserflags to allow 'label_alter' syntax |
| masterGlob->getStatement()->getContext()->setSqlParserFlags(0x1); |
| |
| cliRC = cliInterface()->executeImmediate(buf); |
| |
| masterGlob->getStatement()->getContext()->resetSqlParserFlags(0x1); |
| |
| if (cliRC < 0) |
| { |
| str_sprintf(failReason, "Could not %s the corrupt bit on index %s.", |
| (val == 1 ? "set" : "reset"), indexName); |
| |
| return -1; |
| } |
| } // while |
| |
| } // index present |
| |
| return 0; |
| } |
| |
| short ExExeUtilTcb::alterAuditFlag(NABoolean audited, char * tableName, |
| NABoolean isIndex) |
| { |
| char buf[4000]; |
| Lng32 cliRC = 0; |
| |
| // Get the globals stucture of the master executor. |
| ExExeStmtGlobals *exeGlob = getGlobals()->castToExExeStmtGlobals(); |
| ExMasterStmtGlobals *masterGlob = exeGlob->castToExMasterStmtGlobals(); |
| |
| // change the corrupt bit in the label |
| if (isIndex) |
| str_sprintf(buf, "LABEL_ALTER INDEX_TABLE %s PARALLEL EXECUTION ON OPCODE %s ''", |
| tableName, (audited ? "65" : "66")); |
| else |
| str_sprintf(buf, "LABEL_ALTER TABLE %s PARALLEL EXECUTION ON OPCODE %s ''", |
| tableName, (audited ? "65" : "66")); |
| |
| // set sqlparserflags to allow 'label_alter' syntax |
| masterGlob->getStatement()->getContext()->setSqlParserFlags(0x1); |
| |
| cliRC = cliInterface()->executeImmediate(buf); |
| |
| masterGlob->getStatement()->getContext()->resetSqlParserFlags(0x1); |
| |
| if (cliRC < 0) |
| { |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| short ExExeUtilTcb::handleError() |
| { |
| short rc = ex_tcb::handleError(&qparent_, getDiagsArea()); |
| if (diagsArea_ != NULL) |
| diagsArea_->deAllocate(); |
| diagsArea_ = NULL; |
| return rc; |
| } |
| |
| short ExExeUtilTcb::handleDone() |
| { |
| short rc = ex_tcb::handleDone(&qparent_, getDiagsArea()); |
| if (diagsArea_ != NULL) |
| { |
| diagsArea_->deAllocate(); |
| diagsArea_ = NULL; |
| } |
| return rc; |
| } |
| |
| short ExExeUtilTcb::createServer(char *serverName, |
| const char * inPName, |
| IpcServerTypeEnum serverType, |
| IpcServerAllocationMethod servAllocMethod, |
| char *nodeName, |
| short cpu, |
| const char *partnName, |
| IpcServer* &ipcServer, |
| NABoolean logError, |
| const char * operation) |
| { |
| short error = 0; |
| |
| // Get the globals stucture of the master executor. |
| ExExeStmtGlobals *exeGlob = getGlobals()->castToExExeStmtGlobals(); |
| ExMasterStmtGlobals *masterGlob = exeGlob->castToExMasterStmtGlobals(); |
| |
| IpcEnvironment * env = masterGlob->getCliGlobals()->getEnvironment(); |
| NAHeap *ipcHeap = masterGlob->getCliGlobals()->getIpcHeap(); |
| |
| |
| IpcServerClass * sc = |
| new (ipcHeap) IpcServerClass(env, serverType, |
| servAllocMethod, //IPC_LAUNCH_GUARDIAN_PROCESS, |
| COM_VERS_MXV, nodeName); |
| if (!sc) |
| { |
| if (logError) |
| { |
| char emsText[400+ComMAX_3_PART_EXTERNAL_UTF8_NAME_LEN_IN_BYTES]; |
| str_sprintf(emsText, "Failure creating IpcServerClass on \\%s cpu %d to %s %s for %s.", |
| nodeName, cpu, operation, partnName, |
| (char *)exeUtilTdb().getTableName()); |
| SQLMXLoggingArea::logExecRtInfo(NULL, 0, emsText, 0); |
| } |
| return -1; |
| } |
| |
| const char * pName = NULL; |
| char pNameBuf[20]; |
| short pNameLen = 0; |
| |
| if (inPName) |
| pName = inPName; |
| else |
| { |
| pName = pNameBuf; |
| |
| pNameBuf[pNameLen] = 0; |
| } |
| |
| ipcServer = |
| sc->allocateServerProcess(&diagsArea_, |
| ipcHeap, |
| nodeName, |
| cpu, |
| 1, // espLevel (not relevent) |
| FALSE, // no Xn |
| TRUE, // waited creation |
| 0, // maxNowaitRequests |
| serverName, |
| pName |
| ); |
| if (!ipcServer) |
| { |
| if (logError && diagsArea_) |
| { |
| char emsText[400+ComMAX_3_PART_EXTERNAL_UTF8_NAME_LEN_IN_BYTES]; |
| str_sprintf(emsText, "allocateServerProcess() failed with error %d on \\%s cpu %d to %s %s for %s.", |
| diagsArea_->mainSQLCODE(), nodeName, cpu, operation, |
| partnName, (char *)exeUtilTdb().getTableName()); |
| SQLMXLoggingArea::logExecRtInfo(NULL, 0, emsText, 0); |
| } |
| NADELETE(sc, IpcServerClass, ipcHeap); |
| return -3; |
| } |
| |
| return 0; |
| } |
| |
| void ExExeUtilTcb::deleteServer(IpcServer *ipcServer) |
| { |
| IpcServerClass * sc = ipcServer->getServerClass(); |
| IpcEnvironment *env = sc->getEnv(); |
| |
| ipcServer->release(); |
| NADELETE(sc, IpcServerClass, env->getHeap()); |
| } |
| |
| NABoolean ExExeUtilTcb::isProcessObsolete( |
| short cpu, pid_t pin, short segmentNum, |
| Int64 procCreateTime) |
| { |
| Lng32 retcode = 0; |
| |
| // see if process exists. If it exists, check if it is the same |
| // process that is specified in the schemaName. |
| short errorDetail = 0; |
| Int64 l_procCreateTime = 0; |
| retcode = ComRtGetProcessCreateTime(&cpu, &pin, &segmentNum, |
| l_procCreateTime, |
| errorDetail); |
| if (retcode == XZFIL_ERR_OK) |
| { |
| // process specified exists. |
| if (l_procCreateTime != procCreateTime) |
| // but is a different process. Input process is obsolete. |
| return -1; |
| else |
| // process is still alive. |
| return 0; |
| } |
| else if (retcode == XZFIL_ERR_NOSUCHDEV) |
| // process doesn't exist. process is obsolete. |
| return -1; |
| else |
| // some other error while trying to access process. |
| // process is not obsolete. |
| return 0; |
| } |
| |
| Lng32 ExExeUtilTcb::extractParts |
| (char * objectName, |
| char ** paramParts0, |
| char ** paramParts1, |
| char ** paramParts2 |
| ) |
| { |
| |
| char * parts[4]; |
| Lng32 numParts = 0; |
| Lng32 rc = 0; |
| |
| // We want to ignore any "." dots within a delimited |
| // name. The AnsiName object is ultimately deleted |
| // in the ExExeUtilMainObjectTcb destructor. |
| |
| if (extractedPartsObj_) |
| delete extractedPartsObj_; |
| |
| extractedPartsObj_ = new (getHeap()) AnsiName(objectName); |
| if ((rc = extractedPartsObj_->extractParts(numParts, parts)) != 0 || |
| (numParts != 3)) |
| { |
| ExRaiseSqlError(getHeap(), &diagsArea_, -CLI_INTERNAL_ERROR); |
| return -1; |
| } |
| |
| |
| char * parts0 = NULL; |
| char * parts1 = NULL; |
| char * parts2 = NULL; |
| |
| Lng32 parts0Len = strlen(parts[0]); |
| Lng32 parts1Len = strlen(parts[1]); |
| Lng32 parts2Len = strlen(parts[2]); |
| |
| Lng32 parts0OffsetLen = 0; |
| Lng32 parts1OffsetLen = 0; |
| Lng32 parts2OffsetLen = 0; |
| |
| Lng32 foundParts0 = 0; |
| Lng32 foundParts1 = 0; |
| Lng32 foundParts2 = 0; |
| |
| char * testParts = NULL; |
| char * ptr = NULL; |
| |
| testParts = parts[0]; |
| |
| ptr = (char *) strchr (testParts, '\''); |
| while (ptr != NULL) |
| { |
| foundParts0++; |
| ptr = (char *) strchr (ptr+1,'\''); |
| } |
| |
| testParts = parts[1]; |
| |
| ptr = (char *) strchr (testParts, '\''); |
| while (ptr != NULL) |
| { |
| foundParts1++; |
| ptr = (char *) strchr (ptr+1,'\''); |
| } |
| |
| testParts = parts[2]; |
| |
| ptr = (char *) strchr (testParts, '\''); |
| while (ptr != NULL) |
| { |
| foundParts2++; |
| ptr = (char *) strchr (ptr+1,'\''); |
| } |
| |
| Lng32 lenToCopy = 0; |
| char * beginTestParts = NULL; |
| char * formattedParts = NULL; |
| Lng32 totalLen = 0; |
| |
| if (foundParts0) |
| { |
| totalLen = parts0Len + foundParts0 + 1; |
| parts0 = new(getHeap()) char[totalLen]; |
| |
| for (Int32 i = 0; i < totalLen; i++) |
| parts0[i] = ' '; |
| |
| parts0[totalLen-1] = '\0'; |
| |
| testParts = parts[0]; |
| ptr = NULL; |
| |
| ptr = (char *) strchr (testParts, '\''); |
| |
| while (ptr != NULL) |
| { |
| lenToCopy = ptr - testParts; |
| |
| strncpy(parts0 + parts0OffsetLen,testParts,++lenToCopy); |
| |
| strncpy(parts0 + parts0OffsetLen + lenToCopy, "'",1); |
| |
| testParts = testParts + lenToCopy; |
| parts0OffsetLen += lenToCopy; |
| parts0OffsetLen++; |
| |
| ptr = (char *) strchr (ptr+1,'\''); |
| } |
| |
| strncpy(parts0 + parts0OffsetLen, testParts,strlen(testParts)); |
| parts0[totalLen-1] = '\0'; |
| } |
| else |
| { |
| totalLen = parts0Len + 1; |
| parts0 = new(getHeap()) char[totalLen]; |
| strcpy(parts0, parts[0]); |
| } |
| |
| if (foundParts1) |
| { |
| totalLen = parts1Len + foundParts1 + 1; |
| parts1 = new(getHeap()) char[totalLen]; |
| |
| for (Int32 i = 0; i < totalLen; i++) |
| parts1[i] = ' '; |
| |
| parts1[totalLen-1] = '\0'; |
| |
| testParts = parts[1]; |
| ptr = NULL; |
| |
| ptr = (char *) strchr (testParts, '\''); |
| |
| while (ptr != NULL) |
| { |
| lenToCopy = ptr - testParts; |
| |
| strncpy(parts1 + parts1OffsetLen,testParts,++lenToCopy); |
| |
| strncpy(parts1 + parts1OffsetLen + lenToCopy, "'",1); |
| |
| testParts = testParts + lenToCopy; |
| parts1OffsetLen += lenToCopy; |
| parts1OffsetLen++; |
| |
| ptr = (char *) strchr (ptr+1,'\''); |
| } |
| |
| strncpy(parts1 + parts1OffsetLen, testParts,strlen(testParts)); |
| parts1[totalLen-1] = '\0'; |
| } |
| else |
| { |
| totalLen = parts1Len + 1; |
| parts1 = new(getHeap()) char[totalLen]; |
| strcpy(parts1, parts[1]); |
| } |
| |
| if (foundParts2) |
| { |
| totalLen = parts2Len + foundParts2 + 1; |
| parts2 = new(getHeap()) char[totalLen]; |
| |
| for (Int32 i = 0; i < totalLen; i++) |
| parts2[i] = ' '; |
| |
| parts2[totalLen-1] = '\0'; |
| |
| testParts = parts[2]; |
| ptr = NULL; |
| |
| ptr = (char *) strchr (testParts, '\''); |
| |
| while (ptr != NULL) |
| { |
| lenToCopy = ptr - testParts; |
| |
| strncpy(parts2 + parts2OffsetLen,testParts,++lenToCopy); |
| |
| strncpy(parts2 + parts2OffsetLen + lenToCopy, "'",1); |
| |
| testParts = testParts + lenToCopy; |
| parts2OffsetLen += lenToCopy; |
| parts2OffsetLen++; |
| |
| ptr = (char *) strchr (ptr+1,'\''); |
| } |
| |
| strncpy(parts2 + parts2OffsetLen, testParts,strlen(testParts)); |
| parts2[totalLen-1] = '\0'; |
| } |
| else |
| { |
| totalLen = parts2Len + 1; |
| parts2 = new(getHeap()) char[totalLen]; |
| strcpy(parts2, parts[2]); |
| } |
| |
| /* The AnsiName() method strips out the leading |
| and ending double quotes. The following code |
| is no longer needed. |
| |
| // |
| // Strip out the delimited name quotes. |
| // If these are not stripped out, then a maximum |
| // name of 128 characters will cause an overflow |
| // by actually having 130 characters. |
| |
| char maxName[129]; |
| maxName[0] = '\0'; |
| |
| if (parts0[0] == '"') |
| { |
| strncpy(maxName,parts0+1,strlen(parts0) -2); |
| maxName[strlen(parts0)-2] = '\0'; |
| strncpy(parts0,maxName,strlen(parts0) -2); |
| parts0[strlen(maxName)] = '\0'; |
| } |
| |
| maxName[0] = '\0'; |
| |
| if (parts1[0] == '"') |
| { |
| strncpy(maxName,parts1+1,strlen(parts1) -2); |
| maxName[strlen(parts1)-2] = '\0'; |
| strncpy(parts1,maxName,strlen(parts1) -2); |
| parts1[strlen(maxName)] = '\0'; |
| } |
| |
| maxName[0] = '\0'; |
| |
| if (parts2[0] == '"') |
| { |
| strncpy(maxName,parts2+1,strlen(parts2) -2); |
| maxName[strlen(parts2)-2] = '\0'; |
| strncpy(parts2,maxName,strlen(parts2) -2); |
| parts2[strlen(maxName)] = '\0'; |
| } |
| |
| maxName[0] = '\0'; |
| */ |
| |
| *paramParts0 = parts0; |
| *paramParts1 = parts1; |
| *paramParts2 = parts2; |
| |
| return 0; |
| } |
| |
| ex_expr::exp_return_type ExExeUtilTcb::evalScanExpr(char * ptr, Lng32 len, |
| NABoolean copyToVCbuf) |
| { |
| ex_expr::exp_return_type exprRetCode = ex_expr::EXPR_OK; |
| |
| if (exeUtilTdb().scanExpr_) |
| { |
| ex_queue_entry * pentry_down = qparent_.down->getHeadEntry(); |
| |
| char * exprPtr = ptr; |
| if (copyToVCbuf) |
| { |
| exprPtr = new(getGlobals()->getDefaultHeap()) |
| char[SQL_VARCHAR_HDR_SIZE + len]; |
| short shortLen = (short)len; |
| str_cpy_all((char*)exprPtr, (char*)&shortLen, SQL_VARCHAR_HDR_SIZE); |
| str_cpy_all(&exprPtr[SQL_VARCHAR_HDR_SIZE], ptr, shortLen); |
| } |
| |
| workAtp_->getTupp(exeUtilTdb().workAtpIndex()) |
| .setDataPointer(exprPtr); |
| |
| exprRetCode = |
| exeUtilTdb().scanExpr_->eval(pentry_down->getAtp(), workAtp_); |
| |
| if (exprPtr != ptr) |
| NADELETEBASIC(exprPtr, getGlobals()->getDefaultHeap()); |
| } |
| |
| return exprRetCode; |
| } |
| |
| |
| ///////////////////////////////////////////////////////////////////////////// |
| // Constructor and destructor for ExeUtil_private_state |
| ///////////////////////////////////////////////////////////////////////////// |
| ExExeUtilPrivateState::ExExeUtilPrivateState(const ExExeUtilTcb * /*tcb*/) |
| { |
| step_ = ExExeUtilTcb::EMPTY_; |
| matches_ = 0; |
| } |
| |
| ExExeUtilPrivateState::~ExExeUtilPrivateState() |
| { |
| }; |
| |
| ex_tcb_private_state * ExExeUtilPrivateState::allocate_new(const ex_tcb *tcb) |
| { |
| return new(((ex_tcb *)tcb)->getSpace()) ExExeUtilPrivateState((ExExeUtilTcb *) tcb); |
| }; |
| |