GnuCOBOL中的PostgreSQL游标重新打开错误
我正试图在GnuCOBOL上从Oracle迁移到PostgreSQL。我有一段使用游标的代码,需要多次打开游标。但是,当再次尝试打开光标时,出现错误GnuCOBOL中的PostgreSQL游标重新打开错误,postgresql,cobol,gnucobol,embedded-sql,Postgresql,Cobol,Gnucobol,Embedded Sql,我正试图在GnuCOBOL上从Oracle迁移到PostgreSQL。我有一段使用游标的代码,需要多次打开游标。但是,当再次尝试打开光标时,出现错误错误:光标“fetchtbl_c1”已经存在 IDENTIFICATION DIVISION. PROGRAM-ID. FETCHTBL. DATA DIVISION. WORKIN
错误:光标“fetchtbl_c1”已经存在
IDENTIFICATION DIVISION.
PROGRAM-ID. FETCHTBL.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 D-SOC-REC.
05 D-SOC-NO-1 PIC X(3).
05 FILLER PIC X.
05 D-SOC-NO-2 PIC X(3).
EXEC SQL BEGIN DECLARE SECTION END-EXEC.
01 USERNAME PIC X(30) VALUE SPACE.
01 SOC-REC-VARS.
05 SOC-NO-1 PIC X(3).
05 SOC-NO-2 PIC X(3).
EXEC SQL END DECLARE SECTION END-EXEC.
EXEC SQL INCLUDE SQLCA END-EXEC.
PROCEDURE DIVISION.
MAIN-RTN.
MOVE SPACE TO USERNAME.
EXEC SQL
CONNECT :USERNAME
END-EXEC.
IF SQLCODE NOT = ZERO DISPLAY "ERROR CONNECTING".
* DECLARE CURSOR
EXEC SQL
DECLARE C1 CURSOR FOR
SELECT SOC_NO_1, SOC_NO_2
FROM INSP
ORDER BY SOC_NO_1
END-EXEC.
EXEC SQL
OPEN C1
END-EXEC.
IF SQLCODE = ZERO DISPLAY "OPEN SUCCESSFUL"
ELSE DISPLAY "OPEN FAILED".
* FETCH
EXEC SQL
FETCH C1 INTO :SOC-NO-1,:SOC-NO-2
END-EXEC.
IF SQLCODE = ZERO DISPLAY "FETCH SUCCESSFUL"
ELSE DISPLAY "FETCH FAILED".
PERFORM UNTIL SQLCODE NOT = ZERO
MOVE SOC-NO-1 TO D-SOC-NO-1
MOVE SOC-NO-2 TO D-SOC-NO-2
DISPLAY D-SOC-REC
EXEC SQL
FETCH C1 INTO :SOC-NO-1,:SOC-NO-2
END-EXEC
END-PERFORM.
* CLOSE CURSOR
EXEC SQL
CLOSE C1
END-EXEC.
IF SQLCODE = ZERO DISPLAY "CLOSE SUCCESSFUL"
ELSE DISPLAY "CLOSE FAILED".
* OPEN AGAIN
EXEC SQL
OPEN C1
END-EXEC.
IF SQLCODE = ZERO DISPLAY "REOPEN SUCCESSFUL"
ELSE DISPLAY "REOPEN FAILED " SQLERRMC.
* COMMIT
EXEC SQL
COMMIT WORK
END-EXEC.
* DISCONNECT
EXEC SQL
DISCONNECT ALL
END-EXEC.
* END
STOP RUN.
使用ocesql
预编译代码,并使用cobc-x
博士后输出
OPEN SUCCESSFUL
FETCH SUCCESSFUL
003 001
005 001
CLOSE SUCCESSFUL
REOPEN FAILED ERROR: cursor "fetchtbl_c1" already exists
上面的代码在Oracle中工作得非常好(连接部分除外)
Oracle输出
OPEN SUCCESSFUL
FETCH SUCCESSFUL
003 001
CLOSE SUCCESSFUL
REOPEN SUCCESSFUL
我曾尝试在网上搜索,但没有任何运气。有人能帮我吗?
我使用的是PostgreSQL版本10.3和GnuCOBOL版本2.2.0。预编译器似乎存在问题。我在函数
OCDBSetResultStatus
中的ocdb.c
中添加了一个修复程序,以在没有结果资源的情况下返回一个成功的代码(这在打开游标的情况下发生)
这可能不完全正确,但在花了几个小时进行测试后,我发现它工作得很好
代码更改:
int
OCDBSetResultStatus(int id, struct sqlca_t *st){
struct s_conn *p_conn;
int retval;
p_conn = look_up_conn_lists(id);
if(p_conn == NULL){
//return OCDB_RES_FATAL_ERROR;
return RESULT_ERROR;
}
if(p_conn->resaddr == OCDB_RES_DEFAULT_ADDRESS){
// 結果リソースが無いため成功で返す
// Ankit: uncommented since there is no result resource,
// (true in case of open cursor)
return OCDB_RES_COMMAND_OK;
//return RESULT_ERROR;
}
#ifdef PGSQL_MODE_ON
retval = OCDB_PGSetResultStatus(p_conn->resaddr,st);
#endif
return retval;
}
如果有人因为此更改而面临任何问题,请告诉我。暗中猜测:您能否尝试
取消分配准备好的语句(在光标后面)?我没有使用prepare语句。正如上面的代码所示,它是一个直接的光标。问题是如果我要使用prepared语句,我有1000个组件需要更改。我的想法是游标隐式地创建(或使用)一个prepared语句(从Postgres的角度来看)。关闭光标后的解除分配所有
可以验证这一理论。只是尝试了一下,遗憾的是这不起作用。在DEALLOCATE ALL
成功后,我检查了SQLCODE
,但仍然得到相同的错误error:cursor“fetchtbl_c1”已经存在
您使用了什么版本的ocesql和什么操作系统?您是否也尝试过[esqlOC](?这意味着使用COBOLODBC(通过ocsql库)PostgreSQL。注意:我已经检查了您的示例代码,esqlOC目前不支持DISCONNECT
,但至少添加DISCONNECT ALL
应该可以快速完成。但这只有在其他部分适合您的情况下才有意义……似乎是一个合理的PR,可以发布,同时还创建一个包含您的示例的问题问题中张贴的代码、您的解释和参考PR。