X-Original-To: pgsql-interfaces-postgresql.org@localhost.postgresql.org Received: from localhost (unknown [200.46.204.144]) by svr1.postgresql.org (Postfix) with ESMTP id 5F56AD1B16B for ; Mon, 7 Jun 2004 10:39:18 -0300 (ADT) Received: from svr1.postgresql.org ([200.46.204.71]) by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024) with ESMTP id 87324-07 for ; Mon, 7 Jun 2004 13:39:14 +0000 (GMT) Received: from mailserv.intranet.gr (mailserv.intranet.GR [146.124.14.106]) by svr1.postgresql.org (Postfix) with ESMTP id 6D38ED1CCCC for ; Mon, 7 Jun 2004 10:39:05 -0300 (ADT) Received: from mailserv.intranet.gr (localhost [127.0.0.1]) by mailserv.intranet.gr (8.11.7/8.11.3) with ESMTP id i57Diic04565 for ; Mon, 7 Jun 2004 16:44:44 +0300 (EEST) Received: from dadia.intranet.gr (dadia.intranet.GR [146.124.175.10]) by mailserv.intranet.gr (8.11.7/8.11.3) with ESMTP id i57DigG04547; Mon, 7 Jun 2004 16:44:42 +0300 (EEST) Received: from pcszis (pcszis [146.124.175.98]) by dadia.intranet.gr (8.11.7p1+Sun/8.11.7) with SMTP id i57DT3T04241; Mon, 7 Jun 2004 16:29:04 +0300 (EET DST) From: "Stergios Zissakis" To: "Interfaces" Cc: "Kostas Lykiardopoulos" , "Dimitris Pantermalis" Subject: [ECPG] Multiple cursors in the same transaction Date: Mon, 7 Jun 2004 16:36:29 +0300 Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset="ISO-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2910.0) Importance: Normal X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106 X-Virus-Scanned: by amavisd-new at hub.org X-Spam-Status: No, hits=0.3 tagged_above=0.0 required=5.0 tests=UPPERCASE_25_50 X-Spam-Level: X-Archive-Number: 200406/11 X-Sequence-Number: 4939 Dear ECPG support, During a port from Oracle I came accross a problem where a cursor is lost when a commit is performed. Consider the following piece of code: EXEC SQL WHENEVER SQLERROR DO call_sql_error_function(...); EXEC SQL CONNECT TO :connect_str USER :username IDENTIFIED BY :password; sprintf((char *) del_stmt.arr, "select columns from delete_table;\0"); EXEC SQL PREPARE Delete FROM del_stmt; EXEC SQL DECLARE del1 CURSOR FOR Delete; EXEC SQL OPEN del1; EXEC SQL WHENEVER NOT FOUND DO break; while( true ) { EXEC SQL FETCH FROM del1 INTO :dlt; ... sprintf((char *) stmt.arr, "select to_char((date_trunc('month', localtimestamp) - interval '%d month'), 'MM/DD/YYYY HH24:MI:SS');\0", months); EXEC SQL PREPARE S1 FROM :stmt; EXEC SQL DECLARE mytime CURSOR FOR S1; EXEC SQL OPEN mytime; EXEC SQL FETCH mytime INTO :mydate; EXEC SQL CLOSE mytime; ... sprintf((char *) select_stmt, "select ... from ... where ...;\0", ...); EXEC SQL PREPARE ARCH FROM :select_stmt; EXEC SQL DECLARE SEL_CURS CURSOR FROM ARCH; EXEC SQL OPEN SEL_CURS; EXEC SQL WHENEVER NOT FOUND DO break; while( true ) { EXEC SQL FETCH :rows_to_fetch FROM SEL_CURS INTO :alarm_records; for( int i = 0; i < sqlca.sqlerrd[2]; i++ ) { ... } } EXEC SQL CLOSE SEL_CURS; ... EXEC SQL WHENVER NOT FOUND goto somewhere; sprintf((char *) del2_stmt, "delete from %s where %s;\0", from, where); EXEC SQL PREPARE DEL2 FROM :del2_stmt; EXEC SQL EXECUTE DEL2; EXEC SQL COMMIT; // I think this commit causes the problem... see the comments further down. somewhere: ... } EXEC SQL CLOSE del1; EXEC SQL COMMIT WORK RELEASE; The problem is that fetching the second time round from the del1 cursor cause the app to bomb out. The postmaster log displays the following message: "... ERROR: cursor del1 does not exist". Any ideas why this is happening? Who come del1 dissapears whithout closing it? Notice that my delete_table (del_stmt statement at the beginning) contains a single row; so the second time a fetch is performed it should simply not found anything and do a break to terminate the loop. The work-around I found was to split the work in two different connections (contexts); one for selecting from the delete_table and the other for the rest of the statements. This way everything works fine but I cannot really afford an extra connection for this (my app has already 20 connections by design). Here is the code that solved the problem: EXEC SQL WHENEVER SQLERROR DO call_sql_error_function(...); EXEC SQL CONNECT TO :connect_str AS :ctx1 USER :username IDENTIFIED BY :password; EXEC SQL CONNECT TO :connect_str AS :ctx2USER :username IDENTIFIED BY :password; sprintf((char *) del_stmt.arr, "select columns from delete_table;\0"); EXEC SQL PREPARE Delete FROM del_stmt; EXEC SQL AT :ctx1 DECLARE del1 CURSOR FOR Delete; EXEC SQL AT :ctx1 OPEN del1; EXEC SQL WHENEVER NOT FOUND DO break; while( true ) { EXEC SQL AT :ctx1 FETCH FROM del1 INTO :dlt; ... sprintf((char *) stmt.arr, "select to_char((date_trunc('month', localtimestamp) - interval '%d month'), 'MM/DD/YYYY HH24:MI:SS');\0", months); EXEC SQL PREPARE S1 FROM :stmt; EXEC SQL AT :ctx2 DECLARE mytime CURSOR FOR S1; EXEC SQL AT :ctx2 OPEN mytime; EXEC SQL AT :ctx2 FETCH mytime INTO :mydate; EXEC SQL AT :ctx2 CLOSE mytime; ... sprintf((char *) select_stmt, "select ... from ... where ...;\0", ...); EXEC SQL PREPARE ARCH FROM :select_stmt; EXEC SQL AT :ctx2 DECLARE SEL_CURS CURSOR FROM ARCH; EXEC SQL AT :ctx2 OPEN SEL_CURS; EXEC SQL WHENEVER NOT FOUND DO break; while( true ) { EXEC SQL AT :ctx2 FETCH :rows_to_fetch FROM SEL_CURS INTO :alarm_records; for( int i = 0; i < sqlca.sqlerrd[2]; i++ ) { ... } } EXEC SQL AT :ctx2 CLOSE SEL_CURS; ... EXEC SQL WHENVER NOT FOUND goto somewhere; sprintf((char *) del2_stmt, "delete from %s where %s;\0", from, where); EXEC SQL PREPARE DEL2 FROM :del2_stmt; EXEC SQL AT :ctx2 EXECUTE DEL2; EXEC SQL AT :ctx2 COMMIT; somewhere: ... } EXEC SQL AT :ctx1 CLOSE del1; EXEC SQL COMMIT WORK RELEASE; Is there any other solution to this problem? Thanks in advance. Stergios Zissakis Intracom S.A. Network Management Systems Dept. Paiania Athens Greece