对于如下声明的变量I和过程Test:
{DECLARE I INTEGER 1;
CREATE PROCEDURE Test(INOUT I REFERENCE)
} |
当调用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树不会被清理的吧。