PostgreSQL Cursor Re-open error in GnuCOBOL - postgresql

I am trying to move from Oracle to PostgreSQL on GnuCOBOL. I have a piece of code which uses cursors and need opening a cursor multiple times. However when trying to open the cursor again I get the error ERROR: cursor "fetchtbl_c1" already exists
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.
Pre-compiled the code using ocesql and compiled using cobc -x
Postgres Output
OPEN SUCCESSFUL
FETCH SUCCESSFUL
003 001
005 001
CLOSE SUCCESSFUL
REOPEN FAILED ERROR: cursor "fetchtbl_c1" already exists
The above code works perfectly fine (except for connection part) in Oracle.
Oracle output
OPEN SUCCESSFUL
FETCH SUCCESSFUL
003 001
CLOSE SUCCESSFUL
REOPEN SUCCESSFUL
I have tried searching on the internet but without any luck. Anybody can help me with this?
I am using PostgreSQL version 10.3 and GnuCOBOL version 2.2.0.

There seemed to be an issue with ocesql pre-compiler. I have put a fix in ocdb.c in function OCDBSetResultStatus to return a successful code in case there is not result resource (which happens for open cursor case).
This might not be entirely correct but after spending a few hours testing I see this working fine.
Code changes:
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;
}
Let me know if anybody faces any issues because of this change.

Related

Easytrieve Plus and Db2 - Read a file as input to matching against Db2 table

I am running a batch job that reads in a file in with a list of templates. I am trying to find an example since the one I was provided will not work. I have tried to find any example of reading in a file via EZTPA00. The JCL is correct, but I keep getting an error. Here's the basic code followed by the error I'm getting:
LIST ON
PARM SSID('DB2G')
FILE INFILE1 VB (133 6233)
IP-REC 01 133 A
TEMPLATE 01 015 A
FILE OUFILE1 FB (100 1000)
OP-REC 01 100 A
COMMUN_TRANS_ID 01 040 A
COMMUN_TEMPLATE_NO 42 015 A
DEFINE H-CNT W 13 N
SQL DECLARE C1 CURSOR FOR +
SELECT TRANSACTION, TEMPLATE +
FROM DB2.TEMPLATE_TABLE WHERE +
TEMPLATE = INFILE1:TEMPLATE
FETCH FROM INFILE1
IF EOF INFILE1
DISPLAY 'TEMPLATE ' TEMPLATE ' NOT RETURNED'
STOP
END-IF
CLOSE INFILE1
* INPUT SETUP
JOB INPUT(INFILE1) +
START 010-INIT +
FINISH 999-END
* START THE SQL
SQL OPEN C1
DO WHILE SQLCODE NE +100
SQL FETCH C1 +
INTO :WS-TMPLT, :WS-COMMID
IF SQLCODE NE 0
DISPLAY 'PF : ERROR : SQLCODE : ' SQLCODE
STOP
END-IF
13 SQL DECLARE C1 CURSOR FOR +
SELECT COMMUN_TRANS_ID, COMMUN_TEMPLATE_NO +
FROM VMUSIU.E_COMM_DLVY WHERE +
COMMUN_TEMPLATE_NO = INFILE1:TEMPLATE
13 *******B204 SQL - SQL ERROR, SQLCODE IS -104
13 *******B204 SQL - DSNT408I SQLCODE = -104, ERROR: ILLEGAL SYMBOL "?". SOME SYMBOLS THAT MIGHT BE LEGAL
13 *******B204 SQL - ARE: AND * AT OR SELECTIVITY YEAR YEARS MONTH MONTHS DAY DAYS HOUR
13 *******B204 SQL - DSNT418I SQLSTATE = 42601 SQLSTATE RETURN CODE
I have no idea what the "?" is. I tried using a fetch for infile1 but it said it was invalid. Everything I try gives me the same answer. I even tried using ws variables, but it still failed. Does someone have something that allows you to match db2 table info against a file?

WHENEVER SQLERROR of postgresql causes INTO assignment to fail

This is a piece of ecpg code. When using fetch to traverse the data, because of the use of WHENEVER SQLERROR DO sqlerr(), if an error occurs, it will be judged by the sqlerr method that it is a 22002 error, and the error will be ignored and the traversal will continue
int main(int argc, char *argv[]) {
....
EXEC SQL DECLARE mt_cur CURSOR WITH HOLD FOR
SELECT
C1, C2, C3
FROM MYTABLE,
ORDER BY C1;
EXEC SQL WHENEVER SQLERROR CONTINUE;
EXEC SQL CLOSE mt_cur;
EXEC SQL WHENEVER SQLERROR DO sqlerr();
EXEC SQL OPEN mt_cur;
EXEC SQL WHENEVER NOT FOUND DO break;
while (1) {
EXEC SQL FETCH mt_cur INTO :v1, :v2, :v3;
if (v3 > 5 ) {
continue;
}
printf("%d%d\n", v1, v3);
}
EXEC SQL CLOSE mt_cur;
....
return (0);
}
void sqlerr() {
if (strncmp(sqlca.sqlstate, "22002", 5) == 0) {
return;
}
EXEC SQL WHENEVER SQLERROR CONTINUE;
EXEC SQL ROLLBACK WORK;
exit(1);
}
If the data in the table is like this
C1 C2 C3
1 0 2
2 (NULL) 8
3 (NULL) 9
The correct running result should be to print only one 12, but now it prints out 12, 22, 32
After analyzing the program, I think that when traversing the second row of data, the C2 column is NULL, which leads to entering the sqlerr method. After returning in sqlerr, INTO will not be executed to assign a value to v3, and it will enter the next traversal. At this time, the value of v3 is 2 assigned during the first traversal
Is my idea correct? If so, is there a way for postgresql to avoid this situation, I want the value of C3 to be INTO to v3 normally when C2 is NULL

TSQL OUTPUT clause in MERGE statement raise Msg 596 "Cannot continue the execution because the session is in the kill state"

I wrote T-SQL MERGE query to merge staging data into a data warehouse (you can find it at the bottom).
If I uncomment the OUTPUT statement the I get error mentioned in the title.
However, if I do not include it, everything works perfectly fine and MERGE succeeds.
I know that there are some issue connected to the MERGE clause, however there are more connected to the type of merge.
I checked the following answer: [https://dba.stackexchange.com/questions/140880/why-does-this-merge-statement-cause-the-session-to-be-killed], however in my execution plan I cannot find exactly index insert followed by index merge.
Rather, what I see is the following execution plan
Code was developed on database attached to SQL Server 2012 (SP4) instance
I would really appreciate good explanation of this problem, ideally referencing steps from my execution plan.
Thank you.
declare #changes table (chgType varchar(50),Id varchar(18))
begin try
set xact_abort on
begin tran
;with TargetUserLogHsh as (select
hsh =hashbytes('md5',concat(coalesce([AccountName],'')
,coalesce([TaxNumber],'')))
,LastLoginCast = coalesce(CONVERT(datetime,LastLogin,103),getdate())
,* from
dw.table1)
,SourceUserLogHsh as (select
hsh =hashbytes('md5',concat(coalesce([AccountName],'')
,coalesce([TaxNumber],'')))
,LastLoginCast = coalesce(CONVERT(datetime,LastLogin,103),getdate())
,* from
sta.table1)
merge TargetUserLogHsh target
using SourceUserLogHsh source
on target.ContactId = source.ContactId and target.Lastlogincast >= source.LastLoginCast
when not matched then insert (
[AccountName]
,[TaxNumber]
,[LastLogin]
)
values (
source.[AccountName]
,source.[TaxNumber]
,source.[LastLogin]
)
when matched and target.lastlogincast = source.lastlogincast
and target.hsh != source.hsh then
update
set
[AccountName] = source.[AccountName]
,[TaxNumber] = source.[TaxNumber]
,[LastLogin] = source.[LastLogin]
output $action,inserted.contactid into #changes
;
commit tran
end try
begin catch
if ##TRANCOUNT > 0 rollback tran
select ERROR_MESSAGE()
end catch

Throw error in SQL Server 2008 R2

I'm working with SQL Server 2008 R2 and I have an stored procedure where I'm trying to throw errror
throw 50001, 'Couldnot process,Please verify Transaction ID and EmbossLine', 1
But the query doesn't get executed and throws error on 50001. It was working fine on SQL Server 2012. I think there is some issue with versions. Is there anyother way I can throw error in SQL Server 2008 R2?
This is my stored procedure:
Alter procedure [dbo].[spGetRedemption]
#pan varchar(19),
#transId bigint
AS
Begin
if EXISTS(select * from POS_Transactions where ID=#transId)
Begin
select
PT.ID, PT.TransactionDate, M.MerchantName1,
PT.TerminalID, PT.BatchNumber, PT.SequenceNumber, PT.PAN,
C.EmbossName, PT.TotalAmount, PT.CurrencyCode,
TT.TransactionType, PT.InvoiceNumber
from
POS_Transactions PT
inner join
Terminal T on T.TerminalID = PT.TerminalID
inner join
Merchant M on M.MerchantID = T.MerchantID
inner join
Card C on C.EmbossLine = PT.PAN
inner join
TransactionType TT on TT.TransactionTypeID = PT.TransactionTypeID
where
PT.ID = #transId
and PT.PAN = #pan
END
Else
Begin
throw 50001, 'Couldnot process,Please verify Transaction ID and EmbossLine', 1
END
End
Throw is not available in SQL Server 2008R2; it was first introduced in SQL Server 2012.
https://msdn.microsoft.com/en-us/library/ee677615(v=sql.110).aspx
The alternative would be to use Raiserror (note; only 1 E in the middle; it's not RaiseError).
From the above link, there are some differences between these methods:
RAISERROR statement
If a msg_id is passed to RAISERROR, the ID must be defined in sys.messages.
The msg_str parameter can contain printf formatting styles.
The severity parameter specifies the severity of the exception.
THROW statement
The error_number parameter does not have to be defined in sys.messages.
The message parameter does not accept printf style formatting.
There is no severity parameter. The exception severity is always set to 16.

Problems using REXX to access both Teradata output and DB2 output

I have a REXX job that needs to read from both Teradata (using BTEQ) and DB2. At present, I can get it to either read from Teradata or DB2, but not both. When I try to read from both, the Teradata one (which runs first) works fine but the DB2 read gives an error of RC(1) upon attempting to open the cursor.
Code to read from Teradata (by and large copied from http://www.teradataforum.com/teradata/20040928_131203.htm):
ADDRESS TSO "DELETE BLAH.TEMP"
"ALLOC FI(SYSPRINT) DA(BLAH.TEMP) NEW CATALOG SP(10 10) TR RELEASE",
"UNIT(SYSDA) RECFM(F B A) LRECL(133) BLKSIZE(0) REUSE"
"ATTRIB FBATTR LRECL(220)"
"ALLOC F(SYSIN) UNIT(VIO) TRACKS SPACE(10,10) USING(FBATTR)"
/* Set up BTEQ script */
QUEUE ".RUN FILE=LOGON"
QUEUE "SELECT COLUMN1 FROM TABLE1;"
/* Run BTEQ script */
"EXECIO * DISKW SYSIN (FINIS"
"CALL 'SYS3.TDP.APPLOAD(BTQMAIN)'"; bteq_rc = rc
"FREE FI(SYSPRINT SYSIN)"
/* Read and parse BTEQ output */
"EXECIO * DISKR SYSPRINT (STEM BTEQOUT. FINIS"
DO I = 1 to BTEQOUT.0
...
END
Code to read from DB2:
ADDRESS TSO "SUBCOM DSNREXX"
IF RC THEN rcDB2 = RXSUBCOM('ADD','DSNREXX','DSNREXX')
ADDRESS DSNREXX "CONNECT " subsys
sqlQuery = "SELECT COLUMN2 FROM TABLE2;"
ADDRESS DSNREXX "EXECSQL DECLARE C001 CURSOR FOR S001"
IF SQLCODE <> 0 THEN DO
SAY 'DECLARE C001 SQLCODE = ' SQLCODE
EXIT 12
END
ADDRESS DSNREXX "EXECSQL PREPARE S001 FROM :sqlQuery"
IF SQLCODE <> 0 THEN DO
SAY 'PREPARE S001 SQLCODE = ' SQLCODE SQLERROR
EXIT 12
END
ADDRESS DSNREXX "EXECSQL OPEN C001"
IF SQLCODE <> 0 THEN DO
SAY 'OPEN C001 SQLCODE = ' SQLCODE
EXIT 12
END
ADDRESS DSNREXX "EXECSQL FETCH C001 INTO :col2"
IF SQLCODE <> 0 THEN DO
SAY 'FETCH C001 SQLCODE = ' SQLCODE
EXIT 12
END
I suspect that this has something to do with my use of SYSPRINT and SYSIN. Anyone know how I can get this to work?
Thanks.
Edit
The question as stated was actually wrong. Apologies for not correcting this earlier.
What I had really done was have this:
ADDRESS TSO "SUBCOM DSNREXX"
IF RC THEN rcDB2 = RXSUBCOM('ADD','DSNREXX','DSNREXX')
ADDRESS DSNREXX "CONNECT " subsys
...followed by a small read from DB2, then followed by the code to read from Teradata, followed by more code to read from DB2. When this was changed to reading from Teradata first before having anything to do with DB2 at all, it worked.
I don't think this has anything to do with SYSPRINT or SYSIN.
I think you are getting TSO RC = 1, not SQLCODE = 1 (because there is no SQLCODE of 1.
1 is a warning, -1 is an error. You can look this up in the DB2 Application Programming
and SQL Guide
Turn on TRACE R and run it.
There are variables (shown below) that display info about the error/warning.
22 *-* ADDRESS DSNREXX "EXECSQL OPEN C1"
>>> "EXECSQL OPEN C1"
+++ RC(1) +++
23 *-* IF SQLCODE <> 0
28 *-* SAY 'SQLSTATE='sqlstate', SQLERRMC='sqlerrmc', SQLERRP='sqlerrp
SQLSTATE=00000, SQLERRMC=, SQLERRP=DSN
29 - SAY 'SQLERRD='sqlerrd.1', 'sqlerrd.2', 'sqlerrd.3', 'sqlerrd.4',',
sqlerrd.5', 'sqlerrd.6
SQLERRD=0, 0, 0, -1, 0, 0
32 - SAY 'SQLWARN='sqlwarn.0', 'sqlwarn.1', 'sqlwarn.2', 'sqlwarn.3',',
sqlwarn.4', 'sqlwarn.5', 'sqlwarn.6', 'sqlwarn.7',',
sqlwarn.8', 'sqlwarn.9', 'sqlwarn.10
SQLWARN= , N, , , , 2, , , , ,
For example, it could be that when both are used together, there is not enough memory.