//CmpStoredProc::Status CmpInternalSP::open(CmpISPDataObject& data) CmpStoredProc::ExecStatus CmpInternalSP::open(CmpISPDataObject& data) { CMPASSERT(state_ == NONE); procFuncs_ = procFuncsLookupTable_[procName()]; if (!procFuncsLookupTable_.ValidPFuncs(procFuncs_)) { *(cmpContext()->diags()) << DgSqlCode(arkcmpErrorISPNotFound) << DgString0(procName().data()); return FAIL; } initSP_ERROR_STRUCT(); SP_STATUS spStatus = (*(procFuncs_.procFunc_))( SP_PROC_OPEN, (SP_ROW_DATA)data.input(), CmpSPExtractFunc, (SP_ROW_DATA)data.output(), CmpSPFormatFunc, (SP_KEY_VALUE)data.key(), CmpSPKeyValueFunc, &procHandle_, procFuncs_.spHandle_, &spError_[0]); if (spStatus == SP_FAIL || spStatus == SP_SUCCESS_WARNING) { // Errors or warnings, go get them data.output()->MoveDiags(spError_, spStatus); if (spStatus == SP_FAIL) return FAIL; } state_ = PROCESS; return SUCCESS; }
CmpStatement::ReturnStatus CmpStatementISP::process (CmpMessageISPRequest& isp) { #pragma nowarn(262) // warning elimination ReturnStatus ret = CmpStatement_ERROR; #ifdef _DEBUG if (getenv("DEBUG_SP2")) DebugBreak(); #endif CmpCommon::context()->sqlSession()->setParentQid(isp.getParentQid()); // Instantiate a CmpInternalSP CmpInternalSP* storedProc = new(heap_) CmpInternalSP(isp.procName(), context_); CMPASSERT(storedProc); setStoredProc(storedProc); reply_ = new(outHeap_) CmpMessageReplyISP(outHeap_, isp.id(), 0, 0, outHeap_); // prepare the data for execution // Make sure the pointer that ispData owns won't be deleted until ispData is // out of scope. Because of the performance reason, the pointers are copied, // not the contents. // The procedure flow is : // .CmpContext contains CmpStatements // .one CmpStatementISP is created per CmpMessageISPRequest, there might be many CmpMessageGetNext to fetch more data, // but they all share the same CmpStatementISP. This CmpStatementISP will be deleted when the execution of ISP is finished. // .CmpStatementISP owns a CmpInternalSP, the interface to stored procedure execution. CmpInternalSP will be deleted in // CmpStatement::~CmpStatement // . CmpInternalSP owns a CmpISPDataObject which contains data passed from executor for ISP execution. this // CmpISPDataObject will only be deleted when CmpInternalSP is out of scope. // .CmpISPDataObject is constructed from the CmpMessageISPRequest, for better performance // the data pointers are copied instead of duplicating the data, so it should own the // data member and only delete them when CmpISPDataObject is out of scope. // storedProc_ owns this ispData, it should be deleted in storedProc is out of scope. CmpISPDataObject* ispData = new(heap_) CmpISPDataObject(&isp, storedProc, context_->heap(), context_); ISPReqId_ = isp.id(); // open ISP short inputStatus = 0; NABoolean bufferFull = FALSE; for (; !bufferFull && (inputStatus = ispData->input()->next() ) == 0; ) { if (storedProc->open(*ispData) == CmpStoredProc::SUCCESS) bufferFull = ISPFetchPut(storedProc, ispData); else { if ( ispData->output()->AddEOR() == 1 ) bufferFull = TRUE; } } CMPASSERT(inputStatus != -1); // fail for retrieving input data // prepare to send the data back to executor ISPPrepareReply(ispData, reply_, bufferFull); return CmpStatement_SUCCESS; }
CmpStoredProc::ExecStatus CmpInternalSP::close(CmpISPDataObject& data) { CMPASSERT(state_ == PROCESS); initSP_ERROR_STRUCT(); state_ = NONE; SP_STATUS spStatus = (*(procFuncs_.procFunc_))( SP_PROC_CLOSE, (SP_ROW_DATA)data.input(), CmpSPExtractFunc, (SP_ROW_DATA)data.output(), CmpSPFormatFunc, (SP_KEY_VALUE)data.key(), CmpSPKeyValueFunc, &procHandle_, procFuncs_.spHandle_, &spError_[0]); if (spStatus != SP_SUCCESS ) { data.output()->MoveDiags(spError_, spStatus); return FAIL; } return SUCCESS; }
CmpStoredProc::ExecStatus CmpInternalSP::fetch(CmpISPDataObject& data) { CMPASSERT(state_ == PROCESS); // Need to send controls explicitly from the compiler space to the // cli context so ISP requests can perform CLI operations to extract // their values. // For now, only send controls for MODIFY, POPULATE INDEX, TRANSFORM, // PURGEDATA, MV_refresh and VALIDATE sp requests. // This also means RECOVER since these operations // can be perfomed through a RECOVER operation. // // VO, Versioning Light: Also send controls for sp_SchLevel // (UPGRADE and DOWNGRADE) if (procName() == "sp_partn" || procName() == "sp_populate" || procName() == "sp_purgedata" || procName() == "sp_recover" || procName() == "sp_transform" || procName() == "sp_validate" || procName() == "sp_purgedata" || procName() == "sp_refresh" || procName() == "sp_SchLevel") { sendAllControls(FALSE, FALSE, TRUE); // set the parent qid for this session const char *parentQid = cmpContext()->sqlSession()->getParentQid(); if (parentQid != NULL) { setParentQidAtSession(cmpContext()->statementHeap(), parentQid); } } // Send sqlparser_flags if (Get_SqlParser_Flags(ALLOW_FUNNY_IDENTIFIER)) sendParserFlag(ALLOW_FUNNY_IDENTIFIER); initSP_ERROR_STRUCT(); SP_STATUS spStatus = (*(procFuncs_.procFunc_))( SP_PROC_FETCH, (SP_ROW_DATA)data.input(), CmpSPExtractFunc, (SP_ROW_DATA)data.output(), CmpSPFormatFunc, (SP_KEY_VALUE)data.key(), CmpSPKeyValueFunc, &procHandle_, procFuncs_.spHandle_, &spError_[0]); if (spStatus == SP_FAIL) { // Errors, go get them data.output()->MoveDiags(spError_, spStatus); if (CmpCommon::diags() != NULL) { data.output()->MergeDiags(CmpCommon::diags()); CmpCommon::diags()->clear(); } return FAIL; } if (CmpCommon::diags() != NULL) { data.output()->MergeDiags(CmpCommon::diags()); CmpCommon::diags()->clear(); } if ( spStatus == SP_MOREDATA) { return MOREDATA; } return SUCCESS; }