| //********************************************************************** |
| // @@@ 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: NAroutine.cpp |
| * Description: SQL compiler representation of SP routine metadata |
| * Created: 5/3/2000 |
| * Language: C++ |
| * |
| * |
| ************************************************************************** |
| */ |
| #include "BaseTypes.h" |
| #include "TrafDDLdesc.h" |
| #include "BindWA.h" |
| #include "NAType.h" |
| #include "NumericType.h" |
| #include "CharType.h" |
| #include "DatetimeType.h" |
| #include "ComSmallDefs.h" |
| #include "CmpCommon.h" |
| #include "UdrErrors.h" |
| #include "NARoutineDB.h" |
| #include "NARoutine.h" |
| #include "SchemaDB.h" |
| #include "str.h" |
| #include "hs_util.h" |
| #include "LmJavaSignature.h" |
| #include "CmUtil.h" |
| #include "NATableSt.h" |
| #include "CmpMain.h" |
| #include "Globals.h" |
| #include "Context.h" |
| #include "ComUser.h" |
| #include "CmpSeabaseDDL.h" |
| |
| // ----------------------------------------------------------------------- |
| // Copy a string. A null terminated buffer is returned. |
| // ----------------------------------------------------------------------- |
| char *UDRCopyString ( const ComString &sourceString, CollHeap *heap ) |
| { |
| char *string = new(heap)char [sourceString.length()+1]; |
| str_cpy_all ( string |
| , sourceString.data() |
| , sourceString.length()+1 |
| ); |
| return string; |
| } // UDRCopyString |
| |
| |
| |
| NARoutine::NARoutine (CollHeap *heap) |
| : name_ ("", heap) |
| , extRoutineName_ (NULL) // ExtendedQualName * |
| , extActionName_ (NULL) // ExtendedQualName * - Empty if not an action. |
| , intActionName_ (NULL) // ComObjectName * - Empty if not an action. |
| , language_ (COM_UNKNOWN_ROUTINE_LANGUAGE) |
| , UDRType_ (COM_UNKNOWN_ROUTINE_TYPE) |
| , sqlAccess_ (COM_UNKNOWN_ROUTINE_SQL_ACCESS) |
| , transactionAttributes_ (COM_UNKNOWN_ROUTINE_TRANSACTION_ATTRIBUTE) |
| , maxResults_ (0) |
| , stateAreaSize_ (0) |
| , externalFile_ ("", heap) |
| , externalPath_ ("", heap) |
| , externalName_ ("", heap) |
| , librarySqlName_ (NULL) |
| , signature_ ("", heap) |
| , paramStyle_ (COM_UNKNOWN_ROUTINE_PARAM_STYLE) |
| , paramStyleVersion_ (1) |
| , isDeterministic_ (FALSE) |
| , isCallOnNull_ (TRUE) |
| , isIsolate_ (TRUE) |
| , externalSecurity_ (COM_ROUTINE_EXTERNAL_SECURITY_INVOKER) |
| , isExtraCall_ (FALSE) |
| , hasOutParams_ (FALSE) |
| , redefTime_ (0) |
| , lastUsedTime_ (0) |
| , routineSecKeySet_ (heap) |
| , passThruDataNumEntries_ (0) |
| , passThruData_ (NULL) |
| , passThruDataSize_ (NULL) |
| , udfFanOut_ (1) |
| , uecValues_ (heap, 0) |
| , isUniversal_ (FALSE) |
| , actionPosition_ (-1) |
| , executionMode_ (COM_ROUTINE_SAFE_EXECUTION) |
| , objectUID_ (0) |
| , dllName_ ("", heap) |
| , dllEntryPoint_ ("", heap) |
| , comRoutineParallelism_ ("NO", heap) |
| , sasFormatWidth_ ("", heap) |
| , systemName_ ("", heap) |
| , dataSource_ ("", heap) |
| , fileSuffix_ ("", heap) |
| , schemaVersionOfRoutine_ (COM_VERS_UNKNOWN) |
| , objectOwner_ (0) |
| , schemaOwner_ (0) |
| , privInfo_ (NULL) |
| , heap_ (heap) |
| { |
| } |
| |
| |
| // This is an empty constructor, with only the name specified |
| // It is meant for use with TMUDF code where we want to fake the |
| // presence of a TMUDF in metadata, for example with predefined |
| // table mapping functions, where the metadata is all determined |
| // by the compiler interface. |
| |
| NARoutine::NARoutine ( const QualifiedName &name |
| , CollHeap *heap |
| ) |
| : name_ (name, heap) |
| , hashKey_ (name, heap) |
| , language_ (COM_LANGUAGE_C) |
| , UDRType_ (COM_TABLE_UDF_TYPE) |
| , sqlAccess_ (COM_NO_SQL) |
| , transactionAttributes_ (COM_UNKNOWN_ROUTINE_TRANSACTION_ATTRIBUTE) |
| , maxResults_ (0) |
| , stateAreaSize_ (0) |
| , externalFile_ ("", heap) |
| , externalPath_ ("", heap) |
| , externalName_ ("", heap) |
| , librarySqlName_ (NULL) |
| , signature_ ("", heap) |
| , paramStyle_ (COM_STYLE_SQLROW) |
| , paramStyleVersion_ (COM_ROUTINE_PARAM_STYLE_VERSION_1) |
| , isDeterministic_ (1) |
| , isCallOnNull_ (1) |
| , isIsolate_ (0) // Trusted UDR like FastExtract |
| , externalSecurity_ (COM_ROUTINE_EXTERNAL_SECURITY_INVOKER) |
| , isExtraCall_ (1) |
| , hasOutParams_ (FALSE) |
| , redefTime_ (0) |
| , lastUsedTime_ (0) |
| , routineSecKeySet_ (heap) |
| , passThruDataNumEntries_ (0) |
| , passThruData_ (NULL) |
| , passThruDataSize_ (NULL) |
| , udfFanOut_ (1) |
| , uecValues_ (heap,0) |
| , isUniversal_ (0) |
| , actionPosition_ (-1) |
| , executionMode_ (COM_ROUTINE_SAFE_EXECUTION) |
| , objectUID_ (0) |
| , dllName_ ("", heap) |
| , dllEntryPoint_ ("", heap) |
| , comRoutineParallelism_ ("", heap) |
| , sasFormatWidth_ ("", heap) |
| , systemName_ ("", heap) |
| , dataSource_ ("", heap) |
| , fileSuffix_ ("", heap) |
| , schemaVersionOfRoutine_ (COM_VERS_2500) |
| , objectOwner_ (0) |
| , schemaOwner_ (0) |
| , privInfo_ (NULL) |
| , heap_(heap) |
| { |
| CollIndex colCount = 0; |
| NAColumn *newCol = NULL; |
| NAType *newColType = NULL; |
| extRoutineName_ = new (heap) ExtendedQualName( name_, heap ); |
| extActionName_ = new (heap) NAString(heap); |
| intActionName_ = new (heap) ComObjectName(heap); |
| params_ = new (heap) NAColumnArray(heap); |
| inParams_ = new (heap) NAColumnArray(heap); |
| outParams_ = new (heap) NAColumnArray(heap); |
| |
| // Construct the CostVectors |
| // CQDs are checked at Bind time. |
| Int32 initCpuCost = -1; |
| Int32 initIOCost = -1; |
| Int32 initMsgCost = -1; |
| |
| CostScalar initialCpuCost( initCpuCost); |
| CostScalar initialIOCost( initIOCost); |
| CostScalar initialMsgCost( initMsgCost); |
| |
| initialRowCost_.setCPUTime( initCpuCost < 0 ? csMinusOne : initialCpuCost); |
| initialRowCost_.setIOTime( initIOCost < 0 ? csMinusOne : initialIOCost); |
| initialRowCost_.setMSGTime( initMsgCost < 0 ? csMinusOne : initialMsgCost); |
| |
| Int32 normCpuCost = -1; |
| Int32 normIOCost = -1; |
| Int32 normMsgCost = -1; |
| |
| CostScalar normalCpuCost( normCpuCost); |
| CostScalar normalIOCost( normIOCost); |
| CostScalar normalMsgCost( normMsgCost); |
| |
| normalRowCost_.setCPUTime( normCpuCost < 0 ? csMinusOne : normalCpuCost); |
| normalRowCost_.setIOTime( normIOCost < 0 ? csMinusOne : normalIOCost); |
| normalRowCost_.setMSGTime( normMsgCost < 0 ? csMinusOne : normalMsgCost); |
| |
| // this is for prototyping only |
| for (CollIndex currentCol=0; currentCol<colCount; currentCol++) |
| { |
| // Create the new NAType. |
| newColType = new (heap) SQLVarChar (heap, 255 |
| , 1 |
| , FALSE |
| , FALSE /*not caseinsensitive, for now*/ |
| , CharInfo::ISO88591 |
| , CharInfo::DefaultCollation |
| , CharInfo::COERCIBLE |
| , CharInfo::ISO88591 |
| ); |
| |
| ComColumnDirection colDirection = COM_INPUT_COLUMN; |
| |
| NAString nameStr("pattern"); |
| NAString empStr(" "); |
| |
| // Create the new NAColumn and insert it into the NAColumnArray |
| newCol = new (heap) NAColumn ( (char *)nameStr.data() |
| , currentCol +1 |
| , newColType |
| , heap |
| , NULL // NATable * |
| , USER_COLUMN |
| , COM_NO_DEFAULT |
| , NULL // default value |
| , NULL |
| , FALSE |
| , FALSE // addedColumn |
| , colDirection |
| , FALSE |
| , NULL// (char *) ucol->routineParamType |
| ); |
| |
| |
| inParams_->insert (newCol); |
| params_->insert (newCol ); |
| } // for |
| |
| passThruDataNumEntries_ = 0; |
| passThruData_ = NULL; |
| passThruDataSize_ = NULL; |
| |
| // Copy privilege information |
| heapSize_ = (heap ? heap->getTotalSize() : 0); |
| } // NARoutine |
| |
| NARoutine::NARoutine (const NARoutine &old, CollHeap *h) |
| : name_ (old.name_, h) |
| , hashKey_ (old.hashKey_, h) |
| , language_ (old.language_) |
| , UDRType_ (old.UDRType_) |
| , sqlAccess_ (old.sqlAccess_) |
| , transactionAttributes_ (old.transactionAttributes_) |
| , maxResults_ (old.maxResults_) |
| , externalFile_ (old.externalFile_, h) |
| , externalPath_ (old.externalPath_, h) |
| , externalName_ (old.externalName_, h) |
| , signature_ (old.signature_, h) |
| , librarySqlName_ (old.librarySqlName_, h) |
| , paramStyle_ (old.paramStyle_) |
| , paramStyleVersion_ (old.paramStyleVersion_) |
| , isDeterministic_ (old.isDeterministic_) |
| , isCallOnNull_ (old.isCallOnNull_) |
| , isIsolate_ (old.isIsolate_) |
| , externalSecurity_ (old.externalSecurity_) |
| , isExtraCall_ (old.isExtraCall_) |
| , hasOutParams_ (old.hasOutParams_) |
| , redefTime_ (old.redefTime_) |
| , lastUsedTime_ (old.lastUsedTime_) |
| , routineSecKeySet_ (h) |
| , isUniversal_ (old.isUniversal_) |
| , executionMode_ (old.getExecutionMode()) |
| , objectUID_ (old.objectUID_) |
| , stateAreaSize_ (old.stateAreaSize_) |
| , dllName_ (old.dllName_, h) |
| , dllEntryPoint_ (old.dllEntryPoint_, h) |
| , comRoutineParallelism_ (old.comRoutineParallelism_) |
| , sasFormatWidth_ (old.sasFormatWidth_, h) |
| , systemName_ (old.systemName_, h) |
| , dataSource_ (old.dataSource_, h) |
| , fileSuffix_ (old.fileSuffix_, h) |
| , initialRowCost_ (old.initialRowCost_) |
| , normalRowCost_ (old.normalRowCost_) |
| , udfFanOut_ (old.udfFanOut_) |
| , passThruDataNumEntries_ (old.passThruDataNumEntries_) |
| , uecValues_ (old.uecValues_, h) |
| , actionPosition_ (old.actionPosition_) |
| , schemaVersionOfRoutine_ (old.schemaVersionOfRoutine_) |
| , objectOwner_ (0) |
| , schemaOwner_ (0) |
| , privInfo_ (NULL) |
| , heap_ (h) |
| { |
| extRoutineName_ = new (h) ExtendedQualName(*old.extRoutineName_, h); |
| extActionName_ = new (h) NAString(*old.extActionName_, h); |
| intActionName_ = new (h) ComObjectName(*old.intActionName_, h); |
| inParams_ = new (h) NAColumnArray(*old.inParams_, h); |
| outParams_ = new (h) NAColumnArray(*old.outParams_, h); |
| params_ = new (h) NAColumnArray(*old.params_, h); |
| |
| if (old.passThruDataNumEntries_ EQU 0) |
| { |
| passThruDataNumEntries_ = 0; |
| passThruData_ = NULL; |
| passThruDataSize_ = NULL; |
| } |
| else |
| { |
| passThruData_ = new (h) char*[(UInt32) passThruDataNumEntries_]; |
| passThruDataSize_ = new (h) Int64[(UInt32) passThruDataNumEntries_]; |
| for (Int32 i=0; i<passThruDataNumEntries_; i++) |
| { |
| passThruDataSize_[i]=old.passThruDataSize_[i]; |
| passThruData_[i] = new (h) char[(UInt32)passThruDataSize_[i]+1]; |
| memcpy(passThruData_[i], old.passThruData_[i], (size_t)passThruDataSize_[i]); |
| passThruData_[i][(size_t)passThruDataSize_[i]]=0; // make sure to Null terminate the string |
| } |
| } |
| |
| routineSecKeySet_ = old.routineSecKeySet_; |
| |
| heapSize_ = (h ? h->getTotalSize() : 0); |
| } |
| |
| NARoutine::NARoutine(const QualifiedName &name, |
| const TrafDesc *routine_desc, |
| BindWA *bindWA, |
| Int32 &errorOccurred, |
| NAMemory *heap) |
| : name_ (name, heap) |
| , hashKey_ (name, heap) |
| , language_ (routine_desc->routineDesc()->language) |
| , UDRType_ (routine_desc->routineDesc()->UDRType) |
| , sqlAccess_ (routine_desc->routineDesc()->sqlAccess) |
| , transactionAttributes_ (routine_desc->routineDesc()->transactionAttributes) |
| , maxResults_ (routine_desc->routineDesc()->maxResults) |
| , stateAreaSize_ (routine_desc->routineDesc()->stateAreaSize) |
| , externalFile_ ("", heap) |
| , externalPath_ (routine_desc->routineDesc()->libraryFileName, heap) |
| , externalName_ ("", heap) |
| , librarySqlName_ (routine_desc->routineDesc()->librarySqlName, COM_UNKNOWN_NAME, FALSE, heap) //TODO |
| , signature_ (routine_desc->routineDesc()->signature, heap) |
| , paramStyle_ (routine_desc->routineDesc()->paramStyle) |
| , paramStyleVersion_ (COM_ROUTINE_PARAM_STYLE_VERSION_1) |
| , isDeterministic_ (routine_desc->routineDesc()->isDeterministic) |
| , isCallOnNull_ (routine_desc->routineDesc()->isCallOnNull ) |
| , isIsolate_ (routine_desc->routineDesc()->isIsolate) |
| , externalSecurity_ (routine_desc->routineDesc()->externalSecurity) |
| , isExtraCall_ (FALSE) //TODO |
| , hasOutParams_ (FALSE) |
| , redefTime_ (0) //TODO |
| , lastUsedTime_ (0) |
| , routineSecKeySet_ (heap) |
| , passThruDataNumEntries_ (0) |
| , passThruData_ (NULL) |
| , passThruDataSize_ (0) |
| , udfFanOut_ (1) // TODO |
| , uecValues_ (heap,0) |
| , isUniversal_ (0) // TODO |
| , actionPosition_ (0) // TODO |
| , executionMode_ (COM_ROUTINE_SAFE_EXECUTION) |
| , objectUID_ (routine_desc->routineDesc()->objectUID) |
| , dllName_ (routine_desc->routineDesc()->libraryFileName, heap) |
| , dllEntryPoint_ (routine_desc->routineDesc()->externalName, heap) |
| , sasFormatWidth_ ("", heap) //TODO |
| , systemName_ ("", heap) // TODO |
| , dataSource_ ("", heap) // TODO |
| , fileSuffix_ ("", heap) // TODO |
| , schemaVersionOfRoutine_ ((COM_VERSION)0) // TODO |
| , objectOwner_ (routine_desc->routineDesc()->owner) |
| , schemaOwner_ (routine_desc->routineDesc()->schemaOwner) |
| , privInfo_ (NULL) |
| , heap_(heap) |
| { |
| char parallelism[5]; |
| CmGetComRoutineParallelismAsLit(routine_desc->routineDesc()->parallelism, parallelism); |
| comRoutineParallelism_ = ((char *)parallelism); |
| |
| if (paramStyle_ == COM_STYLE_JAVA_CALL) |
| { |
| NAString extName(routine_desc->routineDesc()->externalName); |
| size_t pos=extName.last('.'); |
| externalName_ = extName(pos+1, (extName.length()-pos-1)); // method_name |
| externalFile_ = extName.remove (pos); // package_name.class_name |
| } |
| else |
| { |
| externalName_ = routine_desc->routineDesc()->externalName; |
| if (language_ == COM_LANGUAGE_C || |
| language_ == COM_LANGUAGE_CPP) |
| { |
| // Split the fully-qualified DLL name into a directory name and |
| // simple file name |
| ComUInt32 len = dllName_.length(); |
| if (len > 0) |
| { |
| size_t lastSlash = dllName_.last('/'); |
| if (lastSlash == NA_NPOS) |
| { |
| // No slash was found |
| externalPath_ = "."; |
| externalFile_ = dllName_; |
| } |
| else |
| { |
| // A slash was found. EXTERNAL PATH is everything before the |
| // slash. EXTERNAL FILE is everything after. |
| externalPath_ = dllName_; |
| externalPath_.remove(lastSlash, len - lastSlash); |
| externalFile_ = dllName_; |
| externalFile_.remove(0, lastSlash + 1); |
| } |
| } |
| } // if (len > 0) |
| } |
| |
| ComSInt32 colCount = routine_desc->routineDesc()->paramsCount; |
| NAColumn *newCol = NULL; |
| NAType *newColType = NULL; |
| extRoutineName_ = new (heap) ExtendedQualName( name_, heap ); |
| extActionName_ = new (heap) NAString(heap); |
| intActionName_ = new (heap) ComObjectName(heap); |
| params_ = new (heap) NAColumnArray(heap); |
| inParams_ = new (heap) NAColumnArray(heap); |
| outParams_ = new (heap) NAColumnArray(heap); |
| |
| // to compute java signature |
| ComFSDataType *paramType = new STMTHEAP ComFSDataType[colCount]; |
| ComUInt32 *subType = new STMTHEAP ComUInt32 [colCount]; |
| ComColumnDirection *direction = new STMTHEAP ComColumnDirection[colCount] ; |
| // |
| // Construct the CostVectors |
| // CQDs are checked at Bind time. |
| Int32 initCpuCost = -1; |
| Int32 initIOCost = -1; |
| Int32 initMsgCost = -1; |
| |
| CostScalar initialCpuCost( initCpuCost); |
| CostScalar initialIOCost( initIOCost); |
| CostScalar initialMsgCost( initMsgCost); |
| |
| initialRowCost_.setCPUTime( initCpuCost < 0 ? csMinusOne : initialCpuCost); |
| initialRowCost_.setIOTime( initIOCost < 0 ? csMinusOne : initialIOCost); |
| initialRowCost_.setMSGTime( initMsgCost < 0 ? csMinusOne : initialMsgCost); |
| |
| Int32 normCpuCost = -1; |
| Int32 normIOCost = -1; |
| Int32 normMsgCost = -1; |
| |
| CostScalar normalCpuCost( normCpuCost); |
| CostScalar normalIOCost( normIOCost); |
| CostScalar normalMsgCost( normMsgCost); |
| |
| normalRowCost_.setCPUTime( normCpuCost < 0 ? csMinusOne : normalCpuCost); |
| normalRowCost_.setIOTime( normIOCost < 0 ? csMinusOne : normalIOCost); |
| normalRowCost_.setMSGTime( normMsgCost < 0 ? csMinusOne : normalMsgCost); |
| |
| TrafDesc *params_desc_list = routine_desc->routineDesc()->params; |
| TrafColumnsDesc *param_desc; |
| |
| int i = 0; |
| while (params_desc_list) |
| { |
| param_desc = params_desc_list->columnsDesc(); |
| |
| // Create the new NAType. |
| if (NAColumn::createNAType(param_desc->columnsDesc(), (const NATable *)NULL, newColType, heap_)) |
| { |
| errorOccurred = TRUE; |
| return; |
| } |
| if (param_desc->colname && strncmp(param_desc->colname, "#:", 2) == 0) |
| { |
| memset(param_desc->colname, 0, 2); |
| } |
| |
| ComParamDirection colDirection = param_desc->paramDirection(); |
| |
| // Create the new NAColumn and insert it into the NAColumnArray |
| newCol = new (heap) NAColumn( |
| (const char *)UDRCopyString (param_desc->colname, heap) |
| , param_desc->colnumber |
| , newColType |
| , heap |
| , NULL // NATable * |
| , USER_COLUMN |
| , COM_NO_DEFAULT |
| , NULL // default value |
| , UDRCopyString("", heap) // TODO:heading can it have some value |
| , param_desc->isUpshifted() |
| , FALSE // addedColumn |
| , (ComColumnDirection) colDirection |
| , param_desc->isOptional() |
| , (char *) COM_NORMAL_PARAM_TYPE_LIT |
| ); |
| |
| // We have to check for INOUT in both the |
| // if's below |
| if ( COM_OUTPUT_PARAM == colDirection || |
| COM_INOUT_PARAM == colDirection ) |
| { |
| hasOutParams_ = TRUE; |
| outParams_->insert (newCol); |
| params_->insert (newCol ); |
| } |
| |
| if ( COM_INPUT_PARAM == colDirection || |
| COM_INOUT_PARAM == colDirection ) |
| { |
| inParams_->insert (newCol); |
| if ( COM_INOUT_PARAM != colDirection ) |
| { |
| params_->insert (newCol ); |
| } // if not INOUT |
| } // if IN or INOUT |
| |
| // Gather the param attributes for LM from the paramDefArray previously |
| // populated and from the routineparamList generated from paramDefArray. |
| paramType[i] = (ComFSDataType)newColType->getFSDatatype(); |
| subType[i] = 0; // default |
| |
| // Set subType for special cases detected by LM |
| switch ( paramType[i] ) |
| { |
| case COM_SIGNED_BIN16_FSDT : |
| case COM_SIGNED_BIN32_FSDT : |
| case COM_SIGNED_BIN64_FSDT : |
| case COM_UNSIGNED_BIN16_FSDT : |
| case COM_UNSIGNED_BIN32_FSDT : |
| case COM_UNSIGNED_BPINT_FSDT : |
| { |
| subType[i] = newColType->getPrecision(); |
| break; |
| } |
| |
| case COM_DATETIME_FSDT : |
| { |
| switch ( ((DatetimeType *)newColType)->getSubtype() ) |
| { |
| case DatetimeType::SUBTYPE_SQLDate : subType[i] = 1; break; |
| case DatetimeType::SUBTYPE_SQLTime : subType[i] = 2; break; |
| case DatetimeType::SUBTYPE_SQLTimestamp : subType[i] = 3; break; |
| } |
| } |
| } // end switch paramType[i] |
| |
| direction[i] = (ComColumnDirection) colDirection; |
| |
| params_desc_list = params_desc_list->next; |
| i++; |
| } // for |
| |
| passThruDataNumEntries_ = 0; |
| passThruData_ = NULL; |
| passThruDataSize_ = NULL; |
| |
| #define MAX_SIGNATURE_LENGTH 8193 |
| if ((language_ == COM_LANGUAGE_JAVA)&&(signature_.length() < 2)) |
| { |
| // Allocate buffer for generated signature |
| char sigBuf[MAX_SIGNATURE_LENGTH]; |
| sigBuf[0] = '\0'; |
| |
| // If the syntax specified a signature, pass that to LanguageManager. |
| char* optionalSig = NULL; |
| ComBoolean isJavaMain = |
| ((str_cmp_ne(externalName_.data(), "main") == 0) ? TRUE : FALSE); |
| |
| LmResult createSigResult; |
| LmJavaSignature *lmSignature = new (STMTHEAP) LmJavaSignature(NULL, |
| STMTHEAP); |
| createSigResult = lmSignature->createSig(paramType, subType, direction, |
| colCount, COM_UNKNOWN_FSDT, 0, |
| maxResults_, optionalSig, |
| isJavaMain, sigBuf, |
| MAX_SIGNATURE_LENGTH, |
| CmpCommon::diags()); |
| NADELETE(lmSignature, LmJavaSignature, STMTHEAP); |
| |
| |
| // Lm returned error. Lm fills diags area |
| if (createSigResult != LM_ERR) |
| signature_ = sigBuf; |
| } |
| |
| |
| getPrivileges(routine_desc->routineDesc()->priv_desc); |
| |
| heapSize_ = (heap ? heap->getTotalSize() : 0); |
| } |
| |
| NARoutine::~NARoutine() |
| { |
| // Call deepDelete() on NAColumnArray's. |
| // The destructor does not do this. |
| inParams_->deepDelete(); |
| outParams_->deepDelete(); |
| delete inParams_; |
| delete outParams_; |
| delete params_; // Do not do a deepDelete() on params_ the |
| // elements are shared with in|outParams_. |
| delete extRoutineName_; |
| delete extActionName_; |
| delete intActionName_; |
| uecValues_.clear(); // delete all its elements. |
| if (passThruData_ NEQ NULL) |
| { |
| for (Int32 i = 0; i < passThruDataNumEntries_; i++) |
| NADELETEBASIC(passThruData_[i], heap_); // Can't use NADELETEARRAY on C types. |
| NADELETEBASIC(passThruData_, heap_); // Can't use NADELETEARRAY on C types. |
| } |
| if (passThruDataSize_ NEQ NULL) // Use NADELETEARRAY for any 'new(heap)<class>[<size>]' |
| NADELETEARRAY(passThruDataSize_, (UInt32)passThruDataNumEntries_, Int64, heap_); |
| |
| if (privInfo_) |
| NADELETE(privInfo_, PrivMgrUserPrivs, heap_); |
| } |
| |
| void NARoutine::setSasFormatWidth(NAString &width) |
| { |
| sasFormatWidth_ = width; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // method: getPrivileges |
| // |
| // If authorization is enabled, set privs based on the passed in priv_desc |
| // and set up query invalidation (security) keys for the routine. |
| // ---------------------------------------------------------------------------- |
| void NARoutine::getPrivileges(TrafDesc *priv_desc) |
| { |
| if ( !CmpCommon::context()->isAuthorizationEnabled() || ComUser::isRootUserID()) |
| { |
| privInfo_ = new(heap_) PrivMgrUserPrivs; |
| privInfo_->setOwnerDefaultPrivs(); |
| return; |
| } |
| |
| NAString privMDLoc = CmpSeabaseDDL::getSystemCatalogStatic(); |
| privMDLoc += ".\""; |
| privMDLoc += SEABASE_PRIVMGR_SCHEMA; |
| privMDLoc += "\""; |
| PrivMgrCommands privInterface(privMDLoc.data(), CmpCommon::diags(),PrivMgr::PRIV_INITIALIZED); |
| |
| if (priv_desc == NULL) |
| { |
| privInfo_ = new(heap_) PrivMgrUserPrivs; |
| |
| CmpSeabaseDDL cmpSBD(STMTHEAP); |
| if (cmpSBD.switchCompiler(CmpContextInfo::CMPCONTEXT_TYPE_META)) |
| { |
| if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0) |
| *CmpCommon::diags() << DgSqlCode( -4400 ); |
| |
| return; |
| } |
| |
| ComObjectType objectType = (UDRType_ == COM_PROCEDURE_TYPE ? |
| COM_STORED_PROCEDURE_OBJECT : |
| COM_USER_DEFINED_ROUTINE_OBJECT); |
| |
| std::vector <ComSecurityKey *>* secKeyVec = new(heap_) std::vector<ComSecurityKey *>; |
| if (privInterface.getPrivileges(objectUID_, objectType, |
| ComUser::getCurrentUser(), |
| *privInfo_, secKeyVec) != STATUS_GOOD) |
| { |
| NADELETE(privInfo_, PrivMgrUserPrivs, heap_); |
| privInfo_ = NULL; |
| } |
| |
| cmpSBD.switchBackCompiler(); |
| |
| if (privInfo_) |
| { |
| for (std::vector<ComSecurityKey*>::iterator iter = secKeyVec->begin(); |
| iter != secKeyVec->end(); |
| iter++) |
| { |
| // Insertion of the dereferenced pointer results in NASet making |
| // a copy of the object, and then we delete the original. |
| routineSecKeySet_.insert(**iter); |
| delete *iter; |
| } |
| } |
| } |
| else |
| { |
| // get roles granted to current user |
| // SQL_EXEC_GetRoleList returns the list of roles from the CliContext |
| std::vector<int32_t> myRoles; |
| Int32 numRoles = 0; |
| Int32 *roleIDs = NULL; |
| if (SQL_EXEC_GetRoleList(numRoles, roleIDs) < 0) |
| { |
| *CmpCommon::diags() << DgSqlCode(-1034); |
| return; |
| } |
| |
| // At this time we should have at least one entry in roleIDs (PUBLIC_USER) |
| CMPASSERT (roleIDs && numRoles > 0); |
| |
| for (Int32 i = 0; i < numRoles; i++) |
| myRoles.push_back(roleIDs[i]); |
| |
| privInfo_ = new (heap_) PrivMgrUserPrivs; |
| privInfo_->initUserPrivs(myRoles, priv_desc, ComUser::getCurrentUser(),objectUID_, routineSecKeySet_); |
| } |
| } |
| |
| ULng32 NARoutineDBKey::hash() const |
| { |
| return routine_.hash() ^ action_.hash(); |
| } |
| |
| ULng32 hashKey(const NARoutineDBKey &key) |
| { |
| return key.hash(); |
| } |
| // NARoutineDB member functions (NARoutine caching) |
| #define DEFAULT_ROUTINEDB_CACHE_SZ 20 // in MB |
| |
| // NARoutineDB public member functions. |
| // ====================================== |
| // Constructor |
| NARoutineDB::NARoutineDB(NAMemory *h) : |
| heap_(h), |
| routinesToDeleteAfterStatement_(h), |
| cacheMetaData_(TRUE), |
| metadata(""), |
| currentCacheSize_(0), |
| refreshCacheInThisStatement_(FALSE), |
| entries_(0), |
| highWatermarkCache_(0), |
| totalLookupsCount_(0), |
| totalCacheHits_(0), |
| NAKeyLookup<NARoutineDBKey, NARoutine> (NARoutineDB_INIT_SIZE, |
| NAKeyLookupEnums::KEY_INSIDE_VALUE, |
| h) |
| { |
| // Initial size. Cannot use CQDs, since NARoutineDB is constructed as |
| // part of SchemaDB object. |
| defaultCacheSize_ = DEFAULT_ROUTINEDB_CACHE_SZ*1024*1024; |
| maxCacheSize_ = defaultCacheSize_; |
| } |
| |
| NABoolean NARoutineDB::cachingMetaData() |
| { |
| maxCacheSize_ = CmpCommon::getDefaultLong(ROUTINE_CACHE_SIZE); |
| return cacheMetaData_ && maxCacheSize_; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // method: moveRoutineToDeleteList |
| // |
| // This method removes the routine from the primary cache and adds it to the |
| // list of routines to delete after statement execution completes. |
| // |
| // cachedNARoutine is a pointer to an NARoutine entry |
| // key is a pointer to the routine key |
| // ---------------------------------------------------------------------------- |
| void NARoutineDB::moveRoutineToDeleteList(NARoutine *cachedNARoutine, const NARoutineDBKey *key) |
| { |
| // routine is not cached, just return |
| if (cachedNARoutine == NULL || !cachingMetaData()) |
| return; |
| |
| // Add pointer to the routine to the list that will be deleted after the |
| // statement completes (to avoid affecting compile time) |
| routinesToDeleteAfterStatement_.insert(cachedNARoutine); |
| |
| // The NARoutine in cache is dirty and needs to be removed. |
| // Remove entry that the key is pointing to |
| remove(key); |
| |
| // Adjust cache size |
| if ((ULng32)cachedNARoutine->getSize() <= currentCacheSize_) |
| { |
| currentCacheSize_ -= cachedNARoutine->getSize(); |
| if (entries_>0) entries_--; |
| } |
| else |
| { |
| currentCacheSize_ = 0; |
| entries_ = 0; |
| } |
| } |
| |
| // Cleanup NARoutine cache after the statement completes. Remove entries |
| // using LRU policy, if the cache has grown too large. The approach here is |
| // somewhat different from NATableDB caching, which deletes entries from the |
| // NATable cache if the statement was DDL that may have affected the table |
| // definition. NATable caching also deletes tables from the cache at this |
| // time for performance reasons. |
| void NARoutineDB::resetAfterStatement() |
| { |
| // Delete 'dirty' NARoutine objects that were not deleted earlier |
| // to save compile-time performance. |
| if (routinesToDeleteAfterStatement_.entries()) |
| { |
| // Clear the list of tables to delete after statement |
| routinesToDeleteAfterStatement_.clear(); |
| } |
| |
| if (entries()) |
| { |
| // Reduce size of cache if it has grown too large. |
| if (!enforceMemorySpaceConstraints()) |
| cacheMetaData_ = FALSE; // Disable cache if there is a problem. |
| |
| // Reset statement level flags |
| refreshCacheInThisStatement_=FALSE; |
| |
| // Clear 'accessed in current statement' flag for all cached NARoutines. |
| NAHashDictionaryIterator<NARoutineDBKey,NARoutine> iter (*this); |
| NARoutineDBKey *key; |
| NARoutine *routine; |
| iter.getNext(key,routine); |
| while(key) { |
| routine->getAccessedInCurStmt() = FALSE; |
| iter.getNext(key,routine); |
| } |
| } |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // method: free_entries_with_QI_key |
| // |
| // This method is sent a list of query invalidation keys. |
| // It looks through the list of routines to see if any of them need to be |
| // removed from cache because their definitions are no longer valid. |
| // |
| // numKeys - number of existing invalidation keys |
| // qiKeyArray - actual keys |
| // ---------------------------------------------------------------------------- |
| void NARoutineDB::free_entries_with_QI_key(Int32 numKeys, SQL_QIKEY* qiKeyArray) |
| { |
| NAHashDictionaryIterator<NARoutineDBKey,NARoutine> iter (*this); |
| NARoutineDBKey *key; |
| NARoutine *routine; |
| iter.getNext(key,routine); |
| while(key && routine) |
| { |
| // See if item should be removed |
| if (qiCheckForInvalidObject(numKeys, qiKeyArray, |
| routine->getRoutineID(), |
| routine->getSecKeySet())) |
| moveRoutineToDeleteList(routine, key); |
| iter.getNext(key,routine); |
| } |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // method: removeNARoutine |
| // |
| // The method is called when DDL is performed against a routine making its |
| // definition incorrect. |
| // It has a side affect of generating query invalidation keys that are |
| // propagate to all the other processes that could have the routine stored |
| // in cache. |
| // ---------------------------------------------------------------------------- |
| void NARoutineDB::removeNARoutine2(QualifiedName &routineName, |
| ComQiScope qiScope, |
| Int64 objUID) |
| { |
| |
| NAHashDictionaryIterator<NARoutineDBKey,NARoutine> iter (*this); |
| NARoutineDBKey *key = NULL; |
| NARoutine *cachedNARoutine = NULL; |
| |
| NASet<Int64> objectUIDs(CmpCommon::statementHeap(), 1); |
| |
| // If there are no items in cache, skip |
| if (entries() > 0) |
| { |
| NASet<Int64> objectUIDs(CmpCommon::statementHeap(), 1); |
| |
| // iterate over all entries and remove the ones that match the name |
| iter.reset(); |
| iter.getNext(key,cachedNARoutine); |
| |
| while(key && cachedNARoutine) |
| { |
| if (cachedNARoutine->getSqlName() == routineName) |
| { |
| objectUIDs.insert(cachedNARoutine->getRoutineID()); |
| moveRoutineToDeleteList(cachedNARoutine,key); |
| } |
| iter.getNext(key,cachedNARoutine); |
| } |
| } |
| |
| // clear out the other users' caches too. |
| if (qiScope == REMOVE_FROM_ALL_USERS) |
| { |
| // There are some scenarios where the affected object does not have an |
| // NARoutine cache entry. However, other processes may have this routine |
| // in their caches. Go ahead and create an invalidation key |
| if (0 == objectUIDs.entries()) |
| objectUIDs.insert(objUID); |
| |
| Int32 numKeys = objectUIDs.entries(); |
| SQL_QIKEY qiKeys[numKeys]; |
| for (CollIndex i = 0; i < numKeys; i++) |
| { |
| qiKeys[i].ddlObjectUID = objectUIDs[i]; |
| qiKeys[i].operation[0] = 'O'; |
| qiKeys[i].operation[1] = 'R'; |
| } |
| long retcode = SQL_EXEC_SetSecInvalidKeys(numKeys, qiKeys); |
| } |
| } |
| |
| // This method follows the same semantics as NATableDB::removeNATable |
| void NARoutineDB::removeNARoutine(QualifiedName &routineName, |
| ComQiScope qiScope, |
| Int64 objUID, |
| NABoolean ddlXns, NABoolean atCommit) |
| |
| { |
| if ((ddlXns) && |
| (NOT atCommit)) |
| { |
| CmpContext::DDLObjInfo ddlObj; |
| ddlObj.ddlObjName = routineName.getQualifiedNameAsString(); |
| ddlObj.qiScope = qiScope; |
| ddlObj.ot = COM_USER_DEFINED_ROUTINE_OBJECT; |
| ddlObj.objUID = objUID; |
| |
| NABoolean found = FALSE; |
| for (Lng32 i = 0; |
| ((NOT found) && (i < CmpCommon::context()->ddlObjsList().entries())); |
| i++) |
| { |
| CmpContext::DDLObjInfo &ddlObjInList = |
| CmpCommon::context()->ddlObjsList()[i]; |
| if (ddlObj.ddlObjName == ddlObjInList.ddlObjName) |
| found = TRUE; |
| } |
| |
| removeNARoutine2(routineName, qiScope, objUID); |
| |
| if (NOT found) |
| CmpCommon::context()->ddlObjsList().insert(ddlObj); |
| |
| return; |
| } |
| |
| removeNARoutine2(routineName, qiScope, objUID); |
| } |
| |
| // Find the NARoutine entry in the cache for 'key' or create it if not found. |
| // 1. Check for entry in cache. |
| // 2. If it doesn't exist, return. |
| // 3. If it does exist, check to see if this is first time entry accessed. |
| // 4. If so, check to see if entry is dirty (obsolete). |
| // 5. If dirty, remove key and add to list to remove entry after statement |
| // completes. |
| // Note that BindWA is needed to be passed to this function so that we can |
| // use it with getRedefTime() is necessary. |
| NARoutine *NARoutineDB::get(BindWA *bindWA, const NARoutineDBKey *key) |
| { |
| // Check cache to see if a cached NARoutine object exists |
| NARoutine *cachedNARoutine = |
| NAKeyLookup<NARoutineDBKey,NARoutine>::get(key); /* 1 */ |
| |
| totalLookupsCount_++; // Statistics counter: number of lookups |
| |
| if (!cachedNARoutine || !cacheMetaData_) return NULL; /* 2 */ |
| |
| totalCacheHits_++; // Statistics counter: number of cache hits. |
| |
| // Record time that this NARoutine was obtained from cache for LRU. |
| cachedNARoutine->setLastUsedTime(hs_getEpochTime()); |
| |
| cachedNARoutine->getAccessedInCurStmt() = TRUE; |
| |
| return cachedNARoutine; |
| } |
| |
| // Insert NARoutine in NARoutineDB cache and update size. |
| void NARoutineDB::put(NARoutine *routine) |
| { |
| if (cacheMetaData_ && maxCacheSize_) |
| { |
| routine->setLastUsedTime(hs_getEpochTime()); |
| insert(routine); // This function returns void. |
| |
| entries_++; |
| currentCacheSize_ += routine->getSize(); |
| if (currentCacheSize_ > highWatermarkCache_) |
| highWatermarkCache_ = currentCacheSize_; // statistics counter |
| } |
| } |
| |
| |
| // NARoutineDB private member functions. |
| // ====================================== |
| // Check if cache size is within maximum allowed cache size. If not, |
| // then remove entries in the cache based on the replacement policy, |
| // until the cache size drops below the allowed size. |
| // DO NOT CALL THIS ROUTINE IN THE MIDDLE OF A STATEMENT. |
| NABoolean NARoutineDB::enforceMemorySpaceConstraints() |
| { |
| NABoolean retval = TRUE; |
| |
| // Set cache size to CQD setting. |
| maxCacheSize_ = CmpCommon::getDefaultLong(ROUTINE_CACHE_SIZE) |
| * 1024 * 1024; |
| |
| // Check if cache size is within memory constraints |
| if (currentCacheSize_ <= maxCacheSize_) |
| return retval; |
| |
| // Need to reduce cache size |
| |
| // Loop through the list and attempt to remove the entries |
| // that are least recently used (that is, that have the oldest |
| // timestamps of when they were last used). Do not allow the |
| // number of times looped to exceed the number of entries in |
| // cache. |
| Lng32 loopCnt = 0, entries = this->entries(); |
| while (currentCacheSize_ > maxCacheSize_ && loopCnt++ < entries){ |
| // Find least recently used NARoutine in cache. |
| NAHashDictionaryIterator<NARoutineDBKey,NARoutine> iter (*this); |
| NARoutineDBKey *key=0, *oldestKey=0; |
| NARoutine *routine=0, *oldestRoutine=0; |
| Int64 oldestTime; |
| |
| iter.reset(); |
| iter.getNext(key,routine); |
| if (key && routine) // This should always be true. |
| { |
| oldestTime = routine->getLastUsedTime(); |
| while(key) |
| { |
| // Check routine for last used time. Save oldest. Must use |
| // '<=' so that oldestKey will get set first time through loop. |
| if (routine && routine->getLastUsedTime() <= oldestTime) |
| { |
| oldestTime = routine->getLastUsedTime(); |
| oldestKey = key; |
| oldestRoutine = routine; |
| } |
| iter.getNext(key, routine); |
| } |
| remove(oldestKey); |
| currentCacheSize_ -= oldestRoutine->getSize(); |
| if (entries_>0) entries_--; |
| delete oldestRoutine; |
| } |
| if ((ULng32) oldestRoutine->getSize() <= currentCacheSize_) |
| { |
| currentCacheSize_ -= oldestRoutine->getSize(); |
| if (entries_>0) entries_--; |
| } |
| else |
| { |
| currentCacheSize_ = 0; |
| entries_ = 0; |
| } |
| } |
| |
| //return true indicating cache size is below maximum memory allowance. |
| if (currentCacheSize_ > maxCacheSize_) retval = FALSE; |
| return retval; |
| } |
| |
| void NARoutineDB::flushCache() |
| { |
| |
| //if something is cached |
| if(cacheMetaData_) |
| { |
| //set the flag to indicate cache is clear |
| cacheMetaData_ = FALSE; |
| |
| NAHashDictionaryIterator<NARoutineDBKey,NARoutine> iter (*this); |
| NARoutineDBKey *key; |
| NARoutine *routine; |
| iter.getNext(key,routine); |
| while(key && routine) |
| { |
| remove(key); |
| delete routine ; |
| iter.getNext(key,routine); |
| } |
| |
| routinesToDeleteAfterStatement_.clear(); |
| |
| //set cache size to 0 to indicate nothing in cache |
| currentCacheSize_ = 0; |
| entries_ = 0; |
| highWatermarkCache_ = 0; // High watermark of currentCacheSize_ |
| totalLookupsCount_ = 0; // reset NARoutine entries lookup counter |
| totalCacheHits_ = 0; // reset cache hit counter |
| replacementCursor_ = 0; |
| } |
| |
| |
| } |
| |
| void NARoutineDB::getCacheStats(NARoutineCacheStats & stats) |
| { |
| stats.numLookups = totalLookupsCount_; |
| stats.numCacheHits = totalCacheHits_; |
| stats.currentCacheSize = currentCacheSize_; |
| stats.highWaterMark = highWatermarkCache_; |
| stats.maxCacheSize = maxCacheSize_; |
| stats.numEntries = entries_; |
| } |
| |
| //----------------------------------------------------------------------- |
| // NARoutineCacheStoredProcedure is a class that contains functions used by |
| // the NARoutineCache virtual table, whose purpose is to serve as an interface |
| // to the SQL/MX NARoutine cache statistics. This table is implemented as |
| // an internal stored procedure. |
| //----------------------------------------------------------------------- |
| |
| SP_STATUS NARoutineCacheStatStoredProcedure::sp_InputFormat(SP_FIELDDESC_STRUCT *inputFieldFormat, |
| Lng32 numFields, |
| SP_COMPILE_HANDLE spCompileObj, |
| SP_HANDLE spObj, |
| SP_ERROR_STRUCT *error) |
| { |
| if ( numFields != 2 ) |
| { |
| //accepts 2 input columns |
| error->error = arkcmpErrorISPWrongInputNum; |
| strcpy(error->optionalString[0], "NARoutineCache"); |
| error->optionalInteger[0] = 2; |
| return SP_FAIL; |
| } |
| |
| //column as input parameter for ISP, specifiy cache of metadata or user context |
| strcpy(&((inputFieldFormat++)->COLUMN_DEF[0]), "instance char(16) not null"); |
| strcpy(&((inputFieldFormat++)->COLUMN_DEF[0]), "location char(16) not null"); |
| return SP_SUCCESS; |
| } |
| |
| SP_STATUS NARoutineCacheStatStoredProcedure::sp_NumOutputFields( |
| Lng32 *numFields, |
| SP_COMPILE_HANDLE spCompileObj, |
| SP_HANDLE spObj, |
| SP_ERROR_STRUCT *error) |
| { |
| const Lng32 NUM_OF_OUTPUT = 6; |
| |
| *numFields = NUM_OF_OUTPUT; |
| return SP_SUCCESS; |
| } |
| |
| SP_STATUS NARoutineCacheStatStoredProcedure::sp_OutputFormat( |
| SP_FIELDDESC_STRUCT *format, |
| SP_KEYDESC_STRUCT keyFields[], |
| Lng32 *numKeyFields, |
| SP_HANDLE spCompileObj, |
| SP_HANDLE spObj, |
| SP_ERROR_STRUCT *error) |
| { |
| strcpy(&((format++)->COLUMN_DEF[0]), "Num_lookups INT UNSIGNED"); |
| strcpy(&((format++)->COLUMN_DEF[0]), "Num_cache_hits INT UNSIGNED"); |
| strcpy(&((format++)->COLUMN_DEF[0]), "Num_entries INT UNSIGNED"); |
| strcpy(&((format++)->COLUMN_DEF[0]), "Current_cache_size INT UNSIGNED"); |
| strcpy(&((format++)->COLUMN_DEF[0]), "High_watermark INT UNSIGNED"); |
| strcpy(&((format++)->COLUMN_DEF[0]), "Max_cache_size INT UNSIGNED"); |
| |
| return SP_SUCCESS; |
| } |
| |
| SP_STATUS NARoutineCacheStatStoredProcedure::sp_ProcessRoutine( |
| SP_PROCESS_ACTION action, |
| SP_ROW_DATA inputData, |
| SP_EXTRACT_FUNCPTR eFunc, |
| SP_ROW_DATA outputData, |
| SP_FORMAT_FUNCPTR fFunc, |
| SP_KEY_VALUE keys, |
| SP_KEYVALUE_FUNCPTR kFunc, |
| SP_PROCESS_HANDLE *spProcHandle, |
| SP_HANDLE spObj, |
| SP_ERROR_STRUCT *error) |
| { |
| if (action == SP_PROC_OPEN) { |
| NARoutineCacheStatsISPIterator * it = new (GetCliGlobals()->exCollHeap()) |
| NARoutineCacheStatsISPIterator(inputData, eFunc, error, |
| GetCliGlobals()->currContext()->getCmpContextInfo(), |
| GetCliGlobals()->exCollHeap()); |
| *spProcHandle = it; |
| return SP_SUCCESS; |
| } |
| |
| if (action == SP_PROC_FETCH) { |
| NARoutineCacheStatsISPIterator* it = (NARoutineCacheStatsISPIterator *)(*spProcHandle); |
| if (!it) { |
| return SP_FAIL; |
| } |
| NARoutineCacheStats stats; |
| if(!it->getNext(stats)) |
| return SP_SUCCESS; |
| fFunc(0, outputData, sizeof(ULng32), &(stats.numLookups), 0); |
| fFunc(1, outputData, sizeof(ULng32), &(stats.numCacheHits), 0); |
| fFunc(2, outputData, sizeof(ULng32), &(stats.numEntries), 0); |
| fFunc(3, outputData, sizeof(ULng32), &(stats.currentCacheSize), 0); |
| fFunc(4, outputData, sizeof(ULng32), &(stats.highWaterMark), 0); |
| fFunc(5, outputData, sizeof(ULng32), &(stats.maxCacheSize), 0); |
| return SP_MOREDATA; |
| } |
| |
| if (action == SP_PROC_CLOSE) { |
| if (*spProcHandle) |
| NADELETEBASIC((NARoutineCacheStatsISPIterator *)(*spProcHandle), GetCliGlobals()->exCollHeap()); |
| return SP_SUCCESS; |
| } |
| return SP_SUCCESS; |
| } |
| |
| SP_STATUS NARoutineCacheStatStoredProcedure::sp_ProcessAction( |
| SP_PROCESS_ACTION action, |
| SP_ROW_DATA inputData, |
| SP_EXTRACT_FUNCPTR eFunc, |
| SP_ROW_DATA outputData, |
| SP_FORMAT_FUNCPTR fFunc, |
| SP_KEY_VALUE keys, |
| SP_KEYVALUE_FUNCPTR kFunc, |
| SP_PROCESS_HANDLE *spProcHandle, |
| SP_HANDLE spObj, |
| SP_ERROR_STRUCT *error) |
| { |
| struct InfoStruct |
| { |
| ULng32 counter; |
| }; |
| |
| SP_STATUS status = SP_SUCCESS; |
| InfoStruct *is = NULL; |
| |
| NARoutineDB * tableDB = ActiveSchemaDB()->getNARoutineActionDB(); |
| |
| switch (action) |
| { |
| case SP_PROC_OPEN: |
| is = new InfoStruct; |
| is->counter = 0; |
| *spProcHandle = is; |
| break; |
| |
| case SP_PROC_FETCH: |
| is = (InfoStruct*)(*spProcHandle); |
| if (is == NULL ) |
| { |
| status = SP_FAIL; |
| break; |
| } |
| |
| if (is->counter > 0) break; |
| is->counter++; |
| fFunc(0, outputData, sizeof(ULng32), &(tableDB->totalLookupsCount_), 0); |
| fFunc(1, outputData, sizeof(ULng32), &(tableDB->totalCacheHits_), 0); |
| fFunc(2, outputData, sizeof(ULng32), &(tableDB->entries_), 0); |
| fFunc(3, outputData, sizeof(ULng32), &(tableDB->currentCacheSize_), 0); |
| fFunc(4, outputData, sizeof(ULng32), &(tableDB->highWatermarkCache_), 0); |
| fFunc(5, outputData, sizeof(ULng32), &(tableDB->maxCacheSize_), 0); |
| status = SP_MOREDATA; |
| break; |
| |
| case SP_PROC_CLOSE: |
| delete (InfoStruct*) (*spProcHandle); |
| break; |
| } |
| return status; |
| } |
| |
| void NARoutineCacheStatStoredProcedure::Initialize(SP_REGISTER_FUNCPTR regFunc) |
| { |
| regFunc("NAROUTINECACHE", |
| sp_Compile, |
| sp_InputFormat, |
| 0, |
| sp_NumOutputFields, |
| sp_OutputFormat, |
| sp_ProcessRoutine, |
| 0, |
| CMPISPVERSION); |
| regFunc("NAROUTINEACTIONCACHE", |
| sp_Compile, |
| sp_InputFormat, |
| 0, |
| sp_NumOutputFields, |
| sp_OutputFormat, |
| sp_ProcessAction, |
| 0, |
| CMPISPVERSION); |
| } |
| |
| //----------------------------------------------------------------------- |
| // NARoutineCacheDeleteStoredProcedure is a class that contains functions used |
| // to delete the contents of the NARoutineCache virtual table. The delete |
| // function is implemented as an internal stored procedure. |
| //----------------------------------------------------------------------- |
| |
| |
| SP_STATUS NARoutineCacheDeleteStoredProcedure::sp_Process( |
| SP_PROCESS_ACTION action, |
| SP_ROW_DATA inputData, |
| SP_EXTRACT_FUNCPTR eFunc, |
| SP_ROW_DATA outputData, |
| SP_FORMAT_FUNCPTR fFunc, |
| SP_KEY_VALUE keys, |
| SP_KEYVALUE_FUNCPTR kFunc, |
| SP_PROCESS_HANDLE *spProcHandle, |
| SP_HANDLE spObj, |
| SP_ERROR_STRUCT *error) |
| { |
| struct InfoStruct |
| { |
| ULng32 counter; |
| }; |
| |
| SP_STATUS status = SP_SUCCESS; |
| InfoStruct *is = NULL; |
| NARoutineDB * routineDB = NULL; |
| NARoutineDB * actionDB = NULL; |
| |
| switch (action) |
| { |
| case SP_PROC_OPEN: |
| // No inputs to process |
| is = new InfoStruct; |
| is->counter = 0; |
| *spProcHandle = is; |
| break; |
| |
| case SP_PROC_FETCH: |
| is = (InfoStruct*)(*spProcHandle); |
| if (is == NULL ) |
| { |
| status = SP_FAIL; |
| break; |
| } |
| |
| routineDB = ActiveSchemaDB()->getNARoutineDB(); |
| actionDB = ActiveSchemaDB()->getNARoutineActionDB(); |
| |
| //clear out NARoutineCache |
| if (routineDB) |
| { |
| routineDB->setCachingOFF(); |
| routineDB->setCachingON(); |
| } |
| if (actionDB) |
| { |
| actionDB->setCachingOFF(); |
| actionDB->setCachingON(); |
| } |
| break; |
| |
| case SP_PROC_CLOSE: |
| delete (InfoStruct*) (*spProcHandle); |
| break; |
| } |
| return status; |
| } |
| |
| void NARoutineCacheDeleteStoredProcedure::Initialize(SP_REGISTER_FUNCPTR regFunc) |
| { |
| regFunc("NAROUTINECACHEDELETE", |
| sp_Compile, |
| sp_InputFormat, |
| 0, |
| sp_NumOutputFields, |
| sp_OutputFormat, |
| sp_Process, |
| 0, |
| CMPISPVERSION); |
| } |
| |
| NARoutineCacheStatsISPIterator::NARoutineCacheStatsISPIterator( |
| SP_ROW_DATA inputData, SP_EXTRACT_FUNCPTR eFunc, |
| SP_ERROR_STRUCT* error, const NAArray<CmpContextInfo*> & ctxs, |
| CollHeap * h) |
| : ISPIterator(ctxs, h) |
| { |
| initializeISPCaches(inputData, eFunc, error, ctxs, |
| contextName_, currCacheIndex_); |
| } |
| |
| |
| NABoolean NARoutineCacheStatsISPIterator::getNext(NARoutineCacheStats & stats) |
| { |
| //Only for remote tdm_arkcmp with 0 context |
| if(currCacheIndex_ == -1) |
| { |
| ActiveSchemaDB()->getNARoutineDB()->getCacheStats(stats); |
| currCacheIndex_ = -2; |
| return TRUE; |
| } |
| |
| //fetch QueryCaches of all CmpContexts with name equal to contextName_ |
| if(currCacheIndex_ > -1 && currCacheIndex_ < ctxInfos_.entries()) |
| { |
| if( !ctxInfos_[currCacheIndex_]->isSameClass(contextName_.data()) //current context name is not equal to contextName_ |
| && contextName_.compareTo("ALL", NAString::exact)!=0) //and contextName_ is not "ALL" |
| {// go to next context in ctxInfos_ |
| currCacheIndex_++; |
| return getNext(stats); |
| } |
| ctxInfos_[currCacheIndex_++]->getCmpContext()->getSchemaDB()->getNARoutineDB()->getCacheStats(stats); |
| return TRUE; |
| } |
| //all entries of all caches are fetched, we are done! |
| return FALSE; |
| } |
| |
| |
| |
| |