关于ESQL中调用参数为INOUT REFERENCE类型过程会出错的有关问题浅析

关于ESQL中调用参数为INOUT REFERENCE类型过程会出错的问题浅析

对于如下声明的变量I和过程Test:

 

{DECLARE I INTEGER 1;

 

CREATE PROCEDURE Test(INOUT I REFERENCE)
 BEGIN


  SET I = I + 1;
  
  RETURN;
 END;

}

 

 

当调用CALL Test(I);时执行到RUTURN时会抛出异常,不光当I是INTEGER类型时会这样,我试过当I是ROW类型的时候也一样会抛异常,但是如果参数I为IN REFERENCE类型或INOUT INTEGER类型时调用Test不会出问题,或者I引用的是Environment的子树时也不会出问题。

异常栈信息如下:

 

ExceptionList
 RecoverableException
   File:CHARACTER:F:\build\S000_P\src\DataFlowEngine\ImbDataFlowNode.cpp
   Line:INTEGER:739
   Function:CHARACTER:ImbDataFlowNode::createExceptionList
   Type:CHARACTER:ComIbmMQInputNode
   Name:CHARACTER:mySchema/MyMsgFlow#FCMComposite_1_1
   Label:CHARACTER:mySchema.MyMsgFlow.QIn
   Catalog:CHARACTER:BIPv610
   Severity:INTEGER:3
   Number:INTEGER:2230
   Text:CHARACTER:Node throwing exception
   RecoverableException
     File:CHARACTER:F:\build\S000_P\src\DataFlowEngine\ImbComputeNode.cpp
     Line:INTEGER:464
     Function:CHARACTER:ImbComputeNode::evaluate
     Type:CHARACTER:ComIbmComputeNode
     Name:CHARACTER:mySchema/MyMsgFlow#FCMComposite_1_7
     Label:CHARACTER:mySchema.MyMsgFlow.8583ToSoap
     Catalog:CHARACTER:BIPv610
     Severity:INTEGER:3
     Number:INTEGER:2230
     Text:CHARACTER:Caught exception and rethrowing
     RecoverableException
       File:CHARACTER:F:\build\S000_P\src\DataFlowEngine\ImbRdl\ImbRdlStatementGroup.cpp
       Line:INTEGER:602
       Function:CHARACTER:SqlStatementGroup::execute
       Type:CHARACTER:ComIbmComputeNode
       Name:CHARACTER:mySchema/MyMsgFlow#FCMComposite_1_7
       Label:CHARACTER:mySchema.MyMsgFlow.8583ToSoap
       Catalog:CHARACTER:BIPv610
       Severity:INTEGER:3
       Number:INTEGER:2488
       Text:CHARACTER:Error detected, rethrowing
       Insert
         Type:INTEGER:5
         Text:CHARACTER:mySchema.MyMsgFlow_8583ToSoap.Main
       Insert
         Type:INTEGER:5
         Text:CHARACTER:6.3
       Insert
         Type:INTEGER:5
         Text:CHARACTER:Test(I);
       RecoverableException
         File:CHARACTER:F:\build\S000_P\src\DataFlowEngine\ImbRdl\ImbRdlRoutine.cpp
         Line:INTEGER:1466
         Function:CHARACTER:SqlRoutine::clearDownChildEnv
         Type:CHARACTER:ComIbmComputeNode
         Name:CHARACTER:mySchema/MyMsgFlow#FCMComposite_1_7
         Label:CHARACTER:mySchema.MyMsgFlow.8583ToSoap
         Catalog:CHARACTER:BIPv610
         Severity:INTEGER:3
         Number:INTEGER:2933
         Text:CHARACTER:
         Insert
           Type:INTEGER:5
           Text:CHARACTER:I

 

这个问题昨天发现的,今天才想明白是因为什么。可以注意到异常栈最后一层中有个SqlRoutine::clearDownChildEnv,从字面理解它是清理"child"环境,再想想过程Test的参数I是INOUT REFERENCE类型,说明I既是引用其它变量的,又需要传入和传出,关键是在这个引用和传出,引用可以很好理解,I和所引用的变量一样使用,对于传出,ESQL中定义OUT类型的变量是在RETURN时将变量返回,应该可以理解为C或JAVA中函数返回值时候的return I;若是这样,在返回之前,需要为返回值构建一个临时变量暂存,返回之后清理这个临时变量。若是一般的变量,它传入时是之传入,返回时清理它本身没有问题,而现在传入的参数是引用类型的,清理时就会出问题。这也就是为什么参数I为IN REFERENCE类型或INOUT INTEGER类型时调用Test不会出问题的原因。而对于I引用的是Environment子树时Call Test(I);也正常运行的原因也许是Environment树不会被清理的吧。