Db2 这是SQL GET诊断的正确行为吗?

Db2 这是SQL GET诊断的正确行为吗?,db2,ibm-midrange,db2-400,rpgle,Db2,Ibm Midrange,Db2 400,Rpgle,SQL语句GET DIAGNOSTICS的for表示可以请求将诊断数据放入特定变量中,并列出相关变量名称和类型。文章和演示了如何在RPG程序的上下文中使用此SQL语句 看起来我从DB2得到的一些结果与文档和文章中所说的不匹配。我使用的是IBMi,版本7.3 我正在查看从SQL用户定义表函数(UDTF)返回的诊断数据。如果使用“ALL”子句,则可以得到包含所有值的字符串: COMMAND_FUNCTION=FETCH; COMMAND_FUNCTION_CODE=+45; DB2_NUMBER_C

SQL语句
GET DIAGNOSTICS
的for表示可以请求将诊断数据放入特定变量中,并列出相关变量名称和类型。文章和演示了如何在RPG程序的上下文中使用此SQL语句

看起来我从DB2得到的一些结果与文档和文章中所说的不匹配。我使用的是IBMi,版本7.3

我正在查看从SQL用户定义表函数(UDTF)返回的诊断数据。如果使用“ALL”子句,则可以得到包含所有值的字符串:

COMMAND_FUNCTION=FETCH;
COMMAND_FUNCTION_CODE=+45;
DB2_NUMBER_CONNECTIONS=+1;
MORE=N;
NUMBER=+1;
CONDITION_NUMBER=+1;
DB2_MESSAGE_ID=SQL0443;
DB2_MESSAGE_ID1=CPF503E;
DB2_MODULE_DETECTING_ERROR=QSQFETCH;
DB2_ORDINAL_TOKEN_1=*N.*N;
DB2_ORDINAL_TOKEN_2=DUMMYUDTF;
DB2_ORDINAL_TOKEN_3=*******.DUMMYUDTF;
DB2_ORDINAL_TOKEN_4=Parameter '2' cannot be null.;
DB2_RETURNED_SQLCODE=-443;
DB2_TOKEN_COUNT=+4;
DB2_TOKEN_STRING=*N.*NDUMMYUDTFDUMMYUDTFParameter '2' cannot be null.;
MESSAGE_LENGTH=Parameter '2' cannot be null.;
MESSAGE_OCTET_LENGTH=Parameter '2' cannot be null.;
MESSAGE_TEXT=Parameter '2' cannot be null.;
RETURNED_SQLSTATE=90002;
ROUTINE_NAME=DUMMYUDTF;
ROUTINE_SCHEMA=QGPL;
SERVER_NAME=******;
SPECIFIC_NAME=DUMMYUDTF;
DB2_SQLERRD_SET=Y;
DB2_SQLERRD1=-168758331;
CONNECTION_NAME=******;
DB2_AUTHORIZATION_ID=********;
DB2_CONNECTION_METHOD=D;
DB2_CONNECTION_NUMBER=+1;
DB2_CONNECTION_STATE=+1;
DB2_CONNECTION_TYPE=+1;
DB2_PRODUCT_ID=QSQ07030;
DB2_SERVER_CLASS_NAME=DB2 for i;
DB2_SERVER_NAME=******;
文档规定字段
消息长度
消息八位字节长度
应为整数。正如你所看到的,他们都是瓦查尔人。如果我编写的代码将这些变量定义为整数,则会得到转义消息:
标量操作数没有指令所需的属性。
在作业日志和两个诊断中,严重程度为50
SQL系统错误。
以及SQL服务转储
qsvcdmp
。另一个反常现象是变量
DB2_MESSAGE_ID2
看起来不像是实现的,它会使程序在SQL分配它的行上崩溃

相反,如果我在内置函数上使用
GET DIAGNOSTICS
,则数据类型都与文档中所述相符,并且所有变量似乎都可用:

COMMAND_FUNCTION=SELECT;
COMMAND_FUNCTION_CODE=+65;
DB2_NUMBER_CONNECTIONS=+1;
MORE=N;
NUMBER=+1;
CLASS_ORIGIN=ISO9075;
CONDITION_NUMBER=+1;
DB2_MESSAGE_ID=SQL0138;
DB2_MESSAGE_ID1=CPF4278;
DB2_MESSAGE_ID2=CPD4317;
DB2_MODULE_DETECTING_ERROR=QSQOPEN;
DB2_ORDINAL_TOKEN_1=*N;
DB2_RETURNED_SQLCODE=-138;
DB2_TOKEN_COUNT=+1;
DB2_TOKEN_STRING=*N;
MESSAGE_LENGTH=+47;
MESSAGE_OCTET_LENGTH=+47;
MESSAGE_TEXT=Argument *N of substringing function not valid.;
RETURNED_SQLSTATE=22011;
ROUTINE_CATALOG=******;
SERVER_NAME=******;
SUBCLASS_ORIGIN=ISO9075;
DB2_SQLERRD_SET=Y;
DB2_SQLERRD1=-185403400;
DB2_SQLERRD2=-185339401;
CONNECTION_NAME=******;
DB2_AUTHORIZATION_ID=********;
DB2_CONNECTION_METHOD=D;
DB2_CONNECTION_NUMBER=+1;
DB2_CONNECTION_STATE=+1;
DB2_CONNECTION_TYPE=+1;
DB2_PRODUCT_ID=QSQ07030;
DB2_SERVER_CLASS_NAME=DB2 for i;
DB2_SERVER_NAME=******;
这是一个应该向IBM报告的bug吗?一个人是如何做到这一点的?我制作了一个UDTF和一个调用RPGLE程序来演示这个问题。如果有人想验证我的发现,代码如下。您可能需要在RPGLE程序
TSTDIAUDTF
中注释掉几行,因为您没有我的错误消息服务程序
ERRFUNC

DUMMYUDTF
是一个外部用户定义的SQL函数,代码在SQL和RPGLE中
TSTDIAUDTF
是一个RPGLE程序,我正在使用它来测试
GET DIAGNOSTICS
SQL语句的行为

例如,这似乎与过去报告的一些bug大体相似,但细节不同

编辑: 更正了早期错误粘贴操作中的代码格式错误

DUMMYUDTF,TXT

-- Build function by calling:
-- RUNSQLSTM SRCFILE(*******/QTXTSRC) SRCMBR(DUMMYUDTF) COMMIT(*NONE)

CREATE OR REPLACE FUNCTION DummyUDTF( 
                             parm1    NUMERIC(7,0),
                             parm2    VARCHAR(7)
                             parm3    VARCHAR(4))
   RETURNS TABLE (Out1    NUMERIC(7,0),
                  Out2    VARCHAR(13),
                  Out3    VARCHAR(4),
                  Out4    NUMERIC(7,2), 
                  Out5    NUMERIC(5,4))
   LANGUAGE RPGLE 
   DETERMINISTIC 
   READS SQL DATA   
   CALLED ON NULL INPUT 
   DISALLOW PARALLEL 
   NOT FENCED
   EXTERNAL NAME '******/DUMMYUDTF'  
   PARAMETER STYLE DB2SQL;            
DUMMYUDTF,SQLRPGLE

/IF DEFINED (*CRTBNDRPG)
H DFTACTGRP(*NO) ACTGRP('DUMMYUDTF')
/ENDIF
H DEBUG
H ALWNULL(*USRCTL) OPTION(*NoDebugIO) EXTBININT(*YES)

D DUMMYUDTF       PI

*  Input Parameters
D parm1                          7S 0
D parm2                          7A   VARYING
D parm3                          4A   VARYING

* Columns to be returned
D out1                           7S 0
D out2                          13A   VARYING
D out3                           4A   VARYING
D out4                           7S 2
D out5                           5S 4

* NULL Indicators for all input and output parameters
D parm1_n                        5I 0
D parm2_n                        5I 0
D parm3_n                        5I 0

D out1_n                         5I 0
D out2_n                         5I 0
D out3_n                         5I 0
D out4_n                         5I 0
D out5_n                         5I 0

* SQL Function Parameters

D OutputSQLState                 5A
D FunctionName                 517A   VARYING CONST
D SpecificName                 128A   VARYING CONST
D MessageText                 1000A   VARYING
D CallType                      10I 0


* Locals

D CallTypeFirst   C                   CONST(-2)
D CallTypeOpen    C                   CONST(-1)
D CallTypeFetch   C                   CONST(0)
D CallTypeClose   C                   CONST(1)
D CallTypeFinal   C                   CONST(2)

D out             DS                  TEMPLATE QUALIFIED
D  out1                          7S 0
D  out2                         13A   VARYING
D  out3                          4A   VARYING
D  out4                          7S 2
D  out5                          5S 4

D results         DS                  DIM(99) LIKEDS(out)
D index           S              2S 0
D count           S              2S 0

D var4            S              7S 2
D var5            S              5S 4

MONITOR;

OutputSQLState = *ZEROS;       // Initialize Output Parameters
CLEAR MessageText;

SELECT;
WHEN CallType = CallTypeOpen;
IF parm1_n = -1;
MessageText = BuildNullError('1');
RETURN;
ENDIF;
IF parm2_n = -1;
MessageText = BuildNullError('2');
RETURN;
ENDIF;
IF parm3_n = -1;
MessageText = BuildNullError('3');
RETURN;
ENDIF;
IF parm1 < 1;
OutputSQLState = '90002';
MessageText = 'Parameter 1 must be a number greater than 0.';
RETURN;
ENDIF;
EXSR BuildDummyData;

WHEN CallType = CallTypeFetch;
index += 1;
IF index > count;
OutputSQLState = '02000';
RETURN;
ENDIF;

out1 = results(index).out1;
out2 = results(index).out2;
out3 = results(index).out3;
out4 = results(index).out4;
out5 = results(index).out5;
WHEN CallType = CallTypeClose;
*INLR = *ON;
ENDSL;
ON-ERROR;
DUMP;  // This dump ends up in the output queue QUSRSYS\QEZDEBUG
OutputSQLState = '90001';
MessageText = 'Error occurred in RPG program ''DUMMYUDTF''. ' +
'See program dump for additional details.';
ENDMON;
RETURN;

********************************************************************
BEGSR BuildDummyData;

EXEC SQL SELECT 350.05, .65
INTO :var4, :var5
FROM SYSIBM.SYSDUMMY1;

SaveToResults(parm1 : parm2 : parm3 : var4 : var5);
SaveToResults(219 : 'ABCDEF'     : 'ZYXW' : 20.1 : .65);
SaveToResults(438 : 'GHIJKLMNOP' : 'ZYXW' : 2.95 : 0);
ENDSR;

********************************************************************

P BuildNullError...
P                 B
D                 PI          1000A   VARYING
D  parmName                     20A   VALUE VARYING

OutputSQLState = '90002';
RETURN 'Parameter ''' + parmName + ''' cannot be null.';
P                 E

********************************************************************

P SaveToResults...
P                 B
D                 PI
D  loc1                          7S 0 VALUE
D  loc2                         13A   VALUE VARYING
D  loc3                          4A   VALUE VARYING
D  loc4                          7S 2 VALUE
D  loc5                          5S 4 VALUE

IF count = 99;
OutputSQLState = '10Z01';
MessageText = 'SQL warning in DUMMYUDTF +
More than 99 parts generated.';
ELSE;
count += 1;
results(count).out1 = loc1;
results(count).out2 = loc2;
results(count).out3 = loc3;
results(count).out4 = loc4;
results(count).out5 = loc5;
ENDIF;
P                 E
H DEBUG(*YES)
H MAIN(Main)
H DFTACTGRP(*NO)
H BNDDIR('ERRFUNC')

/copy QRPGLESRC,ERRFUNCPR
D  Message        DS                  LIKEDS(ErrorMsg)

D success         S              3I 0
D failure         S              3I 0
D diagAll         S          32740A   VARYING
D displayText     S             52A

D dummyItem       DS                  INZ
D  out1                          7S 0
D  out2                         13A
D  out3                          4A
D  out4                          7S 2
D  out5                          5S 4

D SQLDiagData     DS                  INZ
D  MessageID                    10A
D  MessageID1                    7A
D  MessageID2                    7A
D  MessageLength                 5I 0
D  MessageText               32740A   VARYING
D  otherType                 32740A   VARYING
D  ReturnedSQLCode...
D                                5A
D  ReturnedSQLState...
D                                5A
D  RowCount                     10I 0

P Main            B

DSPLY 'Beginning of test';
TestDummyUDTF();
TestDiagnoticsFromUDTF();
TestDiagnoticsFromBIF();

DSPLY ('Successful tests: ' + %char(success));
DSPLY ('Failed tests:     ' + %char(failure));
RETURN;

BEGSR *PSSR;
DUMP;
DSPLY 'Unexpected error while running tests.';
GetErrorMsg(Message);
DSPLY ('Message.MsgId: ' + Message.MsgId);
DSPLY (%subst(Message.MsgText:1:52));
RETURN;
ENDSR;
P                 E

********************************************************************

P TestDiagnoticsFromBIF...
P                 B

D text            S             10A
DSPLY 'Causing error from SUBSTR to read diagnostics.';
EXEC SQL SELECT SUBSTR('ABC', 1, -1) INTO :text
FROM SYSIBM.SYSDUMMY1;
IF SQLSTATE = '00000';
failure +=1;
DSPLY 'Test failed. Data returned, no error.';
ELSEIF SQLSTATE = '02000';
failure +=1;
DSPLY 'Test failed. No error returned.';
ELSE;
ReadSQLDiagnosticsAll();
IF diagAll <> '';
success += 1;
DisplayTextWindow(diagAll : 'CPF9898':'QCPFMSG');
DSPLY 'GET DIAGNOSTICS ALL succeeded.';
ELSE;
failure +=1;
DSPLY 'GET DIAGNOSTICS ALL failed.';
ENDIF;

ReadSQLDiagnosticsAllCondition();
IF diagAll <> '';
success += 1;
DisplayTextWindow(diagAll : 'CPF9898':'QCPFMSG');
DSPLY 'GET DIAGNOSTICS ALL CONDITION succeeded.';
ELSE;
failure +=1;
DSPLY 'GET DIAGNOSTICS ALL CONDITION failed.';
ENDIF;

ReadSQLDiagnostics();
IF ReturnedSQLCode <> '-138 ' OR
ReturnedSQLState <> '22011';
failure +=1;
DSPLY 'Test failed. Unexpected diagnostic.';
displayText = 'SQLCODE  ' + ReturnedSQLCode +
'   SQLSTATE ' + ReturnedSQLState;
DSPLY displayText;
ELSE;
displayText = MessageText;
DSPLY displayText;
displayText = 'MESSAGE_LENGTH ' + %char(MessageLength);
DSPLY displayText;
displayText = 'DB2_MESSAGE_ID  ' + MessageID +
' DB2_MESSAGE_ID1 ' + MessageID1;
DSPLY displayText;
displayText = 'DB2_MESSAGE_ID2 ' + MessageID2;
DSPLY displayText;
IF MessageText <> '';
success += 1;
DSPLY 'GET DIAGNOSTICS MessageText succeeded.';
ELSE;
failure +=1;
DSPLY 'GET DIAGNOSTICS MessageText failed.';
ENDIF;
ENDIF;
ENDIF;
P                 E

********************************************************************

P TestDiagnoticsFromUDTF...
P                 B

D var2            S              7A
D var2_n          S              5I 0

var2_n = -1;
DSPLY 'Causing error from DummyUDTF to read diagnostics.';
EXEC SQL DECLARE CUR_DIAG_UDTF CURSOR FOR (
SELECT ITEMS.*
FROM TABLE (QGPL.DummyUDTF(22, :var2 :var2_n, 'ZZ')) AS ITEMS
);
EXEC SQL OPEN CUR_DIAG_UDTF;
DOW 1=1;
EXEC SQL FETCH CUR_DIAG_UDTF INTO :dummyItem;
IF SQLSTATE = '00000';
failure +=1;
DSPLY 'Test failed. Records returned, no error.';
LEAVE;
ELSEIF SQLSTATE = '02000';
failure +=1;
DSPLY 'Test failed. No error returned.';
LEAVE;
ELSE;
ReadSQLDiagnosticsAll();
IF diagAll <> '';
success += 1;
DisplayTextWindow(diagAll : 'CPF9898':'QCPFMSG');
DSPLY 'GET DIAGNOSTICS ALL succeeded.';
ELSE;
failure +=1;
DSPLY 'GET DIAGNOSTICS ALL failed.';
ENDIF;

ReadSQLDiagnosticsAllCondition();
IF diagAll <> '';
success += 1;
DisplayTextWindow(diagAll : 'CPF9898':'QCPFMSG');
DSPLY 'GET DIAGNOSTICS ALL CONDITION succeeded.';
ELSE;
failure +=1;
DSPLY 'GET DIAGNOSTICS ALL CONDITION failed.';
ENDIF;

ReadSQLDiagnosticsUDTF();
IF ReturnedSQLCode <> '-443 ' OR
ReturnedSQLState <> '90002';
failure +=1;
DSPLY 'Test failed. Unexpected diagnostic.';
displayText = 'SQLCODE  ' + ReturnedSQLCode +
'   SQLSTATE ' + ReturnedSQLState;
DSPLY displayText;
ELSE;
*        DSPLY MessageID;
*        DSPLY %char(MessageLength);
displayText = MessageText;
DSPLY displayText;
displayText = 'MESSAGE_LENGTH ' + OtherType;
DSPLY displayText;
displayText = 'DB2_MESSAGE_ID  ' + MessageID +
' DB2_MESSAGE_ID1 ' + MessageID1;
DSPLY displayText;
IF MessageText <> '';
success += 1;
DSPLY 'GET DIAGNOSTICS MessageText succeeded.';
ELSE;
failure +=1;
DSPLY 'GET DIAGNOSTICS MessageText failed.';
ENDIF;
ENDIF;
LEAVE;
ENDIF;
ENDDO;
EXEC SQL CLOSE CUR_DIAG_UDTF;
P                 E
********************************************************************

P TestDummyUDTF...
P                 B

D expected        DS                  DIM(3) LIKEDS(dummyItem)
D index           S              3I 0

expected(1).out1 = 22;
expected(1).out2 = 'AAAA';
expected(1).out3 = 'ZZ';
expected(1).out4 = 350.05;
expected(1).out5 = .65;
expected(2).out1 = 219;
expected(2).out2 = 'ABCDEF';
expected(2).out3 = 'ZYXW';
expected(2).out4 = 20.1;
expected(2).out5 = .65;
expected(3).out1 = 438;
expected(3).out2 = 'GHIJKLMNOP';
expected(3).out3 = 'ZYXW';
expected(3).out4 = 2.95;
expected(3).out5 = 0;

DSPLY 'Running test on DummyUDTF, success expected.';
EXEC SQL DECLARE CUR_UDTF CURSOR FOR (
SELECT ITEMS.*
FROM TABLE (QGPL.DummyUDTF(22, 'AAAA', 'ZZ')) AS ITEMS
);
EXEC SQL OPEN CUR_UDTF;
DOW 1=1;
EXEC SQL FETCH CUR_UDTF INTO :dummyItem;
IF SQLSTATE = '00000';
index += 1;
IF out1 <> expected(index).out1 OR
out2 <> expected(index).out2 OR
out3 <> expected(index).out3 OR
out4 <> expected(index).out4 OR
out5 <> expected(index).out5;
failure +=1;
DSPLY 'Test failed. Data mismatch from UDTF.';
ELSE;
success += 1;
DSPLY 'Test succeeded.';
ENDIF;
LEAVE;
ELSEIF SQLSTATE = '02000';
IF index = 0;
failure +=1;
DSPLY 'Test failed. No records returned.';
ENDIF;
LEAVE;
ELSE;
failure +=1;
DSPLY ('Test failed. SQLSTATE ' + SQLSTATE);
// ReadSQLDiagnostics();
LEAVE;
ENDIF;
ENDDO;
EXEC SQL CLOSE CUR_UDTF;
RETURN;
P                 E

**************************************************************************

P ReadSQLDiagnostics...
P                 B
D                 PI
D  condition#                    5I 0 VALUE OPTIONS(*NOPASS)

IF %parms = 0 OR condition# < 1;
condition# = 1;
ENDIF;
EXEC SQL GET DIAGNOSTICS CONDITION :condition#
:SQLDiagData.ReturnedSQLCode  = DB2_RETURNED_SQLCODE,
:SQLDiagData.ReturnedSQLState = RETURNED_SQLSTATE,
:SQLDiagData.MessageText      = MESSAGE_TEXT,
:SQLDiagData.MessageLength    = MESSAGE_LENGTH,
:SQLDiagData.MessageID        = DB2_MESSAGE_ID,
:SQLDiagData.MessageID1       = DB2_MESSAGE_ID1,
:SQLDiagData.MessageID2       = DB2_MESSAGE_ID2;
RETURN;
P                 E

**************************************************************************

P ReadSQLDiagnosticsUDTF...
P                 B
D                 PI
D  condition#                    5I 0 VALUE OPTIONS(*NOPASS)

IF %parms = 0 OR condition# < 1;
condition# = 1;
ENDIF;
EXEC SQL GET DIAGNOSTICS CONDITION :condition#
:SQLDiagData.ReturnedSQLCode  = DB2_RETURNED_SQLCODE,
:SQLDiagData.ReturnedSQLState = RETURNED_SQLSTATE,
:SQLDiagData.MessageText      = MESSAGE_TEXT,
:SQLDiagData.otherType        = MESSAGE_LENGTH,
:SQLDiagData.MessageID        = DB2_MESSAGE_ID,
:SQLDiagData.MessageID1       = DB2_MESSAGE_ID1;

//   :SQLDiagData.MessageLength    = MESSAGE_LENGTH,
//   :SQLDiagData.MessageID        = DB2_MESSAGE_ID;

RETURN;
P                 E

************************4*************************************************

P ReadSQLDiagnosticsAll...
P                 B

EXEC SQL GET DIAGNOSTICS :diagAll = ALL;
RETURN;
P                 E
**************************************************************************

P ReadSQLDiagnosticsAllCondition...
P                 B
D                 PI
D  condition#                    5I 0 VALUE OPTIONS(*NOPASS)

IF %parms = 0 OR condition# < 1;
condition# = 1;
ENDIF;
EXEC SQL GET DIAGNOSTICS :diagAll = ALL CONDITION;
RETURN;
P                 E

P DisplayTextWindow...
P                 B                   Export
D                 PI
D Text                        8192    Const Varying
D MessageId                      7    Const
D MessageFile                   21    Const

D ErrCode         DS
D  BytesIn                      10I 0 INZ(0)
D  BytesOut                     10I 0 INZ(0)

DQUILNGTX         PR                  EXTPGM('QUILNGTX')
D MsgText                     8192    CONST
D MsgLength                     10I 0 CONST
D MessageId                      7    CONST
D MessageFile                   21    CONST
D dsErrCode                           LIKE(ErrCode)

QUILNGTX(Text : %Len(Text) :
MessageId : MessageFile : ErrCode);
P                 E
/如果定义(*CRTBNDRPG)
H DFTACTGRP(*否)ACTGRP('DUMMYUDTF'))
/恩迪夫
H调试
H ALWNULL(*USRCTL)选项(*NoDebugIO)EXTBININT(*是)
D DUMMYUDTF PI
*输入参数
D parm1 7S 0
D parm2 7A可变
D parm3 4A可变
*要返回的列
D输出17秒0
D输出2 13A变化
D输出3 4A变化
D输出4 7S 2
D输出5 5S 4
*所有输入和输出参数的空指示符
D parm1_n 5I 0
D parm2_n 5I 0
D parm3_n 5I 0
D输出1_n 5I 0
D输出2_n 5I 0
D输出3_n 5I 0
D输出4_n 5I 0
D输出5_n 5I 0
*SQL函数参数
D输出SQLSTATE 5A
D函数名517A可变常数
D SpecificName 128A可变常量
D消息文本1000A
D调用类型10I 0
*当地人
D CallTypeFirst C常量(-2)
D调用类型打开C常量(-1)
D CallTypeFetch C常量(0)
D调用类型关闭C常量(1)
D调用类型最终C常量(2)
D输出DS模板合格
D输出17秒0
D输出2 13A变化
D输出3 4A变化
D输出4 7S 2
D输出5 5S 4
D结果DS DIM(99)LIKEDS(out)
D指数s2s0
D计数S 2S 0
D var4 S 7S 2
D var5 S 5S 4
班长
OutputSQLState=*零;//初始化输出参数
文本清晰;
选择;
当CallType=CallTypeOpen时;
如果parm1_n=-1;
MessageText=BuildNullError('1');
返回;
ENDIF;
如果parm2_n=-1;
MessageText=BuildNullError('2');
返回;
ENDIF;
如果parm3_n=-1;
MessageText=BuildNullError('3');
返回;
ENDIF;
如果parm1<1;
OutputSQLState='90002';
MessageText='参数1必须是大于0的数字';
返回;
ENDIF;
EXSR BuildDummyData;
当CallType=CallTypeFetch时;
指数+=1;
如果索引>计数;
OutputSQLState='02000';
返回;
ENDIF;
out1=结果(指数)。out1;
out2=结果(指数)。out2;
out3=结果(指数)。out3;
out4=结果(指数)。out4;
out5=结果(指数)。out5;
当CallType=CallTypeClose时;
*INLR=*ON;
ENDSL;
在线误差;
转储;//此转储将在输出队列QUSRSYS\QEZDEBUG中结束
OutputSQLState='90001';
MessageText='RPG程序“DUMMYUDTF”中发生错误。'+
'有关其他详细信息,请参阅程序转储';
尾声;
返回;
********************************************************************
BEGSR BuildDummyData;
EXEC SQL SELECT 350.05、.65
进入:var4,:var5
来自SYSIBM.SYSDUMMY1;
保存结果(parm1:parm2:parm3:var4:var5);
保存结果(219:'ABCDEF':'ZYXW':20.1:.65);
保存结果(438:'GHIJKLMNOP':'ZYXW':2.95:0);
ENDSR;
********************************************************************
P BuildNullError。。。
P B
D PI 1000A可变
D参数名称20A值变化
OutputSQLState='90002';
返回“参数”+“参数名”+“不能为空”;
体育课
*******************************************************************
**free
ctl-opt actgrp(*NEW) main(mainline) cvtopt(*NOVARCHAR) debug(*yes);
dcl-pr mainline extpgm('TESTRPGLE');
end-pr;


dcl-proc mainline;

  dcl-s diagAll varchar(32740);
  dcl-ds dummyItem qualified;
    out1 zoned(7);
    out2 varchar(13);
    out3 varchar(4);
    out4 zoned(7:2);
    out5 zoned(5:4);
  end-ds;
  dcl-s nullArr int(5) dim(5);

  exec sql
    declare C1 cursor for (
    SELECT ITEMS.*
     FROM TABLE (DummyUDTF(22, cast(null as varchar(7)), 'ZZ')) AS ITEMS
     );

  exec sql
    open C1;

  //I expected  SQLSTATE to be 90002 here, but it's not
  if sqlstate <> *ZEROS;
    exec sql
      get diagnostics :diagAll = ALL;
    dump;
    return;
  endif;

  exec sql
    fetch C1 into :dummyItem :nullArr;

  //here's where the SQLSTATE of 90002 is returned.
  if sqlstate <> *ZEROS;
    exec sql
      get diagnostics :diagAll = ALL;
    dump;
    return;
  endif;
  return;
end-proc;