LmResult LmRoutineCppObj::dealloc(ComDiagsArea *diagsArea) { LmResult result = LM_OK; delete invocationInfo_; invocationInfo_ = NULL; for (CollIndex i=0; i<planInfos_.getUsedLength(); i++) if (planInfos_.used(i)) delete planInfos_[i]; planInfos_.clear(); if (paramRow_) { NADELETEBASIC(paramRow_, collHeap()); paramRow_ = NULL; } if (inputRows_) { for (int i=0; i<numInputTables_; i++) if (inputRows_[i]) NADELETEBASIC((inputRows_[i]), collHeap()); NADELETEBASIC(inputRows_, collHeap()); inputRows_ = NULL; } if (outputRow_) { // actually allocated buffer started where the wall starts NADELETEBASIC((outputRow_ - WALL_STRING_LEN), collHeap()); outputRow_ = NULL; } try { // delete the interface object, the virtual destructor may call user code delete interfaceObj_; } catch (tmudr::UDRException e) { *diagsArea << DgSqlCode(-LME_UDR_METHOD_ERROR) << DgString0("destructor") << DgString1(getNameForDiags()) << DgString2(e.getMessage().c_str()); result = LM_ERR; } catch (...) { *diagsArea << DgSqlCode(-LME_UDR_METHOD_ERROR) << DgString0("destructor") << DgString1(getNameForDiags()) << DgString2("General exception."); result = LM_ERR; } interfaceObj_ = NULL; return result; }
////////////////////////////////////////////////////////////////////// // // Class LmRoutineCppObj // If we get errors in creating this object, fill diagsArea and return // error. Caller is responsbile to cleanup by calling destructor. // ////////////////////////////////////////////////////////////////////// LmRoutineCppObj::LmRoutineCppObj( tmudr::UDRInvocationInfo *invocationInfo, tmudr::UDRPlanInfo *planInfo, tmudr::UDR *interfaceObj, const char *sqlName, const char *externalName, const char *librarySqlName, ComUInt32 maxResultSets, ComRoutineTransactionAttributes transactionAttrs, ComRoutineSQLAccess sqlAccessMode, ComRoutineExternalSecurity externalSecurity, Int32 routineOwnerId, LmLanguageManagerC *lm, LmContainer *container, ComDiagsArea *diags) : LmRoutine(container, (LmHandle) interfaceObj, sqlName, externalName, librarySqlName, 0, maxResultSets, COM_LANGUAGE_CPP, COM_STYLE_CPP_OBJ, transactionAttrs, sqlAccessMode, externalSecurity, routineOwnerId, invocationInfo->getQueryId().c_str(), invocationInfo->par().getRecordLength(), invocationInfo->out().getRecordLength(), invocationInfo->getCurrentUser().c_str(), invocationInfo->getSessionUser().c_str(), NULL, lm), planInfos_(collHeap()), invocationInfo_(invocationInfo), interfaceObj_(interfaceObj), paramRow_(NULL), inputRows_(NULL), outputRow_(NULL) { if (planInfo) planInfos_.insertAt(0, planInfo); interfaceObj_->getNextRowPtr_ = NULL; // set these with setFunctionPtrs() interfaceObj_->emitRowPtr_ = NULL; numInputTables_ = invocationInfo->getNumTableInputs(); if (inputParamRowLen_ > 0) { paramRow_ = new(collHeap()) char[inputParamRowLen_]; memset(paramRow_,0,inputParamRowLen_); const_cast<tmudr::ParameterListInfo &>(invocationInfo->par()).setRowPtr(paramRow_); } // inputRows_ and outputRow_ will be allocated in setRuntimeInfo() }
LmResult LmRoutineCppObj::setRuntimeInfo( const char *parentQid, int totalNumInstances, int myInstanceNum, ComDiagsArea *da) { invocationInfo_->setQueryId(parentQid); invocationInfo_->setTotalNumInstances(totalNumInstances); invocationInfo_->setMyInstanceNum(myInstanceNum); // allocate row buffers if (numInputTables_ > 0) { inputRows_ = new (collHeap()) char *[numInputTables_]; for (int i=0; i<numInputTables_; i++) { int inputRowLength = invocationInfo_->in(i).recordLength_; if (inputRowLength > 0) { inputRows_[i] = new(collHeap()) char[inputRowLength]; memset(inputRows_[i], 0, inputRowLength); const_cast<tmudr::TableInfo &>( invocationInfo_->in(i)).setRowPtr(inputRows_[i]); } else // at compile time, input rows are not specified inputRows_[i] = NULL; } } else { inputRows_ = NULL; } if (outputRowLen_ > 0) { outputRow_ = new (collHeap()) char[outputRowLen_ + 2*WALL_STRING_LEN]; // remember the pointer to the actually usable // buffer, not where the wall starts outputRow_ += WALL_STRING_LEN; memset(outputRow_, 0, outputRowLen_); setUpWall(outputRow_, outputRowLen_); invocationInfo_->out().setRowPtr(outputRow_); } else outputRow_ = NULL; return LM_OK; }
LmRoutineJava::~LmRoutineJava() { JNIEnv *jni = (JNIEnv*)getLM()->jniEnv_; jvalue *jval = (jvalue*)javaParams_; // Free LmResultSet objects // This will also close the Java result set objects // and the Java connections that they are part of. cleanupResultSets(); // Free LmConnection objects for default connections // Closes any open default connections that do not have // result sets associated with them closeDefConnWithNoRS(); connectionList_.clear(); // Release array refs for params, indicated // by non-null object. for (Int32 i = 0; i < (Int32)numParamsInSig_; i++) { if (jval[i].l != NULL) jni->DeleteLocalRef(jval[i].l); } // Free the Java parameter array if (javaParams_) NADELETEBASIC((jvalue *)javaParams_, collHeap()); }
LmHandle LmLanguageManagerC::loadContainer( const char *containerName, const char *externalPath, LmHandle extLoader, ComUInt32 *containerSize, ComDiagsArea *da) { return loadDll(containerName, externalPath, extLoader, containerSize, da, collHeap()); }
// This method creates a LmResultSetJava object for the // passed in java.sql.ResultSet object (newRS) and inserts // it into resultSetList_. // // Parameters: // newRS - A java.sql.ResultSet object // paramPos - The position (1-based) of newRS // in the Java method signature. // da - ComDiagsArea object to report any errors. // This object should not be NULL. LmResult LmRoutineJava::populateResultSetInfo(LmHandle newRS, Int32 paramPos, ComDiagsArea *da) { LmResult result = LM_OK; jobject newRSRef = (jobject)newRS; LM_ASSERT(da != NULL); // SPJ method can return same java.sql.ResultSet object in // multiple OUT params but we ignore such duplicates. // We also ignore a NULL java.sql.ResultSet object. if( newRSRef == NULL || isDuplicateRS( newRSRef )) return result; LmResultSetJava::LmResultSetInfoStatus rsInfoStatus; LmResultSetJava *newLmRS = new (collHeap()) LmResultSetJava( getLM(), (LmHandle)newRSRef, paramPos, getNameForDiags(), rsInfoStatus, connectionList_, da ); // If the constructor returned a success status then insert // the newLmRS object into resultSetList_ otherwise delete it. if( rsInfoStatus == LmResultSetJava::RS_INFO_OK ) { // Order the objects inserted in the resultSetList_ based on // the order in which the result set cursors were opened. ComUInt32 i; LmResultSetJava *lmRS; for( i = 0; i < resultSetList_.entries(); i++ ) { lmRS = (LmResultSetJava *)resultSetList_[i]; if( newLmRS->rsCounter_ < lmRS->rsCounter_ ) break; } resultSetList_.insertAt( i, newLmRS ); } else { delete newLmRS; newLmRS = NULL; // Ignore closed result sets if( rsInfoStatus == LmResultSetJava::RS_INFO_CLOSED ) result = LM_OK; else result = LM_ERR; } return result; }
LmLanguageManagerC::LmLanguageManagerC( LmResult &result, NABoolean commandLineMode, ComDiagsArea *diagsArea) : LmLanguageManager(commandLineMode), diagsArea_(diagsArea) { setRoutineIsActive(FALSE); contManager_ = new (collHeap()) LmContainerManagerSimple(this); result = LM_OK; }
UniqueConstraint::~UniqueConstraint() { NAHeap *heap = (NAHeap *)collHeap(); CollIndex entryCount = refConstraintsReferencingMe_.entries(); if (heap != NULL) { for (CollIndex i = 0 ; i < entryCount; i++) { NADELETE(refConstraintsReferencingMe_[i], ComplementaryRIConstraint, heap); } } else { for (CollIndex i = 0 ; i < entryCount; i++) delete refConstraintsReferencingMe_[i]; } refConstraintsReferencingMe_.clear(); }
AbstractRIConstraint::~AbstractRIConstraint() { NAHeap *heap = (NAHeap *)collHeap(); CollIndex entryCount = keyColumns_.entries(); if (heap != NULL) { for (CollIndex i = 0 ; i < entryCount; i++) { NADELETE(keyColumns_[i], NAColumn, heap); } } else { for (CollIndex i = 0 ; i < entryCount; i++) delete keyColumns_[i]; } keyColumns_.clear(); }
LmRoutineCSql::LmRoutineCSql(const char *sqlName, const char *externalName, const char *librarySqlName, ComUInt32 numSqlParam, char *routineSig, ComUInt32 maxResultSets, ComRoutineTransactionAttributes transactionAttrs, ComRoutineSQLAccess sqlAccessMode, ComRoutineExternalSecurity externalSecurity, Int32 routineOwnerId, const char *parentQid, ComUInt32 inputRowLen, ComUInt32 outputRowLen, const char *currentUserName, const char *sessionUserName, LmParameter *parameters, LmLanguageManagerC *lm, LmHandle routine, LmContainer *container, ComDiagsArea *diagsArea) : LmRoutineC(sqlName, externalName, librarySqlName, numSqlParam, routineSig, maxResultSets, COM_LANGUAGE_C, COM_STYLE_SQL, transactionAttrs, sqlAccessMode, externalSecurity, routineOwnerId, parentQid, inputRowLen, outputRowLen, currentUserName, sessionUserName, parameters, lm, routine, container, diagsArea), cBuf_(NULL), data_(NULL), ind_(numSqlParam * sizeof(short)) { ComUInt32 i = 0; data_ = (char **) collHeap()->allocateMemory(numSqlParam * sizeof(char *)); // Allocate C data buffers. Each LmCBuffer instance points to a C // buffer and the data_ buffer is an array of pointers to the C data // buffers. The LmCBuffer is mainly used to track the actual size of // the C buffers because each buffer has some extra bytes at the end // to protect against buffer overwrites. // // cBuf_ -> LmCBuffer LmCBuffer LmCBuffer ... // | | | // v v v // buffer buffer buffer ... // ^ ^ ^ // | | | // data_[0] data_[1] data_[2] ... // // NOTE: the cBuf_ array is allocated on the C++ heap because we // want to manage the collection as a single array, and we want // constructors and destructors to be called when the collection is // created and destroyed. Right now, NAMemory and NABasic object // interfaces do not provide the appropriate array versions of new // and delete operators to accomplish these things. cBuf_ = new LmCBuffer[numSqlParam_]; LM_ASSERT(cBuf_); for (i = 0; i < numSqlParam_; i++) { LmParameter &p = lmParams_[i]; LmCBuffer &cBuf = cBuf_[i]; ComUInt32 dataBytes = 0; switch (p.direction()) { // NOTE: The code currently supports IN and OUT parameters for C // routines. There is no reason we couldn't support INOUT as // well, which will be needed if we ever provide stored // procedures written in C. But the INOUT code paths have not // been implemented yet. case COM_INPUT_COLUMN: dataBytes = p.inSize(); break; case COM_OUTPUT_COLUMN: dataBytes = p.outSize(); break; default: LM_ASSERT(0); break; } switch (p.fsType()) { case COM_VCHAR_FSDT: case COM_VCHAR_DBL_FSDT: { // VARCHAR(N) CHARACTER SET ISO88591 // VARCHAR(N) CHARACTER SET UCS2 // This is a VARCHAR parameter. Allocate one buffer that will // hold the VC struct and the data. Data will begin at the first // 8-byte boundary following the VC struct. ComUInt32 vcBytes = ROUND8(sizeof(SQLUDR_VC_STRUCT)) + dataBytes; cBuf.init(vcBytes); data_[i] = cBuf.getBuffer(); // Initialize the VC struct SQLUDR_VC_STRUCT *vc = (SQLUDR_VC_STRUCT *) cBuf.getBuffer(); char *charPtr = (char *) vc; vc->data = charPtr + ROUND8(sizeof(SQLUDR_VC_STRUCT)); vc->length = dataBytes; } break; case COM_FCHAR_FSDT: case COM_FCHAR_DBL_FSDT: case COM_SIGNED_DECIMAL_FSDT: case COM_UNSIGNED_DECIMAL_FSDT: case COM_DATETIME_FSDT: case COM_SIGNED_NUM_BIG_FSDT: case COM_UNSIGNED_NUM_BIG_FSDT: { // CHAR(N) CHARACTER SET ISO88591 // CHAR(N) CHARACTER SET UCS2 // DECIMAL [UNSIGNED] // DATE, TIME, TIMESTAMP // NUMERIC precision > 18 // These types require a null-terminated C string. Add one to // dataBytes to account for the null terminator. cBuf.init(dataBytes + 1); data_[i] = cBuf.getBuffer(); } break; default: { // All other types cBuf.init(dataBytes); data_[i] = cBuf.getBuffer(); } break; } // switch (p.fsType()) } // for each param } // LmRoutineCSql::LmRoutineCSql
////////////////////////////////////////////////////////////////////// // // Class LmRoutineJava // If we get errors in creating this object, fill diagsArea and return // error. Caller is responsbile to cleanup by calling destructor. // ////////////////////////////////////////////////////////////////////// LmRoutineJava::LmRoutineJava( const char *sqlName, const char *externalName, const char *librarySqlName, ComUInt32 numSqlParam, LmParameter *returnValue, ComUInt32 maxResultSets, char *routineSig, ComRoutineParamStyle paramStyle, ComRoutineTransactionAttributes transactionAttrs, ComRoutineSQLAccess sqlAccessMode, ComRoutineExternalSecurity externalSecurity, Int32 routineOwnerId, const char *parentQid, ComUInt32 inputRowLen, ComUInt32 outputRowLen, const char *currentUserName, const char *sessionUserName, LmParameter *parameters, LmLanguageManagerJava *lm, LmHandle routine, LmContainer *container, ComDiagsArea *da) : LmRoutine(container, routine, sqlName, externalName, librarySqlName, numSqlParam, maxResultSets, COM_LANGUAGE_JAVA, paramStyle, transactionAttrs, sqlAccessMode, externalSecurity, routineOwnerId, parentQid, inputRowLen, outputRowLen, currentUserName, sessionUserName, parameters, lm), javaParams_(NULL), retType_(LmJavaType::JT_NONE), defaultCatSch_(FALSE), connectionList_(collHeap()) { JNIEnv *jni = (JNIEnv*)getLM()->jniEnv_; setUdrForJavaMain((str_cmp_ne(externalName, "main") == 0) ? TRUE : FALSE); // this is the internal SPJ used in CREATE PROCEDURE // mark it for examining Java exceptions to determine SQL diagnostics later if ((str_cmp_ne(container->getName(), "org.trafodion.sql.udr.LmUtility") == 0) && (str_cmp_ne(externalName, "validateMethod") == 0)) setIsInternalSPJ(TRUE); else setIsInternalSPJ(FALSE); if (paramStyle == COM_STYLE_JAVA_OBJ) return; // Get method return type. retType_ = LmJavaType(returnValue).getType(); // // Now setup the parameters to the method. // // UDR-MAIN gets special treatment // // Allocate only one jvalue because main() takes only // one parameter of type String[]. // // Then create java.lang.String array of size numSqlParam_ // which equals to numSqlParam // if (isUdrForJavaMain()) { numParamsInSig_ = 1; // Number of parameters in Java main method javaParams_ = new (collHeap()) jvalue[1]; memset((char*)javaParams_, 0, sizeof(jvalue)); ((jvalue *)javaParams_)->l = jni->NewObjectArray((jsize)numSqlParam_, (jclass)lm->stringClass_, NULL); if (((jvalue *)javaParams_)->l == NULL) { *da << DgSqlCode(-LME_JVM_OUT_OF_MEMORY); getLM()->exceptionReporter_->checkJVMException(da, 0); } return; } // For a Java main method we would have already returned and // do not get this far. Logic in the rest of this method does // not need to consider main methods as a special case. // Get the total number of parameters present in the method // signature. LmJavaSignature lmSig(routineSig, collHeap()); Int32 result = lmSig.getParamCount(); if( result < (Int32)numSqlParam_ ) { *da << DgSqlCode(-LME_INTERNAL_ERROR) << DgString0(": LmJavaSignature::getParamCount() returned an invalid value."); return; } numParamsInSig_ = (ComUInt32)result; // // Setup Paramters for Non-main methods // // Allocate Java method parameter array for SQL // and result set params if (numParamsInSig_ > 0) { javaParams_ = new (collHeap()) jvalue[numParamsInSig_]; memset((char*)javaParams_, 0, numParamsInSig_ * sizeof(jvalue)); } // Allocate a 1-element array for each OUT/INOUT mode parameter. jvalue *jval = (jvalue*)javaParams_; Int32 i = 0; for (i = 0; i < (Int32)numSqlParam_; i++) { LmParameter &p = lmParams_[i]; if (p.direction() == COM_INPUT_COLUMN) continue; jobjectArray ja = NULL; switch (LmJavaType(&p).getType()) { case LmJavaType::JT_SHORT: jval[i].l = (jobject)jni->NewShortArray(1); break; case LmJavaType::JT_INT: jval[i].l = (jobject)jni->NewIntArray(1); break; case LmJavaType::JT_LONG: jval[i].l = (jobject)jni->NewLongArray(1); break; case LmJavaType::JT_FLOAT: jval[i].l = (jobject)jni->NewFloatArray(1); break; case LmJavaType::JT_DOUBLE: jval[i].l = (jobject)jni->NewDoubleArray(1); break; case LmJavaType::JT_LANG_STRING: ja = (jobjectArray) jni->NewObjectArray(1, (jclass)lm->stringClass_, NULL); break; case LmJavaType::JT_MATH_BIGDEC: ja = (jobjectArray) jni->NewObjectArray(1, (jclass)lm->bigdecClass_, NULL); break; case LmJavaType::JT_SQL_DATE: ja = (jobjectArray) jni->NewObjectArray(1, (jclass)lm->dateClass_, NULL); break; case LmJavaType::JT_SQL_TIME: ja = (jobjectArray) jni->NewObjectArray(1, (jclass)lm->timeClass_, NULL); break; case LmJavaType::JT_SQL_TIMESTAMP: ja = (jobjectArray) jni->NewObjectArray(1, (jclass)lm->stampClass_, NULL); break; case LmJavaType::JT_LANG_INTEGER: ja = (jobjectArray) jni->NewObjectArray(1, (jclass)lm->intClass_, NULL); break; case LmJavaType::JT_LANG_LONG: ja = (jobjectArray) jni->NewObjectArray(1, (jclass)lm->longClass_, NULL); break; case LmJavaType::JT_LANG_FLOAT: ja = (jobjectArray) jni->NewObjectArray(1, (jclass)lm->floatClass_, NULL); break; case LmJavaType::JT_LANG_DOUBLE: ja = (jobjectArray) jni->NewObjectArray(1, (jclass)lm->doubleClass_, NULL); break; default: char str[LMJ_ERR_SIZE_256]; sprintf (str, ": Unknown parameter type at parameter position %d.", i+1); *da << DgSqlCode(-LME_INTERNAL_ERROR) << DgString0(str); return; }// switch() if (ja != NULL) jval[i].l = ja; if (jval[i].l == NULL) { // OutOfMemory is the only error that could happen here. *da << DgSqlCode(-LME_JVM_OUT_OF_MEMORY); getLM()->exceptionReporter_->checkJVMException(da, 0); return; } } // for() // Allocate a 1-element array for each result set parameter. for (i = (Int32)numSqlParam_; i < (Int32)numParamsInSig_; i++) { jobjectArray ja = NULL; ja = jni->NewObjectArray(1, (jclass)lm->resultSetClass_, NULL); if (ja != NULL) jval[i].l = ja; if (jval[i].l == NULL) { // OutOfMemory is the only error that could happen here. *da << DgSqlCode(-LME_JVM_OUT_OF_MEMORY); getLM()->exceptionReporter_->checkJVMException(da, 0); return; } } return; }
LmResult LmRoutineJava::invokeRoutine(void *inputRow, void *outputRow, ComDiagsArea *da) { // Delete the LmResultSet objects for re-invocations // This will also close the Java result set objects // and the Java connections that they are part of cleanupResultSets(da); // This will close any default connections that do not have // result sets associated with them closeDefConnWithNoRS(da); // Cleanup the list maintained in LmUtlity.cpp file that will get // populated with default connection objects that may get created // during this routine's invocation. lmUtilityInitConnList((JNIEnv*)getLM()->jniEnv_, (jmethodID)getLM()->connCloseId_); // Set the default catalog & schema as system properties. These // values are then retrieved by LmSQLMXDriver class for setting // it on a getConnection() call if (getDefaultCatSchFlag()) { // Determine the catalog & schema values that will be in effect for // this UDR. If the values are set globally(with catalog/schema // props in CQD) they are used else the catalog/schema of // the UDR are used. const char *catalog = (getLM()->sysCatalog_) ? getLM()->sysCatalog_ : udrCatalog_; const char *schema = (getLM()->sysSchema_) ? getLM()->sysSchema_ : udrSchema_; if (getLM()->setSystemProperty("sqlmx.udr.catalog", catalog, da) == LM_ERR) return LM_ERR; if (getLM()->setSystemProperty("sqlmx.udr.schema", schema, da) == LM_ERR) return LM_ERR; } const char *parentQid; if ((parentQid = getParentQid()) == NULL) parentQid = "NONE"; if (getLM()->setSystemProperty("sqlmx.udr.parentQid", parentQid, da) == LM_ERR) return LM_ERR; // Set SQL access mode in LmUtility. This will be checked while SPJ // is trying to make a JDBC connection. lmUtilitySetSqlAccessMode(getSqlAccessMode()); // Set Transaction Attribute in LmUtility. This will be checked while SPJ // is trying to join a transaction. lmUtilitySetTransactionAttrs(getTransactionAttrs()); LmResult result = LM_OK; // Set the Definer Authentication Token as system property for // Definer Rights SPJs. This value is then retrieved by LmSQLMXDriver class // for setting the password property in getConnection() call. if ( externalSecurity_ == COM_ROUTINE_EXTERNAL_SECURITY_DEFINER ) { char *defAuthToken = new (collHeap()) char[DR_SPJ_TOKEN_LEN + 1]; result = generateDefAuthToken(defAuthToken, da); if (result != LM_ERR) result = getLM()->setSystemProperty("sqlmx.udr.defAuthToken", defAuthToken, da); NADELETEBASIC(defAuthToken, collHeap()); if (result == LM_ERR) { char errStr[LMJ_ERR_SIZE_256]; sprintf (errStr, ": Error returned from setting System Property: %s.", "sqlmx.udr.defAuthToken"); *da << DgSqlCode(-LME_INTERNAL_ERROR) << DgString0(errStr); return LM_ERR; } } lm_->setRoutineIsActive(TRUE); switch (retType_) { case LmJavaType::JT_VOID: result = voidRoutine(outputRow, NULL); break; default: // Other return types are not supported. In the future if we // support routines with non-void return types we will need to // add case blocks to this switch statement. LM_ASSERT(0); break; } lm_->setRoutineIsActive(FALSE); // Reset the sqlmx.udr.defAuthToken system property for // Definer Rights SPJs. if ( externalSecurity_ == COM_ROUTINE_EXTERNAL_SECURITY_DEFINER ) { result = getLM()->clearSystemProperty("sqlmx.udr.defAuthToken", da); if (result == LM_ERR) { char errStr[LMJ_ERR_SIZE_256]; sprintf (errStr, ": Error returned from Resetting System Property: %s.", "sqlmx.udr.defAuthToken"); *da << DgSqlCode(-LME_INTERNAL_ERROR) << DgString0(errStr); return LM_ERR; } } // Get the list containing the default connection objects // from LmUtility.cpp and create a LmConnection object for // each item in that list. NAList<jobject> &connList = lmUtilityGetConnList(); while(connList.entries()) { jobject conn = connList[0]; LmConnection *lmConn = new (collHeap()) LmConnection(getLM(), conn, LmConnection::DEFAULT_CONN, getTransactionAttrs()); connectionList_.insert( lmConn ); connList.removeAt(0); } // reset SQL Access mode to COM_UNKNOWN_ROUTINE_SQL_ACCESS lmUtilitySetSqlAccessMode(COM_UNKNOWN_ROUTINE_SQL_ACCESS); // reset Transaction Attributes to COM_UNKNOWN_ROUTINE_TRANSACTION_ATTRIBUTE lmUtilitySetTransactionAttrs(COM_UNKNOWN_ROUTINE_TRANSACTION_ATTRIBUTE); return result; }
LmResult LmLanguageManagerC::getRoutine( ComUInt32 numSqlParam, LmParameter parameters[], ComUInt32 numTableInfo, LmTableInfo tableInfo[], LmParameter *returnValue, ComRoutineParamStyle paramStyle, ComRoutineTransactionAttributes transactionAttrs, ComRoutineSQLAccess sqlAccessMode, const char *parentQid, ComUInt32 inputRowLen, ComUInt32 outputRowLen, const char *sqlName, const char *externalName, const char *routineSig, const char *containerName, const char *externalPath, const char *librarySqlName, const char *currentUserName, const char *sessionUserName, ComRoutineExternalSecurity externalSecurity, Int32 routineOwnerId, LmRoutine **handle, LmHandle getNextRowPtr, LmHandle emitRowPtr, ComUInt32 maxResultSets, ComDiagsArea *diagsArea) { *handle = NULL; LmContainer *container = NULL; LmResult result = LM_OK; ComDiagsArea *da = (diagsArea != NULL) ? diagsArea : diagsArea_; // Get the requested container from the CM. result = contManager_->getContainer(containerName, externalPath, &container, da); if (result == LM_ERR) return LM_ERR; // Get a handle to the requested routine LmHandle routinePtr = NULL; routinePtr = getRoutinePtr(container->getHandle(), externalName); const char *operation = "dlsym"; if (routinePtr == NULL) { char *libraryName = new (collHeap()) char[str_len(externalPath) + str_len(containerName) + 2]; sprintf(libraryName, "%s/%s", externalPath, containerName); *da << DgSqlCode(-LME_DLL_METHOD_NOT_FOUND) << DgString0(externalName) << DgString1(libraryName); addDllErrors(*da, operation, FALSE); NADELETEBASIC(libraryName, collHeap()); return LM_ERR; } // allocate an LM handle for the external method. LmRoutine *routineHandle = NULL; if (paramStyle == COM_STYLE_SQL) { routineHandle = new (collHeap()) LmRoutineCSql(sqlName, externalName, librarySqlName, numSqlParam, (char *)routineSig, maxResultSets, transactionAttrs, sqlAccessMode, externalSecurity, routineOwnerId, parentQid, inputRowLen, outputRowLen, currentUserName, sessionUserName, parameters, this, routinePtr, container, da); } else if (paramStyle == COM_STYLE_SQLROW) { routineHandle = new (collHeap()) LmRoutineCSqlRow(sqlName, externalName, librarySqlName, numSqlParam, (char *)routineSig, maxResultSets, transactionAttrs, sqlAccessMode, externalSecurity, routineOwnerId, parentQid, inputRowLen, outputRowLen, currentUserName, sessionUserName, parameters, this, routinePtr, container, da); } else if (paramStyle == COM_STYLE_TM) { routineHandle = new (collHeap()) LmRoutineCSqlRowTM(sqlName, externalName, librarySqlName, numSqlParam, numTableInfo, tableInfo, (char *)routineSig, maxResultSets, transactionAttrs, sqlAccessMode, externalSecurity, routineOwnerId, parentQid, inputRowLen, outputRowLen, currentUserName, sessionUserName, parameters, this, routinePtr, getNextRowPtr, emitRowPtr, container, da); } else { // XXX LM_ASSERT(0); char *paramStyleMsg = new (collHeap()) char[100]; sprintf(paramStyleMsg, "Unknown ParameterStyle(%d)", paramStyle); *da << DgSqlCode(-LME_VALIDATION_FAILED) << DgString0(externalName) << DgString1(paramStyleMsg); addDllErrors(*da, operation, FALSE); } // Verify the handle. if (routineHandle == NULL) { // DiagsArea is already filled if (container) contManager_->putContainer(container); return LM_ERR; } else { *handle = routineHandle; return LM_OK; } }
LmHandle LmLanguageManagerC::createLoader( const char *externalPath, ComDiagsArea *da) { return new (collHeap()) LmCLoader(); }