LmResult LmRoutineCppObj::invokeRoutineMethod(
     /* IN */     tmudr::UDRInvocationInfo::CallPhase phase,
     /* IN */     const char   *serializedInvocationInfo,
     /* IN */     Int32         invocationInfoLen,
     /* OUT */    Int32        *invocationInfoLenOut,
     /* IN */     const char   *serializedPlanInfo,
     /* IN */     Int32         planInfoLen,
     /* IN */     Int32         planNum,
     /* OUT */    Int32        *planInfoLenOut,
     /* IN */     char         *inputParamRow,
     /* IN */     Int32         inputParamRowLen,
     /* OUT */    char         *outputRow,
     /* IN */     Int32         outputRowLen,
     /* IN/OUT */ ComDiagsArea *da)
{
  LmResult result = LM_OK;

  // initialize out parameters
  *invocationInfoLenOut = 0;
  *planInfoLenOut = 0;

  // some parameter checks
  if (invocationInfoLen <= 0 &&
      invocationInfo_ == NULL)
    {
      // we need to have an Invocation info
      *da << DgSqlCode(-LME_OBJECT_INTERFACE_ERROR)
          << DgString0(getNameForDiags())
          << DgString1(tmudr::UDRInvocationInfo::callPhaseToString(
                            tmudr::UDRInvocationInfo::COMPILER_INITIAL_CALL))
          << DgString2("LmRoutineCppObj::invokeRoutineMethod()")
          << DgString3("Missing UDRInvocationInfo");
    }

  try
    {
      if (invocationInfoLen > 0)
        {
          if (invocationInfo_ == NULL)
            invocationInfo_ = new tmudr::UDRInvocationInfo;

          // unpack the invocation info
          invocationInfo_->deserializeObj(serializedInvocationInfo,
                                          invocationInfoLen);
        }

      if (planInfoLen > 0)
        {
          if (!planInfos_.used(planNum))
            planInfos_.insertAt(planNum, new tmudr::UDRPlanInfo(invocationInfo_,
                                                                planNum));

          // unpack the invocation info
          planInfos_[planNum]->deserializeObj(serializedPlanInfo,
                                              planInfoLen);
        }

      // some parameter checks
      if (inputParamRowLen < inputParamRowLen_)
        return LM_ERR;
      // test to do for scalar UDFs
      // if (outputRowLen < invocationInfo_->out().getRecordLength())
      //   return LM_ERR;

      if (inputParamRow && inputParamRowLen_ > 0)
        // copy parameter row
        memcpy(invocationInfo_->par().getRowPtr(), inputParamRow, inputParamRowLen_);

      invocationInfo_->callPhase_ = phase;
      switch (phase)
        {
        case tmudr::UDRInvocationInfo::COMPILER_INITIAL_CALL:
          if (invocationInfo_->getDebugFlags() &
              tmudr::UDRInvocationInfo::PRINT_INVOCATION_INFO_INITIAL)
            invocationInfo_->print();

          if (invocationInfo_->getDebugFlags() &
              tmudr::UDRInvocationInfo::DEBUG_INITIAL_COMPILE_TIME_LOOP)
            if (invocationInfo_->getSessionUser() == ComUser::getRootUserName())
              interfaceObj_->debugLoop();
            else if (da)
              *da << DgSqlCode(1260); // warning, only root user can debug

          interfaceObj_->describeParamsAndColumns(*invocationInfo_);
          break;

        case tmudr::UDRInvocationInfo::COMPILER_DATAFLOW_CALL:
          interfaceObj_->describeDataflowAndPredicates(*invocationInfo_);
          break;

        case tmudr::UDRInvocationInfo::COMPILER_CONSTRAINTS_CALL:
          interfaceObj_->describeConstraints(*invocationInfo_);
          break;

        case tmudr::UDRInvocationInfo::COMPILER_STATISTICS_CALL:
          interfaceObj_->describeStatistics(*invocationInfo_);
          break;

        case tmudr::UDRInvocationInfo::COMPILER_DOP_CALL:
          interfaceObj_->describeDesiredDegreeOfParallelism(
               *invocationInfo_,
               *planInfos_[planNum]);
          break;

        case tmudr::UDRInvocationInfo::COMPILER_PLAN_CALL:
          interfaceObj_->describePlanProperties(*invocationInfo_,
                                                *planInfos_[planNum]);
          break;

        case tmudr::UDRInvocationInfo::COMPILER_COMPLETION_CALL:
          interfaceObj_->completeDescription(*invocationInfo_,
                                             *planInfos_[planNum]);
          if (invocationInfo_->getDebugFlags() &
              tmudr::UDRInvocationInfo::PRINT_INVOCATION_INFO_END_COMPILE)
            {
              invocationInfo_->print();
              printf("\n");
              for (CollIndex i=0; i<planInfos_.getUsedLength(); i++)
                if (planInfos_.used(i))
                  {
                    if (i == planNum)
                      printf("++++++++++ Chosen plan: ++++++++++\n");
                    else
                      printf("-------- Plan not chosen: --------\n");
                    planInfos_[i]->print();
                  }
            }

          break;

        case tmudr::UDRInvocationInfo::RUNTIME_WORK_CALL:
          {
            if (invocationInfo_->getDebugFlags() &
                tmudr::UDRInvocationInfo::PRINT_INVOCATION_INFO_AT_RUN_TIME)
              {
                invocationInfo_->print();
                planInfos_[planNum]->print();
              }

            if ((invocationInfo_->getDebugFlags() &
                 tmudr::UDRInvocationInfo::DEBUG_INITIAL_RUN_TIME_LOOP_ALL) ||
                (invocationInfo_->getDebugFlags() &
                 tmudr::UDRInvocationInfo::DEBUG_INITIAL_RUN_TIME_LOOP_ONE &&
                 invocationInfo_->getMyInstanceNum() == 0))
              interfaceObj_->debugLoop();

            interfaceObj_->processData(*invocationInfo_,
                                       *planInfos_[planNum]);

            if (result == LM_OK)
              {
                if (invocationInfo_->getDebugFlags() & tmudr::UDRInvocationInfo::TRACE_ROWS)
                  printf("(%d) Emitting EOD\n",
                         invocationInfo_->getMyInstanceNum());

                // call emitRow to indicate EOD, something the
                // C interface would do inside the UDF
                SQLUDR_Q_STATE qstate = SQLUDR_Q_EOD;

                (*interfaceObj_->emitRowPtr_)(
                     invocationInfo_->out().getRowPtr(),
                     0,
                     &qstate);
              }
          }
          break;

        default:
          *da << DgSqlCode(-11111)
              << DgString0("Invalid call phase in LmRoutineCppObj::invokeRoutineMethod()");

          result = LM_ERR;
          break;
        
        }

      // return length of updated invocation and plan info for
      // compile-time phases
      if (invocationInfo_ &&
          phase < tmudr::UDRInvocationInfo::RUNTIME_WORK_CALL)
        {
          *invocationInfoLenOut = invocationInfo_->serializedLength();
          if (planInfos_.used(planNum))
            *planInfoLenOut = planInfos_[planNum]->serializedLength();
        }
    }
  catch (tmudr::UDRException e)
    {
      // Check the returned SQLSTATE value and raise appropriate
      // SQL code. Valid SQLSTATE values begin with "38" except "38000"
      const char *sqlState = e.getSQLState();

      if ((strncmp(sqlState, "38", 2) == 0) &&
          (strncmp(sqlState, "38000", 5) != 0))
        {
          *da << DgSqlCode(-LME_CUSTOM_ERROR)
              << DgString0(e.getMessage().c_str())
              << DgString1(sqlState);
          *da << DgCustomSQLState(sqlState);
        }
      else
        {
          *da << DgSqlCode(-LME_UDF_ERROR)
              << DgString0(invocationInfo_->getUDRName().c_str())
              << DgString1(sqlState)
              << DgString2(e.getMessage().c_str());
        }
      result = LM_ERR;
    }
  catch (...)
    {
      *da << DgSqlCode(-LME_OBJECT_INTERFACE_ERROR)
          << DgString0(getNameForDiags())
          << DgString1(invocationInfo_->callPhaseToString(phase))
          << DgString2("LmRoutineCppObj::invokeRoutineMethod()")
          << DgString3("general exception");
      result = LM_ERR;
    }

  invocationInfo_->callPhase_ =
    tmudr::UDRInvocationInfo::UNKNOWN_CALL_PHASE;

  return result;
}
LmResult LmRoutineCppObj::getRoutineInvocationInfo(
     /* IN/OUT */ char         *serializedInvocationInfo,
     /* IN */     Int32         invocationInfoMaxLen,
     /* OUT */    Int32        *invocationInfoLenOut,
     /* IN/OUT */ char         *serializedPlanInfo,
     /* IN */     Int32         planInfoMaxLen,
     /* IN */     Int32         planNum,
     /* OUT */    Int32        *planInfoLenOut,
     /* IN/OUT */ ComDiagsArea *da)
{
  LmResult result = LM_OK;

  // Retrieve updated invocation and plan info.
  // The invokeRoutineMethod provided the required buffer
  // space, so there is no excuse for having insufficient
  // buffer when calling this, and doing so will raise
  // an exception in the try block below.
  try
    {
      if (invocationInfo_ && invocationInfoMaxLen > 0)
        {
          char *tempiibuf = serializedInvocationInfo;
          int tempiilen   = invocationInfoMaxLen;
          *invocationInfoLenOut = invocationInfo_->serialize(
               tempiibuf, tempiilen);
        }
      else
        *invocationInfoLenOut = 0;

      if (planInfos_.used(planNum) && planInfoMaxLen > 0)
        {
          char *temppibuf = serializedPlanInfo;
          int temppilen   = planInfoMaxLen;
          *planInfoLenOut = planInfos_[planNum]->serialize(
               temppibuf, temppilen);
        }
      else
        *planInfoLenOut = 0;
    }
  catch (tmudr::UDRException e)
    {
      // this UDRException is generated by Trafodion code and
      // it is an internal error to fail serializing the structs,
      // even though the user might have caused it by corrupting
      // these structs
      *da << DgSqlCode(-LME_OBJECT_INTERFACE_ERROR)
          << DgString0(getNameForDiags())
          << DgString1(invocationInfo_->callPhaseToString(invocationInfo_->getCallPhase()))
          << DgString2("LmRoutineCppObj::getRoutineInvocationInfo()")
          << DgString3(e.getMessage().c_str());
      result = LM_ERR;
    }
  catch (...)
    {
      *da << DgSqlCode(-LME_OBJECT_INTERFACE_ERROR)
          << DgString0(getNameForDiags())
          << DgString1(invocationInfo_->callPhaseToString(invocationInfo_->getCallPhase()))
          << DgString2("LmRoutineCppObj::getRoutineInvocationInfo()")
          << DgString3("general exception");
      result = LM_ERR;
    }

  return result;
}
Example #3
0
static void CmpSPERROR2Diags(const SP_ERROR_STRUCT* spError, 
                             ComDiagsArea* diags)
{
  if ( !diags )
    return;

  if (spError[0].error == arkcmpErrorISPMergeCatDiags)
  {
    // Special error message to indicate that errors should really be
    // merged in from the catalog manager diags area.
    // not supported, raise unsupported error instead
    *diags << DgSqlCode(-4222)
           << DgString0("CmpSPERROR2Diags");
    return;
  }

  for ( Int32 i=0; i< SP_MAX_ERROR_STRUCTS; i++)
  {
    const SP_ERROR_STRUCT* pSET = &(spError[i]);
    if (pSET->error)
    {
      *diags << DgSqlCode(pSET->error);
      if(pSET->error == -20067) { //IDS_UTILITIES_BADSYNTAX = 20067
	// If utilities parser returned syntax error for syntax based 
	// utilities, error IDS_UTILITIES_BADSYNTAX is returned by 
	// utilities code to mxmcp.   
	// pSET->optionalString[1] has the utilities command from command line.
	// pSET->optionalInteger[0] has the approximate position of error in
	// the syntax of the utilities command given by user in command line.
	// The approximate error position is returned by utilities parser.

	// Function  StoreSyntaxError(.....) takes the information to put a 
	// caret (^) in the approximate position of the command and the 
	// information is saved in diags.
 
        StoreSyntaxError(pSET->optionalString[1],  // const char *      input_str
                         pSET->optionalInteger[0], // Int32             input_pos
                         *diags,                   // ComDiagsArea &    diagsArea
                         0,                        // Int32             dgStrNum
                         CharInfo::UTF8,           // CharInfo::CharSet input_str_cs
                         CharInfo::UTF8);          // CharInfo::CharSet terminal_cs
      }
      else{
      if ( pSET->optionalString[0] && 
           pSET->optionalString[0] != (char *) ComDiags_UnInitialized_Int )
        *diags << DgString0(pSET->optionalString[0]);
      if ( pSET->optionalString[1] &&
           pSET->optionalString[1] != (char *)ComDiags_UnInitialized_Int )
        *diags << DgString1(pSET->optionalString[1]);
      if ( pSET->optionalString[2] &&
           pSET->optionalString[2] != (char *)ComDiags_UnInitialized_Int )
        *diags << DgString2(pSET->optionalString[2]);
      if ( pSET->optionalString[3] &&
           pSET->optionalString[3] != (char *)ComDiags_UnInitialized_Int )
        *diags << DgString3(pSET->optionalString[3]);
      if ( pSET->optionalString[4] &&
           pSET->optionalString[4] != (char *)ComDiags_UnInitialized_Int )
        *diags << DgString4(pSET->optionalString[4]);
      if ( pSET->optionalInteger[0] != ComDiags_UnInitialized_Int )
        *diags << DgInt0(pSET->optionalInteger[0]);
      if ( pSET->optionalInteger[1] != ComDiags_UnInitialized_Int )
        *diags << DgInt1(pSET->optionalInteger[1]);
      if ( pSET->optionalInteger[2] != ComDiags_UnInitialized_Int )
        *diags << DgInt2(pSET->optionalInteger[2]);
      if ( pSET->optionalInteger[3] != ComDiags_UnInitialized_Int )
        *diags << DgInt3(pSET->optionalInteger[3]);
      if ( pSET->optionalInteger[4] != ComDiags_UnInitialized_Int )
        *diags << DgInt4(pSET->optionalInteger[4]);
      }
    }
    else if ( i==0 )
    {
      // this is the case that ISP implementation does not return any
      // SP_ERROR_STRUCT info back, but does return with error status.
      *diags << DgSqlCode(arkcmpErrorISPNoSPError);
      break;
    }
    else
      // no more SP_ERROR_STRUCT.
      break;
  }
}